@pikokr/command.ts 4.0.5 → 5.0.0-dev.144e990
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.
- package/.github/workflows/codeql-analysis.yml +70 -0
- package/.github/workflows/docs.yml +2 -2
- package/.github/workflows/publish.stable.yml +1 -1
- package/.github/workflows/publish.yml +1 -1
- package/.vscode/settings.json +10 -0
- package/.vscode/templates/ts.lict +5 -0
- package/README.md +2 -0
- package/dist/index.d.ts +140 -292
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/docs/index.yml +1 -1
- package/package.json +22 -16
- package/publish-version.js +20 -0
- package/renovate.json +5 -0
- package/scripts/docs.ts +8 -4
- package/src/applicationCommand/ApplicationCommand.ts +17 -0
- package/src/applicationCommand/ApplicationCommandExtension.ts +169 -0
- package/src/applicationCommand/ApplicationCommandOption.ts +16 -0
- package/src/applicationCommand/index.ts +10 -6
- package/src/core/components/BaseComponent.ts +62 -0
- package/src/core/components/ComponentArgument.ts +15 -0
- package/src/core/components/ComponentArgumentDecorator.ts +25 -0
- package/src/core/components/decoratorCreator.ts +81 -0
- package/src/core/components/index.ts +13 -0
- package/src/core/converter/index.ts +16 -0
- package/src/core/extensions/CTSExtension.ts +17 -0
- package/src/core/extensions/Extension.ts +62 -0
- package/src/core/extensions/index.ts +9 -0
- package/src/core/hooks/componentHook.ts +40 -0
- package/src/core/hooks/index.ts +11 -0
- package/src/core/hooks/moduleHook.ts +39 -0
- package/src/core/index.ts +15 -0
- package/src/core/listener/index.ts +29 -0
- package/src/core/structures/CommandClient.ts +78 -0
- package/src/core/structures/Registry.ts +110 -0
- package/src/core/structures/index.ts +10 -0
- package/src/core/symbols.ts +13 -0
- package/src/core/utils/checks.ts +27 -0
- package/src/core/utils/errors.ts +9 -0
- package/src/core/utils/index.ts +10 -0
- package/src/index.ts +11 -16
- package/src/textCommand/TextCommand.ts +20 -0
- package/src/textCommand/TextCommandExtension.ts +128 -0
- package/src/textCommand/index.ts +11 -0
- package/src/textCommand/parameters.ts +14 -0
- package/test/index.ts +84 -21
- package/tsconfig.json +3 -3
- package/tsconfig.prod.json +8 -0
- package/tsup.config.ts +9 -4
- package/src/applicationCommand/AppCommand.ts +0 -32
- package/src/applicationCommand/decorator.ts +0 -62
- package/src/builtinModules/BuiltInModule.ts +0 -13
- package/src/builtinModules/BuiltinApplicationCommandConverters.ts +0 -16
- package/src/builtinModules/BuiltinCommandConverters.ts +0 -87
- package/src/builtinModules/CommandHandler.ts +0 -363
- package/src/builtinModules/index.ts +0 -7
- package/src/command/ArgumentConverter.ts +0 -22
- package/src/command/Command.ts +0 -35
- package/src/command/cooldown/adapter.ts +0 -22
- package/src/command/cooldown/decorator.ts +0 -67
- package/src/command/cooldown/error.ts +0 -9
- package/src/command/cooldown/index.ts +0 -9
- package/src/command/cooldown/type.ts +0 -12
- package/src/command/decorator.ts +0 -185
- package/src/command/index.ts +0 -9
- package/src/command/utils.ts +0 -33
- package/src/constants.ts +0 -31
- package/src/error/ArgumentConverterNotFound.ts +0 -18
- package/src/error/ArgumentNotProvided.ts +0 -12
- package/src/error/CommandCheckFailed.ts +0 -19
- package/src/error/CommandNotFound.ts +0 -11
- package/src/error/InvalidTargetError.ts +0 -9
- package/src/error/ModuleError.ts +0 -11
- package/src/error/PermissionRequired.ts +0 -17
- package/src/error/checks/DMOnlyCommand.ts +0 -9
- package/src/error/checks/GuildOnlyCommand.ts +0 -9
- package/src/error/checks/OwnerOnlyCommand.ts +0 -9
- package/src/error/checks/SlashCommandGlobalCheckError.ts +0 -11
- package/src/error/checks/index.ts +0 -8
- package/src/error/index.ts +0 -12
- package/src/interface/index.ts +0 -7
- package/src/listener/Listener.ts +0 -7
- package/src/listener/decorator.ts +0 -29
- package/src/listener/index.ts +0 -6
- package/src/messageComponents/base.ts +0 -16
- package/src/messageComponents/button.ts +0 -30
- package/src/messageComponents/index.ts +0 -6
- package/src/messageComponents/selectMenu.ts +0 -30
- package/src/structures/CommandClient.ts +0 -103
- package/src/structures/Module.ts +0 -54
- package/src/structures/Registry.ts +0 -245
- package/src/structures/index.ts +0 -7
- package/src/typings.ts +0 -35
- package/src/utils.ts +0 -10
- package/test/config.example.json +0 -3
- package/test/modules/dev.ts +0 -45
- 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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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,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
|
-
}
|
package/src/command/Command.ts
DELETED
|
@@ -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
|
-
)
|