@hyperneutrino/djs-lite 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.ts +79 -34
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -31,6 +31,10 @@ import path from "node:path";
31
31
 
32
32
  process.on("uncaughtException", (err) => console.error(err));
33
33
 
34
+ const identity = <T>(value: T): T => value;
35
+
36
+ type Wrapper<T extends Function> = (fn: T) => T;
37
+
34
38
  type Handler<T extends CommandInteraction | AutocompleteInteraction | MessageComponentInteraction | ModalSubmitInteraction> = (
35
39
  interaction: T,
36
40
  ...args: T extends MessageComponentInteraction | ModalSubmitInteraction ? (string | undefined)[] : []
@@ -95,11 +99,11 @@ abstract class ComponentHandler<T extends ModalSubmitInteraction | MessageCompon
95
99
 
96
100
  export class ModalHandler extends ComponentHandler<ModalSubmitInteraction> {}
97
101
  export class ButtonHandler extends ComponentHandler<ButtonInteraction> {}
98
- export class StringSelectHandler extends ComponentHandler<StringSelectMenuInteraction> {}
99
- export class UserSelectHandler extends ComponentHandler<UserSelectMenuInteraction> {}
100
- export class RoleSelectHandler extends ComponentHandler<RoleSelectMenuInteraction> {}
101
- export class MentionSelectHandler extends ComponentHandler<MentionableSelectMenuInteraction> {}
102
- export class ChannelSelectHandler extends ComponentHandler<ChannelSelectMenuInteraction> {}
102
+ export class StringSelectMenuHandler extends ComponentHandler<StringSelectMenuInteraction> {}
103
+ export class UserSelectMenuHandler extends ComponentHandler<UserSelectMenuInteraction> {}
104
+ export class RoleSelectMenuHandler extends ComponentHandler<RoleSelectMenuInteraction> {}
105
+ export class MentionableSelectMenuHandler extends ComponentHandler<MentionableSelectMenuInteraction> {}
106
+ export class ChannelSelectMenuHandler extends ComponentHandler<ChannelSelectMenuInteraction> {}
103
107
 
104
108
  export class EventHandler<T extends keyof ClientEvents> {
105
109
  event: T;
@@ -120,6 +124,7 @@ async function importAll(
120
124
  await Promise.all(
121
125
  files.map(async (file) => {
122
126
  if (file.isDirectory()) return;
127
+ if (file.name.startsWith(".")) return;
123
128
 
124
129
  const absolutePath = path.resolve(file.parentPath, file.name);
125
130
  const relativePath = path.join(directory, path.relative(path.resolve(directory), absolutePath));
@@ -185,7 +190,19 @@ async function loadSubcommandsAndGroups(directory: string): Promise<{
185
190
  };
186
191
  }
187
192
 
188
- export async function loadCommands(client: Client<true>, directory: string, guildId?: string) {
193
+ export async function loadCommands(
194
+ client: Client<true>,
195
+ directory: string,
196
+ config?: {
197
+ guildId?: string;
198
+ wrappers?: {
199
+ slashCommands?: Wrapper<Handler<ChatInputCommandInteraction>>;
200
+ userCommands?: Wrapper<Handler<UserContextMenuCommandInteraction>>;
201
+ messageCommands?: Wrapper<Handler<MessageContextMenuCommandInteraction>>;
202
+ autocompletes?: Wrapper<Handler<AutocompleteInteraction>>;
203
+ };
204
+ },
205
+ ) {
189
206
  const commandData: (ChatInputApplicationCommandData | UserApplicationCommandData | MessageApplicationCommandData)[] = [];
190
207
 
191
208
  const slashCommandHandlers = new Map<string, Handler<ChatInputCommandInteraction>>();
@@ -197,18 +214,18 @@ export async function loadCommands(client: Client<true>, directory: string, guil
197
214
  await importAll({ directory, recursive: false }, async ({ file, absolutePath, relativePath, item }) => {
198
215
  if (item instanceof SlashCommand) {
199
216
  commandData.push({ ...item.data, type: ApplicationCommandType.ChatInput });
200
- slashCommandHandlers.set(item.data.name, item.handler);
201
- if (item.autocomplete) slashCommandAutocompletes.set(item.data.name, item.autocomplete);
217
+ slashCommandHandlers.set(item.data.name, (config?.wrappers?.slashCommands ?? identity)(item.handler));
218
+ if (item.autocomplete) slashCommandAutocompletes.set(item.data.name, (config?.wrappers?.autocompletes ?? identity)(item.autocomplete));
202
219
  } else if (item instanceof UserCommand) {
203
220
  commandData.push({ ...item.data, type: ApplicationCommandType.User });
204
- userCommandHandlers.set(item.data.name, item.handler);
221
+ userCommandHandlers.set(item.data.name, (config?.wrappers?.userCommands ?? identity)(item.handler));
205
222
  } else if (item instanceof MessageCommand) {
206
223
  commandData.push({ ...item.data, type: ApplicationCommandType.Message });
207
- messageCommandHandlers.set(item.data.name, item.handler);
224
+ messageCommandHandlers.set(item.data.name, (config?.wrappers?.messageCommands ?? identity)(item.handler));
208
225
  } else if (item instanceof SlashCommandWithSubcommands) {
209
226
  const { options, handler } = await loadSubcommandsAndGroups(relativePath.replace(/\.[^/.]+$/, ""));
210
227
  commandData.push({ ...item.data, options });
211
- slashCommandHandlers.set(item.data.name, handler);
228
+ slashCommandHandlers.set(item.data.name, (config?.wrappers?.slashCommands ?? identity)(handler));
212
229
  } else {
213
230
  throw new Error(`Loading commands failed: export from ${absolutePath} was not an instance of <Type>Command.`);
214
231
  }
@@ -234,10 +251,12 @@ export async function loadCommands(client: Client<true>, directory: string, guil
234
251
  await fs.mkdir(".cache", { recursive: true }).catch(() => null);
235
252
  await fs.writeFile(".cache/command-data.json", JSON.stringify(commandData)).catch(() => null);
236
253
 
237
- if (guildId) {
238
- const testGuild = client.guilds.resolve(guildId);
254
+ if (config?.guildId) {
255
+ const testGuild = client.guilds.resolve(config.guildId);
239
256
  if (!testGuild)
240
- throw new Error(`Provided test guild (${guildId}) can not be found, please make sure the bot you started this project on is in this guild.`);
257
+ throw new Error(
258
+ `Provided test guild (${config.guildId}) can not be found, please make sure the bot you started this project on is in this guild.`,
259
+ );
241
260
  await testGuild.commands.set(commandData);
242
261
  } else {
243
262
  await client.application.commands.set(commandData);
@@ -247,14 +266,29 @@ export async function loadCommands(client: Client<true>, directory: string, guil
247
266
  return { commands: commandData, slashCommandHandlers, userCommandHandlers, messageCommandHandlers, setCommands: commandDataHasBeenUpdated };
248
267
  }
249
268
 
250
- export async function loadInteractions(client: Client, directory: string, argumentSeparator: string = ":") {
269
+ export async function loadInteractions(
270
+ client: Client,
271
+ directory: string,
272
+ config?: {
273
+ argumentSeparator?: string;
274
+ wrappers?: {
275
+ modal?: Wrapper<Handler<ModalSubmitInteraction>>;
276
+ button?: Wrapper<Handler<ButtonInteraction>>;
277
+ stringSelectMenu?: Wrapper<Handler<StringSelectMenuInteraction>>;
278
+ userSelectMenu?: Wrapper<Handler<UserSelectMenuInteraction>>;
279
+ roleSelectMenu?: Wrapper<Handler<RoleSelectMenuInteraction>>;
280
+ mentionableSelectMenu?: Wrapper<Handler<MentionableSelectMenuInteraction>>;
281
+ channelSelectMenu?: Wrapper<Handler<ChannelSelectMenuInteraction>>;
282
+ };
283
+ },
284
+ ) {
251
285
  const modalHandlers = new Map<string, Handler<ModalSubmitInteraction>>();
252
286
  const buttonHandlers = new Map<string, Handler<ButtonInteraction>>();
253
- const stringSelectHandlers = new Map<string, Handler<StringSelectMenuInteraction>>();
254
- const userSelectHandlers = new Map<string, Handler<UserSelectMenuInteraction>>();
255
- const roleSelectHandlers = new Map<string, Handler<RoleSelectMenuInteraction>>();
256
- const mentionSelectHandlers = new Map<string, Handler<MentionableSelectMenuInteraction>>();
257
- const channelSelectHandlers = new Map<string, Handler<ChannelSelectMenuInteraction>>();
287
+ const stringSelectMenuHandlers = new Map<string, Handler<StringSelectMenuInteraction>>();
288
+ const userSelectMenuHandlers = new Map<string, Handler<UserSelectMenuInteraction>>();
289
+ const roleSelectMenuHandlers = new Map<string, Handler<RoleSelectMenuInteraction>>();
290
+ const mentionableSelectMenuHandlers = new Map<string, Handler<MentionableSelectMenuInteraction>>();
291
+ const channelSelectMenuHandlers = new Map<string, Handler<ChannelSelectMenuInteraction>>();
258
292
 
259
293
  await importAll({ directory, recursive: true }, async ({ absolutePath, item }) => {
260
294
  const handlerKey = path
@@ -262,32 +296,43 @@ export async function loadInteractions(client: Client, directory: string, argume
262
296
  .replace(/\.[^/.]+$/, "")
263
297
  .replace(/\\/g, "/");
264
298
 
265
- if (item instanceof ModalHandler) modalHandlers.set(handlerKey, item.handler);
266
- else if (item instanceof ButtonHandler) buttonHandlers.set(handlerKey, item.handler);
267
- else if (item instanceof StringSelectHandler) stringSelectHandlers.set(handlerKey, item.handler);
268
- else if (item instanceof UserSelectHandler) userSelectHandlers.set(handlerKey, item.handler);
269
- else if (item instanceof RoleSelectHandler) roleSelectHandlers.set(handlerKey, item.handler);
270
- else if (item instanceof MentionSelectHandler) mentionSelectHandlers.set(handlerKey, item.handler);
271
- else if (item instanceof ChannelSelectHandler) channelSelectHandlers.set(handlerKey, item.handler);
299
+ if (item instanceof ModalHandler) modalHandlers.set(handlerKey, (config?.wrappers?.modal ?? identity)(item.handler));
300
+ else if (item instanceof ButtonHandler) buttonHandlers.set(handlerKey, (config?.wrappers?.button ?? identity)(item.handler));
301
+ else if (item instanceof StringSelectMenuHandler)
302
+ stringSelectMenuHandlers.set(handlerKey, (config?.wrappers?.stringSelectMenu ?? identity)(item.handler));
303
+ else if (item instanceof UserSelectMenuHandler) userSelectMenuHandlers.set(handlerKey, (config?.wrappers?.userSelectMenu ?? identity)(item.handler));
304
+ else if (item instanceof RoleSelectMenuHandler) roleSelectMenuHandlers.set(handlerKey, (config?.wrappers?.roleSelectMenu ?? identity)(item.handler));
305
+ else if (item instanceof MentionableSelectMenuHandler)
306
+ mentionableSelectMenuHandlers.set(handlerKey, (config?.wrappers?.mentionableSelectMenu ?? identity)(item.handler));
307
+ else if (item instanceof ChannelSelectMenuHandler)
308
+ channelSelectMenuHandlers.set(handlerKey, (config?.wrappers?.channelSelectMenu ?? identity)(item.handler));
272
309
  else throw new Error(`Loading interactions failed: export from ${absolutePath} was not an instance of <InteractionType>Handler.`);
273
310
  });
274
311
 
275
312
  client.on(Events.InteractionCreate, (interaction) => {
276
313
  if (!interaction.isMessageComponent() && !interaction.isModalSubmit()) return;
277
314
 
278
- const [, userId, path, ...args] = interaction.customId.split(argumentSeparator);
315
+ const [, userId, path, ...args] = interaction.customId.split(config?.argumentSeparator ?? ":");
279
316
  if (!path || (userId && interaction.user.id !== userId)) return;
280
317
 
281
318
  if (interaction.isModalSubmit()) modalHandlers.get(path)?.(interaction, ...args);
282
319
  else if (interaction.isButton()) buttonHandlers.get(path)?.(interaction, ...args);
283
- else if (interaction.isStringSelectMenu()) stringSelectHandlers.get(path)?.(interaction, ...args);
284
- else if (interaction.isUserSelectMenu()) userSelectHandlers.get(path)?.(interaction, ...args);
285
- else if (interaction.isRoleSelectMenu()) roleSelectHandlers.get(path)?.(interaction, ...args);
286
- else if (interaction.isMentionableSelectMenu()) mentionSelectHandlers.get(path)?.(interaction, ...args);
287
- else if (interaction.isChannelSelectMenu()) channelSelectHandlers.get(path)?.(interaction, ...args);
320
+ else if (interaction.isStringSelectMenu()) stringSelectMenuHandlers.get(path)?.(interaction, ...args);
321
+ else if (interaction.isUserSelectMenu()) userSelectMenuHandlers.get(path)?.(interaction, ...args);
322
+ else if (interaction.isRoleSelectMenu()) roleSelectMenuHandlers.get(path)?.(interaction, ...args);
323
+ else if (interaction.isMentionableSelectMenu()) mentionableSelectMenuHandlers.get(path)?.(interaction, ...args);
324
+ else if (interaction.isChannelSelectMenu()) channelSelectMenuHandlers.get(path)?.(interaction, ...args);
288
325
  });
289
326
 
290
- return { modalHandlers, buttonHandlers, stringSelectHandlers, userSelectHandlers, roleSelectHandlers, mentionSelectHandlers, channelSelectHandlers };
327
+ return {
328
+ modalHandlers,
329
+ buttonHandlers,
330
+ stringSelectHandlers: stringSelectMenuHandlers,
331
+ userSelectHandlers: userSelectMenuHandlers,
332
+ roleSelectHandlers: roleSelectMenuHandlers,
333
+ mentionSelectHandlers: mentionableSelectMenuHandlers,
334
+ channelSelectHandlers: channelSelectMenuHandlers,
335
+ };
291
336
  }
292
337
 
293
338
  export async function loadEvents(client: Client, directory: string, recursive: boolean = false) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hyperneutrino/djs-lite",
3
3
  "private": false,
4
- "version": "1.5.0",
4
+ "version": "1.6.0",
5
5
  "module": "index.ts",
6
6
  "type": "module",
7
7
  "devDependencies": {