zumito-framework 1.1.33 → 1.1.34
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/TranslationManager.js +6 -1
- package/dist/ZumitoFramework.js +21 -9
- package/dist/baseModule/events/discord/messageCreate.d.ts +10 -0
- package/dist/baseModule/events/discord/messageCreate.js +124 -23
- package/dist/baseModule/index.d.ts +1 -1
- package/dist/baseModule/index.js +1 -1
- package/dist/types/Command.d.ts +2 -2
- package/dist/types/Command.js +1 -2
- package/dist/types/Commands.js +1 -1
- package/dist/types/Module.d.ts +2 -2
- package/dist/types/Module.js +61 -33
- package/dist/types/SelectMenuParameters.d.ts +2 -2
- package/package.json +7 -5
- package/plop-templates/command.js.hbs +9 -2
- package/plopfile.js +3 -0
|
@@ -4,7 +4,12 @@ export class TranslationManager {
|
|
|
4
4
|
defaultLanguage = 'en';
|
|
5
5
|
constructor() { }
|
|
6
6
|
get(key, language, params) {
|
|
7
|
-
|
|
7
|
+
if (this.translations.has(key)) {
|
|
8
|
+
return this.translations.get(key).get(language, params);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return key;
|
|
12
|
+
}
|
|
8
13
|
}
|
|
9
14
|
set(key, language, text) {
|
|
10
15
|
if (!this.translations.has(key)) {
|
package/dist/ZumitoFramework.js
CHANGED
|
@@ -13,6 +13,7 @@ import mongoose from "mongoose";
|
|
|
13
13
|
import cookieParser from 'cookie-parser';
|
|
14
14
|
import cors from 'cors';
|
|
15
15
|
import http from 'http';
|
|
16
|
+
import * as url from 'url';
|
|
16
17
|
/**
|
|
17
18
|
* @class ZumitoFramework
|
|
18
19
|
* @classdesc The main class of the framework.
|
|
@@ -28,7 +29,7 @@ export class ZumitoFramework {
|
|
|
28
29
|
modules;
|
|
29
30
|
commands;
|
|
30
31
|
events;
|
|
31
|
-
translations
|
|
32
|
+
translations;
|
|
32
33
|
routes;
|
|
33
34
|
models;
|
|
34
35
|
database;
|
|
@@ -54,9 +55,12 @@ export class ZumitoFramework {
|
|
|
54
55
|
this.events = new Map();
|
|
55
56
|
this.translations = new TranslationManager();
|
|
56
57
|
this.models = new Map();
|
|
58
|
+
if (settings.logLevel) {
|
|
59
|
+
console.logLevel = settings.logLevel;
|
|
60
|
+
}
|
|
57
61
|
this.initialize().then(() => {
|
|
58
62
|
if (callback)
|
|
59
|
-
callback();
|
|
63
|
+
callback(this);
|
|
60
64
|
}).catch(err => {
|
|
61
65
|
console.error(err, err.message, err.stack, err.name);
|
|
62
66
|
});
|
|
@@ -75,7 +79,7 @@ export class ZumitoFramework {
|
|
|
75
79
|
}
|
|
76
80
|
this.initializeDiscordClient();
|
|
77
81
|
this.startApiServer();
|
|
78
|
-
this.registerModules();
|
|
82
|
+
await this.registerModules();
|
|
79
83
|
}
|
|
80
84
|
startApiServer() {
|
|
81
85
|
this.app = express();
|
|
@@ -108,7 +112,7 @@ export class ZumitoFramework {
|
|
|
108
112
|
}
|
|
109
113
|
});
|
|
110
114
|
}
|
|
111
|
-
registerModules() {
|
|
115
|
+
async registerModules() {
|
|
112
116
|
let modulesFolder;
|
|
113
117
|
if (fs.existsSync(`${process.cwd()}/modules`)) {
|
|
114
118
|
modulesFolder = `${process.cwd()}/modules`;
|
|
@@ -118,10 +122,12 @@ export class ZumitoFramework {
|
|
|
118
122
|
}
|
|
119
123
|
else
|
|
120
124
|
return;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
126
|
+
await this.registerModule(__dirname, 'baseModule', baseModule);
|
|
127
|
+
let files = fs.readdirSync(modulesFolder);
|
|
128
|
+
for (let file of files) {
|
|
129
|
+
await this.registerModule(modulesFolder, file);
|
|
130
|
+
}
|
|
125
131
|
this.models.forEach((modelDefiniton, modelName) => {
|
|
126
132
|
const schema = new mongoose.Schema(modelDefiniton);
|
|
127
133
|
this.models.set(modelName, mongoose.model(modelName, schema));
|
|
@@ -147,12 +153,18 @@ export class ZumitoFramework {
|
|
|
147
153
|
try {
|
|
148
154
|
moduleInstance = new module(path.join(modulesFolder, moduleName), this);
|
|
149
155
|
await moduleInstance.initialize();
|
|
150
|
-
this.modules.set(moduleInstance.constructor.name, moduleInstance);
|
|
156
|
+
this.modules.set(moduleName || moduleInstance.constructor.name, moduleInstance);
|
|
151
157
|
}
|
|
152
158
|
catch (err) {
|
|
153
159
|
console.error(`[📦🔴] Error loading module ${moduleName}: ${err.message}`);
|
|
160
|
+
console.error(err.stack);
|
|
154
161
|
}
|
|
155
162
|
// Register module commands
|
|
163
|
+
if (moduleInstance.getCommands()) {
|
|
164
|
+
moduleInstance.getCommands().forEach((command) => {
|
|
165
|
+
this.commands.set(command.name, command);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
156
168
|
this.commands = new Map([...this.commands, ...moduleInstance.getCommands()]);
|
|
157
169
|
// Register module events
|
|
158
170
|
this.events = new Map([...this.events, ...moduleInstance.getEvents()]);
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import { ActionRowBuilder, EmbedBuilder } from "discord.js";
|
|
1
2
|
import { EventParameters } from "../../../types/EventParameters.js";
|
|
2
3
|
import { FrameworkEvent } from "../../../types/FrameworkEvent.js";
|
|
3
4
|
export declare class MessageCreate extends FrameworkEvent {
|
|
4
5
|
once: boolean;
|
|
5
6
|
execute({ message, client, framework }: EventParameters): Promise<import("discord.js").Message<boolean>>;
|
|
7
|
+
autocorrect(str: string, words: string[]): any;
|
|
8
|
+
getErrorEmbed(error: any, parse: any): {
|
|
9
|
+
embeds: EmbedBuilder[];
|
|
10
|
+
components: ActionRowBuilder<import("discord.js").AnyComponentBuilder>[];
|
|
11
|
+
allowedMentions: {
|
|
12
|
+
repliedUser: boolean;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
parseError(error: any): any;
|
|
6
16
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { PermissionsBitField } from "discord.js";
|
|
1
|
+
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, PermissionsBitField } from "discord.js";
|
|
2
2
|
import { FrameworkEvent } from "../../../types/FrameworkEvent.js";
|
|
3
3
|
import { ZumitoFramework } from "../../../ZumitoFramework.js";
|
|
4
|
+
import leven from 'leven';
|
|
5
|
+
import ErrorStackParser from 'error-stack-parser';
|
|
6
|
+
import * as url from 'url';
|
|
7
|
+
import path from "path";
|
|
4
8
|
export class MessageCreate extends FrameworkEvent {
|
|
5
9
|
once = false;
|
|
6
10
|
async execute({ message, client, framework }) {
|
|
@@ -12,9 +16,7 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
12
16
|
if (message.content.startsWith(prefix)) {
|
|
13
17
|
if (!framework.commands.has(command)) {
|
|
14
18
|
let commandNames = Array.from(framework.commands.keys());
|
|
15
|
-
var
|
|
16
|
-
autocorrect = autocorrect({ words: commandNames });
|
|
17
|
-
var correctedCommand = autocorrect(command);
|
|
19
|
+
var correctedCommand = this.autocorrect(command, commandNames);
|
|
18
20
|
if (framework.commands.has(correctedCommand)) {
|
|
19
21
|
commandInstance = framework.commands.get(correctedCommand);
|
|
20
22
|
}
|
|
@@ -27,11 +29,11 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
27
29
|
}
|
|
28
30
|
if (message.guild == null && commandInstance.dm == false)
|
|
29
31
|
return;
|
|
30
|
-
if (commandInstance.adminOnly || commandInstance.
|
|
32
|
+
if (commandInstance.adminOnly || commandInstance.userPermissions.length > 0) {
|
|
31
33
|
let denied = false;
|
|
32
34
|
if (framework.memberHasPermission(message.member, message.channel, PermissionsBitField.Flags.Administrator) || message.member.id != message.guild.ownerId) {
|
|
33
|
-
if (commandInstance.
|
|
34
|
-
commandInstance.
|
|
35
|
+
if (commandInstance.userPermissions.length > 0) {
|
|
36
|
+
commandInstance.userPermissions.forEach(permission => {
|
|
35
37
|
if (!framework.memberHasPermission(message.member, message.channel, permission)) {
|
|
36
38
|
denied = true;
|
|
37
39
|
}
|
|
@@ -62,10 +64,7 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
62
64
|
try {
|
|
63
65
|
let parsedArgs = new Map();
|
|
64
66
|
args.forEach(function (arg, index) {
|
|
65
|
-
parsedArgs.set(commandInstance.args?.[index]?.name || index,
|
|
66
|
-
name: commandInstance.args?.[index]?.name || index,
|
|
67
|
-
value: arg
|
|
68
|
-
});
|
|
67
|
+
parsedArgs.set(commandInstance.args?.[index]?.name || index, arg);
|
|
69
68
|
});
|
|
70
69
|
await commandInstance.execute({
|
|
71
70
|
message,
|
|
@@ -86,19 +85,121 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
catch (error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
let content = await this.getErrorEmbed({
|
|
89
|
+
name: error.name,
|
|
90
|
+
message: error.message,
|
|
91
|
+
command: commandInstance,
|
|
92
|
+
args: args,
|
|
93
|
+
stack: error.stack,
|
|
94
|
+
}, true);
|
|
95
|
+
try {
|
|
96
|
+
message.reply(content);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
channel.send(content);
|
|
100
|
+
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
autocorrect(str, words) {
|
|
105
|
+
var distance, bestWord, i, word, min;
|
|
106
|
+
var dictionary = words || [];
|
|
107
|
+
var len = dictionary.length;
|
|
108
|
+
for (i = 0; i < len; i++) {
|
|
109
|
+
word = dictionary[i];
|
|
110
|
+
distance = leven(str, word);
|
|
111
|
+
if (distance === 0) {
|
|
112
|
+
return word;
|
|
113
|
+
}
|
|
114
|
+
else if (min === undefined || distance < min) {
|
|
115
|
+
min = distance;
|
|
116
|
+
bestWord = word;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return bestWord;
|
|
120
|
+
}
|
|
121
|
+
getErrorEmbed(error, parse) {
|
|
122
|
+
let parsedError;
|
|
123
|
+
if (parse) {
|
|
124
|
+
parsedError = this.parseError(error);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
parsedError = error;
|
|
128
|
+
}
|
|
129
|
+
let embed = new EmbedBuilder()
|
|
130
|
+
.setTitle('Error')
|
|
131
|
+
.setDescription('An error has occured while executing this command.')
|
|
132
|
+
.setTimestamp()
|
|
133
|
+
.addFields([{
|
|
134
|
+
name: 'Command:',
|
|
135
|
+
value: (error.command.name || 'Not defined')
|
|
136
|
+
}])
|
|
137
|
+
.addFields([{
|
|
138
|
+
name: 'Arguments:',
|
|
139
|
+
value: (error.args.toString() || 'None')
|
|
140
|
+
}])
|
|
141
|
+
.addFields([{
|
|
142
|
+
name: 'Error name:',
|
|
143
|
+
value: (error.name || 'Not defined')
|
|
144
|
+
}])
|
|
145
|
+
.addFields([{
|
|
146
|
+
name: 'Error message:',
|
|
147
|
+
value: (error.message || 'Not defined')
|
|
148
|
+
}]);
|
|
149
|
+
if (error.possibleSolutions !== undefined) {
|
|
150
|
+
error.possibleSolutions.forEach((solution) => {
|
|
151
|
+
embed.addFields([{
|
|
152
|
+
name: 'Posible solution:',
|
|
153
|
+
value: solution
|
|
154
|
+
}]);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
let stackFrames = ErrorStackParser.parse(error).filter(e => !e.fileName.includes('node_modules') && !e.fileName.includes('node:internal'));
|
|
158
|
+
let stack = '';
|
|
159
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
160
|
+
let path1 = path.resolve('./');
|
|
161
|
+
let path2 = path1.replaceAll('\\', '/');
|
|
162
|
+
stackFrames.forEach((frame) => {
|
|
163
|
+
stack += `[${frame.fileName.replace(path1, '').replace(path2, '').replace('file://', '')}:${frame.lineNumber}](https://zumito.ga/redirect?url=vscode://file/${frame.fileName.replace('file://', '')}:${frame.lineNumber}) ${frame.functionName}()\n`;
|
|
164
|
+
});
|
|
165
|
+
if (error.stack !== undefined) {
|
|
166
|
+
embed.addFields([{
|
|
167
|
+
name: 'Call stack:',
|
|
168
|
+
value: stack || error.stack || error.stack.toString()
|
|
169
|
+
}]);
|
|
170
|
+
}
|
|
171
|
+
if (error.details !== undefined) {
|
|
172
|
+
error.details.forEach((detail) => {
|
|
173
|
+
embed.addFields([{
|
|
174
|
+
name: 'Detail:',
|
|
175
|
+
value: detail
|
|
176
|
+
}]);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const body = `\n\n\n---\nComand:\`\`\`${error.command.name || 'not defined'}\`\`\`\nArguments:\`\`\`${error.args.toString() || 'none'}\`\`\`\nError:\`\`\`${error.name || 'not defined'}\`\`\`\nError message:\`\`\`${error.message || 'not defined'}\`\`\`\n`;
|
|
180
|
+
const requestUrl = `https://github.com/fernandomema/Zumito/issues/new?body=${encodeURIComponent(body)}`;
|
|
181
|
+
const row = new ActionRowBuilder()
|
|
182
|
+
.addComponents(new ButtonBuilder()
|
|
183
|
+
.setStyle(ButtonStyle.Link)
|
|
184
|
+
.setLabel('Report error')
|
|
185
|
+
.setEmoji('975645505302437978')
|
|
186
|
+
.setURL(requestUrl));
|
|
187
|
+
return {
|
|
188
|
+
embeds: [embed],
|
|
189
|
+
components: [row],
|
|
190
|
+
allowedMentions: {
|
|
191
|
+
repliedUser: false
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
parseError(error) {
|
|
196
|
+
error.possibleSolutions = [];
|
|
197
|
+
if (/(?:^|(?<= ))(EmbedBuilder|Discord|ActionRowBuilder|ButtonBuilder|MessageSelectMenu)(?:(?= )|$) is not defined/gm.test(error.message)) {
|
|
198
|
+
error.possibleSolutions.push('const { ' + error.message.split(" ")[0] + ' } = require(\'discord.js\');');
|
|
199
|
+
}
|
|
200
|
+
else if (error.message.includes('A custom id and url cannot both be specified')) {
|
|
201
|
+
error.possibleSolutions.push("Remove .setCustomId(...) or .setURL(...)");
|
|
202
|
+
}
|
|
203
|
+
return error;
|
|
204
|
+
}
|
|
104
205
|
}
|
|
@@ -2,5 +2,5 @@ import { Module } from "../types/Module.js";
|
|
|
2
2
|
import { ZumitoFramework } from "../ZumitoFramework.js";
|
|
3
3
|
export declare class baseModule extends Module {
|
|
4
4
|
constructor(modulePath: string, framework: ZumitoFramework);
|
|
5
|
-
|
|
5
|
+
registerEvents(): Promise<any>;
|
|
6
6
|
}
|
package/dist/baseModule/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export class baseModule extends Module {
|
|
|
5
5
|
constructor(modulePath, framework) {
|
|
6
6
|
super(modulePath, framework);
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
async registerEvents() {
|
|
9
9
|
this.events.set('interactionCreate', new InteractionCreate());
|
|
10
10
|
this.events.set('messageCreate', new MessageCreate());
|
|
11
11
|
this.events.forEach(event => {
|
package/dist/types/Command.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare abstract class Command {
|
|
|
5
5
|
categories: string[];
|
|
6
6
|
aliases?: string[];
|
|
7
7
|
examples?: string[];
|
|
8
|
-
|
|
8
|
+
userPermissions?: bigint[];
|
|
9
9
|
botPermissions?: string[];
|
|
10
10
|
hidden?: boolean;
|
|
11
11
|
adminOnly?: boolean;
|
|
@@ -19,5 +19,5 @@ export declare abstract class Command {
|
|
|
19
19
|
abstract execute({ message, interaction, args, client, framework }: CommandParameters): void;
|
|
20
20
|
executePrefixCommand({ message, interaction, args, client, framework }: CommandParameters): void;
|
|
21
21
|
executeSlashCommand({ message, interaction, args, client, framework }: CommandParameters): void;
|
|
22
|
-
selectMenu({ path, interaction, client, framework }: SelectMenuParameters): void;
|
|
22
|
+
abstract selectMenu({ path, interaction, client, framework }: SelectMenuParameters): void;
|
|
23
23
|
}
|
package/dist/types/Command.js
CHANGED
|
@@ -4,7 +4,7 @@ export class Command {
|
|
|
4
4
|
categories = [];
|
|
5
5
|
aliases = [];
|
|
6
6
|
examples = [];
|
|
7
|
-
|
|
7
|
+
userPermissions = [];
|
|
8
8
|
botPermissions = [];
|
|
9
9
|
hidden = false;
|
|
10
10
|
adminOnly = false;
|
|
@@ -22,5 +22,4 @@ export class Command {
|
|
|
22
22
|
executeSlashCommand({ message, interaction, args, client, framework }) {
|
|
23
23
|
this.execute({ message, interaction, args, client, framework });
|
|
24
24
|
}
|
|
25
|
-
selectMenu({ path, interaction, client, framework }) { }
|
|
26
25
|
}
|
package/dist/types/Commands.js
CHANGED
package/dist/types/Module.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export declare abstract class Module {
|
|
|
10
10
|
constructor(path: any, framework: any);
|
|
11
11
|
initialize(): Promise<void>;
|
|
12
12
|
registerCommands(): Promise<void>;
|
|
13
|
-
onCommandCreated(filePath: string): void
|
|
14
|
-
onCommandChanged(filePath: string): void
|
|
13
|
+
onCommandCreated(filePath: string): Promise<void>;
|
|
14
|
+
onCommandChanged(filePath: string): Promise<void>;
|
|
15
15
|
onErrorLoadingCommand(error: Error): void;
|
|
16
16
|
getCommands(): Map<string, Command>;
|
|
17
17
|
registerEvents(): Promise<void>;
|
package/dist/types/Module.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as chokidar from 'chokidar';
|
|
2
|
+
import chalk from 'chalk';
|
|
2
3
|
import boxen from "boxen";
|
|
3
4
|
import * as fs from 'fs';
|
|
4
5
|
import path from 'path';
|
|
6
|
+
import { SelectMenuInteraction } from "discord.js";
|
|
5
7
|
export class Module {
|
|
6
8
|
path;
|
|
7
9
|
framework;
|
|
@@ -16,41 +18,62 @@ export class Module {
|
|
|
16
18
|
await this.registerCommands();
|
|
17
19
|
await this.registerEvents();
|
|
18
20
|
await this.registerTranslations();
|
|
21
|
+
// console.error('[🔄🔴 ] Error initializing module ' + this.constructor.name);
|
|
22
|
+
// console.log(boxen(e + '\n' + e.stack, { padding: 1 }));
|
|
19
23
|
}
|
|
20
24
|
async registerCommands() {
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (fs.existsSync(path.join(this.path, 'commands'))) {
|
|
26
|
+
let files = fs.readdirSync(path.join(this.path, 'commands'));
|
|
27
|
+
for (let file of files) {
|
|
28
|
+
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
29
|
+
let command = await import('file://' + path.join(this.path, 'commands', file)).catch(e => {
|
|
30
|
+
console.error(`[🔄🔴 ] Error loading ${file.slice(0, -3)} command on module ${this.constructor.name}`);
|
|
31
|
+
console.error(e + '\n' + e.name + '\n' + e.stack);
|
|
32
|
+
});
|
|
33
|
+
command = Object.values(command)[0];
|
|
34
|
+
command = new command();
|
|
35
|
+
this.commands.set(command.constructor.name.toLowerCase(), command);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
;
|
|
39
|
+
// register watcher
|
|
40
|
+
if (process.env.DEBUG) {
|
|
41
|
+
/*
|
|
42
|
+
Debug only cause in prod environment commands should't be changed.
|
|
43
|
+
Appart from that, esm module cache invalidation is not working properly
|
|
44
|
+
and can cause memory leaks and crashes.
|
|
45
|
+
*/
|
|
46
|
+
chokidar.watch(path.resolve(path.join(this.path, 'commands')), { ignored: /^\./, persistent: true, ignoreInitial: true })
|
|
47
|
+
.on('add', this.onCommandCreated.bind(this))
|
|
48
|
+
.on('change', this.onCommandChanged.bind(this))
|
|
49
|
+
//.on('unlink', function(path) {console.log('File', path, 'has been removed');})
|
|
50
|
+
.on('error', this.onErrorLoadingCommand.bind(this));
|
|
30
51
|
}
|
|
31
|
-
}
|
|
32
|
-
;
|
|
33
|
-
// register watcher
|
|
34
|
-
if (process.env.DEBUG) {
|
|
35
|
-
chokidar.watch(path.resolve(path.join(this.path, 'commands')), { ignored: /^\./, persistent: true, ignoreInitial: true })
|
|
36
|
-
.on('add', this.onCommandCreated.bind(this))
|
|
37
|
-
.on('change', this.onCommandChanged.bind(this))
|
|
38
|
-
//.on('unlink', function(path) {console.log('File', path, 'has been removed');})
|
|
39
|
-
.on('error', this.onErrorLoadingCommand.bind(this));
|
|
40
52
|
}
|
|
41
53
|
}
|
|
42
|
-
onCommandCreated(filePath) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
async onCommandCreated(filePath) {
|
|
55
|
+
if (filePath.endsWith('.js') || filePath.endsWith('.ts')) {
|
|
56
|
+
let command = await import('file://' + filePath).catch(e => {
|
|
57
|
+
console.error('[🆕🔴 ] Error loading command ' + chalk.blue(filePath.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')));
|
|
58
|
+
console.log(e + '\n' + e.name + '\n' + e.stack);
|
|
59
|
+
});
|
|
60
|
+
command = Object.values(command)[0];
|
|
61
|
+
command = new command();
|
|
62
|
+
this.commands.set(command.constructor.name.toLowerCase(), command);
|
|
63
|
+
console.debug('[🆕🟢 ] Command ' + chalk.blue(filePath.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')) + ' loaded');
|
|
64
|
+
}
|
|
52
65
|
}
|
|
53
|
-
onCommandChanged(filePath) {
|
|
66
|
+
async onCommandChanged(filePath) {
|
|
67
|
+
if (filePath.endsWith('.js') || filePath.endsWith('.ts')) {
|
|
68
|
+
let command = await import('file://' + filePath + '?update=' + Date.now().toString()).catch(e => {
|
|
69
|
+
console.error('[🔄🔴 ] Error reloading command ' + chalk.blue(filePath.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')));
|
|
70
|
+
console.log(boxen(e + '\n' + e.name + '\n' + e.stack, { padding: 1 }));
|
|
71
|
+
});
|
|
72
|
+
command = Object.values(command)[0];
|
|
73
|
+
command = new command();
|
|
74
|
+
this.commands.set(command.constructor.name.toLowerCase(), command);
|
|
75
|
+
console.debug('[🔄🟢 ] Command ' + chalk.blue(filePath.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')) + ' reloaded');
|
|
76
|
+
}
|
|
54
77
|
}
|
|
55
78
|
onErrorLoadingCommand(error) {
|
|
56
79
|
console.error('[🔄🔴 ] Error reloading command');
|
|
@@ -68,7 +91,10 @@ export class Module {
|
|
|
68
91
|
let moduleFileNames = fs.readdirSync(path.join(this.path, 'events', 'discord'));
|
|
69
92
|
for (let moduleFileName of moduleFileNames) {
|
|
70
93
|
if (moduleFileName.endsWith('.js') || moduleFileName.endsWith('.ts')) {
|
|
71
|
-
let event = await import('file://' + path.join(this.path, 'events', 'discord', moduleFileName))
|
|
94
|
+
let event = await import('file://' + path.join(this.path, 'events', 'discord', moduleFileName)).catch(e => {
|
|
95
|
+
console.error(`[🔄🔴 ] Error loading ${moduleFileName.slice(0, -3)} event on module ${this.constructor.name}`);
|
|
96
|
+
console.log(boxen(e + '\n' + e.name + '\n' + e.stack, { padding: 1 }));
|
|
97
|
+
});
|
|
72
98
|
event = Object.values(event)[0];
|
|
73
99
|
event = new event();
|
|
74
100
|
this.events.set(event.constructor.name.toLowerCase(), event);
|
|
@@ -101,6 +127,10 @@ export class Module {
|
|
|
101
127
|
args.forEach(arg => {
|
|
102
128
|
finalArgs[arg.constructor.name.toLowerCase()] = arg;
|
|
103
129
|
});
|
|
130
|
+
let selectMenuInteraction = args.find((arg) => arg instanceof SelectMenuInteraction);
|
|
131
|
+
if (selectMenuInteraction) {
|
|
132
|
+
finalArgs['interaction'] = selectMenuInteraction;
|
|
133
|
+
}
|
|
104
134
|
return finalArgs;
|
|
105
135
|
}
|
|
106
136
|
getEvents() {
|
|
@@ -112,7 +142,6 @@ export class Module {
|
|
|
112
142
|
let files = fs.readdirSync(path.join(this.path, 'translations'));
|
|
113
143
|
for (let file of files) {
|
|
114
144
|
if (file.endsWith('.json')) {
|
|
115
|
-
console.log('load ' + file);
|
|
116
145
|
let json = await import('file://' + `${this.path}/translations/${file}`, {
|
|
117
146
|
assert: {
|
|
118
147
|
type: "json",
|
|
@@ -122,7 +151,7 @@ export class Module {
|
|
|
122
151
|
console.log(boxen(e + '\n' + e.name + '\n' + e.stack, { padding: 1 }));
|
|
123
152
|
});
|
|
124
153
|
let lang = file.slice(0, -5);
|
|
125
|
-
this.parseTranslation('', lang, json);
|
|
154
|
+
this.parseTranslation('', lang, json.default);
|
|
126
155
|
}
|
|
127
156
|
}
|
|
128
157
|
}
|
|
@@ -143,7 +172,6 @@ export class Module {
|
|
|
143
172
|
for (let file of files) {
|
|
144
173
|
if (file.endsWith('.json')) {
|
|
145
174
|
let modelName = file.slice(0, -5).charAt(0).toUpperCase() + file.slice(0, -5).slice(1);
|
|
146
|
-
console.log('load ' + file);
|
|
147
175
|
let modelDefiniton = await import('file://' + `${this.path}/models/${file}`, {
|
|
148
176
|
assert: {
|
|
149
177
|
type: "json",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Client,
|
|
1
|
+
import { Client, SelectMenuInteraction } from "discord.js";
|
|
2
2
|
import { ZumitoFramework } from "../ZumitoFramework.js";
|
|
3
3
|
export interface SelectMenuParameters {
|
|
4
4
|
path: string[];
|
|
5
|
-
interaction:
|
|
5
|
+
interaction: SelectMenuInteraction;
|
|
6
6
|
client: Client;
|
|
7
7
|
framework: ZumitoFramework;
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zumito-framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.34",
|
|
4
4
|
"description": "Discord.js bot framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
18
|
-
"build": "tsc",
|
|
18
|
+
"build": "tsc-esm",
|
|
19
19
|
"publish": "npm publish",
|
|
20
20
|
"docs": "typedoc --out docs src"
|
|
21
21
|
},
|
|
@@ -30,16 +30,18 @@
|
|
|
30
30
|
"chokidar": "^3.5.3",
|
|
31
31
|
"cookie-parser": "^1.4.6",
|
|
32
32
|
"cors": "^2.8.5",
|
|
33
|
-
"discord.js": "^14.
|
|
33
|
+
"discord.js": "^14.3.0",
|
|
34
|
+
"error-stack-parser": "^2.1.4",
|
|
34
35
|
"express": "^4.18.1",
|
|
36
|
+
"leven": "^4.0.0",
|
|
35
37
|
"mongoose": "^6.5.2",
|
|
36
38
|
"plop": "^3.1.1",
|
|
37
39
|
"zumito-framework": "^1.1.16"
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"@types/node": "^18.7.16",
|
|
41
|
-
"typedoc": "^0.23.
|
|
42
|
-
"typescript": "^4.
|
|
43
|
+
"typedoc": "^0.23.14",
|
|
44
|
+
"typescript": "^4.8.2"
|
|
43
45
|
},
|
|
44
46
|
"type": "module"
|
|
45
47
|
}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { Command, CommandParameters } from "zumito-framework";
|
|
2
2
|
|
|
3
|
-
export class {{
|
|
3
|
+
export class {{capitalize command}} extends Command {
|
|
4
4
|
|
|
5
5
|
execute({ message, interaction, args, client, framework }: CommandParameters): void {
|
|
6
|
-
(message || interaction).reply({
|
|
6
|
+
(message || interaction!).reply({
|
|
7
7
|
content: "Message content",
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
async selectMenu({ path, interaction, client, framework }: SelectMenuParameters): Promise<void> {
|
|
12
|
+
await interaction.deferUpdate();
|
|
13
|
+
await interaction.editReply({
|
|
14
|
+
content: "Select menu content",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
10
17
|
}
|
package/plopfile.js
CHANGED