@somehiddenkey/discord-command-utils 2.6.0 → 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 +1 -1
- package/package.json +1 -1
- package/src/Configs/Fetchable.js +3 -3
- package/src/Configs/GlobalConfig/GlobalConfig.js +2 -2
- package/src/Configs/LocalConfig.js +49 -7
- package/src/Configs/SecretConfig.js +3 -14
- package/src/Interactions/InteractionContainer.js +10 -9
- package/src/Utils/consola.js +25 -0
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ Interaction.OnButton(
|
|
|
169
169
|
```
|
|
170
170
|
|
|
171
171
|
### Call Interaction
|
|
172
|
-
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.
|
|
173
173
|
```js
|
|
174
174
|
const interactionContainer = new InteractionContainer(localConfig, globalConfig);
|
|
175
175
|
|
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);
|
|
@@ -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
|
}
|
|
@@ -2,10 +2,10 @@ 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
7
|
import { ChannelType } from 'discord.js';
|
|
8
|
+
import { consolaInteraction } from "../Utils/consola.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @typedef { import("discord.js").Interaction } DiscordBaseInteraction
|
|
@@ -44,7 +44,7 @@ export default class InteractionContainer {
|
|
|
44
44
|
*/
|
|
45
45
|
static add(base_interaction) {
|
|
46
46
|
const key = InteractionContainer.#make_key(base_interaction.type, base_interaction.scope, base_interaction.id);
|
|
47
|
-
|
|
47
|
+
consolaInteraction.debug(`Registered interaction with key ${key}`);
|
|
48
48
|
InteractionContainer.#interaction_container.set(key, base_interaction);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -56,7 +56,7 @@ export default class InteractionContainer {
|
|
|
56
56
|
*/
|
|
57
57
|
static get(type, scope, id) {
|
|
58
58
|
const key = InteractionContainer.#make_key(type, scope, id);
|
|
59
|
-
|
|
59
|
+
consolaInteraction.debug(`Fetching interaction with key ${key}`);
|
|
60
60
|
return InteractionContainer.#interaction_container.get(key);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -118,10 +118,8 @@ export default class InteractionContainer {
|
|
|
118
118
|
const scope =
|
|
119
119
|
(interaction.channel.type === ChannelType.DM) ?
|
|
120
120
|
InteractionScope.DM : this.#global_config.get_scope(interaction.guild.id);
|
|
121
|
-
console.log(scope)
|
|
122
121
|
|
|
123
122
|
const [customId, ...command_arguments] = (interaction.commandName || interaction.customId)?.split("?")
|
|
124
|
-
console.log(customId)
|
|
125
123
|
|
|
126
124
|
var type;
|
|
127
125
|
if (interaction.isChatInputCommand())
|
|
@@ -134,7 +132,6 @@ export default class InteractionContainer {
|
|
|
134
132
|
type = InteractionType.Modal;
|
|
135
133
|
else
|
|
136
134
|
return;
|
|
137
|
-
console.log(type)
|
|
138
135
|
|
|
139
136
|
return InteractionContainer
|
|
140
137
|
.#call(interaction, type, scope, {name: customId, subcommand: interaction.options?.getSubcommand()}, command_arguments)
|
|
@@ -145,8 +142,12 @@ export default class InteractionContainer {
|
|
|
145
142
|
return interaction
|
|
146
143
|
.editReply("something went wrong")
|
|
147
144
|
.catch(() => interaction.reply("something went wrong"))
|
|
148
|
-
.then(
|
|
149
|
-
|
|
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);
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
153
|
|
|
@@ -163,7 +164,7 @@ export default class InteractionContainer {
|
|
|
163
164
|
static async #call(interaction, type, scope, customId, command_arguments = []) {
|
|
164
165
|
const interaction_command = InteractionContainer.get(type, scope, customId);
|
|
165
166
|
if(!interaction_command)
|
|
166
|
-
return
|
|
167
|
+
return consolaInteraction.error(`No interaction found:\n${JSON.stringify({customId, type, scope, command_arguments: command_arguments.join(',')}, null, 2)}`);
|
|
167
168
|
|
|
168
169
|
return await interaction_command.interaction_command_function.apply(null, [interaction, ...command_arguments]);
|
|
169
170
|
}
|
|
@@ -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;
|