@pikokr/command.ts 4.0.7 → 5.0.0-dev.a9cbae8

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 (73) hide show
  1. package/.github/workflows/codeql-analysis.yml +70 -0
  2. package/.github/workflows/publish.stable.yml +1 -1
  3. package/.github/workflows/publish.yml +1 -1
  4. package/.vscode/settings.json +10 -0
  5. package/.vscode/templates/ts.lict +5 -0
  6. package/dist/index.d.ts +40 -318
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/package.json +10 -7
  10. package/publish-version.js +10 -0
  11. package/scripts/docs.ts +8 -4
  12. package/src/applicationCommand/ApplicationCommand.ts +18 -0
  13. package/src/applicationCommand/ApplicationCommandOption.ts +9 -0
  14. package/src/applicationCommand/index.ts +2 -6
  15. package/src/core/components/BaseComponent.ts +32 -0
  16. package/src/core/components/ComponentArgument.ts +7 -0
  17. package/src/core/components/ComponentArgumentDecorator.ts +17 -0
  18. package/src/core/components/decoratorCreator.ts +69 -0
  19. package/src/core/components/index.ts +3 -0
  20. package/src/core/index.ts +1 -0
  21. package/src/core/symbols.ts +2 -0
  22. package/src/index.ts +10 -16
  23. package/test/index.ts +32 -23
  24. package/tsconfig.json +1 -1
  25. package/tsup.config.ts +8 -4
  26. package/src/applicationCommand/AppCommand.ts +0 -32
  27. package/src/applicationCommand/decorator.ts +0 -62
  28. package/src/builtinModules/BuiltInModule.ts +0 -13
  29. package/src/builtinModules/BuiltinApplicationCommandConverters.ts +0 -16
  30. package/src/builtinModules/BuiltinCommandConverters.ts +0 -87
  31. package/src/builtinModules/CommandHandler.ts +0 -363
  32. package/src/builtinModules/index.ts +0 -7
  33. package/src/command/ArgumentConverter.ts +0 -22
  34. package/src/command/Command.ts +0 -35
  35. package/src/command/cooldown/adapter.ts +0 -22
  36. package/src/command/cooldown/decorator.ts +0 -67
  37. package/src/command/cooldown/error.ts +0 -9
  38. package/src/command/cooldown/index.ts +0 -9
  39. package/src/command/cooldown/type.ts +0 -12
  40. package/src/command/decorator.ts +0 -185
  41. package/src/command/index.ts +0 -9
  42. package/src/command/utils.ts +0 -33
  43. package/src/constants.ts +0 -31
  44. package/src/error/ArgumentConverterNotFound.ts +0 -18
  45. package/src/error/ArgumentNotProvided.ts +0 -12
  46. package/src/error/CommandCheckFailed.ts +0 -19
  47. package/src/error/CommandNotFound.ts +0 -11
  48. package/src/error/InvalidTargetError.ts +0 -9
  49. package/src/error/ModuleError.ts +0 -11
  50. package/src/error/PermissionRequired.ts +0 -17
  51. package/src/error/checks/DMOnlyCommand.ts +0 -9
  52. package/src/error/checks/GuildOnlyCommand.ts +0 -9
  53. package/src/error/checks/OwnerOnlyCommand.ts +0 -9
  54. package/src/error/checks/SlashCommandGlobalCheckError.ts +0 -11
  55. package/src/error/checks/index.ts +0 -8
  56. package/src/error/index.ts +0 -12
  57. package/src/interface/index.ts +0 -7
  58. package/src/listener/Listener.ts +0 -7
  59. package/src/listener/decorator.ts +0 -29
  60. package/src/listener/index.ts +0 -6
  61. package/src/messageComponents/base.ts +0 -16
  62. package/src/messageComponents/button.ts +0 -30
  63. package/src/messageComponents/index.ts +0 -6
  64. package/src/messageComponents/selectMenu.ts +0 -30
  65. package/src/structures/CommandClient.ts +0 -103
  66. package/src/structures/Module.ts +0 -54
  67. package/src/structures/Registry.ts +0 -253
  68. package/src/structures/index.ts +0 -7
  69. package/src/typings.ts +0 -35
  70. package/src/utils.ts +0 -10
  71. package/test/config.example.json +0 -3
  72. package/test/modules/dev.ts +0 -44
  73. package/test/modules/test.ts +0 -148
