Skip to content

Commit 579b1c0

Browse files
committed
feat: note button handler
1 parent c91d7bd commit 579b1c0

4 files changed

Lines changed: 66 additions & 10 deletions

File tree

src/bot/events/client-ready/jobs/handlers/reset-grinder-roles.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import type { Event } from '@events/event'
22
import type { Client } from 'discord.js'
33
import process from 'node:process'
44
import { GRIND_ASHES_CHANNEL } from '@config/discord'
5-
import { EVENT_PATH } from '@events/index'
6-
import { generateCustomId } from '@utils/component'
75
import { getChannel } from '@utils/discord'
86
import { DiscordBaseError } from '@utils/discord/error'
97
import { log } from '@utils/logger'
@@ -17,8 +15,6 @@ export class ResetGrinderRolesError extends DiscordBaseError {
1715
}
1816
}
1917

20-
export const GOODBYE_NOTE_BUTTON_ID = `${generateCustomId(EVENT_PATH, __filename)}`
21-
2218
export default {
2319
name: Events.ClientReady,
2420
desc: `Reset Grinder roles for users that didn't do a check-in yesterday or the check-in didn't approved.`,

src/bot/events/client-ready/jobs/messages/reset-grinder-roles.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { GuildMember } from 'discord.js'
2-
import { FLAMEWARDEN_ROLE, IGNITE_PATH_CHANNEL } from '@config/discord'
2+
import { AUDIT_FLAME_CHANNEL, FLAMEWARDEN_ROLE, IGNITE_PATH_CHANNEL } from '@config/discord'
33
import { DiscordAssert } from '@utils/discord'
44

55
export class ResetGrinderRolesMessage extends DiscordAssert {
@@ -26,7 +26,7 @@ Namun jangan berduka, jalan ini selalu terbuka bagi mereka yang bersedia memulai
2626
GoodByeNotes: `
2727
> 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:
2828
> 1. Jangan terlebih dahulu memasuki ⁠<#${IGNITE_PATH_CHANNEL}>, demi menjaga ketertiban alur peninjauan.
29-
> 2. Silakan menjalankan perintah **\`/checkin-status\`** untuk menampilkan status *check-in* terakhir Tuan/Nona.
29+
> 2. Silakan menjalankan perintah **\`/checkin-status\`** pada <#${AUDIT_FLAME_CHANNEL}> untuk menampilkan status *check-in* terakhir Tuan/Nona.
3030
> 3. Setelah pesan status tersebut muncul, berikan reaksi “❓” pada pesan tersebut.
3131
> 4. Dari reaksi tersebut, sebuah *thread* akan tercipta secara otomatis sebagai ruang klarifikasi dan komunikasi dengan <@&${FLAMEWARDEN_ROLE}>.
3232
> ⏳ Batas waktu penantian atas status WAITING adalah maksimal 1×24 jam sejak *check-in* diajukan.

src/bot/events/client-ready/jobs/validators/reset-grinder-roles.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
import type { PrismaClient } from '@generatedDB/client'
22
import type { CheckinStreak } from '@type/checkin-streak'
33
import type { User } from '@type/user'
4-
import type { Guild, GuildMember, TextChannel } from 'discord.js'
4+
import type { Guild, GuildMember, Interaction, TextChannel } from 'discord.js'
55
import { getGrindRoles, GRINDER_ROLE } from '@config/discord'
6-
import { encodeSnowflake, getCustomId } from '@utils/component'
6+
import { GOODBYE_NOTE_BUTTON_ID, ResetGrinderRolesButtonError } from '@events/interaction-create/jobs/handlers/reset-grinder-roles-button'
7+
import { decodeSnowflakes, encodeSnowflake, getCustomId } from '@utils/component'
78
import { isDateToday, isDateYesterday } from '@utils/date'
8-
import { sendAsBot } from '@utils/discord'
9+
import { DiscordAssert, sendAsBot } from '@utils/discord'
910
import { log } from '@utils/logger'
1011
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'
11-
import { GOODBYE_NOTE_BUTTON_ID } from '../handlers/reset-grinder-roles'
1212
import { ResetGrinderRolesMessage } from '../messages/reset-grinder-roles'
1313

1414
export class ResetGrinderRoles extends ResetGrinderRolesMessage {
15+
static override BASE_PERMS = [
16+
...DiscordAssert.BASE_PERMS,
17+
]
18+
19+
static getButtonId(interaction: Interaction, customId: string) {
20+
const [prefix, guildId] = decodeSnowflakes(customId)
21+
22+
if (!guildId)
23+
throw new ResetGrinderRolesButtonError(this.ERR.GuildMissing)
24+
if (interaction.guildId !== guildId)
25+
throw new ResetGrinderRolesButtonError(this.ERR.NotGuild)
26+
27+
return { prefix, guildId }
28+
}
29+
1530
static generateButton(guildId: string): ActionRowBuilder<ButtonBuilder> {
1631
const noteButtonId = getCustomId([GOODBYE_NOTE_BUTTON_ID, encodeSnowflake(guildId)])
1732
const noteButton = new ButtonBuilder()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { Event } from '@events/event'
2+
import type { Interaction, TextChannel } from 'discord.js'
3+
import { ResetGrinderRoles } from '@events/client-ready/jobs/validators/reset-grinder-roles'
4+
import { EVENT_PATH } from '@events/index'
5+
import { generateCustomId } from '@utils/component'
6+
import { sendReply } from '@utils/discord'
7+
import { DiscordBaseError } from '@utils/discord/error'
8+
import { log } from '@utils/logger'
9+
import { Events } from 'discord.js'
10+
11+
export class ResetGrinderRolesButtonError extends DiscordBaseError {
12+
constructor(message: string, options?: { cause?: unknown }) {
13+
super('ResetGrinderRolesButtonError', message, options)
14+
}
15+
}
16+
17+
export const GOODBYE_NOTE_BUTTON_ID = `${generateCustomId(EVENT_PATH, __filename)}`
18+
19+
export default {
20+
name: Events.InteractionCreate,
21+
desc: 'Opens goodbye note modal for users losing Grinder roles.',
22+
async exec(_, interaction: Interaction) {
23+
if (!interaction.isButton())
24+
return
25+
26+
const isValid = ResetGrinderRoles.assertComponentId(interaction.customId, GOODBYE_NOTE_BUTTON_ID)
27+
if (!isValid)
28+
return
29+
30+
try {
31+
if (!interaction.inCachedGuild())
32+
throw new ResetGrinderRolesButtonError(ResetGrinderRoles.ERR.NotGuild)
33+
34+
const channel = interaction.channel as TextChannel
35+
ResetGrinderRoles.assertMissPerms(interaction.client.user, channel)
36+
37+
await sendReply(interaction, ResetGrinderRoles.MSG.GoodByeNotes)
38+
}
39+
catch (err: any) {
40+
if (err instanceof DiscordBaseError)
41+
await sendReply(interaction, err.message)
42+
else log.error(`Failed to handle ${GOODBYE_NOTE_BUTTON_ID}: ${ResetGrinderRoles.ERR.UnexpectedButton}: ${err}`)
43+
}
44+
},
45+
} as Event

0 commit comments

Comments
 (0)