zumito-framework 1.2.5 → 1.2.7

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.
@@ -144,58 +144,19 @@ export declare class ZumitoFramework {
144
144
  */
145
145
  private initializeDiscordClient;
146
146
  /**
147
- * From a command-line string, returns an array of parameters.
148
- * @param commandLine
149
- * @returns {string[]}
150
- * @private
151
- * @static
152
- * @example
153
- * // returns ['a', 'b', 'c']
154
- * splitCommandLine('a b c');
155
- * @example
156
- * // returns ['a', 'b c']
157
- * splitCommandLine('a "b c"');
147
+ * @deprecated use CommandParser service instead
158
148
  */
159
149
  static splitCommandLine(commandLine: any): any;
160
150
  /**
161
- * Checks if a member has a permission in a channel.
162
- * @param member
163
- * @param channel
164
- * @param permission
165
- * @returns {Promise<boolean>}
166
- * @public
167
- * @example
168
- * // returns true if the member has the permission
169
- * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES);
170
- * @example
171
- * // returns true if the member has the permission
172
- * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES | Permissions.FLAGS.MANAGE_CHANNELS);
173
- * @example
174
- */
175
- memberHasPermission(member: GuildMember, channel: TextChannel, permission: bigint): Promise<boolean>;
176
- /**
177
- * Gets the guild settings from the database.
178
- * If the guild is not in the database, it is added.
179
- * @param guildId
180
- * @returns {Promise<any>}
181
- * @public
182
- * @async
183
- * @example
184
- * // returns the guild settings
185
- * getGuildSettings('123456789012345678');
186
- * @example
187
- * // returns the guild settings
188
- * getGuildSettings(guild.id);
189
- * @example
190
- * // returns the guild settings
191
- * getGuildSettings(message.guild.id);
192
- * @example
193
- * // returns the guild settings
194
- * getGuildSettings(interaction.guild.id);
195
- * @example
196
- * // returns the guild settings
197
- * getGuildSettings(interaction.guildId);
151
+ * @deprecated use MemberPermissionChecker service
152
+ */
153
+ memberHasPermission(member: GuildMember, channel: TextChannel, permission: bigint): Promise<any>;
154
+ /**
155
+ * @deprecated use GuildDataGetter service
198
156
  */
199
157
  getGuildSettings(guildId: string): Promise<unknown>;
158
+ /**
159
+ * @deprecated
160
+ */
200
161
  refreshSlashCommands(): Promise<void>;
201
162
  }
@@ -1,11 +1,8 @@
1
1
  import * as fs from 'fs';
2
2
  import * as url from 'url';
3
- import { Client, SlashCommandBuilder, } from 'discord.js';
3
+ import { Client, } from 'discord.js';
4
4
  import { ApiResponse } from './definitions/api/ApiResponse.js';
5
- import { CommandType } from './definitions/commands/CommandType.js';
6
5
  import { EventEmitter } from 'events';
7
- import { REST } from '@discordjs/rest';
8
- import { Routes } from 'discord-api-types/v9';
9
6
  import { StatusManager } from './services/StatusManager.js';
10
7
  import { TranslationManager } from './services/TranslationManager.js';
11
8
  import { betterLogging } from 'better-logging';
@@ -18,6 +15,12 @@ import path from 'path';
18
15
  import { EventManager } from './services/EventManager.js';
19
16
  import { CommandManager } from './services/CommandManager.js';
20
17
  import { ModuleManager } from './services/ModuleManager.js';
18
+ import { ServiceContainer } from './services/ServiceContainer.js';
19
+ import { GuildDataGetter } from './services/GuildDataGetter.js';
20
+ import { RecursiveObjectMerger } from './services/RecursiveObjectMerger.js';
21
+ import { MemberPermissionChecker } from './services/MemberPermissionChecker.js';
22
+ import { CommandParser } from './services/CommandParser.js';
23
+ import { SlashCommandRefresher } from './services/SlashCommandRefresher.js';
21
24
  // import better-logging
22
25
  betterLogging(console);
