From 940a9e5e43a2a362177f6ea6492332e0d2727f50 Mon Sep 17 00:00:00 2001 From: alfianchii Date: Fri, 26 Dec 2025 20:16:52 +0700 Subject: [PATCH 1/5] chore: move grinder greetings into aura channel --- .../events/guild-member-update/grinder-role/handlers/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts index c4cc1ed..c31d52a 100644 --- a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts +++ b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts @@ -1,5 +1,5 @@ import type { TextChannel } from 'discord.js' -import { GRIND_ASHES_CHANNEL, GRINDER_ROLE } from '@config/discord' +import { AURA_FARMING_CHANNEL, GRINDER_ROLE } from '@config/discord' import { registerGuildMemberUpdateHandler } from '@events/guild-member-update/registry' import { EVENT_PATH } from '@events/index' import { getChannelOrThread, sendAsBot } from '@utils/discord' @@ -27,7 +27,7 @@ registerGuildMemberUpdateHandler({ const newHasGrinderRole = GrinderRole.isMemberHasRole(newMember, GRINDER_ROLE) const oldHasGrinderRole = GrinderRole.isMemberHasRole(oldMember, GRINDER_ROLE) if (newHasGrinderRole && !oldHasGrinderRole) { - const channel = await getChannelOrThread(newMember.guild, GRIND_ASHES_CHANNEL) as TextChannel + const channel = await getChannelOrThread(newMember.guild, AURA_FARMING_CHANNEL) as TextChannel GrinderRole.assertChannel(channel) const button = GrinderRole.generateButton(newMember.guild.id) From ec19a214e2314af73d1ea779c5e978a91d0d9011 Mon Sep 17 00:00:00 2001 From: alfianchii Date: Fri, 26 Dec 2025 20:47:41 +0700 Subject: [PATCH 2/5] chore: remove unnecessary match --- .../events/guild-member-update/grinder-role/handlers/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts index c31d52a..a9b4b33 100644 --- a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts +++ b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts @@ -18,7 +18,6 @@ const moduleName = getModuleName(EVENT_PATH, __filename) registerGuildMemberUpdateHandler({ desc: 'Watches grinder role assignment/removal for members on guild member update.', errorTag: () => `${moduleName}: ${GrinderRole.ERR.UnexpectedGrinderRole}`, - match: (_, newMember) => GrinderRole.isMemberHasRole(newMember, GRINDER_ROLE), async exec(_, oldMember, newMember) { try { if (!newMember.guild) From 239ceca66f081cd375b969d6f12798c127b3eff4 Mon Sep 17 00:00:00 2001 From: alfianchii Date: Fri, 26 Dec 2025 20:48:22 +0700 Subject: [PATCH 3/5] chore: just make it clear into getChannel (there are so many channels) --- src/bot/commands/checkin/handlers/checkin-audit.ts | 4 ++-- .../client-ready/jobs/handlers/reset-grinder-roles.ts | 4 ++-- .../guild-member-update/grinder-role/handlers/index.ts | 4 ++-- .../events/interaction-create/checkin/validators/index.ts | 6 +++--- .../embed/handlers/role-grant-create-modal.ts | 4 ++-- .../interaction-create/message/handlers/send-modal.ts | 4 ++-- src/utils/discord/assert.ts | 6 +++--- src/utils/discord/index.ts | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/bot/commands/checkin/handlers/checkin-audit.ts b/src/bot/commands/checkin/handlers/checkin-audit.ts index 9cd3556..1e322d7 100644 --- a/src/bot/commands/checkin/handlers/checkin-audit.ts +++ b/src/bot/commands/checkin/handlers/checkin-audit.ts @@ -3,7 +3,7 @@ import { registerCommand } from '@commands/registry' import { AUDIT_FLAME_CHANNEL, FLAMEWARDEN_ROLE } from '@config/discord' import { CHECKIN_AUDIT_ID } from '@events/interaction-create/checkin/handlers/audit-modal' import { createCheckinReviewModal, encodeSnowflake, getCustomId } from '@utils/component' -import { getChannelOrThread, sendReply } from '@utils/discord' +import { getChannel, sendReply } from '@utils/discord' import { DiscordBaseError } from '@utils/discord/error' import { log } from '@utils/logger' import { SlashCommandBuilder } from 'discord.js' @@ -30,7 +30,7 @@ registerCommand({ if (!interaction.inCachedGuild()) throw new CheckinAuditError(CheckinAudit.ERR.NotGuild) - const channel = await getChannelOrThread(interaction.guild, AUDIT_FLAME_CHANNEL) as TextChannel + const channel = await getChannel(interaction.guild, AUDIT_FLAME_CHANNEL) as TextChannel CheckinAudit.assertMissPerms(interaction.client.user, channel) const thread = await CheckinAudit.assertThreadUnderChannel(interaction.guild, interaction.channelId, channel) CheckinAudit.assertNotArchivedThread(thread) diff --git a/src/bot/events/client-ready/jobs/handlers/reset-grinder-roles.ts b/src/bot/events/client-ready/jobs/handlers/reset-grinder-roles.ts index 782567e..7ff831e 100644 --- a/src/bot/events/client-ready/jobs/handlers/reset-grinder-roles.ts +++ b/src/bot/events/client-ready/jobs/handlers/reset-grinder-roles.ts @@ -3,7 +3,7 @@ import process from 'node:process' import { GRIND_ASHES_CHANNEL } from '@config/discord' import { registerClientReadyHandler } from '@events/client-ready/registry' import { EVENT_PATH } from '@events/index' -import { getChannelOrThread } from '@utils/discord' +import { getChannel } from '@utils/discord' import { DiscordBaseError } from '@utils/discord/error' import { getModuleName } from '@utils/io' import { log } from '@utils/logger' @@ -27,7 +27,7 @@ registerClientReadyHandler({ log.check(ResetGrinderRoles.MSG.JobRunning) const guild = await client.guilds.fetch(process.env.GUILD_ID!) - const channel = await getChannelOrThread(guild, GRIND_ASHES_CHANNEL) as TextChannel + const channel = await getChannel(guild, GRIND_ASHES_CHANNEL) as TextChannel ResetGrinderRoles.assertChannel(channel) const users = await ResetGrinderRoles.getUsersWithLatestStreak(client.prisma) diff --git a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts index a9b4b33..c593ffb 100644 --- a/src/bot/events/guild-member-update/grinder-role/handlers/index.ts +++ b/src/bot/events/guild-member-update/grinder-role/handlers/index.ts @@ -2,7 +2,7 @@ import type { TextChannel } from 'discord.js' import { AURA_FARMING_CHANNEL, GRINDER_ROLE } from '@config/discord' import { registerGuildMemberUpdateHandler } from '@events/guild-member-update/registry' import { EVENT_PATH } from '@events/index' -import { getChannelOrThread, sendAsBot } from '@utils/discord' +import { getChannel, sendAsBot } from '@utils/discord' import { DiscordBaseError } from '@utils/discord/error' import { getModuleName } from '@utils/io' import { GrinderRole } from '../validators' @@ -26,7 +26,7 @@ registerGuildMemberUpdateHandler({ const newHasGrinderRole = GrinderRole.isMemberHasRole(newMember, GRINDER_ROLE) const oldHasGrinderRole = GrinderRole.isMemberHasRole(oldMember, GRINDER_ROLE) if (newHasGrinderRole && !oldHasGrinderRole) { - const channel = await getChannelOrThread(newMember.guild, AURA_FARMING_CHANNEL) as TextChannel + const channel = await getChannel(newMember.guild, AURA_FARMING_CHANNEL) as TextChannel GrinderRole.assertChannel(channel) const button = GrinderRole.generateButton(newMember.guild.id) diff --git a/src/bot/events/interaction-create/checkin/validators/index.ts b/src/bot/events/interaction-create/checkin/validators/index.ts index 3d983ba..a7bc4bd 100644 --- a/src/bot/events/interaction-create/checkin/validators/index.ts +++ b/src/bot/events/interaction-create/checkin/validators/index.ts @@ -11,7 +11,7 @@ import { AURA_FARMING_CHANNEL, CHECKIN_CHANNEL, GRINDER_ROLE } from '@config/dis import { SubmittedCheckinError } from '@events/message-reaction-add/checkin/handlers/submitted' import { createEmbed, decodeSnowflakes, encodeSnowflake, getCustomId } from '@utils/component' import { isDateToday, isDateYesterday } from '@utils/date' -import { DiscordAssert, getChannelOrThread, sendAsBot } from '@utils/discord' +import { DiscordAssert, getChannel, sendAsBot } from '@utils/discord' import { attachNewGrindRole, getGrindRoleByStreakCount } from '@utils/discord/roles' import { DUMMY } from '@utils/placeholder' import { ActionRowBuilder, ButtonBuilder, ButtonStyle, messageLink, PermissionsBitField } from 'discord.js' @@ -155,7 +155,7 @@ export class Checkin extends CheckinMessage { return const hasGrindRole = this.isMemberHasRole(member, newRole.id) - const channel = await getChannelOrThread(guild, AURA_FARMING_CHANNEL) as TextChannel + const channel = await getChannel(guild, AURA_FARMING_CHANNEL) as TextChannel this.assertChannel(channel) if (!hasGrindRole) { @@ -166,7 +166,7 @@ export class Checkin extends CheckinMessage { }) } else { - const checkinChannel = await getChannelOrThread(guild, CHECKIN_CHANNEL) as TextChannel + const checkinChannel = await getChannel(guild, CHECKIN_CHANNEL) as TextChannel await sendAsBot(null, checkinChannel, { content: `Hey, <@${member.id}>. You already have <@&${newRole.id}>`, allowedMentions: { users: [member.id], roles: [] }, diff --git a/src/bot/events/interaction-create/embed/handlers/role-grant-create-modal.ts b/src/bot/events/interaction-create/embed/handlers/role-grant-create-modal.ts index 4a1f719..8faed0f 100644 --- a/src/bot/events/interaction-create/embed/handlers/role-grant-create-modal.ts +++ b/src/bot/events/interaction-create/embed/handlers/role-grant-create-modal.ts @@ -2,7 +2,7 @@ import type { TextChannel } from 'discord.js' import { EVENT_PATH } from '@events/index' import { registerInteractionHandler } from '@events/interaction-create/registry' import { createEmbed, encodeSnowflake, generateCustomId, getCustomId } from '@utils/component' -import { getChannelOrThread, getRole, sendAsBot, sendReply } from '@utils/discord' +import { getChannel, getRole, sendAsBot, sendReply } from '@utils/discord' import { DiscordBaseError } from '@utils/discord/error' import { getModuleName } from '@utils/io' import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js' @@ -31,7 +31,7 @@ registerInteractionHandler({ throw new EmbedRoleGrantModalError(RoleGrantCreate.ERR.NotGuild) const { channelId, roleId, buttonName } = RoleGrantCreate.getModalId(interaction, interaction.customId) - const channel = await getChannelOrThread(interaction.guild, channelId) as TextChannel + const channel = await getChannel(interaction.guild, channelId) as TextChannel RoleGrantCreate.assertChannel(channel) RoleGrantCreate.assertMissPerms(interaction.client.user, channel) const role = await getRole(interaction.guild, roleId) diff --git a/src/bot/events/interaction-create/message/handlers/send-modal.ts b/src/bot/events/interaction-create/message/handlers/send-modal.ts index 2f66cae..7347be4 100644 --- a/src/bot/events/interaction-create/message/handlers/send-modal.ts +++ b/src/bot/events/interaction-create/message/handlers/send-modal.ts @@ -2,7 +2,7 @@ import type { Attachment, TextChannel } from 'discord.js' import { EVENT_PATH } from '@events/index' import { registerInteractionHandler } from '@events/interaction-create/registry' import { generateCustomId, tempStore } from '@utils/component' -import { getChannelOrThread, sendAsBot, sendReply } from '@utils/discord' +import { getChannel, sendAsBot, sendReply } from '@utils/discord' import { DiscordBaseError } from '@utils/discord/error' import { getModuleName } from '@utils/io' import { Send } from '../validators/send' @@ -29,7 +29,7 @@ registerInteractionHandler({ throw new SendModalError(Send.ERR.NotGuild) const { channelId, tempToken } = Send.getModalId(interaction, interaction.customId) - const channel = await getChannelOrThread(interaction.guild, channelId) as TextChannel + const channel = await getChannel(interaction.guild, channelId) as TextChannel Send.assertChannel(channel) Send.assertMissPerms(interaction.client.user, channel) const attachments = tempStore.get(tempToken) as Attachment[] diff --git a/src/utils/discord/assert.ts b/src/utils/discord/assert.ts index 105be25..83bda9c 100644 --- a/src/utils/discord/assert.ts +++ b/src/utils/discord/assert.ts @@ -1,7 +1,7 @@ import type { ClientUser, Guild, GuildMember, Message, Role, TextChannel, ThreadAutoArchiveDuration, ThreadChannel } from 'discord.js' import { getTempToken, parseMessageLink, tempStore } from '@utils/component' import { ChannelType, PermissionsBitField } from 'discord.js' -import { getBotPerms, getChannelOrThread, getMissPerms } from '.' +import { getBotPerms, getChannel, getMissPerms } from '.' import { DiscordBaseError } from './error' import { DiscordMessage } from './message' @@ -102,7 +102,7 @@ export class DiscordAssert extends DiscordMessage { throw new DiscordAssertError(this.ERR.AllowedChannel(channelId)) } - const channel = await getChannelOrThread(guild, channelId) as TextChannel + const channel = await getChannel(guild, channelId) as TextChannel this.assertChannel(channel) return channel @@ -126,7 +126,7 @@ export class DiscordAssert extends DiscordMessage { } static async assertThreadUnderChannel(guild: Guild, currentChannelId: string, parentChannel: TextChannel) { - const thread = await getChannelOrThread(guild, currentChannelId) as ThreadChannel + const thread = await getChannel(guild, currentChannelId) as ThreadChannel if (!thread.isThread()) throw new DiscordAssertError(this.ERR.MustBeThread(parentChannel.id)) diff --git a/src/utils/discord/index.ts b/src/utils/discord/index.ts index 7877fc1..a393b61 100644 --- a/src/utils/discord/index.ts +++ b/src/utils/discord/index.ts @@ -1,7 +1,7 @@ import type { Attachment, ChatInputCommandInteraction, ClientUser, Guild, GuildMember, Interaction, InteractionDeferReplyOptions, InteractionReplyOptions, MessageCreateOptions, PermissionsBitField, Role, TextChannel, ThreadChannel } from 'discord.js' import { MessageFlags } from 'discord.js' -export async function getChannelOrThread(guild: Guild, id: string, isThread: boolean = false): Promise { +export async function getChannel(guild: Guild, id: string, isThread: boolean = false): Promise { if (isThread) { return guild!.channels.cache.get(id) as TextChannel ?? await guild!.channels.fetch(id).then(channel => channel as TextChannel) } From fb9e67699c69697c227c07a230800d1a45b6f1b5 Mon Sep 17 00:00:00 2001 From: alfianchii Date: Fri, 26 Dec 2025 21:32:30 +0700 Subject: [PATCH 4/5] feat: server booster listener --- .../server-booster/handlers/index.ts | 48 ++++++++++++++++ .../server-booster/messages/index.ts | 57 +++++++++++++++++++ .../server-booster/validators/index.ts | 8 +++ src/config/discord.ts | 1 + src/utils/component.ts | 23 +++++--- 5 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 src/bot/events/guild-member-update/server-booster/handlers/index.ts create mode 100644 src/bot/events/guild-member-update/server-booster/messages/index.ts create mode 100644 src/bot/events/guild-member-update/server-booster/validators/index.ts diff --git a/src/bot/events/guild-member-update/server-booster/handlers/index.ts b/src/bot/events/guild-member-update/server-booster/handlers/index.ts new file mode 100644 index 0000000..104f06f --- /dev/null +++ b/src/bot/events/guild-member-update/server-booster/handlers/index.ts @@ -0,0 +1,48 @@ +import type { TextChannel } from 'discord.js' +import { AURA_FARMING_CHANNEL } from '@config/discord' +import { registerGuildMemberUpdateHandler } from '@events/guild-member-update/registry' +import { EVENT_PATH } from '@events/index' +import { getChannel, sendAsBot } from '@utils/discord' +import { DiscordBaseError } from '@utils/discord/error' +import { getModuleName } from '@utils/io' +import { ServerBooster } from '../validators' + +export class ServerBoosterError extends DiscordBaseError { + constructor(message: string, options?: { cause?: unknown }) { + super('ServerBoosterError', message, options) + } +} + +const moduleName = getModuleName(EVENT_PATH, __filename) + +registerGuildMemberUpdateHandler({ + desc: 'Watches server booster for members on guild member update.', + errorTag: () => `${moduleName}: ${ServerBooster.ERR.UnexpectedServerBooster}`, + async exec(_, oldMember, newMember) { + try { + if (!newMember.guild) + throw new ServerBoosterError(ServerBooster.ERR.NotGuild) + + const wasBoosting = !!oldMember.premiumSince + const isBoosting = !!newMember.premiumSince + + const justBoosted = !wasBoosting && isBoosting + if (!justBoosted) + return + + const channel = await getChannel(newMember.guild, AURA_FARMING_CHANNEL) as TextChannel + ServerBooster.assertChannel(channel) + + const embed = ServerBooster.sayDeeplyThanksTo(newMember) + + await sendAsBot(null, channel, { + content: ServerBooster.MSG.SpecialThanks, + embeds: [embed], + }) + } + catch (err: any) { + if (!(err instanceof DiscordBaseError)) + throw err + } + }, +}) diff --git a/src/bot/events/guild-member-update/server-booster/messages/index.ts b/src/bot/events/guild-member-update/server-booster/messages/index.ts new file mode 100644 index 0000000..a30a924 --- /dev/null +++ b/src/bot/events/guild-member-update/server-booster/messages/index.ts @@ -0,0 +1,57 @@ +import type { GuildMember } from 'discord.js' +import { BEARER_LOUNGE_CHANNEL, GRINDER_ROLE } from '@config/discord' +import { createEmbed } from '@utils/component' +import { DiscordAssert } from '@utils/discord' +import { DUMMY } from '@utils/placeholder' + +export class ServerBoosterMessage extends DiscordAssert { + static override readonly ERR = { + ...DiscordAssert.ERR, + UnexpectedServerBooster: 'โŒ Something went wrong while managing the server booster', + } + + static override readonly MSG = { + ...DiscordAssert.MSG, + SpecialThanks: `# โค๏ธโ€๐Ÿ”ฅ Sebuah Nyala Telah Diperkuat`, + Really: ` +Api tidak selalu membesar karena banyak kayu, +kadang karena satu jiwa yang rela memberi nyala!`, + ItMeansALot: (guildName: string, userDiscordId: string, boostCount: number) => ` +Tuan/Nona <@${userDiscordId}> telah mempersembahkan aura mereka untuk menguatkan nyala ${guildName} beserta para <@&${GRINDER_ROLE}>๐Ÿ”ฅ! + +**โœจ Maklumat Anugerah** +- Jumlah *Server Boost* Aksaria kini bertambah menjadi **\`${boostCount}\`**. +- Tuan/Nona resmi diakui sebagai *Bearer of the Flame*. +- Gerbang khusus โ <#${BEARER_LOUNGE_CHANNEL}> kini terbuka bagi Tuan/Nona; sebuah ruang kehormatan untuk para penjaga nyala. + +Kami sampaikan terima kasih setinggi-tingginya. +Semoga nyala kebaikan ini kembali pada Tuan/Nona +dalam wujud disiplin, keberkahan, dan pertumbuhan. + `, + SayDeeplyThanksTo: (member: GuildMember) => createEmbed( + this.MSG.Really, + this.MSG.ItMeansALot(member.guild.name, member.id, member.guild.premiumSubscriptionCount ?? 0), + DUMMY.COLOR, + { text: DUMMY.FOOTER }, + { + name: member.user.tag, + iconURL: member.user.displayAvatarURL(), + }, + member.user.displayAvatarURL({ size: 512 }), + ), + } + + static sayDeeplyThanksTo(member: GuildMember) { + return createEmbed( + this.MSG.Really, + this.MSG.ItMeansALot(member.guild.name, member.id, member.guild.premiumSubscriptionCount ?? 0), + DUMMY.COLOR, + { text: DUMMY.FOOTER }, + { + name: member.user.tag, + iconURL: member.user.displayAvatarURL(), + }, + member.user.displayAvatarURL({ size: 512 }), + ) + } +} diff --git a/src/bot/events/guild-member-update/server-booster/validators/index.ts b/src/bot/events/guild-member-update/server-booster/validators/index.ts new file mode 100644 index 0000000..9622c8c --- /dev/null +++ b/src/bot/events/guild-member-update/server-booster/validators/index.ts @@ -0,0 +1,8 @@ +import { DiscordAssert } from '@utils/discord' +import { ServerBoosterMessage } from '../messages' + +export class ServerBooster extends ServerBoosterMessage { + static override BASE_PERMS = [ + ...DiscordAssert.BASE_PERMS, + ] +} diff --git a/src/config/discord.ts b/src/config/discord.ts index 8e031c1..42ebd41 100644 --- a/src/config/discord.ts +++ b/src/config/discord.ts @@ -6,6 +6,7 @@ export const GRIND_ASHES_CHANNEL = '1405165926600409148' export const WARDEN_DUTY_CHANNEL = '1404086708051509318' export const AUDIT_FLAME_CHANNEL = '1447816805329539162' export const IGNITE_PATH_CHANNEL = '1405159743596793997' +export const BEARER_LOUNGE_CHANNEL = '1404087168552403044' export interface GrindRole { name?: string diff --git a/src/utils/component.ts b/src/utils/component.ts index cebe097..8ec8429 100644 --- a/src/utils/component.ts +++ b/src/utils/component.ts @@ -1,6 +1,6 @@ import type { Checkin } from '@type/checkin' import type { DiscordCustomIdMetadata } from '@type/discord-component' -import type { EmbedFooterOptions } from 'discord.js' +import type { EmbedAuthorOptions, EmbedFooterOptions } from 'discord.js' import { ALPHABETS, CUSTOM_ID_SEPARATOR, SNOWFLAKE_MARKER } from '@constants' import { EmbedBuilder, LabelBuilder, ModalBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, TextInputBuilder, TextInputStyle } from 'discord.js' import { parseHexColor } from './color' @@ -73,10 +73,13 @@ export const getTempToken = () => Math.random().toString(36).slice(2, 8) export const tempStore = new Map() export function createEmbed( - title?: string | null | undefined, - desc?: string | null | undefined, - color?: string | null, - footer?: EmbedFooterOptions | null | undefined, + title: string | null | undefined = null, + desc: string | null | undefined = null, + color: string | null = null, + footer: EmbedFooterOptions | null | undefined = null, + author: EmbedAuthorOptions | null | undefined = null, + thumbnail: string | null | undefined = null, + image: string | null | undefined = null, date: boolean = true, ): EmbedBuilder { const embed = new EmbedBuilder() @@ -89,10 +92,16 @@ export function createEmbed( embed.setDescription(desc) if (parsedColor) embed.setColor(parsedColor) - if (date) - embed.setTimestamp(new Date()) if (footer) embed.setFooter(footer) + if (author) + embed.setAuthor(author) + if (thumbnail) + embed.setThumbnail(thumbnail) + if (image) + embed.setImage(image) + if (date) + embed.setTimestamp(new Date()) return embed } From be2628ec24daba086fd4820b2c9c82fe373ab3d8 Mon Sep 17 00:00:00 2001 From: alfianchii Date: Fri, 26 Dec 2025 21:40:49 +0700 Subject: [PATCH 5/5] refactor: using `guild.name` instead of Aksaria hard-coded --- .../commands/checkin/messages/checkin-status.ts | 8 ++++---- .../commands/checkin/validators/checkin-status.ts | 12 ++++++------ .../commands/embed/handlers/role-grant-create.ts | 4 ++-- .../jobs/messages/reset-grinder-roles.ts | 6 +++--- .../jobs/validators/reset-grinder-roles.ts | 2 +- .../server-booster/messages/index.ts | 15 ++------------- .../checkin/handlers/audit-modal.ts | 4 ++-- .../interaction-create/checkin/handlers/modal.ts | 2 +- .../checkin/handlers/status-note-button.ts | 2 +- .../interaction-create/checkin/messages/audit.ts | 4 ++-- .../interaction-create/checkin/messages/index.ts | 4 ++-- .../checkin/validators/index.ts | 6 +++--- src/types/placeholder.d.ts | 2 +- src/utils/placeholder.ts | 2 +- 14 files changed, 31 insertions(+), 42 deletions(-) diff --git a/src/bot/commands/checkin/messages/checkin-status.ts b/src/bot/commands/checkin/messages/checkin-status.ts index b9ccd73..d2f010c 100644 --- a/src/bot/commands/checkin/messages/checkin-status.ts +++ b/src/bot/commands/checkin/messages/checkin-status.ts @@ -76,10 +76,10 @@ ${checkin.public_id} โœ๐Ÿป **${flamewarden.displayName}'(s) Comment**: ${checkin.comment ?? '-'} > *"[Api Tuan/Nona](${checkin.link}) <@${userDiscordId}> meredup hari ini, namun belum padam sepenuhnya. Perbaiki, dan nyalakan kembali percikan yang benar."* `, - LastCheckin: (userDiscordId: string, checkin: Checkin, flamewarden?: GuildMember) => ` + LastCheckin: (guildName: string, userDiscordId: string, checkin: Checkin, flamewarden?: GuildMember) => ` Wahai Tuan/Nona <@${userDiscordId}>, tercatat bahwa rangkaian nyala api Tuan/Nona telah terputus pada pergantian hari sebelumnya. -Namun demikian, percikan terakhir masih tersimpan dalam arsip Aksaria dan dapat ditinjau kembali. +Namun demikian, percikan terakhir masih tersimpan dalam arsip ${guildName} dan dapat ditinjau kembali. Berikut adalah *check-in* terakhir yang pernah Tuan/Nona torehkan: ๐Ÿ†” **Check-In ID**: @@ -99,9 +99,9 @@ ${flamewarden?.displayName : ''} > *"[Percikan ini](${checkin.link}) pernah kau titipkan pada api, namun belum sempat ditakar oleh penjaga nyala."* `, - LastCheckinNote: (checkinLink: string, statusLink: string) => ` + LastCheckinNote: (guildName: string, checkinLink: string, statusLink: string) => ` Apabila Tuan/Nona meyakini bahwa [*check-in*](${checkinLink}) belum sempat ditinjau oleh <@&${FLAMEWARDEN_ROLE}>, -maka Aksaria membuka ruang klarifikasi dengan tata cara sebagai berikut: +maka ${guildName} membuka ruang klarifikasi dengan tata cara sebagai berikut: โ… . Berikan reaksi โ“ pada pesan [*status check-in*](${statusLink}) ini. โ…ก. Sebuah *thread* khusus akan tercipta secara otomatis. โ…ข. Gunakan *thread* tersebut untuk berkomunikasi dan mengajukan peninjauan kepada <@&${FLAMEWARDEN_ROLE}>. diff --git a/src/bot/commands/checkin/validators/checkin-status.ts b/src/bot/commands/checkin/validators/checkin-status.ts index 521320c..616dd01 100644 --- a/src/bot/commands/checkin/validators/checkin-status.ts +++ b/src/bot/commands/checkin/validators/checkin-status.ts @@ -56,7 +56,7 @@ export class CheckinStatus extends CheckinStatusMessage { `๐Ÿงญ Check-In #${checkin.public_id}`, CheckinStatus.MSG.WaitingCheckin(userDiscordId, checkin), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(guild.name) }, ) break } @@ -66,7 +66,7 @@ export class CheckinStatus extends CheckinStatusMessage { `๐Ÿ”ฅ Check-In #${checkin.public_id}`, CheckinStatus.MSG.ApprovedCheckin(userDiscordId, flamewarden, checkin), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(guild.name) }, ) break } @@ -76,7 +76,7 @@ export class CheckinStatus extends CheckinStatusMessage { `โŒ Check-In #${checkin.public_id}`, CheckinStatus.MSG.RejectedCheckin(userDiscordId, flamewarden, checkin), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(guild.name) }, ) break } @@ -91,7 +91,7 @@ export class CheckinStatus extends CheckinStatusMessage { `๐Ÿง Check-In`, CheckinStatus.MSG.NoCheckin(userDiscordId, checkinStreak), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(guild.name) }, ) return { content, embed } @@ -101,9 +101,9 @@ export class CheckinStatus extends CheckinStatusMessage { const buttons = this.generateButtons(guild.id, checkin) embed = createEmbed( `๐Ÿ•ฏ๏ธ Check-In #${checkin.public_id}`, - CheckinStatus.MSG.LastCheckin(userDiscordId, checkin, flamewarden), + CheckinStatus.MSG.LastCheckin(guild.name, userDiscordId, checkin, flamewarden), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(guild.name) }, ) return { content, embed, buttons } diff --git a/src/bot/commands/embed/handlers/role-grant-create.ts b/src/bot/commands/embed/handlers/role-grant-create.ts index 4551ae2..7e0ef6c 100644 --- a/src/bot/commands/embed/handlers/role-grant-create.ts +++ b/src/bot/commands/embed/handlers/role-grant-create.ts @@ -87,8 +87,8 @@ registerCommand({ .setTextInputComponent( new TextInputBuilder() .setCustomId('footer') - .setPlaceholder(DUMMY.FOOTER) - .setValue(DUMMY.FOOTER) + .setPlaceholder(DUMMY.FOOTER(interaction.guild.name)) + .setValue(DUMMY.FOOTER(interaction.guild.name)) .setStyle(TextInputStyle.Short) .setRequired(false), ), diff --git a/src/bot/events/client-ready/jobs/messages/reset-grinder-roles.ts b/src/bot/events/client-ready/jobs/messages/reset-grinder-roles.ts index 21ec8b4..77d4ae0 100644 --- a/src/bot/events/client-ready/jobs/messages/reset-grinder-roles.ts +++ b/src/bot/events/client-ready/jobs/messages/reset-grinder-roles.ts @@ -13,15 +13,15 @@ export class ResetGrinderRolesMessage extends DiscordAssert { JobRunning: '[JOB] Running daily grinder reset...', JobSuccess: '[JOB] Grinder daily reset finished successfully', RemoveGrinderRoleFrom: (member: GuildMember) => `[JOB] Removed Grinder role from ${member.user.tag}`, - GoodBye: (member: GuildMember) => ` + GoodBye: (guildName: string, member: GuildMember) => ` # ๐Ÿ’” Nyala Api Tuan/Nona <@${member.id}> Telah Gugur -Tatkala hari telah berganti dan lonceng waktu menunjukkan pergantian malam, tercatat bahwa tiada *check-in* yang sah diterima pada hari yang telah berlalu. Maka, sesuai hukum Aksaria, peran Grinder untuk saat ini harus dilepaskan. +Tatkala hari telah berganti dan lonceng waktu menunjukkan pergantian malam, tercatat bahwa tiada *check-in* yang sah diterima pada hari yang telah berlalu. Maka, sesuai hukum ${guildName}, peran Grinder untuk saat ini harus dilepaskan. Api bukanlah padam karena kelemahan, melainkan karena ia tak disirami pada waktunya. Namun jangan berduka, jalan ini selalu terbuka bagi mereka yang bersedia memulai kembali. Apabila Tuan/Nona berkehendak menyalakan api kembali, silakan kembali ke <#${IGNITE_PATH_CHANNEL}> dan bangkitlah dari awal. -*Aksaria menanti mereka yang konsisten.* +*${guildName} menanti mereka yang konsisten.* `, GoodByeNotes: ` > Apabila *check-in* Tuan/Nona masih berada dalam status menunggu peninjauan (*waiting*) dan belum memperoleh keputusan hingga mendekati pergantian hari, maka dengan ini disampaikan ketentuan berikut: diff --git a/src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts b/src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts index def0b3d..0d341da 100644 --- a/src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts +++ b/src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts @@ -79,7 +79,7 @@ export class ResetGrinderRoles extends ResetGrinderRolesMessage { await sendAsBot( null, channel, - { content: ResetGrinderRoles.MSG.GoodBye(member), components: [button], allowedMentions: { users: [member.id], roles: [] } }, + { content: ResetGrinderRoles.MSG.GoodBye(guild.name, member), components: [button], allowedMentions: { users: [member.id], roles: [] } }, ) log.info(this.MSG.RemoveGrinderRoleFrom(member)) diff --git a/src/bot/events/guild-member-update/server-booster/messages/index.ts b/src/bot/events/guild-member-update/server-booster/messages/index.ts index a30a924..a9d99dd 100644 --- a/src/bot/events/guild-member-update/server-booster/messages/index.ts +++ b/src/bot/events/guild-member-update/server-booster/messages/index.ts @@ -20,7 +20,7 @@ kadang karena satu jiwa yang rela memberi nyala!`, Tuan/Nona <@${userDiscordId}> telah mempersembahkan aura mereka untuk menguatkan nyala ${guildName} beserta para <@&${GRINDER_ROLE}>๐Ÿ”ฅ! **โœจ Maklumat Anugerah** -- Jumlah *Server Boost* Aksaria kini bertambah menjadi **\`${boostCount}\`**. +- Jumlah *Server Boost* ${guildName} kini bertambah menjadi **\`${boostCount}\`**. - Tuan/Nona resmi diakui sebagai *Bearer of the Flame*. - Gerbang khusus โ <#${BEARER_LOUNGE_CHANNEL}> kini terbuka bagi Tuan/Nona; sebuah ruang kehormatan untuk para penjaga nyala. @@ -28,17 +28,6 @@ Kami sampaikan terima kasih setinggi-tingginya. Semoga nyala kebaikan ini kembali pada Tuan/Nona dalam wujud disiplin, keberkahan, dan pertumbuhan. `, - SayDeeplyThanksTo: (member: GuildMember) => createEmbed( - this.MSG.Really, - this.MSG.ItMeansALot(member.guild.name, member.id, member.guild.premiumSubscriptionCount ?? 0), - DUMMY.COLOR, - { text: DUMMY.FOOTER }, - { - name: member.user.tag, - iconURL: member.user.displayAvatarURL(), - }, - member.user.displayAvatarURL({ size: 512 }), - ), } static sayDeeplyThanksTo(member: GuildMember) { @@ -46,7 +35,7 @@ dalam wujud disiplin, keberkahan, dan pertumbuhan. this.MSG.Really, this.MSG.ItMeansALot(member.guild.name, member.id, member.guild.premiumSubscriptionCount ?? 0), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(member.guild.name) }, { name: member.user.tag, iconURL: member.user.displayAvatarURL(), diff --git a/src/bot/events/interaction-create/checkin/handlers/audit-modal.ts b/src/bot/events/interaction-create/checkin/handlers/audit-modal.ts index 0e30fab..f33acb3 100644 --- a/src/bot/events/interaction-create/checkin/handlers/audit-modal.ts +++ b/src/bot/events/interaction-create/checkin/handlers/audit-modal.ts @@ -58,9 +58,9 @@ registerInteractionHandler({ const embed = createEmbed( `๐Ÿ”ฅ Audit Check-In Telah Diselesaikan`, - CheckinAudit.MSG.AuditSuccess(updatedCheckin.link!, flamewarden.id, updatedCheckin.user!.discord_id), + CheckinAudit.MSG.AuditSuccess(interaction.guild.name, updatedCheckin.link!, flamewarden.id, updatedCheckin.user!.discord_id), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(interaction.guild.name) }, ) await sendReply(interaction, '', false, { embeds: [embed], allowedMentions: { users: [updatedCheckin.user!.discord_id] } }) diff --git a/src/bot/events/interaction-create/checkin/handlers/modal.ts b/src/bot/events/interaction-create/checkin/handlers/modal.ts index ff52429..dbf4e10 100644 --- a/src/bot/events/interaction-create/checkin/handlers/modal.ts +++ b/src/bot/events/interaction-create/checkin/handlers/modal.ts @@ -47,7 +47,7 @@ registerInteractionHandler({ const msg = await sendReply( interaction, - Checkin.MSG.CheckinSuccess(todo), + Checkin.MSG.CheckinSuccess(interaction.guild.name, todo), false, { files: attachments.length ? attachments : undefined, diff --git a/src/bot/events/interaction-create/checkin/handlers/status-note-button.ts b/src/bot/events/interaction-create/checkin/handlers/status-note-button.ts index 21550cc..6072a95 100644 --- a/src/bot/events/interaction-create/checkin/handlers/status-note-button.ts +++ b/src/bot/events/interaction-create/checkin/handlers/status-note-button.ts @@ -37,7 +37,7 @@ registerInteractionHandler({ const statusMessageLink = messageLink(interaction.channelId, interaction.message.id, interaction.guildId) - await sendReply(interaction, CheckinStatus.MSG.LastCheckinNote(checkinLink, statusMessageLink)) + await sendReply(interaction, CheckinStatus.MSG.LastCheckinNote(interaction.guild.name, checkinLink, statusMessageLink)) } catch (err: any) { if (err instanceof DiscordBaseError) diff --git a/src/bot/events/interaction-create/checkin/messages/audit.ts b/src/bot/events/interaction-create/checkin/messages/audit.ts index 0dbd9cd..1ea0197 100644 --- a/src/bot/events/interaction-create/checkin/messages/audit.ts +++ b/src/bot/events/interaction-create/checkin/messages/audit.ts @@ -16,13 +16,13 @@ ${waitingCheckinList} static override readonly MSG = { ...DiscordAssert.MSG, - AuditSuccess: (checkinLink: string, flamewardenId: string, userDiscordId: string) => ` + AuditSuccess: (guildName: string, checkinLink: string, flamewardenId: string, userDiscordId: string) => ` Wahai Tuan/Nona <@${userDiscordId}>, [percikan](${checkinLink}) yang Tuan/Nona titipkan telah selesai ditakar dan ditetapkan. ๐Ÿ—“ **Audited At**: ${getParsedNow(getNow())} ๐Ÿ‘€ **Audited By**: <@${flamewardenId}> -> *"Api telah diuji, dan keputusannya kini tercatat dalam Aksaria."* +> *"Api telah diuji, dan keputusannya kini tercatat dalam ${guildName}."* `, } } diff --git a/src/bot/events/interaction-create/checkin/messages/index.ts b/src/bot/events/interaction-create/checkin/messages/index.ts index b491cf6..521753b 100644 --- a/src/bot/events/interaction-create/checkin/messages/index.ts +++ b/src/bot/events/interaction-create/checkin/messages/index.ts @@ -19,14 +19,14 @@ export class CheckinMessage extends DiscordAssert { static override readonly MSG = { ...DiscordAssert.MSG, - CheckinSuccess: (todo: string) => ` + CheckinSuccess: (guildName: string, todo: string) => ` # โœ… Check-In Baru Terdeteksi! *Kindly take a look and do a review for this one, <@&${FLAMEWARDEN_ROLE}>* โ‹†๏ฝกหš โ˜๏ธŽ หš๏ฝกโ‹†๏ฝกหšโ˜ฝหš๏ฝกโ‹† ${todo} -> ${DUMMY.FOOTER}`, +> ${DUMMY.FOOTER(guildName)}`, GrinderDetails: (checkin: Checkin, lastCheckin?: Checkin) => ` โœจโ”€โ”€โ”€โ”€โ”€โœจ/โœจโ”โ”โ”โ”โœจ diff --git a/src/bot/events/interaction-create/checkin/validators/index.ts b/src/bot/events/interaction-create/checkin/validators/index.ts index a7bc4bd..72c4fc9 100644 --- a/src/bot/events/interaction-create/checkin/validators/index.ts +++ b/src/bot/events/interaction-create/checkin/validators/index.ts @@ -516,7 +516,7 @@ export class Checkin extends CheckinMessage { `๐ŸŽ‰ *Check-In* Berhasil`, this.MSG.CheckinSuccessToMember(checkin), DUMMY.COLOR, - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(member.guild.name) }, ) await member.send({ embeds: [embed] }) @@ -531,7 +531,7 @@ export class Checkin extends CheckinMessage { `โš ๏ธ *Check-In* Ditolak`, this.MSG.CheckinRejected(flamewarden, checkin), '#D9534F', - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(member.guild.name) }, ) break @@ -540,7 +540,7 @@ export class Checkin extends CheckinMessage { `๐Ÿ”ฅ *Check-In* Disetujui`, this.MSG.CheckinApproved(flamewarden, checkin), '#4CAF50', - { text: DUMMY.FOOTER }, + { text: DUMMY.FOOTER(member.guild.name) }, ) break diff --git a/src/types/placeholder.d.ts b/src/types/placeholder.d.ts index 315b8d7..a3d6bf7 100644 --- a/src/types/placeholder.d.ts +++ b/src/types/placeholder.d.ts @@ -2,6 +2,6 @@ export interface PlaceholderDummy { TITLE: string DESC: string COLOR: string - FOOTER: string + FOOTER: (guildName: string) => string MARKDOWN: string } diff --git a/src/utils/placeholder.ts b/src/utils/placeholder.ts index 175d181..0408f87 100644 --- a/src/utils/placeholder.ts +++ b/src/utils/placeholder.ts @@ -4,6 +4,6 @@ export const DUMMY: PlaceholderDummy = { TITLE: 'Pengumuman Penting', DESC: 'Halo, teman-teman! Hari ini...', COLOR: '#FF7518', - FOOTER: 'Aksaria โ€ข Where discipline meets destiny', + FOOTER: (guildName: string) => `${guildName} โ€ข Where discipline meets destiny`, MARKDOWN: `Kamu dapat menggunakan Discord formatting untuk memperindah atau memperjelas rangkaian kata yang telah kamu buat. Untuk panduan lengkap, silakan merujuk ke [Markdown Text 101](https://support.discord.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline).`, }