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.
- package/dist/ZumitoFramework.d.ts +9 -48
- package/dist/ZumitoFramework.js +33 -175
- package/dist/definitions/FrameworkSettings.d.ts +1 -0
- package/dist/definitions/commands/CommandParameters.d.ts +6 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +12 -1
- package/dist/services/CommandParser.d.ts +16 -0
- package/dist/services/CommandParser.js +39 -0
- package/dist/services/GuildDataGetter.d.ts +29 -0
- package/dist/services/GuildDataGetter.js +51 -0
- package/dist/services/MemberPermissionChecker.d.ts +19 -0
- package/dist/services/MemberPermissionChecker.js +21 -0
- package/dist/services/RecursiveObjectMerger.d.ts +3 -0
- package/dist/services/RecursiveObjectMerger.js +20 -0
- package/dist/services/ServiceContainer.d.ts +8 -0
- package/dist/services/ServiceContainer.js +30 -0
- package/dist/services/SlashCommandRefresher.d.ts +6 -0
- package/dist/services/SlashCommandRefresher.js +73 -0
- package/package.json +1 -1
|
@@ -144,58 +144,19 @@ export declare class ZumitoFramework {
|
|
|
144
144
|
*/
|
|
145
145
|
private initializeDiscordClient;
|
|
146
146
|
/**
|
|
147
|
-
*
|
|
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
|
-
*
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
* @
|
|
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
|
}
|
package/dist/ZumitoFramework.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as url from 'url';
|
|
3
|
-
import { Client,
|
|
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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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] =
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
343
|
-
return
|
|
309
|
+
const memberPermissionChecker = ServiceContainer.getService(MemberPermissionChecker);
|
|
310
|
+
return await memberPermissionChecker(member, channel, permission);
|
|
344
311
|
}
|
|
345
312
|
/**
|
|
346
|
-
*
|
|
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
|
|
370
|
-
return await
|
|
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
|
|
392
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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,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,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
|
+
}
|