@pikokr/command.ts 3.2.3 → 3.2.4-dev.535de3c

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 (90) hide show
  1. package/dist/applicationCommand/AppCommand.d.ts +18 -0
  2. package/dist/{slashCommand/SlashCommand.js → applicationCommand/AppCommand.js} +7 -7
  3. package/dist/applicationCommand/AppCommand.js.map +1 -0
  4. package/dist/applicationCommand/decorator.d.ts +10 -0
  5. package/dist/{slashCommand → applicationCommand}/decorator.js +9 -8
  6. package/dist/applicationCommand/decorator.js.map +1 -0
  7. package/dist/applicationCommand/index.d.ts +2 -0
  8. package/dist/{slashCommand → applicationCommand}/index.js +1 -1
  9. package/dist/applicationCommand/index.js.map +1 -0
  10. package/dist/builtinModules/BuiltinCommandConverters.d.ts +1 -1
  11. package/dist/builtinModules/BuiltinSlashCommandConverters.d.ts +1 -1
  12. package/dist/builtinModules/BuiltinSlashCommandConverters.js.map +1 -1
  13. package/dist/builtinModules/CommandHandler.d.ts +4 -1
  14. package/dist/builtinModules/CommandHandler.js +114 -19
  15. package/dist/builtinModules/CommandHandler.js.map +1 -1
  16. package/dist/command/Command.d.ts +2 -2
  17. package/dist/command/decorator.d.ts +1 -0
  18. package/dist/command/decorator.js +2 -1
  19. package/dist/command/decorator.js.map +1 -1
  20. package/dist/command/utils.d.ts +2 -2
  21. package/dist/command/utils.js +6 -6
  22. package/dist/command/utils.js.map +1 -1
  23. package/dist/constants.d.ts +3 -2
  24. package/dist/constants.js +4 -3
  25. package/dist/constants.js.map +1 -1
  26. package/dist/error/ArgumentConverterNotFound.d.ts +1 -1
  27. package/dist/error/CommandCheckFailed.d.ts +6 -6
  28. package/dist/error/CommandCheckFailed.js +3 -3
  29. package/dist/error/CommandCheckFailed.js.map +1 -1
  30. package/dist/error/checks/SlashCommandGlobalCheckError.d.ts +5 -0
  31. package/dist/error/checks/SlashCommandGlobalCheckError.js +11 -0
  32. package/dist/error/checks/SlashCommandGlobalCheckError.js.map +1 -0
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.js +2 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/messageComponents/base.d.ts +10 -0
  37. package/dist/messageComponents/base.js +15 -0
  38. package/dist/messageComponents/base.js.map +1 -0
  39. package/dist/messageComponents/button.d.ts +5 -0
  40. package/dist/messageComponents/button.js +28 -0
  41. package/dist/messageComponents/button.js.map +1 -0
  42. package/dist/messageComponents/index.d.ts +2 -0
  43. package/dist/messageComponents/index.js +15 -0
  44. package/dist/messageComponents/index.js.map +1 -0
  45. package/dist/messageComponents/selectMenu.d.ts +5 -0
  46. package/dist/messageComponents/selectMenu.js +28 -0
  47. package/dist/messageComponents/selectMenu.js.map +1 -0
  48. package/dist/structures/CommandClient.d.ts +8 -3
  49. package/dist/structures/CommandClient.js +7 -7
  50. package/dist/structures/CommandClient.js.map +1 -1
  51. package/dist/structures/Module.d.ts +4 -2
  52. package/dist/structures/Module.js +5 -2
  53. package/dist/structures/Module.js.map +1 -1
  54. package/dist/structures/Registry.d.ts +4 -2
  55. package/dist/structures/Registry.js +16 -13
  56. package/dist/structures/Registry.js.map +1 -1
  57. package/dist/typings.d.ts +15 -3
  58. package/package.json +3 -5
  59. package/src/applicationCommand/AppCommand.ts +28 -0
  60. package/src/{slashCommand → applicationCommand}/decorator.ts +10 -10
  61. package/src/applicationCommand/index.ts +2 -0
  62. package/src/builtinModules/BuiltinSlashCommandConverters.ts +1 -1
  63. package/src/builtinModules/CommandHandler.ts +131 -22
  64. package/src/command/Command.ts +2 -2
  65. package/src/command/decorator.ts +2 -1
  66. package/src/command/utils.ts +9 -9
  67. package/src/constants.ts +4 -2
  68. package/src/error/ArgumentConverterNotFound.ts +1 -1
  69. package/src/error/CommandCheckFailed.ts +4 -4
  70. package/src/error/checks/SlashCommandGlobalCheckError.ts +7 -0
  71. package/src/index.ts +2 -1
  72. package/src/messageComponents/base.ts +12 -0
  73. package/src/messageComponents/button.ts +26 -0
  74. package/src/messageComponents/index.ts +2 -0
  75. package/src/messageComponents/selectMenu.ts +26 -0
  76. package/src/structures/CommandClient.ts +16 -8
  77. package/src/structures/Module.ts +9 -4
  78. package/src/structures/Registry.ts +21 -15
  79. package/src/typings.ts +15 -3
  80. package/test/index.ts +2 -2
  81. package/test/modules/dev.ts +9 -5
  82. package/test/modules/test.ts +88 -15
  83. package/dist/slashCommand/SlashCommand.d.ts +0 -19
  84. package/dist/slashCommand/SlashCommand.js.map +0 -1
  85. package/dist/slashCommand/decorator.d.ts +0 -10
  86. package/dist/slashCommand/decorator.js.map +0 -1
  87. package/dist/slashCommand/index.d.ts +0 -2
  88. package/dist/slashCommand/index.js.map +0 -1
  89. package/src/slashCommand/SlashCommand.ts +0 -29
  90. package/src/slashCommand/index.ts +0 -2