@@ -1,62 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { ApplicationCommandDataResolvable, Collection, Snowflake } from 'discord.js'
6
- import { checkTarget } from '../utils'
7
- import { KSlashCommandOptions, KApplicationCommands } from '../constants'
8
- import { Module } from '../structures'
9
- import { AppCommand } from './AppCommand'
10
-
11
- type ApplicationCommandOptions = {
12
- guild: Snowflake | Snowflake[]
13
- optionTypes?: any[]
14
- }
15
-
16
- export const applicationCommand = (opt: Partial<ApplicationCommandOptions> & { command: ApplicationCommandDataResolvable }) => {
17
- return (
18
- target: Object,
19
- propertyKey: string,
20
- // descriptor: TypedPropertyDescriptor<any>,
21
- ) => {
22
- checkTarget(target)
23
-
24
- let properties: AppCommand[] = Reflect.getMetadata(KApplicationCommands, target)
25
-
26
- const params: any[] = opt.optionTypes ?? Reflect.getMetadata('design:paramtypes', target, propertyKey)
27
-
28
- const options: Collection<number, string> = Reflect.getMetadata(KSlashCommandOptions, target, propertyKey) || new Collection<number, string>()
29
-
30
- const command = new AppCommand(
31
- opt.command,
32
- Reflect.get(target, propertyKey),
33
- target as Module,
34
- params.map((x, i) => ({
35
- type: x,
36
- name: options.get(i),
37
- })),
38
- opt.guild,
39
- propertyKey,
40
- )
41
-
42
- if (properties) {
43
- properties.push(command)
44
- } else {
45
- properties = [command]
46
- Reflect.defineMetadata(KApplicationCommands, properties, target)
47
- }
48
- }
49
- }
50
-
51
- export const option = (key: string): ParameterDecorator => (target, propertyKey, parameterIndex) => {
52
- checkTarget(target)
53
-
54
- let properties: Collection<number, string> = Reflect.getMetadata(KSlashCommandOptions, target, propertyKey)
55
-
56
- if (!properties) {
57
- properties = new Collection<number, string>()
58
- Reflect.defineMetadata(KSlashCommandOptions, properties, target, propertyKey)
59
- }
60
-
61
- properties.set(parameterIndex, key)
62
- }
@@ -1,13 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { Module } from '../structures'
6
- import { KBuiltInModule } from '../constants'
7
-
8
- export class BuiltInModule extends Module {
9
- constructor() {
10
- super()
11
- Reflect.defineMetadata(KBuiltInModule, true, this)
12
- }
13
- }
@@ -1,16 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { BuiltInModule } from './BuiltInModule'
6
- import { Client } from 'discord.js'
7
- import { CommandClient } from '../structures'
8
-
9
- export class BuiltinApplicationCommandConverters extends BuiltInModule {
10
- client: Client
11
-
12
- constructor(private cts: CommandClient) {
13
- super()
14
- this.client = cts.client
15
- }
16
- }
@@ -1,87 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { BuiltInModule } from './BuiltInModule'
6
- import { argumentConverter } from '../command'
7
- import { Client, GuildMember, Message, User, Role } from 'discord.js'
8
- import { CommandClient } from '../structures'
9
-
10
- export class BuiltinCommandConverters extends BuiltInModule {
11
- client: Client
12
-
13
- constructor(private cts: CommandClient) {
14
- super()
15
- this.client = cts.client
16
- }
17
-
18
- @argumentConverter(Message, false)
19
- message(msg: Message) {
20
- return msg
21
- }
22
-
23
- @argumentConverter(String)
24
- string(msg: Message, arg: string) {
25
- return arg
26
- }
27
-
28
- getUserIDByMention(mention: string): `${bigint}` | undefined {
29
- if (!mention) return
30
- if (mention.startsWith('<@') && mention.endsWith('>')) {
31
- mention = mention.slice(2, -1)
32
- if (mention.startsWith('!')) {
33
- mention = mention.slice(1)
34
- }
35
- return mention as `${bigint}`
36
- }
37
- }
38
-
39
- @argumentConverter(User)
40
- user(msg: Message, value: string): User | null {
41
- let user = this.client.users.cache.get(value)
42
- if (user) return user
43
- user = this.client.users.cache.find((x) => x.tag === value || x.username === value)
44
- if (user) return user
45
- const id = this.getUserIDByMention(value)
46
- if (!id) return null
47
- user = this.client.users.cache.get(id)
48
- return user || null
49
- }
50
-
51
- @argumentConverter(GuildMember)
52
- member(msg: Message, value: string): GuildMember | undefined {
53
- let user = msg.guild?.members.cache.get(value)
54
- if (!user) return user
55
- user = msg.guild?.members.cache.find((x) => x.user.tag === value)
56
- if (user) return user
57
- const id = this.getUserIDByMention(value)
58
- if (!id) return
59
- user = msg.guild?.members.cache.get(id)
60
- return user || undefined
61
- }
62
-
63
- @argumentConverter(Number)
64
- number(msg: Message, value: string) {
65
- const n = Number(value)
66
- return isNaN(n) ? undefined : n
67
- }
68
-
69
- getRoleIDByMention(mention: string): `${bigint}` | undefined {
70
- if (!mention) return
71
- if (mention.startsWith('<@') && mention.endsWith('>')) {
72
- mention = mention.slice(2, -1)
73
- if (mention.startsWith('&')) {
74
- mention = mention.slice(1)
75
- }
76
- return mention as `${bigint}`
77
- }
78
- }
79
-
80
- @argumentConverter(Role)
81
- role(msg: Message, value: string): Role | undefined {
82
- const id = this.getRoleIDByMention(value)
83
- if (!id) return
84
- const role = msg.guild?.roles.cache.get(id)
85
- return role || undefined
86
- }
87
- }
@@ -1,363 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { BuiltInModule } from './BuiltInModule'
6
- import { Registry } from '../structures'
7
- import { listener } from '../listener'
8
- import {
9
- CommandInteraction,
10
- CommandInteractionOptionResolver,
11
- GuildMember,
12
- Interaction,
13
- Message,
14
- MessageComponentInteraction,
15
- MessageContextMenuInteraction,
16
- Role,
17
- User,
18
- UserContextMenuInteraction,
19
- } from 'discord.js'
20
- import { CommandClient } from '../structures'
21
- import { Command } from '../command'
22
- import { ArgumentConverterNotFound, ArgumentNotProvided, CommandCheckFailed, ApplicationCommandArgumentConverterNotFound, ApplicationCommandCheckFailed } from '../error'
23
- import { CommandNotFound } from '../error/CommandNotFound'
24
- import { SlashCommandGlobalCheckError } from '../error/checks/SlashCommandGlobalCheckError'
25
- import { MessageComponentHandler } from '../messageComponents/base'
26
-
27
- export class CommandHandler extends BuiltInModule {
28
- private readonly client: CommandClient
29
-
30
- constructor(private registry: Registry) {
31
- super()
32
- this.client = registry.client
33
- }
34
-
35
- // region message command handler
36
- @listener('messageCreate')
37
- async message(msg: Message) {
38
- const error = (error: Error) => this.client.client.emit('commandError', error, msg)
39
-
40
- try {
41
- const prefixList: string[] | string =
42
- typeof this.client.options.command.prefix === 'string'
43
- ? this.client.options.command.prefix
44
- : typeof this.client.options.command.prefix === 'function'
45
- ? await this.client.options.command.prefix(msg)
46
- : this.client.options.command.prefix
47
- let prefix: string
48
- if (typeof prefixList === 'object') {
49
- const res = prefixList.find((x) => msg.content.includes(x))
50
-
51
- if (!res) return
52
-
53
- prefix = res
54
- } else {
55
- if (!msg.content.includes(prefixList)) return
56
- prefix = prefixList
57
- }
58
-
59
- if (!msg.content.startsWith(prefix)) return
60
-
61
- const args = msg.content.slice(prefix.length).split(' ')
62
-
63
- const command = args.shift()
64
-
65
- if (!command) return
66
-
67
- let cmd: Command | null = null
68
-
69
- for (const c of this.registry.commands) {
70
- const aliases = typeof c.aliases === 'function' ? await c.aliases(msg) : c.aliases
71
- if ([...aliases, c.name].some((x) => x === command)) {
72
- cmd = c
73
- break
74
- }
75
- }
76
-
77
- msg.data = {
78
- cts: this.client,
79
- command: cmd,
80
- prefix: prefix,
81
- }
82
-
83
- if (!(await this.client.options.command.check(msg))) {
84
- return
85
- }
86
-
87
- if (!cmd) return error(new CommandNotFound(command, msg, args))
88
-
89
- const module = this.registry.modules.find((x) => x.commands.includes(cmd!))
90
-
91
- if (!module) return
92
-
93
- const argList: any[] = []
94
-
95
- for (const check of cmd.checks) {
96
- if (!(await check(msg))) return error(new CommandCheckFailed(msg, cmd))
97
- }
98
-
99
- for (let i = 0; i < cmd.argTypes.length; i++) {
100
- const argType = cmd.argTypes[i]
101
- const converter = this.registry.argumentConverters.find((x) => x.type === argType.type)
102
-
103
- if (argType.rest) {
104
- const i = args.join(' ')
105
- argList.push(i)
106
- break
107
- }
108
-
109
- if (!converter) return error(new ArgumentConverterNotFound(argType, msg))
110
-
111
- const converterModule = this.registry.modules.find((x) => x.argumentConverters.includes(converter))
112
-
113
- if (!converterModule) return error(new ArgumentConverterNotFound(argType, msg))
114
-
115
- if (converter.withoutParameter) {
116
- argList.push(await converter.execute(converterModule, msg))
117
- continue
118
- }
119
- const arg = args.shift()
120
- if (argType.optional && !arg) {
121
- break
122
- }
123
- if (!arg) {
124
- return error(new ArgumentNotProvided(i, cmd, msg))
125
- }
126
- const executed = await converter.execute(converterModule, msg, arg)
127
- if ((executed === undefined || executed === null) && !argType.optional) {
128
- return error(new ArgumentNotProvided(i, cmd, msg))
129
- }
130
- argList.push(executed)
131
- }
132
-
133
- try {
134
- await cmd.execute(module, argList)
135
- } catch (e: any) {
136
- return error(e)
137
- }
138
- } catch (e: any) {
139
- return error(e)
140
- }
141
- }
142
- // endregion
143
-
144
- // region slash command handler
145
- private async command(i: CommandInteraction) {
146
- const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
147
- try {
148
- const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'CHAT_INPUT' && x.command.name === i.commandName)
149
-
150
- if (!cmd) return
151
-
152
- const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
153
-
154
- if (!module) return
155
-
156
- const argList: any[] = []
157
-
158
- i.data = {
159
- cts: this.client,
160
- command: cmd,
161
- }
162
-
163
- if (!(await this.client.options.slashCommands.check(i))) {
164
- return error(new SlashCommandGlobalCheckError(i))
165
- }
166
- for (const check of cmd.checks) {
167
- if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
168
- }
169
-
170
- for (let j = 0; j < cmd.params.length; j++) {
171
- const argType = cmd.params[j]
172
- const converter = this.registry.applicationCommandArgumentConverters.find((x) => x.type === argType.type)
173
-
174
- if (argType.type === CommandInteraction) {
175
- argList.push(i)
176
- continue
177
- }
178
-
179
- if (argType.type === CommandInteractionOptionResolver) {
180
- argList.push(i.options)
181
- continue
182
- }
183
-
184
- if (argType.name) {
185
- switch (argType.type) {
186
- case String:
187
- argList.push(i.options.getString(argType.name, false) || undefined)
188
- break
189
- case Role:
190
- argList.push(i.options.getRole(argType.name, false) || undefined)
191
- break
192
- case User:
193
- argList.push(i.options.getUser(argType.name, false) || undefined)
194
- break
195
- case GuildMember:
196
- argList.push(i.options.getMember(argType.name, false) || undefined)
197
- break
198
- case Boolean:
199
- argList.push(i.options.getBoolean(argType.name, false) || undefined)
200
- break
201
- case Number:
202
- const opt = i.options.get(argType.name, false)
203
- if (!opt) {
204
- argList.push(undefined)
205
- break
206
- }
207
- if (opt.type == 'NUMBER') {
208
- argList.push(i.options.getNumber(argType.name, false) ?? undefined)
209
- break
210
- }
211
- if (opt.type == 'INTEGER') {
212
- argList.push(i.options.getInteger(argType.name, false) ?? undefined)
213
- break
214
- }
215
- }
216
- continue
217
- }
218
-
219
- if (!converter) return error(new ApplicationCommandArgumentConverterNotFound(argType, i))
220
-
221
- argList.push(await converter.execute(module, i))
222
- }
223
-
224
- await cmd.execute(module, argList)
225
- } catch (e: any) {
226
- return error(e)
227
- }
228
- }
229
- // endregion
230
-
231
- private async messageComponent(i: MessageComponentInteraction) {
232
- const error = (e: any) => this.client.client.emit('messageComponentError', e)
233
-
234
- try {
235
- const handlers: MessageComponentHandler[] = []
236
-
237
- for (const handler of this.registry.messageComponentHandlers) {
238
- if (handler.componentId === handler.componentId && handler.componentType === i.componentType) {
239
- handlers.push(handler)
240
- }
241
- }
242
-
243
- for (const handler of handlers) {
244
- const module = this.registry.modules.find((x) => x.messageComponentHandlers.includes(handler))
245
- if (!module) continue
246
- await handler.run(module, i)
247
- }
248
- } catch (e) {
249
- error(e)
250
- }
251
- }
252
-
253
- private async userContextMenu(i: UserContextMenuInteraction) {
254
- const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
255
- try {
256
- const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'USER' && x.command.name === i.commandName)
257
-
258
- if (!cmd) return
259
-
260
- const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
261
-
262
- if (!module) return
263
-
264
- i.data = {
265
- cts: this.client,
266
- command: cmd,
267
- }
268
-
269
- for (const check of cmd.checks) {
270
- if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
271
- }
272
-
273
- let argList: any[] = []
274
-
275
- for (let j = 0; j < cmd.params.length; j++) {
276
- const argType = cmd.params[j]
277
- const converter = this.registry.applicationCommandArgumentConverters.find((x) => x.type === argType.type)
278
-
279
- if (argType.type === UserContextMenuInteraction) {
280
- argList.push(i)
281
- continue
282
- }
283
-
284
- if (!converter) return error(new ApplicationCommandArgumentConverterNotFound(argType, i))
285
-
286
- argList.push(await converter.execute(module, i))
287
- }
288
-
289
- await cmd.execute(module, argList)
290
- } catch (e: any) {
291
- return error(e)
292
- }
293
- }
294
-
295
- private async messageContextMenu(i: MessageContextMenuInteraction) {
296
- const error = (error: Error) => this.client.client.emit('applicationCommandError', error, i)
297
- try {
298
- const cmd = this.registry.applicationCommands.find((x) => x.command.type === 'MESSAGE' && x.command.name === i.commandName)
299
-
300
- if (!cmd) return
301
-
302
- const module = this.registry.modules.find((x) => x.applicationCommands.includes(cmd))
303
-
304
- if (!module) return
305
-
306
- i.data = {
307
- cts: this.client,
308
- command: cmd,
309
- }
310
-
311
- for (const check of cmd.checks) {
312
- if (!(await check(i))) return error(new ApplicationCommandCheckFailed(i, cmd))
313
- }
314
-
315
- let argList: any[] = []
316
-
317
- for (let j = 0; j < cmd.params.length; j++) {
318
- const argType = cmd.params[j]
319
- const converter = this.registry.applicationCommandArgumentConverters.find((x) => x.type === argType.type)
320
-
321
- if (argType.type === MessageContextMenuInteraction) {
322
- argList.push(i)
323
- continue
324
- }
325
-
326
- if (!converter) return error(new ApplicationCommandArgumentConverterNotFound(argType, i))
327
-
328
- argList.push(await converter.execute(module, i))
329
- }
330
-
331
- await cmd.execute(module, argList)
332
- } catch (e: any) {
333
- return error(e)
334
- }
335
- }
336
-
337
- @listener('interactionCreate')
338
- async interaction(i: Interaction) {
339
- const error = (e: any) => this.client.client.emit('interactionError', e, i)
340
-
341
- try {
342
- await this.client.options.applicationCommands.beforeRunCheck(i)
343
- if (i.isCommand()) {
344
- await this.command(i)
345
- return
346
- }
347
- if (i.isMessageComponent()) {
348
- await this.messageComponent(i)
349
- return
350
- }
351
- if (i.isMessageContextMenu()) {
352
- await this.messageContextMenu(i)
353
- return
354
- }
355
- if (i.isUserContextMenu()) {
356
- await this.userContextMenu(i)
357
- return
358
- }
359
- } catch (e) {
360
- return error(e)
361
- }
362
- }
363
- }
@@ -1,7 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- export * from './CommandHandler'
6
- export * from './BuiltinCommandConverters'
7
- export * from './BuiltinApplicationCommandConverters'
@@ -1,22 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { Module } from '../structures'
6
- import { CommandInteraction, ContextMenuInteraction, Message } from 'discord.js'
7
-
8
- export class ArgumentConverter {
9
- execute(module: Module, msg: Message, arg?: string) {
10
- return this.run.apply(module, [msg, arg])
11
- }
12
-
13
- constructor(public type: object, private run: Function, public withoutParameter: boolean) {}
14
- }
15
-
16
- export class ApplicationCommandArgumentConverter {
17
- execute(module: Module, interaction: CommandInteraction | ContextMenuInteraction) {
18
- return this.run.apply(module, [interaction])
19
- }
20
-
21
- constructor(public type: object, private run: Function) {}
22
- }
@@ -1,35 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { Module } from '../structures'
6
- import { CommandInteraction, ContextMenuInteraction, Message, MessageComponentInteraction } from 'discord.js'
7
- import { KCommandChecks } from '../constants'
8
-
9
- export type Argument = {
10
- optional: boolean
11
- type: any
12
- rest: boolean
13
- }
14
-
15
- export type CheckFunction = (msg: Message) => boolean | Promise<boolean>
16
- export type ApplicationCommandCheckFunction = (i: CommandInteraction | MessageComponentInteraction | ContextMenuInteraction) => boolean | Promise<boolean>
17
-
18
- export class Command {
19
- execute(module: Module, args: any[]) {
20
- return this.run.apply(module, args)
21
- }
22
-
23
- get checks(): CheckFunction[] {
24
- return Reflect.getMetadata(KCommandChecks, this.module, this.key) || []
25
- }
26
-
27
- constructor(
28
- private run: Function,
29
- public argTypes: Argument[],
30
- public name: string,
31
- public aliases: string[] | ((msg: Message) => string[] | Promise<string[]>),
32
- public module: Module,
33
- public key: symbol | string,
34
- ) {}
35
- }
@@ -1,22 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { Collection } from 'discord.js'
6
-
7
- export interface CoolDownAdapter {
8
- get(id: string): Promise<number | undefined>
9
- set(id: string, value: number): Promise<void>
10
- }
11
-
12
- export class DefaultCoolDownAdapter implements CoolDownAdapter {
13
- map = new Collection<string, number>()
14
- async get(id: string): Promise<number | undefined> {
15
- return this.map.get(id)
16
- }
17
-
18
- async set(id: string, value: number) {
19
- this.map.set(id, value)
20
- return
21
- }
22
- }
@@ -1,67 +0,0 @@
1
- /*
2
- * Copyright (c) 2022 pikokr. Licensed under the MIT license
3
- */
4
-
5
- import { createCheckDecorator } from '../utils'
6
- import { CoolDownType } from './type'
7
- import { DMChannel, GuildMember, TextChannel } from 'discord.js'
8
- import { CoolDownError } from './error'
9
-
10
- export const coolDown = (type: CoolDownType, seconds: number) =>
11
- createCheckDecorator(
12
- async (msg) => {
13
- const a = msg.data.cts.coolDownAdapter
14
- const getKey = (): string => {
15
- switch (type) {
16
- case CoolDownType.USER:
17
- return msg.author.id
18
- case CoolDownType.GUILD:
19
- return (msg.guild || msg.author).id
20
- case CoolDownType.CHANNEL:
21
- return msg.channel.id
22
- case CoolDownType.MEMBER:
23
- return `${msg.guild?.id}.${msg.author.id}`
24
- case CoolDownType.ROLE:
25
- return (msg.channel instanceof DMChannel ? msg.channel : msg.member!.roles.highest).id
26
- case CoolDownType.CATEGORY:
27
- return ((msg.channel as TextChannel).parent || msg.channel).id
28
- }
29
- }
30
- const key = getKey() + '-command-' + msg.data.command?.name
31
- const data = await a.get(key)
32
- const now = Date.now()
33
- if (!data || !(now - data < seconds * 1000)) {
34
- await a.set(key, now)
35
- return true
36
- }
37
- throw new CoolDownError(new Date(data + seconds * 1000))
38
- },
39
- async (i) => {
40
- if (i.isMessageComponent()) return true
41
- const a = i.data.cts.coolDownAdapter
42
- const getKey = (): string => {
43
- switch (type) {
44
- case CoolDownType.USER:
45
- return i.user.id + '.user'
46
- case CoolDownType.GUILD:
47
- return (i.guild || i.user).id + '.guild'
48
- case CoolDownType.CHANNEL:
49
- return i.channel!.id + '.channel'
50
- case CoolDownType.MEMBER:
51
- return `${i.guild?.id}.${i.user.id}`
52
- case CoolDownType.ROLE:
53
- return (i.channel instanceof DMChannel ? i.channel : (i.member as GuildMember)!.roles.highest).id + '.role'
54
- case CoolDownType.CATEGORY:
55
- return ((i.channel as TextChannel).parent || i.channel!).id + '.category'
56
- }
57
- }
58
- const key = getKey() + '-appCommand-' + i.commandName
59
- const data = await a.get(key)
60
- const now = Date.now()
61
- if (!data || !(now - data < seconds * 1000)) {
62
- await a.set(key, now)
63
- return true
64
- }
65
- throw new CoolDownError(new Date(data + seconds * 1000))
66
- },
67
- )