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.
Files changed (76) hide show
  1. package/dist/ZumitoFramework.d.ts +20 -12
  2. package/dist/ZumitoFramework.js +36 -61
  3. package/dist/{types → definitions}/Module.d.ts +6 -8
  4. package/dist/definitions/Module.js +129 -0
  5. package/dist/{types → definitions}/Translation.d.ts +0 -1
  6. package/dist/{types → definitions}/Translation.js +0 -1
  7. package/dist/{types → definitions/commands}/Command.d.ts +1 -1
  8. package/dist/{types → definitions/commands}/CommandParameters.d.ts +1 -1
  9. package/dist/{types → definitions/parameters}/EventParameters.d.ts +1 -1
  10. package/dist/{types/Commands → definitions/parameters}/SelectMenu.d.ts +1 -1
  11. package/dist/{types → definitions/parameters}/SelectMenuParameters.d.ts +1 -1
  12. package/dist/index.d.ts +21 -21
  13. package/dist/index.js +13 -13
  14. package/dist/{baseModule/events/discord/interactionCreate.d.ts → modules/core/baseModule/events/discord/InteractionCreate.d.ts} +3 -3
  15. package/dist/{baseModule/events/discord/interactionCreate.js → modules/core/baseModule/events/discord/InteractionCreate.js} +28 -21
  16. package/dist/{baseModule/events/discord/messageCreate.d.ts → modules/core/baseModule/events/discord/MessageCreate.d.ts} +3 -3
  17. package/dist/{baseModule/events/discord/messageCreate.js → modules/core/baseModule/events/discord/MessageCreate.js} +8 -10
  18. package/dist/{baseModule → modules/core/baseModule}/models/Guild.d.ts +1 -1
  19. package/dist/{baseModule → modules/core/baseModule}/models/Guild.js +1 -1
  20. package/dist/services/CommandManager.d.ts +40 -0
  21. package/dist/services/CommandManager.js +160 -0
  22. package/dist/services/EventManager.d.ts +8 -0
  23. package/dist/services/EventManager.js +27 -0
  24. package/dist/services/InteractionIdGenerator.d.ts +13 -0
  25. package/dist/services/InteractionIdGenerator.js +40 -0
  26. package/dist/services/ModuleManager.d.ts +17 -0
  27. package/dist/services/ModuleManager.js +78 -0
  28. package/dist/{managers → services}/StatusManager.d.ts +1 -1
  29. package/dist/services/TranslationManager.d.ts +34 -0
  30. package/dist/services/TranslationManager.js +122 -0
  31. package/package.json +9 -4
  32. package/dist/TranslationManager.d.ts +0 -15
  33. package/dist/TranslationManager.js +0 -41
  34. package/dist/baseModule/BaseModule.d.ts +0 -6
  35. package/dist/baseModule/BaseModule.js +0 -16
  36. package/dist/baseModule/index.d.ts +0 -7
  37. package/dist/baseModule/index.js +0 -19
  38. package/dist/types/Commands.d.ts +0 -23
  39. package/dist/types/Commands.js +0 -26
  40. package/dist/types/Module.js +0 -211
  41. /package/dist/{types → definitions}/DatabaseModel.d.ts +0 -0
  42. /package/dist/{types → definitions}/DatabaseModel.js +0 -0
  43. /package/dist/{types → definitions}/FrameworkEvent.d.ts +0 -0
  44. /package/dist/{types → definitions}/FrameworkEvent.js +0 -0
  45. /package/dist/{types → definitions}/FrameworkSettings.d.ts +0 -0
  46. /package/dist/{types → definitions}/FrameworkSettings.js +0 -0
  47. /package/dist/{types → definitions}/StatusManagerOptions.d.ts +0 -0
  48. /package/dist/{types → definitions}/StatusManagerOptions.js +0 -0
  49. /package/dist/definitions/{ApiResponse.d.ts → api/ApiResponse.d.ts} +0 -0
  50. /package/dist/definitions/{ApiResponse.js → api/ApiResponse.js} +0 -0
  51. /package/dist/{types → definitions/commands}/Command.js +0 -0
  52. /package/dist/{types → definitions/commands}/CommandArgDefinition.d.ts +0 -0
  53. /package/dist/{types → definitions/commands}/CommandArgDefinition.js +0 -0
  54. /package/dist/{types → definitions/commands}/CommandArguments.d.ts +0 -0
  55. /package/dist/{types → definitions/commands}/CommandArguments.js +0 -0
  56. /package/dist/{types → definitions/commands}/CommandChoiceDefinition.d.ts +0 -0
  57. /package/dist/{types → definitions/commands}/CommandChoiceDefinition.js +0 -0
  58. /package/dist/{types → definitions/commands}/CommandParameters.js +0 -0
  59. /package/dist/{types → definitions/commands}/CommandType.d.ts +0 -0
  60. /package/dist/{types → definitions/commands}/CommandType.js +0 -0
  61. /package/dist/{types/Commands → definitions/parameters}/ButtonPressed.d.ts +0 -0
  62. /package/dist/{types/Commands → definitions/parameters}/ButtonPressed.js +0 -0
  63. /package/dist/{types/Commands → definitions/parameters}/ButtonPressedParams.d.ts +0 -0
  64. /package/dist/{types/Commands → definitions/parameters}/ButtonPressedParams.js +0 -0
  65. /package/dist/{types → definitions/parameters}/EventParameters.js +0 -0
  66. /package/dist/{types/Commands → definitions/parameters}/SelectMenu.js +0 -0
  67. /package/dist/{types → definitions/parameters}/SelectMenuParameters.js +0 -0
  68. /package/dist/{utils → services}/DatabaseConfigLoader.d.ts +0 -0
  69. /package/dist/{utils → services}/DatabaseConfigLoader.js +0 -0
  70. /package/dist/{utils → services}/EmojiFallback.d.ts +0 -0
  71. /package/dist/{utils → services}/EmojiFallback.js +0 -0
  72. /package/dist/{managers → services}/EmojiManager.d.ts +0 -0
  73. /package/dist/{managers → services}/EmojiManager.js +0 -0
  74. /package/dist/{managers → services}/StatusManager.js +0 -0
  75. /package/dist/{utils → services}/TextFormatter.d.ts +0 -0
  76. /package/dist/{utils → services}/TextFormatter.js +0 -0
@@ -1,9 +1,9 @@
1
1
  import { ActionRowBuilder, EmbedBuilder } from 'discord.js';
2
- import { EventParameters } from '../../../types/EventParameters.js';
3
- import { FrameworkEvent } from '../../../types/FrameworkEvent.js';
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, client, framework }: EventParameters): Promise<import("discord.js").Message<boolean>>;
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 '../../../types/FrameworkEvent.js';
5
- import { ZumitoFramework } from '../../../ZumitoFramework.js';
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, client, framework }) {
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) => {
@@ -1,4 +1,4 @@
1
- import { DatabaseModel } from '../../types/DatabaseModel.js';
1
+ import { DatabaseModel } from '../../../../definitions/DatabaseModel.js';
2
2
  export declare class Guild extends DatabaseModel {
3
3
  getModel(schema: any): {
4
4
  guild_id: {
@@ -1,4 +1,4 @@
1
- import { DatabaseModel } from '../../types/DatabaseModel.js';
1
+ import { DatabaseModel } from '../../../../definitions/DatabaseModel.js';
2
2
  export class Guild extends DatabaseModel {
3
3
  getModel(schema) {
4
4
  return {
@@ -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 "../types/StatusManagerOptions";
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
+ }