@@ -1,11 +1,23 @@
1
1
  import { BuiltInModule } from './BuiltInModule'
2
2
  import { Registry } from '../structures'
3
3
  import { listener } from '../listener'
4
- import { CommandInteraction, GuildMember, Interaction, Message, Role, User } from 'discord.js'
4
+ import {
5
+ CommandInteraction,
6
+ GuildMember,
7
+ Interaction,
8
+ Message,
9
+ MessageComponentInteraction,
10
+ MessageContextMenuInteraction,
11
+ Role,
12
+ User,
13
+ UserContextMenuInteraction,
14
+ } from 'discord.js'
5
15
  import { CommandClient } from '../structures'
6
16
  import { Command } from '../command'
7
- import { ArgumentConverterNotFound, ArgumentNotProvided, CommandCheckFailed, SlashArgumentConverterNotFound, SlashCommandCheckFailed } from '../error'
17
+ import { ArgumentConverterNotFound, ArgumentNotProvided, CommandCheckFailed, SlashArgumentConverterNotFound, ApplicationCommandCheckFailed } from '../error'
8
18
  import { CommandNotFound } from '../error/CommandNotFound'
19
+ import { SlashCommandGlobalCheckError } from '../error/checks/SlashCommandGlobalCheckError'
20
+ import { MessageComponentHandler } from '../messageComponents/base'
9
21
 
