Skip to content

Commit 51e13eb

Browse files
committed
refactor: interaction-create event
1 parent 579b1c0 commit 51e13eb

4 files changed

Lines changed: 56 additions & 15 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { Event } from '@events/event'
2+
import type { Interaction } from 'discord.js'
3+
import { log } from '@utils/logger'
4+
import { Events } from 'discord.js'
5+
import { interactionHandlers } from './registry'
6+
7+
export default {
8+
name: Events.InteractionCreate,
9+
desc: 'Handles Discord InteractionCreate events by dispatching to registered interaction handlers.',
10+
async exec(client, interaction: Interaction) {
11+
for (const handler of interactionHandlers) {
12+
try {
13+
if (handler.match && !handler.match(interaction))
14+
continue
15+
16+
await handler.exec(client, interaction)
17+
}
18+
catch (err) {
19+
log.error(`Interaction handler failed [${handler.id}]: ${err}`)
20+
}
21+
}
22+
},
23+
} as Event
Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import type { Event } from '@events/event'
1+
import type { InteractionHandler } from '@events/interaction-create/registry'
22
import type { Interaction, TextChannel } from 'discord.js'
33
import { ResetGrinderRoles } from '@events/client-ready/jobs/validators/reset-grinder-roles'
44
import { EVENT_PATH } from '@events/index'
55
import { generateCustomId } from '@utils/component'
66
import { sendReply } from '@utils/discord'
77
import { DiscordBaseError } from '@utils/discord/error'
8-
import { log } from '@utils/logger'
9-
import { Events } from 'discord.js'
108

119
export class ResetGrinderRolesButtonError extends DiscordBaseError {
1210
constructor(message: string, options?: { cause?: unknown }) {
@@ -16,17 +14,18 @@ export class ResetGrinderRolesButtonError extends DiscordBaseError {
1614

1715
export const GOODBYE_NOTE_BUTTON_ID = `${generateCustomId(EVENT_PATH, __filename)}`
1816

19-
export default {
20-
name: Events.InteractionCreate,
17+
const handler: InteractionHandler = {
18+
id: GOODBYE_NOTE_BUTTON_ID,
2119
desc: 'Opens goodbye note modal for users losing Grinder roles.',
22-
async exec(_, interaction: Interaction) {
23-
if (!interaction.isButton())
24-
return
2520

26-
const isValid = ResetGrinderRoles.assertComponentId(interaction.customId, GOODBYE_NOTE_BUTTON_ID)
27-
if (!isValid)
28-
return
21+
match(interaction: Interaction) {
22+
return (
23+
interaction.isButton()
24+
&& interaction.customId === GOODBYE_NOTE_BUTTON_ID
25+
)
26+
},
2927

28+
async exec(_, interaction) {
3029
try {
3130
if (!interaction.inCachedGuild())
3231
throw new ResetGrinderRolesButtonError(ResetGrinderRoles.ERR.NotGuild)
@@ -36,10 +35,12 @@ export default {
3635

3736
await sendReply(interaction, ResetGrinderRoles.MSG.GoodByeNotes)
3837
}
39-
catch (err: any) {
38+
catch (err) {
4039
if (err instanceof DiscordBaseError)
4140
await sendReply(interaction, err.message)
42-
else log.error(`Failed to handle ${GOODBYE_NOTE_BUTTON_ID}: ${ResetGrinderRoles.ERR.UnexpectedButton}: ${err}`)
41+
else throw err
4342
}
4443
},
45-
} as Event
44+
}
45+
46+
export default handler
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { Client, Interaction } from 'discord.js'
2+
3+
export interface InteractionHandler {
4+
/** Unique id or customId prefix */
5+
id: string
6+
7+
/** Human-readable description */
8+
desc: string
9+
10+
/** Optional guard for quick filtering */
11+
match?: (interaction: Interaction) => boolean
12+
13+
/** Main execution logic */
14+
exec: (client: Client, interaction: Interaction) => Promise<void> | void
15+
}
16+
17+
export const interactionHandlers: InteractionHandler[] = []

src/utils/io.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'node:fs'
22
import { resolve } from 'node:path'
33

4-
const EXCLUDED_FILES = new Set(['index.ts', 'messages.ts', 'validators.ts'])
4+
const EXCLUDED_FILES = new Set(['messages.ts', 'validators.ts'])
55
const EXCLUDED_FOLDERS = new Set(['validators', 'messages'])
66
const EXCLUDED_PATTERNS: RegExp[] = [/\.d\.ts$/]
77

0 commit comments

Comments
 (0)