23
26
  /**
@@ -135,6 +138,9 @@ export class ZumitoFramework {
135
138
  if (settings.logLevel) {
136
139
  console.logLevel = settings.logLevel;
137
140
  }
141
+ // Register this class instance to service container
142
+ ServiceContainer.addService(ZumitoFramework, [], true, this);
143
+ ServiceContainer.addService(TranslationManager, [], true, this.translations);
138
144
  this.initialize()
139
145
  .then(() => {
140
146
  if (callback)
@@ -234,13 +240,16 @@ export class ZumitoFramework {
234
240
  else if (fs.existsSync(`${process.cwd()}/src/modules`)) {
235
241
  modulesFolder = `${process.cwd()}/src/modules`;
236
242
  }
237
- else
238
- return;
239
243
  const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
240
244
  await this.registerModule(path.join(__dirname, 'modules', 'core'), 'baseModule');
241
- const files = fs.readdirSync(modulesFolder);
242
- for (const file of files) {
243
- await this.registerModule(modulesFolder, file);
245
+ if (modulesFolder) {
246
+ const files = fs.readdirSync(modulesFolder);
247
+ for (const file of files) {
248
+ await this.registerModule(modulesFolder, file);
249
+ }
250
+ }
251
+ else if (this.settings.srcMode == 'monoBundle') {
252
+ await this.registerModule(process.cwd(), 'src');
244
253
  }
245
254
  // Define models
246
255
  const schemas = {};
@@ -249,7 +258,7 @@ export class ZumitoFramework {
249
258
  schemas[model.name] = model.getModel(this.database);
250
259
  }
251
260
  else {
252
- schemas[model.name] = MergeRecursive(schemas[model.name], model.getModel(this.database));
261
+ schemas[model.name] = RecursiveObjectMerger.merge(schemas[model.name], model.getModel(this.database));
253
262
  }
254
263
  });
255
264
  Object.keys(schemas).forEach((schemaName) => {
@@ -278,6 +287,7 @@ export class ZumitoFramework {
278
287
  intents: this.settings.discordClientOptions.intents,
279
288
  });
280
289
  this.client.login(this.settings.discordClientOptions.token);
290
+ ServiceContainer.addService(Client, [], true, this.client);
281
291
  await new Promise((resolve) => {
282
292
  this.client.on('ready', () => {
283
293
  // Bot emoji
@@ -287,182 +297,30 @@ export class ZumitoFramework {
287
297
  });
288
298
  }
289
299
  /**
290
- * From a command-line string, returns an array of parameters.
291
- * @param commandLine
292
- * @returns {string[]}
293
- * @private
294
- * @static
295
- * @example
296
- * // returns ['a', 'b', 'c']
297
- * splitCommandLine('a b c');
298
- * @example
299
- * // returns ['a', 'b c']
300
- * splitCommandLine('a "b c"');
300
+ * @deprecated use CommandParser service instead
301
301
  */
302
302
  static splitCommandLine(commandLine) {
303
- //log( 'commandLine', commandLine ) ;
304
- // Find a unique marker for the space character.
305
- // Start with '<SP>' and repeatedly append '@' if necessary to make it unique.
306
- let spaceMarker = '<SP>';
307
- while (commandLine.indexOf(spaceMarker) > -1)
308
- spaceMarker += '@';
309
- // Protect double-quoted strings.
310
- // o Find strings of non-double-quotes, wrapped in double-quotes.
311
- // o The final double-quote is optional to allow for an unterminated string.
312
- // o Replace each double-quoted-string with what's inside the qouble-quotes,
313
- // after each space character has been replaced with the space-marker above.
314
- // o The outer double-quotes will not be present.
315
- const noSpacesInQuotes = commandLine.replace(/"([^"]*)"?/g, (fullMatch, capture) => {
316
- return capture.replace(/ /g, spaceMarker);
317
- });
318
- // Now that it is safe to do so, split the command-line at one-or-more spaces.
319
- const mangledParamArray = noSpacesInQuotes.split(/ +/);
320
- // Create a new array by restoring spaces from any space-markers.
321
- const paramArray = mangledParamArray.map((mangledParam) => {
322
- return mangledParam.replace(RegExp(spaceMarker, 'g'), ' ');
323
- });
324
- return paramArray;
303
+ return CommandParser.splitCommandLine(commandLine);
325
304
  }