10
22
  export class CommandHandler extends BuiltInModule {
11
23
  private readonly client: CommandClient
@@ -15,6 +27,7 @@ export class CommandHandler extends BuiltInModule {
15
27
  this.client = registry.client
16
28
  }
17
29
 
30
+ // region message command handler
18
31
  @listener('messageCreate')
19
32
  async message(msg: Message) {
20
33
  const error = (error: Error) => this.client.client.emit('commandError', error, msg)
@@ -48,19 +61,21 @@ export class CommandHandler extends BuiltInModule {
48
61
 
49
62
  let cmd: Command | null = null
50
63
 
64
+ const globalAliases = await this.client.options.command.globalAliases(command, msg)
65
+
51
66
  for (const c of this.registry.commands) {
52
- if (c.name === command) {
67
+ const globalAliases2 = await this.client.options.command.globalAliases(c.name, msg)
68
+ const aliases = typeof c.aliases === 'function' ? await c.aliases(msg) : c.aliases
69
+ if ([...aliases, c.name].some((x) => x === command)) {
53
70
  cmd = c
54
71
  break
55
72
  }
56
- if ((typeof c.aliases === 'function' ? await c.aliases(msg) : c.aliases).includes(command)) {
73
+ if (globalAliases.every((x, i) => globalAliases2[i] === x)) {
57
74
  cmd = c
58
75
  break
59
76
  }
60
77
  }
61
78
 
62
- if (!cmd) return error(new CommandNotFound(command, msg, args))
63
-
64
79
  msg.data = {
65
80
  cts: this.client,
66
81
  command: cmd,
@@ -71,6 +86,8 @@ export class CommandHandler extends BuiltInModule {
71
86
  return
72
87
  }
73
88
 
89
+ if (!cmd) return error(new CommandNotFound(command, msg, args))
90
+
74
91
  const module = this.registry.modules.find((x) => x.commands.includes(cmd!))
75
92
 
76
93
  if (!module) return
@@ -125,31 +142,32 @@ export class CommandHandler extends BuiltInModule {
125
142
  return error(e)
126
143
  }
127
144
  }
145
+ // endregion
128
146
 
147
+ // region slash command handler
129
148
  private async command(i: CommandInteraction) {
130
- const error = (error: Error) => this.client.client.emit('slashCommandError', error, i)
149
+ const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
131
150
  try {
132
- const cmd = this.registry.slashCommands.find((x) => x.commandBuilder.name === i.commandName)
151
+ const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'CHAT_INPUT' && x.command.name === i.commandName)
133
152
 
134
- const module = this.registry.modules.find((x) => x.slashCommands.includes(cmd!))
153
+ if (!cmd) return
154
+
155
+ const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
135
156
 
136
157
  if (!module) return
137
158
 
138
159
  const argList: any[] = []
139
160
 
140
- if (!cmd)
141
- return i.reply({
142
- content: 'Unknown command.',
143
- ephemeral: true,
144
- })
145
-
146
161
  i.data = {
147
162
  cts: this.client,
148
163
  command: cmd,
149
164
  }
150
165
 
166
+ if (!(await this.client.options.slashCommands.check(i))) {
167
+ return error(new SlashCommandGlobalCheckError(i))
168
+ }
151
169
  for (const check of cmd.checks) {
152
- if (!(await check(i))) return error(new SlashCommandCheckFailed(i, cmd))
170
+ if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
153
171
  }
154
172
 
155
173
  for (let j = 0; j < cmd.params.length; j++) {
@@ -196,11 +214,82 @@ export class CommandHandler extends BuiltInModule {
196
214
  argList.push(await converter.execute(module, i))
197
215
  }
198
216
 
199
- try {
200
- await cmd.execute(module, argList)
201
- } catch (e: any) {
202
- return error(e)
217
+ await cmd.execute(module, argList)
218
+ } catch (e) {
219
+ return error(e)
220
+ }
221
+ }
222
+ // endregion
223
+
224
+ private async messageComponent(i: MessageComponentInteraction) {
225
+ const error = (e: any) => this.client.client.emit('messageComponentError', e)
226
+
227
+ try {
228
+ const handlers: MessageComponentHandler[] = []
229
+
230
+ for (const handler of this.registry.messageComponentHandlers) {
231
+ if (handler.componentId === handler.componentId && handler.componentType === i.componentType) {
232
+ handlers.push(handler)
233
+ }
234
+ }
235
+
236
+ for (const handler of handlers) {
237
+ const module = this.registry.modules.find((x) => x.messageComponentHandlers.includes(handler))
238
+ if (!module) continue
239
+ await handler.run(module, i)
240
+ }
241
+ } catch (e) {
242
+ error(e)
243
+ }
244
+ }
245
+
246
+ private async userContextMenu(i: UserContextMenuInteraction) {
247
+ const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
248
+ try {
249
+ const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'USER' && x.command.name === i.commandName)
250
+
251
+ if (!cmd) return
252
+
253
+ const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
254
+
255
+ if (!module) return
256
+
257
+ i.data = {
258
+ cts: this.client,
259
+ command: cmd,
260
+ }
261
+
262
+ for (const check of cmd.checks) {
263
+ if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
264
+ }
265
+
266
+ await cmd.execute(module, [i])
267
+ } catch (e) {
268
+ return error(e)
269
+ }
270
+ }
271
+
272
+ private async messageContextMenu(i: MessageContextMenuInteraction) {
273
+ const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
274
+ try {
275
+ const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'MESSAGE' && x.command.name === i.commandName)
276
+
277
+ if (!cmd) return
278
+
279
+ const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
280
+
281
+ if (!module) return
282
+
283
+ i.data = {
284
+ cts: this.client,
285
+ command: cmd,
286
+ }
287
+
288
+ for (const check of cmd.checks) {
289
+ if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
203
290
  }
291
+
292
+ await cmd.execute(module, [i])
204
293
  } catch (e) {
205
294
  return error(e)
206
295
  }
@@ -208,8 +297,28 @@ export class CommandHandler extends BuiltInModule {
208
297
 
209
298
  @listener('interactionCreate')
210
299
  async interaction(i: Interaction) {
211
- if (i.isCommand()) {
212
- await this.command(i)
300
+ const error = (e: any) => this.client.client.emit('interactionError', e, i)
301
+
302
+ try {
303
+ await this.client.options.applicationCommands.beforeRunCheck(i)
304
+ if (i.isCommand()) {
305
+ await this.command(i)
306
+ return
307
+ }
308
+ if (i.isMessageComponent()) {
309
+ await this.messageComponent(i)
310
+ return
311
+ }
312
+ if (i.isMessageContextMenu()) {
313
+ await this.messageContextMenu(i)
314
+ return
315
+ }
316
+ if (i.isUserContextMenu()) {
317
+ await this.userContextMenu(i)
318
+ return
319
+ }
320
+ } catch (e) {
321
+ return error(e)
213
322
  }
214
323
  }
215
324
  }
@@ -1,5 +1,5 @@
1
1
  import { Module } from '../structures'
2
- import { CommandInteraction, Message } from 'discord.js'
2
+ import { CommandInteraction, ContextMenuInteraction, Message, MessageComponentInteraction } from 'discord.js'
3
3
  import { KCommandChecks } from '../constants'
4
4
 
5
5
  export type Argument = {
@@ -9,7 +9,7 @@ export type Argument = {
9
9
  }
10
10
 
11
11
  export type CheckFunction = (msg: Message) => boolean | Promise<boolean>
12
- export type SlashCheckFunction = (i: CommandInteraction) => boolean | Promise<boolean>
12
+ export type ApplicationCommandCheckFunction = (i: CommandInteraction | MessageComponentInteraction | ContextMenuInteraction) => boolean | Promise<boolean>
13
13
 
14
14
  export class Command {
15
15
  execute(module: Module, args: any[]) {
@@ -10,6 +10,7 @@ import { ClientPermissionRequired, DMOnlyCommandError, GuildOnlyCommandError, Ow
10
10
  type CommandOptions = {
11
11
  name: string
12
12
  aliases: string[] | ((msg: Message) => string[])
13
+ optionTypes?: any[]
13
14
  }
14
15
 
15
16
  export const command = (options: Partial<CommandOptions> = {}) => {
@@ -22,7 +23,7 @@ export const command = (options: Partial<CommandOptions> = {}) => {
22
23
 
23
24
  let properties: Command[] = Reflect.getMetadata(KCommands, target)
24
25
 
25
- const params: any[] = Reflect.getMetadata('design:paramtypes', target, propertyKey)
26
+ const params: any[] = options.optionTypes ?? Reflect.getMetadata('design:paramtypes', target, propertyKey)
26
27
 
27
28
  const optionals: number = Reflect.getMetadata(KOptionals, target, propertyKey) || -1
28
29
 
@@ -1,10 +1,10 @@
1
- import { CommandInteraction, Message } from 'discord.js'
2
- import type { CheckFunction, SlashCheckFunction } from './Command'
3
- import { KCommandChecks, KSlashCommandChecks } from '../constants'
1
+ import { CommandInteraction, ContextMenuInteraction, Message, MessageComponentInteraction } from 'discord.js'
2
+ import type { CheckFunction, ApplicationCommandCheckFunction } from './Command'
3
+ import { KCommandChecks, KApplicationCommandChecks } from '../constants'
4
4
 
5
5
  export const createCheckDecorator = (
6
6
  execute: ((msg: Message) => boolean | Promise<boolean>) | null,
7
- slashExecute?: (i: CommandInteraction) => boolean | Promise<boolean>,
7
+ executeApplicationCommand?: (i: CommandInteraction | MessageComponentInteraction | ContextMenuInteraction) => boolean | Promise<boolean>,
8
8
  ): MethodDecorator => {
9
9
  return (target, propertyKey) => {
10
10
  if (execute) {
@@ -16,13 +16,13 @@ export const createCheckDecorator = (
16
16
  Reflect.defineMetadata(KCommandChecks, properties, target, propertyKey)
17
17
  }
18
18
  }
19
- if (slashExecute) {
20
- let properties: SlashCheckFunction[] = Reflect.getMetadata(KSlashCommandChecks, target, propertyKey)
19
+ if (executeApplicationCommand) {
20
+ let properties: ApplicationCommandCheckFunction[] = Reflect.getMetadata(KApplicationCommandChecks, target, propertyKey)
21
21
  if (properties) {
22
- properties.push(slashExecute)
22
+ properties.push(executeApplicationCommand)
23
23
  } else {
24
- properties = [slashExecute]
25
- Reflect.defineMetadata(KSlashCommandChecks, properties, target, propertyKey)
24
+ properties = [executeApplicationCommand]
25
+ Reflect.defineMetadata(KApplicationCommandChecks, properties, target, propertyKey)
26
26
  }
27
27
  }
28
28
  }
package/src/constants.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export const KCommands = Symbol('Command.TS Commands')
2
2
 
3
- export const KSlashCommands = Symbol('Command.TS Slash Commands')
3
+ export const KApplicationCommands = Symbol('Command.TS Slash Commands')
4
4
 
5
5
  export const KSlashCommandOptions = Symbol('Command.TS Slash Command Options')
6
6
 
@@ -22,4 +22,6 @@ export const KSlashArgumentConverters = Symbol('Command.TS Slash Argument Conver
22
22
 
23
23
  export const KCommandChecks = Symbol('Command.TS Command Checks')
24
24
 
25
- export const KSlashCommandChecks = Symbol('Command.TS Slash Command Checks')
25
+ export const KApplicationCommandChecks = Symbol('Command.TS Slash Command Checks')
26
+
27
+ export const KMessageComponentHandlers = Symbol('Command.TS Message Component Handlers')
@@ -1,6 +1,6 @@
1
1
  import { CommandInteraction, Message } from 'discord.js'
2
2
  import type { Argument } from '../command'
3
- import type { SlashArgument } from '../slashCommand'
3
+ import type { SlashArgument } from '../applicationCommand'
4
4
 
5
5
  export class ArgumentConverterNotFound extends Error {
6
6
  constructor(public type: Argument, public msg: Message) {
@@ -1,6 +1,6 @@
1
- import { CommandInteraction, Message } from 'discord.js'
1
+ import { CommandInteraction, ContextMenuInteraction, Message, MessageComponentInteraction } from 'discord.js'
2
2
  import { Command } from '../command'
3
- import { SlashCommand } from '../slashCommand'
3
+ import { AppCommand } from '../applicationCommand'
4
4
 
5
5
  export class CommandCheckFailed extends Error {
6
6
  constructor(public msg: Message, public command: Command) {
@@ -8,8 +8,8 @@ export class CommandCheckFailed extends Error {
8
8
  }
9
9
  }
10
10
 
11
- export class SlashCommandCheckFailed extends Error {
12
- constructor(public interaction: CommandInteraction, public command: SlashCommand) {
11
+ export class ApplicationCommandCheckFailed extends Error {
12
+ constructor(public interaction: CommandInteraction | MessageComponentInteraction | ContextMenuInteraction, public command: AppCommand) {
13
13
  super()
14
14
  }
15
15
  }
@@ -0,0 +1,7 @@
1
+ import { CommandInteraction } from 'discord.js'
2
+
3
+ export class SlashCommandGlobalCheckError extends Error {
4
+ constructor(public i: CommandInteraction) {
5
+ super('Slash command before-run check failed.')
6
+ }
7
+ }
package/src/index.ts CHANGED
@@ -7,4 +7,5 @@ export * from './error'
7
7
  export * from './command'
8
8
  export * from './listener'
9
9
  export * from './builtinModules/BuiltInModule'
10
- export * from './slashCommand'
10
+ export * from './applicationCommand'
11
+ export * from './messageComponents'
@@ -0,0 +1,12 @@
1
+ import { MessageComponentInteraction, MessageComponentType } from 'discord.js'
2
+ import { Module } from '../structures'
3
+
4
+ export type MessageComponentExecutor = (i: MessageComponentInteraction) => void | Promise<void>
5
+
6
+ export class MessageComponentHandler {
7
+ constructor(public componentId: string, public componentType: Exclude<MessageComponentType, 'ACTION_ROW'>, public execute: MessageComponentExecutor) {}
8
+
9
+ run(module: Module, i: MessageComponentInteraction) {
10
+ return this.execute.apply(module, [i])
11
+ }
12
+ }
@@ -0,0 +1,26 @@
1
+ import { MessageComponentExecutor, MessageComponentHandler } from './base'
2
+ import { checkTarget } from '../utils'
3
+ import { KMessageComponentHandlers } from '../constants'
4
+
5
+ export class ButtonInteractionHandler extends MessageComponentHandler {
6
+ constructor(id: string, execute: MessageComponentExecutor) {
7
+ super(id, 'BUTTON', execute)
8
+ }
9
+ }
10
+
11
+ export const messageButton = (id: string): MethodDecorator => {
12
+ return (target, propertyKey) => {
13
+ checkTarget(target)
14
+
15
+ const handler = new ButtonInteractionHandler(id, Reflect.get(target, propertyKey))
16
+
17
+ let properties: MessageComponentHandler[] = Reflect.getMetadata(KMessageComponentHandlers, target)
18
+
19
+ if (properties) {
20
+ properties.push(handler)
21
+ } else {
22
+ properties = [handler]
23
+ Reflect.defineMetadata(KMessageComponentHandlers, properties, target)
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,2 @@
1
+ export * from './button'
2
+ export * from './selectMenu'
@@ -0,0 +1,26 @@
1
+ import { MessageComponentExecutor, MessageComponentHandler } from './base'
2
+ import { checkTarget } from '../utils'
3
+ import { KMessageComponentHandlers } from '../constants'
4
+
5
+ export class SelectMenuInteractionHandler extends MessageComponentHandler {
6
+ constructor(id: string, execute: MessageComponentExecutor) {
7
+ super(id, 'SELECT_MENU', execute)
8
+ }
9
+ }
10
+
11
+ export const messageSelectMenu = (id: string): MethodDecorator => {
12
+ return (target, propertyKey) => {
13
+ checkTarget(target)
14
+
15
+ const handler = new SelectMenuInteractionHandler(id, Reflect.get(target, propertyKey))
16
+
17
+ let properties: MessageComponentHandler[] = Reflect.getMetadata(KMessageComponentHandlers, target)
18
+
19
+ if (properties) {
20
+ properties.push(handler)
21
+ } else {
22
+ properties = [handler]
23
+ Reflect.defineMetadata(KMessageComponentHandlers, properties, target)
24
+ }
25
+ }
26
+ }
@@ -1,31 +1,38 @@
1
1
  import _ from 'lodash'
2
2
  import { Registry } from './Registry'
3
- import { Client, Message, Snowflake, User } from 'discord.js'
3
+ import { Client, CommandInteraction, Interaction, Message, Snowflake, User } from 'discord.js'
4
4
  import { BuiltinCommandConverters, BuiltinSlashCommandConverters, CommandHandler } from '../builtinModules'
5
5
  import { CoolDownAdapter, DefaultCoolDownAdapter } from '../command'
6
- import { REST } from '@discordjs/rest'
7
6
  import { Logger } from 'tslog'
8
7
 
9
8
  export interface CommandOptions {
10
9
  prefix: string | ((msg: any) => string | Promise<string | string[]> | string[]) | string[]
11
10
  check: (msg: Message) => boolean | Promise<boolean>
11
+ globalAliases: (cmd: string, msg: Message) => string[] | Promise<string[]>
12
12
  }
13
13
 
14
14
  export interface SlashCommandOptions {
15
+ check: (i: CommandInteraction) => boolean | Promise<boolean>
16
+ }
17
+
18
+ export interface ApplicationCommandOptions {
15
19
  guild?: Snowflake | Snowflake[]
16
20
  autoSync: boolean
21
+ beforeRunCheck: (i: Interaction) => void | Promise<void>
17
22
  }
18
23
 
19
24
  export interface CommandClientOptions {
20
25
  command: CommandOptions
21
26
  owners: 'auto' | Snowflake[]
22
27
  slashCommands: SlashCommandOptions
28
+ applicationCommands: ApplicationCommandOptions
23
29
  }
24
30
 
25
31
  export interface CommandClientOptionsParam {
26
32
  command: Partial<CommandOptions>
27
33
  owners: 'auto' | string[]
28
34
  slashCommands: Partial<SlashCommandOptions>
35
+ applicationCommands: Partial<ApplicationCommandOptions>
29
36
  }
30
37
 
31
38
  export class CommandClient {
@@ -34,9 +41,6 @@ export class CommandClient {
34
41
  registry = new Registry(this)
35
42
  client: Client
36
43
  coolDownAdapter: CoolDownAdapter
37
- rest = new REST({
38
- version: '9',
39
- })
40
44
  logger: Logger
41
45
 
42
46
  private _isReady = false
@@ -51,13 +55,12 @@ export class CommandClient {
51
55
 
52
56
  async ready() {
53
57
  if (this._isReady) return
54
- this.rest.setToken(this.client.token!)
55
58
  this._isReady = true
56
59
  if (this.options.owners === 'auto') {
57
60
  const owners = await this.fetchOwners()
58
61
  this.owners.push(...owners)
59
62
  }
60
- if (this.options.slashCommands.autoSync) {
63
+ if (this.options.applicationCommands.autoSync) {
61
64
  await this.registry.syncCommands()
62
65
  }
63
66
  }
@@ -70,10 +73,15 @@ export class CommandClient {
70
73
  command: {
71
74
  prefix: '!',
72
75
  check: () => true,
76
+ globalAliases: () => [],
73
77
  },
74
78
  owners: 'auto',
75
79
  slashCommands: {
76
- autoSync: true,
80
+ check: () => true,
81
+ },
82
+ applicationCommands: {
83
+ autoSync: false,
84
+ beforeRunCheck: () => {},
77
85
  },
78
86
  },
79
87
  options,
@@ -1,9 +1,10 @@
1
- import { KArgumentConverters, KCommands, KListeners, KModulePath, KSlashArgumentConverters, KSlashCommands } from '../constants'
1
+ import { KArgumentConverters, KCommands, KListeners, KMessageComponentHandlers, KModulePath, KSlashArgumentConverters, KApplicationCommands } from '../constants'
2
2
  import type { Command } from '../command'
3
3
  import { Listener } from '../listener'
4
4
  import { ArgumentConverter, SlashArgumentConverter } from '../command'
5
- import { SlashCommand } from '../slashCommand'
5
+ import { AppCommand } from '../applicationCommand'
6
6
  import { CommandClient } from './CommandClient'
7
+ import { MessageComponentHandler } from '../messageComponents/base'
7
8
 
8
9
  export abstract class Module {
9
10
  commandClient!: CommandClient
@@ -30,8 +31,12 @@ export abstract class Module {
30
31
  return Reflect.getMetadata(KSlashArgumentConverters, this) || []
31
32
  }
32
33
 
33
- get slashCommands(): SlashCommand[] {
34
- return Reflect.getMetadata(KSlashCommands, this) || []
34
+ get applicationCommands(): AppCommand[] {
35
+ return Reflect.getMetadata(KApplicationCommands, this) || []
36
+ }
37
+
38
+ get messageComponentHandlers(): MessageComponentHandler[] {
39
+ return Reflect.getMetadata(KMessageComponentHandlers, this) || []
35
40
  }
36
41
 
37
42
  get path(): string | undefined {
@@ -7,9 +7,9 @@ import { InvalidModuleError, InvalidTargetError, ModuleLoadError } from '../erro
7
7
  import { Collection, Guild } from 'discord.js'
8
8
  import walkSync from 'walk-sync'
9
9
  import { ArgumentConverter } from '../command'
10
- import { SlashCommand } from '../slashCommand'
11
- import { Routes } from 'discord-api-types/v9'
10
+ import { AppCommand } from '../applicationCommand'
12
11
  import * as fs from 'fs'
12
+ import { MessageComponentHandler } from '../messageComponents/base'
13
13
 
14
14
  type ListenerExecutor = {
15
15
  event: string
@@ -57,11 +57,21 @@ export class Registry {
57
57
  return result
58
58
  }
59
59
 
60
- get slashCommands(): SlashCommand[] {
61
- const result: SlashCommand[] = []
60
+ get applicationCommands(): AppCommand[] {
61
+ const result: AppCommand[] = []
62
62
 
63
63
  for (const [, module] of this.modules) {
64
- result.push(...module.slashCommands)
64
+ result.push(...module.applicationCommands)
65
+ }
66
+
67
+ return result
68
+ }
69
+
70
+ get messageComponentHandlers(): MessageComponentHandler[] {
71
+ const result: MessageComponentHandler[] = []
72
+
73
+ for (const [, module] of this.modules) {
74
+ result.push(...module.messageComponentHandlers)
65
75
  }
66
76
 
67
77
  return result
@@ -128,19 +138,17 @@ export class Registry {
128
138
 
129
139
  async syncCommands() {
130
140
  this.logger.debug(`Syncing commands...`)
131
- const commands = this.slashCommands.filter((x) => !x.guild)
132
- const guild = this.client.options.slashCommands.guild
141
+ const commands = this.applicationCommands.filter((x) => !x.guild)
142
+ const guild = this.client.options.applicationCommands.guild
133
143
  if (guild) {
134
144
  const syncForGuild = async (g: Guild) => {
135
145
  this.logger.debug(`Syncing for guild ${g.name}(${g.id})`)
136
146
  const commandsToRegister = [
137
- ...commands.map((x) => x.commandBuilder),
138
- ...this.slashCommands.filter((y) => y.guild === g.id || y.guild?.includes(g.id) || false).map((x) => x.commandBuilder),
147
+ ...commands.map((x) => x.command),
148
+ ...this.applicationCommands.filter((y) => y.guild === g.id || y.guild?.includes(g.id) || false).map((x) => x.command),
139
149
  ]
140
150
  this.logger.debug(`Command List: ${commandsToRegister.map((x) => x.name).join(', ')}`)
141
- await this.client.rest.put(Routes.applicationGuildCommands(this.client.client.application!.id, g.id) as any, {
142
- body: commandsToRegister.map((x) => x.toJSON()),
143
- })
151
+ await g.commands.set(commandsToRegister)
144
152
  }
145
153
 
146
154
  if (typeof guild === 'string') {
@@ -152,9 +160,7 @@ export class Registry {
152
160
  }
153
161
  } else {
154
162
  this.logger.debug('Syncing global...')
155
- await this.client.rest.put(Routes.applicationCommands(this.client.client.application!.id) as any, {
156
- body: commands.map((x) => x.commandBuilder.toJSON()),
157
- })
163
+ await this.client.client.application?.commands.set(commands.map((x) => x.command))
158
164
  }
159
165
  this.logger.debug('Syncing ended.')
160
166
  }
package/src/typings.ts CHANGED
@@ -1,18 +1,30 @@
1
1
  import type { Command } from './command'
2
2
  import { CommandClient } from './structures'
3
- import { SlashCommand } from './slashCommand'
3
+ import { AppCommand } from './applicationCommand'
4
4
 
5
5
  declare module 'discord.js' {
6
6
  interface Message {
7
7
  data: {
8
- command: Command
8
+ command: Command | null
9
9
  prefix: string
10
10
  cts: CommandClient
11
11
  }
12
12
  }
13
13
  interface CommandInteraction {
14
14
  data: {
15
- command: SlashCommand
15
+ command: AppCommand
16
+ cts: CommandClient
17
+ }
18
+ }
19
+ interface MessageComponentInteraction {
20
+ data: {
21
+ command: AppCommand
22
+ cts: CommandClient
23
+ }
24
+ }
25
+ interface ContextMenuInteraction {
26
+ data: {
27
+ command: AppCommand
16
28
  cts: CommandClient
17
29
  }
18
30
  }
package/test/index.ts CHANGED
@@ -8,12 +8,12 @@ const client = new Client({
8
8
  })
9
9
 
10
10
  const cts = new CommandClient({
11
- owners: [],
11
+ owners: 'auto',
12
12
  client,
13
13
  command: {
14
14
  prefix: '!',
15
15
  },
16
- slashCommands: {
16
+ applicationCommands: {
17
17
  autoSync: true,
18
18
  guild: '832938554438844438',
19
19
  },