zumito-framework 1.2.17 → 1.2.19
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/dist/ZumitoFramework.d.ts +1 -1
- package/dist/ZumitoFramework.js +3 -1
- package/dist/definitions/ErrorType.d.ts +2 -1
- package/dist/definitions/ErrorType.js +1 -0
- package/dist/definitions/FrameworkSettings.d.ts +4 -19
- package/dist/definitions/commands/Command.d.ts +8 -12
- package/dist/definitions/commands/Command.js +9 -4
- package/dist/definitions/commands/CommandBinds.d.ts +6 -0
- package/dist/definitions/commands/CommandBinds.js +1 -0
- package/dist/definitions/commands/CommandParameters.d.ts +10 -3
- package/dist/definitions/parameters/EventParameters.d.ts +6 -0
- package/dist/definitions/parameters/ModalSubmitParameters.d.ts +10 -0
- package/dist/definitions/parameters/ModalSubmitParameters.js +1 -0
- package/dist/definitions/parameters/SelectMenuParameters.d.ts +6 -0
- package/dist/definitions/settings/FrameworkSettings.d.ts +24 -0
- package/dist/definitions/settings/FrameworkSettings.js +1 -0
- package/dist/definitions/settings/InteractionHandlerSettings.d.ts +3 -0
- package/dist/definitions/settings/InteractionHandlerSettings.js +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -1
- package/dist/modules/core/baseModule/events/discord/InteractionCreate.d.ts +4 -3
- package/dist/modules/core/baseModule/events/discord/InteractionCreate.js +8 -122
- package/dist/modules/core/baseModule/events/discord/MessageCreate.d.ts +7 -0
- package/dist/modules/core/baseModule/events/discord/MessageCreate.js +35 -36
- package/dist/services/CommandManager.js +16 -9
- package/dist/services/CommandParser.d.ts +7 -0
- package/dist/services/CommandParser.js +32 -0
- package/dist/services/ErrorHandler.d.ts +2 -1
- package/dist/services/ErrorHandler.js +69 -7
- package/dist/services/InteractionHandler.d.ts +21 -0
- package/dist/services/InteractionHandler.js +212 -0
- package/dist/services/ServiceContainer.d.ts +9 -1
- package/dist/services/ServiceContainer.js +14 -2
- package/dist/services/SlashCommandRefresher.d.ts +4 -1
- package/dist/services/SlashCommandRefresher.js +67 -50
- package/dist/services/TranslationManager.d.ts +1 -0
- package/dist/services/TranslationManager.js +12 -0
- package/package.json +6 -1
|
@@ -36,4 +36,36 @@ export class CommandParser {
|
|
|
36
36
|
});
|
|
37
37
|
return paramArray;
|
|
38
38
|
}
|
|
39
|
+
static async parseFromSplitedString(args, argDefinitions, guild) {
|
|
40
|
+
const parsedArgs = new Map();
|
|
41
|
+
const errors = [];
|
|
42
|
+
for (let i = 0; i < args.length; i++) {
|
|
43
|
+
const arg = args[i];
|
|
44
|
+
const type = argDefinitions[i]?.type;
|
|
45
|
+
if (type) {
|
|
46
|
+
if (type == 'member' || type == 'user') {
|
|
47
|
+
const member = await guild.members.cache.get(arg.replace(/[<@!>]/g, ''));
|
|
48
|
+
if (member) {
|
|
49
|
+
if (type == 'user') {
|
|
50
|
+
parsedArgs.set(argDefinitions[i].name, member.user);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
parsedArgs.set(argDefinitions[i].name, member);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
errors.push('Invalid user.');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (type == 'string') {
|
|
61
|
+
parsedArgs.set(argDefinitions[i]?.name || i.toString(), arg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
validated: errors.length == 0,
|
|
67
|
+
errors,
|
|
68
|
+
parsedArgs,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
39
71
|
}
|
|
@@ -12,8 +12,9 @@ declare type CommandErrorOptions = BaseErrorOptions & {
|
|
|
12
12
|
export declare class ErrorHandler {
|
|
13
13
|
framework: ZumitoFramework;
|
|
14
14
|
constructor(framework: ZumitoFramework);
|
|
15
|
-
handleError(error:
|
|
15
|
+
handleError(error: any, options: BaseErrorOptions | CommandErrorOptions): void;
|
|
16
16
|
handleCommandError(error: Error, options: CommandErrorOptions): void;
|
|
17
|
+
handleShapeShiftErrors(error: any): void;
|
|
17
18
|
printErrorStack(error: Error): void;
|
|
18
19
|
}
|
|
19
20
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ErrorStackParser from "error-stack-parser";
|
|
2
2
|
import { ErrorType } from "../definitions/ErrorType";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import sf from 'source-fragment';
|
|
4
5
|
export class ErrorHandler {
|
|
5
6
|
framework;
|
|
6
7
|
constructor(framework) {
|
|
@@ -10,8 +11,20 @@ export class ErrorHandler {
|
|
|
10
11
|
if (options?.type == ErrorType.CommandInstance || options?.type == ErrorType.CommandLoad || options?.type == ErrorType.CommandRun) {
|
|
11
12
|
this.handleCommandError(error, options);
|
|
12
13
|
}
|
|
14
|
+
else if (error.constructor.name == 'CombinedError') {
|
|
15
|
+
this.handleShapeShiftErrors(error);
|
|
16
|
+
}
|
|
17
|
+
else if (error.constructor?.name == "ExpectedValidationError") {
|
|
18
|
+
console.error(`Validation error: Expected ${error.expected}, but received ${error.given}.`);
|
|
19
|
+
console.line('');
|
|
20
|
+
}
|
|
21
|
+
else if (error.constructor.name == "ValidationError") {
|
|
22
|
+
console.error(`Validation error: ${error.validator} received invalid input: ${error.given}`);
|
|
23
|
+
console.line('');
|
|
24
|
+
}
|
|
13
25
|
else {
|
|
14
26
|
console.error(error.toString());
|
|
27
|
+
console.line('');
|
|
15
28
|
}
|
|
16
29
|
this.printErrorStack(error);
|
|
17
30
|
if (options.exit)
|
|
@@ -20,7 +33,7 @@ export class ErrorHandler {
|
|
|
20
33
|
handleCommandError(error, options) {
|
|
21
34
|
switch (options.type) {
|
|
22
35
|
case ErrorType.CommandInstance:
|
|
23
|
-
console.group(`[❌] Error instanciating command ${options
|
|
36
|
+
console.group(`[❌] Error instanciating command ${options?.command?.name}`);
|
|
24
37
|
break;
|
|
25
38
|
case ErrorType.CommandLoad:
|
|
26
39
|
console.group(`[❌] Error loading command ${options.command.name}`);
|
|
@@ -29,21 +42,70 @@ export class ErrorHandler {
|
|
|
29
42
|
console.group(`[❌] Error running command ${options.command.name}`);
|
|
30
43
|
break;
|
|
31
44
|
}
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
if (error.constructor.name == 'CombinedError') {
|
|
46
|
+
console.groupEnd();
|
|
47
|
+
this.handleShapeShiftErrors(error);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.line(chalk.red('Error:'));
|
|
51
|
+
console.line(error.toString());
|
|
52
|
+
console.line('');
|
|
53
|
+
console.groupEnd();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
handleShapeShiftErrors(error) {
|
|
57
|
+
if (error.constructor.name == 'CombinedError') {
|
|
58
|
+
error.errors.forEach(err => {
|
|
59
|
+
this.handleError(err, {
|
|
60
|
+
type: ErrorType.Other
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
34
64
|
}
|
|
35
65
|
printErrorStack(error) {
|
|
36
66
|
const stackParsedError = ErrorStackParser.parse(error);
|
|
37
67
|
let functionColor = 'blue';
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
68
|
+
const lines = [];
|
|
69
|
+
let codeFragment;
|
|
70
|
+
let lastStack;
|
|
71
|
+
for (const stack of stackParsedError) {
|
|
72
|
+
const filePath = stack.getFileName().replace(process.cwd(), '.').replace('file://', '');
|
|
73
|
+
const functionName = stack.getFunctionName();
|
|
41
74
|
if (functionName == 'CommandManager.loadCommandFile') {
|
|
42
75
|
functionColor = 'yellow';
|
|
43
76
|
}
|
|
44
|
-
|
|
77
|
+
lines.push(` at ${chalk.gray(filePath)}:${stack.getLineNumber()}:${stack.getColumnNumber()} ${chalk[functionColor](functionName)}`);
|
|
45
78
|
if (functionName == 'CommandManager.loadCommandFile' && !this.framework.settings.debug)
|
|
46
79
|
break;
|
|
80
|
+
if (!codeFragment && functionName.includes('.execute')) {
|
|
81
|
+
let columnEnd = -1;
|
|
82
|
+
if (lastStack) {
|
|
83
|
+
if (lastStack.getFunctionName().contains('.')) {
|
|
84
|
+
columnEnd = lastStack.getFunctionName().split('.').at(-1).length;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
columnEnd = lastStack.getFunctionName().length;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
codeFragment = {
|
|
91
|
+
path: `${filePath}:${stack.getLineNumber()}:${stack.getColumnNumber()}`,
|
|
92
|
+
code: sf(`${filePath}:${stack.getLineNumber()}:${stack.getColumnNumber()}:${stack.getLineNumber()}:${stack.getColumnNumber() + columnEnd}`, {
|
|
93
|
+
format: 'tty',
|
|
94
|
+
linesBefore: 2,
|
|
95
|
+
linesAfter: 2,
|
|
96
|
+
})
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
lastStack = stack;
|
|
100
|
+
}
|
|
101
|
+
// Log code fragment
|
|
102
|
+
if (codeFragment) {
|
|
103
|
+
console.line(chalk.blue('File: ') + `${codeFragment.path}`);
|
|
104
|
+
console.line(codeFragment.code);
|
|
105
|
+
console.line('');
|
|
47
106
|
}
|
|
107
|
+
// Log stack
|
|
108
|
+
console.line(chalk.blue('StackTrace:'));
|
|
109
|
+
lines.forEach(line => console.line(line));
|
|
48
110
|
}
|
|
49
111
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ButtonInteraction, Client, CommandInteraction, Interaction, ModalSubmitInteraction, StringSelectMenuInteraction } from "discord.js";
|
|
2
|
+
import { CommandManager } from "./CommandManager";
|
|
3
|
+
import { GuildDataGetter } from "./GuildDataGetter";
|
|
4
|
+
import { TranslationManager } from "./TranslationManager";
|
|
5
|
+
import { EventManager } from "./EventManager";
|
|
6
|
+
import { InteractionHandlerSettings } from "@definitions/settings/InteractionHandlerSettings";
|
|
7
|
+
import { ErrorHandler } from "./ErrorHandler";
|
|
8
|
+
export declare class InteractionHandler {
|
|
9
|
+
protected commandManager: CommandManager;
|
|
10
|
+
protected guildDataGetter: GuildDataGetter;
|
|
11
|
+
protected client: Client;
|
|
12
|
+
protected translationManager: TranslationManager;
|
|
13
|
+
protected eventManager: EventManager;
|
|
14
|
+
protected errorHandler: ErrorHandler;
|
|
15
|
+
constructor();
|
|
16
|
+
handleInteraction(interaction: Interaction, params?: InteractionHandlerSettings): Promise<void>;
|
|
17
|
+
handleCommandInteraction(interaction: CommandInteraction, guildSettings?: any): Promise<void>;
|
|
18
|
+
handleButtonInteraction(interaction: ButtonInteraction, guildSettings?: any): Promise<void>;
|
|
19
|
+
handleSelectMenu(interaction: StringSelectMenuInteraction, guildSettings?: any): Promise<void>;
|
|
20
|
+
handleModalInteraction(interaction: ModalSubmitInteraction, guildSettings?: any): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Client } from "discord.js";
|
|
2
|
+
import { CommandManager } from "./CommandManager";
|
|
3
|
+
import { GuildDataGetter } from "./GuildDataGetter";
|
|
4
|
+
import { ServiceContainer } from "./ServiceContainer";
|
|
5
|
+
import { CommandType } from "../definitions/commands/CommandType";
|
|
6
|
+
import { ZumitoFramework } from "../ZumitoFramework";
|
|
7
|
+
import { TranslationManager } from "./TranslationManager";
|
|
8
|
+
import { EventManager } from "./EventManager";
|
|
9
|
+
import { ErrorHandler } from "./ErrorHandler";
|
|
10
|
+
import { ErrorType } from "../definitions/ErrorType";
|
|
11
|
+
export class InteractionHandler {
|
|
12
|
+
commandManager;
|
|
13
|
+
guildDataGetter;
|
|
14
|
+
client;
|
|
15
|
+
translationManager;
|
|
16
|
+
eventManager;
|
|
17
|
+
errorHandler;
|
|
18
|
+
constructor() {
|
|
19
|
+
this.commandManager = ServiceContainer.getService(CommandManager);
|
|
20
|
+
this.guildDataGetter = ServiceContainer.getService(GuildDataGetter);
|
|
21
|
+
this.client = ServiceContainer.getService(Client);
|
|
22
|
+
this.translationManager = ServiceContainer.getService(TranslationManager);
|
|
23
|
+
this.eventManager = ServiceContainer.getService(EventManager);
|
|
24
|
+
this.errorHandler = ServiceContainer.getService(ErrorHandler);
|
|
25
|
+
}
|
|
26
|
+
async handleInteraction(interaction, params) {
|
|
27
|
+
if (interaction.isCommand()) {
|
|
28
|
+
if (params?.disabledHandlers?.includes("command"))
|
|
29
|
+
return;
|
|
30
|
+
await this.handleCommandInteraction(interaction);
|
|
31
|
+
}
|
|
32
|
+
else if (interaction.isButton()) {
|
|
33
|
+
if (params?.disabledHandlers?.includes("button"))
|
|
34
|
+
return;
|
|
35
|
+
await this.handleButtonInteraction(interaction);
|
|
36
|
+
}
|
|
37
|
+
else if (interaction.isStringSelectMenu()) {
|
|
38
|
+
if (params?.disabledHandlers?.includes("selectMenu"))
|
|
39
|
+
return;
|
|
40
|
+
await this.handleSelectMenu(interaction);
|
|
41
|
+
}
|
|
42
|
+
else if (interaction.isModalSubmit()) {
|
|
43
|
+
if (params?.disabledHandlers?.includes("modal"))
|
|
44
|
+
return;
|
|
45
|
+
await this.handleModalInteraction(interaction);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async handleCommandInteraction(interaction, guildSettings) {
|
|
49
|
+
const subcommandName = interaction.options.getSubcommand(false);
|
|
50
|
+
const commandName = interaction.commandName;
|
|
51
|
+
let commandInstance;
|
|
52
|
+
if (subcommandName) {
|
|
53
|
+
commandInstance = Array.from(this.commandManager.getAll().values()).find(c => c.name == subcommandName && c.parent == commandName);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
commandInstance = this.commandManager.get(commandName);
|
|
57
|
+
}
|
|
58
|
+
if (!commandInstance)
|
|
59
|
+
return;
|
|
60
|
+
const framework = ServiceContainer.getService(ZumitoFramework);
|
|
61
|
+
const args = new Map();
|
|
62
|
+
commandInstance.args.forEach((arg) => {
|
|
63
|
+
const option = (interaction).options.get(arg.name);
|
|
64
|
+
if (option) {
|
|
65
|
+
switch (arg.type) {
|
|
66
|
+
case 'user':
|
|
67
|
+
args.set(arg.name, option.user);
|
|
68
|
+
break;
|
|
69
|
+
case 'member':
|
|
70
|
+
args.set(arg.name, option.member);
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
args.set(arg.name, option.value ||
|
|
74
|
+
option.user ||
|
|
75
|
+
option.role ||
|
|
76
|
+
option.channel ||
|
|
77
|
+
option.options ||
|
|
78
|
+
option.message ||
|
|
79
|
+
option.member ||
|
|
80
|
+
option.focused ||
|
|
81
|
+
option.autocomplete ||
|
|
82
|
+
option.attachment);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
if (![CommandType.any, CommandType.separated, CommandType.slash,].includes(commandInstance.type))
|
|
88
|
+
return;
|
|
89
|
+
if (!guildSettings && interaction.guildId) {
|
|
90
|
+
guildSettings = await ServiceContainer.getService(GuildDataGetter).getGuildSettings(interaction.guildId);
|
|
91
|
+
}
|
|
92
|
+
const trans = this.translationManager.getShortHandMethod('command.' + commandInstance.name, guildSettings?.lang);
|
|
93
|
+
if (commandInstance.type === CommandType.separated ||
|
|
94
|
+
commandInstance.type === CommandType.slash) {
|
|
95
|
+
await commandInstance.executeSlashCommand({
|
|
96
|
+
client: this.client,
|
|
97
|
+
interaction, args, framework, guildSettings, trans,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
try {
|
|
102
|
+
await commandInstance.execute({
|
|
103
|
+
client: this.client,
|
|
104
|
+
interaction, args, framework, guildSettings, trans,
|
|
105
|
+
}).catch((error) => {
|
|
106
|
+
this.errorHandler.handleError(error, {
|
|
107
|
+
command: commandInstance,
|
|
108
|
+
type: ErrorType.CommandRun,
|
|
109
|
+
});
|
|
110
|
+
interaction.reply({
|
|
111
|
+
content: "An error ocurred while running this command.",
|
|
112
|
+
ephemeral: true
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.errorHandler.handleError(error, {
|
|
118
|
+
command: commandInstance,
|
|
119
|
+
type: ErrorType.CommandRun,
|
|
120
|
+
});
|
|
121
|
+
interaction.reply({
|
|
122
|
+
content: "An error ocurred while running this command.",
|
|
123
|
+
ephemeral: true,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async handleButtonInteraction(interaction, guildSettings) {
|
|
129
|
+
const framework = ServiceContainer.getService(ZumitoFramework);
|
|
130
|
+
const path = interaction.customId.split('.');
|
|
131
|
+
const commandInstance = this.commandManager.get(path[0]);
|
|
132
|
+
if (!commandInstance)
|
|
133
|
+
throw new Error(`Command ${path[0]} not found or button id bad formatted`);
|
|
134
|
+
if (!guildSettings && interaction.guildId) {
|
|
135
|
+
guildSettings = await ServiceContainer.getService(GuildDataGetter).getGuildSettings(interaction.guildId);
|
|
136
|
+
}
|
|
137
|
+
// If the command has impements ButtonPress class then execute the method
|
|
138
|
+
if (commandInstance.constructor.prototype.hasOwnProperty('buttonPressed')) {
|
|
139
|
+
commandInstance.buttonPressed({
|
|
140
|
+
client: this.client,
|
|
141
|
+
path,
|
|
142
|
+
interaction,
|
|
143
|
+
framework,
|
|
144
|
+
guildSettings,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async handleSelectMenu(interaction, guildSettings) {
|
|
149
|
+
const path = interaction.customId.split('.');
|
|
150
|
+
const commandInstance = this.commandManager.get(path[0]);
|
|
151
|
+
if (!commandInstance)
|
|
152
|
+
throw new Error(`Command ${path[0]} not found or select menu id bad formatted`);
|
|
153
|
+
if (!guildSettings && interaction.guildId) {
|
|
154
|
+
guildSettings = await ServiceContainer.getService(GuildDataGetter).getGuildSettings(interaction.guildId);
|
|
155
|
+
}
|
|
156
|
+
const trans = this.translationManager.getShortHandMethod('command.' + commandInstance.name, guildSettings?.lang);
|
|
157
|
+
const framework = ServiceContainer.getService(ZumitoFramework);
|
|
158
|
+
if (commandInstance.binds?.selectMenu) {
|
|
159
|
+
commandInstance.binds?.selectMenu({
|
|
160
|
+
path,
|
|
161
|
+
interaction,
|
|
162
|
+
client: this.client,
|
|
163
|
+
framework,
|
|
164
|
+
guildSettings,
|
|
165
|
+
trans,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else if ( // Deprecated
|
|
169
|
+
commandInstance.constructor.prototype.hasOwnProperty('selectMenu')) {
|
|
170
|
+
commandInstance.selectMenu({
|
|
171
|
+
path,
|
|
172
|
+
interaction,
|
|
173
|
+
client: this.client,
|
|
174
|
+
framework,
|
|
175
|
+
guildSettings,
|
|
176
|
+
trans,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async handleModalInteraction(interaction, guildSettings) {
|
|
181
|
+
const path = interaction.customId.split('.');
|
|
182
|
+
const commandInstance = this.commandManager.get(path[0]);
|
|
183
|
+
if (!commandInstance) {
|
|
184
|
+
throw new Error(`Command ${path[0]} not found or modal id bad formatted`);
|
|
185
|
+
}
|
|
186
|
+
const framework = ServiceContainer.getService(ZumitoFramework);
|
|
187
|
+
if (commandInstance.binds?.modalSubmit) {
|
|
188
|
+
const trans = this.translationManager.getShortHandMethod('command.' + commandInstance.name, guildSettings?.lang);
|
|
189
|
+
commandInstance.binds.modalSubmit({
|
|
190
|
+
interaction,
|
|
191
|
+
path,
|
|
192
|
+
trans,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else if (commandInstance.modalSubmit) {
|
|
196
|
+
if (!guildSettings && interaction.guildId) {
|
|
197
|
+
guildSettings = await ServiceContainer.getService(GuildDataGetter).getGuildSettings(interaction.guildId);
|
|
198
|
+
}
|
|
199
|
+
commandInstance.modalSubmit({
|
|
200
|
+
client: this.client,
|
|
201
|
+
path,
|
|
202
|
+
interaction,
|
|
203
|
+
framework,
|
|
204
|
+
guildSettings,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
this.eventManager.emitEvent('modalSubmit', 'framework', {
|
|
208
|
+
client: this.client,
|
|
209
|
+
path, interaction, framework, guildSettings,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
declare class ServiceContainerManager {
|
|
2
|
+
private services;
|
|
3
|
+
addService(serviceClass: any, dependencies: string[], singleton?: boolean, instance?: any): void;
|
|
4
|
+
getService<T>(serviceClass: new (...args: any[]) => T | string): T;
|
|
5
|
+
getServiceByName<T>(serviceName: string): T;
|
|
6
|
+
addInstance(serviceClass: any, instance: any): void;
|
|
7
|
+
}
|
|
8
|
+
export declare const ServiceContainer: ServiceContainerManager;
|
|
9
|
+
export {};
|
|
@@ -9,13 +9,25 @@ class ServiceContainerManager {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
getService(serviceClass) {
|
|
12
|
-
const serviceName = typeof serviceClass
|
|
12
|
+
const serviceName = typeof serviceClass === 'string' ? serviceClass : serviceClass.name;
|
|
13
|
+
const service = this.services.get(serviceName);
|
|
14
|
+
if (!service)
|
|
15
|
+
throw new Error(`Service ${serviceName} not found`);
|
|
16
|
+
if (service.singleton && service.instance)
|
|
17
|
+
return service.instance;
|
|
18
|
+
const dependencies = service.dependencies.map(dependency => this.getServiceByName(dependency));
|
|
19
|
+
const instance = new service.class(...dependencies);
|
|
20
|
+
if (service.singleton)
|
|
21
|
+
service.instance = instance;
|
|
22
|
+
return instance;
|
|
23
|
+
}
|
|
24
|
+
getServiceByName(serviceName) {
|
|
13
25
|
const service = this.services.get(serviceName);
|
|
14
26
|
if (!service)
|
|
15
27
|
throw new Error(`Service ${serviceName} not found`);
|
|
16
28
|
if (service.singleton && service.instance)
|
|
17
29
|
return service.instance;
|
|
18
|
-
const dependencies = service.dependencies.map(dependency => this.
|
|
30
|
+
const dependencies = service.dependencies.map(dependency => this.getServiceByName(dependency));
|
|
19
31
|
const instance = new service.class(...dependencies);
|
|
20
32
|
if (service.singleton)
|
|
21
33
|
service.instance = instance;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ZumitoFramework } from "../ZumitoFramework";
|
|
2
|
+
import { Command } from "../definitions/commands/Command";
|
|
3
|
+
import { SlashCommandSubcommandBuilder } from "discord.js";
|
|
2
4
|
export declare class SlashCommandRefresher {
|
|
3
|
-
framework: ZumitoFramework;
|
|
5
|
+
protected framework: ZumitoFramework;
|
|
4
6
|
constructor(framework: ZumitoFramework);
|
|
5
7
|
refreshSlashCommands(): Promise<void>;
|
|
8
|
+
mapCommand(command: Command, commandBuilder?: SlashCommandSubcommandBuilder): import("discord.js").RESTPostAPIChatInputApplicationCommandsJSONBody | import("discord.js").APIApplicationCommandSubcommandOption;
|
|
6
9
|
}
|
|
@@ -13,61 +13,78 @@ export class SlashCommandRefresher {
|
|
|
13
13
|
async refreshSlashCommands() {
|
|
14
14
|
const rest = new REST({ version: '10' }).setToken(this.framework.settings.discordClientOptions.token);
|
|
15
15
|
const commands = Array.from(this.framework.commands.getAll().values())
|
|
16
|
-
.filter((command) => command.type == CommandType.slash ||
|
|
16
|
+
.filter((command) => (command.type == CommandType.slash ||
|
|
17
17
|
command.type == CommandType.separated ||
|
|
18
18
|
command.type == CommandType.any)
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
19
|
+
&& !command.parent)
|
|
20
|
+
.map(command => this.mapCommand(command));
|
|
21
|
+
const data = await rest.put(Routes.applicationCommands(this.framework.settings.discordClientOptions.clientId), { body: commands });
|
|
22
|
+
console.debug(`Successfully reloaded ${data.length} of ${commands.length} application (/) commands.`);
|
|
23
|
+
}
|
|
24
|
+
mapCommand(command, commandBuilder) {
|
|
25
|
+
const slashCommand = commandBuilder || new SlashCommandBuilder();
|
|
26
|
+
slashCommand
|
|
27
|
+
.setName(command.name)
|
|
28
|
+
.setDescription(this.framework.translations.get('command.' + command.name + '.description', 'en'));
|
|
29
|
+
if (command.args) {
|
|
30
|
+
command.args.forEach((arg) => {
|
|
31
|
+
let method;
|
|
32
|
+
switch (arg.type) {
|
|
33
|
+
case 'string':
|
|
34
|
+
method = 'addStringOption';
|
|
35
|
+
break;
|
|
36
|
+
case 'user':
|
|
37
|
+
case 'member':
|
|
38
|
+
method = 'addUserOption';
|
|
39
|
+
break;
|
|
40
|
+
case 'channel':
|
|
41
|
+
method = 'addChannelOption';
|
|
42
|
+
break;
|
|
43
|
+
case 'role':
|
|
44
|
+
method = 'addRoleOption';
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
throw new Error('Invalid argument type ' + arg.type);
|
|
48
|
+
}
|
|
49
|
+
slashCommand[method]((option) => {
|
|
50
|
+
option.setName(arg.name);
|
|
51
|
+
option.setDescription(this.framework.translations.get('command.' +
|
|
52
|
+
command.name +
|
|
53
|
+
'.args.' +
|
|
54
|
+
arg.name +
|
|
55
|
+
'.description', 'en'));
|
|
56
|
+
option.setRequired(!arg.optional);
|
|
57
|
+
if (arg.choices) {
|
|
58
|
+
// if arg.choices is function, call it
|
|
59
|
+
if (typeof arg.choices == 'function') {
|
|
60
|
+
arg.choices =
|
|
61
|
+
arg.choices();
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
arg.choices.forEach((choice) => {
|
|
64
|
+
option.addChoices({
|
|
65
|
+
name: choice.name,
|
|
66
|
+
value: choice.value,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return option;
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
Array.from(this.framework.commands.getAll().values())
|
|
75
|
+
.filter((subcommand) => (subcommand.type == CommandType.slash ||
|
|
76
|
+
subcommand.type == CommandType.separated ||
|
|
77
|
+
subcommand.type == CommandType.any)
|
|
78
|
+
&& subcommand.parent
|
|
79
|
+
&& subcommand.parent == command.name)
|
|
80
|
+
.forEach(subcommand => {
|
|
81
|
+
if (!commandBuilder) {
|
|
82
|
+
slashCommand.addSubcommand((subcommandSlashBuilder) => {
|
|
83
|
+
this.mapCommand(subcommand, subcommandSlashBuilder);
|
|
84
|
+
return subcommandSlashBuilder;
|
|
66
85
|
});
|
|
67
86
|
}
|
|
68
|
-
return slashCommand.toJSON();
|
|
69
87
|
});
|
|
70
|
-
|
|
71
|
-
console.debug(`Successfully reloaded ${data.length} of ${commands.length} application (/) commands.`);
|
|
88
|
+
return slashCommand.toJSON();
|
|
72
89
|
}
|
|
73
90
|
}
|
|
@@ -31,4 +31,5 @@ export declare class TranslationManager {
|
|
|
31
31
|
*/
|
|
32
32
|
registerTranslationsFromFolder(folderPath: string, baseKey?: string, watch?: boolean): Promise<void>;
|
|
33
33
|
watchTranslationFolder(folderPath: string, baseKey: string): void;
|
|
34
|
+
getShortHandMethod(keyPrefix: string, language?: string): (key: string, params?: any, lang?: string) => string;
|
|
34
35
|
}
|
|
@@ -119,4 +119,16 @@ export class TranslationManager {
|
|
|
119
119
|
// TODO: Handle file removal
|
|
120
120
|
//.on('unlink', function(path) {console.log('File', path, 'has been removed');})
|
|
121
121
|
}
|
|
122
|
+
getShortHandMethod(keyPrefix, language) {
|
|
123
|
+
return (key, params, lang) => {
|
|
124
|
+
if (key.startsWith('$')) {
|
|
125
|
+
return this.get(key.replace('$', ''), lang || language, params);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
if (!keyPrefix.endsWith('.'))
|
|
129
|
+
keyPrefix += '.';
|
|
130
|
+
return this.get(keyPrefix + key, lang || language, params);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
122
134
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zumito-framework",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.19",
|
|
4
4
|
"description": "Discord.js bot framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"express": "^4.18.1",
|
|
34
34
|
"leven": "^4.0.0",
|
|
35
35
|
"mongoose": "^6.6.5",
|
|
36
|
+
"source-fragment": "^1.1.0",
|
|
36
37
|
"tingodb": "^0.6.1",
|
|
37
38
|
"tseep": "^1.2.2",
|
|
38
39
|
"zumito-db": "^1.0.0"
|
|
@@ -54,6 +55,10 @@
|
|
|
54
55
|
".": "./dist/index.js",
|
|
55
56
|
"./discord": "./dist/discord/index.js"
|
|
56
57
|
},
|
|
58
|
+
"_moduleAliases": {
|
|
59
|
+
"@definitions": "definitions",
|
|
60
|
+
"@services": "services"
|
|
61
|
+
},
|
|
57
62
|
"typesVersions": {
|
|
58
63
|
"*": {
|
|
59
64
|
".": [
|