zumito-framework 1.1.70 → 1.1.72-dev-update-pull-request-ci.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/dist/ZumitoFramework.d.ts +20 -12
- package/dist/ZumitoFramework.js +36 -61
- package/dist/{types → definitions}/Module.d.ts +6 -8
- package/dist/definitions/Module.js +129 -0
- package/dist/{types → definitions}/Translation.d.ts +0 -1
- package/dist/{types → definitions}/Translation.js +0 -1
- package/dist/{types → definitions/commands}/Command.d.ts +1 -1
- package/dist/{types → definitions/commands}/CommandParameters.d.ts +1 -1
- package/dist/{types → definitions/parameters}/EventParameters.d.ts +1 -1
- package/dist/{types/Commands → definitions/parameters}/SelectMenu.d.ts +1 -1
- package/dist/{types → definitions/parameters}/SelectMenuParameters.d.ts +1 -1
- package/dist/index.d.ts +21 -21
- package/dist/index.js +13 -13
- package/dist/{baseModule/events/discord/interactionCreate.d.ts → modules/core/baseModule/events/discord/InteractionCreate.d.ts} +3 -3
- package/dist/{baseModule/events/discord/interactionCreate.js → modules/core/baseModule/events/discord/InteractionCreate.js} +28 -21
- package/dist/{baseModule/events/discord/messageCreate.d.ts → modules/core/baseModule/events/discord/MessageCreate.d.ts} +3 -3
- package/dist/{baseModule/events/discord/messageCreate.js → modules/core/baseModule/events/discord/MessageCreate.js} +8 -10
- package/dist/{baseModule → modules/core/baseModule}/models/Guild.d.ts +1 -1
- package/dist/{baseModule → modules/core/baseModule}/models/Guild.js +1 -1
- package/dist/services/CommandManager.d.ts +40 -0
- package/dist/services/CommandManager.js +160 -0
- package/dist/services/EventManager.d.ts +8 -0
- package/dist/services/EventManager.js +27 -0
- package/dist/services/InteractionIdGenerator.d.ts +13 -0
- package/dist/services/InteractionIdGenerator.js +40 -0
- package/dist/services/ModuleManager.d.ts +17 -0
- package/dist/services/ModuleManager.js +78 -0
- package/dist/{managers → services}/StatusManager.d.ts +1 -1
- package/dist/services/TranslationManager.d.ts +34 -0
- package/dist/services/TranslationManager.js +122 -0
- package/package.json +9 -4
- package/dist/TranslationManager.d.ts +0 -15
- package/dist/TranslationManager.js +0 -41
- package/dist/baseModule/BaseModule.d.ts +0 -6
- package/dist/baseModule/BaseModule.js +0 -16
- package/dist/baseModule/index.d.ts +0 -7
- package/dist/baseModule/index.js +0 -19
- package/dist/types/Commands.d.ts +0 -23
- package/dist/types/Commands.js +0 -26
- package/dist/types/Module.js +0 -211
- /package/dist/{types → definitions}/DatabaseModel.d.ts +0 -0
- /package/dist/{types → definitions}/DatabaseModel.js +0 -0
- /package/dist/{types → definitions}/FrameworkEvent.d.ts +0 -0
- /package/dist/{types → definitions}/FrameworkEvent.js +0 -0
- /package/dist/{types → definitions}/FrameworkSettings.d.ts +0 -0
- /package/dist/{types → definitions}/FrameworkSettings.js +0 -0
- /package/dist/{types → definitions}/StatusManagerOptions.d.ts +0 -0
- /package/dist/{types → definitions}/StatusManagerOptions.js +0 -0
- /package/dist/definitions/{ApiResponse.d.ts → api/ApiResponse.d.ts} +0 -0
- /package/dist/definitions/{ApiResponse.js → api/ApiResponse.js} +0 -0
- /package/dist/{types → definitions/commands}/Command.js +0 -0
- /package/dist/{types → definitions/commands}/CommandArgDefinition.d.ts +0 -0
- /package/dist/{types → definitions/commands}/CommandArgDefinition.js +0 -0
- /package/dist/{types → definitions/commands}/CommandArguments.d.ts +0 -0
- /package/dist/{types → definitions/commands}/CommandArguments.js +0 -0
- /package/dist/{types → definitions/commands}/CommandChoiceDefinition.d.ts +0 -0
- /package/dist/{types → definitions/commands}/CommandChoiceDefinition.js +0 -0
- /package/dist/{types → definitions/commands}/CommandParameters.js +0 -0
- /package/dist/{types → definitions/commands}/CommandType.d.ts +0 -0
- /package/dist/{types → definitions/commands}/CommandType.js +0 -0
- /package/dist/{types/Commands → definitions/parameters}/ButtonPressed.d.ts +0 -0
- /package/dist/{types/Commands → definitions/parameters}/ButtonPressed.js +0 -0
- /package/dist/{types/Commands → definitions/parameters}/ButtonPressedParams.d.ts +0 -0
- /package/dist/{types/Commands → definitions/parameters}/ButtonPressedParams.js +0 -0
- /package/dist/{types → definitions/parameters}/EventParameters.js +0 -0
- /package/dist/{types/Commands → definitions/parameters}/SelectMenu.js +0 -0
- /package/dist/{types → definitions/parameters}/SelectMenuParameters.js +0 -0
- /package/dist/{utils → services}/DatabaseConfigLoader.d.ts +0 -0
- /package/dist/{utils → services}/DatabaseConfigLoader.js +0 -0
- /package/dist/{utils → services}/EmojiFallback.d.ts +0 -0
- /package/dist/{utils → services}/EmojiFallback.js +0 -0
- /package/dist/{managers → services}/EmojiManager.d.ts +0 -0
- /package/dist/{managers → services}/EmojiManager.js +0 -0
- /package/dist/{managers → services}/StatusManager.js +0 -0
- /package/dist/{utils → services}/TextFormatter.d.ts +0 -0
- /package/dist/{utils → services}/TextFormatter.js +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ActionRowBuilder, EmbedBuilder } from 'discord.js';
|
|
2
|
-
import { EventParameters } from '
|
|
3
|
-
import { FrameworkEvent } from '
|
|
2
|
+
import { EventParameters } from '../../../../../definitions/parameters/EventParameters.js';
|
|
3
|
+
import { FrameworkEvent } from '../../../../../definitions/FrameworkEvent.js';
|
|
4
4
|
export declare class MessageCreate extends FrameworkEvent {
|
|
5
5
|
once: boolean;
|
|
6
|
-
execute({ message,
|
|
6
|
+
execute({ message, framework }: EventParameters): Promise<import("discord.js").Message<boolean>>;
|
|
7
7
|
autocorrect(str: string, words: string[]): any;
|
|
8
8
|
getErrorEmbed(error: any, parse: any): {
|
|
9
9
|
embeds: EmbedBuilder[];
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import * as url from 'url';
|
|
2
1
|
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, EmbedBuilder, PermissionsBitField, } from 'discord.js';
|
|
3
2
|
import ErrorStackParser from 'error-stack-parser';
|
|
4
|
-
import { FrameworkEvent } from '
|
|
5
|
-
import { ZumitoFramework } from '
|
|
3
|
+
import { FrameworkEvent } from '../../../../../definitions/FrameworkEvent.js';
|
|
4
|
+
import { ZumitoFramework } from '../../../../../ZumitoFramework.js';
|
|
6
5
|
import leven from 'leven';
|
|
7
6
|
import path from 'path';
|
|
7
|
+
import { InteractionIdGenerator } from '../../../../../services/InteractionIdGenerator.js';
|
|
8
8
|
export class MessageCreate extends FrameworkEvent {
|
|
9
9
|
once = false;
|
|
10
|
-
async execute({ message,
|
|
10
|
+
async execute({ message, framework }) {
|
|
11
11
|
const channel = message.channel;
|
|
12
12
|
const prefix = framework.settings.defaultPrefix;
|
|
13
13
|
const args = ZumitoFramework.splitCommandLine(message.content.slice(prefix.length));
|
|
14
14
|
const command = args.shift().toLowerCase();
|
|
15
15
|
let commandInstance;
|
|
16
16
|
if (message.content.startsWith(prefix)) {
|
|
17
|
-
if (!framework.commands.has(command)) {
|
|
18
|
-
const commandNames = Array.from(framework.commands.keys());
|
|
17
|
+
if (!framework.commands.getAll().has(command)) {
|
|
18
|
+
const commandNames = Array.from(framework.commands.getAll().keys());
|
|
19
19
|
const correctedCommand = this.autocorrect(command, commandNames);
|
|
20
|
-
if (framework.commands.has(correctedCommand)) {
|
|
20
|
+
if (framework.commands.getAll().has(correctedCommand)) {
|
|
21
21
|
commandInstance = framework.commands.get(correctedCommand);
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
@@ -71,7 +71,6 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
71
71
|
try {
|
|
72
72
|
const guildSettings = await framework.getGuildSettings(message.guildId);
|
|
73
73
|
const parsedArgs = new Map();
|
|
74
|
-
const userMentionCount = 0;
|
|
75
74
|
for (let i = 0; i < args.length; i++) {
|
|
76
75
|
const arg = args[i];
|
|
77
76
|
const type = commandInstance.args[i]?.type;
|
|
@@ -100,6 +99,7 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
}
|
|
102
|
+
const interactionIdGenerator = new InteractionIdGenerator(undefined, commandInstance.name);
|
|
103
103
|
await commandInstance.execute({
|
|
104
104
|
message,
|
|
105
105
|
args: parsedArgs,
|
|
@@ -122,7 +122,6 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
122
122
|
message.delete().catch(function () {
|
|
123
123
|
console.error("can't delete user command");
|
|
124
124
|
});
|
|
125
|
-
const metadata = await fetch('https://tulipo.ga/api/last_command/' + command).then((res) => res.json());
|
|
126
125
|
}
|
|
127
126
|
catch (err) {
|
|
128
127
|
console.error(err.name, err.message);
|
|
@@ -214,7 +213,6 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
214
213
|
const stackFrames = ErrorStackParser.parse(error).filter((e) => !e.fileName.includes('node_modules') &&
|
|
215
214
|
!e.fileName.includes('node:internal'));
|
|
216
215
|
let stack = '';
|
|
217
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
218
216
|
const path1 = path.resolve('./');
|
|
219
217
|
const path2 = path1.replaceAll('\\', '/');
|
|
220
218
|
stackFrames.forEach((frame) => {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ZumitoFramework } from "../ZumitoFramework";
|
|
2
|
+
import { Command } from "../definitions/commands/Command.js";
|
|
3
|
+
export declare class CommandManager {
|
|
4
|
+
protected commands: Map<string, Command>;
|
|
5
|
+
protected framework: ZumitoFramework;
|
|
6
|
+
constructor(framework: any);
|
|
7
|
+
set(name: string, command: Command): void;
|
|
8
|
+
get(name: string): Command;
|
|
9
|
+
getAll(): Map<string, Command>;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
get size(): number;
|
|
14
|
+
/**
|
|
15
|
+
* Load command from file
|
|
16
|
+
* @async
|
|
17
|
+
* @public
|
|
18
|
+
* @param filePath - Absolute path to command file
|
|
19
|
+
* @returns {Promise<Command>}
|
|
20
|
+
*/
|
|
21
|
+
loadCommandFile(filePath: string): Promise<any>;
|
|
22
|
+
/**
|
|
23
|
+
* Load all command files from a folder
|
|
24
|
+
* @async
|
|
25
|
+
* @public
|
|
26
|
+
* @param folderPath - Absolute path to commands folder
|
|
27
|
+
* @returns {Promise<Map<string, Command>>}
|
|
28
|
+
*/
|
|
29
|
+
loadCommandsFolder(folderPath: string): Promise<Map<string, any>>;
|
|
30
|
+
/**
|
|
31
|
+
* Watch command files on a folder.
|
|
32
|
+
* It loads command when new file is created, update command when file is modified and deletes command when file is deleted.
|
|
33
|
+
* @async
|
|
34
|
+
* @public
|
|
35
|
+
* @param folderPath - Absolute path to commands folder
|
|
36
|
+
* @returns {Promise<Map<string, Command>>}
|
|
37
|
+
*/
|
|
38
|
+
watchCommandsFolder(folderPath: string): void;
|
|
39
|
+
refreshSlashCommands(): Promise<void>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import * as chokidar from 'chokidar';
|
|
3
|
+
import path from "path";
|
|
4
|
+
import boxen from "boxen";
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import { REST, Routes, SlashCommandBuilder } from "discord.js";
|
|
7
|
+
import { CommandType } from "../definitions/commands/CommandType.js";
|
|
8
|
+
export class CommandManager {
|
|
9
|
+
commands;
|
|
10
|
+
framework;
|
|
11
|
+
constructor(framework) {
|
|
12
|
+
this.commands = new Map;
|
|
13
|
+
this.framework = framework;
|
|
14
|
+
}
|
|
15
|
+
set(name, command) {
|
|
16
|
+
this.commands.set(name, command);
|
|
17
|
+
}
|
|
18
|
+
get(name) {
|
|
19
|
+
return this.commands.get(name);
|
|
20
|
+
}
|
|
21
|
+
getAll() {
|
|
22
|
+
return this.commands;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated
|
|
26
|
+
*/
|
|
27
|
+
get size() {
|
|
28
|
+
return this.commands.size;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Load command from file
|
|
32
|
+
* @async
|
|
33
|
+
* @public
|
|
34
|
+
* @param filePath - Absolute path to command file
|
|
35
|
+
* @returns {Promise<Command>}
|
|
36
|
+
*/
|
|
37
|
+
async loadCommandFile(filePath) {
|
|
38
|
+
// Validate file has .ts or .js extension
|
|
39
|
+
if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {
|
|
40
|
+
throw new Error("File must be a .ts or .js");
|
|
41
|
+
}
|
|
42
|
+
// import file
|
|
43
|
+
let command = await import('file://' + filePath + '?update=' + Date.now().toString()).catch(e => {
|
|
44
|
+
console.error('[🆕🔴 ] Error loading command ' + chalk.blue(filePath.toString().replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')));
|
|
45
|
+
console.log(e + '\n' + e.name + '\n' + e.stack);
|
|
46
|
+
});
|
|
47
|
+
command = Object.values(command)[0];
|
|
48
|
+
command = new command();
|
|
49
|
+
this.framework.commands.set(command.constructor.name.toLowerCase(), command);
|
|
50
|
+
console.debug('[🆕🟢 ] Command ' + chalk.blue(filePath.toString().replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.')) + ' loaded');
|
|
51
|
+
return command;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Load all command files from a folder
|
|
55
|
+
* @async
|
|
56
|
+
* @public
|
|
57
|
+
* @param folderPath - Absolute path to commands folder
|
|
58
|
+
* @returns {Promise<Map<string, Command>>}
|
|
59
|
+
*/
|
|
60
|
+
async loadCommandsFolder(folderPath) {
|
|
61
|
+
const files = fs.readdirSync(folderPath);
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
if (file.endsWith('d.ts'))
|
|
64
|
+
continue;
|
|
65
|
+
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
66
|
+
const command = await this.loadCommandFile(path.join(folderPath, file));
|
|
67
|
+
this.commands.set(command.constructor.name.toLowerCase(), command);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return this.commands;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Watch command files on a folder.
|
|
74
|
+
* It loads command when new file is created, update command when file is modified and deletes command when file is deleted.
|
|
75
|
+
* @async
|
|
76
|
+
* @public
|
|
77
|
+
* @param folderPath - Absolute path to commands folder
|
|
78
|
+
* @returns {Promise<Map<string, Command>>}
|
|
79
|
+
*/
|
|
80
|
+
watchCommandsFolder(folderPath) {
|
|
81
|
+
chokidar
|
|
82
|
+
.watch(path.resolve(folderPath), {
|
|
83
|
+
ignored: /^\./,
|
|
84
|
+
persistent: true,
|
|
85
|
+
ignoreInitial: true,
|
|
86
|
+
})
|
|
87
|
+
.on('add', (filePath) => {
|
|
88
|
+
this.loadCommandFile(filePath);
|
|
89
|
+
})
|
|
90
|
+
.on('change', (filePath) => {
|
|
91
|
+
this.loadCommandFile(filePath);
|
|
92
|
+
})
|
|
93
|
+
.on('error', (error) => {
|
|
94
|
+
console.error('[🔄🔴 ] Error reloading command');
|
|
95
|
+
console.log(boxen(error + '\n' + error.stack, { padding: 1 }));
|
|
96
|
+
});
|
|
97
|
+
// TODO: Handle file removal
|
|
98
|
+
//.on('unlink', function(path) {console.log('File', path, 'has been removed');})
|
|
99
|
+
}
|
|
100
|
+
async refreshSlashCommands() {
|
|
101
|
+
const rest = new REST({ version: '10' }).setToken(this.framework.settings.discordClientOptions.token);
|
|
102
|
+
const commands = Array.from(this.commands.values())
|
|
103
|
+
.filter((command) => command.type == CommandType.slash ||
|
|
104
|
+
command.type == CommandType.separated ||
|
|
105
|
+
command.type == CommandType.any)
|
|
106
|
+
.map((command) => {
|
|
107
|
+
const slashCommand = new SlashCommandBuilder()
|
|
108
|
+
.setName(command.name)
|
|
109
|
+
.setDescription(this.framework.translations.get('command.' + command.name + '.description', 'en'));
|
|
110
|
+
if (command.args) {
|
|
111
|
+
command.args.forEach((arg) => {
|
|
112
|
+
let method;
|
|
113
|
+
switch (arg.type) {
|
|
114
|
+
case 'string':
|
|
115
|
+
method = 'addStringOption';
|
|
116
|
+
break;
|
|
117
|
+
case 'user':
|
|
118
|
+
case 'member':
|
|
119
|
+
method = 'addUserOption';
|
|
120
|
+
break;
|
|
121
|
+
case 'channel':
|
|
122
|
+
method = 'addChannelOption';
|
|
123
|
+
break;
|
|
124
|
+
case 'role':
|
|
125
|
+
method = 'addRoleOption';
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
throw new Error('Invalid argument type ' + arg.type);
|
|
129
|
+
}
|
|
130
|
+
slashCommand[method]((option) => {
|
|
131
|
+
option.setName(arg.name);
|
|
132
|
+
option.setDescription(this.framework.translations.get('command.' +
|
|
133
|
+
command.name +
|
|
134
|
+
'.args.' +
|
|
135
|
+
arg.name +
|
|
136
|
+
'.description', 'en'));
|
|
137
|
+
option.setRequired(!arg.optional);
|
|
138
|
+
if (arg.choices) {
|
|
139
|
+
// if arg.choices is function, call it
|
|
140
|
+
if (typeof arg.choices == 'function') {
|
|
141
|
+
arg.choices =
|
|
142
|
+
arg.choices();
|
|
143
|
+
}
|
|
144
|
+
arg.choices.forEach((choice) => {
|
|
145
|
+
option.addChoices({
|
|
146
|
+
name: choice.name,
|
|
147
|
+
value: choice.value,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return option;
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return slashCommand.toJSON();
|
|
156
|
+
});
|
|
157
|
+
const data = await rest.put(Routes.applicationCommands(this.framework.settings.discordClientOptions.clientId), { body: commands });
|
|
158
|
+
console.debug(`Successfully reloaded ${data.length} of ${commands.length} application (/) commands.`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class EventManager {
|
|
2
|
+
eventEmitters: Map<string, any>;
|
|
3
|
+
addEventEmitter(name: string, eventEmitter: any): void;
|
|
4
|
+
getEventEmitter(name: string): any;
|
|
5
|
+
removeEventEmitter(name: string): void;
|
|
6
|
+
emitEvent(eventName: string, eventEmitterName: string, ...args: any): void;
|
|
7
|
+
addEventListener(eventEmitterName: string, eventName: string, callback: any, params?: any): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class EventManager {
|
|
2
|
+
eventEmitters = new Map();
|
|
3
|
+
addEventEmitter(name, eventEmitter) {
|
|
4
|
+
this.eventEmitters.set(name, eventEmitter);
|
|
5
|
+
}
|
|
6
|
+
getEventEmitter(name) {
|
|
7
|
+
return this.eventEmitters.get(name);
|
|
8
|
+
}
|
|
9
|
+
removeEventEmitter(name) {
|
|
10
|
+
this.eventEmitters.delete(name);
|
|
11
|
+
}
|
|
12
|
+
emitEvent(eventName, eventEmitterName, ...args) {
|
|
13
|
+
const eventEmitter = this.getEventEmitter(eventEmitterName);
|
|
14
|
+
if (!eventEmitter)
|
|
15
|
+
throw new Error(`EventEmitter ${eventEmitterName} not found`);
|
|
16
|
+
eventEmitter.emit(eventName, ...args);
|
|
17
|
+
}
|
|
18
|
+
addEventListener(eventEmitterName, eventName, callback, params) {
|
|
19
|
+
const eventEmitter = this.getEventEmitter(eventEmitterName);
|
|
20
|
+
if (!eventEmitter)
|
|
21
|
+
throw new Error(`EventEmitter ${eventEmitterName} not found`);
|
|
22
|
+
const method = params?.once ? 'once' : 'on';
|
|
23
|
+
eventEmitter[method](eventName, (...args) => {
|
|
24
|
+
callback(...args);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SelectMenuIdParams {
|
|
2
|
+
id: string;
|
|
3
|
+
params?: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare class InteractionIdGenerator {
|
|
6
|
+
module: string;
|
|
7
|
+
command: string;
|
|
8
|
+
constructor(module?: string, command?: string);
|
|
9
|
+
protected generatePrefix(): string;
|
|
10
|
+
generateSelectMenuId(id: string, params?: string[]): string;
|
|
11
|
+
generateButtonId(id: string, params?: string[]): string;
|
|
12
|
+
generateModalId(id: string, params?: string[]): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export class InteractionIdGenerator {
|
|
2
|
+
module;
|
|
3
|
+
command;
|
|
4
|
+
constructor(module, command) {
|
|
5
|
+
this.module = module;
|
|
6
|
+
this.command = command;
|
|
7
|
+
}
|
|
8
|
+
generatePrefix() {
|
|
9
|
+
const components = [];
|
|
10
|
+
if (this.module)
|
|
11
|
+
components.push(this.module);
|
|
12
|
+
if (this.command)
|
|
13
|
+
components.push(this.command);
|
|
14
|
+
return components.join('.');
|
|
15
|
+
}
|
|
16
|
+
generateSelectMenuId(id, params) {
|
|
17
|
+
let components = [this.generatePrefix()];
|
|
18
|
+
if (id)
|
|
19
|
+
components.push(id);
|
|
20
|
+
if (params)
|
|
21
|
+
components = components.concat(params);
|
|
22
|
+
return components.join('.');
|
|
23
|
+
}
|
|
24
|
+
generateButtonId(id, params) {
|
|
25
|
+
let components = [this.generatePrefix()];
|
|
26
|
+
if (id)
|
|
27
|
+
components.push(id);
|
|
28
|
+
if (params)
|
|
29
|
+
components = components.concat(params);
|
|
30
|
+
return components.join('.');
|
|
31
|
+
}
|
|
32
|
+
generateModalId(id, params) {
|
|
33
|
+
let components = [this.generatePrefix()];
|
|
34
|
+
if (id)
|
|
35
|
+
components.push(id);
|
|
36
|
+
if (params)
|
|
37
|
+
components = components.concat(params);
|
|
38
|
+
return components.join('.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ZumitoFramework } from "../ZumitoFramework.js";
|
|
2
|
+
import { Module } from "../definitions/Module.js";
|
|
3
|
+
export declare class ModuleManager {
|
|
4
|
+
protected modules: Map<string, Module>;
|
|
5
|
+
protected framework: ZumitoFramework;
|
|
6
|
+
constructor(framework: ZumitoFramework);
|
|
7
|
+
set(name: string, module: Module): void;
|
|
8
|
+
get(name: string): Module;
|
|
9
|
+
getAll(): Map<string, Module>;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
get size(): number;
|
|
14
|
+
loadModuleFile(folderPath: string): Promise<unknown>;
|
|
15
|
+
registerModule(module: InstanceType<typeof Module>): void;
|
|
16
|
+
instanceModule(module: any, rootPath: string, name?: string): Promise<Module>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Module } from "../definitions/Module.js";
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
export class ModuleManager {
|
|
5
|
+
modules;
|
|
6
|
+
framework;
|
|
7
|
+
constructor(framework) {
|
|
8
|
+
this.modules = new Map();
|
|
9
|
+
this.framework = framework;
|
|
10
|
+
}
|
|
11
|
+
set(name, module) {
|
|
12
|
+
this.modules.set(name, module);
|
|
13
|
+
}
|
|
14
|
+
get(name) {
|
|
15
|
+
return this.modules.get(name);
|
|
16
|
+
}
|
|
17
|
+
getAll() {
|
|
18
|
+
return this.modules;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated
|
|
22
|
+
*/
|
|
23
|
+
get size() {
|
|
24
|
+
return this.modules.size;
|
|
25
|
+
}
|
|
26
|
+
async loadModuleFile(folderPath) {
|
|
27
|
+
let file;
|
|
28
|
+
if (fs.existsSync(path.join(folderPath, 'index.js'))) {
|
|
29
|
+
file = path.join(folderPath, 'index.js');
|
|
30
|
+
}
|
|
31
|
+
else if (fs.existsSync(path.join(folderPath, 'index.ts'))) {
|
|
32
|
+
file = path.join(folderPath, 'index.ts');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return Module;
|
|
36
|
+
}
|
|
37
|
+
const module = await import('file://' + file);
|
|
38
|
+
return Object.values(module)[0];
|
|
39
|
+
}
|
|
40
|
+
registerModule(module) {
|
|
41
|
+
// Register module commands
|
|
42
|
+
if (module.getCommands()) {
|
|
43
|
+
module.getCommands().forEach((command) => {
|
|
44
|
+
this.framework.commands.set(command.name, command);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Register module events
|
|
48
|
+
this.framework.events = new Map([...this.framework.events, ...module.getEvents()]);
|
|
49
|
+
// Register models
|
|
50
|
+
module.getModels().forEach((model) => {
|
|
51
|
+
this.framework.models.push(model);
|
|
52
|
+
});
|
|
53
|
+
/*
|
|
54
|
+
|
|
55
|
+
// Register module routes
|
|
56
|
+
this.routes = new Map([...this.routes, ...moduleInstance.getRoutes()]);
|
|
57
|
+
|
|
58
|
+
*/
|
|
59
|
+
}
|
|
60
|
+
async instanceModule(module, rootPath, name) {
|
|
61
|
+
let moduleInstance;
|
|
62
|
+
if (module.constructor) {
|
|
63
|
+
try {
|
|
64
|
+
moduleInstance = new module(rootPath, this.framework);
|
|
65
|
+
await moduleInstance.initialize();
|
|
66
|
+
this.modules.set(name || moduleInstance.constructor.name, moduleInstance);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error(`[📦🔴] Error loading module ${name || moduleInstance?.constructor?.name}: ${err.message}`);
|
|
70
|
+
console.error(err.stack);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
//moduleInstance = new Module();
|
|
75
|
+
}
|
|
76
|
+
return moduleInstance;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PresenceData } from "discord.js";
|
|
2
|
-
import { StatusManagerOptions } from "../
|
|
2
|
+
import { StatusManagerOptions } from "../definitions/StatusManagerOptions";
|
|
3
3
|
import { ZumitoFramework } from "../ZumitoFramework";
|
|
4
4
|
export declare class StatusManager {
|
|
5
5
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Translation } from '../definitions/Translation.js';
|
|
2
|
+
export declare class TranslationManager {
|
|
3
|
+
private translations;
|
|
4
|
+
private defaultLanguage;
|
|
5
|
+
private languages;
|
|
6
|
+
get(key: string, language?: string, params?: unknown): string;
|
|
7
|
+
set(key: string, language: string, text: string): void;
|
|
8
|
+
has(key: string): boolean;
|
|
9
|
+
getAll(): Map<string, Translation>;
|
|
10
|
+
setAll(translations: Map<string, Translation>): void;
|
|
11
|
+
getDefaultLanguage(): string;
|
|
12
|
+
setDefaultLanguage(language: string): void;
|
|
13
|
+
getLanguages(): string[];
|
|
14
|
+
importTranslationsJson(path: string, lang: string, json: object | string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Returns content of translation json file
|
|
17
|
+
* @async
|
|
18
|
+
* @public
|
|
19
|
+
* @param filePath - Absolute path to translations file
|
|
20
|
+
* @returns {Promise<any>}
|
|
21
|
+
*/
|
|
22
|
+
loadTranslationFile(filePath: string): Promise<object>;
|
|
23
|
+
/**
|
|
24
|
+
* load translation files from folder and subfolders
|
|
25
|
+
* @async
|
|
26
|
+
* @public
|
|
27
|
+
* @param folderPath - Absolute path to translations files folder
|
|
28
|
+
* @param [baseKey=''] - (Optional) the translation key to start from. All translations loaded will be children translations of that key
|
|
29
|
+
* @param watch - Watch folder for file modifications
|
|
30
|
+
* @returns {Promise<void>}
|
|
31
|
+
*/
|
|
32
|
+
registerTranslationsFromFolder(folderPath: string, baseKey?: string, watch?: boolean): Promise<void>;
|
|
33
|
+
watchTranslationFolder(folderPath: string, baseKey: string): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Translation } from '../definitions/Translation.js';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import * as chokidar from 'chokidar';
|
|
5
|
+
import boxen from 'boxen';
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
export class TranslationManager {
|
|
8
|
+
translations = new Map();
|
|
9
|
+
defaultLanguage = 'en';
|
|
10
|
+
languages = [];
|
|
11
|
+
get(key, language, params) {
|
|
12
|
+
if (this.translations.has(key)) {
|
|
13
|
+
return this.translations.get(key).get(language, params);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return key;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
set(key, language, text) {
|
|
20
|
+
if (!this.translations.has(key)) {
|
|
21
|
+
this.translations.set(key, new Translation());
|
|
22
|
+
}
|
|
23
|
+
this.translations.get(key).set(language, text);
|
|
24
|
+
if (!this.languages.includes(language))
|
|
25
|
+
this.languages.push(language);
|
|
26
|
+
}
|
|
27
|
+
has(key) {
|
|
28
|
+
return this.translations.has(key);
|
|
29
|
+
}
|
|
30
|
+
getAll() {
|
|
31
|
+
return this.translations;
|
|
32
|
+
}
|
|
33
|
+
setAll(translations) {
|
|
34
|
+
this.translations = translations;
|
|
35
|
+
}
|
|
36
|
+
getDefaultLanguage() {
|
|
37
|
+
return this.defaultLanguage;
|
|
38
|
+
}
|
|
39
|
+
setDefaultLanguage(language) {
|
|
40
|
+
this.defaultLanguage = language;
|
|
41
|
+
}
|
|
42
|
+
getLanguages() {
|
|
43
|
+
return this.languages;
|
|
44
|
+
}
|
|
45
|
+
importTranslationsJson(path, lang, json) {
|
|
46
|
+
if (typeof json === 'object') {
|
|
47
|
+
for (const key in json) {
|
|
48
|
+
this.importTranslationsJson(path + key + '.', lang, json[key]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.set(path.slice(0, -1), lang, json);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns content of translation json file
|
|
57
|
+
* @async
|
|
58
|
+
* @public
|
|
59
|
+
* @param filePath - Absolute path to translations file
|
|
60
|
+
* @returns {Promise<any>}
|
|
61
|
+
*/
|
|
62
|
+
async loadTranslationFile(filePath) {
|
|
63
|
+
const json = fs.readFileSync(filePath);
|
|
64
|
+
return JSON.parse(json);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* load translation files from folder and subfolders
|
|
68
|
+
* @async
|
|
69
|
+
* @public
|
|
70
|
+
* @param folderPath - Absolute path to translations files folder
|
|
71
|
+
* @param [baseKey=''] - (Optional) the translation key to start from. All translations loaded will be children translations of that key
|
|
72
|
+
* @param watch - Watch folder for file modifications
|
|
73
|
+
* @returns {Promise<void>}
|
|
74
|
+
*/
|
|
75
|
+
async registerTranslationsFromFolder(folderPath, baseKey = '', watch = false) {
|
|
76
|
+
if (!fs.existsSync(path.join(folderPath)))
|
|
77
|
+
return;
|
|
78
|
+
const files = fs.readdirSync(folderPath);
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
if (file.endsWith('.json')) {
|
|
81
|
+
const json = await this.loadTranslationFile(path.join(folderPath, file));
|
|
82
|
+
const lang = file.slice(0, -5);
|
|
83
|
+
this.importTranslationsJson(baseKey, lang, json);
|
|
84
|
+
}
|
|
85
|
+
else if (fs
|
|
86
|
+
.lstatSync(path.join(folderPath, file))
|
|
87
|
+
.isDirectory()) {
|
|
88
|
+
const key = baseKey + path.basename(path.join(folderPath, file)) + '.';
|
|
89
|
+
await this.registerTranslationsFromFolder(path.join(folderPath, file), key, watch);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (watch) {
|
|
93
|
+
this.watchTranslationFolder(folderPath, baseKey);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
watchTranslationFolder(folderPath, baseKey) {
|
|
97
|
+
chokidar
|
|
98
|
+
.watch(path.resolve(folderPath), {
|
|
99
|
+
ignored: /^\./,
|
|
100
|
+
persistent: true,
|
|
101
|
+
ignoreInitial: true,
|
|
102
|
+
})
|
|
103
|
+
.on('add', async (filePath) => {
|
|
104
|
+
const json = await this.loadTranslationFile(filePath);
|
|
105
|
+
const lang = filePath.replace(/^.*[\\/]/, '').slice(0, -5);
|
|
106
|
+
this.importTranslationsJson(baseKey, lang, json);
|
|
107
|
+
console.debug('[🆕🟢 ] Translations file ' + chalk.blue(filePath) + ' loaded');
|
|
108
|
+
})
|
|
109
|
+
.on('change', async (filePath) => {
|
|
110
|
+
const json = await this.loadTranslationFile(filePath);
|
|
111
|
+
const lang = filePath.replace(/^.*[\\/]/, '').slice(0, -5);
|
|
112
|
+
this.importTranslationsJson(baseKey, lang, json);
|
|
113
|
+
console.debug('[🆕🟢 ] Translations file ' + chalk.blue(filePath) + ' loaded');
|
|
114
|
+
})
|
|
115
|
+
.on('error', (error) => {
|
|
116
|
+
console.error('[🔄🔴 ] Error reloading translation file');
|
|
117
|
+
console.log(boxen(error + '\n' + error.stack, { padding: 1 }));
|
|
118
|
+
});
|
|
119
|
+
// TODO: Handle file removal
|
|
120
|
+
//.on('unlink', function(path) {console.log('File', path, 'has been removed');})
|
|
121
|
+
}
|
|
122
|
+
}
|