326
305
  /**
327
- * Checks if a member has a permission in a channel.
328
- * @param member
329
- * @param channel
330
- * @param permission
331
- * @returns {Promise<boolean>}
332
- * @public
333
- * @example
334
- * // returns true if the member has the permission
335
- * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES);
336
- * @example
337
- * // returns true if the member has the permission
338
- * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES | Permissions.FLAGS.MANAGE_CHANNELS);
339
- * @example
306
+ * @deprecated use MemberPermissionChecker service
340
307
  */
341
308
  async memberHasPermission(member, channel, permission) {
342
- const memberPermission = await channel.permissionsFor(member);
343
- return memberPermission.has(permission);
309
+ const memberPermissionChecker = ServiceContainer.getService(MemberPermissionChecker);
310
+ return await memberPermissionChecker(member, channel, permission);
344
311
  }
345
312
  /**
346
- * Gets the guild settings from the database.
347
- * If the guild is not in the database, it is added.
348
- * @param guildId
349
- * @returns {Promise<any>}
350
- * @public
351
- * @async
352
- * @example
353
- * // returns the guild settings
354
- * getGuildSettings('123456789012345678');
355
- * @example
356
- * // returns the guild settings
357
- * getGuildSettings(guild.id);
358
- * @example
359
- * // returns the guild settings
360
- * getGuildSettings(message.guild.id);
361
- * @example
362
- * // returns the guild settings
363
- * getGuildSettings(interaction.guild.id);
364
- * @example
365
- * // returns the guild settings
366
- * getGuildSettings(interaction.guildId);
313
+ * @deprecated use GuildDataGetter service
367
314
  */
368
315
  async getGuildSettings(guildId) {
369
- const Guild = this.database.models.Guild;
370
- return await new Promise((resolve, reject) => {
371
- Guild.findOne({ where: { guild_id: guildId } }, (err, guild) => {
372
- if (err)
373
- reject(err);
374
- if (guild == null) {
375
- guild = new Guild({
376
- guild_id: guildId,
377
- });
378
- guild.save((err) => {
379
- if (err)
380
- reject(err);
381
- resolve(guild);
382
- });
383
- }
384
- else {
385
- resolve(guild);
386
- }
387
- });
388
- });
316
+ const guildDataGetter = ServiceContainer.getService(GuildDataGetter);
317
+ return await guildDataGetter.getGuildSettings(guildId);
389
318
  }
319
+ /**
320
+ * @deprecated
321
+ */
390
322
  async refreshSlashCommands() {
391
- const rest = new REST({ version: '10' }).setToken(this.settings.discordClientOptions.token);
392
- const commands = Array.from(this.commands.getAll().values())
393
- .filter((command) => command.type == CommandType.slash ||
394
- command.type == CommandType.separated ||
395
- command.type == CommandType.any)
396
- .map((command) => {
397
- const slashCommand = new SlashCommandBuilder()
398
- .setName(command.name)
399
- .setDescription(this.translations.get('command.' + command.name + '.description', 'en'));
400
- if (command.args) {
401
- command.args.forEach((arg) => {
402
- let method;
403
- switch (arg.type) {
404
- case 'string':
405
- method = 'addStringOption';
406
- break;
407
- case 'user':
408
- case 'member':
409
- method = 'addUserOption';
410
- break;
411
- case 'channel':
412
- method = 'addChannelOption';
413
- break;
414
- case 'role':
415
- method = 'addRoleOption';
416
- break;
417
- default:
418
- throw new Error('Invalid argument type ' + arg.type);
419
- }
420
- slashCommand[method]((option) => {
421
- option.setName(arg.name);
422
- option.setDescription(this.translations.get('command.' +
423
- command.name +
424
- '.args.' +
425
- arg.name +
426
- '.description', 'en'));
427
- option.setRequired(!arg.optional);
428
- if (arg.choices) {
429
- // if arg.choices is function, call it
430
- if (typeof arg.choices == 'function') {
431
- arg.choices =
432
- arg.choices();
433
- }
434
- arg.choices.forEach((choice) => {
435
- option.addChoices({
436
- name: choice.name,
437
- value: choice.value,
438
- });
439
- });
440
- }
441
- return option;
442
- });
443
- });
444
- }
445
- return slashCommand.toJSON();
446
- });
447
- const data = await rest.put(Routes.applicationCommands(this.settings.discordClientOptions.clientId), { body: commands });
448
- console.debug(`Successfully reloaded ${data.length} of ${commands.length} application (/) commands.`);
449
- }
450
- }
451
- function MergeRecursive(obj1, obj2) {
452
- for (const p in obj2) {
453
- try {
454
- // Property in destination object set; update its value.
455
- if (obj2[p].constructor == Object) {
456
- obj1[p] = MergeRecursive(obj1[p], obj2[p]);
457
- }
458
- else {
459
- obj1[p] = obj2[p];
460
- }
461
- }
462
- catch (e) {
463
- // Property in destination object not set; create it and set its value.
464
- obj1[p] = obj2[p];
465
- }
323
+ const slashCommandRefresher = ServiceContainer.getService(SlashCommandRefresher);
324
+ slashCommandRefresher.refreshSlashCommands();
466
325
  }
467
- return obj1;
468
326
  }
