@somehiddenkey/discord-command-utils 2.5.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/package.json +1 -1
- package/src/Configs/Fetchable.js +3 -3
- package/src/Configs/GlobalConfig/GlobalConfig.js +6 -6
- package/src/Configs/LocalConfig.js +49 -7
- package/src/Configs/SecretConfig.js +3 -14
- package/src/Interactions/Interaction.js +11 -2
- package/src/Interactions/InteractionContainer.js +48 -32
- package/src/Interactions/RestCommands.js +15 -0
- package/src/Utils/consola.js +25 -0
package/README.md
CHANGED
|
@@ -144,8 +144,32 @@ The same exists for:
|
|
|
144
144
|
- Selection menu : `OnSelectMenu`
|
|
145
145
|
- Message : `OnMessageCommand`
|
|
146
146
|
- Modal submission : `OnModal`
|
|
147
|
+
|
|
148
|
+
A slash command with a specific subcommand can be defined as follows:
|
|
149
|
+
```js
|
|
150
|
+
Interaction.OnSlashCommand(
|
|
151
|
+
{name: "ping", subcommand: "webping"},
|
|
152
|
+
InteractionScope.Main,
|
|
153
|
+
async (interaction) => await interaction.reply("pong")
|
|
154
|
+
);
|
|
155
|
+
```
|
|
156
|
+
### Callback arguments
|
|
157
|
+
#### Message arguments
|
|
158
|
+
Message commands start with a prefix, after which the proceeding arguments are the arguments. E.g. the message `!ping "google.com"` would trigger `async (interaction, website) => //...`
|
|
159
|
+
|
|
160
|
+
#### Interaction IDs
|
|
161
|
+
You can burry hidden information in the custom ID of a selection menu, button and modal submission by concatting them to them to the custom ID. The helper function `Interaction.makeCustomId()` exists for this. This is handy to e.g. hide session IDs as not to have to recompute them. Example:
|
|
162
|
+
```js
|
|
163
|
+
new ButtonBuilder().setCustomId(Interaction.makeCustomId("ping", session_id))
|
|
164
|
+
|
|
165
|
+
Interaction.OnButton(
|
|
166
|
+
"ping", InteractionScope.Main,
|
|
167
|
+
async (interaction, session_id) => await interaction.reply(`pong from ${session_id}`)
|
|
168
|
+
);
|
|
169
|
+
```
|
|
170
|
+
|
|
147
171
|
### Call Interaction
|
|
148
|
-
All interactions get stored in a so-called `InteractionContainer` that still needs to be called
|
|
172
|
+
All interactions get stored in a so-called `InteractionContainer` that still needs to be called. If someone goes wrong in an unexpected way, the interaction will be replied to with "something went wrong" and a consola error will be displayed. Optionally, you can provide an extra error handler as second argument to the interaction caller.
|
|
149
173
|
```js
|
|
150
174
|
const interactionContainer = new InteractionContainer(localConfig, globalConfig);
|
|
151
175
|
|
|
@@ -164,7 +188,7 @@ For slash commands to work, you need to register them to a bot. There are two ki
|
|
|
164
188
|
|
|
165
189
|
You can add a set of slash commands through the following abstraction:
|
|
166
190
|
```js
|
|
167
|
-
const rest = interactionContainer.Rest
|
|
191
|
+
const rest = await interactionContainer.Rest
|
|
168
192
|
.add([firstSlashCommand, secondSlashCommand], localConfig.guilds.tutor)
|
|
169
193
|
.add([firstSlashCommand, secondSlashCommand], localConfig.guilds.community)
|
|
170
194
|
.add([somePublicSlashCommand])
|
package/package.json
CHANGED
package/src/Configs/Fetchable.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @typedef {string} Snowflake
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import consola from 'consola';
|
|
6
5
|
import { Client } from 'discord.js';
|
|
6
|
+
import { consolaConfig } from '../Utils/consola.js';
|
|
7
7
|
|
|
8
8
|
export default class Fetchable {
|
|
9
9
|
/** @type {string[]} */
|
|
@@ -30,7 +30,7 @@ export default class Fetchable {
|
|
|
30
30
|
if (prop === "refreshFromBot") {
|
|
31
31
|
return async () => {
|
|
32
32
|
cachedObject = await fetcher(id);
|
|
33
|
-
|
|
33
|
+
consolaConfig.debug(`Fetched config object with ID ${id}`);
|
|
34
34
|
return cachedObject;
|
|
35
35
|
};
|
|
36
36
|
}
|
|
@@ -41,7 +41,7 @@ export default class Fetchable {
|
|
|
41
41
|
cachedObject = await fetcher(id);
|
|
42
42
|
if (!cachedObject)
|
|
43
43
|
throw new Error(`Cannot fetch config object for ID "${id}"`);
|
|
44
|
-
|
|
44
|
+
consolaConfig.debug(`Fetched config object with ID ${id}`);
|
|
45
45
|
}
|
|
46
46
|
return cachedObject;
|
|
47
47
|
};
|
|
@@ -23,7 +23,7 @@ import GuildStaff from './GlobalConfigStaff.js';
|
|
|
23
23
|
import { GuildBased } from '../NestedGlobalConfig.js';
|
|
24
24
|
import { Client } from 'discord.js';
|
|
25
25
|
import ConfigError from '../ConfigError.js';
|
|
26
|
-
import
|
|
26
|
+
import { consolaConfig } from '../../Utils/consola.js';
|
|
27
27
|
|
|
28
28
|
export default class GlobalConfig {
|
|
29
29
|
/** @type {GuildMain} */
|
|
@@ -47,7 +47,7 @@ export default class GlobalConfig {
|
|
|
47
47
|
const raw = fs.readFileSync(path, { encoding: 'utf8', flag: 'r' });
|
|
48
48
|
json = JSON.parse(raw);
|
|
49
49
|
const g = new GlobalConfig(json.guilds, bot);
|
|
50
|
-
|
|
50
|
+
consolaConfig.start(`Loaded GlobalConfig from path: ${path}`);
|
|
51
51
|
return g;
|
|
52
52
|
} catch (error) {
|
|
53
53
|
throw new ConfigError(`Failed to load GlobalConfig from path: ${path}`, error);
|
|
@@ -60,13 +60,13 @@ export default class GlobalConfig {
|
|
|
60
60
|
*/
|
|
61
61
|
get_scope(guild_id) {
|
|
62
62
|
switch(guild_id) {
|
|
63
|
-
case this.main:
|
|
63
|
+
case this.main.guild.id:
|
|
64
64
|
return InteractionScope.Main;
|
|
65
|
-
case this.community:
|
|
65
|
+
case this.community.guild.id:
|
|
66
66
|
return InteractionScope.Community;
|
|
67
|
-
case this.tutor:
|
|
67
|
+
case this.tutor.guild.id:
|
|
68
68
|
return InteractionScope.Tutor;
|
|
69
|
-
case this.staff:
|
|
69
|
+
case this.staff.guild.id:
|
|
70
70
|
return InteractionScope.Staff;
|
|
71
71
|
default:
|
|
72
72
|
return InteractionScope.OtherGuild;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import ConfigError from "./ConfigError.js";
|
|
3
|
-
import
|
|
3
|
+
import { consolaConfig } from '../Utils/consola.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {string} Snowflake
|
|
@@ -10,26 +10,29 @@ export default class LocalConfig {
|
|
|
10
10
|
/** @type {string?} */
|
|
11
11
|
prefix;
|
|
12
12
|
/** @type {Snowflake} */
|
|
13
|
-
|
|
13
|
+
#client_id;
|
|
14
14
|
|
|
15
15
|
/** @type {object} */
|
|
16
16
|
local;
|
|
17
17
|
/** @type {object} */
|
|
18
|
-
|
|
18
|
+
#rest_options;
|
|
19
19
|
/** @type {object} */
|
|
20
20
|
activity;
|
|
21
21
|
|
|
22
22
|
constructor(data) {
|
|
23
23
|
this.prefix = data.prefix;
|
|
24
|
-
this
|
|
24
|
+
this.#client_id = data.client_id;
|
|
25
25
|
this.local = data.local || {};
|
|
26
|
-
this
|
|
26
|
+
this.#rest_options = data.rest_options || {};
|
|
27
27
|
this.activity = data.activity || {};
|
|
28
28
|
|
|
29
|
-
if(!this
|
|
29
|
+
if(!this.#client_id)
|
|
30
30
|
throw new ConfigError('No client_id initialized for LocalConfig');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
get clientId() { return this.#client_id; }
|
|
34
|
+
get restOptions() { return this.#rest_options; }
|
|
35
|
+
|
|
33
36
|
/**
|
|
34
37
|
* Loads the JSON file and returns a GlobalConfig instance.
|
|
35
38
|
* @param {string} path
|
|
@@ -40,9 +43,48 @@ export default class LocalConfig {
|
|
|
40
43
|
try {
|
|
41
44
|
const raw = fs.readFileSync(path, { encoding: 'utf8', flag: 'r' });
|
|
42
45
|
json = JSON.parse(raw);
|
|
43
|
-
|
|
46
|
+
const localConfig =new LocalConfig(json);
|
|
47
|
+
localConfig.#reloadable(path, "localConfig");
|
|
48
|
+
consolaConfig.start(`Loaded LocalConfig from path: ${path}`);
|
|
49
|
+
return localConfig;
|
|
44
50
|
} catch (error) {
|
|
45
51
|
throw new ConfigError(`Failed to load LocalConfig from path: ${path}`, error);
|
|
46
52
|
}
|
|
47
53
|
}
|
|
54
|
+
|
|
55
|
+
#reloadable(filepath, root=""){
|
|
56
|
+
fs.watch(filepath, { encoding: 'utf8' }, (eventType, _) => {
|
|
57
|
+
if (eventType !== 'change') return;
|
|
58
|
+
fs.readFile(filepath, 'utf8', (err, data) => {
|
|
59
|
+
if (err)
|
|
60
|
+
return consolaConfig.error(err);
|
|
61
|
+
else
|
|
62
|
+
LocalConfig.#compareObjects(JSON.parse(data), this, root+".");
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static #compareObjects(data, currentObject, tree="") {
|
|
68
|
+
Object.entries(data).forEach(([key, newValue]) => {
|
|
69
|
+
const oldValue = currentObject[key]
|
|
70
|
+
const newValueIsObject = typeof newValue === 'object' && !Array.isArray(newValue) && newValue !== null
|
|
71
|
+
const oldValueIsObject = typeof oldValue === 'object' && !Array.isArray(oldValue) && oldValue !== null
|
|
72
|
+
|
|
73
|
+
if(newValueIsObject && oldValueIsObject)
|
|
74
|
+
LocalConfig.#compareObjects(newValue, oldValue, tree+"."+key);
|
|
75
|
+
else {
|
|
76
|
+
if(Array.isArray(newValue) || Array.isArray(oldValue)) {
|
|
77
|
+
const newValueString = JSON.stringify(newValue);
|
|
78
|
+
const oldValueString = JSON.stringify(oldValue);
|
|
79
|
+
if(newValueString != oldValueString) {
|
|
80
|
+
currentObject[key] = newValue
|
|
81
|
+
consolaConfig.warn(`Updated ${tree}${key}\n - Old: ${oldValueString}\n - New: ${newValueString}`);
|
|
82
|
+
}
|
|
83
|
+
} else if (newValue !== oldValue){
|
|
84
|
+
currentObject[key] = newValue
|
|
85
|
+
consolaConfig.warn(`Updated ${tree}${key}\n - Old: ${JSON.stringify(oldValue)}\n - New: ${JSON.stringify(newValue)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
48
90
|
}
|
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import consola from "consola";
|
|
2
1
|
import ConfigError from "./ConfigError.js";
|
|
2
|
+
import { consolaConfig } from "../Utils/consola.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {{client: string, connection: {host: string, user: string, password: string, database: string}}} DatabaseConfig
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const levels = {
|
|
9
|
-
silent: -1,
|
|
10
|
-
fatal: 0,
|
|
11
|
-
error: 1,
|
|
12
|
-
warn: 2,
|
|
13
|
-
info: 3,
|
|
14
|
-
debug: 4,
|
|
15
|
-
trace: 5,
|
|
16
|
-
};
|
|
17
|
-
consola.level = levels[process.env.LOG_LEVEL?.toLowerCase() || "info"] ?? 3;
|
|
18
|
-
|
|
19
8
|
export default class SecretConfig {
|
|
20
9
|
/** @type {string} */
|
|
21
10
|
token;
|
|
@@ -52,11 +41,11 @@ export default class SecretConfig {
|
|
|
52
41
|
|
|
53
42
|
databaseConfigs.push(db_config);
|
|
54
43
|
} catch (error) {
|
|
55
|
-
|
|
44
|
+
consolaConfig.error(`Failed to load database config for section: ${section}`, error);
|
|
56
45
|
throw error;
|
|
57
46
|
}
|
|
58
47
|
}
|
|
59
48
|
this.databaseConfig = databaseConfigs;
|
|
60
|
-
|
|
49
|
+
consolaConfig.start(`Loaded SecretConfig for environment: ${this.environment}`);
|
|
61
50
|
}
|
|
62
51
|
}
|
|
@@ -15,11 +15,11 @@ const {
|
|
|
15
15
|
/**
|
|
16
16
|
* @typedef { (interaction: DiscordBaseInteraction<CacheType>) => Promise<any> } InteractionFunction
|
|
17
17
|
* @typedef { (message: OmitPartialGroupDMChannel<Message<boolean>>) => Promise<any> } InteractionMsgFunction
|
|
18
|
-
* @typedef { string } InteractionID
|
|
18
|
+
* @typedef { {name: string, subcommand: string | null} | string } InteractionID
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
export default class Interaction {
|
|
22
|
-
/** @type {
|
|
22
|
+
/** @type {InteractionID} */
|
|
23
23
|
id;
|
|
24
24
|
/** @type {InteractionType} */
|
|
25
25
|
type;
|
|
@@ -94,4 +94,13 @@ export default class Interaction {
|
|
|
94
94
|
static OnModal(custom_id, scope, target) {
|
|
95
95
|
return Interaction.On(custom_id, InteractionType.Modal, scope, target)
|
|
96
96
|
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Hides arbitrary number of arguments in the custom ID
|
|
100
|
+
* @param {...any} args
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
103
|
+
static makeCustomId(...args) {
|
|
104
|
+
return args.map(arg => String(arg)).join("?");
|
|
105
|
+
}
|
|
97
106
|
}
|
|
@@ -2,25 +2,23 @@ import Interaction from "./Interaction.js";
|
|
|
2
2
|
import { InteractionScope, InteractionType } from "../Utils/enums.js";
|
|
3
3
|
import GlobalConfig from "../Configs/GlobalConfig/GlobalConfig.js";
|
|
4
4
|
import LocalConfig from "../Configs/LocalConfig.js";
|
|
5
|
-
import consola from "consola";
|
|
6
5
|
import CommandError from "./CommandError.js";
|
|
7
6
|
import RestCommands from './RestCommands.js';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
Interaction: DiscordBaseInteraction,
|
|
11
|
-
OmitPartialGroupDMChannel,
|
|
12
|
-
Message,
|
|
13
|
-
CacheType
|
|
14
|
-
} = pkg;
|
|
7
|
+
import { ChannelType } from 'discord.js';
|
|
8
|
+
import { consolaInteraction } from "../Utils/consola.js";
|
|
15
9
|
|
|
16
10
|
/**
|
|
11
|
+
* @typedef { import("discord.js").Interaction } DiscordBaseInteraction
|
|
12
|
+
* @typedef { import("discord.js").OmitPartialGroupDMChannel } OmitPartialGroupDMChannel
|
|
13
|
+
* @typedef { import("discord.js").Message } Message
|
|
14
|
+
* @typedef { import("discord.js").CacheType } CacheType
|
|
17
15
|
* @typedef { (interaction: DiscordBaseInteraction<CacheType>) => Promise<any> } InteractionFunction
|
|
18
16
|
* @typedef { (message: OmitPartialGroupDMChannel<Message<boolean>>) => Promise<any> } InteractionMsgFunction
|
|
19
|
-
* @typedef {
|
|
17
|
+
* @typedef { import("./Interaction.js").InteractionID } InteractionID
|
|
20
18
|
*/
|
|
21
19
|
|
|
22
20
|
export default class InteractionContainer {
|
|
23
|
-
/** @type {Map<
|
|
21
|
+
/** @type {Map<string, Interaction>} */
|
|
24
22
|
static #interaction_container = new Map();
|
|
25
23
|
|
|
26
24
|
/** @type {GlobalConfig} */
|
|
@@ -29,42 +27,55 @@ export default class InteractionContainer {
|
|
|
29
27
|
#local_config;
|
|
30
28
|
|
|
31
29
|
/** @type {RestCommands} */
|
|
32
|
-
Rest
|
|
30
|
+
Rest;
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
33
|
* @param {InteractionType} type
|
|
36
34
|
* @param {InteractionScope} scope
|
|
37
|
-
* @param {
|
|
38
|
-
* @returns {
|
|
35
|
+
* @param {InteractionID} id
|
|
36
|
+
* @returns {string} interction ID
|
|
39
37
|
*/
|
|
40
38
|
static #make_key(type, scope, id) {
|
|
41
|
-
return `${type}__${scope}__${id}`;
|
|
39
|
+
return `${type}__${scope}__${id.subcommand ? `${id.name}>${id.subcommand}` : (id.name || id)}`;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
/**
|
|
45
|
-
* @param {InteractionType} type
|
|
46
|
-
* @param {InteractionScope} scope
|
|
47
|
-
* @param {string} id
|
|
48
43
|
* @param {Interaction} base_interaction
|
|
49
44
|
*/
|
|
50
45
|
static add(base_interaction) {
|
|
51
46
|
const key = InteractionContainer.#make_key(base_interaction.type, base_interaction.scope, base_interaction.id);
|
|
47
|
+
consolaInteraction.debug(`Registered interaction with key ${key}`);
|
|
52
48
|
InteractionContainer.#interaction_container.set(key, base_interaction);
|
|
53
49
|
}
|
|
54
50
|
|
|
55
51
|
/**
|
|
56
52
|
* @param {InteractionType} type
|
|
57
53
|
* @param {InteractionScope} scope
|
|
58
|
-
* @param {
|
|
54
|
+
* @param {InteractionID} id
|
|
59
55
|
* @returns {Interaction?}
|
|
60
56
|
*/
|
|
61
57
|
static get(type, scope, id) {
|
|
62
|
-
|
|
58
|
+
const key = InteractionContainer.#make_key(type, scope, id);
|
|
59
|
+
consolaInteraction.debug(`Fetching interaction with key ${key}`);
|
|
60
|
+
return InteractionContainer.#interaction_container.get(key);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static dump() {
|
|
64
|
+
return Array.from(InteractionContainer.#interaction_container.entries()).map(([key, interaction]) => {
|
|
65
|
+
return {
|
|
66
|
+
key,
|
|
67
|
+
type: interaction.type,
|
|
68
|
+
scope: interaction.scope,
|
|
69
|
+
id: interaction.id,
|
|
70
|
+
function: interaction.interaction_command_function.name
|
|
71
|
+
}
|
|
72
|
+
});
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
constructor(local_config, global_config) {
|
|
66
76
|
this.#local_config = local_config;
|
|
67
77
|
this.#global_config = global_config;
|
|
78
|
+
this.Rest = new RestCommands(global_config, local_config);
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
/**
|
|
@@ -82,10 +93,10 @@ export default class InteractionContainer {
|
|
|
82
93
|
(interaction.channel.type === ChannelType.DM) ?
|
|
83
94
|
InteractionScope.DM : this.#global_config.get_scope(interaction.guild.id);
|
|
84
95
|
|
|
85
|
-
const customId = interaction.content.slice(this.#local_config.prefix?.length)
|
|
96
|
+
const [customId, ...command_arguments] = interaction.content.slice(this.#local_config.prefix?.length)?.split("?")
|
|
86
97
|
|
|
87
98
|
return InteractionContainer
|
|
88
|
-
.#call(InteractionType.Message, scope,
|
|
99
|
+
.#call(interaction, InteractionType.Message, scope, customId, command_arguments)
|
|
89
100
|
.catch(error => {
|
|
90
101
|
if (error instanceof CommandError)
|
|
91
102
|
return error.error_as_message(interaction)
|
|
@@ -107,8 +118,8 @@ export default class InteractionContainer {
|
|
|
107
118
|
const scope =
|
|
108
119
|
(interaction.channel.type === ChannelType.DM) ?
|
|
109
120
|
InteractionScope.DM : this.#global_config.get_scope(interaction.guild.id);
|
|
110
|
-
|
|
111
|
-
const customId = (interaction.commandName || interaction.customId)?.split(
|
|
121
|
+
|
|
122
|
+
const [customId, ...command_arguments] = (interaction.commandName || interaction.customId)?.split("?")
|
|
112
123
|
|
|
113
124
|
var type;
|
|
114
125
|
if (interaction.isChatInputCommand())
|
|
@@ -123,7 +134,7 @@ export default class InteractionContainer {
|
|
|
123
134
|
return;
|
|
124
135
|
|
|
125
136
|
return InteractionContainer
|
|
126
|
-
.#call(type, scope, customId, interaction)
|
|
137
|
+
.#call(interaction, type, scope, {name: customId, subcommand: interaction.options?.getSubcommand()}, command_arguments)
|
|
127
138
|
.catch(error => {
|
|
128
139
|
if (error instanceof CommandError)
|
|
129
140
|
return error.error_as_command(interaction)
|
|
@@ -131,25 +142,30 @@ export default class InteractionContainer {
|
|
|
131
142
|
return interaction
|
|
132
143
|
.editReply("something went wrong")
|
|
133
144
|
.catch(() => interaction.reply("something went wrong"))
|
|
134
|
-
.then(
|
|
135
|
-
|
|
145
|
+
.then(
|
|
146
|
+
() => {consolaInteraction.error(e); return on_error(error)},
|
|
147
|
+
() => {consolaInteraction.error(e); return on_error(error)}
|
|
148
|
+
)
|
|
149
|
+
.then()
|
|
150
|
+
.catch(consolaInteraction.error);
|
|
136
151
|
});
|
|
137
152
|
}
|
|
138
153
|
|
|
139
154
|
/**
|
|
140
155
|
*
|
|
156
|
+
* @param {DiscordBaseInteraction} interaction
|
|
141
157
|
* @param {InteractionType} type
|
|
142
158
|
* @param {InteractionScope} scope
|
|
143
|
-
* @param {InteractionID
|
|
144
|
-
* @param {
|
|
159
|
+
* @param {InteractionID} customId
|
|
160
|
+
* @param {string[]} command_arguments
|
|
145
161
|
* @returns {Promise<any>}
|
|
146
162
|
* @throws {CommandError}
|
|
147
163
|
*/
|
|
148
|
-
static async #call(type, scope, customId,
|
|
149
|
-
const interaction_command = InteractionContainer.get(type, scope, customId
|
|
164
|
+
static async #call(interaction, type, scope, customId, command_arguments = []) {
|
|
165
|
+
const interaction_command = InteractionContainer.get(type, scope, customId);
|
|
150
166
|
if(!interaction_command)
|
|
151
|
-
return
|
|
167
|
+
return consolaInteraction.error(`No interaction found:\n${JSON.stringify({customId, type, scope, command_arguments: command_arguments.join(',')}, null, 2)}`);
|
|
152
168
|
|
|
153
|
-
return await interaction_command.interaction_command_function.apply(null, [interaction, ...
|
|
169
|
+
return await interaction_command.interaction_command_function.apply(null, [interaction, ...command_arguments]);
|
|
154
170
|
}
|
|
155
171
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import GlobalConfig from "../Configs/GlobalConfig/GlobalConfig.js";
|
|
2
2
|
import LocalConfig from "../Configs/LocalConfig.js";
|
|
3
3
|
import { REST, Routes } from "discord.js";
|
|
4
|
+
import { InteractionScope } from "../Utils/enums.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import("discord.js").SlashCommandSubcommandsOnlyBuilder} SlashCommandSubcommandsOnlyBuilder
|
|
8
|
+
*/
|
|
4
9
|
|
|
5
10
|
export default class RestCommands {
|
|
6
11
|
#commands = new Map();
|
|
@@ -20,6 +25,12 @@ export default class RestCommands {
|
|
|
20
25
|
this.#local_config = local_config;
|
|
21
26
|
}
|
|
22
27
|
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param {SlashCommandSubcommandsOnlyBuilder[]} commands
|
|
31
|
+
* @param {InteractionScope} scope
|
|
32
|
+
* @returns {RestCommands}
|
|
33
|
+
*/
|
|
23
34
|
add(commands, scope) {
|
|
24
35
|
if(!!scope)
|
|
25
36
|
this.#commands.set(scope, commands);
|
|
@@ -29,6 +40,10 @@ export default class RestCommands {
|
|
|
29
40
|
return this;
|
|
30
41
|
}
|
|
31
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} secret_token
|
|
45
|
+
* @returns {Promise<REST>}
|
|
46
|
+
*/
|
|
32
47
|
async register(secret_token){
|
|
33
48
|
const rest = new REST(this.#local_config.restOptions).setToken(secret_token);
|
|
34
49
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createConsola } from "consola";
|
|
2
|
+
|
|
3
|
+
const levels = {
|
|
4
|
+
silent: -1,
|
|
5
|
+
fatal: 0,
|
|
6
|
+
error: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
info: 3,
|
|
9
|
+
debug: 4,
|
|
10
|
+
trace: 5,
|
|
11
|
+
};
|
|
12
|
+
const level = levels[process.env.LOG_LEVEL?.toLowerCase() || "info"] ?? 3;
|
|
13
|
+
|
|
14
|
+
const consolaInstance = createConsola({
|
|
15
|
+
level,
|
|
16
|
+
fancy: true,
|
|
17
|
+
formatOptions: {
|
|
18
|
+
date: true,
|
|
19
|
+
columns: 20
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const consolaConfig = consolaInstance.withTag("Config");
|
|
24
|
+
export const consolaInteraction = consolaInstance.withTag("Interaction");
|
|
25
|
+
export default consolaInstance;
|