@pikokr/command.ts 5.0.0-dev.6057824 → 5.0.0-dev.610cc76
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 +4 -4
- package/.github/workflows/docs.yml +5 -5
- package/.github/workflows/publish.stable.yml +2 -2
- package/.github/workflows/publish.yml +2 -2
- package/dist/index.d.ts +80 -9
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
- package/publish-version.js +10 -0
- package/renovate.json +5 -0
- package/scripts/docs.ts +8 -8
- package/src/applicationCommand/ApplicationCommand.ts +11 -2
- package/src/applicationCommand/ApplicationCommandExtension.ts +169 -0
- package/src/applicationCommand/ApplicationCommandOption.ts +9 -2
- package/src/applicationCommand/index.ts +8 -0
- package/src/core/components/BaseComponent.ts +35 -2
- package/src/core/components/ComponentArgument.ts +8 -0
- package/src/core/components/ComponentArgumentDecorator.ts +8 -0
- package/src/core/components/decoratorCreator.ts +14 -0
- package/src/core/components/index.ts +13 -3
- package/src/core/converter/index.ts +16 -0
- package/src/core/extensions/CTSExtension.ts +17 -0
- package/src/core/extensions/Extension.ts +43 -1
- package/src/core/extensions/index.ts +8 -0
- package/src/core/hooks/componentHook.ts +40 -0
- package/src/core/hooks/index.ts +11 -1
- package/src/core/hooks/moduleHook.ts +11 -3
- package/src/core/index.ts +13 -1
- package/src/core/listener/index.ts +10 -1
- package/src/core/structures/CommandClient.ts +45 -3
- package/src/core/structures/Registry.ts +10 -1
- package/src/core/structures/index.ts +8 -0
- package/src/core/symbols.ts +13 -4
- 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 -10
- 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 +32 -8
- package/tsup.config.ts +8 -8
- package/src/core/extensions/ApplicationCommand.ts +0 -80
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File: checks.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseInteraction, Interaction, Message } from 'discord.js'
|
|
10
|
+
import { createComponentHook } from '../hooks'
|
|
11
|
+
import { ComponentHookFn } from '../hooks/componentHook'
|
|
12
|
+
import { CommandClient } from '../structures'
|
|
13
|
+
import { OwnerOnlyError } from './errors'
|
|
14
|
+
|
|
15
|
+
export const createCheckDecorator = (fn: ComponentHookFn) => createComponentHook('beforeCall', fn)
|
|
16
|
+
|
|
17
|
+
export const ownerOnly = createCheckDecorator(async (client: CommandClient, i: Interaction | Message) => {
|
|
18
|
+
let isOwner = false
|
|
19
|
+
|
|
20
|
+
if (i instanceof BaseInteraction) {
|
|
21
|
+
isOwner = client.owners.has(i.user.id)
|
|
22
|
+
} else if (i instanceof Message) {
|
|
23
|
+
isOwner = client.owners.has(i.author.id)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!isOwner) throw new OwnerOnlyError()
|
|
27
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export * from './core'
|
|
10
|
-
export * from './applicationCommand'
|
|
1
|
+
/*
|
|
2
|
+
* File: index.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './core'
|
|
10
|
+
export * from './applicationCommand'
|
|
11
|
+
export * from './textCommand'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File: TextCommand.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createComponentDecorator } from '../core/components/decoratorCreator'
|
|
10
|
+
import { BaseComponent } from '../core/components/BaseComponent'
|
|
11
|
+
|
|
12
|
+
type TextCommandOptions = {
|
|
13
|
+
name: string
|
|
14
|
+
aliases?: string
|
|
15
|
+
description?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class TextCommandComponent extends BaseComponent<TextCommandOptions> {}
|
|
19
|
+
|
|
20
|
+
export const command = createComponentDecorator(TextCommandComponent)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File: TextCommandExtension.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { listener } from '../core/listener'
|
|
10
|
+
import { Message } from 'discord.js'
|
|
11
|
+
import { CTSExtension } from '../core/extensions/CTSExtension'
|
|
12
|
+
import { TextCommandComponent } from './TextCommand'
|
|
13
|
+
import { TextCommandRestOption } from './parameters'
|
|
14
|
+
import { argConverter } from '../core'
|
|
15
|
+
|
|
16
|
+
export type TextCommandConfig = {
|
|
17
|
+
prefix: string | string[] | ((msg: Message) => Promise<string | string[]> | string | string[])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TextCommandExtension extends CTSExtension {
|
|
21
|
+
constructor(private config: TextCommandConfig) {
|
|
22
|
+
super()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private async processPrefix(msg: Message): Promise<number | null> {
|
|
26
|
+
const content = msg.content
|
|
27
|
+
let prefix = this.config.prefix
|
|
28
|
+
|
|
29
|
+
if (typeof prefix === 'function') {
|
|
30
|
+
prefix = await prefix(msg)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof prefix === 'string') {
|
|
34
|
+
if (content.startsWith(prefix)) return prefix.length
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (prefix instanceof Array) {
|
|
39
|
+
const p = prefix.find((x) => content.startsWith(x))
|
|
40
|
+
|
|
41
|
+
if (p) return p.length
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@listener({ event: 'messageCreate', emitter: 'discord' })
|
|
49
|
+
private async messageCreate(msg: Message) {
|
|
50
|
+
const startIndex = await this.processPrefix(msg)
|
|
51
|
+
|
|
52
|
+
if (!startIndex) return
|
|
53
|
+
|
|
54
|
+
const content = msg.content.slice(startIndex)
|
|
55
|
+
|
|
56
|
+
const commands: TextCommandComponent[] = []
|
|
57
|
+
|
|
58
|
+
const extensions = new Map<TextCommandComponent, object>()
|
|
59
|
+
|
|
60
|
+
for (const ext of this.commandClient.registry.extensions) {
|
|
61
|
+
for (const cmd of this.commandClient.registry.getComponentsWithType(ext, TextCommandComponent)) {
|
|
62
|
+
commands.push(cmd)
|
|
63
|
+
extensions.set(cmd, ext)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let commandNameLength = 0
|
|
68
|
+
|
|
69
|
+
const command = commands.find((x) => {
|
|
70
|
+
const names = [x.options.name]
|
|
71
|
+
|
|
72
|
+
if (x.options.aliases) {
|
|
73
|
+
names.push(...x.options.aliases)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for (const name of names) {
|
|
77
|
+
if (content.startsWith(name)) {
|
|
78
|
+
if (content.length === name.length) {
|
|
79
|
+
commandNameLength = name.length
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
commandNameLength = name.length
|
|
83
|
+
return content.startsWith(name + ' ')
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return false
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if (!command) return
|
|
91
|
+
|
|
92
|
+
const ext = extensions.get(command)
|
|
93
|
+
|
|
94
|
+
if (!ext) return
|
|
95
|
+
|
|
96
|
+
const args: unknown[] = []
|
|
97
|
+
|
|
98
|
+
let argStrings = content.slice(commandNameLength + 1).split(/ /g)
|
|
99
|
+
|
|
100
|
+
await this.convertArguments(TextCommandComponent, args, command.argTypes, async (arg, i, converter) => {
|
|
101
|
+
if (converter.options.parameterless) return [msg]
|
|
102
|
+
|
|
103
|
+
if (arg.decorators.find((x) => x.constructor === TextCommandRestOption)) {
|
|
104
|
+
const text = argStrings.join(' ')
|
|
105
|
+
argStrings = []
|
|
106
|
+
return [text, msg]
|
|
107
|
+
}
|
|
108
|
+
return [argStrings.shift(), msg]
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
await command.execute(ext, args, [msg])
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@argConverter({ component: TextCommandComponent, type: Message, parameterless: true })
|
|
115
|
+
async mesage(msg: Message) {
|
|
116
|
+
return msg
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@argConverter({ component: TextCommandComponent, type: String })
|
|
120
|
+
async str(value: string) {
|
|
121
|
+
return value
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@argConverter({ component: TextCommandComponent, type: Number })
|
|
125
|
+
async num(value: string) {
|
|
126
|
+
return Number(value)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File: index.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './TextCommand'
|
|
10
|
+
export type { TextCommandConfig } from './TextCommandExtension'
|
|
11
|
+
export * from './parameters'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File: parameters.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ComponentArgumentDecorator } from '../core'
|
|
10
|
+
import { createArgumentDecorator } from '../core'
|
|
11
|
+
|
|
12
|
+
export class TextCommandRestOption extends ComponentArgumentDecorator<void> {}
|
|
13
|
+
|
|
14
|
+
export const rest = createArgumentDecorator(TextCommandRestOption)
|
package/test/index.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/*
|
|
2
|
+
* File: index.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ApplicationCommandOptionType, ApplicationCommandType, ChatInputCommandInteraction, Client, Message } from 'discord.js'
|
|
10
|
+
import { applicationCommand, CommandClient, moduleHook, option, ownerOnly, listener, Extension, command, rest } from '../src'
|
|
4
11
|
import 'dotenv/config'
|
|
5
12
|
import { Logger } from 'tslog'
|
|
6
13
|
import chalk from 'chalk'
|
|
7
|
-
import { Extension } from '../src/core/extensions'
|
|
8
14
|
|
|
9
15
|
class Test extends Extension {
|
|
10
16
|
@applicationCommand({
|
|
@@ -12,8 +18,11 @@ class Test extends Extension {
|
|
|
12
18
|
name: 'test',
|
|
13
19
|
description: 'wow this is test',
|
|
14
20
|
})
|
|
15
|
-
async testCommand() {
|
|
21
|
+
async testCommand(i: ChatInputCommandInteraction) {
|
|
22
|
+
i.reply('Wow')
|
|
23
|
+
}
|
|
16
24
|
|
|
25
|
+
@ownerOnly
|
|
17
26
|
@applicationCommand({
|
|
18
27
|
type: ApplicationCommandType.ChatInput,
|
|
19
28
|
name: 'test2',
|
|
@@ -24,9 +33,13 @@ class Test extends Extension {
|
|
|
24
33
|
name: 'sans',
|
|
25
34
|
description: '와',
|
|
26
35
|
type: ApplicationCommandOptionType.String,
|
|
36
|
+
required: true,
|
|
27
37
|
})
|
|
28
38
|
wa: string,
|
|
29
|
-
|
|
39
|
+
i: ChatInputCommandInteraction,
|
|
40
|
+
) {
|
|
41
|
+
i.reply(wa)
|
|
42
|
+
}
|
|
30
43
|
|
|
31
44
|
@moduleHook('load')
|
|
32
45
|
load() {
|
|
@@ -39,14 +52,21 @@ class Test extends Extension {
|
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
@listener({ event: 'ready' })
|
|
42
|
-
testEvent() {
|
|
55
|
+
async testEvent() {
|
|
43
56
|
this.logger.info(`Login: ${chalk.green(client.user!.tag)}`)
|
|
57
|
+
await this.commandClient.fetchOwners()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@command({ name: 'test' })
|
|
61
|
+
async test(msg: Message, @rest() sans: string) {
|
|
62
|
+
console.log(sans)
|
|
63
|
+
await msg.reply('Wow')
|
|
44
64
|
}
|
|
45
65
|
}
|
|
46
66
|
|
|
47
67
|
const ext = new Test()
|
|
48
68
|
|
|
49
|
-
const client = new Client({ intents: [] })
|
|
69
|
+
const client = new Client({ intents: ['GuildMessages', 'MessageContent', 'DirectMessages', 'Guilds'] })
|
|
50
70
|
|
|
51
71
|
const logger = new Logger({ dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone })
|
|
52
72
|
|
|
@@ -59,6 +79,10 @@ const run = async () => {
|
|
|
59
79
|
guilds: ['832938554438844438'],
|
|
60
80
|
})
|
|
61
81
|
|
|
82
|
+
await cc.enableTextCommandsExtension({
|
|
83
|
+
prefix: '.',
|
|
84
|
+
})
|
|
85
|
+
|
|
62
86
|
await registry.registerModule(ext)
|
|
63
87
|
|
|
64
88
|
await client.login(process.env.TOKEN)
|
package/tsup.config.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/*
|
|
2
|
+
* File: tsup.config.ts
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2022-2022 pikokr
|
|
5
|
+
*
|
|
6
|
+
* Licensed under MIT License. Please see more defails in LICENSE file.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
9
|
import { defineConfig } from 'tsup'
|
|
10
10
|
|
|
11
11
|
export default defineConfig({
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
import { ApplicationCommandData, ApplicationCommandType, GuildAuditLogs, Interaction, Snowflake } from 'discord.js'
|
|
3
|
-
import { ApplicationCommandComponent } from '../../applicationCommand'
|
|
4
|
-
import { ApplicationCommandOption } from '../../applicationCommand/ApplicationCommandOption'
|
|
5
|
-
import { moduleHook } from '../hooks'
|
|
6
|
-
import { listener } from '../listener'
|
|
7
|
-
import { CommandClient } from '../structures'
|
|
8
|
-
import { Extension } from './Extension'
|
|
9
|
-
|
|
10
|
-
export type ApplicationCommandExtensionConfig = {
|
|
11
|
-
guilds?: Snowflake[]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class ApplicationCommandExtension extends Extension {
|
|
15
|
-
constructor(public config: ApplicationCommandExtensionConfig) {
|
|
16
|
-
super()
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@listener({ event: 'interactionCreate' })
|
|
20
|
-
async interactionCreate(i: Interaction) {
|
|
21
|
-
console.log(i)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@moduleHook('load')
|
|
25
|
-
async load() {}
|
|
26
|
-
|
|
27
|
-
async sync() {
|
|
28
|
-
const client = CommandClient.getFromModule(this)
|
|
29
|
-
|
|
30
|
-
this.logger.info('Trying to sync commands...')
|
|
31
|
-
|
|
32
|
-
const commands: ApplicationCommandData[] = []
|
|
33
|
-
|
|
34
|
-
for (const command of client.registry.getComponentsWithTypeGlobal(ApplicationCommandComponent)) {
|
|
35
|
-
const cmd: ApplicationCommandData = { ...command.options }
|
|
36
|
-
|
|
37
|
-
if (cmd.type === ApplicationCommandType.ChatInput) {
|
|
38
|
-
cmd.options = []
|
|
39
|
-
|
|
40
|
-
for (const [, arg] of command.argTypes) {
|
|
41
|
-
const option = arg.decorators.find((x) => x.constructor === ApplicationCommandOption) as ApplicationCommandOption
|
|
42
|
-
|
|
43
|
-
if (option) {
|
|
44
|
-
cmd.options.push(option.options)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
commands.push(cmd)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.logger.info(`Processing ${chalk.green(commands.length)} commands(${commands.map((x) => chalk.blue(x.name)).join(', ')})`)
|
|
53
|
-
|
|
54
|
-
if (this.config.guilds) {
|
|
55
|
-
for (const guild of this.config.guilds) {
|
|
56
|
-
try {
|
|
57
|
-
const g = await this.client.guilds.fetch(guild)
|
|
58
|
-
await g.fetch()
|
|
59
|
-
this.logger.info(`Registering commands for guild ${chalk.green(g.name)}(${chalk.blue(g.id)})`)
|
|
60
|
-
|
|
61
|
-
await g.commands.set(commands)
|
|
62
|
-
|
|
63
|
-
this.logger.info(`Successfully registered commands for guild ${chalk.green(g.name)}(${chalk.blue(g.id)})`)
|
|
64
|
-
} catch (e) {
|
|
65
|
-
this.logger.error(`Failed to register commands to guild ${chalk.green(guild)}: ${(e as Error).message}`)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
try {
|
|
70
|
-
this.logger.info(`Registering commands globally...`)
|
|
71
|
-
|
|
72
|
-
await this.client.application!.commands.set(commands)
|
|
73
|
-
|
|
74
|
-
this.logger.info('Successfully registered commands.')
|
|
75
|
-
} catch (e) {
|
|
76
|
-
this.logger.error(`Failed to register commands to global: ${(e as Error).message}`)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|