@@ -10,4 +10,5 @@ export interface FrameworkSettings {
10
10
  };
11
11
  defaultPrefix?: string;
12
12
  statusOptions?: StatusManagerOptions;
13
+ srcMode?: 'multiBundle' | 'monoBundle' | undefined;
13
14
  }
@@ -12,7 +12,13 @@ export interface CommandParameters {
12
12
  message?: Message;
13
13
  interaction?: CommandInteraction;
14
14
  args: Map<string, any>;
15
+ /**
16
+ * @deprecated The client should be obtained from `ServiceContainer.get(Client);`
17
+ */
15
18
  client: Client;
19
+ /**
20
+ * @deprecated The frameworkInstance should be obtained from `ServiceContainer.get(ZumitoFramework);`
21
+ */
16
22
  framework: ZumitoFramework;
17
23
  guildSettings?: any;
18
24
  trans: (key: string, params?: any) => string;
package/dist/index.d.ts CHANGED
@@ -21,4 +21,8 @@ import { TranslationManager } from './services/TranslationManager.js';
21
21
  import { ZumitoFramework } from './ZumitoFramework.js';
22
22
  import * as discord from 'discord.js';
23
23
  import { EventParameters } from './definitions/parameters/EventParameters.js';
24
- export { ZumitoFramework, FrameworkSettings, Command, Module, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, };
24
+ import { ServiceContainer } from './services/ServiceContainer.js';
25
+ import { GuildDataGetter } from './services/GuildDataGetter.js';
26
+ import { CommandParser } from './services/CommandParser.js';
27
+ import { SlashCommandRefresher } from './services/SlashCommandRefresher.js';
28
+ export { ZumitoFramework, FrameworkSettings, Command, Module, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, };
package/dist/index.js CHANGED
@@ -13,4 +13,15 @@ import { Translation } from './definitions/Translation.js';
13
13
  import { TranslationManager } from './services/TranslationManager.js';
14
14
  import { ZumitoFramework } from './ZumitoFramework.js';
15
15
  import * as discord from 'discord.js';
16
- export { ZumitoFramework, Command, Module, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, CommandType, ButtonPressed, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, discord, };
16
+ import { ServiceContainer } from './services/ServiceContainer.js';
17
+ import { GuildDataGetter } from './services/GuildDataGetter.js';
18
+ import { MemberPermissionChecker } from './services/MemberPermissionChecker.js';
19
+ import { CommandParser } from './services/CommandParser.js';
20
+ import { SlashCommandRefresher } from './services/SlashCommandRefresher.js';
21
+ ServiceContainer.addService(TextFormatter, []);
22
+ ServiceContainer.addService(EmojiFallback, []);
23
+ ServiceContainer.addService(GuildDataGetter, [ZumitoFramework.name]);
24
+ ServiceContainer.addService(MemberPermissionChecker, []);
25
+ ServiceContainer.addService(CommandParser, []);
26
+ ServiceContainer.addService(SlashCommandRefresher, [ZumitoFramework.name]);
27
+ export { ZumitoFramework, Command, Module, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, CommandType, ButtonPressed, TextFormatter, EmojiFallback, DatabaseConfigLoader, DatabaseModel, discord, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, };
@@ -0,0 +1,16 @@
1
+ export declare class CommandParser {
2
+ /**
3
+ * From a command-line string, returns an array of parameters.
4
+ * @param commandLine
5
+ * @returns {string[]}
6
+ * @private
7
+ * @static
8
+ * @example
9
+ * // returns ['a', 'b', 'c']
10
+ * splitCommandLine('a b c');
11
+ * @example
12
+ * // returns ['a', 'b c']
13
+ * splitCommandLine('a "b c"');
14
+ */
15
+ static splitCommandLine(commandLine: any): any;
16
+ }
@@ -0,0 +1,39 @@
1
+ export class CommandParser {
2
+ /**
3
+ * From a command-line string, returns an array of parameters.
4
+ * @param commandLine
5
+ * @returns {string[]}
6
+ * @private
7
+ * @static
8
+ * @example
9
+ * // returns ['a', 'b', 'c']
10
+ * splitCommandLine('a b c');
11
+ * @example
12
+ * // returns ['a', 'b c']
13
+ * splitCommandLine('a "b c"');
14
+ */
15
+ static splitCommandLine(commandLine) {
16
+ //log( 'commandLine', commandLine ) ;
17
+ // Find a unique marker for the space character.
18
+ // Start with '<SP>' and repeatedly append '@' if necessary to make it unique.
19
+ let spaceMarker = '<SP>';
20
+ while (commandLine.indexOf(spaceMarker) > -1)
21
+ spaceMarker += '@';
22
+ // Protect double-quoted strings.
23
+ // o Find strings of non-double-quotes, wrapped in double-quotes.
24
+ // o The final double-quote is optional to allow for an unterminated string.
25
+ // o Replace each double-quoted-string with what's inside the qouble-quotes,
26
+ // after each space character has been replaced with the space-marker above.
27
+ // o The outer double-quotes will not be present.
28
+ const noSpacesInQuotes = commandLine.replace(/"([^"]*)"?/g, (fullMatch, capture) => {
29
+ return capture.replace(/ /g, spaceMarker);
30
+ });
31
+ // Now that it is safe to do so, split the command-line at one-or-more spaces.
32
+ const mangledParamArray = noSpacesInQuotes.split(/ +/);
33
+ // Create a new array by restoring spaces from any space-markers.
34
+ const paramArray = mangledParamArray.map((mangledParam) => {
35
+ return mangledParam.replace(RegExp(spaceMarker, 'g'), ' ');
36
+ });
37
+ return paramArray;
38
+ }
39
+ }
@@ -0,0 +1,29 @@
1
+ import { ZumitoFramework } from "../ZumitoFramework";
2
+ export declare class GuildDataGetter {
3
+ framework: ZumitoFramework;
4
+ constructor(framework: ZumitoFramework);
5
+ /**
6
+ * Gets the guild settings from the database.
7
+ * If the guild is not in the database, it is added.
8
+ * @param guildId
9
+ * @returns {Promise<any>}
10
+ * @public
11
+ * @async
12
+ * @example
13
+ * // returns the guild settings
14
+ * getGuildSettings('123456789012345678');
15
+ * @example
16
+ * // returns the guild settings
17
+ * getGuildSettings(guild.id);
18
+ * @example
19
+ * // returns the guild settings
20
+ * getGuildSettings(message.guild.id);
21
+ * @example
22
+ * // returns the guild settings
23
+ * getGuildSettings(interaction.guild.id);
24
+ * @example
25
+ * // returns the guild settings
26
+ * getGuildSettings(interaction.guildId);
27
+ */
28
+ getGuildSettings(guildId: string): Promise<unknown>;
29
+ }
@@ -0,0 +1,51 @@
1
+ export class GuildDataGetter {
2
+ framework;
3
+ constructor(framework) {
4
+ this.framework = framework;
5
+ }
6
+ /**
7
+ * Gets the guild settings from the database.
8
+ * If the guild is not in the database, it is added.
9
+ * @param guildId
10
+ * @returns {Promise<any>}
11
+ * @public
12
+ * @async
13
+ * @example
14
+ * // returns the guild settings
15
+ * getGuildSettings('123456789012345678');
16
+ * @example
17
+ * // returns the guild settings
18
+ * getGuildSettings(guild.id);
19
+ * @example
20
+ * // returns the guild settings
21
+ * getGuildSettings(message.guild.id);
22
+ * @example
23
+ * // returns the guild settings
24
+ * getGuildSettings(interaction.guild.id);
25
+ * @example
26
+ * // returns the guild settings
27
+ * getGuildSettings(interaction.guildId);
28
+ */
29
+ async getGuildSettings(guildId) {
30
+ const Guild = this.framework.database.models.Guild;
31
+ return await new Promise((resolve, reject) => {
32
+ Guild.findOne({ where: { guild_id: guildId } }, (err, guild) => {
33
+ if (err)
34
+ reject(err);
35
+ if (guild == null) {
36
+ guild = new Guild({
37
+ guild_id: guildId,
38
+ });
39
+ guild.save((err) => {
40
+ if (err)
41
+ reject(err);
42
+ resolve(guild);
43
+ });
44
+ }
45
+ else {
46
+ resolve(guild);
47
+ }
48
+ });
49
+ });
50
+ }
51
+ }
@@ -0,0 +1,19 @@
1
+ import { GuildMember, TextChannel } from "discord.js";
2
+ export declare class MemberPermissionChecker {
3
+ /**
4
+ * Checks if a member has a permission in a channel.
5
+ * @param member
6
+ * @param channel
7
+ * @param permission
8
+ * @returns {Promise<boolean>}
9
+ * @public
10
+ * @example
11
+ * // returns true if the member has the permission
12
+ * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES);
13
+ * @example
14
+ * // returns true if the member has the permission
15
+ * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES | Permissions.FLAGS.MANAGE_CHANNELS);
16
+ * @example
17
+ */
18
+ hasPermissionOnChannel(member: GuildMember, channel: TextChannel, permission: bigint): Promise<boolean>;
19
+ }
@@ -0,0 +1,21 @@
1
+ export class MemberPermissionChecker {
2
+ /**
3
+ * Checks if a member has a permission in a channel.
4
+ * @param member
5
+ * @param channel
6
+ * @param permission
7
+ * @returns {Promise<boolean>}
8
+ * @public
9
+ * @example
10
+ * // returns true if the member has the permission
11
+ * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES);
12
+ * @example
13
+ * // returns true if the member has the permission
14
+ * memberHasPermission(member, channel, Permissions.FLAGS.MANAGE_MESSAGES | Permissions.FLAGS.MANAGE_CHANNELS);
15
+ * @example
16
+ */
17
+ async hasPermissionOnChannel(member, channel, permission) {
18
+ const memberPermission = await channel.permissionsFor(member);
19
+ return memberPermission.has(permission);
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ export declare class RecursiveObjectMerger {
2
+ static merge(obj1: any, obj2: any): any;
3
+ }
@@ -0,0 +1,20 @@
1
+ export class RecursiveObjectMerger {
2
+ static merge(obj1, obj2) {
3
+ for (const p in obj2) {
4
+ try {
5
+ // Property in destination object set; update its value.
6
+ if (obj2[p].constructor == Object) {
7
+ obj1[p] = this.merge(obj1[p], obj2[p]);
8
+ }
9
+ else {
10
+ obj1[p] = obj2[p];
11
+ }
12
+ }
13
+ catch (e) {
14
+ // Property in destination object not set; create it and set its value.
15
+ obj1[p] = obj2[p];
16
+ }
17
+ }
18
+ return obj1;
19
+ }
20
+ }
@@ -0,0 +1,8 @@
1
+ declare class ServiceContainerManager {
2
+ private services;
3
+ addService(serviceClass: any, dependencies: string[], singleton?: boolean, instance?: any): void;
4
+ getService(serviceClass: any): any;
5
+ addInstance(serviceClass: any, instance: any): void;
6
+ }
7
+ export declare const ServiceContainer: ServiceContainerManager;
8
+ export {};
@@ -0,0 +1,30 @@
1
+ class ServiceContainerManager {
2
+ services = new Map();
3
+ addService(serviceClass, dependencies, singleton = false, instance) {
4
+ this.services.set(serviceClass.name, {
5
+ class: serviceClass,
6
+ dependencies,
7
+ singleton,
8
+ instance
9
+ });
10
+ }
11
+ getService(serviceClass) {
12
+ const classname = typeof serviceClass === 'string' ? serviceClass : serviceClass.name;
13
+ const service = this.services.get(classname);
14
+ if (!service)
15
+ throw new Error(`Service ${classname} not found`);
16
+ if (service.singleton && service.instance)
17
+ return service.instance;
18
+ const dependencies = service.dependencies.map(dependency => this.getService(dependency));
19
+ const instance = new service.class(...dependencies);
20
+ if (service.singleton)
21
+ service.instance = instance;
22
+ return instance;
23
+ }
24
+ addInstance(serviceClass, instance) {
25
+ if (!this.services.has(serviceClass.name))
26
+ return;
27
+ this.services.get(serviceClass.name).instance = instance;
28
+ }
29
+ }
30
+ export const ServiceContainer = new ServiceContainerManager();
@@ -0,0 +1,6 @@
1
+ import { ZumitoFramework } from "../ZumitoFramework";
2
+ export declare class SlashCommandRefresher {
3
+ framework: ZumitoFramework;
4
+ constructor(framework: ZumitoFramework);
5
+ refreshSlashCommands(): Promise<void>;
6
+ }
@@ -0,0 +1,73 @@
1
+ import { REST } from '@discordjs/rest';
2
+ import { Routes } from 'discord-api-types/v9';
3
+ import { CommandType } from "../definitions/commands/CommandType";
4
+ import { SlashCommandBuilder } from "discord.js";
5
+ export class SlashCommandRefresher {
6
+ framework;
7
+ constructor(framework) {
8
+ this.framework = framework;
9
+ }
10
+ /*
11
+ * Update slash commands on discord
12
+ */
13
+ async refreshSlashCommands() {
14
+ const rest = new REST({ version: '10' }).setToken(this.framework.settings.discordClientOptions.token);
15
+ const commands = Array.from(this.framework.commands.getAll().values())
16
+ .filter((command) => command.type == CommandType.slash ||
17
+ command.type == CommandType.separated ||
18
+ command.type == CommandType.any)
19
+ .map((command) => {
20
+ const slashCommand = new SlashCommandBuilder()
21
+ .setName(command.name)
22
+ .setDescription(this.framework.translations.get('command.' + command.name + '.description', 'en'));
23
+ if (command.args) {
24
+ command.args.forEach((arg) => {
25
+ let method;
26
+ switch (arg.type) {
27
+ case 'string':
28
+ method = 'addStringOption';
29
+ break;
30
+ case 'user':
31
+ case 'member':
32
+ method = 'addUserOption';
33
+ break;
34
+ case 'channel':
35
+ method = 'addChannelOption';
36
+ break;
37
+ case 'role':
38
+ method = 'addRoleOption';
39
+ break;
40
+ default:
41
+ throw new Error('Invalid argument type ' + arg.type);
42
+ }
43
+ slashCommand[method]((option) => {
44
+ option.setName(arg.name);
45
+ option.setDescription(this.framework.translations.get('command.' +
46
+ command.name +
47
+ '.args.' +
48
+ arg.name +
49
+ '.description', 'en'));
50
+ option.setRequired(!arg.optional);
51
+ if (arg.choices) {
52
+ // if arg.choices is function, call it
53
+ if (typeof arg.choices == 'function') {
54
+ arg.choices =
55
+ arg.choices();
56
+ }
57
+ arg.choices.forEach((choice) => {
58
+ option.addChoices({
59
+ name: choice.name,
60
+ value: choice.value,
61
+ });
62
+ });
63
+ }
64
+ return option;
65
+ });
66
+ });
67
+ }
68
+ return slashCommand.toJSON();
69
+ });
70
+ const data = await rest.put(Routes.applicationCommands(this.framework.settings.discordClientOptions.clientId), { body: commands });
71
+ console.debug(`Successfully reloaded ${data.length} of ${commands.length} application (/) commands.`);
72
+ }
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zumito-framework",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Discord.js bot framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",