From 8937987b43ce29e0800363f63a1331518ac272e6 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 20:57:40 +0530 Subject: [PATCH 001/106] ### fix github.com/OwenCalvin/discord.ts/pull/55 --- src/decorators/decorators/Permission.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index 5dbc2f7f..c86eb423 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -9,13 +9,13 @@ export function Permission(id: string, type: PermissionType) { type }; - return async ( + return ( target: Object, key: string, descriptor: PropertyDescriptor ) => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.defaultPermission = false; original.permissions = [...original.permissions, permission]; From c0b39d7500313d8e5be2aa76de2ade86b53f6380 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 21:18:02 +0530 Subject: [PATCH 002/106] fix github.com/OwenCalvin/discord.ts/pull/56 --- src/decorators/classes/DSlash.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index f9663185..2dd661f2 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -143,10 +143,6 @@ export class DSlash extends Method { parseParams(interaction: CommandInteraction) { const options = this.getLastNestedOption(interaction.options); - const values = this.options.map((opt, index) => { - return options[index]?.value; - }); - - return values; + return this.options.sort((a, b) => a.index - b.index).map((op) => options.find((o) => o.name === op.name)?.value); } } From a9ad6ee05ff0e3d5c4ad64d6e30e5417b680a80a Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 21:20:29 +0530 Subject: [PATCH 003/106] fix github.com/OwenCalvin/discord.ts/pull/58 --- src/decorators/decorators/Guild.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index 13d8cd87..cdad73ef 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -14,14 +14,14 @@ export function Guild(...guildIDs: string[]) { Modifier.create(async (original) => { original.guilds = [ ...original.guilds, - ...guildIDs + ...guildIDs.filter(guildID => !original.guilds.includes(guildID)) ]; if (original instanceof DDiscord) { original.slashes.map((slash) => { slash.guilds = [ ...slash.guilds, - ...guildIDs + ...guildIDs.filter(guildID => !slash.guilds.includes(guildID)) ]; }); } From 2138b4f80e919e2780ab1ea78482295047290914 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 21:35:21 +0530 Subject: [PATCH 004/106] fix github.com/OwenCalvin/discord.ts/pull/60 --- src/Client.ts | 12 +++++------- src/decorators/classes/DSlash.ts | 2 +- src/decorators/classes/Method.ts | 4 ++-- src/decorators/classes/Modifier.ts | 4 ++-- src/decorators/decorators/Discord.ts | 6 +++--- src/decorators/decorators/Group.ts | 2 +- src/decorators/decorators/Guild.ts | 2 +- src/decorators/decorators/Permission.ts | 2 +- src/logic/metadatas/MetadataStorage.ts | 12 ++++++------ 9 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 3aeafdd5..61c23824 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -1,6 +1,4 @@ import { - ApplicationCommandOption, - ApplicationCommandOptionData, Client as ClientJS, CommandInteraction, CommandInteractionOption, @@ -155,7 +153,7 @@ export class Client extends ClientJS { const tab = Array(depth).join(" "); - options.map((option) => { + options.forEach((option) => { console.log(`${tab}${option.name}: ${option.stringType} (${option.classRef.name}.${option.key})`); printOptions(option.options, depth + 1); }); @@ -184,7 +182,7 @@ export class Client extends ClientJS { } }); - return await super.login(token); + return super.login(token); } /** @@ -365,7 +363,7 @@ export class Client extends ClientJS { if (!slash) return; // Parse the options values and inject it into the @Slash method - return await slash.execute(interaction, this); + return slash.execute(interaction, this); } /** @@ -395,10 +393,10 @@ export class Client extends ClientJS { return; } - this._loadClasses.map((file) => { + this._loadClasses.forEach((file) => { if (typeof file === "string") { const files = Glob.sync(file); - files.map((file) => { + files.forEach((file) => { require(file); }); } diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 2dd661f2..096d6d03 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -5,7 +5,7 @@ import { CommandInteractionOption, Snowflake, } from "discord.js"; -import { DOption, Client, SubValueType, PermissionType } from "../.."; +import { DOption, Client, PermissionType } from "../.."; import { Method } from "./Method"; export class DSlash extends Method { diff --git a/src/decorators/classes/Method.ts b/src/decorators/classes/Method.ts index 3381703e..823f66b9 100644 --- a/src/decorators/classes/Method.ts +++ b/src/decorators/classes/Method.ts @@ -1,4 +1,4 @@ -import { DGuard, Client, DDiscord, DIService } from "../.."; +import { DGuard, Client, DDiscord } from "../.."; import { Decorator } from "./Decorator"; export abstract class Method extends Decorator { @@ -26,7 +26,7 @@ export abstract class Method extends Decorator { */ get execute() { return async (...params: any[]) => { - return await this.getGuardFunction()(...params); + return this.getGuardFunction()(...params); }; } diff --git a/src/decorators/classes/Modifier.ts b/src/decorators/classes/Modifier.ts index 7ee988ae..233b57af 100644 --- a/src/decorators/classes/Modifier.ts +++ b/src/decorators/classes/Modifier.ts @@ -37,7 +37,7 @@ export class Modifier extends Decorator { modifiers: Modifier[], originals: Decorator[] ) { - return await Promise.all( + return Promise.all( modifiers.map(async (modifier) => { // Get the list of objects that are linked to the specified modifier let linked = DecoratorUtils.getLinkedObjects(modifier, originals); @@ -50,7 +50,7 @@ export class Modifier extends Decorator { // Apply the modifications await Promise.all( linked.map(async (linkedOriginal) => { - return await modifier.applyModifications(linkedOriginal); + return modifier.applyModifications(linkedOriginal); }) ); }) diff --git a/src/decorators/decorators/Discord.ts b/src/decorators/decorators/Discord.ts index 985ba650..50b4489a 100644 --- a/src/decorators/decorators/Discord.ts +++ b/src/decorators/decorators/Discord.ts @@ -19,7 +19,7 @@ function importCommand(classType: Function, target: Function) { return on.classRef === classType; }); - ons.map((event) => { + ons.forEach((event) => { // Set the property hidden to true when // it's imported event.from = target; @@ -37,11 +37,11 @@ export function Discord(params?: DiscordParams) { } // For the commands that were imported like @Discord({ import: [...] }) - importCommands.map((cmd) => { + importCommands.forEach((cmd) => { if (typeof cmd === "string") { // For the commands that were imported like @Discord({ import: ["*.ts"] }) const files = Glob.sync(cmd); - files.map((file) => { + files.forEach((file) => { let classType; const classImport = require(file); if (classImport.default) { diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index be608eb2..d2df86ea 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -47,7 +47,7 @@ export function Group( // Create a subgroup if @Group decorate a method if (subCommands) { - Object.keys(subCommands).map((key) => { + Object.keys(subCommands).forEach((key) => { const group = DGroup.create( key, { description: subCommands[key] } diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index cdad73ef..50ca2300 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -18,7 +18,7 @@ export function Guild(...guildIDs: string[]) { ]; if (original instanceof DDiscord) { - original.slashes.map((slash) => { + original.slashes.forEach((slash) => { slash.guilds = [ ...slash.guilds, ...guildIDs.filter(guildID => !slash.guilds.includes(guildID)) diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index c86eb423..ab53f101 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -20,7 +20,7 @@ export function Permission(id: string, type: PermissionType) { original.permissions = [...original.permissions, permission]; if (original instanceof DDiscord) { - original.slashes.map((slash) => { + original.slashes.forEach((slash) => { slash.defaultPermission = false; slash.permissions = [...slash.permissions, permission]; }); diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index db151127..7e1d8d04 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -151,8 +151,8 @@ export class MetadataStorage { // Set the class level "group" property of all @Slash // Cannot achieve it using modifiers - this._groups.map((group) => { - this._slashes.map((slash) => { + this._groups.forEach((group) => { + this._slashes.forEach((slash) => { if (group.from !== slash.from) { return; } @@ -176,7 +176,7 @@ export class MetadataStorage { // ...comands // ] // - this._groups.map((group) => { + this._groups.forEach((group) => { const slashParent = DSlash.create( group.name, group.infos.description @@ -202,7 +202,7 @@ export class MetadataStorage { return slash.group === slashParent.name && !slash.subgroup; }); - slashes.map((slash) => { + slashes.forEach((slash) => { slashParent.options.push(slash.toSubCommand()); }); }); @@ -221,7 +221,7 @@ export class MetadataStorage { // ] // } // ] - this._subGroups.map((subGroup) => { + this._subGroups.forEach((subGroup) => { const option = DOption.create( subGroup.name, "SUB_COMMAND_GROUP", @@ -259,7 +259,7 @@ export class MetadataStorage { // } // ] // - slashes.map((slash) => { + slashes.forEach((slash) => { option.options.push(slash.toSubCommand()); }); From 9906e106856930813560687e1a9eeeed002e2626 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 21:48:48 +0530 Subject: [PATCH 005/106] unused var and decorator fix --- .eslintrc | 2 +- src/Client.ts | 2 +- src/decorators/classes/DGroup.ts | 1 - src/decorators/decorators/Choices.ts | 4 ++-- src/decorators/decorators/Description.ts | 2 +- src/decorators/decorators/Discord.ts | 2 +- src/decorators/decorators/Slash.ts | 5 ++--- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.eslintrc b/.eslintrc index 59674b61..c832fa2e 100755 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,7 @@ "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/ban-types": "off", - "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-inferrable-types": "off", "@typescript-eslint/no-var-requires": "off", diff --git a/src/Client.ts b/src/Client.ts index 61c23824..ac6e29c0 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -213,7 +213,7 @@ export class Client extends ClientJS { } else { // If the @Slash is global, add it globaly const commands = this.application.commands; - const command = await commands.create(slash.toObject()); + await commands.create(slash.toObject()); // Only available for Guilds // https://discord.js.org/#/docs/main/master/class/ApplicationCommand?scrollTo=setPermissions diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index 9e67849f..2ff2e809 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -1,4 +1,3 @@ -import { InstanceOf, ToInterface } from "../../types"; import { Decorator } from "./Decorator"; export class DGroup extends Decorator { diff --git a/src/decorators/decorators/Choices.ts b/src/decorators/decorators/Choices.ts index f3043bb3..addd6334 100644 --- a/src/decorators/decorators/Choices.ts +++ b/src/decorators/decorators/Choices.ts @@ -2,9 +2,9 @@ import { MetadataStorage, DChoice, DOption, Modifier, ChoicesType } from "../.." export function Choices(choices: ChoicesType); export function Choices(choices: ChoicesType) { - return async (target: Object, key: string, index: number) => { + return (target: Object, key: string, index: number) => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { const arrayChoices = Object.keys(choices).map((key) => { return DChoice.create(key, choices[key]); }); diff --git a/src/decorators/decorators/Description.ts b/src/decorators/decorators/Description.ts index 37510db4..2d7b8115 100644 --- a/src/decorators/decorators/Description.ts +++ b/src/decorators/decorators/Description.ts @@ -1,4 +1,4 @@ -import { MetadataStorage, Modifier, DDiscord } from "../.."; +import { MetadataStorage, Modifier } from "../.."; import { DSlash } from "../classes/DSlash"; export function Description(description: string); diff --git a/src/decorators/decorators/Discord.ts b/src/decorators/decorators/Discord.ts index 50b4489a..e2030907 100644 --- a/src/decorators/decorators/Discord.ts +++ b/src/decorators/decorators/Discord.ts @@ -29,7 +29,7 @@ function importCommand(classType: Function, target: Function) { export function Discord(); // export function Discord(params: DiscordParams); export function Discord(params?: DiscordParams) { - return (target: Function, key: string) => { + return (target: Function) => { if (params?.import) { let importCommands = params?.import || []; if (!Array.isArray(importCommands)) { diff --git a/src/decorators/decorators/Slash.ts b/src/decorators/decorators/Slash.ts index ddc99c57..d71f976f 100644 --- a/src/decorators/decorators/Slash.ts +++ b/src/decorators/decorators/Slash.ts @@ -4,10 +4,9 @@ export function Slash(); export function Slash(name: string); export function Slash(name: string, params: SlashParams); export function Slash(name?: string, params?: SlashParams) { - return async ( + return ( target: Object, - key: string, - descriptor: PropertyDescriptor + key: string ) => { name = name || key; name = name.toLocaleLowerCase(); From d66fc7101ca5605714a56fd48b57509ba4ca9610 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 22:02:08 +0530 Subject: [PATCH 006/106] fix https://discord.js.org/#/docs/main/master/class/ApplicationCommandPermissionsManager?scrollTo=set --- src/Client.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index ac6e29c0..ec22b5ef 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -207,7 +207,11 @@ export class Client extends ClientJS { if (slash.permissions.length <= 0) return; - await commands.setPermissions(command, slash.getPermissions()); + // https://discord.js.org/#/docs/main/master/class/ApplicationCommandPermissionsManager?scrollTo=set + await commands.permissions.set({ + command: command, + permissions: slash.getPermissions(), + }); }) ); } else { From 4815968b3ba733d719dbb623604eeb4b2bc93132 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 22:13:09 +0530 Subject: [PATCH 007/106] fix no-inferrable-types --- .eslintrc | 2 +- src/Client.ts | 4 ++-- src/decorators/classes/DDiscord.ts | 2 +- src/decorators/classes/DOption.ts | 4 ++-- src/decorators/classes/DSlash.ts | 4 ++-- src/logic/metadatas/MetadataStorage.ts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.eslintrc b/.eslintrc index c832fa2e..de537b35 100755 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,7 @@ "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-inferrable-types": "warn", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-non-null-asserted-optional-chain": "off", "@typescript-eslint/no-non-null-assertion": "off" diff --git a/src/Client.ts b/src/Client.ts index ec22b5ef..821ba0b4 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -20,7 +20,7 @@ import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { private _silent: boolean; private _loadClasses: LoadClass[] = []; - private static _requiredByDefault: boolean = false; + private static _requiredByDefault = false; private static _slashGuilds: string[] = []; private static _guards: GuardFunction[] = []; @@ -387,7 +387,7 @@ export class Client extends ClientJS { trigger( event: DiscordEvents, params?: any, - once: boolean = false + once = false ): Promise { return this.decorators.trigger(event, this, once)(params); } diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index 2a45b472..af67ec75 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -13,7 +13,7 @@ export class DDiscord extends Decorator { private _events: DOn[] = []; private _description: string; private _name: string; - private _defaultPermission: boolean = true; + private _defaultPermission = true; private _permissions: { id: string, type: PermissionType }[] = []; private _guilds: string[] = []; diff --git a/src/decorators/classes/DOption.ts b/src/decorators/classes/DOption.ts index 59aa5686..3a52cb20 100644 --- a/src/decorators/classes/DOption.ts +++ b/src/decorators/classes/DOption.ts @@ -12,13 +12,13 @@ import { Decorator } from "../classes/Decorator"; import { DChoice, Client, OptionValueType, StringOptionType, OptionType } from "../.."; export class DOption extends Decorator { - private _required: boolean = false; + private _required = false; private _name: string; private _type: OptionValueType; private _description: string; private _choices: DChoice[] = []; private _options: DOption[] = []; - private _isNode: boolean = false; + private _isNode = false; get isNode() { return this._isNode; diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 096d6d03..6bfa808f 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -11,7 +11,7 @@ import { Method } from "./Method"; export class DSlash extends Method { private _description: string; private _name: string; - private _defaultPermission: boolean = true; + private _defaultPermission = true; private _options: DOption[] = []; private _permissions: { id: string, type: PermissionType }[] = []; private _guilds: string[]; @@ -81,7 +81,7 @@ export class DSlash extends Method { static create( name: string, description?: string, - defaultPermission: boolean = true, + defaultPermission = true, guilds?: string[] ) { const slash = new DSlash(); diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 7e1d8d04..9e1dd2d7 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -285,7 +285,7 @@ export class MetadataStorage { trigger( event: Event, client: Client, - once: boolean = false + once = false ): ((...params: ArgsOf) => Promise) { const responses: any[] = []; From 5762d9a40f7457e81ea63ef7c609e1a4b48c6fec Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 22:23:00 +0530 Subject: [PATCH 008/106] fix type error --- .eslintrc | 8 ++++---- src/decorators/classes/Decorator.ts | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.eslintrc b/.eslintrc index de537b35..e0710e82 100755 --- a/.eslintrc +++ b/.eslintrc @@ -11,13 +11,13 @@ "quotes": "error", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-empty-function": "warn", "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-unused-vars": "warn", - "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-inferrable-types": "warn", "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-non-null-asserted-optional-chain": "off", - "@typescript-eslint/no-non-null-assertion": "off" + "@typescript-eslint/no-non-null-asserted-optional-chain": "warn", + "@typescript-eslint/no-non-null-assertion": "warn" } } diff --git a/src/decorators/classes/Decorator.ts b/src/decorators/classes/Decorator.ts index 7103595b..6460a79e 100644 --- a/src/decorators/classes/Decorator.ts +++ b/src/decorators/classes/Decorator.ts @@ -39,6 +39,7 @@ export class Decorator { } protected constructor() { + // empty constructor } decorateUnknown( @@ -83,5 +84,7 @@ export class Decorator { return this; } - update() {} + update() { + // empty function + } } From d02a9536228fff91f9342f20e1d65f632c571ca8 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 22:46:50 +0530 Subject: [PATCH 009/106] ## init slash for guilds > register one time > delete one time > update always ## init slash for global guilds --- src/Client.ts | 220 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 164 insertions(+), 56 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 821ba0b4..bfa122cc 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -1,4 +1,5 @@ import { + ApplicationCommand, Client as ClientJS, CommandInteraction, CommandInteractionOption, @@ -150,17 +151,19 @@ export class Client extends ClientJS { console.log(` ${slash.name} (${slash.classRef.name}.${slash.key})`); const printOptions = (options: DOption[], depth: number) => { if (!options) return; - + const tab = Array(depth).join(" "); - + options.forEach((option) => { - console.log(`${tab}${option.name}: ${option.stringType} (${option.classRef.name}.${option.key})`); + console.log( + `${tab}${option.name}: ${option.stringType} (${option.classRef.name}.${option.key})` + ); printOptions(option.options, depth + 1); }); }; - + printOptions(slash.options, 2); - + console.log(""); }); } else { @@ -175,10 +178,7 @@ export class Client extends ClientJS { this.decorators.trigger(on.event, this, true) ); } else { - this.on( - on.event as any, - this.decorators.trigger(on.event, this) - ); + this.on(on.event as any, this.decorators.trigger(on.event, this)); } }); @@ -189,44 +189,156 @@ export class Client extends ClientJS { * Initialize all the @Slash with their permissions */ async initSlashes() { - await Promise.all( - this.slashes.map(async (slash) => { - // Init all the @Slash - if (slash.guilds.length > 0) { - // If the @Slash is guild specific, add it to the guild - await Promise.all( - slash.guilds.map(async (guildID) => { - const guild = this.guilds.cache.get(guildID as Snowflake); + // # first init guild's all slash + const guildSlashStorage = new Map(); + const guildsSlash = this.slashes.filter((s) => s.guilds?.length); + + // group single guild slash togather + for (const s of guildsSlash) { + s.guilds.forEach((guild) => + guildSlashStorage.set(guild, [ + ...(guildSlashStorage.get(guild) ?? []), + s, + ]) + ); + } - if (!guild) { - throw new GuildNotFoundError(guildID); - } + // update guild commands + for (const gc of guildSlashStorage) { + const guild = await this.guilds.fetch({ guild: gc[0] as Snowflake }); + if (!guild) console.log("guild not found"); - const commands = guild.commands; - const command = await commands.create(slash.toObject()); + // commands for guild + const slashes = gc[1]; - if (slash.permissions.length <= 0) return; + // fetch already registered command + const existing = await guild.commands.fetch(); - // https://discord.js.org/#/docs/main/master/class/ApplicationCommandPermissionsManager?scrollTo=set - await commands.permissions.set({ - command: command, - permissions: slash.getPermissions(), - }); - }) - ); - } else { - // If the @Slash is global, add it globaly - const commands = this.application.commands; - await commands.create(slash.toObject()); - - // Only available for Guilds - // https://discord.js.org/#/docs/main/master/class/ApplicationCommand?scrollTo=setPermissions - // if (slash.permissions.length <= 0) return; - - // await commands.setPermissions(command, slash.getPermissions()); - } - }) + // filter only unregistered command + const added = slashes.filter( + (s) => !existing.find((c) => c.name === s.name) + ); + + // filter commands to update + const updated = slashes + .map<[ApplicationCommand, DSlash]>((s) => [ + existing.find((c) => c.name === s.name), + s, + ]) + .filter((s) => s[0]); + + // filter commands to delete + const deleted = existing.filter( + (s) => + !this.slashes.find( + (bs) => s.name === bs.name && bs.guilds.includes(s.guild.id) + ) + ); + + if (!this.silent) + console.log( + `${this.user.username} >> guild: #${guild} >> command >> Adding ${ + added.length + } [${added.map((s) => s.name).join(", ")}]` + ); + + if (!this.silent) + console.log( + `${this.user.username} >> guild: #${guild} >> command >> deleting ${ + deleted.size + } [${deleted.map((s) => s.name).join(", ")}]` + ); + + if (!this.silent) + console.log( + `${this.user.username} >> guild: #${guild} >> command >> updating ${updated.length}` + ); + + await Promise.all([ + ...added.map((s) => guild.commands.create(s.toObject())), // + ...updated.map((s) => s[0].edit(s[1].toObject())), + ...deleted.map((key) => guild.commands.delete(key)), + ]); + } + + // # init global commands + const existing = (await this.fetchSlash()).filter((s) => !s.guild); + const slashes = this.slashes.filter((s) => !s.guilds?.length); + + const added = slashes.filter( + (s) => !existing.find((c) => c.name === s.name) + ); + const updated = slashes + .map<[ApplicationCommand, DSlash]>((s) => [ + existing.find((c) => c.name === s.name), + s, + ]) + .filter((s) => s[0]); + const deleted = existing.filter((c) => + slashes.every((s) => s.name !== c.name) ); + + if (!this.silent) + console.log( + `${this.user.username} >> global >> command >> Adding ${ + added.length + } [${added.map((s) => s.name).join(", ")}]` + ); + if (!this.silent) + console.log( + `${this.user.username} >> global >> command >> deleting ${ + deleted.size + } [${deleted.map((s) => s.name).join(", ")}]` + ); + if (!this.silent) + console.log( + `${this.user.username} >> global >> command >> updating ${updated.length}` + ); + + await Promise.all([ + ...added.map((s) => this.application.commands.create(s.toObject())), + ...updated.map((s) => s[0].edit(s[1].toObject())), + ...deleted.map((key) => this.application.commands.delete(key)), + ]); + + // await Promise.all( + // this.slashes.map(async (slash) => { + // // Init all the @Slash + // if (slash.guilds.length > 0) { + // // If the @Slash is guild specific, add it to the guild + // await Promise.all( + // slash.guilds.map(async (guildID) => { + // const guild = this.guilds.cache.get(guildID as Snowflake); + // + // if (!guild) { + // throw new GuildNotFoundError(guildID); + // } + // + // const commands = guild.commands; + // const command = await commands.create(slash.toObject()); + // + // if (slash.permissions.length <= 0) return; + // + // // https://discord.js.org/#/docs/main/master/class/ApplicationCommandPermissionsManager?scrollTo=set + // await commands.permissions.set({ + // command: command, + // permissions: slash.getPermissions(), + // }); + // }) + // ); + // } else { + // // If the @Slash is global, add it globaly + // const commands = this.application.commands; + // await commands.create(slash.toObject()); + // + // // Only available for Guilds + // // https://discord.js.org/#/docs/main/master/class/ApplicationCommand?scrollTo=setPermissions + // // if (slash.permissions.length <= 0) return; + // + // // await commands.setPermissions(command, slash.getPermissions()); + // } + // }) + // ); } /** @@ -257,7 +369,9 @@ export class Client extends ClientJS { const commands = await this.fetchSlash(guild); await Promise.all( commands.map(async (value) => { - await this.guilds.cache.get(guild as Snowflake).commands.delete(value); + await this.guilds.cache + .get(guild as Snowflake) + .commands.delete(value); }) ); }) @@ -274,7 +388,7 @@ export class Client extends ClientJS { } /** - * Get the group tree of an interaction + * Get the group tree of an interaction * /hello => ["hello"] * /test hello => ["test", "hello"] * /test hello me => ["test", "hello", "me"] @@ -284,13 +398,11 @@ export class Client extends ClientJS { getInteractionGroupTree(interaction: CommandInteraction) { const tree = []; - const getOptionsTree = ( - option: Partial - ) => { + const getOptionsTree = (option: Partial) => { if (!option) return; if ( - !option.type || + !option.type || option.type === "SUB_COMMAND_GROUP" || option.type === "SUB_COMMAND" ) { @@ -302,7 +414,7 @@ export class Client extends ClientJS { getOptionsTree({ name: interaction.commandName, options: interaction.options, - type: undefined + type: undefined, }); return tree; @@ -310,13 +422,13 @@ export class Client extends ClientJS { /** * Return the corresponding @Slash from a tree - * @param tree + * @param tree * @returns The corresponding Slash */ getSlashFromTree(tree: string[]) { // Find the corresponding @Slash return this.allSlashes.find((slash) => { - switch(tree.length) { + switch (tree.length) { case 1: // Simple command /hello return ( @@ -384,11 +496,7 @@ export class Client extends ClientJS { * @param params Params to inject * @param once Trigger an once event */ - trigger( - event: DiscordEvents, - params?: any, - once = false - ): Promise { + trigger(event: DiscordEvents, params?: any, once = false): Promise { return this.decorators.trigger(event, this, once)(params); } From d87ebba2f2f571fc1745a4d265aefdad5312cf69 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 23:18:03 +0530 Subject: [PATCH 010/106] multiple bot support --- src/Client.ts | 20 ++++++++++++++++---- src/decorators/classes/DSlash.ts | 12 +++++++++++- src/decorators/decorators/Slash.ts | 2 +- src/decorators/params/SlashParams.ts | 1 + src/types/core/ClientOptions.ts | 5 +++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index bfa122cc..76d80a7a 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -19,6 +19,8 @@ import { DDiscord, DOption, DSlash } from "./decorators"; import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { + botid?: string; + static importedClass: string[] = [] private _silent: boolean; private _loadClasses: LoadClass[] = []; private static _requiredByDefault = false; @@ -118,6 +120,7 @@ export class Client extends ClientJS { this.guards = options.guards || []; this.requiredByDefault = options.requiredByDefault; this.slashGuilds = options.slashGuilds || []; + this.botid = options.botid; } /** @@ -216,7 +219,9 @@ export class Client extends ClientJS { // filter only unregistered command const added = slashes.filter( - (s) => !existing.find((c) => c.name === s.name) + (s) => + !existing.find((c) => c.name === s.name) && + (!s.botids || s.botids.includes(this.botid)) ); // filter commands to update @@ -231,7 +236,10 @@ export class Client extends ClientJS { const deleted = existing.filter( (s) => !this.slashes.find( - (bs) => s.name === bs.name && bs.guilds.includes(s.guild.id) + (bs) => + s.name === bs.name && + bs.guilds.includes(s.guild.id) && + (!bs.botids || bs.botids.includes(this.botid)) ) ); @@ -476,7 +484,7 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if (!slash) return; + if (!slash || !slash.botids?.includes(this.botid)) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); @@ -509,7 +517,11 @@ export class Client extends ClientJS { if (typeof file === "string") { const files = Glob.sync(file); files.forEach((file) => { - require(file); + // skip already imported files + if (!Client.importedClass.includes(file)) { + Client.importedClass.push(file); + require(file); + } }); } }); diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 6bfa808f..88d2bb12 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -15,6 +15,7 @@ export class DSlash extends Method { private _options: DOption[] = []; private _permissions: { id: string, type: PermissionType }[] = []; private _guilds: string[]; + private _botids: string[]; private _group: string; private _subgroup: string; @@ -46,6 +47,13 @@ export class DSlash extends Method { this._guilds = value; } + get botids() { + return this._botids; + } + set botids(value) { + this._botids = value; + } + get defaultPermission() { return this._defaultPermission; } @@ -82,7 +90,8 @@ export class DSlash extends Method { name: string, description?: string, defaultPermission = true, - guilds?: string[] + guilds?: string[], + botids?: string[] ) { const slash = new DSlash(); @@ -90,6 +99,7 @@ export class DSlash extends Method { slash.description = description || slash.name; slash.defaultPermission = defaultPermission; slash.guilds = guilds || Client.slashGuilds; + slash.botids = botids; return slash; } diff --git a/src/decorators/decorators/Slash.ts b/src/decorators/decorators/Slash.ts index d71f976f..41c626a6 100644 --- a/src/decorators/decorators/Slash.ts +++ b/src/decorators/decorators/Slash.ts @@ -11,7 +11,7 @@ export function Slash(name?: string, params?: SlashParams) { name = name || key; name = name.toLocaleLowerCase(); - const slash = DSlash.create(name, params?.description, params?.defaultPermission, params?.guilds).decorate( + const slash = DSlash.create(name, params?.description, params?.defaultPermission, params?.guilds, params?.botids).decorate( target.constructor, key, target[key] diff --git a/src/decorators/params/SlashParams.ts b/src/decorators/params/SlashParams.ts index 3bff7a82..9ed0e210 100644 --- a/src/decorators/params/SlashParams.ts +++ b/src/decorators/params/SlashParams.ts @@ -2,4 +2,5 @@ export interface SlashParams { description?: string; defaultPermission?: boolean; guilds?: string[]; + botids?: string[]; } diff --git a/src/types/core/ClientOptions.ts b/src/types/core/ClientOptions.ts index a2a7689d..57471e1a 100644 --- a/src/types/core/ClientOptions.ts +++ b/src/types/core/ClientOptions.ts @@ -3,6 +3,11 @@ import { GuardFunction } from "../public/GuardFunction"; import { LoadClass } from "./LoadClass"; export interface ClientOptions extends DiscordJSClientOptions { + /** + * Specifiy bot id (added for multiple bot support) + */ + botid?: string; + /** * Do not log anything in the console */ From 029539ba7b1d307696905ac08972067bff4b1943 Mon Sep 17 00:00:00 2001 From: iorp Date: Thu, 1 Jul 2021 23:35:25 +0530 Subject: [PATCH 011/106] fix github.com/OwenCalvin/discord.ts/issues/49 --- src/Client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 76d80a7a..52d18738 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -20,7 +20,7 @@ import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { botid?: string; - static importedClass: string[] = [] + static importedClass: string[] = []; private _silent: boolean; private _loadClasses: LoadClass[] = []; private static _requiredByDefault = false; @@ -484,7 +484,7 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if (!slash || !slash.botids?.includes(this.botid)) return; + if (!slash || (this.botid && !slash.botids?.includes(this.botid))) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); From d5bf0df1bda2aded10af52b824b1fa12bcba8414 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 00:03:47 +0530 Subject: [PATCH 012/106] multi bot support --- src/Client.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 52d18738..553b662f 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -20,7 +20,7 @@ import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { botid?: string; - static importedClass: string[] = []; + static build = false; private _silent: boolean; private _loadClasses: LoadClass[] = []; private static _requiredByDefault = false; @@ -209,7 +209,10 @@ export class Client extends ClientJS { // update guild commands for (const gc of guildSlashStorage) { const guild = await this.guilds.fetch({ guild: gc[0] as Snowflake }); - if (!guild) console.log("guild not found"); + if (!guild) { + console.log("guild not found"); + continue; + } // commands for guild const slashes = gc[1]; @@ -494,6 +497,8 @@ export class Client extends ClientJS { * Manually build the app */ async build() { + if(Client.build) return ; + Client.build = true; this.loadClasses(); await this.decorators.build(); } @@ -517,11 +522,7 @@ export class Client extends ClientJS { if (typeof file === "string") { const files = Glob.sync(file); files.forEach((file) => { - // skip already imported files - if (!Client.importedClass.includes(file)) { - Client.importedClass.push(file); - require(file); - } + require(file); }); } }); From 841d5063b0de6b220f9b474f79cacd00419900af Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 00:11:45 +0530 Subject: [PATCH 013/106] fix multiple bot --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index d45180ed..40ae1689 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,22 @@ +# ⚠️ Caution +this repo can be only used by experienced developer, this repo contain untested codes, for stable support use original repo + +# Changes from original repo +changes which are not yet accepted under original repo + +## New Features +* multiple bot support (only slash supported for now, events will be supported soon) + +#### Issue Fixed +* github.com/OwenCalvin/discord.ts/issues/54 +* github.com/OwenCalvin/discord.ts/issues/49 + +### Pull Accepted +* github.com/OwenCalvin/discord.ts/pull/60 +* github.com/OwenCalvin/discord.ts/pull/58 +* github.com/OwenCalvin/discord.ts/pull/56 +* github.com/OwenCalvin/discord.ts/pull/55 +


From 26ae1b74139a4c9f0f9529e6a1992d59bd82b6f1 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 00:21:44 +0530 Subject: [PATCH 014/106] readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40ae1689..5be234c5 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ this repo can be only used by experienced developer, this repo contain untested changes which are not yet accepted under original repo ## New Features +* improved ``bot.initSlashes()`` to register commands only if required (to overcome the daily register command limit from discord) * multiple bot support (only slash supported for now, events will be supported soon) #### Issue Fixed From 2e5cb5c9d9d162dd34554eb01bcd816b59b7b4eb Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 00:35:57 +0530 Subject: [PATCH 015/106] original readme restored --- README.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/README.md b/README.md index 5be234c5..d45180ed 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,3 @@ -# ⚠️ Caution -this repo can be only used by experienced developer, this repo contain untested codes, for stable support use original repo - -# Changes from original repo -changes which are not yet accepted under original repo - -## New Features -* improved ``bot.initSlashes()`` to register commands only if required (to overcome the daily register command limit from discord) -* multiple bot support (only slash supported for now, events will be supported soon) - -#### Issue Fixed -* github.com/OwenCalvin/discord.ts/issues/54 -* github.com/OwenCalvin/discord.ts/issues/49 - -### Pull Accepted -* github.com/OwenCalvin/discord.ts/pull/60 -* github.com/OwenCalvin/discord.ts/pull/58 -* github.com/OwenCalvin/discord.ts/pull/56 -* github.com/OwenCalvin/discord.ts/pull/55 -


From 2b5ab41db87223a7cf3690ef117acaf9747dca8d Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 01:11:23 +0530 Subject: [PATCH 016/106] fixes based on @AndyClausen suggestion --- src/Client.ts | 71 ++++++++-------------------- src/decorators/classes/DSlash.ts | 8 ++-- src/decorators/decorators/Slash.ts | 2 +- src/decorators/params/SlashParams.ts | 2 +- src/types/core/ClientOptions.ts | 2 +- 5 files changed, 27 insertions(+), 58 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 553b662f..2f7bd29b 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -19,8 +19,8 @@ import { DDiscord, DOption, DSlash } from "./decorators"; import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { - botid?: string; - static build = false; + private static isAlreadyBuilt = false; + private _botId: string; private _silent: boolean; private _loadClasses: LoadClass[] = []; private static _requiredByDefault = false; @@ -33,6 +33,14 @@ export class Client extends ClientJS { static set slashGuilds(value) { Client._slashGuilds = value; } + + get botid() { + return this._botId; + } + set botid(value) { + this._botId = value; + } + get slashGuilds() { return Client._slashGuilds; } @@ -120,7 +128,7 @@ export class Client extends ClientJS { this.guards = options.guards || []; this.requiredByDefault = options.requiredByDefault; this.slashGuilds = options.slashGuilds || []; - this.botid = options.botid; + this.botid = options.botId; } /** @@ -196,7 +204,7 @@ export class Client extends ClientJS { const guildSlashStorage = new Map(); const guildsSlash = this.slashes.filter((s) => s.guilds?.length); - // group single guild slash togather + // group single guild slash together for (const s of guildsSlash) { s.guilds.forEach((guild) => guildSlashStorage.set(guild, [ @@ -224,7 +232,7 @@ export class Client extends ClientJS { const added = slashes.filter( (s) => !existing.find((c) => c.name === s.name) && - (!s.botids || s.botids.includes(this.botid)) + (!s.botIds || s.botIds.includes(this.botid)) ); // filter commands to update @@ -242,13 +250,13 @@ export class Client extends ClientJS { (bs) => s.name === bs.name && bs.guilds.includes(s.guild.id) && - (!bs.botids || bs.botids.includes(this.botid)) + (!bs.botIds || bs.botIds.includes(this.botid)) ) ); if (!this.silent) console.log( - `${this.user.username} >> guild: #${guild} >> command >> Adding ${ + `${this.user.username} >> guild: #${guild} >> command >> adding ${ added.length } [${added.map((s) => s.name).join(", ")}]` ); @@ -266,7 +274,7 @@ export class Client extends ClientJS { ); await Promise.all([ - ...added.map((s) => guild.commands.create(s.toObject())), // + ...added.map((s) => guild.commands.create(s.toObject())), ...updated.map((s) => s[0].edit(s[1].toObject())), ...deleted.map((key) => guild.commands.delete(key)), ]); @@ -291,7 +299,7 @@ export class Client extends ClientJS { if (!this.silent) console.log( - `${this.user.username} >> global >> command >> Adding ${ + `${this.user.username} >> global >> command >> adding ${ added.length } [${added.map((s) => s.name).join(", ")}]` ); @@ -311,45 +319,6 @@ export class Client extends ClientJS { ...updated.map((s) => s[0].edit(s[1].toObject())), ...deleted.map((key) => this.application.commands.delete(key)), ]); - - // await Promise.all( - // this.slashes.map(async (slash) => { - // // Init all the @Slash - // if (slash.guilds.length > 0) { - // // If the @Slash is guild specific, add it to the guild - // await Promise.all( - // slash.guilds.map(async (guildID) => { - // const guild = this.guilds.cache.get(guildID as Snowflake); - // - // if (!guild) { - // throw new GuildNotFoundError(guildID); - // } - // - // const commands = guild.commands; - // const command = await commands.create(slash.toObject()); - // - // if (slash.permissions.length <= 0) return; - // - // // https://discord.js.org/#/docs/main/master/class/ApplicationCommandPermissionsManager?scrollTo=set - // await commands.permissions.set({ - // command: command, - // permissions: slash.getPermissions(), - // }); - // }) - // ); - // } else { - // // If the @Slash is global, add it globaly - // const commands = this.application.commands; - // await commands.create(slash.toObject()); - // - // // Only available for Guilds - // // https://discord.js.org/#/docs/main/master/class/ApplicationCommand?scrollTo=setPermissions - // // if (slash.permissions.length <= 0) return; - // - // // await commands.setPermissions(command, slash.getPermissions()); - // } - // }) - // ); } /** @@ -487,7 +456,7 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if (!slash || (this.botid && !slash.botids?.includes(this.botid))) return; + if (!slash || (slash.botIds && !slash.botIds.includes(this.botid))) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); @@ -497,8 +466,8 @@ export class Client extends ClientJS { * Manually build the app */ async build() { - if(Client.build) return ; - Client.build = true; + if(Client.isAlreadyBuilt) return ; + Client.isAlreadyBuilt = true; this.loadClasses(); await this.decorators.build(); } diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 88d2bb12..ce1f635d 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -47,10 +47,10 @@ export class DSlash extends Method { this._guilds = value; } - get botids() { + get botIds() { return this._botids; } - set botids(value) { + set botIds(value) { this._botids = value; } @@ -91,7 +91,7 @@ export class DSlash extends Method { description?: string, defaultPermission = true, guilds?: string[], - botids?: string[] + botIds?: string[] ) { const slash = new DSlash(); @@ -99,7 +99,7 @@ export class DSlash extends Method { slash.description = description || slash.name; slash.defaultPermission = defaultPermission; slash.guilds = guilds || Client.slashGuilds; - slash.botids = botids; + slash.botIds = botIds; return slash; } diff --git a/src/decorators/decorators/Slash.ts b/src/decorators/decorators/Slash.ts index 41c626a6..f5f57c65 100644 --- a/src/decorators/decorators/Slash.ts +++ b/src/decorators/decorators/Slash.ts @@ -11,7 +11,7 @@ export function Slash(name?: string, params?: SlashParams) { name = name || key; name = name.toLocaleLowerCase(); - const slash = DSlash.create(name, params?.description, params?.defaultPermission, params?.guilds, params?.botids).decorate( + const slash = DSlash.create(name, params?.description, params?.defaultPermission, params?.guilds, params?.botIds).decorate( target.constructor, key, target[key] diff --git a/src/decorators/params/SlashParams.ts b/src/decorators/params/SlashParams.ts index 9ed0e210..ae5f2fcc 100644 --- a/src/decorators/params/SlashParams.ts +++ b/src/decorators/params/SlashParams.ts @@ -2,5 +2,5 @@ export interface SlashParams { description?: string; defaultPermission?: boolean; guilds?: string[]; - botids?: string[]; + botIds?: string[]; } diff --git a/src/types/core/ClientOptions.ts b/src/types/core/ClientOptions.ts index 57471e1a..96802b29 100644 --- a/src/types/core/ClientOptions.ts +++ b/src/types/core/ClientOptions.ts @@ -6,7 +6,7 @@ export interface ClientOptions extends DiscordJSClientOptions { /** * Specifiy bot id (added for multiple bot support) */ - botid?: string; + botId: string; /** * Do not log anything in the console From 0558c4a9a3863716f647fd693bcc2ce4ebdef2b2 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 02:26:37 +0530 Subject: [PATCH 017/106] * formated code with prettier * minor fixes based on @AndyClausen suggestion * event update for multiple bot support --- .eslintrc | 2 +- src/Client.ts | 18 ++++---- src/decorators/classes/DDiscord.ts | 11 ++--- src/decorators/classes/DGroup.ts | 2 +- src/decorators/classes/DOn.ts | 20 ++++++--- src/decorators/classes/DOption.ts | 12 +++++- src/decorators/classes/DSlash.ts | 32 +++++++------- src/decorators/classes/Method.ts | 22 ++++------ src/decorators/classes/Modifier.ts | 4 +- src/decorators/decorators/Choice.ts | 5 +-- src/decorators/decorators/Choices.ts | 13 +++--- src/decorators/decorators/Discord.ts | 12 +----- src/decorators/decorators/Group.ts | 33 +++++++------- src/decorators/decorators/Guard.ts | 25 +++++++---- src/decorators/decorators/Guild.ts | 34 +++++++++------ src/decorators/decorators/Name.ts | 10 +++-- src/decorators/decorators/On.ts | 7 ++- src/decorators/decorators/Once.ts | 7 ++- src/decorators/decorators/Option.ts | 13 +----- src/decorators/decorators/Permission.ts | 32 +++++++------- src/decorators/decorators/Slash.ts | 17 ++++---- src/decorators/params/EventParams.ts | 3 ++ src/logic/index.ts | 2 - src/logic/metadatas/MetadataStorage.ts | 57 +++++++++---------------- src/logic/utils/DecoratorUtils.ts | 17 +++----- 25 files changed, 200 insertions(+), 210 deletions(-) create mode 100644 src/decorators/params/EventParams.ts diff --git a/.eslintrc b/.eslintrc index e0710e82..0425fe87 100755 --- a/.eslintrc +++ b/.eslintrc @@ -10,13 +10,13 @@ "semi": "error", "quotes": "error", "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-function": "warn", "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-inferrable-types": "warn", - "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-non-null-asserted-optional-chain": "warn", "@typescript-eslint/no-non-null-assertion": "warn" } diff --git a/src/Client.ts b/src/Client.ts index 2f7bd29b..2766d829 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -19,7 +19,7 @@ import { DDiscord, DOption, DSlash } from "./decorators"; import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { - private static isAlreadyBuilt = false; + private static isBuilt = false; private _botId: string; private _silent: boolean; private _loadClasses: LoadClass[] = []; @@ -34,10 +34,10 @@ export class Client extends ClientJS { Client._slashGuilds = value; } - get botid() { + get botId() { return this._botId; } - set botid(value) { + set botId(value) { this._botId = value; } @@ -128,7 +128,7 @@ export class Client extends ClientJS { this.guards = options.guards || []; this.requiredByDefault = options.requiredByDefault; this.slashGuilds = options.slashGuilds || []; - this.botid = options.botId; + this.botId = options.botId; } /** @@ -232,7 +232,7 @@ export class Client extends ClientJS { const added = slashes.filter( (s) => !existing.find((c) => c.name === s.name) && - (!s.botIds || s.botIds.includes(this.botid)) + (!s.botIds || s.botIds.includes(this.botId)) ); // filter commands to update @@ -250,7 +250,7 @@ export class Client extends ClientJS { (bs) => s.name === bs.name && bs.guilds.includes(s.guild.id) && - (!bs.botIds || bs.botIds.includes(this.botid)) + (!bs.botIds || bs.botIds.includes(this.botId)) ) ); @@ -456,7 +456,7 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if (!slash || (slash.botIds && !slash.botIds.includes(this.botid))) return; + if (!slash || (slash.botIds && !slash.botIds.includes(this.botId))) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); @@ -466,8 +466,8 @@ export class Client extends ClientJS { * Manually build the app */ async build() { - if(Client.isAlreadyBuilt) return ; - Client.isAlreadyBuilt = true; + if (Client.isBuilt) return; + Client.isBuilt = true; this.loadClasses(); await this.decorators.build(); } diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index af67ec75..776caa08 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -1,10 +1,5 @@ import { Decorator } from "./Decorator"; -import { - DGuard, - DSlash, - DIService, - DOn -} from "../.."; +import { DGuard, DSlash, DIService, DOn } from "../.."; import { PermissionType } from "../../types"; export class DDiscord extends Decorator { @@ -14,7 +9,7 @@ export class DDiscord extends Decorator { private _description: string; private _name: string; private _defaultPermission = true; - private _permissions: { id: string, type: PermissionType }[] = []; + private _permissions: { id: string; type: PermissionType }[] = []; private _guilds: string[] = []; get permissions() { @@ -83,7 +78,7 @@ export class DDiscord extends Decorator { static create(name: string) { const discord = new DDiscord(); - + discord.name = name; return discord; diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index 2ff2e809..fef6258c 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -12,7 +12,7 @@ export class DGroup extends Decorator { const group = new DGroup(); group.name = name.toLowerCase(); - group.infos = infos || {} as any; + group.infos = infos; return group; } diff --git a/src/decorators/classes/DOn.ts b/src/decorators/classes/DOn.ts index 7797f985..512d967c 100644 --- a/src/decorators/classes/DOn.ts +++ b/src/decorators/classes/DOn.ts @@ -1,12 +1,19 @@ -import { - DiscordEvents -} from "../.."; +import { DiscordEvents } from "../.."; +import { EventParams } from "../params/EventParams"; import { Method } from "./Method"; export class DOn extends Method { + protected _botIds?: string[]; protected _event: DiscordEvents; protected _once: boolean; + get botIds() { + return this._botIds; + } + set botIds(value: string[]) { + this._botIds = value; + } + get event() { return this._event; } @@ -25,11 +32,12 @@ export class DOn extends Method { super(); } - static create(event: DiscordEvents, once: boolean) { + static create(event: DiscordEvents, once: boolean, params?: EventParams) { const on = new DOn(); - on._event = event; - on._once = once; + on.event = event; + on.once = once; + on.botIds = params.botIds; return on; } diff --git a/src/decorators/classes/DOption.ts b/src/decorators/classes/DOption.ts index 3a52cb20..ec2b7600 100644 --- a/src/decorators/classes/DOption.ts +++ b/src/decorators/classes/DOption.ts @@ -9,7 +9,13 @@ import { VoiceChannel, } from "discord.js"; import { Decorator } from "../classes/Decorator"; -import { DChoice, Client, OptionValueType, StringOptionType, OptionType } from "../.."; +import { + DChoice, + Client, + OptionValueType, + StringOptionType, + OptionType, +} from "../.."; export class DOption extends Decorator { private _required = false; @@ -126,7 +132,9 @@ export class DOption extends Decorator { type: this.stringType, required: this.required, choices: this.choices.map((choice) => choice.toObject()), - options: [...this.options].reverse().map((option) => option.toObject()) as ApplicationCommandOption[] + options: [...this.options] + .reverse() + .map((option) => option.toObject()) as ApplicationCommandOption[], }; if (!this.isNode) { diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index ce1f635d..3bcea067 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -13,9 +13,9 @@ export class DSlash extends Method { private _name: string; private _defaultPermission = true; private _options: DOption[] = []; - private _permissions: { id: string, type: PermissionType }[] = []; + private _permissions: { id: string; type: PermissionType }[] = []; private _guilds: string[]; - private _botids: string[]; + private _botIds?: string[]; private _group: string; private _subgroup: string; @@ -48,10 +48,10 @@ export class DSlash extends Method { } get botIds() { - return this._botids; + return this._botIds; } set botIds(value) { - this._botids = value; + this._botIds = value; } get defaultPermission() { @@ -109,21 +109,17 @@ export class DSlash extends Method { this.name, "SUB_COMMAND", this.description - ).decorate( - this.classRef, - this.key, - this.method, - this.from, - this.index - ); + ).decorate(this.classRef, this.key, this.method, this.from, this.index); option.options = this.options; return option; } toObject(): ApplicationCommandData { - const options = [...this.options].reverse().map((option) => option.toObject()); - + const options = [...this.options] + .reverse() + .map((option) => option.toObject()); + return { name: this.name, description: this.description, @@ -140,9 +136,11 @@ export class DSlash extends Method { })); } - getLastNestedOption(options: Map): CommandInteractionOption[] { + getLastNestedOption( + options: Map + ): CommandInteractionOption[] { const arrOptions = Array.from(options?.values()); - + if (!arrOptions?.[0]?.options) { return arrOptions; } @@ -153,6 +151,8 @@ export class DSlash extends Method { parseParams(interaction: CommandInteraction) { const options = this.getLastNestedOption(interaction.options); - return this.options.sort((a, b) => a.index - b.index).map((op) => options.find((o) => o.name === op.name)?.value); + return this.options + .sort((a, b) => a.index - b.index) + .map((op) => options.find((o) => o.name === op.name)?.value); } } diff --git a/src/decorators/classes/Method.ts b/src/decorators/classes/Method.ts index 823f66b9..301e6392 100644 --- a/src/decorators/classes/Method.ts +++ b/src/decorators/classes/Method.ts @@ -37,13 +37,15 @@ export abstract class Method extends Decorator { * The guards that decorate the method (this) */ get guards() { - const clientGuards = Client.guards.map((guard) => DGuard.create(guard.bind(undefined))); + const clientGuards = Client.guards.map((guard) => + DGuard.create(guard.bind(undefined)) + ); return [ ...clientGuards, ...this.discord.guards, ...this._guards, - DGuard.create(this._method.bind(this._discord.instance)) + DGuard.create(this._method.bind(this._discord.instance)), ]; } set guards(value) { @@ -60,11 +62,7 @@ export abstract class Method extends Decorator { * Execute a guard with params */ getGuardFunction(): (...params: any[]) => Promise { - const next = async ( - params: any, - index: number, - paramsToNext: any - ) => { + const next = async (params: any, index: number, paramsToNext: any) => { const nextFn = () => next(params, index + 1, paramsToNext); const guardToExecute = this.guards[index]; let res: any; @@ -73,18 +71,14 @@ export abstract class Method extends Decorator { // If it's the main method res = await (guardToExecute.fn as any)( // method(...ParsedOptions, [Interaction, Client], ...) => method(...ParsedOptions, Interaction, Client, ...) - ...this.parseParams(...params as any), + ...this.parseParams(...(params as any)), ...params, paramsToNext ); } else { // If it's the guards // method([Interaction, Client]) - res = await (guardToExecute.fn as any)( - ...params, - nextFn, - paramsToNext - ); + res = await (guardToExecute.fn as any)(...params, nextFn, paramsToNext); } if (res) { @@ -96,4 +90,4 @@ export abstract class Method extends Decorator { return (...params: any[]) => next(params, 0, {}); } -} \ No newline at end of file +} diff --git a/src/decorators/classes/Modifier.ts b/src/decorators/classes/Modifier.ts index 233b57af..1334ea4f 100644 --- a/src/decorators/classes/Modifier.ts +++ b/src/decorators/classes/Modifier.ts @@ -31,7 +31,7 @@ export class Modifier extends Decorator { * that are on the targets type of modification * @param modifiers The modifier list * @param originals The list of objects to modify - * @returns + * @returns */ static async applyFromModifierListToList( modifiers: Modifier[], @@ -43,7 +43,7 @@ export class Modifier extends Decorator { let linked = DecoratorUtils.getLinkedObjects(modifier, originals); // Filter the linked objects to match the target types of modification - linked = linked.filter((l) => + linked = linked.filter((l) => modifier._modifyTypes.includes((l as Object).constructor) ); diff --git a/src/decorators/decorators/Choice.ts b/src/decorators/decorators/Choice.ts index 051f638d..c08e4b77 100644 --- a/src/decorators/decorators/Choice.ts +++ b/src/decorators/decorators/Choice.ts @@ -6,10 +6,7 @@ export function Choice(name: string, value: string | number) { return async (target: Object, key: string, index: number) => { MetadataStorage.instance.addModifier( Modifier.create(async (original) => { - original.choices = [ - ...original.choices, - DChoice.create(name, value), - ]; + original.choices = [...original.choices, DChoice.create(name, value)]; }, DOption).decorate( target.constructor, key, diff --git a/src/decorators/decorators/Choices.ts b/src/decorators/decorators/Choices.ts index addd6334..941245f2 100644 --- a/src/decorators/decorators/Choices.ts +++ b/src/decorators/decorators/Choices.ts @@ -1,4 +1,10 @@ -import { MetadataStorage, DChoice, DOption, Modifier, ChoicesType } from "../.."; +import { + MetadataStorage, + DChoice, + DOption, + Modifier, + ChoicesType, +} from "../.."; export function Choices(choices: ChoicesType); export function Choices(choices: ChoicesType) { @@ -8,10 +14,7 @@ export function Choices(choices: ChoicesType) { const arrayChoices = Object.keys(choices).map((key) => { return DChoice.create(key, choices[key]); }); - original.choices = [ - ...original.choices, - ...arrayChoices, - ]; + original.choices = [...original.choices, ...arrayChoices]; }, DOption).decorate( target.constructor, key, diff --git a/src/decorators/decorators/Discord.ts b/src/decorators/decorators/Discord.ts index e2030907..498dc1c1 100644 --- a/src/decorators/decorators/Discord.ts +++ b/src/decorators/decorators/Discord.ts @@ -1,10 +1,5 @@ import * as Glob from "glob"; -import { - MetadataStorage, - DiscordParams, - DDiscord, - DIService, -} from "../.."; +import { MetadataStorage, DiscordParams, DDiscord, DIService } from "../.."; /** * Import the commands when using @Discord({ imports: [...] }) @@ -65,10 +60,7 @@ export function Discord(params?: DiscordParams) { }); } - const instance = DDiscord.create(target.name).decorate( - target, - target.name - ); + const instance = DDiscord.create(target.name).decorate(target, target.name); MetadataStorage.instance.addDiscord(instance); }; diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index d2df86ea..553ed922 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -7,7 +7,11 @@ export function Group(group: string); export function Group(subCommands: SubCommand); export function Group(group: string, description: string); export function Group(group: string, subCommands: SubCommand); -export function Group(group: string, description: string, subCommands: SubCommand); +export function Group( + group: string, + description: string, + subCommands: SubCommand +); export function Group( groupOrSubcommands: string | SubCommand, subCommandsOrDescription?: SubCommand | string, @@ -20,27 +24,28 @@ export function Group( ) => { // Detect the type of parameters for overloading const isGroup = typeof groupOrSubcommands === "string"; - const group = isGroup ? (groupOrSubcommands as string).toLocaleLowerCase() : undefined; + const group = isGroup + ? (groupOrSubcommands as string).toLocaleLowerCase() + : undefined; const isDescription = typeof subCommandsOrDescription === "string"; - const description = isDescription ? subCommandsOrDescription as string : undefined; + const description = isDescription + ? (subCommandsOrDescription as string) + : undefined; if (subCommandsOrDescription !== undefined && !isDescription) { subCommands = subCommandsOrDescription as SubCommand; } - subCommands = isGroup ? subCommands : groupOrSubcommands as SubCommand; + subCommands = isGroup ? subCommands : (groupOrSubcommands as SubCommand); if (!descriptor) { // Add the group to groups if @Group decorate a class if (group) { const group = DGroup.create( - groupOrSubcommands as string || key, + (groupOrSubcommands as string) || key, { description } - ).decorate( - target as Function, - (target as Function).name - ); + ).decorate(target as Function, (target as Function).name); MetadataStorage.instance.addGroup(group); } @@ -48,13 +53,9 @@ export function Group( // Create a subgroup if @Group decorate a method if (subCommands) { Object.keys(subCommands).forEach((key) => { - const group = DGroup.create( - key, - { description: subCommands[key] } - ).decorate( - target as Function, - (target as Function).name - ); + const group = DGroup.create(key, { + description: subCommands[key], + }).decorate(target as Function, (target as Function).name); MetadataStorage.instance.addSubGroup(group); }); diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index 0b8de8d1..583de5d5 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -1,4 +1,10 @@ -import { MetadataStorage, GuardFunction, DGuard, Modifier, Method } from "../.."; +import { + MetadataStorage, + GuardFunction, + DGuard, + Modifier, + Method, +} from "../.."; import { DDiscord } from "../classes/DDiscord"; import { DOn } from "../classes/DOn"; import { DSlash } from "../classes/DSlash"; @@ -12,17 +18,18 @@ export function Guard( descriptor?: PropertyDescriptor ): void => { const guards = fns.map((fn) => { - return DGuard.create(fn).decorateUnknown( - target, - key, - descriptor - ); + return DGuard.create(fn).decorateUnknown(target, key, descriptor); }); MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { - original.guards = guards; - }, DSlash, DOn, DDiscord).decorateUnknown(target, key, descriptor) + Modifier.create( + async (original) => { + original.guards = guards; + }, + DSlash, + DOn, + DDiscord + ).decorateUnknown(target, key, descriptor) ); }; } diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index 50ca2300..30d6f241 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -11,21 +11,27 @@ export function Guild(...guildIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { - original.guilds = [ - ...original.guilds, - ...guildIDs.filter(guildID => !original.guilds.includes(guildID)) - ]; + Modifier.create( + async (original) => { + original.guilds = [ + ...original.guilds, + ...guildIDs.filter((guildID) => !original.guilds.includes(guildID)), + ]; - if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { - slash.guilds = [ - ...slash.guilds, - ...guildIDs.filter(guildID => !slash.guilds.includes(guildID)) - ]; - }); - } - }, DSlash, DDiscord).decorateUnknown(target, key, descriptor) + if (original instanceof DDiscord) { + original.slashes.forEach((slash) => { + slash.guilds = [ + ...slash.guilds, + ...guildIDs.filter( + (guildID) => !slash.guilds.includes(guildID) + ), + ]; + }); + } + }, + DSlash, + DDiscord + ).decorateUnknown(target, key, descriptor) ); }; } diff --git a/src/decorators/decorators/Name.ts b/src/decorators/decorators/Name.ts index 530f7336..3fd8441c 100644 --- a/src/decorators/decorators/Name.ts +++ b/src/decorators/decorators/Name.ts @@ -8,9 +8,13 @@ export function Name(name: string) { descriptor?: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { - original.name = name; - }, DSlash, DDiscord).decorateUnknown(target, key, descriptor) + Modifier.create( + async (original) => { + original.name = name; + }, + DSlash, + DDiscord + ).decorateUnknown(target, key, descriptor) ); }; } diff --git a/src/decorators/decorators/On.ts b/src/decorators/decorators/On.ts index 57bfc09b..de975446 100644 --- a/src/decorators/decorators/On.ts +++ b/src/decorators/decorators/On.ts @@ -1,17 +1,20 @@ import { MetadataStorage, DiscordEvents, DOn } from "../.."; +import { EventParams } from "../params/EventParams"; /** * Trigger a discord event * @link https://github.com/OwenCalvin/discord.ts#client-payload-injection * @param event The discord event to trigger */ -export function On(event: DiscordEvents) { +export function On(event: DiscordEvents); +export function On(event: DiscordEvents, params?: EventParams); +export function On(event: DiscordEvents, params?: EventParams) { return ( target: Object, key: string, descriptor?: PropertyDescriptor ): void => { - const on = DOn.create(event, false).decorate( + const on = DOn.create(event, false, params).decorate( target.constructor, key, descriptor.value diff --git a/src/decorators/decorators/Once.ts b/src/decorators/decorators/Once.ts index 748150d7..d927fd48 100644 --- a/src/decorators/decorators/Once.ts +++ b/src/decorators/decorators/Once.ts @@ -1,17 +1,20 @@ import { MetadataStorage, DiscordEvents, DOn } from "../.."; +import { EventParams } from "../params/EventParams"; /** * Trigger a discord event only once * @link https://github.com/OwenCalvin/discord.ts#client-payload-injection * @param event The discord event to trigger */ -export function Once(event: DiscordEvents) { +export function Once(event: DiscordEvents); +export function Once(event: DiscordEvents, params?: EventParams); +export function Once(event: DiscordEvents, params?: EventParams) { return ( target: Object, key: string, descriptor: PropertyDescriptor ): void => { - const on = DOn.create(event, true).decorate( + const on = DOn.create(event, true, params).decorate( target.constructor, key, descriptor.value diff --git a/src/decorators/decorators/Option.ts b/src/decorators/decorators/Option.ts index c9295dce..e324729b 100644 --- a/src/decorators/decorators/Option.ts +++ b/src/decorators/decorators/Option.ts @@ -41,22 +41,13 @@ export function Option( finalParams?.description, finalParams?.required, index - ).decorate( - target.constructor, - key, - target[key], - target.constructor, - index - ); + ).decorate(target.constructor, key, target[key], target.constructor, index); option.isNode = true; MetadataStorage.instance.addModifier( Modifier.create(async (original) => { - original.options = [ - ...original.options, - option - ]; + original.options = [...original.options, option]; }, DSlash).decorate( target.constructor, key, diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index ab53f101..2b5518fa 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -6,26 +6,26 @@ export function Permission(id: string, type: PermissionType); export function Permission(id: string, type: PermissionType) { const permission = { id, - type + type, }; - return ( - target: Object, - key: string, - descriptor: PropertyDescriptor - ) => { + return (target: Object, key: string, descriptor: PropertyDescriptor) => { MetadataStorage.instance.addModifier( - Modifier.create((original) => { - original.defaultPermission = false; - original.permissions = [...original.permissions, permission]; + Modifier.create( + (original) => { + original.defaultPermission = false; + original.permissions = [...original.permissions, permission]; - if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { - slash.defaultPermission = false; - slash.permissions = [...slash.permissions, permission]; - }); - } - }, DSlash, DDiscord).decorateUnknown(target, key, descriptor) + if (original instanceof DDiscord) { + original.slashes.forEach((slash) => { + slash.defaultPermission = false; + slash.permissions = [...slash.permissions, permission]; + }); + } + }, + DSlash, + DDiscord + ).decorateUnknown(target, key, descriptor) ); }; } diff --git a/src/decorators/decorators/Slash.ts b/src/decorators/decorators/Slash.ts index f5f57c65..60327224 100644 --- a/src/decorators/decorators/Slash.ts +++ b/src/decorators/decorators/Slash.ts @@ -4,18 +4,17 @@ export function Slash(); export function Slash(name: string); export function Slash(name: string, params: SlashParams); export function Slash(name?: string, params?: SlashParams) { - return ( - target: Object, - key: string - ) => { + return (target: Object, key: string) => { name = name || key; name = name.toLocaleLowerCase(); - const slash = DSlash.create(name, params?.description, params?.defaultPermission, params?.guilds, params?.botIds).decorate( - target.constructor, - key, - target[key] - ); + const slash = DSlash.create( + name, + params?.description, + params?.defaultPermission, + params?.guilds, + params?.botIds + ).decorate(target.constructor, key, target[key]); MetadataStorage.instance.addSlash(slash); }; diff --git a/src/decorators/params/EventParams.ts b/src/decorators/params/EventParams.ts new file mode 100644 index 00000000..5ac608d2 --- /dev/null +++ b/src/decorators/params/EventParams.ts @@ -0,0 +1,3 @@ +export interface EventParams { + botIds?: string[]; +} diff --git a/src/logic/index.ts b/src/logic/index.ts index 740afa2b..de8c62fb 100644 --- a/src/logic/index.ts +++ b/src/logic/index.ts @@ -1,5 +1,3 @@ export * from "./metadatas/MetadataStorage"; - export * from "./utils/DecoratorUtils"; - export * from "./di/DIService"; diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 9e1dd2d7..10baecbd 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -9,7 +9,7 @@ import { DIService, DSlash, DOption, - Method + Method, } from "../.."; import { DGroup } from "../../decorators"; @@ -45,21 +45,16 @@ export class MetadataStorage { * Get the list of used events without duplications */ get usedEvents() { - return this.events.reduce( - (prev, event, index) => { - const found = this.events.find( - (event2) => event.event === event2.event - ); - const foundIndex = this.events.indexOf(found); - - if (foundIndex === index || found.once !== event.once) { - prev.push(event); - } + return this.events.reduce((prev, event, index) => { + const found = this.events.find((event2) => event.event === event2.event); + const foundIndex = this.events.indexOf(found); + + if (foundIndex === index || found.once !== event.once) { + prev.push(event); + } - return prev; - }, - [] - ) as readonly DOn[]; + return prev; + }, []) as readonly DOn[]; } get discords() { @@ -83,10 +78,7 @@ export class MetadataStorage { } private get discordMembers(): readonly Method[] { - return [ - ...this._slashes, - ...this._events, - ]; + return [...this._slashes, ...this._events]; } addModifier(modifier: Modifier) { @@ -143,7 +135,7 @@ export class MetadataStorage { discord.events.push(member); } }); - + await Modifier.applyFromModifierListToList(this._modifiers, this._discords); await Modifier.applyFromModifierListToList(this._modifiers, this._events); await Modifier.applyFromModifierListToList(this._modifiers, this._slashes); @@ -180,11 +172,7 @@ export class MetadataStorage { const slashParent = DSlash.create( group.name, group.infos.description - ).decorate( - group.classRef, - group.key, - group.method - ); + ).decorate(group.classRef, group.key, group.method); slashParent.discord = this._discords.find((instance) => { return instance.from === slashParent.from; @@ -192,7 +180,7 @@ export class MetadataStorage { slashParent.guilds = [ ...Client.slashGuilds, - ...slashParent.discord.guilds + ...slashParent.discord.guilds, ]; slashParent.permissions = slashParent.discord.permissions; @@ -226,11 +214,7 @@ export class MetadataStorage { subGroup.name, "SUB_COMMAND_GROUP", subGroup.infos.description - ).decorate( - subGroup.classRef, - subGroup.key, - subGroup.method - ); + ).decorate(subGroup.classRef, subGroup.key, subGroup.method); // Get the slashes that are in this subgroup const slashes = this._slashes.filter((slash) => { @@ -262,7 +246,7 @@ export class MetadataStorage { slashes.forEach((slash) => { option.options.push(slash.toSubCommand()); }); - + // The the root option to the root Slash command const groupSlash = groupedSlashes.get(slashes[0].group); if (groupSlash) { @@ -272,7 +256,7 @@ export class MetadataStorage { return [ ...this._slashes.filter((s) => !s.group && !s.subgroup), - ...Array.from(groupedSlashes.values()) + ...Array.from(groupedSlashes.values()), ]; } @@ -286,14 +270,11 @@ export class MetadataStorage { event: Event, client: Client, once = false - ): ((...params: ArgsOf) => Promise) { + ): (...params: ArgsOf) => Promise { const responses: any[] = []; const eventsToExecute = this._events.filter((on) => { - return ( - on.event === event && - on.once === once - ); + return on.event === event && on.once === once; }); return async (...params: ArgsOf) => { diff --git a/src/logic/utils/DecoratorUtils.ts b/src/logic/utils/DecoratorUtils.ts index 84beed83..0f7e4365 100644 --- a/src/logic/utils/DecoratorUtils.ts +++ b/src/logic/utils/DecoratorUtils.ts @@ -3,16 +3,16 @@ import { Decorator } from "../.."; export class DecoratorUtils { /** * Get the list of the linked decorators - * + * * A and B are two linked decorators - * + * * @example * ```typescript * .@A() * .@B() * method() {} * ``` - * + * * @example * ```typescript * method( @@ -21,22 +21,19 @@ export class DecoratorUtils { * param: string * ) {} * ``` - * + * * @example * ```typescript * .@A() * .@B() * class X {} * ``` - * + * * @param a The decorator * @param list The list of linked decorators to a - * @returns + * @returns */ - static getLinkedObjects( - a: Decorator, - list: Type[] - ) { + static getLinkedObjects(a: Decorator, list: Type[]) { return list.filter((b) => { let cond = a.from === b.from && a.key === b.key; From 0587f805ffeeaba33af7720fa96ebab3d36d7da9 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 04:39:05 +0530 Subject: [PATCH 018/106] strong type checking --- .eslintrc | 10 ++--- src/decorators/classes/DChoice.ts | 15 +++++--- src/decorators/classes/DDiscord.ts | 11 ++---- src/decorators/classes/DGroup.ts | 4 +- src/decorators/classes/DGuard.ts | 2 +- src/decorators/classes/DOn.ts | 16 ++++---- src/decorators/classes/DOption.ts | 8 ++-- src/decorators/classes/DSlash.ts | 20 +++++----- src/decorators/classes/Decorator.ts | 20 ++++------ src/decorators/classes/Method.ts | 5 ++- src/decorators/classes/Modifier.ts | 4 +- src/decorators/decorators/Discord.ts | 57 ++-------------------------- src/decorators/decorators/Group.ts | 4 +- src/decorators/decorators/On.ts | 4 +- src/decorators/decorators/Once.ts | 2 +- tsconfig.json | 1 + 16 files changed, 66 insertions(+), 117 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0425fe87..3dbcf038 100755 --- a/.eslintrc +++ b/.eslintrc @@ -9,15 +9,15 @@ "rules": { "semi": "error", "quotes": "error", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-function": "warn", - "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-inferrable-types": "warn", "@typescript-eslint/no-non-null-asserted-optional-chain": "warn", - "@typescript-eslint/no-non-null-assertion": "warn" + "@typescript-eslint/no-non-null-assertion": "warn", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-types": "off" } } diff --git a/src/decorators/classes/DChoice.ts b/src/decorators/classes/DChoice.ts index d963fca7..776ba3cf 100644 --- a/src/decorators/classes/DChoice.ts +++ b/src/decorators/classes/DChoice.ts @@ -1,9 +1,9 @@ import { ApplicationCommandOptionChoice } from "discord.js"; import { Decorator } from "../classes/Decorator"; -export class DChoice extends Decorator { +export class DChoice extends Decorator { private _name: string; - private _value: Type; + private _value: string | number; get name() { return this._name; @@ -19,12 +19,15 @@ export class DChoice extends Decorator { this._value = value; } - protected constructor() { + protected constructor(name: string, value: string | number) { super(); + + this._name = name; + this._value = value; } - static create(name: string, value: Type) { - const choice = new DChoice(); + static create(name: string, value: string | number) { + const choice = new DChoice(name, value); choice.name = name; choice.value = value; @@ -35,7 +38,7 @@ export class DChoice extends Decorator { toObject(): ApplicationCommandOptionChoice { return { name: this.name, - value: this.value as any, + value: this.value, }; } } diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index 776caa08..1f56ffda 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -6,7 +6,7 @@ export class DDiscord extends Decorator { private _guards: DGuard[] = []; private _slashes: DSlash[] = []; private _events: DOn[] = []; - private _description: string; + private _description?: string; private _name: string; private _defaultPermission = true; private _permissions: { id: string; type: PermissionType }[] = []; @@ -72,15 +72,12 @@ export class DDiscord extends Decorator { return DIService.instance.getService(this.from); } - protected constructor() { + protected constructor(name: string) { super(); + this._name = name; } static create(name: string) { - const discord = new DDiscord(); - - discord.name = name; - - return discord; + return new DDiscord(name); } } diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index fef6258c..1d3e7005 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -1,8 +1,8 @@ import { Decorator } from "./Decorator"; export class DGroup extends Decorator { - name: string; - infos: Partial; + name: string | undefined; + infos: Partial | undefined; protected constructor() { super(); diff --git a/src/decorators/classes/DGuard.ts b/src/decorators/classes/DGuard.ts index a8aee3de..236cfbe5 100644 --- a/src/decorators/classes/DGuard.ts +++ b/src/decorators/classes/DGuard.ts @@ -2,7 +2,7 @@ import { Decorator } from "./Decorator"; import { GuardFunction } from "../.."; export class DGuard extends Decorator { - protected _fn: GuardFunction; + protected _fn!: GuardFunction; get fn() { return this._fn; diff --git a/src/decorators/classes/DOn.ts b/src/decorators/classes/DOn.ts index 512d967c..8ed96607 100644 --- a/src/decorators/classes/DOn.ts +++ b/src/decorators/classes/DOn.ts @@ -1,11 +1,11 @@ import { DiscordEvents } from "../.."; -import { EventParams } from "../params/EventParams"; import { Method } from "./Method"; export class DOn extends Method { - protected _botIds?: string[]; - protected _event: DiscordEvents; - protected _once: boolean; + // required fix + protected _botIds!: string[]; + protected _event!: DiscordEvents; + protected _once!: boolean; get botIds() { return this._botIds; @@ -32,12 +32,12 @@ export class DOn extends Method { super(); } - static create(event: DiscordEvents, once: boolean, params?: EventParams) { + static create(event: DiscordEvents, once: boolean, botIds: string[]) { const on = new DOn(); - on.event = event; - on.once = once; - on.botIds = params.botIds; + on._event = event; + on._once = once; + on._botIds = botIds; return on; } diff --git a/src/decorators/classes/DOption.ts b/src/decorators/classes/DOption.ts index ec2b7600..07075947 100644 --- a/src/decorators/classes/DOption.ts +++ b/src/decorators/classes/DOption.ts @@ -19,9 +19,9 @@ import { export class DOption extends Decorator { private _required = false; - private _name: string; - private _type: OptionValueType; - private _description: string; + private _name!: string; + private _type!: OptionValueType; + private _description!: string; private _choices: DChoice[] = []; private _options: DOption[] = []; private _isNode = false; @@ -99,6 +99,8 @@ export class DOption extends Decorator { return OptionType.USER; case ClientUser: return OptionType.USER; + default: + return OptionType.STRING; } } diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 3bcea067..92ef3ae8 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -9,15 +9,15 @@ import { DOption, Client, PermissionType } from "../.."; import { Method } from "./Method"; export class DSlash extends Method { - private _description: string; - private _name: string; + private _description!: string; + private _name!: string; private _defaultPermission = true; private _options: DOption[] = []; private _permissions: { id: string; type: PermissionType }[] = []; - private _guilds: string[]; - private _botIds?: string[]; - private _group: string; - private _subgroup: string; + private _guilds!: string[]; + private _botIds!: string[]; + private _group!: string; + private _subgroup!: string; get group() { return this._group; @@ -99,7 +99,7 @@ export class DSlash extends Method { slash.description = description || slash.name; slash.defaultPermission = defaultPermission; slash.guilds = guilds || Client.slashGuilds; - slash.botIds = botIds; + slash.botIds = botIds ?? []; return slash; } @@ -108,7 +108,9 @@ export class DSlash extends Method { const option = DOption.create( this.name, "SUB_COMMAND", - this.description + this.description, + false, + 0 // required fix ).decorate(this.classRef, this.key, this.method, this.from, this.index); option.options = this.options; @@ -152,7 +154,7 @@ export class DSlash extends Method { const options = this.getLastNestedOption(interaction.options); return this.options - .sort((a, b) => a.index - b.index) + .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)) .map((op) => options.find((o) => o.name === op.name)?.value); } } diff --git a/src/decorators/classes/Decorator.ts b/src/decorators/classes/Decorator.ts index 6460a79e..28549543 100644 --- a/src/decorators/classes/Decorator.ts +++ b/src/decorators/classes/Decorator.ts @@ -1,11 +1,12 @@ import { DecoratorUtils } from "../../logic"; export class Decorator { - protected _classRef: Function; - protected _from: Function; - protected _key: string; - protected _method: Function; - protected _index: number = undefined; + // required fix + protected _classRef!: Function; + protected _from!: Function; + protected _key: string | undefined; + protected _method: Function | undefined; + protected _index: number | undefined = undefined; get index() { return this._index; @@ -68,7 +69,7 @@ export class Decorator { decorate( classRef: Function, - key: string, + key?: string, method?: Function, from?: Function, index?: number @@ -78,13 +79,6 @@ export class Decorator { this._key = key; this._method = method; this._index = index; - - this.update(); - return this; } - - update() { - // empty function - } } diff --git a/src/decorators/classes/Method.ts b/src/decorators/classes/Method.ts index 301e6392..a6ca5c13 100644 --- a/src/decorators/classes/Method.ts +++ b/src/decorators/classes/Method.ts @@ -2,7 +2,8 @@ import { DGuard, Client, DDiscord } from "../.."; import { Decorator } from "./Decorator"; export abstract class Method extends Decorator { - protected _discord: DDiscord; + // required fix + protected _discord!: DDiscord; protected _guards: DGuard[] = []; get discord() { @@ -45,7 +46,7 @@ export abstract class Method extends Decorator { ...clientGuards, ...this.discord.guards, ...this._guards, - DGuard.create(this._method.bind(this._discord.instance)), + DGuard.create(this._method?.bind(this._discord.instance)), ]; } set guards(value) { diff --git a/src/decorators/classes/Modifier.ts b/src/decorators/classes/Modifier.ts index 1334ea4f..c91e7fff 100644 --- a/src/decorators/classes/Modifier.ts +++ b/src/decorators/classes/Modifier.ts @@ -6,8 +6,8 @@ export type ModifyFunction = ( ) => any; export class Modifier extends Decorator { - private _toModify: ModifyFunction; - private _modifyTypes: any[]; + private _toModify!: ModifyFunction; + private _modifyTypes!: any[]; protected constructor() { super(); diff --git a/src/decorators/decorators/Discord.ts b/src/decorators/decorators/Discord.ts index 498dc1c1..17c1d435 100644 --- a/src/decorators/decorators/Discord.ts +++ b/src/decorators/decorators/Discord.ts @@ -1,67 +1,16 @@ -import * as Glob from "glob"; -import { MetadataStorage, DiscordParams, DDiscord, DIService } from "../.."; +import { MetadataStorage, DDiscord } from "../.."; +// required comment fix /** * Import the commands when using @Discord({ imports: [...] }) * command.hidden / on.hidden is set to true of the command was imported this way * @param classType The class of the imported command / on * @param target The class of the destination (the class that is decorated by @Discord) */ -function importCommand(classType: Function, target: Function) { - DIService.instance.addService(classType); - const ons = MetadataStorage.instance.events.filter((on) => { - return on.classRef === classType; - }); - - ons.forEach((event) => { - // Set the property hidden to true when - // it's imported - event.from = target; - }); -} - -export function Discord(); -// export function Discord(params: DiscordParams); -export function Discord(params?: DiscordParams) { +export function Discord() { return (target: Function) => { - if (params?.import) { - let importCommands = params?.import || []; - if (!Array.isArray(importCommands)) { - importCommands = [importCommands]; - } - - // For the commands that were imported like @Discord({ import: [...] }) - importCommands.forEach((cmd) => { - if (typeof cmd === "string") { - // For the commands that were imported like @Discord({ import: ["*.ts"] }) - const files = Glob.sync(cmd); - files.forEach((file) => { - let classType; - const classImport = require(file); - if (classImport.default) { - // If the class was exported by default it sets - // the classType to the default export - // export default MyClass - classType = classImport.default; - } else { - // If the class was exported inside a file it sets - // the classType to the first export - // export MyClass - const key = Object.keys(classImport)[0]; - classType = classImport[key]; - } - importCommand(classType, target); - }); - } else { - // For the commands that were imported like @Discord({ import: [MyClass] }) - importCommand(cmd, target); - } - }); - } - const instance = DDiscord.create(target.name).decorate(target, target.name); - MetadataStorage.instance.addDiscord(instance); }; } diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index 553ed922..e4fdc111 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -43,7 +43,7 @@ export function Group( // Add the group to groups if @Group decorate a class if (group) { const group = DGroup.create( - (groupOrSubcommands as string) || key, + (groupOrSubcommands as string) ?? key, { description } ).decorate(target as Function, (target as Function).name); @@ -54,7 +54,7 @@ export function Group( if (subCommands) { Object.keys(subCommands).forEach((key) => { const group = DGroup.create(key, { - description: subCommands[key], + description: subCommands?.[key], }).decorate(target as Function, (target as Function).name); MetadataStorage.instance.addSubGroup(group); diff --git a/src/decorators/decorators/On.ts b/src/decorators/decorators/On.ts index de975446..c08fd0fe 100644 --- a/src/decorators/decorators/On.ts +++ b/src/decorators/decorators/On.ts @@ -14,10 +14,10 @@ export function On(event: DiscordEvents, params?: EventParams) { key: string, descriptor?: PropertyDescriptor ): void => { - const on = DOn.create(event, false, params).decorate( + const on = DOn.create(event, false, params?.botIds ?? []).decorate( target.constructor, key, - descriptor.value + descriptor?.value ); MetadataStorage.instance.addOn(on); diff --git a/src/decorators/decorators/Once.ts b/src/decorators/decorators/Once.ts index d927fd48..b41ed7b1 100644 --- a/src/decorators/decorators/Once.ts +++ b/src/decorators/decorators/Once.ts @@ -14,7 +14,7 @@ export function Once(event: DiscordEvents, params?: EventParams) { key: string, descriptor: PropertyDescriptor ): void => { - const on = DOn.create(event, true, params).decorate( + const on = DOn.create(event, true, params?.botIds ?? []).decorate( target.constructor, key, descriptor.value diff --git a/tsconfig.json b/tsconfig.json index 78867a43..16bf918b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "target": "es2019", "noImplicitAny": false, "sourceMap": true, + "strict": true /* Enable all strict type-checking options. */, "outDir": "build", "emitDecoratorMetadata": true, "experimentalDecorators": true, From a0aad89a0f25d4dc14e988b06ca5e8158f9f1a89 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 04:40:23 +0530 Subject: [PATCH 019/106] fix empty constructor --- src/decorators/classes/Decorator.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/decorators/classes/Decorator.ts b/src/decorators/classes/Decorator.ts index 28549543..de7d1f82 100644 --- a/src/decorators/classes/Decorator.ts +++ b/src/decorators/classes/Decorator.ts @@ -39,10 +39,6 @@ export class Decorator { return !!this._method; } - protected constructor() { - // empty constructor - } - decorateUnknown( classRef: Function | Object, key?: string, From f73bd73fb58507a15708da09a028769334a6721d Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 04:43:02 +0530 Subject: [PATCH 020/106] DGroup type fix --- src/decorators/classes/DGroup.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index 1d3e7005..31c8f162 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -1,6 +1,7 @@ +import { DSlash, DOption } from ".."; import { Decorator } from "./Decorator"; -export class DGroup extends Decorator { +export class DGroup extends Decorator { name: string | undefined; infos: Partial | undefined; @@ -8,7 +9,10 @@ export class DGroup extends Decorator { super(); } - static create(name: string, infos?: Partial) { + static create( + name: string, + infos?: Partial + ) { const group = new DGroup(); group.name = name.toLowerCase(); From 56cf961f0d241e3823e412dc52355b95f743f1db Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 04:53:24 +0530 Subject: [PATCH 021/106] ModifyFunction from it's usage --- src/decorators/classes/Modifier.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/decorators/classes/Modifier.ts b/src/decorators/classes/Modifier.ts index c91e7fff..3a67fce8 100644 --- a/src/decorators/classes/Modifier.ts +++ b/src/decorators/classes/Modifier.ts @@ -1,13 +1,21 @@ import { Decorator } from "./Decorator"; import { DecoratorUtils } from "../../logic/utils/DecoratorUtils"; +import { DSlash, DDiscord, DOption } from ".."; +import { DOn } from "./DOn"; export type ModifyFunction = ( original: ToModify -) => any; +) => void; export class Modifier extends Decorator { private _toModify!: ModifyFunction; - private _modifyTypes!: any[]; + private _modifyTypes!: ( + | typeof DSlash + | typeof DDiscord + | typeof DOption + | typeof DOn + | Function + )[]; protected constructor() { super(); @@ -15,7 +23,12 @@ export class Modifier extends Decorator { static create( toModify: ModifyFunction, - ...modifyTypes: any[] + ...modifyTypes: ( + | typeof DSlash + | typeof DDiscord + | typeof DOption + | typeof DOn + )[] ) { const modifier = new Modifier(); From dcb582bf3842bdedc0445b782793bcae1554a408 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 10:19:35 +0530 Subject: [PATCH 022/106] Client type fix --- src/Client.ts | 120 +++++++++++++------------ src/decorators/classes/DGroup.ts | 2 +- src/logic/metadatas/MetadataStorage.ts | 16 ++-- 3 files changed, 75 insertions(+), 63 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 2766d829..9a081826 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -120,15 +120,15 @@ export class Client extends ClientJS { * Create your bot * @param options { silent: boolean, loadClasses: LoadClass[] } */ - constructor(options?: ClientOptions) { + constructor(options: ClientOptions) { super(options); this._silent = !!options?.silent; this._loadClasses = options?.classes || []; this.guards = options.guards || []; - this.requiredByDefault = options.requiredByDefault; + this.requiredByDefault = options.requiredByDefault ?? true; this.slashGuilds = options.slashGuilds || []; - this.botId = options.botId; + this._botId = options.botId; } /** @@ -237,11 +237,11 @@ export class Client extends ClientJS { // filter commands to update const updated = slashes - .map<[ApplicationCommand, DSlash]>((s) => [ + .map<[ApplicationCommand | undefined, DSlash]>((s) => [ existing.find((c) => c.name === s.name), s, ]) - .filter((s) => s[0]); + .map((s) => s !== undefined); // filter commands to delete const deleted = existing.filter( @@ -249,6 +249,7 @@ export class Client extends ClientJS { !this.slashes.find( (bs) => s.name === bs.name && + s.guild && bs.guilds.includes(s.guild.id) && (!bs.botIds || bs.botIds.includes(this.botId)) ) @@ -256,21 +257,21 @@ export class Client extends ClientJS { if (!this.silent) console.log( - `${this.user.username} >> guild: #${guild} >> command >> adding ${ + `${this.user?.username} >> guild: #${guild} >> command >> adding ${ added.length } [${added.map((s) => s.name).join(", ")}]` ); if (!this.silent) console.log( - `${this.user.username} >> guild: #${guild} >> command >> deleting ${ + `${this.user?.username} >> guild: #${guild} >> command >> deleting ${ deleted.size } [${deleted.map((s) => s.name).join(", ")}]` ); if (!this.silent) console.log( - `${this.user.username} >> guild: #${guild} >> command >> updating ${updated.length}` + `${this.user?.username} >> guild: #${guild} >> command >> updating ${updated.length}` ); await Promise.all([ @@ -281,44 +282,45 @@ export class Client extends ClientJS { } // # init global commands - const existing = (await this.fetchSlash()).filter((s) => !s.guild); + const existing = (await this.fetchSlash())?.filter((s) => !s.guild); const slashes = this.slashes.filter((s) => !s.guilds?.length); - - const added = slashes.filter( - (s) => !existing.find((c) => c.name === s.name) - ); - const updated = slashes - .map<[ApplicationCommand, DSlash]>((s) => [ - existing.find((c) => c.name === s.name), - s, - ]) - .filter((s) => s[0]); - const deleted = existing.filter((c) => - slashes.every((s) => s.name !== c.name) - ); - - if (!this.silent) - console.log( - `${this.user.username} >> global >> command >> adding ${ - added.length - } [${added.map((s) => s.name).join(", ")}]` - ); - if (!this.silent) - console.log( - `${this.user.username} >> global >> command >> deleting ${ - deleted.size - } [${deleted.map((s) => s.name).join(", ")}]` + if (existing) { + const added = slashes.filter( + (s) => !existing.find((c) => c.name === s.name) ); - if (!this.silent) - console.log( - `${this.user.username} >> global >> command >> updating ${updated.length}` + const updated = slashes + .map<[ApplicationCommand | undefined, DSlash]>((s) => [ + existing.find((c) => c.name === s.name), + s, + ]) + .map((s) => s !== undefined); + const deleted = existing.filter((c) => + slashes.every((s) => s.name !== c.name) ); - await Promise.all([ - ...added.map((s) => this.application.commands.create(s.toObject())), - ...updated.map((s) => s[0].edit(s[1].toObject())), - ...deleted.map((key) => this.application.commands.delete(key)), - ]); + if (!this.silent) + console.log( + `${this.user?.username} >> global >> command >> adding ${ + added.length + } [${added.map((s) => s.name).join(", ")}]` + ); + if (!this.silent) + console.log( + `${this.user?.username} >> global >> command >> deleting ${ + deleted.size + } [${deleted.map((s) => s.name).join(", ")}]` + ); + if (!this.silent) + console.log( + `${this.user?.username} >> global >> command >> updating ${updated.length}` + ); + + await Promise.all([ + ...added.map((s) => this.application?.commands.create(s.toObject())), + ...updated.map((s) => s[0].edit(s[1].toObject())), + ...deleted.map((key) => this.application?.commands.delete(key)), + ]); + } } /** @@ -334,7 +336,7 @@ export class Client extends ClientJS { } return await guild.commands.fetch(); } - return await this.application.commands.fetch(); + return await this.application?.commands.fetch(); } /** @@ -347,23 +349,27 @@ export class Client extends ClientJS { guilds.map(async (guild) => { // Select and delete the commands of each guild const commands = await this.fetchSlash(guild); - await Promise.all( - commands.map(async (value) => { - await this.guilds.cache - .get(guild as Snowflake) - .commands.delete(value); - }) - ); + if (commands && this.guilds.cache !== undefined) + await Promise.all( + commands.map(async (value) => { + const guildManager = await this.guilds.cache.get( + guild as Snowflake + ); + if (guildManager) guildManager.commands.delete(value); + }) + ); }) ); } else { // Select and delete the commands of each guild const commands = await this.fetchSlash(); - await Promise.all( - commands.map(async (value) => { - await this.application.commands.delete(value); - }) - ); + if (commands) { + await Promise.all( + commands.map(async (value) => { + await this.application?.commands.delete(value); + }) + ); + } } } @@ -376,7 +382,7 @@ export class Client extends ClientJS { * @returns The group tree */ getInteractionGroupTree(interaction: CommandInteraction) { - const tree = []; + const tree: string[] = []; const getOptionsTree = (option: Partial) => { if (!option) return; @@ -386,7 +392,7 @@ export class Client extends ClientJS { option.type === "SUB_COMMAND_GROUP" || option.type === "SUB_COMMAND" ) { - tree.push(option.name); + if (option.name) tree.push(option.name); return getOptionsTree(Array.from(option.options?.values() || [])?.[0]); } }; diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index 31c8f162..a4f43706 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -2,7 +2,7 @@ import { DSlash, DOption } from ".."; import { Decorator } from "./Decorator"; export class DGroup extends Decorator { - name: string | undefined; + name!: string; infos: Partial | undefined; protected constructor() { diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 10baecbd..36a2094d 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -47,9 +47,9 @@ export class MetadataStorage { get usedEvents() { return this.events.reduce((prev, event, index) => { const found = this.events.find((event2) => event.event === event2.event); - const foundIndex = this.events.indexOf(found); + const foundIndex = found ? this.events.indexOf(found) : -1; - if (foundIndex === index || found.once !== event.once) { + if (foundIndex === index || found?.once !== event.once) { prev.push(event); } @@ -123,6 +123,8 @@ export class MetadataStorage { return instance.from === member.from; }); + if (!discord) return; + // You can get the @Discord that wrap a @Command/@On by using // on.discord or slash.discord member.discord = discord; @@ -171,13 +173,17 @@ export class MetadataStorage { this._groups.forEach((group) => { const slashParent = DSlash.create( group.name, - group.infos.description + group.infos?.description ).decorate(group.classRef, group.key, group.method); - slashParent.discord = this._discords.find((instance) => { + const discord = this._discords.find((instance) => { return instance.from === slashParent.from; }); + if (!discord) return; + + slashParent.discord = discord; + slashParent.guilds = [ ...Client.slashGuilds, ...slashParent.discord.guilds, @@ -213,7 +219,7 @@ export class MetadataStorage { const option = DOption.create( subGroup.name, "SUB_COMMAND_GROUP", - subGroup.infos.description + subGroup.infos?.description ).decorate(subGroup.classRef, subGroup.key, subGroup.method); // Get the slashes that are in this subgroup From 6479166dbfa441b7b6d5e43f3121d372e8f8c032 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 11:22:05 +0530 Subject: [PATCH 023/106] classes code fix --- src/decorators/classes/DChoice.ts | 7 +---- src/decorators/classes/DGroup.ts | 29 +++++++++++------ src/decorators/classes/DGuard.ts | 11 +++---- src/decorators/classes/DOn.ts | 20 +++++------- src/decorators/classes/DOption.ts | 36 ++++++++++++--------- src/decorators/classes/DSlash.ts | 43 ++++++++++++++++---------- src/decorators/classes/Decorator.ts | 1 - src/decorators/classes/Method.ts | 1 - src/decorators/decorators/Discord.ts | 3 -- src/logic/metadatas/MetadataStorage.ts | 4 ++- tsconfig.json | 2 +- 11 files changed, 85 insertions(+), 72 deletions(-) diff --git a/src/decorators/classes/DChoice.ts b/src/decorators/classes/DChoice.ts index 776ba3cf..175d1b6e 100644 --- a/src/decorators/classes/DChoice.ts +++ b/src/decorators/classes/DChoice.ts @@ -27,12 +27,7 @@ export class DChoice extends Decorator { } static create(name: string, value: string | number) { - const choice = new DChoice(name, value); - - choice.name = name; - choice.value = value; - - return choice; + return new DChoice(name, value); } toObject(): ApplicationCommandOptionChoice { diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index a4f43706..1be61514 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -2,22 +2,33 @@ import { DSlash, DOption } from ".."; import { Decorator } from "./Decorator"; export class DGroup extends Decorator { - name!: string; - infos: Partial | undefined; + private _name: string; + private _infos?: Partial; - protected constructor() { + protected constructor(name: string, infos?: Partial) { super(); + this._name = name; + this._infos = infos; + } + + get name() { + return this._name; + } + set name(value) { + this._name = value; + } + + get infos() { + return this._infos; + } + set infos(value) { + this._infos = value; } static create( name: string, infos?: Partial ) { - const group = new DGroup(); - - group.name = name.toLowerCase(); - group.infos = infos; - - return group; + return new DGroup(name.toLowerCase(), infos); } } diff --git a/src/decorators/classes/DGuard.ts b/src/decorators/classes/DGuard.ts index 236cfbe5..a75906b6 100644 --- a/src/decorators/classes/DGuard.ts +++ b/src/decorators/classes/DGuard.ts @@ -2,21 +2,18 @@ import { Decorator } from "./Decorator"; import { GuardFunction } from "../.."; export class DGuard extends Decorator { - protected _fn!: GuardFunction; + protected _fn: GuardFunction; get fn() { return this._fn; } - protected constructor() { + protected constructor(fn: GuardFunction) { super(); + this._fn = fn; } static create(fn: GuardFunction) { - const guard = new DGuard(); - - guard._fn = fn; - - return guard; + return new DGuard(fn); } } diff --git a/src/decorators/classes/DOn.ts b/src/decorators/classes/DOn.ts index 8ed96607..42926afb 100644 --- a/src/decorators/classes/DOn.ts +++ b/src/decorators/classes/DOn.ts @@ -2,10 +2,9 @@ import { DiscordEvents } from "../.."; import { Method } from "./Method"; export class DOn extends Method { - // required fix - protected _botIds!: string[]; - protected _event!: DiscordEvents; - protected _once!: boolean; + protected _botIds: string[]; + protected _event: DiscordEvents; + protected _once: boolean; get botIds() { return this._botIds; @@ -28,18 +27,15 @@ export class DOn extends Method { this._once = value; } - protected constructor() { + protected constructor(event, once, botIds) { super(); + this._event = event; + this._once = once; + this._botIds = botIds; } static create(event: DiscordEvents, once: boolean, botIds: string[]) { - const on = new DOn(); - - on._event = event; - on._once = once; - on._botIds = botIds; - - return on; + return new DOn(event, once, botIds); } parseParams() { diff --git a/src/decorators/classes/DOption.ts b/src/decorators/classes/DOption.ts index 07075947..ea925faa 100644 --- a/src/decorators/classes/DOption.ts +++ b/src/decorators/classes/DOption.ts @@ -19,9 +19,9 @@ import { export class DOption extends Decorator { private _required = false; - private _name!: string; - private _type!: OptionValueType; - private _description!: string; + private _name: string; + private _type: OptionValueType; + private _description: string; private _choices: DChoice[] = []; private _options: DOption[] = []; private _isNode = false; @@ -104,8 +104,19 @@ export class DOption extends Decorator { } } - protected constructor() { + protected constructor(options: { + name: string; + type: OptionValueType; + description: string; + required: boolean; + index?: number; + }) { super(); + this._name = options.name; + this._type = options.type; + this._description = options.description; + this._required = options.required; + this._index = options.index; } static create( @@ -115,16 +126,13 @@ export class DOption extends Decorator { required?: boolean, index?: number ) { - const option = new DOption(); - - option._name = name.toLowerCase(); - option._type = type || String; - option._description = description || `${name} - ${option.stringType}`; - option._required = - required !== undefined ? required : Client.requiredByDefault; - option._index = index; - - return option; + return new DOption({ + name: name.toLowerCase(), + type: type || String, + description: description || `${name}`, + required: required !== undefined ? required : Client.requiredByDefault, + index: index, + }); } toObject(): ApplicationCommandOptionData { diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 92ef3ae8..60772075 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -9,15 +9,15 @@ import { DOption, Client, PermissionType } from "../.."; import { Method } from "./Method"; export class DSlash extends Method { - private _description!: string; - private _name!: string; + private _description: string; + private _name: string; private _defaultPermission = true; private _options: DOption[] = []; private _permissions: { id: string; type: PermissionType }[] = []; - private _guilds!: string[]; - private _botIds!: string[]; - private _group!: string; - private _subgroup!: string; + private _guilds: string[]; + private _botIds: string[]; + private _group?: string; + private _subgroup?: string; get group() { return this._group; @@ -82,8 +82,19 @@ export class DSlash extends Method { this._options = value; } - protected constructor() { + protected constructor(options: { + name: string; + description: string; + defaultPermission: boolean; + guilds: string[]; + botIds: string[]; + }) { super(); + this._name = options.name.toLowerCase(); + this._description = options.description; + this._defaultPermission = options.defaultPermission; + this._guilds = options.guilds || Client.slashGuilds; + this._botIds = options.botIds; } static create( @@ -93,15 +104,13 @@ export class DSlash extends Method { guilds?: string[], botIds?: string[] ) { - const slash = new DSlash(); - - slash.name = name.toLowerCase(); - slash.description = description || slash.name; - slash.defaultPermission = defaultPermission; - slash.guilds = guilds || Client.slashGuilds; - slash.botIds = botIds ?? []; - - return slash; + return new DSlash({ + name: name.toLowerCase(), + description: description ?? name, + defaultPermission: defaultPermission, + guilds: guilds ?? Client.slashGuilds, + botIds: botIds ?? [], + }); } toSubCommand() { @@ -110,7 +119,7 @@ export class DSlash extends Method { "SUB_COMMAND", this.description, false, - 0 // required fix + this.index ).decorate(this.classRef, this.key, this.method, this.from, this.index); option.options = this.options; diff --git a/src/decorators/classes/Decorator.ts b/src/decorators/classes/Decorator.ts index de7d1f82..5d6308ef 100644 --- a/src/decorators/classes/Decorator.ts +++ b/src/decorators/classes/Decorator.ts @@ -1,7 +1,6 @@ import { DecoratorUtils } from "../../logic"; export class Decorator { - // required fix protected _classRef!: Function; protected _from!: Function; protected _key: string | undefined; diff --git a/src/decorators/classes/Method.ts b/src/decorators/classes/Method.ts index a6ca5c13..fba9d02d 100644 --- a/src/decorators/classes/Method.ts +++ b/src/decorators/classes/Method.ts @@ -2,7 +2,6 @@ import { DGuard, Client, DDiscord } from "../.."; import { Decorator } from "./Decorator"; export abstract class Method extends Decorator { - // required fix protected _discord!: DDiscord; protected _guards: DGuard[] = []; diff --git a/src/decorators/decorators/Discord.ts b/src/decorators/decorators/Discord.ts index 17c1d435..25cdb652 100644 --- a/src/decorators/decorators/Discord.ts +++ b/src/decorators/decorators/Discord.ts @@ -1,9 +1,6 @@ import { MetadataStorage, DDiscord } from "../.."; -// required comment fix /** - * Import the commands when using @Discord({ imports: [...] }) - * command.hidden / on.hidden is set to true of the command was imported this way * @param classType The class of the imported command / on * @param target The class of the destination (the class that is decorated by @Discord) */ diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 36a2094d..858f921b 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -254,7 +254,9 @@ export class MetadataStorage { }); // The the root option to the root Slash command - const groupSlash = groupedSlashes.get(slashes[0].group); + const groupSlash = slashes[0].group + ? groupedSlashes.get(slashes[0].group) + : undefined; if (groupSlash) { groupSlash.options.push(option); } diff --git a/tsconfig.json b/tsconfig.json index 16bf918b..eaa00a0d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es2019", - "noImplicitAny": false, + "noImplicitAny": true, "sourceMap": true, "strict": true /* Enable all strict type-checking options. */, "outDir": "build", From c234eea5755d9dbeabefb5695d22305f8e9828a7 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 11:53:39 +0530 Subject: [PATCH 024/106] initslash fix --- src/Client.ts | 10 ++++++++-- tsconfig.json | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 9a081826..2220dd56 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -241,7 +241,9 @@ export class Client extends ClientJS { existing.find((c) => c.name === s.name), s, ]) - .map((s) => s !== undefined); + .filter<[ApplicationCommand, DSlash]>( + (s): s is [ApplicationCommand, DSlash] => s[0] !== undefined + ); // filter commands to delete const deleted = existing.filter( @@ -288,12 +290,16 @@ export class Client extends ClientJS { const added = slashes.filter( (s) => !existing.find((c) => c.name === s.name) ); + const updated = slashes .map<[ApplicationCommand | undefined, DSlash]>((s) => [ existing.find((c) => c.name === s.name), s, ]) - .map((s) => s !== undefined); + .filter<[ApplicationCommand, DSlash]>( + (s): s is [ApplicationCommand, DSlash] => s[0] !== undefined + ); + const deleted = existing.filter((c) => slashes.every((s) => s.name !== c.name) ); diff --git a/tsconfig.json b/tsconfig.json index eaa00a0d..16bf918b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es2019", - "noImplicitAny": true, + "noImplicitAny": false, "sourceMap": true, "strict": true /* Enable all strict type-checking options. */, "outDir": "build", From f81c2c160abcb4d5e7f5ffcd2e20687d2bd57ac9 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 12:01:28 +0530 Subject: [PATCH 025/106] multibot events support fix --- src/logic/metadatas/MetadataStorage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 858f921b..b85ed572 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -287,6 +287,7 @@ export class MetadataStorage { return async (...params: ArgsOf) => { for (const on of eventsToExecute) { + if (on.botIds.length > 0 && !on.botIds.includes(client.botId)) return; const res = await on.execute(params, client); responses.push(res); } From 7314985377dcd639fe1e5fbf9ef7691555e4fee4 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 12:38:43 +0530 Subject: [PATCH 026/106] adde log options for initslash --- src/Client.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 2220dd56..de7ed124 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -199,7 +199,9 @@ export class Client extends ClientJS { /** * Initialize all the @Slash with their permissions */ - async initSlashes() { + async initSlashes(options?: { + log: { forGuild: boolean; forGlobal: boolean }; + }) { // # first init guild's all slash const guildSlashStorage = new Map(); const guildsSlash = this.slashes.filter((s) => s.guilds?.length); @@ -257,24 +259,23 @@ export class Client extends ClientJS { ) ); - if (!this.silent) + if (options?.log.forGuild) { console.log( `${this.user?.username} >> guild: #${guild} >> command >> adding ${ added.length } [${added.map((s) => s.name).join(", ")}]` ); - if (!this.silent) console.log( `${this.user?.username} >> guild: #${guild} >> command >> deleting ${ deleted.size } [${deleted.map((s) => s.name).join(", ")}]` ); - if (!this.silent) console.log( `${this.user?.username} >> guild: #${guild} >> command >> updating ${updated.length}` ); + } await Promise.all([ ...added.map((s) => guild.commands.create(s.toObject())), @@ -304,22 +305,21 @@ export class Client extends ClientJS { slashes.every((s) => s.name !== c.name) ); - if (!this.silent) + if (options?.log.forGlobal) { console.log( `${this.user?.username} >> global >> command >> adding ${ added.length } [${added.map((s) => s.name).join(", ")}]` ); - if (!this.silent) console.log( `${this.user?.username} >> global >> command >> deleting ${ deleted.size } [${deleted.map((s) => s.name).join(", ")}]` ); - if (!this.silent) console.log( `${this.user?.username} >> global >> command >> updating ${updated.length}` ); + } await Promise.all([ ...added.map((s) => this.application?.commands.create(s.toObject())), From c43d6c0fb008dae45bc2739b43450b651b49ee7d Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 12:59:29 +0530 Subject: [PATCH 027/106] init slash fix --- src/Client.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index de7ed124..6d7acf4b 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -468,7 +468,11 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if (!slash || (slash.botIds && !slash.botIds.includes(this.botId))) return; + if ( + !slash || + (slash.botIds.length > 0 && !slash.botIds.includes(this.botId)) + ) + return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); From f4ab388834506022bed7fdabd919ddc187c430b5 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 13:42:12 +0530 Subject: [PATCH 028/106] execute slash fix --- src/Client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 6d7acf4b..77b72dfc 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -234,7 +234,7 @@ export class Client extends ClientJS { const added = slashes.filter( (s) => !existing.find((c) => c.name === s.name) && - (!s.botIds || s.botIds.includes(this.botId)) + (!s.botIds.length || s.botIds.includes(this.botId)) ); // filter commands to update @@ -255,7 +255,7 @@ export class Client extends ClientJS { s.name === bs.name && s.guild && bs.guilds.includes(s.guild.id) && - (!bs.botIds || bs.botIds.includes(this.botId)) + (!bs.botIds.length || bs.botIds.includes(this.botId)) ) ); From 3474122bc04285cc9f3aac891ee0cab50e631b21 Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 13:54:44 +0530 Subject: [PATCH 029/106] init slash fix --- src/Client.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index 77b72dfc..071a567e 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -240,7 +240,11 @@ export class Client extends ClientJS { // filter commands to update const updated = slashes .map<[ApplicationCommand | undefined, DSlash]>((s) => [ - existing.find((c) => c.name === s.name), + existing.find( + (c) => + c.name === s.name && + (!s.botIds.length || s.botIds.includes(this.botId)) + ), s, ]) .filter<[ApplicationCommand, DSlash]>( From 6a27fd3a5b82f9922fc55a92fd7b1b0ad8ad4f9a Mon Sep 17 00:00:00 2001 From: iorp Date: Fri, 2 Jul 2021 16:10:12 +0530 Subject: [PATCH 030/106] * test update * options type update * fixed OwenCalvin/discord.ts/issues/59 --- src/decorators/decorators/Option.ts | 33 +-- src/decorators/params/OptionParams.ts | 3 + src/logic/metadatas/MetadataStorage.ts | 2 +- tests/create-on-events.test.ts | 4 +- tests/slash.test.ts | 315 ++++++++++--------------- 5 files changed, 133 insertions(+), 224 deletions(-) diff --git a/src/decorators/decorators/Option.ts b/src/decorators/decorators/Option.ts index e324729b..cf51aab5 100644 --- a/src/decorators/decorators/Option.ts +++ b/src/decorators/decorators/Option.ts @@ -2,7 +2,6 @@ import "reflect-metadata"; import { MetadataStorage, DOption, - OptionType, OptionValueType, OptionParams, Modifier, @@ -10,36 +9,20 @@ import { import { DSlash } from "../classes/DSlash"; export function Option(name: string); -export function Option(name: string, type: OptionValueType | OptionType); export function Option(name: string, params: OptionParams); -export function Option( - name: string, - type: OptionValueType | OptionType, - params: OptionParams -); -export function Option( - name: string, - typeOrParams?: OptionParams | OptionValueType | OptionType, - params?: OptionParams -) { +export function Option(name: string, params?: OptionParams) { return (target: Object, key: string, index: number) => { - const isParams = typeof typeOrParams === "object"; - let finalParams: OptionParams = params || {}; - let type = Reflect.getMetadata("design:paramtypes", target, key)[ - index - ] as OptionValueType; - - if (isParams) { - finalParams = typeOrParams as OptionParams; - } else if (typeOrParams !== undefined) { - type = typeOrParams as OptionValueType; - } + const type = + params?.type ?? + (Reflect.getMetadata("design:paramtypes", target, key)[ + index + ] as OptionValueType); const option = DOption.create( name || key, type, - finalParams?.description, - finalParams?.required, + params?.description, + params?.required, index ).decorate(target.constructor, key, target[key], target.constructor, index); diff --git a/src/decorators/params/OptionParams.ts b/src/decorators/params/OptionParams.ts index d0459e78..5ae4c12e 100644 --- a/src/decorators/params/OptionParams.ts +++ b/src/decorators/params/OptionParams.ts @@ -1,4 +1,7 @@ +import { OptionType } from "../.."; + export interface OptionParams { + type?: OptionType; description?: string; required?: boolean; } diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index b85ed572..183e2b7a 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -254,7 +254,7 @@ export class MetadataStorage { }); // The the root option to the root Slash command - const groupSlash = slashes[0].group + const groupSlash = slashes?.[0]?.group ? groupedSlashes.get(slashes[0].group) : undefined; if (groupSlash) { diff --git a/tests/create-on-events.test.ts b/tests/create-on-events.test.ts index 32a350ed..85e0ccc7 100644 --- a/tests/create-on-events.test.ts +++ b/tests/create-on-events.test.ts @@ -1,4 +1,4 @@ -import { Discord, On, Client, Guard, GuardFunction, Description } from "../src"; +import { Discord, On, Client, Guard, GuardFunction } from "../src"; const guard1: GuardFunction = async ([message]: [string], client, next, mwDatas) => { @@ -46,7 +46,7 @@ abstract class Bot { } } -const client = new Client({ intents: [] }); +const client = new Client({ botId: "test", intents: [] }); beforeAll(async () => { await client.build(); diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 792bef25..8b534c52 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -1,4 +1,11 @@ -import { Channel, CommandInteraction, CommandInteractionOption, Role, TextChannel, User, VoiceChannel } from "discord.js"; +import { + Channel, + CommandInteraction, + Role, + TextChannel, + User, + VoiceChannel, +} from "discord.js"; import { Discord, Slash, @@ -7,30 +14,23 @@ import { Group, Choices, Client, - DSlash, - DOption, Permission, - OptionValueType, StringOptionType, Guard, - Description + Description, } from "../src"; enum TextChoices { Hello = "Hello", - "Good Bye" = "GoodBye" + "Good Bye" = "GoodBye", } @Discord() @Guild("693401527494377482") -@Group( - "testing", - "Testing group description", - { - maths: "maths group description", - text: "text group description" - } -) +@Group("testing", "Testing group description", { + maths: "maths group description", + text: "text group description", +}) @Guard(async (params, client, next, datas) => { datas.passed = true; return await next(); @@ -48,12 +48,7 @@ export abstract class AppDiscord { client: Client, datas: any ) { - return [ - "/testing maths add", - x + y, - interaction, - datas.passed - ]; + return ["/testing maths add", x + y, interaction, datas.passed]; } @Slash("multiply", { description: "Multiply" }) @@ -67,12 +62,7 @@ export abstract class AppDiscord { client: Client, datas: any ) { - return [ - "/testing maths multiply", - x * y, - interaction, - datas.passed - ]; + return ["/testing maths multiply", x * y, interaction, datas.passed]; } @Slash("hello") @@ -85,12 +75,7 @@ export abstract class AppDiscord { client: Client, datas: any ) { - return [ - "/testing text hello", - text, - interaction, - datas.passed - ]; + return ["/testing text hello", text, interaction, datas.passed]; } @Slash("hello") @@ -103,13 +88,7 @@ export abstract class AppDiscord { client: Client, datas: any ) { - return [ - "/testing hello text", - text, - text2, - interaction, - datas.passed - ]; + return ["/testing hello text", text, text2, interaction, datas.passed]; } } @@ -129,12 +108,7 @@ export abstract class AppDiscord1 { client: Client, datas: any ) { - return [ - "/hello", - text, - interaction, - datas.passed - ]; + return ["/hello", text, interaction, datas.passed]; } @Slash("inferance") @@ -167,16 +141,11 @@ export abstract class AppDiscord1 { client: Client, datas: any ) { - return [ - "/inferance", - "infer", - interaction, - datas.passed - ]; + return ["/inferance", "infer", interaction, datas.passed]; } } -const client = new Client({ intents: [] }); +const client = new Client({ botId: "test", intents: [] }); beforeAll(async () => { await client.build(); @@ -192,7 +161,7 @@ class FakeOption { name: string, type: StringOptionType, value: string | number, - options?: FakeOption[], + options?: FakeOption[] ) { this.type = type; this.name = name; @@ -218,10 +187,12 @@ class FakeInteraction { describe("Slash", () => { it("Should create the slash structure", async () => { expect(client.slashes[0].guilds).toEqual(["invalid_id"]); - expect(client.slashes[0].permissions).toEqual([{ - id: "123", - type: "USER", - }]); + expect(client.slashes[0].permissions).toEqual([ + { + id: "123", + type: "USER", + }, + ]); const slashesObjects = client.slashes.map((slash) => slash.toObject()); expect(slashesObjects).toEqual([ @@ -234,10 +205,8 @@ describe("Slash", () => { name: "text", type: "STRING", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, ], defaultPermission: false, @@ -251,80 +220,64 @@ describe("Slash", () => { name: "text", type: "STRING", required: true, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "bool - BOOLEAN", name: "bool", type: "BOOLEAN", required: true, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "nb - INTEGER", name: "nb", type: "INTEGER", required: true, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "channel - CHANNEL", name: "channel", type: "CHANNEL", required: true, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "textchannel - CHANNEL", name: "textchannel", type: "CHANNEL", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "voicechannel - CHANNEL", name: "voicechannel", type: "CHANNEL", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "user - USER", name: "user", type: "USER", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "role - ROLE", name: "role", type: "ROLE", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, ], defaultPermission: true, @@ -337,15 +290,13 @@ describe("Slash", () => { description: "text group description", name: "text", type: "SUB_COMMAND_GROUP", - choices: [ - ], + choices: [], options: [ { description: "hello", name: "hello", type: "SUB_COMMAND", - choices: [ - ], + choices: [], options: [ { description: "text - STRING", @@ -362,8 +313,7 @@ describe("Slash", () => { value: "GoodBye", }, ], - options: [ - ], + options: [], }, ], }, @@ -373,35 +323,29 @@ describe("Slash", () => { description: "maths group description", name: "maths", type: "SUB_COMMAND_GROUP", - choices: [ - ], + choices: [], options: [ { description: "Multiply", name: "multiply", type: "SUB_COMMAND", - choices: [ - ], + choices: [], options: [ { description: "x value", name: "x", type: "INTEGER", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "y value", name: "y", type: "INTEGER", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, ], }, @@ -409,28 +353,23 @@ describe("Slash", () => { description: "Addition", name: "add", type: "SUB_COMMAND", - choices: [ - ], + choices: [], options: [ { description: "x value", name: "x", type: "INTEGER", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "y value", name: "y", type: "INTEGER", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, ], }, @@ -440,28 +379,23 @@ describe("Slash", () => { description: "hello", name: "hello", type: "SUB_COMMAND", - choices: [ - ], + choices: [], options: [ { description: "text - STRING", name: "text", type: "STRING", required: true, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, { description: "text2 - STRING", name: "text2", type: "STRING", required: false, - choices: [ - ], - options: [ - ], + choices: [], + options: [], }, ], }, @@ -472,105 +406,94 @@ describe("Slash", () => { }); it("Should execute the simple slash", async () => { - const interaction = new FakeInteraction( - "hello", - [ - new FakeOption("text", "STRING", "hello") - ] - ); + const interaction = new FakeInteraction("hello", [ + new FakeOption("text", "STRING", "hello"), + ]); const res = await client.executeSlash(interaction as any); expect(res).toEqual(["/hello", "hello", interaction, true]); }); it("Should execute the simple grouped text slash", async () => { - const interaction = new FakeInteraction( - "testing", - [ - new FakeOption("hello", "SUB_COMMAND", "text", [ - new FakeOption("text", "STRING", "testing hello text"), - new FakeOption("text2", "STRING", "testing hello text2") - ]) - ] - ); + const interaction = new FakeInteraction("testing", [ + new FakeOption("hello", "SUB_COMMAND", "text", [ + new FakeOption("text", "STRING", "testing hello text"), + new FakeOption("text2", "STRING", "testing hello text2"), + ]), + ]); const res = await client.executeSlash(interaction as any); - expect(res).toEqual(["/testing hello text", "testing hello text", "testing hello text2", interaction, true]); + expect(res).toEqual([ + "/testing hello text", + "testing hello text", + "testing hello text2", + interaction, + true, + ]); }); it("Should execute the simple subgrouped text slash", async () => { - const interaction = new FakeInteraction( - "testing", - [ - new FakeOption("text", "SUB_COMMAND_GROUP", "text", [ - new FakeOption("hello", "SUB_COMMAND", "text", [ - new FakeOption("text", "STRING", "testing text hello") - ]) - ]) - ] - ); + const interaction = new FakeInteraction("testing", [ + new FakeOption("text", "SUB_COMMAND_GROUP", "text", [ + new FakeOption("hello", "SUB_COMMAND", "text", [ + new FakeOption("text", "STRING", "testing text hello"), + ]), + ]), + ]); const res = await client.executeSlash(interaction as any); - expect(res).toEqual(["/testing text hello", "testing text hello", interaction, true]); + expect(res).toEqual([ + "/testing text hello", + "testing text hello", + interaction, + true, + ]); }); it("Should execute the simple subgrouped multiply slash", async () => { - const interaction = new FakeInteraction( - "testing", - [ - new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ - new FakeOption("multiply", "SUB_COMMAND", "text", [ - new FakeOption("x", "INTEGER", 2), - new FakeOption("y", "INTEGER", 5) - ]) - ]) - ] - ); + const interaction = new FakeInteraction("testing", [ + new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ + new FakeOption("multiply", "SUB_COMMAND", "text", [ + new FakeOption("x", "INTEGER", 2), + new FakeOption("y", "INTEGER", 5), + ]), + ]), + ]); const res = await client.executeSlash(interaction as any); expect(res).toEqual(["/testing maths multiply", 10, interaction, true]); }); it("Should execute the simple subgrouped addition slash", async () => { - const interaction = new FakeInteraction( - "testing", - [ - new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ - new FakeOption("add", "SUB_COMMAND", "text", [ - new FakeOption("x", "INTEGER", 2), - new FakeOption("y", "INTEGER", 5) - ]) - ]) - ] - ); + const interaction = new FakeInteraction("testing", [ + new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ + new FakeOption("add", "SUB_COMMAND", "text", [ + new FakeOption("x", "INTEGER", 2), + new FakeOption("y", "INTEGER", 5), + ]), + ]), + ]); const res = await client.executeSlash(interaction as any); expect(res).toEqual(["/testing maths add", 7, interaction, true]); }); it("Should execute the with optional option", async () => { - const interaction = new FakeInteraction( - "hello", - [ - ] - ); + const interaction = new FakeInteraction("hello", []); const res = await client.executeSlash(interaction as any); expect(res).toEqual(["/hello", undefined, interaction, true]); }); it("Should not execute not found slash", async () => { - const interaction = new FakeInteraction( - "testing", - [ - new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ - new FakeOption("notfound", "SUB_COMMAND", "text", [ - new FakeOption("x", "INTEGER", 2), - new FakeOption("y", "INTEGER", 5) - ]) - ]) - ] - ); + const interaction = new FakeInteraction("testing", [ + new FakeOption("maths", "SUB_COMMAND_GROUP", "text", [ + new FakeOption("notfound", "SUB_COMMAND", "text", [ + new FakeOption("x", "INTEGER", 2), + new FakeOption("y", "INTEGER", 5), + ]), + ]), + ]); const res = await client.executeSlash(interaction as any); expect(res).toEqual(undefined); From ee9f472dcfaca5e3d9091f1ba6b7656c56477f44 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 00:01:15 +0530 Subject: [PATCH 031/106] * recoded classes again * fixed issue where group does not have guilds * fixed group issue --- src/decorators/classes/DChoice.ts | 16 +++--- src/decorators/classes/DDiscord.ts | 13 +++-- src/decorators/classes/DGroup.ts | 33 ++++--------- src/decorators/classes/DGuard.ts | 11 +++-- src/decorators/classes/DOn.ts | 21 ++++---- src/decorators/classes/DOption.ts | 36 ++++++-------- src/decorators/classes/DSlash.ts | 67 +++++++++++--------------- src/decorators/classes/Decorator.ts | 23 ++++++--- src/decorators/classes/Method.ts | 4 +- src/decorators/classes/Modifier.ts | 23 ++------- src/decorators/decorators/Group.ts | 2 +- src/decorators/decorators/On.ts | 2 +- src/decorators/decorators/Once.ts | 2 +- src/logic/metadatas/MetadataStorage.ts | 8 ++- tests/slash.test.ts | 24 ++++----- 15 files changed, 134 insertions(+), 151 deletions(-) diff --git a/src/decorators/classes/DChoice.ts b/src/decorators/classes/DChoice.ts index 175d1b6e..9022a4c2 100644 --- a/src/decorators/classes/DChoice.ts +++ b/src/decorators/classes/DChoice.ts @@ -2,8 +2,8 @@ import { ApplicationCommandOptionChoice } from "discord.js"; import { Decorator } from "../classes/Decorator"; export class DChoice extends Decorator { - private _name: string; - private _value: string | number; + private _name!: string; + private _value!: string | number; get name() { return this._name; @@ -19,15 +19,17 @@ export class DChoice extends Decorator { this._value = value; } - protected constructor(name: string, value: string | number) { + protected constructor() { super(); - - this._name = name; - this._value = value; } static create(name: string, value: string | number) { - return new DChoice(name, value); + const choice = new DChoice(); + + choice.name = name; + choice.value = value; + + return choice; } toObject(): ApplicationCommandOptionChoice { diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index 1f56ffda..8f015c97 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -6,8 +6,8 @@ export class DDiscord extends Decorator { private _guards: DGuard[] = []; private _slashes: DSlash[] = []; private _events: DOn[] = []; - private _description?: string; - private _name: string; + private _description!: string; + private _name!: string; private _defaultPermission = true; private _permissions: { id: string; type: PermissionType }[] = []; private _guilds: string[] = []; @@ -72,12 +72,15 @@ export class DDiscord extends Decorator { return DIService.instance.getService(this.from); } - protected constructor(name: string) { + protected constructor() { super(); - this._name = name; } static create(name: string) { - return new DDiscord(name); + const discord = new DDiscord(); + + discord.name = name; + + return discord; } } diff --git a/src/decorators/classes/DGroup.ts b/src/decorators/classes/DGroup.ts index 1be61514..67d79aa1 100644 --- a/src/decorators/classes/DGroup.ts +++ b/src/decorators/classes/DGroup.ts @@ -1,34 +1,19 @@ -import { DSlash, DOption } from ".."; import { Decorator } from "./Decorator"; -export class DGroup extends Decorator { - private _name: string; - private _infos?: Partial; +export class DGroup extends Decorator { + name!: string; + infos!: Partial; - protected constructor(name: string, infos?: Partial) { + protected constructor() { super(); - this._name = name; - this._infos = infos; } - get name() { - return this._name; - } - set name(value) { - this._name = value; - } + static create(name: string, infos?: Partial) { + const group = new DGroup(); - get infos() { - return this._infos; - } - set infos(value) { - this._infos = value; - } + group.name = name.toLowerCase(); + group.infos = infos || ({} as any); - static create( - name: string, - infos?: Partial - ) { - return new DGroup(name.toLowerCase(), infos); + return group; } } diff --git a/src/decorators/classes/DGuard.ts b/src/decorators/classes/DGuard.ts index a75906b6..236cfbe5 100644 --- a/src/decorators/classes/DGuard.ts +++ b/src/decorators/classes/DGuard.ts @@ -2,18 +2,21 @@ import { Decorator } from "./Decorator"; import { GuardFunction } from "../.."; export class DGuard extends Decorator { - protected _fn: GuardFunction; + protected _fn!: GuardFunction; get fn() { return this._fn; } - protected constructor(fn: GuardFunction) { + protected constructor() { super(); - this._fn = fn; } static create(fn: GuardFunction) { - return new DGuard(fn); + const guard = new DGuard(); + + guard._fn = fn; + + return guard; } } diff --git a/src/decorators/classes/DOn.ts b/src/decorators/classes/DOn.ts index 42926afb..c16bca45 100644 --- a/src/decorators/classes/DOn.ts +++ b/src/decorators/classes/DOn.ts @@ -2,9 +2,9 @@ import { DiscordEvents } from "../.."; import { Method } from "./Method"; export class DOn extends Method { - protected _botIds: string[]; - protected _event: DiscordEvents; - protected _once: boolean; + protected _event!: DiscordEvents; + protected _once!: boolean; + protected _botIds!: string[]; get botIds() { return this._botIds; @@ -27,15 +27,18 @@ export class DOn extends Method { this._once = value; } - protected constructor(event, once, botIds) { + protected constructor() { super(); - this._event = event; - this._once = once; - this._botIds = botIds; } - static create(event: DiscordEvents, once: boolean, botIds: string[]) { - return new DOn(event, once, botIds); + static create(event: DiscordEvents, once: boolean, botIds?: string[]) { + const on = new DOn(); + + on._event = event; + on._once = once; + on._botIds = botIds ?? []; + + return on; } parseParams() { diff --git a/src/decorators/classes/DOption.ts b/src/decorators/classes/DOption.ts index ea925faa..07075947 100644 --- a/src/decorators/classes/DOption.ts +++ b/src/decorators/classes/DOption.ts @@ -19,9 +19,9 @@ import { export class DOption extends Decorator { private _required = false; - private _name: string; - private _type: OptionValueType; - private _description: string; + private _name!: string; + private _type!: OptionValueType; + private _description!: string; private _choices: DChoice[] = []; private _options: DOption[] = []; private _isNode = false; @@ -104,19 +104,8 @@ export class DOption extends Decorator { } } - protected constructor(options: { - name: string; - type: OptionValueType; - description: string; - required: boolean; - index?: number; - }) { + protected constructor() { super(); - this._name = options.name; - this._type = options.type; - this._description = options.description; - this._required = options.required; - this._index = options.index; } static create( @@ -126,13 +115,16 @@ export class DOption extends Decorator { required?: boolean, index?: number ) { - return new DOption({ - name: name.toLowerCase(), - type: type || String, - description: description || `${name}`, - required: required !== undefined ? required : Client.requiredByDefault, - index: index, - }); + const option = new DOption(); + + option._name = name.toLowerCase(); + option._type = type || String; + option._description = description || `${name} - ${option.stringType}`; + option._required = + required !== undefined ? required : Client.requiredByDefault; + option._index = index; + + return option; } toObject(): ApplicationCommandOptionData { diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 60772075..addcdccf 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -9,15 +9,22 @@ import { DOption, Client, PermissionType } from "../.."; import { Method } from "./Method"; export class DSlash extends Method { - private _description: string; - private _name: string; + private _description!: string; + private _name!: string; private _defaultPermission = true; private _options: DOption[] = []; private _permissions: { id: string; type: PermissionType }[] = []; - private _guilds: string[]; - private _botIds: string[]; - private _group?: string; - private _subgroup?: string; + private _guilds!: string[]; + private _group!: string; + private _subgroup!: string; + private _botIds!: string[]; + + get botIds() { + return this._botIds; + } + set botIds(value) { + this._botIds = value; + } get group() { return this._group; @@ -47,13 +54,6 @@ export class DSlash extends Method { this._guilds = value; } - get botIds() { - return this._botIds; - } - set botIds(value) { - this._botIds = value; - } - get defaultPermission() { return this._defaultPermission; } @@ -82,19 +82,8 @@ export class DSlash extends Method { this._options = value; } - protected constructor(options: { - name: string; - description: string; - defaultPermission: boolean; - guilds: string[]; - botIds: string[]; - }) { + protected constructor() { super(); - this._name = options.name.toLowerCase(); - this._description = options.description; - this._defaultPermission = options.defaultPermission; - this._guilds = options.guilds || Client.slashGuilds; - this._botIds = options.botIds; } static create( @@ -104,22 +93,22 @@ export class DSlash extends Method { guilds?: string[], botIds?: string[] ) { - return new DSlash({ - name: name.toLowerCase(), - description: description ?? name, - defaultPermission: defaultPermission, - guilds: guilds ?? Client.slashGuilds, - botIds: botIds ?? [], - }); + const slash = new DSlash(); + + slash.name = name.toLowerCase(); + slash.description = description || slash.name; + slash.defaultPermission = defaultPermission; + slash.guilds = guilds || Client.slashGuilds; + slash.botIds = botIds || []; + + return slash; } toSubCommand() { const option = DOption.create( this.name, "SUB_COMMAND", - this.description, - false, - this.index + this.description ).decorate(this.classRef, this.key, this.method, this.from, this.index); option.options = this.options; @@ -162,8 +151,10 @@ export class DSlash extends Method { parseParams(interaction: CommandInteraction) { const options = this.getLastNestedOption(interaction.options); - return this.options - .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)) - .map((op) => options.find((o) => o.name === op.name)?.value); + const values = this.options.map((opt, index) => { + return options[index]?.value; + }); + + return values; } } diff --git a/src/decorators/classes/Decorator.ts b/src/decorators/classes/Decorator.ts index 5d6308ef..06a27166 100644 --- a/src/decorators/classes/Decorator.ts +++ b/src/decorators/classes/Decorator.ts @@ -3,8 +3,8 @@ import { DecoratorUtils } from "../../logic"; export class Decorator { protected _classRef!: Function; protected _from!: Function; - protected _key: string | undefined; - protected _method: Function | undefined; + protected _key!: string; + protected _method!: Function; protected _index: number | undefined = undefined; get index() { @@ -38,6 +38,10 @@ export class Decorator { return !!this._method; } + protected constructor() { + // empty constructor + } + decorateUnknown( classRef: Function | Object, key?: string, @@ -55,7 +59,7 @@ export class Decorator { return this.decorate( finalClassRef, - finalKey, + finalKey as string, finalMethod, finalClassRef, index @@ -64,7 +68,7 @@ export class Decorator { decorate( classRef: Function, - key?: string, + key: string, method?: Function, from?: Function, index?: number @@ -72,8 +76,15 @@ export class Decorator { this._from = from || classRef; this._classRef = classRef; this._key = key; - this._method = method; - this._index = index; + this._method = method as Function; + this._index = index as number; + + this.update(); + return this; } + + update() { + // empty function + } } diff --git a/src/decorators/classes/Method.ts b/src/decorators/classes/Method.ts index fba9d02d..d96b4fe1 100644 --- a/src/decorators/classes/Method.ts +++ b/src/decorators/classes/Method.ts @@ -26,7 +26,7 @@ export abstract class Method extends Decorator { */ get execute() { return async (...params: any[]) => { - return this.getGuardFunction()(...params); + return await this.getGuardFunction()(...params); }; } @@ -45,7 +45,7 @@ export abstract class Method extends Decorator { ...clientGuards, ...this.discord.guards, ...this._guards, - DGuard.create(this._method?.bind(this._discord.instance)), + DGuard.create(this._method.bind(this._discord.instance)), ]; } set guards(value) { diff --git a/src/decorators/classes/Modifier.ts b/src/decorators/classes/Modifier.ts index 3a67fce8..6f6f138b 100644 --- a/src/decorators/classes/Modifier.ts +++ b/src/decorators/classes/Modifier.ts @@ -1,21 +1,13 @@ import { Decorator } from "./Decorator"; import { DecoratorUtils } from "../../logic/utils/DecoratorUtils"; -import { DSlash, DDiscord, DOption } from ".."; -import { DOn } from "./DOn"; export type ModifyFunction = ( original: ToModify -) => void; +) => any; export class Modifier extends Decorator { private _toModify!: ModifyFunction; - private _modifyTypes!: ( - | typeof DSlash - | typeof DDiscord - | typeof DOption - | typeof DOn - | Function - )[]; + private _modifyTypes!: any[]; protected constructor() { super(); @@ -23,12 +15,7 @@ export class Modifier extends Decorator { static create( toModify: ModifyFunction, - ...modifyTypes: ( - | typeof DSlash - | typeof DDiscord - | typeof DOption - | typeof DOn - )[] + ...modifyTypes: any[] ) { const modifier = new Modifier(); @@ -50,7 +37,7 @@ export class Modifier extends Decorator { modifiers: Modifier[], originals: Decorator[] ) { - return Promise.all( + return await Promise.all( modifiers.map(async (modifier) => { // Get the list of objects that are linked to the specified modifier let linked = DecoratorUtils.getLinkedObjects(modifier, originals); @@ -63,7 +50,7 @@ export class Modifier extends Decorator { // Apply the modifications await Promise.all( linked.map(async (linkedOriginal) => { - return modifier.applyModifications(linkedOriginal); + return await modifier.applyModifications(linkedOriginal); }) ); }) diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index e4fdc111..dd186cf0 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -65,7 +65,7 @@ export function Group( MetadataStorage.instance.addModifier( Modifier.create(async (original) => { original.subgroup = group as string; - }, DSlash).decorate(target.constructor, key) + }, DSlash).decorate(target.constructor, key as string) ); } }; diff --git a/src/decorators/decorators/On.ts b/src/decorators/decorators/On.ts index c08fd0fe..5ccb0a4f 100644 --- a/src/decorators/decorators/On.ts +++ b/src/decorators/decorators/On.ts @@ -14,7 +14,7 @@ export function On(event: DiscordEvents, params?: EventParams) { key: string, descriptor?: PropertyDescriptor ): void => { - const on = DOn.create(event, false, params?.botIds ?? []).decorate( + const on = DOn.create(event, false, params?.botIds).decorate( target.constructor, key, descriptor?.value diff --git a/src/decorators/decorators/Once.ts b/src/decorators/decorators/Once.ts index b41ed7b1..5701e014 100644 --- a/src/decorators/decorators/Once.ts +++ b/src/decorators/decorators/Once.ts @@ -14,7 +14,7 @@ export function Once(event: DiscordEvents, params?: EventParams) { key: string, descriptor: PropertyDescriptor ): void => { - const on = DOn.create(event, true, params?.botIds ?? []).decorate( + const on = DOn.create(event, true, params?.botIds).decorate( target.constructor, key, descriptor.value diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 183e2b7a..47b3a1b6 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -196,9 +196,15 @@ export class MetadataStorage { return slash.group === slashParent.name && !slash.subgroup; }); + let groupGuilds: string[] = []; slashes.forEach((slash) => { + groupGuilds = [...groupGuilds, ...slash.guilds]; slashParent.options.push(slash.toSubCommand()); }); + + slashParent.guilds = groupGuilds.filter( + (a, b) => groupGuilds.indexOf(a) === b + ); }); // Create for each subgroup (@Group on methods) create an Option based on Slash @@ -254,7 +260,7 @@ export class MetadataStorage { }); // The the root option to the root Slash command - const groupSlash = slashes?.[0]?.group + const groupSlash = slashes?.[0].group ? groupedSlashes.get(slashes[0].group) : undefined; if (groupSlash) { diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 8b534c52..a563c2ce 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -201,7 +201,7 @@ describe("Slash", () => { description: "hello", options: [ { - description: "text - STRING", + description: "text", name: "text", type: "STRING", required: false, @@ -216,7 +216,7 @@ describe("Slash", () => { description: "inferance", options: [ { - description: "text - STRING", + description: "text", name: "text", type: "STRING", required: true, @@ -224,7 +224,7 @@ describe("Slash", () => { options: [], }, { - description: "bool - BOOLEAN", + description: "bool", name: "bool", type: "BOOLEAN", required: true, @@ -232,7 +232,7 @@ describe("Slash", () => { options: [], }, { - description: "nb - INTEGER", + description: "nb", name: "nb", type: "INTEGER", required: true, @@ -240,7 +240,7 @@ describe("Slash", () => { options: [], }, { - description: "channel - CHANNEL", + description: "channel", name: "channel", type: "CHANNEL", required: true, @@ -248,7 +248,7 @@ describe("Slash", () => { options: [], }, { - description: "textchannel - CHANNEL", + description: "textchannel", name: "textchannel", type: "CHANNEL", required: false, @@ -256,7 +256,7 @@ describe("Slash", () => { options: [], }, { - description: "voicechannel - CHANNEL", + description: "voicechannel", name: "voicechannel", type: "CHANNEL", required: false, @@ -264,7 +264,7 @@ describe("Slash", () => { options: [], }, { - description: "user - USER", + description: "user", name: "user", type: "USER", required: false, @@ -272,7 +272,7 @@ describe("Slash", () => { options: [], }, { - description: "role - ROLE", + description: "role", name: "role", type: "ROLE", required: false, @@ -299,7 +299,7 @@ describe("Slash", () => { choices: [], options: [ { - description: "text - STRING", + description: "text", name: "text", type: "STRING", required: false, @@ -382,7 +382,7 @@ describe("Slash", () => { choices: [], options: [ { - description: "text - STRING", + description: "text", name: "text", type: "STRING", required: true, @@ -390,7 +390,7 @@ describe("Slash", () => { options: [], }, { - description: "text2 - STRING", + description: "text2", name: "text2", type: "STRING", required: false, From f3cb42b0acf3aab8ea7cb1839e3614670bb01d9d Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 00:03:18 +0530 Subject: [PATCH 032/106] jest test passed --- tests/slash.test.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/slash.test.ts b/tests/slash.test.ts index a563c2ce..8b534c52 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -201,7 +201,7 @@ describe("Slash", () => { description: "hello", options: [ { - description: "text", + description: "text - STRING", name: "text", type: "STRING", required: false, @@ -216,7 +216,7 @@ describe("Slash", () => { description: "inferance", options: [ { - description: "text", + description: "text - STRING", name: "text", type: "STRING", required: true, @@ -224,7 +224,7 @@ describe("Slash", () => { options: [], }, { - description: "bool", + description: "bool - BOOLEAN", name: "bool", type: "BOOLEAN", required: true, @@ -232,7 +232,7 @@ describe("Slash", () => { options: [], }, { - description: "nb", + description: "nb - INTEGER", name: "nb", type: "INTEGER", required: true, @@ -240,7 +240,7 @@ describe("Slash", () => { options: [], }, { - description: "channel", + description: "channel - CHANNEL", name: "channel", type: "CHANNEL", required: true, @@ -248,7 +248,7 @@ describe("Slash", () => { options: [], }, { - description: "textchannel", + description: "textchannel - CHANNEL", name: "textchannel", type: "CHANNEL", required: false, @@ -256,7 +256,7 @@ describe("Slash", () => { options: [], }, { - description: "voicechannel", + description: "voicechannel - CHANNEL", name: "voicechannel", type: "CHANNEL", required: false, @@ -264,7 +264,7 @@ describe("Slash", () => { options: [], }, { - description: "user", + description: "user - USER", name: "user", type: "USER", required: false, @@ -272,7 +272,7 @@ describe("Slash", () => { options: [], }, { - description: "role", + description: "role - ROLE", name: "role", type: "ROLE", required: false, @@ -299,7 +299,7 @@ describe("Slash", () => { choices: [], options: [ { - description: "text", + description: "text - STRING", name: "text", type: "STRING", required: false, @@ -382,7 +382,7 @@ describe("Slash", () => { choices: [], options: [ { - description: "text", + description: "text - STRING", name: "text", type: "STRING", required: true, @@ -390,7 +390,7 @@ describe("Slash", () => { options: [], }, { - description: "text2", + description: "text2 - STRING", name: "text2", type: "STRING", required: false, From 0d012963df6bbea41d548593f6404b6f7f524097 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 00:25:21 +0530 Subject: [PATCH 033/106] multiple bot support fix for groups --- src/logic/metadatas/MetadataStorage.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 47b3a1b6..e5a35efa 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -197,14 +197,20 @@ export class MetadataStorage { }); let groupGuilds: string[] = []; + let botIds: string[] = []; slashes.forEach((slash) => { groupGuilds = [...groupGuilds, ...slash.guilds]; + botIds = [...botIds, ...slash.botIds]; slashParent.options.push(slash.toSubCommand()); }); + // remove duplicate guilds slashParent.guilds = groupGuilds.filter( (a, b) => groupGuilds.indexOf(a) === b ); + + // multiple bot support + slashParent.botIds = botIds.filter((a, b) => botIds.indexOf(a) === b); }); // Create for each subgroup (@Group on methods) create an Option based on Slash From 547a04b6269b7221b07588cf0903e2fdef2e09db Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 00:54:22 +0530 Subject: [PATCH 034/106] added ``Bot()`` decorator --- src/decorators/classes/DDiscord.ts | 8 +++++++ src/decorators/decorators/Bot.ts | 35 ++++++++++++++++++++++++++++++ src/decorators/index.ts | 1 + 3 files changed, 44 insertions(+) create mode 100644 src/decorators/decorators/Bot.ts diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index 8f015c97..57d7ded1 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -11,6 +11,7 @@ export class DDiscord extends Decorator { private _defaultPermission = true; private _permissions: { id: string; type: PermissionType }[] = []; private _guilds: string[] = []; + private _botIds: string[] = []; get permissions() { return this._permissions; @@ -19,6 +20,13 @@ export class DDiscord extends Decorator { this._permissions = value; } + get botIds() { + return this._botIds; + } + set botIds(value) { + this._botIds = value; + } + get guilds() { return this._guilds; } diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts new file mode 100644 index 00000000..7f2855ac --- /dev/null +++ b/src/decorators/decorators/Bot.ts @@ -0,0 +1,35 @@ +import { MetadataStorage, Modifier } from "../.."; +import { DDiscord } from "../classes/DDiscord"; +import { DSlash } from "../classes/DSlash"; + +export function Bot(botID: string); +export function Bot(...botIDs: string[]); +export function Bot(...botIDs: string[]) { + return ( + target: Function, + key: string, + descriptor: PropertyDescriptor + ): void => { + MetadataStorage.instance.addModifier( + Modifier.create( + async (original) => { + original.botIds = [ + ...original.botIds, + ...botIDs.filter((botID) => !original.botIds.includes(botID)), + ]; + + if (original instanceof DDiscord) { + original.slashes.forEach((slash) => { + slash.botIds = [ + ...slash.botIds, + ...botIDs.filter((botID) => !slash.botIds.includes(botID)), + ]; + }); + } + }, + DSlash, + DDiscord + ).decorateUnknown(target, key, descriptor) + ); + }; +} diff --git a/src/decorators/index.ts b/src/decorators/index.ts index fe7d9b17..447009f8 100644 --- a/src/decorators/index.ts +++ b/src/decorators/index.ts @@ -11,6 +11,7 @@ export * from "./decorators/Choices"; export * from "./decorators/Permission"; export * from "./decorators/Group"; export * from "./decorators/Guild"; +export * from "./decorators/Bot"; export * from "./params/DiscordParams"; export * from "./params/OptionParams"; From 8d2edfa10dc3af63c6387a3ebd50823fc30e06df Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 01:04:47 +0530 Subject: [PATCH 035/106] fix multiple bot for groups --- src/logic/metadatas/MetadataStorage.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index e5a35efa..8a37b8ac 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -188,6 +188,7 @@ export class MetadataStorage { ...Client.slashGuilds, ...slashParent.discord.guilds, ]; + slashParent.botIds = [...slashParent.discord.botIds]; slashParent.permissions = slashParent.discord.permissions; groupedSlashes.set(group.name, slashParent); @@ -196,21 +197,9 @@ export class MetadataStorage { return slash.group === slashParent.name && !slash.subgroup; }); - let groupGuilds: string[] = []; - let botIds: string[] = []; slashes.forEach((slash) => { - groupGuilds = [...groupGuilds, ...slash.guilds]; - botIds = [...botIds, ...slash.botIds]; slashParent.options.push(slash.toSubCommand()); }); - - // remove duplicate guilds - slashParent.guilds = groupGuilds.filter( - (a, b) => groupGuilds.indexOf(a) === b - ); - - // multiple bot support - slashParent.botIds = botIds.filter((a, b) => botIds.indexOf(a) === b); }); // Create for each subgroup (@Group on methods) create an Option based on Slash From 805f909910162a8fad6812b224cb67a5887485ff Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 06:17:32 +0530 Subject: [PATCH 036/106] * new featured added: buttons selectmenu * fixed OwenCalvin/discord.ts/issues/57 --- src/Client.ts | 42 +++++++++++++++++++++- src/decorators/classes/DButton.ts | 47 +++++++++++++++++++++++++ src/decorators/classes/DDiscord.ts | 18 ++++++++++ src/decorators/classes/DSelectMenu.ts | 47 +++++++++++++++++++++++++ src/decorators/decorators/Button.ts | 16 +++++++++ src/decorators/decorators/Guard.ts | 4 +++ src/decorators/decorators/SelectMenu.ts | 16 +++++++++ src/decorators/index.ts | 4 +++ src/logic/metadatas/MetadataStorage.ts | 41 +++++++++++++++++++-- 9 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 src/decorators/classes/DButton.ts create mode 100644 src/decorators/classes/DSelectMenu.ts create mode 100644 src/decorators/decorators/Button.ts create mode 100644 src/decorators/decorators/SelectMenu.ts diff --git a/src/Client.ts b/src/Client.ts index 071a567e..b19bde47 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -15,7 +15,7 @@ import { DOn, GuardFunction, } from "."; -import { DDiscord, DOption, DSlash } from "./decorators"; +import { DButton, DDiscord, DOption, DSelectMenu, DSlash } from "./decorators"; import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { @@ -81,6 +81,20 @@ export class Client extends ClientJS { return Client.slashes; } + static get buttons() { + return MetadataStorage.instance.buttons as readonly DButton[]; + } + get buttons() { + return Client.buttons; + } + + static get selectMenus() { + return MetadataStorage.instance.selectMenus as readonly DSelectMenu[]; + } + get selectMenus() { + return Client.selectMenus; + } + static get allSlashes() { return MetadataStorage.instance.allSlashes as readonly DSlash[]; } @@ -465,6 +479,32 @@ export class Client extends ClientJS { return; } + // if interaction is a button + if (interaction.isButton()) { + const findButton = this.buttons.find( + (s) => s.id === interaction.customID + ); + if (!findButton) + return console.log( + `button interaction not found, id: ${interaction.id}` + ); + + findButton.execute(interaction, this); + } + + // if interaction is a button + if (interaction.isSelectMenu()) { + const findMenu = this.selectMenus.find( + (s) => s.id === interaction.customID + ); + if (!findMenu) + return console.log( + `selectMenu interaction not found, id: ${interaction.id}` + ); + + findMenu.execute(interaction, this); + } + // If the interaction isn't a slash command, return if (!interaction.isCommand()) return; diff --git a/src/decorators/classes/DButton.ts b/src/decorators/classes/DButton.ts new file mode 100644 index 00000000..fca5617a --- /dev/null +++ b/src/decorators/classes/DButton.ts @@ -0,0 +1,47 @@ +import { Client } from "../.."; +import { Method } from "./Method"; + +export class DButton extends Method { + private _id!: string; + private _guilds!: string[]; + private _botIds!: string[]; + + get botIds() { + return this._botIds; + } + set botIds(value) { + this._botIds = value; + } + + get id() { + return this._id; + } + set id(value) { + this._id = value; + } + + get guilds() { + return this._guilds; + } + set guilds(value) { + this._guilds = value; + } + + protected constructor() { + super(); + } + + static create(id: string, guilds?: string[], botIds?: string[]) { + const button = new DButton(); + + button.id = id; + button.guilds = guilds || Client.slashGuilds; + button.botIds = botIds || []; + + return button; + } + + parseParams() { + return []; + } +} diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index 57d7ded1..f2938daa 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -1,9 +1,13 @@ import { Decorator } from "./Decorator"; import { DGuard, DSlash, DIService, DOn } from "../.."; import { PermissionType } from "../../types"; +import { DButton } from "./DButton"; +import { DSelectMenu } from "./DSelectMenu"; export class DDiscord extends Decorator { private _guards: DGuard[] = []; + private _buttons: DButton[] = []; + private _selectMenus: DSelectMenu[] = []; private _slashes: DSlash[] = []; private _events: DOn[] = []; private _description!: string; @@ -69,6 +73,20 @@ export class DDiscord extends Decorator { this._slashes = value; } + get buttons() { + return this._buttons; + } + set buttons(value) { + this._buttons = value; + } + + get selectMenus() { + return this._selectMenus; + } + set selectMenus(value) { + this._selectMenus = value; + } + get events() { return this._events; } diff --git a/src/decorators/classes/DSelectMenu.ts b/src/decorators/classes/DSelectMenu.ts new file mode 100644 index 00000000..65f738fa --- /dev/null +++ b/src/decorators/classes/DSelectMenu.ts @@ -0,0 +1,47 @@ +import { Client } from "../.."; +import { Method } from "./Method"; + +export class DSelectMenu extends Method { + private _id!: string; + private _guilds!: string[]; + private _botIds!: string[]; + + get botIds() { + return this._botIds; + } + set botIds(value) { + this._botIds = value; + } + + get id() { + return this._id; + } + set id(value) { + this._id = value; + } + + get guilds() { + return this._guilds; + } + set guilds(value) { + this._guilds = value; + } + + protected constructor() { + super(); + } + + static create(id: string, guilds?: string[], botIds?: string[]) { + const menu = new DSelectMenu(); + + menu.id = id; + menu.guilds = guilds || Client.slashGuilds; + menu.botIds = botIds || []; + + return menu; + } + + parseParams() { + return []; + } +} diff --git a/src/decorators/decorators/Button.ts b/src/decorators/decorators/Button.ts new file mode 100644 index 00000000..681497f3 --- /dev/null +++ b/src/decorators/decorators/Button.ts @@ -0,0 +1,16 @@ +import { MetadataStorage, DButton } from "../.."; + +export function Button(id: string); +export function Button( + id: string, + params?: { guilds?: string[]; botIds?: [] } +) { + return (target: Object, key: string) => { + const button = DButton.create(id, params?.guilds, params?.botIds).decorate( + target.constructor, + key, + target[key] + ); + MetadataStorage.instance.addButton(button); + }; +} diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index 583de5d5..fb838a9e 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -5,8 +5,10 @@ import { Modifier, Method, } from "../.."; +import { DButton } from "../classes/DButton"; import { DDiscord } from "../classes/DDiscord"; import { DOn } from "../classes/DOn"; +import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; export function Guard( @@ -26,6 +28,8 @@ export function Guard( async (original) => { original.guards = guards; }, + DSelectMenu, + DButton, DSlash, DOn, DDiscord diff --git a/src/decorators/decorators/SelectMenu.ts b/src/decorators/decorators/SelectMenu.ts new file mode 100644 index 00000000..7e52b5d1 --- /dev/null +++ b/src/decorators/decorators/SelectMenu.ts @@ -0,0 +1,16 @@ +import { MetadataStorage, DSelectMenu } from "../.."; + +export function SelectMenu( + id: string, + params?: { guilds?: string[]; botIds?: [] } +) { + return (target: Object, key: string) => { + const button = DSelectMenu.create( + id, + params?.guilds, + params?.botIds + ).decorate(target.constructor, key, target[key]); + + MetadataStorage.instance.addSelectMenu(button); + }; +} diff --git a/src/decorators/index.ts b/src/decorators/index.ts index 447009f8..c7ddb6b8 100644 --- a/src/decorators/index.ts +++ b/src/decorators/index.ts @@ -12,11 +12,15 @@ export * from "./decorators/Permission"; export * from "./decorators/Group"; export * from "./decorators/Guild"; export * from "./decorators/Bot"; +export * from "./decorators/Button"; +export * from "./decorators/SelectMenu"; export * from "./params/DiscordParams"; export * from "./params/OptionParams"; export * from "./params/SlashParams"; +export * from "./classes/DSelectMenu"; +export * from "./classes/DButton"; export * from "./classes/Decorator"; export * from "./classes/DGuard"; export * from "./classes/DDiscord"; diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 8a37b8ac..1652505a 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -11,7 +11,8 @@ import { DOption, Method, } from "../.."; -import { DGroup } from "../../decorators"; +import { DButton, DGroup } from "../../decorators"; +import { DSelectMenu } from "../../decorators/classes/DSelectMenu"; export class MetadataStorage { private static _instance: MetadataStorage; @@ -19,6 +20,8 @@ export class MetadataStorage { private _guards: DGuard[] = []; private _slashes: DSlash[] = []; private _allSlashes: DSlash[] = []; + private _buttons: DButton[] = []; + private _selectMenu: DSelectMenu[] = []; private _options: DOption[] = []; private _discords: DDiscord[] = []; private _modifiers: Modifier[] = []; @@ -65,6 +68,14 @@ export class MetadataStorage { return this._slashes as readonly DSlash[]; } + get buttons() { + return this._buttons as readonly DButton[]; + } + + get selectMenus() { + return this._selectMenu as readonly DSelectMenu[]; + } + get allSlashes() { return this._allSlashes as readonly DSlash[]; } @@ -78,7 +89,12 @@ export class MetadataStorage { } private get discordMembers(): readonly Method[] { - return [...this._slashes, ...this._events]; + return [ + ...this._slashes, + ...this._events, + ...this._buttons, + ...this._selectMenu, + ]; } addModifier(modifier: Modifier) { @@ -93,6 +109,14 @@ export class MetadataStorage { this._slashes.push(slash); } + addButton(button: DButton) { + this._buttons.push(button); + } + + addSelectMenu(selectMenu: DSelectMenu) { + this._selectMenu.push(selectMenu); + } + addOption(option: DOption) { this._options.push(option); } @@ -136,12 +160,25 @@ export class MetadataStorage { if (member instanceof DOn) { discord.events.push(member); } + + if (member instanceof DButton) { + discord.buttons.push(member); + } + + if (member instanceof DSelectMenu) { + discord.selectMenus.push(member); + } }); await Modifier.applyFromModifierListToList(this._modifiers, this._discords); await Modifier.applyFromModifierListToList(this._modifiers, this._events); await Modifier.applyFromModifierListToList(this._modifiers, this._slashes); + await Modifier.applyFromModifierListToList(this._modifiers, this._buttons); await Modifier.applyFromModifierListToList(this._modifiers, this._options); + await Modifier.applyFromModifierListToList( + this._modifiers, + this._selectMenu + ); // Set the class level "group" property of all @Slash // Cannot achieve it using modifiers From 899551d6cda0729246b49a447dd0cb30c42f3c9f Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 06:44:35 +0530 Subject: [PATCH 037/106] fix button/selectmenu --- src/Client.ts | 26 ++++++++++++++++---------- src/decorators/decorators/Bot.ts | 8 ++++++-- src/decorators/decorators/Guild.ts | 8 ++++++-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index b19bde47..a08c8c91 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -481,28 +481,34 @@ export class Client extends ClientJS { // if interaction is a button if (interaction.isButton()) { - const findButton = this.buttons.find( - (s) => s.id === interaction.customID - ); - if (!findButton) + const button = this.buttons.find((s) => s.id === interaction.customID); + if ( + !button || + (button.guilds.length > 0 && + !button.guilds.includes(interaction.guild?.id as string)) || + (button.botIds.length > 0 && !button.botIds.includes(this.botId)) + ) return console.log( `button interaction not found, id: ${interaction.id}` ); - findButton.execute(interaction, this); + button.execute(interaction, this); } // if interaction is a button if (interaction.isSelectMenu()) { - const findMenu = this.selectMenus.find( - (s) => s.id === interaction.customID - ); - if (!findMenu) + const menu = this.selectMenus.find((s) => s.id === interaction.customID); + if ( + !menu || + (menu.guilds.length > 0 && + !menu.guilds.includes(interaction.guild?.id as string)) || + (menu.botIds.length > 0 && !menu.botIds.includes(this.botId)) + ) return console.log( `selectMenu interaction not found, id: ${interaction.id}` ); - findMenu.execute(interaction, this); + menu.execute(interaction, this); } // If the interaction isn't a slash command, return diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 7f2855ac..4c01ca21 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -1,5 +1,7 @@ import { MetadataStorage, Modifier } from "../.."; +import { DButton } from "../classes/DButton"; import { DDiscord } from "../classes/DDiscord"; +import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; export function Bot(botID: string); @@ -11,7 +13,7 @@ export function Bot(...botIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( async (original) => { original.botIds = [ ...original.botIds, @@ -28,7 +30,9 @@ export function Bot(...botIDs: string[]) { } }, DSlash, - DDiscord + DDiscord, + DButton, + DSelectMenu ).decorateUnknown(target, key, descriptor) ); }; diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index 30d6f241..10c16dab 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -1,5 +1,7 @@ import { MetadataStorage, Modifier } from "../.."; +import { DButton } from "../classes/DButton"; import { DDiscord } from "../classes/DDiscord"; +import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; export function Guild(guildID: string); @@ -11,7 +13,7 @@ export function Guild(...guildIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( async (original) => { original.guilds = [ ...original.guilds, @@ -30,7 +32,9 @@ export function Guild(...guildIDs: string[]) { } }, DSlash, - DDiscord + DDiscord, + DButton, + DSelectMenu ).decorateUnknown(target, key, descriptor) ); }; From 78d4a4ac1c13303444ff7e7a17d69b5215ad520f Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sat, 3 Jul 2021 18:58:27 +0530 Subject: [PATCH 038/106] Update button not found log Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- src/Client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index a08c8c91..77fd3071 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -489,7 +489,7 @@ export class Client extends ClientJS { (button.botIds.length > 0 && !button.botIds.includes(this.botId)) ) return console.log( - `button interaction not found, id: ${interaction.id}` + `button interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` ); button.execute(interaction, this); From 82d60ae4536cb0e295d793e7cd7c95b64fb3dbee Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sat, 3 Jul 2021 19:00:09 +0530 Subject: [PATCH 039/106] Update menu not found log text Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- src/Client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index 77fd3071..9f879b7f 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -505,7 +505,7 @@ export class Client extends ClientJS { (menu.botIds.length > 0 && !menu.botIds.includes(this.botId)) ) return console.log( - `selectMenu interaction not found, id: ${interaction.id}` + `selectMenu interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` ); menu.execute(interaction, this); From ad599cd22951ee95d9b9f3d62ae160d05e02893d Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:12:00 +0530 Subject: [PATCH 040/106] fix init slash with permissions --- src/Client.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 9f879b7f..ef144753 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -295,9 +295,25 @@ export class Client extends ClientJS { ); } + guild.commands + .create(added[0].toObject()) + .then((cmd) => + cmd.permissions.set({ permissions: added[0].getPermissions() }) + ); + await Promise.all([ - ...added.map((s) => guild.commands.create(s.toObject())), - ...updated.map((s) => s[0].edit(s[1].toObject())), + ...added.map((s) => + guild.commands.create(s.toObject()).then((cmd) => { + cmd.permissions.set({ permissions: s.getPermissions() }); + return cmd; + }) + ), + ...updated.map((s) => + s[0].edit(s[1].toObject()).then((cmd) => { + cmd.permissions.set({ permissions: s[1].getPermissions() }); + return cmd; + }) + ), ...deleted.map((key) => guild.commands.delete(key)), ]); } From 86773fd202800b0d34f87374f19aabf40c72c68c Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:13:56 +0530 Subject: [PATCH 041/106] fix permissions on init slash --- src/Client.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index ef144753..bd18112c 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -304,13 +304,17 @@ export class Client extends ClientJS { await Promise.all([ ...added.map((s) => guild.commands.create(s.toObject()).then((cmd) => { - cmd.permissions.set({ permissions: s.getPermissions() }); + if (s.permissions.length > 0) { + cmd.permissions.set({ permissions: s.getPermissions() }); + } return cmd; }) ), ...updated.map((s) => s[0].edit(s[1].toObject()).then((cmd) => { - cmd.permissions.set({ permissions: s[1].getPermissions() }); + if (s[1].permissions.length > 0) { + cmd.permissions.set({ permissions: s[1].getPermissions() }); + } return cmd; }) ), From 82e122c48699fcef46f1055237a4747e7742c086 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:20:13 +0530 Subject: [PATCH 042/106] permissions global comment --- src/Client.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Client.ts b/src/Client.ts index bd18112c..dc914599 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -359,6 +359,10 @@ export class Client extends ClientJS { ); } + // Only available for Guilds + // https://discord.js.org/#/docs/main/master/class/ApplicationCommand?scrollTo=setPermissions + // if (slash.permissions.length <= 0) return; + await Promise.all([ ...added.map((s) => this.application?.commands.create(s.toObject())), ...updated.map((s) => s[0].edit(s[1].toObject())), From ec69d24eee1a487418a9edfa50947aafcabda6ac Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:26:46 +0530 Subject: [PATCH 043/106] removed unwanted permission code --- src/Client.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index dc914599..b728721c 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -295,12 +295,6 @@ export class Client extends ClientJS { ); } - guild.commands - .create(added[0].toObject()) - .then((cmd) => - cmd.permissions.set({ permissions: added[0].getPermissions() }) - ); - await Promise.all([ ...added.map((s) => guild.commands.create(s.toObject()).then((cmd) => { From 64d386eeebce33965999aa2b14849cab94c8d3b0 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:41:02 +0530 Subject: [PATCH 044/106] fixed examples to support latest code --- examples/event/Main.ts | 6 ++--- examples/event/discords/AppDiscord.ts | 6 ++--- examples/guards/Main.ts | 6 ++--- .../Discords/CommandsA.ts | 7 ++---- .../Discords/CommandsB.ts | 7 ++---- examples/multiple-discord-instances/Main.ts | 6 ++--- examples/slash/Main.ts | 6 ++--- examples/slash/discords/AppDiscord.ts | 23 +++++-------------- 8 files changed, 20 insertions(+), 47 deletions(-) diff --git a/examples/event/Main.ts b/examples/event/Main.ts index 742eb478..359cf2b0 100644 --- a/examples/event/Main.ts +++ b/examples/event/Main.ts @@ -11,10 +11,8 @@ export class Main { static async start() { this._client = new Client({ - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ] + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], }); // In the login method, you must specify the glob string to load your classes (for the framework). diff --git a/examples/event/discords/AppDiscord.ts b/examples/event/discords/AppDiscord.ts index 63e541bd..5103bfa1 100644 --- a/examples/event/discords/AppDiscord.ts +++ b/examples/event/discords/AppDiscord.ts @@ -1,12 +1,10 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { Discord, On, Client, ArgsOf } from "../../../src"; @Discord() export abstract class AppDiscord { @On("message") - onMessage( - [message]: ArgsOf<"message">, - client: Client - ) { + onMessage([message]: ArgsOf<"message">, client: Client) { console.log(message.content); } } diff --git a/examples/guards/Main.ts b/examples/guards/Main.ts index 0bc3bc1c..eeee38a4 100644 --- a/examples/guards/Main.ts +++ b/examples/guards/Main.ts @@ -10,10 +10,8 @@ export class Main { static async start() { this._client = new Client({ - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], slashGuilds: ["546281071751331840"], requiredByDefault: true, }); diff --git a/examples/multiple-discord-instances/Discords/CommandsA.ts b/examples/multiple-discord-instances/Discords/CommandsA.ts index f6597ed9..dc884de8 100644 --- a/examples/multiple-discord-instances/Discords/CommandsA.ts +++ b/examples/multiple-discord-instances/Discords/CommandsA.ts @@ -1,13 +1,10 @@ -import { - Discord, - Slash, -} from "../../../src"; +import { Discord, Slash } from "../../../src"; import { CommandInteraction } from "discord.js"; @Discord() export class CommandsB { @Slash("hello2") - hello2(interaction: CommandInteraction) {; + hello2(interaction: CommandInteraction) { interaction.reply("Hello 2"); } } diff --git a/examples/multiple-discord-instances/Discords/CommandsB.ts b/examples/multiple-discord-instances/Discords/CommandsB.ts index ab9efb76..39cc21b2 100644 --- a/examples/multiple-discord-instances/Discords/CommandsB.ts +++ b/examples/multiple-discord-instances/Discords/CommandsB.ts @@ -1,13 +1,10 @@ -import { - Discord, - Slash, -} from "../../../src"; +import { Discord, Slash } from "../../../src"; import { CommandInteraction } from "discord.js"; @Discord() export class CommandsB { @Slash("hello") - hello(interaction: CommandInteraction) {; + hello(interaction: CommandInteraction) { interaction.reply("Hello 1"); } } diff --git a/examples/multiple-discord-instances/Main.ts b/examples/multiple-discord-instances/Main.ts index 0bc3bc1c..eeee38a4 100644 --- a/examples/multiple-discord-instances/Main.ts +++ b/examples/multiple-discord-instances/Main.ts @@ -10,10 +10,8 @@ export class Main { static async start() { this._client = new Client({ - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], slashGuilds: ["546281071751331840"], requiredByDefault: true, }); diff --git a/examples/slash/Main.ts b/examples/slash/Main.ts index 1857af99..315a69c5 100644 --- a/examples/slash/Main.ts +++ b/examples/slash/Main.ts @@ -11,10 +11,8 @@ export class Main { static async start() { this._client = new Client({ - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // slashGuilds: ["693401527494377482"], requiredByDefault: true, }); diff --git a/examples/slash/discords/AppDiscord.ts b/examples/slash/discords/AppDiscord.ts index 2674db04..b5e9d3ef 100644 --- a/examples/slash/discords/AppDiscord.ts +++ b/examples/slash/discords/AppDiscord.ts @@ -1,28 +1,17 @@ import { CommandInteraction } from "discord.js"; -import { - Discord, - Slash, - Option, - Guild, - Group, - Choices, -} from "../../../src"; +import { Discord, Slash, Option, Guild, Group, Choices } from "../../../src"; enum TextChoices { Hello = "Hello", - "Good Bye" = "GoodBye" + "Good Bye" = "GoodBye", } @Discord() @Guild("693401527494377482") -@Group( - "testing", - "Testing group description", - { - maths: "maths group description", - text: "text group description" - } -) +@Group("testing", "Testing group description", { + maths: "maths group description", + text: "text group description", +}) export abstract class AppDiscord { @Slash("add") @Group("maths") From 49fe6e93eae6ea151ccb1eae53004e05c6bb7f78 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:44:36 +0530 Subject: [PATCH 045/106] update executeInteraction --- src/Client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index b728721c..2e917bf0 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -485,11 +485,11 @@ export class Client extends ClientJS { } /** - * Execute the corresponding @Slash command based on an Interaction instance + * Execute the corresponding @Slash @Button @SelectMenu based on an Interaction instance * @param interaction The discord.js interaction instance * @returns void */ - async executeSlash(interaction: Interaction) { + async executeInteraction(interaction: Interaction) { if (!interaction) { if (!this.silent) { console.log("Interaction is undefined"); From 721e7fed188caeb037d776c274d4fe22b8280915 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 19:48:19 +0530 Subject: [PATCH 046/106] doc update bot multiple botid --- docs/src/decorators/guard.md | 1 + docs/src/decorators/option.md | 1 + docs/src/decorators/slash.md | 7 +++++-- docs/src/general/client.md | 4 ++++ docs/src/installation/README.md | 1 + examples/guards/Main.ts | 2 +- examples/multiple-discord-instances/Main.ts | 2 +- examples/slash/Main.ts | 2 +- tests/slash.test.ts | 14 +++++++------- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/src/decorators/guard.md b/docs/src/decorators/guard.md index d2982bef..ee215080 100644 --- a/docs/src/decorators/guard.md +++ b/docs/src/decorators/guard.md @@ -75,6 +75,7 @@ import { Client } from "@typeit/discord"; async function start() { const client = new Client({ + botId: "test", classes: [ `${__dirname}/*Discord.ts`, // glob string to load the classes `${__dirname}/*Discord.js`, // If you compile using "tsc" the file extension change to .js diff --git a/docs/src/decorators/option.md b/docs/src/decorators/option.md index 66647101..e5bc7587 100644 --- a/docs/src/decorators/option.md +++ b/docs/src/decorators/option.md @@ -162,6 +162,7 @@ if you want to set the default required value, you can use `client.requiredByDef ```ts const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, diff --git a/docs/src/decorators/slash.md b/docs/src/decorators/slash.md index de4484a8..1cdacc6c 100644 --- a/docs/src/decorators/slash.md +++ b/docs/src/decorators/slash.md @@ -19,7 +19,7 @@ abstract class AppDiscord { It require a bit of configuration at you Client initialization. You have to manualy execute and initialize your Slash commands by using: - `client.initSlashes()` -- `client.executeSlash(interaction)` +- `client.executeInteraction(interaction)` This provide flexibility in your code @@ -28,6 +28,7 @@ import { Client } from "@typeit/discord"; async function start() { const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, @@ -39,7 +40,7 @@ async function start() { }); client.on("interaction", (interaction) => { - client.executeSlash(interaction); + client.executeInteraction(interaction); }); await client.login("YOUR_TOKEN"); @@ -53,6 +54,7 @@ start(); ```ts const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, @@ -123,6 +125,7 @@ You can do: ```ts const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, diff --git a/docs/src/general/client.md b/docs/src/general/client.md index f7ff8cfa..253763a2 100644 --- a/docs/src/general/client.md +++ b/docs/src/general/client.md @@ -35,6 +35,7 @@ import { Client } from "@typeit/discord"; async function start() { const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, @@ -68,6 +69,7 @@ If an event of your app isn't triggered, you probably missed an Intent import { Intents } from "discord.js"; const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, @@ -81,6 +83,7 @@ const client = new Client({ import { Intents } from "discord.js"; const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, @@ -114,6 +117,7 @@ const client = new Client({ import { Intents } from "discord.js"; const client = new Client({ + botId: "test", intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, diff --git a/docs/src/installation/README.md b/docs/src/installation/README.md index e8de0c95..1b8f6a8c 100644 --- a/docs/src/installation/README.md +++ b/docs/src/installation/README.md @@ -76,6 +76,7 @@ Be aware that if you compile your code into JavaScript with `tsc` you have to sp ```ts const client = new Client({ + botId: "test", // glob string to load the classes classes: [ `${__dirname}/*Discord.ts`, // If you use ts-node diff --git a/examples/guards/Main.ts b/examples/guards/Main.ts index eeee38a4..f8a57a39 100644 --- a/examples/guards/Main.ts +++ b/examples/guards/Main.ts @@ -31,7 +31,7 @@ export class Main { }); this._client.on("interaction", (interaction) => { - this._client.executeSlash(interaction); + this._client.executeInteraction(interaction); }); } } diff --git a/examples/multiple-discord-instances/Main.ts b/examples/multiple-discord-instances/Main.ts index eeee38a4..f8a57a39 100644 --- a/examples/multiple-discord-instances/Main.ts +++ b/examples/multiple-discord-instances/Main.ts @@ -31,7 +31,7 @@ export class Main { }); this._client.on("interaction", (interaction) => { - this._client.executeSlash(interaction); + this._client.executeInteraction(interaction); }); } } diff --git a/examples/slash/Main.ts b/examples/slash/Main.ts index 315a69c5..b1a912a1 100644 --- a/examples/slash/Main.ts +++ b/examples/slash/Main.ts @@ -34,7 +34,7 @@ export class Main { }); this._client.on("interaction", (interaction) => { - this._client.executeSlash(interaction); + this._client.executeInteraction(interaction); }); } } diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 8b534c52..52ebb7cf 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -410,7 +410,7 @@ describe("Slash", () => { new FakeOption("text", "STRING", "hello"), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual(["/hello", "hello", interaction, true]); }); @@ -422,7 +422,7 @@ describe("Slash", () => { ]), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual([ "/testing hello text", "testing hello text", @@ -441,7 +441,7 @@ describe("Slash", () => { ]), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual([ "/testing text hello", "testing text hello", @@ -460,7 +460,7 @@ describe("Slash", () => { ]), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual(["/testing maths multiply", 10, interaction, true]); }); @@ -474,14 +474,14 @@ describe("Slash", () => { ]), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual(["/testing maths add", 7, interaction, true]); }); it("Should execute the with optional option", async () => { const interaction = new FakeInteraction("hello", []); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual(["/hello", undefined, interaction, true]); }); @@ -495,7 +495,7 @@ describe("Slash", () => { ]), ]); - const res = await client.executeSlash(interaction as any); + const res = await client.executeInteraction(interaction as any); expect(res).toEqual(undefined); }); }); From ac44935880107034b9663a8bbbdd271ea0fa52d4 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 20:51:40 +0530 Subject: [PATCH 047/106] accepted pull OwenCalvin/discord.ts/pull/56 --- src/decorators/classes/DSlash.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index addcdccf..a7ccb5d7 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -151,10 +151,8 @@ export class DSlash extends Method { parseParams(interaction: CommandInteraction) { const options = this.getLastNestedOption(interaction.options); - const values = this.options.map((opt, index) => { - return options[index]?.value; - }); - - return values; + return this.options + .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)) + .map((op) => options.find((o) => o.name === op.name)?.value); } } From 1d1c3e76363522dd55067edc83f88f232f6e5d77 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 22:51:07 +0530 Subject: [PATCH 048/106] added button example --- examples/button/Main.ts | 40 ++++ examples/button/discords/AppDiscord.ts | 215 ++++++++++++++++++++ examples/button/tsconfig.json | 17 ++ examples/event/Main.ts | 1 + examples/guards/Main.ts | 4 +- examples/multiple-discord-instances/Main.ts | 4 +- examples/slash/Main.ts | 4 +- 7 files changed, 276 insertions(+), 9 deletions(-) create mode 100644 examples/button/Main.ts create mode 100644 examples/button/discords/AppDiscord.ts create mode 100644 examples/button/tsconfig.json diff --git a/examples/button/Main.ts b/examples/button/Main.ts new file mode 100644 index 00000000..14c6cdc1 --- /dev/null +++ b/examples/button/Main.ts @@ -0,0 +1,40 @@ +import "reflect-metadata"; +import { Client } from "../../src"; +import { Intents } from "discord.js"; + +export class Main { + private static _client: Client; + + static get Client(): Client { + return this._client; + } + + static async start() { + this._client = new Client({ + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + // slashGuilds: [YOUR_GUILD_ID], + requiredByDefault: true, + }); + + // In the login method, you must specify the glob string to load your classes (for the framework). + // In this case that's not necessary because the entry point of your application is this file. + await this._client.login( + "YOU_TOKEN", + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js + ); + + this._client.once("ready", async () => { + await this._client.initSlashes(); + + console.log("Bot started"); + }); + + this._client.on("interaction", (interaction) => { + this._client.executeInteraction(interaction); + }); + } +} + +Main.start(); diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts new file mode 100644 index 00000000..6466f552 --- /dev/null +++ b/examples/button/discords/AppDiscord.ts @@ -0,0 +1,215 @@ +import { + CommandInteraction, + MessageButton, + MessageActionRow, + ButtonInteraction, + EmojiIdentifierResolvable, +} from "discord.js"; +import { + Discord, + Slash, + Button, + Bot, + Option, + Guild, + Description, + Choices, +} from "../../../src"; +import { randomInt } from "crypto"; + +enum spcChoice { + Stone = "Stone", + Paper = "Paper", + Scissor = "Scissor", +} + +enum spcResult { + WIN, + LOSS, + DRAW, +} + +class spcProposition { + public static propositions = [ + new spcProposition(spcChoice.Stone, "💎", "spc-stone"), + new spcProposition(spcChoice.Paper, "🧻", "spc-paper"), + new spcProposition(spcChoice.Scissor, "✂️", "spc-scissor"), + ]; + + public choice: spcChoice; + public emoji: EmojiIdentifierResolvable; + public buttonCustomID: "spc-stone" | "spc-paper" | "spc-scissor"; + + constructor( + choice: spcChoice, + emoji: EmojiIdentifierResolvable, + buttonCustomID: "spc-stone" | "spc-paper" | "spc-scissor" + ) { + this.choice = choice; + this.emoji = emoji; + this.buttonCustomID = buttonCustomID; + } + + public static nameToClass(choice: string) { + return this.propositions.find( + (proposition) => choice === proposition.choice + ); + } + + public static buttonCustomIDToClass(buttonCustomID: string) { + return this.propositions.find( + (proposition) => buttonCustomID === proposition.buttonCustomID + ); + } +} + +@Discord() +@Guild(process.env.IORP_GUILD_ID) +@Bot("alexa") +export abstract class StonePaperScissor { + @Slash("stonepaperscissor") + @Description( + "What could be more fun than play Rock Paper Scissor with a bot?" + ) + private async spc( + @Choices(spcChoice) + @Option("Choice", { + description: + "Your choose. If empty, it will send a message with buttons to choose and play instead.", + required: false, + }) + choice: spcChoice, + interaction: CommandInteraction + ) { + await interaction.defer(); + + if (choice) { + const choixJoueur = spcProposition.nameToClass(choice); + const BotChoice = StonePaperScissor.spcPlayBot(); + const resultat = StonePaperScissor.isWinPfc(choixJoueur, BotChoice); + + interaction.editReply( + StonePaperScissor.spcTraitementResultat( + choixJoueur, + BotChoice, + resultat + ) + ); + } else { + const boutonStone = new MessageButton() + .setLabel("Stone") + .setEmoji("💎") + .setStyle("PRIMARY") + .setCustomID("spc-stone"); + + const boutonPaper = new MessageButton() + .setLabel("Paper") + .setEmoji("🧻") + .setStyle("PRIMARY") + .setCustomID("spc-paper"); + + const boutonScissor = new MessageButton() + .setLabel("Scissor") + .setEmoji("✂️") + .setStyle("PRIMARY") + .setCustomID("spc-scissor"); + + const boutonPuit = new MessageButton() + .setLabel("Well") + .setEmoji("❓") + .setStyle("DANGER") + .setCustomID("spc-well") + .setDisabled(true); + + const buttonRow = new MessageActionRow().addComponents( + boutonStone, + boutonPaper, + boutonScissor, + boutonPuit + ); + + interaction.editReply({ + content: "Ok let's go. 1v1 Stone Paper Scissor. Go choose!", + components: [buttonRow], + }); + + setTimeout( + (interaction) => interaction.deleteReply(), + 10 * 60 * 1000, + interaction + ); + } + } + + @Button("spc-stone") + @Button("spc-paper") + @Button("spc-scissor") + private async spcButton(interaction: ButtonInteraction) { + await interaction.defer(); + + const choice = spcProposition.buttonCustomIDToClass(interaction.customID); + const BotChoice = StonePaperScissor.spcPlayBot(); + const resultat = StonePaperScissor.isWinPfc(choice, BotChoice); + + interaction.editReply( + StonePaperScissor.spcTraitementResultat(choice, BotChoice, resultat) + ); + + setTimeout( + (interaction) => { + try { + interaction.deleteReply(); + } catch (err) { + console.error(err); + } + }, + 30000, + interaction + ); + } + + private static isWinPfc( + player: spcProposition, + bot: spcProposition + ): spcResult { + switch (player.choice) { + case spcChoice.Stone: + if (bot.choice === spcChoice.Scissor) return spcResult.WIN; + if (bot.choice === spcChoice.Paper) return spcResult.LOSS; + return spcResult.DRAW; + case spcChoice.Paper: + if (bot.choice === spcChoice.Stone) return spcResult.WIN; + if (bot.choice === spcChoice.Scissor) return spcResult.LOSS; + return spcResult.DRAW; + case spcChoice.Scissor: + if (bot.choice === spcChoice.Paper) return spcResult.WIN; + if (bot.choice === spcChoice.Stone) return spcResult.LOSS; + return spcResult.DRAW; + } + } + + private static spcPlayBot(): spcProposition { + return spcProposition.propositions[randomInt(3)]; + } + + private static spcTraitementResultat( + choice: spcProposition, + BotChoice: spcProposition, + resultat: spcResult + ) { + switch (resultat) { + case spcResult.WIN: + return { + content: `${BotChoice.emoji} ${BotChoice.choice} ! Well, noob ${choice.emoji} ${choice.choice} need nerf plz...`, + }; + case spcResult.LOSS: + return { + content: `${BotChoice.emoji} ${BotChoice.choice} ! Okay bye, Easy!`, + }; + case spcResult.DRAW: + return { + content: `${BotChoice.emoji} ${BotChoice.choice} ! Ha... Draw...`, + }; + } + } +} diff --git a/examples/button/tsconfig.json b/examples/button/tsconfig.json new file mode 100644 index 00000000..e53b01d4 --- /dev/null +++ b/examples/button/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "noImplicitAny": false, + "sourceMap": true, + "outDir": "build", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2017", "esnext.asynciterable"], + "moduleResolution": "node" + }, + "exclude": ["node_modules", "tests", "examples"] +} diff --git a/examples/event/Main.ts b/examples/event/Main.ts index 359cf2b0..e0c9c080 100644 --- a/examples/event/Main.ts +++ b/examples/event/Main.ts @@ -13,6 +13,7 @@ export class Main { this._client = new Client({ botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + // slashGuilds: [YOUR_GUILD_ID], }); // In the login method, you must specify the glob string to load your classes (for the framework). diff --git a/examples/guards/Main.ts b/examples/guards/Main.ts index f8a57a39..3ac58246 100644 --- a/examples/guards/Main.ts +++ b/examples/guards/Main.ts @@ -12,7 +12,7 @@ export class Main { this._client = new Client({ botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], - slashGuilds: ["546281071751331840"], + // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, }); @@ -25,8 +25,6 @@ export class Main { ); this._client.once("ready", async () => { - await this._client.clearSlashes(); - await this._client.clearSlashes("546281071751331840"); await this._client.initSlashes(); }); diff --git a/examples/multiple-discord-instances/Main.ts b/examples/multiple-discord-instances/Main.ts index f8a57a39..3ac58246 100644 --- a/examples/multiple-discord-instances/Main.ts +++ b/examples/multiple-discord-instances/Main.ts @@ -12,7 +12,7 @@ export class Main { this._client = new Client({ botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], - slashGuilds: ["546281071751331840"], + // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, }); @@ -25,8 +25,6 @@ export class Main { ); this._client.once("ready", async () => { - await this._client.clearSlashes(); - await this._client.clearSlashes("546281071751331840"); await this._client.initSlashes(); }); diff --git a/examples/slash/Main.ts b/examples/slash/Main.ts index b1a912a1..14c6cdc1 100644 --- a/examples/slash/Main.ts +++ b/examples/slash/Main.ts @@ -13,7 +13,7 @@ export class Main { this._client = new Client({ botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], - // slashGuilds: ["693401527494377482"], + // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, }); @@ -26,8 +26,6 @@ export class Main { ); this._client.once("ready", async () => { - await this._client.clearSlashes(); - await this._client.clearSlashes("693401527494377482"); await this._client.initSlashes(); console.log("Bot started"); From df835225aa5fa6af3c26cd2f21c745657e5a642b Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 22:56:51 +0530 Subject: [PATCH 049/106] fix example button --- examples/button/discords/AppDiscord.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 6466f552..b8a8ba1f 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -9,9 +9,7 @@ import { Discord, Slash, Button, - Bot, Option, - Guild, Description, Choices, } from "../../../src"; @@ -64,8 +62,6 @@ class spcProposition { } @Discord() -@Guild(process.env.IORP_GUILD_ID) -@Bot("alexa") export abstract class StonePaperScissor { @Slash("stonepaperscissor") @Description( From 8c5fca1451ea2927828f4bef21d306cb5b896848 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 23:09:29 +0530 Subject: [PATCH 050/106] added menu example --- examples/menu/Main.ts | 40 +++++++++++++++++++++ examples/menu/discords/AppDiscord.ts | 54 ++++++++++++++++++++++++++++ examples/menu/tsconfig.json | 17 +++++++++ 3 files changed, 111 insertions(+) create mode 100644 examples/menu/Main.ts create mode 100644 examples/menu/discords/AppDiscord.ts create mode 100644 examples/menu/tsconfig.json diff --git a/examples/menu/Main.ts b/examples/menu/Main.ts new file mode 100644 index 00000000..14c6cdc1 --- /dev/null +++ b/examples/menu/Main.ts @@ -0,0 +1,40 @@ +import "reflect-metadata"; +import { Client } from "../../src"; +import { Intents } from "discord.js"; + +export class Main { + private static _client: Client; + + static get Client(): Client { + return this._client; + } + + static async start() { + this._client = new Client({ + botId: "test", + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + // slashGuilds: [YOUR_GUILD_ID], + requiredByDefault: true, + }); + + // In the login method, you must specify the glob string to load your classes (for the framework). + // In this case that's not necessary because the entry point of your application is this file. + await this._client.login( + "YOU_TOKEN", + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js + ); + + this._client.once("ready", async () => { + await this._client.initSlashes(); + + console.log("Bot started"); + }); + + this._client.on("interaction", (interaction) => { + this._client.executeInteraction(interaction); + }); + } +} + +Main.start(); diff --git a/examples/menu/discords/AppDiscord.ts b/examples/menu/discords/AppDiscord.ts new file mode 100644 index 00000000..c41899d5 --- /dev/null +++ b/examples/menu/discords/AppDiscord.ts @@ -0,0 +1,54 @@ +import { + CommandInteraction, + MessageActionRow, + SelectMenuInteraction, + MessageSelectMenu, +} from "discord.js"; +import { Discord, Slash, SelectMenu } from "../../../src"; + +const roles = [ + { label: "Principal", value: "principal" }, + { label: "Teacher", value: "teacher" }, + { label: "Student", value: "student" }, +]; + +@Discord() +export abstract class buttons { + @SelectMenu("role-menu") + async handle(interaction: SelectMenuInteraction): Promise { + await interaction.defer(); + + // extract selected value by member + const roleValue = interaction.values?.[0]; + + // if value not found + if (!roleValue) + return await interaction.followUp("invalid role id, select again"); + await interaction.followUp( + `you have selected role: ${ + roles.find((r) => r.value === roleValue).label + }` + ); + return; + } + + @Slash("myroles", { description: "roles menu" }) + async button(interaction: CommandInteraction): Promise { + await interaction.defer(); + + // create menu for roels + const menu = new MessageSelectMenu() + .addOptions(roles) + .setCustomID("role-menu"); + + // create a row for meessage actions + const buttonRow = new MessageActionRow().addComponents(menu); + + // send it + interaction.editReply({ + content: "select your role!", + components: [buttonRow], + }); + return; + } +} diff --git a/examples/menu/tsconfig.json b/examples/menu/tsconfig.json new file mode 100644 index 00000000..e53b01d4 --- /dev/null +++ b/examples/menu/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "noImplicitAny": false, + "sourceMap": true, + "outDir": "build", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2017", "esnext.asynciterable"], + "moduleResolution": "node" + }, + "exclude": ["node_modules", "tests", "examples"] +} From 60d875979d803f2a0bb37c48a6aa550b45fee3f8 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 23:34:51 +0530 Subject: [PATCH 051/106] update --- src/decorators/decorators/Bot.ts | 2 +- src/decorators/decorators/Choice.ts | 4 ++-- src/decorators/decorators/Description.ts | 2 +- src/decorators/decorators/Group.ts | 2 +- src/decorators/decorators/Guard.ts | 2 +- src/decorators/decorators/Guild.ts | 2 +- src/decorators/decorators/Name.ts | 2 +- src/decorators/decorators/Option.ts | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 4c01ca21..05996d72 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -14,7 +14,7 @@ export function Bot(...botIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.botIds = [ ...original.botIds, ...botIDs.filter((botID) => !original.botIds.includes(botID)), diff --git a/src/decorators/decorators/Choice.ts b/src/decorators/decorators/Choice.ts index c08e4b77..40db1cf4 100644 --- a/src/decorators/decorators/Choice.ts +++ b/src/decorators/decorators/Choice.ts @@ -3,9 +3,9 @@ import { MetadataStorage, DChoice, DOption, Modifier } from "../.."; export function Choice(name: string, value: number); export function Choice(name: string, value: string); export function Choice(name: string, value: string | number) { - return async (target: Object, key: string, index: number) => { + return (target: Object, key: string, index: number) => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.choices = [...original.choices, DChoice.create(name, value)]; }, DOption).decorate( target.constructor, diff --git a/src/decorators/decorators/Description.ts b/src/decorators/decorators/Description.ts index 2d7b8115..820ba92c 100644 --- a/src/decorators/decorators/Description.ts +++ b/src/decorators/decorators/Description.ts @@ -9,7 +9,7 @@ export function Description(description: string) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.description = description; }, DSlash).decorate(target.constructor, key, descriptor.value) ); diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index dd186cf0..0c365d50 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -63,7 +63,7 @@ export function Group( } else { // If @Group decorate a method edit the method and add it to subgroup MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.subgroup = group as string; }, DSlash).decorate(target.constructor, key as string) ); diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index fb838a9e..d9037297 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -25,7 +25,7 @@ export function Guard( MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.guards = guards; }, DSelectMenu, diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index 10c16dab..b4efb366 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -14,7 +14,7 @@ export function Guild(...guildIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.guilds = [ ...original.guilds, ...guildIDs.filter((guildID) => !original.guilds.includes(guildID)), diff --git a/src/decorators/decorators/Name.ts b/src/decorators/decorators/Name.ts index 3fd8441c..95eb8ce3 100644 --- a/src/decorators/decorators/Name.ts +++ b/src/decorators/decorators/Name.ts @@ -9,7 +9,7 @@ export function Name(name: string) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.name = name; }, DSlash, diff --git a/src/decorators/decorators/Option.ts b/src/decorators/decorators/Option.ts index cf51aab5..3b7476a4 100644 --- a/src/decorators/decorators/Option.ts +++ b/src/decorators/decorators/Option.ts @@ -29,7 +29,7 @@ export function Option(name: string, params?: OptionParams) { option.isNode = true; MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.options = [...original.options, option]; }, DSlash).decorate( target.constructor, From 16fd3e043d3c230e67de353714c26edfb050aad5 Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 23:47:16 +0530 Subject: [PATCH 052/106] restored important async on decorators --- src/decorators/decorators/Bot.ts | 2 +- src/decorators/decorators/Choice.ts | 2 +- src/decorators/decorators/Description.ts | 2 +- src/decorators/decorators/Group.ts | 2 +- src/decorators/decorators/Guard.ts | 2 +- src/decorators/decorators/Guild.ts | 2 +- src/decorators/decorators/Name.ts | 2 +- src/decorators/decorators/Option.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 05996d72..4c01ca21 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -14,7 +14,7 @@ export function Bot(...botIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - (original) => { + async (original) => { original.botIds = [ ...original.botIds, ...botIDs.filter((botID) => !original.botIds.includes(botID)), diff --git a/src/decorators/decorators/Choice.ts b/src/decorators/decorators/Choice.ts index 40db1cf4..094459e4 100644 --- a/src/decorators/decorators/Choice.ts +++ b/src/decorators/decorators/Choice.ts @@ -5,7 +5,7 @@ export function Choice(name: string, value: string); export function Choice(name: string, value: string | number) { return (target: Object, key: string, index: number) => { MetadataStorage.instance.addModifier( - Modifier.create((original) => { + Modifier.create(async (original) => { original.choices = [...original.choices, DChoice.create(name, value)]; }, DOption).decorate( target.constructor, diff --git a/src/decorators/decorators/Description.ts b/src/decorators/decorators/Description.ts index 820ba92c..2d7b8115 100644 --- a/src/decorators/decorators/Description.ts +++ b/src/decorators/decorators/Description.ts @@ -9,7 +9,7 @@ export function Description(description: string) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create((original) => { + Modifier.create(async (original) => { original.description = description; }, DSlash).decorate(target.constructor, key, descriptor.value) ); diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index 0c365d50..dd186cf0 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -63,7 +63,7 @@ export function Group( } else { // If @Group decorate a method edit the method and add it to subgroup MetadataStorage.instance.addModifier( - Modifier.create((original) => { + Modifier.create(async (original) => { original.subgroup = group as string; }, DSlash).decorate(target.constructor, key as string) ); diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index d9037297..fb838a9e 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -25,7 +25,7 @@ export function Guard( MetadataStorage.instance.addModifier( Modifier.create( - (original) => { + async (original) => { original.guards = guards; }, DSelectMenu, diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index b4efb366..10c16dab 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -14,7 +14,7 @@ export function Guild(...guildIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - (original) => { + async (original) => { original.guilds = [ ...original.guilds, ...guildIDs.filter((guildID) => !original.guilds.includes(guildID)), diff --git a/src/decorators/decorators/Name.ts b/src/decorators/decorators/Name.ts index 95eb8ce3..3fd8441c 100644 --- a/src/decorators/decorators/Name.ts +++ b/src/decorators/decorators/Name.ts @@ -9,7 +9,7 @@ export function Name(name: string) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - (original) => { + async (original) => { original.name = name; }, DSlash, diff --git a/src/decorators/decorators/Option.ts b/src/decorators/decorators/Option.ts index 3b7476a4..cf51aab5 100644 --- a/src/decorators/decorators/Option.ts +++ b/src/decorators/decorators/Option.ts @@ -29,7 +29,7 @@ export function Option(name: string, params?: OptionParams) { option.isNode = true; MetadataStorage.instance.addModifier( - Modifier.create((original) => { + Modifier.create(async (original) => { original.options = [...original.options, option]; }, DSlash).decorate( target.constructor, From fb9866a8dfee96bf2c41310d33005ac40756ee7e Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 23:51:42 +0530 Subject: [PATCH 053/106] * jest test failed because of buttons * removed unwanted asyn from decorator --- src/decorators/decorators/Bot.ts | 2 +- src/decorators/decorators/Choice.ts | 2 +- src/decorators/decorators/Description.ts | 2 +- src/decorators/decorators/Group.ts | 2 +- src/decorators/decorators/Guard.ts | 2 +- src/decorators/decorators/Guild.ts | 2 +- src/decorators/decorators/Name.ts | 2 +- src/decorators/decorators/Option.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 4c01ca21..05996d72 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -14,7 +14,7 @@ export function Bot(...botIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.botIds = [ ...original.botIds, ...botIDs.filter((botID) => !original.botIds.includes(botID)), diff --git a/src/decorators/decorators/Choice.ts b/src/decorators/decorators/Choice.ts index 094459e4..40db1cf4 100644 --- a/src/decorators/decorators/Choice.ts +++ b/src/decorators/decorators/Choice.ts @@ -5,7 +5,7 @@ export function Choice(name: string, value: string); export function Choice(name: string, value: string | number) { return (target: Object, key: string, index: number) => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.choices = [...original.choices, DChoice.create(name, value)]; }, DOption).decorate( target.constructor, diff --git a/src/decorators/decorators/Description.ts b/src/decorators/decorators/Description.ts index 2d7b8115..820ba92c 100644 --- a/src/decorators/decorators/Description.ts +++ b/src/decorators/decorators/Description.ts @@ -9,7 +9,7 @@ export function Description(description: string) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.description = description; }, DSlash).decorate(target.constructor, key, descriptor.value) ); diff --git a/src/decorators/decorators/Group.ts b/src/decorators/decorators/Group.ts index dd186cf0..0c365d50 100644 --- a/src/decorators/decorators/Group.ts +++ b/src/decorators/decorators/Group.ts @@ -63,7 +63,7 @@ export function Group( } else { // If @Group decorate a method edit the method and add it to subgroup MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.subgroup = group as string; }, DSlash).decorate(target.constructor, key as string) ); diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index fb838a9e..d9037297 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -25,7 +25,7 @@ export function Guard( MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.guards = guards; }, DSelectMenu, diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index 10c16dab..b4efb366 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -14,7 +14,7 @@ export function Guild(...guildIDs: string[]) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.guilds = [ ...original.guilds, ...guildIDs.filter((guildID) => !original.guilds.includes(guildID)), diff --git a/src/decorators/decorators/Name.ts b/src/decorators/decorators/Name.ts index 3fd8441c..95eb8ce3 100644 --- a/src/decorators/decorators/Name.ts +++ b/src/decorators/decorators/Name.ts @@ -9,7 +9,7 @@ export function Name(name: string) { ): void => { MetadataStorage.instance.addModifier( Modifier.create( - async (original) => { + (original) => { original.name = name; }, DSlash, diff --git a/src/decorators/decorators/Option.ts b/src/decorators/decorators/Option.ts index cf51aab5..3b7476a4 100644 --- a/src/decorators/decorators/Option.ts +++ b/src/decorators/decorators/Option.ts @@ -29,7 +29,7 @@ export function Option(name: string, params?: OptionParams) { option.isNode = true; MetadataStorage.instance.addModifier( - Modifier.create(async (original) => { + Modifier.create((original) => { original.options = [...original.options, option]; }, DSlash).decorate( target.constructor, From 53017f6023ebc5f311c4ff190995ae771d5f66de Mon Sep 17 00:00:00 2001 From: iorp Date: Sat, 3 Jul 2021 23:57:30 +0530 Subject: [PATCH 054/106] jest test fix for slash commands --- src/Client.ts | 4 ++-- tests/slash.test.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 2e917bf0..9bab5eb4 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -510,7 +510,7 @@ export class Client extends ClientJS { `button interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` ); - button.execute(interaction, this); + return button.execute(interaction, this); } // if interaction is a button @@ -526,7 +526,7 @@ export class Client extends ClientJS { `selectMenu interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` ); - menu.execute(interaction, this); + return menu.execute(interaction, this); } // If the interaction isn't a slash command, return diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 52ebb7cf..32db380f 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -182,6 +182,14 @@ class FakeInteraction { isCommand() { return true; } + + isButton() { + return false; + } + + isSelectMenu() { + return false; + } } describe("Slash", () => { From 932dea0d719604e08b7abb67f9055d1f327f530c Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:00:10 +0530 Subject: [PATCH 055/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index b8a8ba1f..fc56fa1c 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -80,9 +80,9 @@ export abstract class StonePaperScissor { await interaction.defer(); if (choice) { - const choixJoueur = spcProposition.nameToClass(choice); - const BotChoice = StonePaperScissor.spcPlayBot(); - const resultat = StonePaperScissor.isWinPfc(choixJoueur, BotChoice); + const playerChoice = spcProposition.nameToClass(choice); + const botChoice = StonePaperScissor.spcPlayBot(); + const result = StonePaperScissor.isWinPfc(playerChoice, botChoice); interaction.editReply( StonePaperScissor.spcTraitementResultat( From 2b5910568667bd0acdef4a959a0b5f6684a07c68 Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:00:25 +0530 Subject: [PATCH 056/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index fc56fa1c..6dc1247f 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -85,7 +85,7 @@ export abstract class StonePaperScissor { const result = StonePaperScissor.isWinPfc(playerChoice, botChoice); interaction.editReply( - StonePaperScissor.spcTraitementResultat( + StonePaperScissor.spcResultProcess( choixJoueur, BotChoice, resultat From 680ad518bb3cfbd1d76b60683ad472bbfa3f12fd Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:00:50 +0530 Subject: [PATCH 057/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 6dc1247f..4bf7dc95 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -92,25 +92,25 @@ export abstract class StonePaperScissor { ) ); } else { - const boutonStone = new MessageButton() + const buttonStone = new MessageButton() .setLabel("Stone") .setEmoji("💎") .setStyle("PRIMARY") .setCustomID("spc-stone"); - const boutonPaper = new MessageButton() + const buttonPaper = new MessageButton() .setLabel("Paper") .setEmoji("🧻") .setStyle("PRIMARY") .setCustomID("spc-paper"); - const boutonScissor = new MessageButton() + const buttonScissor = new MessageButton() .setLabel("Scissor") .setEmoji("✂️") .setStyle("PRIMARY") .setCustomID("spc-scissor"); - const boutonPuit = new MessageButton() + const buttonWell = new MessageButton() .setLabel("Well") .setEmoji("❓") .setStyle("DANGER") @@ -118,10 +118,10 @@ export abstract class StonePaperScissor { .setDisabled(true); const buttonRow = new MessageActionRow().addComponents( - boutonStone, - boutonPaper, - boutonScissor, - boutonPuit + buttonStone, + buttonPaper, + buttonScissor, + buttonWell ); interaction.editReply({ From 816b6520e161f3ed39c625ec8cf64545d7111d05 Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:00:59 +0530 Subject: [PATCH 058/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 4bf7dc95..009f27a4 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -86,9 +86,9 @@ export abstract class StonePaperScissor { interaction.editReply( StonePaperScissor.spcResultProcess( - choixJoueur, - BotChoice, - resultat + playerChoice, + botChoise, + result ) ); } else { From 8b346ae9ec36ec336f1d8415d19a4bf742f513db Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:01:14 +0530 Subject: [PATCH 059/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 009f27a4..45a0e01e 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -143,12 +143,12 @@ export abstract class StonePaperScissor { private async spcButton(interaction: ButtonInteraction) { await interaction.defer(); - const choice = spcProposition.buttonCustomIDToClass(interaction.customID); - const BotChoice = StonePaperScissor.spcPlayBot(); - const resultat = StonePaperScissor.isWinPfc(choice, BotChoice); + const playerChoice = spcProposition.buttonCustomIDToClass(interaction.customID); + const botChoice = StonePaperScissor.spcPlayBot(); + const result = StonePaperScissor.isWinSpc(playerChoice, botChoice); interaction.editReply( - StonePaperScissor.spcTraitementResultat(choice, BotChoice, resultat) + StonePaperScissor.spcResultProcess(playerChoice, botChoice, result) ); setTimeout( From 92da21fedc01a1879ed2eaa06fbf2cda05d321b6 Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:01:24 +0530 Subject: [PATCH 060/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 45a0e01e..40453b60 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -188,7 +188,7 @@ export abstract class StonePaperScissor { return spcProposition.propositions[randomInt(3)]; } - private static spcTraitementResultat( + private static spcResultProcess( choice: spcProposition, BotChoice: spcProposition, resultat: spcResult From 24118366a1f5bd11c21cef4abbbe0004bb6825f6 Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:01:33 +0530 Subject: [PATCH 061/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 40453b60..8152f929 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -164,7 +164,7 @@ export abstract class StonePaperScissor { ); } - private static isWinPfc( + private static isWinSpc( player: spcProposition, bot: spcProposition ): spcResult { From f84dfbb2b04c2902691edf09ce5d6af98a9ecaa9 Mon Sep 17 00:00:00 2001 From: Indian Ocean Roleplay <43092101+oceanroleplay@users.noreply.github.com> Date: Sun, 4 Jul 2021 00:02:06 +0530 Subject: [PATCH 062/106] Update examples/button/discords/AppDiscord.ts Co-authored-by: Tenebrosful <48710891+Tenebrosful@users.noreply.github.com> --- examples/button/discords/AppDiscord.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 8152f929..94b3935d 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -189,22 +189,22 @@ export abstract class StonePaperScissor { } private static spcResultProcess( - choice: spcProposition, - BotChoice: spcProposition, - resultat: spcResult + playerChoice: spcProposition, + botChoice: spcProposition, + result: spcResult ) { - switch (resultat) { + switch (result) { case spcResult.WIN: return { - content: `${BotChoice.emoji} ${BotChoice.choice} ! Well, noob ${choice.emoji} ${choice.choice} need nerf plz...`, + content: `${botChoice.emoji} ${botChoice.choice} ! Well, noob ${playerChoice.emoji} ${playerChoice.choice} need nerf plz...`, }; case spcResult.LOSS: return { - content: `${BotChoice.emoji} ${BotChoice.choice} ! Okay bye, Easy!`, + content: `${otChoice.emoji} ${otChoice.choice} ! Okay bye, Easy!`, }; case spcResult.DRAW: return { - content: `${BotChoice.emoji} ${BotChoice.choice} ! Ha... Draw...`, + content: `${botChoice.emoji} ${botChoice.choice} ! Ha... Draw...`, }; } } From 5a1a6aaed6e48dd15fb5c091e955fadee6fbaa2b Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 00:03:26 +0530 Subject: [PATCH 063/106] fix button example --- examples/button/discords/AppDiscord.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 94b3935d..3f74c1ff 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -82,14 +82,10 @@ export abstract class StonePaperScissor { if (choice) { const playerChoice = spcProposition.nameToClass(choice); const botChoice = StonePaperScissor.spcPlayBot(); - const result = StonePaperScissor.isWinPfc(playerChoice, botChoice); + const result = StonePaperScissor.isWinSpc(playerChoice, botChoice); interaction.editReply( - StonePaperScissor.spcResultProcess( - playerChoice, - botChoise, - result - ) + StonePaperScissor.spcResultProcess(playerChoice, botChoice, result) ); } else { const buttonStone = new MessageButton() @@ -143,7 +139,9 @@ export abstract class StonePaperScissor { private async spcButton(interaction: ButtonInteraction) { await interaction.defer(); - const playerChoice = spcProposition.buttonCustomIDToClass(interaction.customID); + const playerChoice = spcProposition.buttonCustomIDToClass( + interaction.customID + ); const botChoice = StonePaperScissor.spcPlayBot(); const result = StonePaperScissor.isWinSpc(playerChoice, botChoice); @@ -200,7 +198,7 @@ export abstract class StonePaperScissor { }; case spcResult.LOSS: return { - content: `${otChoice.emoji} ${otChoice.choice} ! Okay bye, Easy!`, + content: `${botChoice.emoji} ${botChoice.choice} ! Okay bye, Easy!`, }; case spcResult.DRAW: return { From fa563e7535fd1d48a34cd01f977e7e7fe3511bc5 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 00:19:31 +0530 Subject: [PATCH 064/106] requiredByDefault set back to false --- src/Client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index 9bab5eb4..ca76f1a0 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -140,7 +140,7 @@ export class Client extends ClientJS { this._silent = !!options?.silent; this._loadClasses = options?.classes || []; this.guards = options.guards || []; - this.requiredByDefault = options.requiredByDefault ?? true; + this.requiredByDefault = options.requiredByDefault ?? false; this.slashGuilds = options.slashGuilds || []; this._botId = options.botId; } From 3514725b290e4e31029e393290154d594717c91d Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 00:23:33 +0530 Subject: [PATCH 065/106] doc update: botid required, classes not required --- docs/src/general/client.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/general/client.md b/docs/src/general/client.md index 253763a2..a49b98b1 100644 --- a/docs/src/general/client.md +++ b/docs/src/general/client.md @@ -5,7 +5,11 @@ It manage all the operations between your app, Discord's API and discord.js In order to start your application, you must use the discord.**ts**'s Client (not the client that is provided by discord.**js**!). It works the same as the discord.**js**'s Client (same methods, properties, ...). -- **`classes` (required)** +- **`botId` (required)** + `string` + a bot id, help you manage your bot interactions, events (this is important in case there are more than one bot running in single instance) + +- **`classes`** `string[]` Indicate the class jacket of your classes containing the `@Discord` decorator. It accepts a list of classes or of (glob) paths From 6929eec3713516007668b20320c4dc57360e4b9e Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 00:24:53 +0530 Subject: [PATCH 066/106] doc update: MetadataStorage --- docs/src/general/metadatastorage.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/general/metadatastorage.md b/docs/src/general/metadatastorage.md index dac722c7..e245f918 100644 --- a/docs/src/general/metadatastorage.md +++ b/docs/src/general/metadatastorage.md @@ -7,5 +7,7 @@ import { MetadataStorage } from "@typeit/discord.ts" MetadataStorage.instance.slashes; MetadataStorage.instance.events; MetadataStorage.instance.discords; +MetadataStorage.instance.buttons; +MetadataStorage.instance.selectMenus; // ... ``` From 79b85cc574482922064fada0a51e290eb783749f Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 01:00:43 +0530 Subject: [PATCH 067/106] doc update --- docs/src/.vuepress/config.js | 17 ++++++++++------- docs/src/decorators/bot.md | 3 +++ docs/src/decorators/button.md | 2 ++ docs/src/decorators/guard.md | 17 +++++++++-------- docs/src/decorators/guild.md | 2 +- docs/src/decorators/on.md | 6 +++--- docs/src/decorators/once.md | 4 ++-- docs/src/decorators/selectmenu.md | 2 ++ docs/src/decorators/slash.md | 2 +- docs/src/general/argsof.md | 4 ++-- docs/src/general/client.md | 6 +++++- 11 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 docs/src/decorators/bot.md create mode 100644 docs/src/decorators/button.md create mode 100644 docs/src/decorators/selectmenu.md diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js index f7883258..5183b5ff 100755 --- a/docs/src/.vuepress/config.js +++ b/docs/src/.vuepress/config.js @@ -69,17 +69,20 @@ module.exports = { path: "/decorators/discord", children: [ ["/decorators/discord", "@Discord"], - ["/decorators/on", "@On"], - ["/decorators/once", "@Once"], - ["/decorators/slash", "@Slash"], - ["/decorators/option", "@Option"], + ["/decorators/bot", "@Bot"], + ["/decorators/button", "@Button"], ["/decorators/choice", "@Choice"], ["/decorators/choices", "@Choices"], - ["/decorators/guild", "@Guild"], - ["/decorators/permission", "@Permission"], + ["/decorators/description", "@Description"], ["/decorators/group", "@Group"], ["/decorators/guard", "@Guard"], - ["/decorators/description", "@Description"], + ["/decorators/guild", "@Guild"], + ["/decorators/on", "@On"], + ["/decorators/once", "@Once"], + ["/decorators/option", "@Option"], + ["/decorators/permission", "@Permission"], + ["/decorators/selectmenu", "@SelectMenu"], + ["/decorators/slash", "@Slash"], ] } ] diff --git a/docs/src/decorators/bot.md b/docs/src/decorators/bot.md new file mode 100644 index 00000000..256ca7ad --- /dev/null +++ b/docs/src/decorators/bot.md @@ -0,0 +1,3 @@ +# @Bot +doc is not ready + diff --git a/docs/src/decorators/button.md b/docs/src/decorators/button.md new file mode 100644 index 00000000..4cac3459 --- /dev/null +++ b/docs/src/decorators/button.md @@ -0,0 +1,2 @@ +# @Button +doc is not ready \ No newline at end of file diff --git a/docs/src/decorators/guard.md b/docs/src/decorators/guard.md index ee215080..df7c5a42 100644 --- a/docs/src/decorators/guard.md +++ b/docs/src/decorators/guard.md @@ -1,10 +1,11 @@ # @Guard +//todo add example for slash, argof message does not apply on interactions You can use functions that are executed before your event to determine if it's executed. For example, if you want to apply a prefix to the messages, you can simply use the `@Guard` decorator. The order of execution of the guards is done according to their position in the list, so they will be executed in order (from top to bottom). -Guards can be set for `@Slash`, `@On`, `@Once`, `@Discord` and globaly. +Guards can be set for `@Slash`, `@Button`, `@SelectMenu`, `@On`, `@Once`, `@Discord` and globaly. ```typescript import { Discord, On, Client, Guard } from "@typeit/discord"; @@ -13,12 +14,12 @@ import { Prefix } from "./Prefix"; @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") @Guard( NotBot, // You can use multiple guard functions, they are excuted in the same order! Prefix("!") ) - async onMessage([message]: ArgsOf<"message">) { + async onMessage([message]: ArgsOf<"messageCreate">) { switch (message.content.toLowerCase()) { case "hello": message.reply("Hello!"); @@ -49,8 +50,8 @@ import { Prefix } from "./Prefix"; @Discord() @Guard(NotBot, Prefix("!")) abstract class AppDiscord { - @On("message") - message([message]: ArgsOf<"message">) { + @On("messageCreate") + message([message]: ArgsOf<"messageCreate">) { //... } @@ -105,7 +106,7 @@ Guards work like `Koa`'s, it's a function passed in parameter (third parameter i ```typescript import { GuardFunction, ArgsOf } from "@typeit/discord"; -export const NotBot: GuardFunction> = ([message], client, next) => { +export const NotBot: GuardFunction> = ([message], client, next) => { if (client.user.id !== message.author.id) { await next(); } @@ -118,7 +119,7 @@ If you have to indicate parameters for a guard function you can simple use the " import { GuardFunction } from "@typeit/discord"; export function Prefix(text: string, replace: boolean = true) { - const guard: GuardFunction> = ([message], client, next) => { + const guard: GuardFunction> = ([message], client, next) => { const startWith = message.content.startsWith(text); if (replace) { message.content = message.content.replace(text, ""); @@ -139,7 +140,7 @@ As 4th parameter you receive a basic empty object that can be used to transmit d ```typescript import { GuardFunction } from "@typeit/discord"; -export const NotBot: GuardFunction> = ( +export const NotBot: GuardFunction> = ( [message], client, next, diff --git a/docs/src/decorators/guild.md b/docs/src/decorators/guild.md index 28e7ff06..84620a40 100644 --- a/docs/src/decorators/guild.md +++ b/docs/src/decorators/guild.md @@ -1,5 +1,5 @@ # @Guild -You can specify in wich guilds your @Slash commands are created by decorating the method with @Slash and @Guild +You can specify in which guilds your @Slash commands are created by decorating the method with @Slash and @Guild ```ts @Discord() diff --git a/docs/src/decorators/on.md b/docs/src/decorators/on.md index a2712e64..800c3867 100644 --- a/docs/src/decorators/on.md +++ b/docs/src/decorators/on.md @@ -10,7 +10,7 @@ import { Discord, On, Once } from "@typeit/discord"; @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") private onMessage() { // ... } @@ -42,9 +42,9 @@ import { @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") private onMessage( - [message]: ArgsOf<"message">, // Type message automatically + [message]: ArgsOf<"messageCreate">, // Type message automatically client: Client, // Client instance injected here, guardPayload: any ) { diff --git a/docs/src/decorators/once.md b/docs/src/decorators/once.md index 96337c96..aacec76d 100644 --- a/docs/src/decorators/once.md +++ b/docs/src/decorators/once.md @@ -33,9 +33,9 @@ import { @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") private onMessage( - [message]: ArgsOf<"message">, // Type message automatically + [message]: ArgsOf<"messageCreate">, // Type message automatically client: Client, // Client instance injected here, guardPayload: any ) { diff --git a/docs/src/decorators/selectmenu.md b/docs/src/decorators/selectmenu.md new file mode 100644 index 00000000..2e002225 --- /dev/null +++ b/docs/src/decorators/selectmenu.md @@ -0,0 +1,2 @@ +# @SelectMenu +doc is not ready \ No newline at end of file diff --git a/docs/src/decorators/slash.md b/docs/src/decorators/slash.md index 1cdacc6c..f8d60668 100644 --- a/docs/src/decorators/slash.md +++ b/docs/src/decorators/slash.md @@ -39,7 +39,7 @@ async function start() { await client.initSlashes(); }); - client.on("interaction", (interaction) => { + client.on("interactionCreate", (interaction) => { client.executeInteraction(interaction); }); diff --git a/docs/src/general/argsof.md b/docs/src/general/argsof.md index fe163c3a..fc4610e7 100644 --- a/docs/src/general/argsof.md +++ b/docs/src/general/argsof.md @@ -13,10 +13,10 @@ import { @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") private onMessage( // The type of message is Message - [message]: ArgsOf<"message"> + [message]: ArgsOf<"messageCreate"> ) { // ... } diff --git a/docs/src/general/client.md b/docs/src/general/client.md index a49b98b1..3b879fa1 100644 --- a/docs/src/general/client.md +++ b/docs/src/general/client.md @@ -9,6 +9,10 @@ It works the same as the discord.**js**'s Client (same methods, properties, ...) `string` a bot id, help you manage your bot interactions, events (this is important in case there are more than one bot running in single instance) +- **`intents` (required)** + `Intents[]` + [see Intents](#intents) + - **`classes`** `string[]` Indicate the class jacket of your classes containing the `@Discord` decorator. It accepts a list of classes or of (glob) paths @@ -58,7 +62,7 @@ start(); ``` ## Intents -You must specify the "**intents**" of your bot when you initialize the Client, it specify wich informations your bot receive from the Discord's servers, **it's different from the permissions** +You must specify the "**intents**" of your bot when you initialize the Client, it specify which informations your bot receive from the Discord's servers, **it's different from the permissions** *Maintaining a stateful application can be difficult when it comes to the amount of data you're expected to process, especially at scale. Gateway Intents are a system to help you lower that computational burden.* From f770a2e51ecb068ee444d9cf591a5fb571315593 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 01:03:32 +0530 Subject: [PATCH 068/106] doc: added incomplete notes --- docs/src/decorators/bot.md | 4 +++- docs/src/decorators/button.md | 5 ++++- docs/src/decorators/guard.md | 4 +++- docs/src/decorators/selectmenu.md | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/src/decorators/bot.md b/docs/src/decorators/bot.md index 256ca7ad..dcd98a23 100644 --- a/docs/src/decorators/bot.md +++ b/docs/src/decorators/bot.md @@ -1,3 +1,5 @@ # @Bot -doc is not ready +::: danger +doc of `@Bot` is not ready +::: \ No newline at end of file diff --git a/docs/src/decorators/button.md b/docs/src/decorators/button.md index 4cac3459..d30d186c 100644 --- a/docs/src/decorators/button.md +++ b/docs/src/decorators/button.md @@ -1,2 +1,5 @@ # @Button -doc is not ready \ No newline at end of file + +::: danger +doc of `@Button` is not ready +::: \ No newline at end of file diff --git a/docs/src/decorators/guard.md b/docs/src/decorators/guard.md index df7c5a42..8d949670 100644 --- a/docs/src/decorators/guard.md +++ b/docs/src/decorators/guard.md @@ -1,5 +1,7 @@ # @Guard -//todo add example for slash, argof message does not apply on interactions +::: warning +add example for slash, argof message does not apply on interactions +::: You can use functions that are executed before your event to determine if it's executed. For example, if you want to apply a prefix to the messages, you can simply use the `@Guard` decorator. diff --git a/docs/src/decorators/selectmenu.md b/docs/src/decorators/selectmenu.md index 2e002225..0091dce2 100644 --- a/docs/src/decorators/selectmenu.md +++ b/docs/src/decorators/selectmenu.md @@ -1,2 +1,5 @@ # @SelectMenu -doc is not ready \ No newline at end of file + +::: danger +doc of `@SelectMenu` is not ready +::: \ No newline at end of file From 659ef2f7a87d2d20de233a8ab676111650161158 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 01:04:51 +0530 Subject: [PATCH 069/106] doc: warning for incomplete docs --- docs/src/decorators/bot.md | 2 +- docs/src/decorators/button.md | 2 +- docs/src/decorators/selectmenu.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/decorators/bot.md b/docs/src/decorators/bot.md index dcd98a23..1229f6e5 100644 --- a/docs/src/decorators/bot.md +++ b/docs/src/decorators/bot.md @@ -1,5 +1,5 @@ # @Bot ::: danger -doc of `@Bot` is not ready +doc for `@Bot` is not ready ::: \ No newline at end of file diff --git a/docs/src/decorators/button.md b/docs/src/decorators/button.md index d30d186c..4f453492 100644 --- a/docs/src/decorators/button.md +++ b/docs/src/decorators/button.md @@ -1,5 +1,5 @@ # @Button ::: danger -doc of `@Button` is not ready +doc for `@Button` is not ready ::: \ No newline at end of file diff --git a/docs/src/decorators/selectmenu.md b/docs/src/decorators/selectmenu.md index 0091dce2..2be83cd8 100644 --- a/docs/src/decorators/selectmenu.md +++ b/docs/src/decorators/selectmenu.md @@ -1,5 +1,5 @@ # @SelectMenu ::: danger -doc of `@SelectMenu` is not ready +doc for `@SelectMenu` is not ready ::: \ No newline at end of file From 0c911f6880a78b4d65577cc38b6baa1fc8e7d854 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 10:35:00 +0530 Subject: [PATCH 070/106] example update: function rename --- examples/menu/discords/AppDiscord.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/menu/discords/AppDiscord.ts b/examples/menu/discords/AppDiscord.ts index c41899d5..3aadf074 100644 --- a/examples/menu/discords/AppDiscord.ts +++ b/examples/menu/discords/AppDiscord.ts @@ -33,7 +33,7 @@ export abstract class buttons { } @Slash("myroles", { description: "roles menu" }) - async button(interaction: CommandInteraction): Promise { + async myroles(interaction: CommandInteraction): Promise { await interaction.defer(); // create menu for roels From 55e13675773f635cbbc8d8e3ee00b0c82c710547 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 10:42:37 +0530 Subject: [PATCH 071/106] updated deprecated events --- README.md | 6 +++--- examples/button/Main.ts | 2 +- examples/event/discords/AppDiscord.ts | 4 ++-- examples/guards/Main.ts | 2 +- examples/guards/discords/AppDiscord.ts | 4 ++-- examples/guards/guards/Say.ts | 2 +- examples/menu/Main.ts | 2 +- examples/multiple-discord-instances/Main.ts | 2 +- examples/slash/Main.ts | 2 +- tests/create-on-events.test.ts | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d45180ed..4ff76813 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ import { Discord, On, Once } from "@typeit/discord"; @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") private onMessage() { // ... } @@ -96,12 +96,12 @@ import { Prefix } from "./Prefix"; @Discord() abstract class AppDiscord { - @On("message") + @On("messageCreate") @Guard( NotBot, // You can use multiple guard functions, they are excuted in the same order! Prefix("!") ) - async onMessage([message]: ArgsOf<"message">) { + async onMessage([message]: ArgsOf<"messageCreate">) { switch (message.content.toLowerCase()) { case "hello": message.reply("Hello!"); diff --git a/examples/button/Main.ts b/examples/button/Main.ts index 14c6cdc1..d4cae955 100644 --- a/examples/button/Main.ts +++ b/examples/button/Main.ts @@ -31,7 +31,7 @@ export class Main { console.log("Bot started"); }); - this._client.on("interaction", (interaction) => { + this._client.on("interactionCreate", (interaction) => { this._client.executeInteraction(interaction); }); } diff --git a/examples/event/discords/AppDiscord.ts b/examples/event/discords/AppDiscord.ts index 5103bfa1..131c4485 100644 --- a/examples/event/discords/AppDiscord.ts +++ b/examples/event/discords/AppDiscord.ts @@ -3,8 +3,8 @@ import { Discord, On, Client, ArgsOf } from "../../../src"; @Discord() export abstract class AppDiscord { - @On("message") - onMessage([message]: ArgsOf<"message">, client: Client) { + @On("messageCreate") + onMessage([message]: ArgsOf<"messageCreate">, client: Client) { console.log(message.content); } } diff --git a/examples/guards/Main.ts b/examples/guards/Main.ts index 3ac58246..41fc2845 100644 --- a/examples/guards/Main.ts +++ b/examples/guards/Main.ts @@ -28,7 +28,7 @@ export class Main { await this._client.initSlashes(); }); - this._client.on("interaction", (interaction) => { + this._client.on("interactionCreate", (interaction) => { this._client.executeInteraction(interaction); }); } diff --git a/examples/guards/discords/AppDiscord.ts b/examples/guards/discords/AppDiscord.ts index d8a0dda4..5636e00f 100644 --- a/examples/guards/discords/AppDiscord.ts +++ b/examples/guards/discords/AppDiscord.ts @@ -4,9 +4,9 @@ import { Say } from "../guards/Say"; @Discord() export abstract class AppDiscord { - @On("message") + @On("messageCreate") @Guard(Say("hello")) - onMessage([message]: ArgsOf<"message">, client: Client) { + onMessage([message]: ArgsOf<"messageCreate">, client: Client) { console.log(message.content); } diff --git a/examples/guards/guards/Say.ts b/examples/guards/guards/Say.ts index 032898b1..58f45215 100644 --- a/examples/guards/guards/Say.ts +++ b/examples/guards/guards/Say.ts @@ -2,7 +2,7 @@ import { CommandInteraction } from "discord.js"; import { ArgsOf, GuardFunction } from "../../../src"; export const Say = (text: string) => { - const guard: GuardFunction | CommandInteraction> = async ( + const guard: GuardFunction | CommandInteraction> = async ( messageOrCommand, client, next, diff --git a/examples/menu/Main.ts b/examples/menu/Main.ts index 14c6cdc1..d4cae955 100644 --- a/examples/menu/Main.ts +++ b/examples/menu/Main.ts @@ -31,7 +31,7 @@ export class Main { console.log("Bot started"); }); - this._client.on("interaction", (interaction) => { + this._client.on("interactionCreate", (interaction) => { this._client.executeInteraction(interaction); }); } diff --git a/examples/multiple-discord-instances/Main.ts b/examples/multiple-discord-instances/Main.ts index 3ac58246..41fc2845 100644 --- a/examples/multiple-discord-instances/Main.ts +++ b/examples/multiple-discord-instances/Main.ts @@ -28,7 +28,7 @@ export class Main { await this._client.initSlashes(); }); - this._client.on("interaction", (interaction) => { + this._client.on("interactionCreate", (interaction) => { this._client.executeInteraction(interaction); }); } diff --git a/examples/slash/Main.ts b/examples/slash/Main.ts index 14c6cdc1..d4cae955 100644 --- a/examples/slash/Main.ts +++ b/examples/slash/Main.ts @@ -31,7 +31,7 @@ export class Main { console.log("Bot started"); }); - this._client.on("interaction", (interaction) => { + this._client.on("interactionCreate", (interaction) => { this._client.executeInteraction(interaction); }); } diff --git a/tests/create-on-events.test.ts b/tests/create-on-events.test.ts index 85e0ccc7..906d7bde 100644 --- a/tests/create-on-events.test.ts +++ b/tests/create-on-events.test.ts @@ -25,12 +25,12 @@ const guard2: GuardFunction = async ( @Discord() abstract class Bot { - @On("message") + @On("messageCreate") private onMessage([message]: [string]) { return message; } - @On("message") + @On("messageCreate") private onMessage2([message]: [string]) { return message; } @@ -54,7 +54,7 @@ beforeAll(async () => { describe("Create on event", () => { it("Should create and execute two messages events", async () => { - const res = await client.trigger("message", "test"); + const res = await client.trigger("messageCreate", "test"); expect(res).toEqual(["test", "test"]); }); From 5c88ad9a3df179c8f6cff869f8c13a26ed93dbaf Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 10:45:02 +0530 Subject: [PATCH 072/106] added unknown interaction warning --- src/Client.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index ca76f1a0..0d524c58 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -536,11 +536,13 @@ export class Client extends ClientJS { const tree = this.getInteractionGroupTree(interaction); const slash = this.getSlashFromTree(tree); - if ( - !slash || - (slash.botIds.length > 0 && !slash.botIds.includes(this.botId)) - ) - return; + if (!slash) { + return console.log( + `interaction not found, commandName: ${interaction.commandName}` + ); + } + + if (slash.botIds.length > 0 && !slash.botIds.includes(this.botId)) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); From 42652d2f7bbc40eeb7fe5fa33b6f0d3daf29c24d Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 11:21:18 +0530 Subject: [PATCH 073/106] removed unwanted filter --- src/logic/metadatas/MetadataStorage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 1652505a..80261e59 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -141,7 +141,7 @@ export class MetadataStorage { async build() { // Link the events with @Discord class instances - this.discordMembers.filter((member) => { + this.discordMembers.forEach((member) => { // Find the linked @Discord of an event const discord = this._discords.find((instance) => { return instance.from === member.from; From 61ecc3a481dc8f808013be4f22e0b7614b2fc677 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 12:59:55 +0530 Subject: [PATCH 074/106] gourp permission fix --- src/logic/metadatas/MetadataStorage.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 80261e59..cfa783ce 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -227,6 +227,8 @@ export class MetadataStorage { ]; slashParent.botIds = [...slashParent.discord.botIds]; slashParent.permissions = slashParent.discord.permissions; + slashParent.defaultPermission = + !slashParent.discord.permissions.length ?? false; groupedSlashes.set(group.name, slashParent); From 445b82ed9e68be790a468aadad1202b293b2010f Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 13:34:52 +0530 Subject: [PATCH 075/106] update: permission decorator --- src/Client.ts | 4 ++-- src/decorators/classes/DDiscord.ts | 4 ++-- src/decorators/classes/DSlash.ts | 13 ++----------- src/decorators/decorators/Permission.ts | 17 +++++++---------- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 0d524c58..b5122c28 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -299,7 +299,7 @@ export class Client extends ClientJS { ...added.map((s) => guild.commands.create(s.toObject()).then((cmd) => { if (s.permissions.length > 0) { - cmd.permissions.set({ permissions: s.getPermissions() }); + cmd.permissions.set({ permissions: s.permissions }); } return cmd; }) @@ -307,7 +307,7 @@ export class Client extends ClientJS { ...updated.map((s) => s[0].edit(s[1].toObject()).then((cmd) => { if (s[1].permissions.length > 0) { - cmd.permissions.set({ permissions: s[1].getPermissions() }); + cmd.permissions.set({ permissions: s[1].permissions }); } return cmd; }) diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index f2938daa..d8032243 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -1,8 +1,8 @@ import { Decorator } from "./Decorator"; import { DGuard, DSlash, DIService, DOn } from "../.."; -import { PermissionType } from "../../types"; import { DButton } from "./DButton"; import { DSelectMenu } from "./DSelectMenu"; +import { ApplicationCommandPermissionData } from "discord.js"; export class DDiscord extends Decorator { private _guards: DGuard[] = []; @@ -13,7 +13,7 @@ export class DDiscord extends Decorator { private _description!: string; private _name!: string; private _defaultPermission = true; - private _permissions: { id: string; type: PermissionType }[] = []; + private _permissions: ApplicationCommandPermissionData[] = []; private _guilds: string[] = []; private _botIds: string[] = []; diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index a7ccb5d7..c8a2adaa 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -3,9 +3,8 @@ import { ApplicationCommandPermissionData, CommandInteraction, CommandInteractionOption, - Snowflake, } from "discord.js"; -import { DOption, Client, PermissionType } from "../.."; +import { DOption, Client } from "../.."; import { Method } from "./Method"; export class DSlash extends Method { @@ -13,7 +12,7 @@ export class DSlash extends Method { private _name!: string; private _defaultPermission = true; private _options: DOption[] = []; - private _permissions: { id: string; type: PermissionType }[] = []; + private _permissions: ApplicationCommandPermissionData[] = []; private _guilds!: string[]; private _group!: string; private _subgroup!: string; @@ -128,14 +127,6 @@ export class DSlash extends Method { }; } - getPermissions(): ApplicationCommandPermissionData[] { - return this.permissions.map((permission) => ({ - permission: true, - id: permission.id as Snowflake, - type: permission.type, - })); - } - getLastNestedOption( options: Map ): CommandInteractionOption[] { diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index 2b5518fa..076e675c 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -1,25 +1,22 @@ -import { MetadataStorage, Modifier, PermissionType } from "../.."; +import { ApplicationCommandPermissionData } from "discord.js"; +import { MetadataStorage, Modifier } from "../.."; import { DDiscord } from "../classes/DDiscord"; import { DSlash } from "../classes/DSlash"; -export function Permission(id: string, type: PermissionType); -export function Permission(id: string, type: PermissionType) { - const permission = { - id, - type, - }; - +export function Permission(permission: ApplicationCommandPermissionData); +export function Permission(...permission: ApplicationCommandPermissionData[]); +export function Permission(...permission: ApplicationCommandPermissionData[]) { return (target: Object, key: string, descriptor: PropertyDescriptor) => { MetadataStorage.instance.addModifier( Modifier.create( (original) => { original.defaultPermission = false; - original.permissions = [...original.permissions, permission]; + original.permissions = [...original.permissions, ...permission]; if (original instanceof DDiscord) { original.slashes.forEach((slash) => { slash.defaultPermission = false; - slash.permissions = [...slash.permissions, permission]; + slash.permissions = [...slash.permissions, ...permission]; }); } }, From c283fbb099152bbabf07b1ed98bf6377ad849f50 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 14:01:19 +0530 Subject: [PATCH 076/106] developer can set default permission for slash this will help them constime commands --- src/decorators/classes/DSlash.ts | 4 ++-- src/decorators/decorators/Permission.ts | 2 -- src/logic/metadatas/MetadataStorage.ts | 4 +++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index c8a2adaa..3b96899f 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -88,7 +88,7 @@ export class DSlash extends Method { static create( name: string, description?: string, - defaultPermission = true, + defaultPermission?: boolean, guilds?: string[], botIds?: string[] ) { @@ -96,7 +96,7 @@ export class DSlash extends Method { slash.name = name.toLowerCase(); slash.description = description || slash.name; - slash.defaultPermission = defaultPermission; + slash.defaultPermission = defaultPermission ?? true; slash.guilds = guilds || Client.slashGuilds; slash.botIds = botIds || []; diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index 076e675c..6e04eed2 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -10,12 +10,10 @@ export function Permission(...permission: ApplicationCommandPermissionData[]) { MetadataStorage.instance.addModifier( Modifier.create( (original) => { - original.defaultPermission = false; original.permissions = [...original.permissions, ...permission]; if (original instanceof DDiscord) { original.slashes.forEach((slash) => { - slash.defaultPermission = false; slash.permissions = [...slash.permissions, ...permission]; }); } diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index cfa783ce..f8257251 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -228,7 +228,9 @@ export class MetadataStorage { slashParent.botIds = [...slashParent.discord.botIds]; slashParent.permissions = slashParent.discord.permissions; slashParent.defaultPermission = - !slashParent.discord.permissions.length ?? false; + slashParent.defaultPermission ?? + !slashParent.discord.permissions.length ?? + false; groupedSlashes.set(group.name, slashParent); From 5c39108efe1f3dd637c504d5a3636168fb200748 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 14:10:37 +0530 Subject: [PATCH 077/106] removed unwanted greater than condition --- src/Client.ts | 22 +++++++++++----------- src/logic/metadatas/MetadataStorage.ts | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index b5122c28..60c15313 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -151,7 +151,7 @@ export class Client extends ClientJS { * @param loadClasses A list of glob path or classes */ async login(token: string, ...loadClasses: LoadClass[]) { - if (loadClasses.length > 0) { + if (loadClasses.length) { this._loadClasses = loadClasses; } @@ -159,7 +159,7 @@ export class Client extends ClientJS { if (!this.silent) { console.log("Events"); - if (this.events.length > 0) { + if (this.events.length) { this.events.map((event) => { const eventName = event.event; console.log(` ${eventName} (${event.classRef.name}.${event.key})`); @@ -171,7 +171,7 @@ export class Client extends ClientJS { console.log(""); console.log("Slashes"); - if (this.slashes.length > 0) { + if (this.slashes.length) { this.slashes.map((slash) => { console.log(` ${slash.name} (${slash.classRef.name}.${slash.key})`); const printOptions = (options: DOption[], depth: number) => { @@ -298,7 +298,7 @@ export class Client extends ClientJS { await Promise.all([ ...added.map((s) => guild.commands.create(s.toObject()).then((cmd) => { - if (s.permissions.length > 0) { + if (s.permissions.length) { cmd.permissions.set({ permissions: s.permissions }); } return cmd; @@ -306,7 +306,7 @@ export class Client extends ClientJS { ), ...updated.map((s) => s[0].edit(s[1].toObject()).then((cmd) => { - if (s[1].permissions.length > 0) { + if (s[1].permissions.length) { cmd.permissions.set({ permissions: s[1].permissions }); } return cmd; @@ -386,7 +386,7 @@ export class Client extends ClientJS { * @param guilds The guild IDs (empty -> globaly) */ async clearSlashes(...guilds: string[]) { - if (guilds.length > 0) { + if (guilds.length) { await Promise.all( guilds.map(async (guild) => { // Select and delete the commands of each guild @@ -502,9 +502,9 @@ export class Client extends ClientJS { const button = this.buttons.find((s) => s.id === interaction.customID); if ( !button || - (button.guilds.length > 0 && + (button.guilds.length && !button.guilds.includes(interaction.guild?.id as string)) || - (button.botIds.length > 0 && !button.botIds.includes(this.botId)) + (button.botIds.length && !button.botIds.includes(this.botId)) ) return console.log( `button interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` @@ -518,9 +518,9 @@ export class Client extends ClientJS { const menu = this.selectMenus.find((s) => s.id === interaction.customID); if ( !menu || - (menu.guilds.length > 0 && + (menu.guilds.length && !menu.guilds.includes(interaction.guild?.id as string)) || - (menu.botIds.length > 0 && !menu.botIds.includes(this.botId)) + (menu.botIds.length && !menu.botIds.includes(this.botId)) ) return console.log( `selectMenu interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` @@ -542,7 +542,7 @@ export class Client extends ClientJS { ); } - if (slash.botIds.length > 0 && !slash.botIds.includes(this.botId)) return; + if (slash.botIds.length && !slash.botIds.includes(this.botId)) return; // Parse the options values and inject it into the @Slash method return slash.execute(interaction, this); diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index f8257251..0e33a7de 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -329,7 +329,7 @@ export class MetadataStorage { return async (...params: ArgsOf) => { for (const on of eventsToExecute) { - if (on.botIds.length > 0 && !on.botIds.includes(client.botId)) return; + if (on.botIds.length && !on.botIds.includes(client.botId)) return; const res = await on.execute(params, client); responses.push(res); } From a105dc51266ab76bb29a0fb062e614c453c1bc3b Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 14:57:56 +0530 Subject: [PATCH 078/106] * new decorator @DefaultPermission --- .../decorators/DefaultPermission.ts | 25 +++++++++++++++++++ src/decorators/index.ts | 1 + src/logic/metadatas/MetadataStorage.ts | 10 ++++---- 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/decorators/decorators/DefaultPermission.ts diff --git a/src/decorators/decorators/DefaultPermission.ts b/src/decorators/decorators/DefaultPermission.ts new file mode 100644 index 00000000..8b582794 --- /dev/null +++ b/src/decorators/decorators/DefaultPermission.ts @@ -0,0 +1,25 @@ +import { MetadataStorage, Modifier } from "../.."; +import { DDiscord } from "../classes/DDiscord"; +import { DSlash } from "../classes/DSlash"; + +export function DefaultPermission(); +export function DefaultPermission(permission: boolean); +export function DefaultPermission(permission?: boolean) { + return (target: Object, key: string, descriptor: PropertyDescriptor) => { + MetadataStorage.instance.addModifier( + Modifier.create( + (original) => { + original.defaultPermission = permission ?? true; + + if (original instanceof DDiscord) { + original.slashes.forEach((slash) => { + slash.defaultPermission = permission ?? true; + }); + } + }, + DSlash, + DDiscord + ).decorateUnknown(target, key, descriptor) + ); + }; +} diff --git a/src/decorators/index.ts b/src/decorators/index.ts index c7ddb6b8..4683c42b 100644 --- a/src/decorators/index.ts +++ b/src/decorators/index.ts @@ -8,6 +8,7 @@ export * from "./decorators/Slash"; export * from "./decorators/Option"; export * from "./decorators/Choice"; export * from "./decorators/Choices"; +export * from "./decorators/DefaultPermission"; export * from "./decorators/Permission"; export * from "./decorators/Group"; export * from "./decorators/Guild"; diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 0e33a7de..03784de2 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -226,11 +226,11 @@ export class MetadataStorage { ...slashParent.discord.guilds, ]; slashParent.botIds = [...slashParent.discord.botIds]; - slashParent.permissions = slashParent.discord.permissions; - slashParent.defaultPermission = - slashParent.defaultPermission ?? - !slashParent.discord.permissions.length ?? - false; + slashParent.permissions = [ + ...slashParent.permissions, + ...slashParent.discord.permissions, + ]; + slashParent.defaultPermission = slashParent.discord.defaultPermission; groupedSlashes.set(group.name, slashParent); From a195d2c8ec42673d396a02c2b46b92952be0eba9 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 15:16:07 +0530 Subject: [PATCH 079/106] doc for @DefaultPermission --- docs/src/.vuepress/config.js | 1 + docs/src/decorators/defaultpermission.md | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 docs/src/decorators/defaultpermission.md diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js index 5183b5ff..b3704cc5 100755 --- a/docs/src/.vuepress/config.js +++ b/docs/src/.vuepress/config.js @@ -80,6 +80,7 @@ module.exports = { ["/decorators/on", "@On"], ["/decorators/once", "@Once"], ["/decorators/option", "@Option"], + ["/decorators/defaultpermission", "@DefaultPermission"], ["/decorators/permission", "@Permission"], ["/decorators/selectmenu", "@SelectMenu"], ["/decorators/slash", "@Slash"], diff --git a/docs/src/decorators/defaultpermission.md b/docs/src/decorators/defaultpermission.md new file mode 100644 index 00000000..ffc1262a --- /dev/null +++ b/docs/src/decorators/defaultpermission.md @@ -0,0 +1,5 @@ +# @DefaultPermission + +::: danger +doc for `@DefaultPermission` is not ready +::: \ No newline at end of file From 65af9b4610277835b9f542dd8a8d9adc063dd966 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 15:24:54 +0530 Subject: [PATCH 080/106] init slash > guild > replace for loop with foreach --- src/Client.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 60c15313..71e6a337 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -231,15 +231,9 @@ export class Client extends ClientJS { } // update guild commands - for (const gc of guildSlashStorage) { - const guild = await this.guilds.fetch({ guild: gc[0] as Snowflake }); - if (!guild) { - console.log("guild not found"); - continue; - } - - // commands for guild - const slashes = gc[1]; + guildSlashStorage.forEach(async (slashes, key) => { + const guild = await this.guilds.fetch({ guild: key as Snowflake }); + if (!guild) return console.log("guild not found"); // fetch already registered command const existing = await guild.commands.fetch(); @@ -314,7 +308,7 @@ export class Client extends ClientJS { ), ...deleted.map((key) => guild.commands.delete(key)), ]); - } + }); // # init global commands const existing = (await this.fetchSlash())?.filter((s) => !s.guild); From 85b28a4112cb367427facf1d4dedf6f2996553d6 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 15:27:19 +0530 Subject: [PATCH 081/106] init slash > guild > replaced for loop --- src/Client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 71e6a337..a0258c37 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -221,14 +221,14 @@ export class Client extends ClientJS { const guildsSlash = this.slashes.filter((s) => s.guilds?.length); // group single guild slash together - for (const s of guildsSlash) { + guildsSlash.forEach((s) => { s.guilds.forEach((guild) => guildSlashStorage.set(guild, [ ...(guildSlashStorage.get(guild) ?? []), s, ]) ); - } + }); // update guild commands guildSlashStorage.forEach(async (slashes, key) => { From 1824aca49b8fe3df8fd898cc9f9480aeb6f0ed56 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 19:16:27 +0530 Subject: [PATCH 082/106] @Bot fix for @On --- src/decorators/decorators/Bot.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 05996d72..42947f8e 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -1,6 +1,7 @@ import { MetadataStorage, Modifier } from "../.."; import { DButton } from "../classes/DButton"; import { DDiscord } from "../classes/DDiscord"; +import { DOn } from "../classes/DOn"; import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; @@ -13,7 +14,7 @@ export function Bot(...botIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( (original) => { original.botIds = [ ...original.botIds, @@ -32,7 +33,8 @@ export function Bot(...botIDs: string[]) { DSlash, DDiscord, DButton, - DSelectMenu + DSelectMenu, + DOn ).decorateUnknown(target, key, descriptor) ); }; From 947a0ef6f500d20c70aa2309d4559dfe876d6493 Mon Sep 17 00:00:00 2001 From: iorp Date: Sun, 4 Jul 2021 19:52:29 +0530 Subject: [PATCH 083/106] botid fix for events --- src/logic/metadatas/MetadataStorage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 03784de2..8420e651 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -329,7 +329,8 @@ export class MetadataStorage { return async (...params: ArgsOf) => { for (const on of eventsToExecute) { - if (on.botIds.length && !on.botIds.includes(client.botId)) return; + const botIDs = [...on.botIds, ...on.discord.botIds]; + if (botIDs.length && !botIDs.includes(client.botId)) return; const res = await on.execute(params, client); responses.push(res); } From 3a787fd8967a8f27d42dd310323cdabd81430b11 Mon Sep 17 00:00:00 2001 From: iorp Date: Mon, 5 Jul 2021 17:25:25 +0530 Subject: [PATCH 084/106] comment update for initslash --- src/Client.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index a0258c37..27befd01 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -216,11 +216,11 @@ export class Client extends ClientJS { async initSlashes(options?: { log: { forGuild: boolean; forGlobal: boolean }; }) { - // # first init guild's all slash + // # group guild slashes by guildId const guildSlashStorage = new Map(); const guildsSlash = this.slashes.filter((s) => s.guilds?.length); - // group single guild slash together + // group single guild slashes together guildsSlash.forEach((s) => { s.guilds.forEach((guild) => guildSlashStorage.set(guild, [ @@ -230,7 +230,7 @@ export class Client extends ClientJS { ); }); - // update guild commands + // run task to add/update/delete slashes for guilds guildSlashStorage.forEach(async (slashes, key) => { const guild = await this.guilds.fetch({ guild: key as Snowflake }); if (!guild) return console.log("guild not found"); @@ -245,7 +245,7 @@ export class Client extends ClientJS { (!s.botIds.length || s.botIds.includes(this.botId)) ); - // filter commands to update + // filter slashes to update const updated = slashes .map<[ApplicationCommand | undefined, DSlash]>((s) => [ existing.find( @@ -259,7 +259,7 @@ export class Client extends ClientJS { (s): s is [ApplicationCommand, DSlash] => s[0] !== undefined ); - // filter commands to delete + // filter slashes to delete const deleted = existing.filter( (s) => !this.slashes.find( @@ -271,7 +271,8 @@ export class Client extends ClientJS { ) ); - if (options?.log.forGuild) { + // log the changes to slashes in console if enabled by options or silent mode is turned off + if (options?.log.forGuild || !this.silent) { console.log( `${this.user?.username} >> guild: #${guild} >> command >> adding ${ added.length @@ -290,6 +291,7 @@ export class Client extends ClientJS { } await Promise.all([ + // add and set permissions ...added.map((s) => guild.commands.create(s.toObject()).then((cmd) => { if (s.permissions.length) { @@ -298,6 +300,8 @@ export class Client extends ClientJS { return cmd; }) ), + + // update and set permissions ...updated.map((s) => s[0].edit(s[1].toObject()).then((cmd) => { if (s[1].permissions.length) { @@ -306,11 +310,13 @@ export class Client extends ClientJS { return cmd; }) ), + + // delete ...deleted.map((key) => guild.commands.delete(key)), ]); }); - // # init global commands + // # initialize add/update/delete task for global slashes const existing = (await this.fetchSlash())?.filter((s) => !s.guild); const slashes = this.slashes.filter((s) => !s.guilds?.length); if (existing) { @@ -331,7 +337,8 @@ export class Client extends ClientJS { slashes.every((s) => s.name !== c.name) ); - if (options?.log.forGlobal) { + // log the changes to slashes in console if enabled by options or silent mode is turned off + if (options?.log.forGlobal || !this.silent) { console.log( `${this.user?.username} >> global >> command >> adding ${ added.length @@ -352,8 +359,11 @@ export class Client extends ClientJS { // if (slash.permissions.length <= 0) return; await Promise.all([ + // add ...added.map((s) => this.application?.commands.create(s.toObject())), + // update ...updated.map((s) => s[0].edit(s[1].toObject())), + // delete ...deleted.map((key) => this.application?.commands.delete(key)), ]); } From a06d22298b0f58951c960b5179924cbabe7aa38c Mon Sep 17 00:00:00 2001 From: iorp Date: Mon, 5 Jul 2021 19:11:21 +0530 Subject: [PATCH 085/106] solution for multiple class import under multiple Clients --- src/Client.ts | 3 +- src/logic/metadatas/MetadataStorage.ts | 101 ++++++++++++++----------- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 27befd01..0a99bc36 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -26,6 +26,7 @@ export class Client extends ClientJS { private static _requiredByDefault = false; private static _slashGuilds: string[] = []; private static _guards: GuardFunction[] = []; + private _metadataStorage = new MetadataStorage(); static get slashGuilds() { return Client._slashGuilds; @@ -120,7 +121,7 @@ export class Client extends ClientJS { return MetadataStorage.instance; } get decorators() { - return MetadataStorage.instance; + return this._metadataStorage; } get silent() { diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 8420e651..f6177cb7 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -16,15 +16,15 @@ import { DSelectMenu } from "../../decorators/classes/DSelectMenu"; export class MetadataStorage { private static _instance: MetadataStorage; - private _events: DOn[] = []; - private _guards: DGuard[] = []; - private _slashes: DSlash[] = []; - private _allSlashes: DSlash[] = []; - private _buttons: DButton[] = []; - private _selectMenu: DSelectMenu[] = []; - private _options: DOption[] = []; - private _discords: DDiscord[] = []; - private _modifiers: Modifier[] = []; + private static _events: DOn[] = []; + private static _guards: DGuard[] = []; + private static _slashes: DSlash[] = []; + private static _allSlashes: DSlash[] = []; + private static _buttons: DButton[] = []; + private static _selectMenu: DSelectMenu[] = []; + private static _options: DOption[] = []; + private static _discords: DDiscord[] = []; + private static _modifiers: Modifier[] = []; private _groups: DGroup[] = []; private _subGroups: DGroup[] = []; @@ -41,7 +41,7 @@ export class MetadataStorage { } get events() { - return this._events as readonly DOn[]; + return MetadataStorage._events as readonly DOn[]; } /** @@ -61,23 +61,23 @@ export class MetadataStorage { } get discords() { - return this._discords as readonly DDiscord[]; + return MetadataStorage._discords as readonly DDiscord[]; } get slashes() { - return this._slashes as readonly DSlash[]; + return MetadataStorage._slashes as readonly DSlash[]; } get buttons() { - return this._buttons as readonly DButton[]; + return MetadataStorage._buttons as readonly DButton[]; } get selectMenus() { - return this._selectMenu as readonly DSelectMenu[]; + return MetadataStorage._selectMenu as readonly DSelectMenu[]; } get allSlashes() { - return this._allSlashes as readonly DSlash[]; + return MetadataStorage._allSlashes as readonly DSlash[]; } get groups() { @@ -90,35 +90,35 @@ export class MetadataStorage { private get discordMembers(): readonly Method[] { return [ - ...this._slashes, - ...this._events, - ...this._buttons, - ...this._selectMenu, + ...MetadataStorage._slashes, + ...MetadataStorage._events, + ...MetadataStorage._buttons, + ...MetadataStorage._selectMenu, ]; } addModifier(modifier: Modifier) { - this._modifiers.push(modifier); + MetadataStorage._modifiers.push(modifier); } addOn(on: DOn) { - this._events.push(on); + MetadataStorage._events.push(on); } addSlash(slash: DSlash) { - this._slashes.push(slash); + MetadataStorage._slashes.push(slash); } addButton(button: DButton) { - this._buttons.push(button); + MetadataStorage._buttons.push(button); } addSelectMenu(selectMenu: DSelectMenu) { - this._selectMenu.push(selectMenu); + MetadataStorage._selectMenu.push(selectMenu); } addOption(option: DOption) { - this._options.push(option); + MetadataStorage._options.push(option); } addGroup(group: DGroup) { @@ -130,12 +130,12 @@ export class MetadataStorage { } addGuard(guard: DGuard) { - this._guards.push(guard); + MetadataStorage._guards.push(guard); DIService.instance.addService(guard.classRef); } addDiscord(discord: DDiscord) { - this._discords.push(discord); + MetadataStorage._discords.push(discord); DIService.instance.addService(discord.classRef); } @@ -143,7 +143,7 @@ export class MetadataStorage { // Link the events with @Discord class instances this.discordMembers.forEach((member) => { // Find the linked @Discord of an event - const discord = this._discords.find((instance) => { + const discord = MetadataStorage._discords.find((instance) => { return instance.from === member.from; }); @@ -170,20 +170,35 @@ export class MetadataStorage { } }); - await Modifier.applyFromModifierListToList(this._modifiers, this._discords); - await Modifier.applyFromModifierListToList(this._modifiers, this._events); - await Modifier.applyFromModifierListToList(this._modifiers, this._slashes); - await Modifier.applyFromModifierListToList(this._modifiers, this._buttons); - await Modifier.applyFromModifierListToList(this._modifiers, this._options); await Modifier.applyFromModifierListToList( - this._modifiers, - this._selectMenu + MetadataStorage._modifiers, + MetadataStorage._discords + ); + await Modifier.applyFromModifierListToList( + MetadataStorage._modifiers, + MetadataStorage._events + ); + await Modifier.applyFromModifierListToList( + MetadataStorage._modifiers, + MetadataStorage._slashes + ); + await Modifier.applyFromModifierListToList( + MetadataStorage._modifiers, + MetadataStorage._buttons + ); + await Modifier.applyFromModifierListToList( + MetadataStorage._modifiers, + MetadataStorage._options + ); + await Modifier.applyFromModifierListToList( + MetadataStorage._modifiers, + MetadataStorage._selectMenu ); // Set the class level "group" property of all @Slash // Cannot achieve it using modifiers this._groups.forEach((group) => { - this._slashes.forEach((slash) => { + MetadataStorage._slashes.forEach((slash) => { if (group.from !== slash.from) { return; } @@ -192,8 +207,8 @@ export class MetadataStorage { }); }); - this._allSlashes = this._slashes; - this._slashes = this.groupSlashes(); + MetadataStorage._allSlashes = MetadataStorage._slashes; + MetadataStorage._slashes = this.groupSlashes(); } private groupSlashes() { @@ -213,7 +228,7 @@ export class MetadataStorage { group.infos?.description ).decorate(group.classRef, group.key, group.method); - const discord = this._discords.find((instance) => { + const discord = MetadataStorage._discords.find((instance) => { return instance.from === slashParent.from; }); @@ -234,7 +249,7 @@ export class MetadataStorage { groupedSlashes.set(group.name, slashParent); - const slashes = this._slashes.filter((slash) => { + const slashes = MetadataStorage._slashes.filter((slash) => { return slash.group === slashParent.name && !slash.subgroup; }); @@ -265,7 +280,7 @@ export class MetadataStorage { ).decorate(subGroup.classRef, subGroup.key, subGroup.method); // Get the slashes that are in this subgroup - const slashes = this._slashes.filter((slash) => { + const slashes = MetadataStorage._slashes.filter((slash) => { return slash.subgroup === option.name; }); @@ -305,7 +320,7 @@ export class MetadataStorage { }); return [ - ...this._slashes.filter((s) => !s.group && !s.subgroup), + ...MetadataStorage._slashes.filter((s) => !s.group && !s.subgroup), ...Array.from(groupedSlashes.values()), ]; } @@ -323,7 +338,7 @@ export class MetadataStorage { ): (...params: ArgsOf) => Promise { const responses: any[] = []; - const eventsToExecute = this._events.filter((on) => { + const eventsToExecute = MetadataStorage._events.filter((on) => { return on.event === event && on.once === once; }); From d83763944b3e4393addcb30456cb295cf58e524f Mon Sep 17 00:00:00 2001 From: iorp Date: Mon, 5 Jul 2021 19:36:06 +0530 Subject: [PATCH 086/106] revert back last commit --- src/Client.ts | 3 +- src/logic/metadatas/MetadataStorage.ts | 101 +++++++++++-------------- 2 files changed, 44 insertions(+), 60 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 0a99bc36..27befd01 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -26,7 +26,6 @@ export class Client extends ClientJS { private static _requiredByDefault = false; private static _slashGuilds: string[] = []; private static _guards: GuardFunction[] = []; - private _metadataStorage = new MetadataStorage(); static get slashGuilds() { return Client._slashGuilds; @@ -121,7 +120,7 @@ export class Client extends ClientJS { return MetadataStorage.instance; } get decorators() { - return this._metadataStorage; + return MetadataStorage.instance; } get silent() { diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index f6177cb7..8420e651 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -16,15 +16,15 @@ import { DSelectMenu } from "../../decorators/classes/DSelectMenu"; export class MetadataStorage { private static _instance: MetadataStorage; - private static _events: DOn[] = []; - private static _guards: DGuard[] = []; - private static _slashes: DSlash[] = []; - private static _allSlashes: DSlash[] = []; - private static _buttons: DButton[] = []; - private static _selectMenu: DSelectMenu[] = []; - private static _options: DOption[] = []; - private static _discords: DDiscord[] = []; - private static _modifiers: Modifier[] = []; + private _events: DOn[] = []; + private _guards: DGuard[] = []; + private _slashes: DSlash[] = []; + private _allSlashes: DSlash[] = []; + private _buttons: DButton[] = []; + private _selectMenu: DSelectMenu[] = []; + private _options: DOption[] = []; + private _discords: DDiscord[] = []; + private _modifiers: Modifier[] = []; private _groups: DGroup[] = []; private _subGroups: DGroup[] = []; @@ -41,7 +41,7 @@ export class MetadataStorage { } get events() { - return MetadataStorage._events as readonly DOn[]; + return this._events as readonly DOn[]; } /** @@ -61,23 +61,23 @@ export class MetadataStorage { } get discords() { - return MetadataStorage._discords as readonly DDiscord[]; + return this._discords as readonly DDiscord[]; } get slashes() { - return MetadataStorage._slashes as readonly DSlash[]; + return this._slashes as readonly DSlash[]; } get buttons() { - return MetadataStorage._buttons as readonly DButton[]; + return this._buttons as readonly DButton[]; } get selectMenus() { - return MetadataStorage._selectMenu as readonly DSelectMenu[]; + return this._selectMenu as readonly DSelectMenu[]; } get allSlashes() { - return MetadataStorage._allSlashes as readonly DSlash[]; + return this._allSlashes as readonly DSlash[]; } get groups() { @@ -90,35 +90,35 @@ export class MetadataStorage { private get discordMembers(): readonly Method[] { return [ - ...MetadataStorage._slashes, - ...MetadataStorage._events, - ...MetadataStorage._buttons, - ...MetadataStorage._selectMenu, + ...this._slashes, + ...this._events, + ...this._buttons, + ...this._selectMenu, ]; } addModifier(modifier: Modifier) { - MetadataStorage._modifiers.push(modifier); + this._modifiers.push(modifier); } addOn(on: DOn) { - MetadataStorage._events.push(on); + this._events.push(on); } addSlash(slash: DSlash) { - MetadataStorage._slashes.push(slash); + this._slashes.push(slash); } addButton(button: DButton) { - MetadataStorage._buttons.push(button); + this._buttons.push(button); } addSelectMenu(selectMenu: DSelectMenu) { - MetadataStorage._selectMenu.push(selectMenu); + this._selectMenu.push(selectMenu); } addOption(option: DOption) { - MetadataStorage._options.push(option); + this._options.push(option); } addGroup(group: DGroup) { @@ -130,12 +130,12 @@ export class MetadataStorage { } addGuard(guard: DGuard) { - MetadataStorage._guards.push(guard); + this._guards.push(guard); DIService.instance.addService(guard.classRef); } addDiscord(discord: DDiscord) { - MetadataStorage._discords.push(discord); + this._discords.push(discord); DIService.instance.addService(discord.classRef); } @@ -143,7 +143,7 @@ export class MetadataStorage { // Link the events with @Discord class instances this.discordMembers.forEach((member) => { // Find the linked @Discord of an event - const discord = MetadataStorage._discords.find((instance) => { + const discord = this._discords.find((instance) => { return instance.from === member.from; }); @@ -170,35 +170,20 @@ export class MetadataStorage { } }); + await Modifier.applyFromModifierListToList(this._modifiers, this._discords); + await Modifier.applyFromModifierListToList(this._modifiers, this._events); + await Modifier.applyFromModifierListToList(this._modifiers, this._slashes); + await Modifier.applyFromModifierListToList(this._modifiers, this._buttons); + await Modifier.applyFromModifierListToList(this._modifiers, this._options); await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._discords - ); - await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._events - ); - await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._slashes - ); - await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._buttons - ); - await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._options - ); - await Modifier.applyFromModifierListToList( - MetadataStorage._modifiers, - MetadataStorage._selectMenu + this._modifiers, + this._selectMenu ); // Set the class level "group" property of all @Slash // Cannot achieve it using modifiers this._groups.forEach((group) => { - MetadataStorage._slashes.forEach((slash) => { + this._slashes.forEach((slash) => { if (group.from !== slash.from) { return; } @@ -207,8 +192,8 @@ export class MetadataStorage { }); }); - MetadataStorage._allSlashes = MetadataStorage._slashes; - MetadataStorage._slashes = this.groupSlashes(); + this._allSlashes = this._slashes; + this._slashes = this.groupSlashes(); } private groupSlashes() { @@ -228,7 +213,7 @@ export class MetadataStorage { group.infos?.description ).decorate(group.classRef, group.key, group.method); - const discord = MetadataStorage._discords.find((instance) => { + const discord = this._discords.find((instance) => { return instance.from === slashParent.from; }); @@ -249,7 +234,7 @@ export class MetadataStorage { groupedSlashes.set(group.name, slashParent); - const slashes = MetadataStorage._slashes.filter((slash) => { + const slashes = this._slashes.filter((slash) => { return slash.group === slashParent.name && !slash.subgroup; }); @@ -280,7 +265,7 @@ export class MetadataStorage { ).decorate(subGroup.classRef, subGroup.key, subGroup.method); // Get the slashes that are in this subgroup - const slashes = MetadataStorage._slashes.filter((slash) => { + const slashes = this._slashes.filter((slash) => { return slash.subgroup === option.name; }); @@ -320,7 +305,7 @@ export class MetadataStorage { }); return [ - ...MetadataStorage._slashes.filter((s) => !s.group && !s.subgroup), + ...this._slashes.filter((s) => !s.group && !s.subgroup), ...Array.from(groupedSlashes.values()), ]; } @@ -338,7 +323,7 @@ export class MetadataStorage { ): (...params: ArgsOf) => Promise { const responses: any[] = []; - const eventsToExecute = MetadataStorage._events.filter((on) => { + const eventsToExecute = this._events.filter((on) => { return on.event === event && on.once === once; }); From 3b7acdabb0d83d144b9e9c33c3116fab8a6afd86 Mon Sep 17 00:00:00 2001 From: iorp Date: Mon, 5 Jul 2021 21:08:51 +0530 Subject: [PATCH 087/106] fix multiple imports under multiple clients --- src/Client.ts | 43 +++++--------------------- src/logic/metadatas/MetadataStorage.ts | 32 +++++++++++++++++++ src/types/core/ClientOptions.ts | 3 +- src/types/core/LoadClass.ts | 1 - src/types/index.ts | 1 - 5 files changed, 40 insertions(+), 40 deletions(-) delete mode 100644 src/types/core/LoadClass.ts diff --git a/src/Client.ts b/src/Client.ts index 27befd01..acc67ced 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -6,10 +6,8 @@ import { Interaction, Snowflake, } from "discord.js"; -import * as Glob from "glob"; import { MetadataStorage, - LoadClass, ClientOptions, DiscordEvents, DOn, @@ -22,7 +20,6 @@ export class Client extends ClientJS { private static isBuilt = false; private _botId: string; private _silent: boolean; - private _loadClasses: LoadClass[] = []; private static _requiredByDefault = false; private static _slashGuilds: string[] = []; private static _guards: GuardFunction[] = []; @@ -132,13 +129,16 @@ export class Client extends ClientJS { /** * Create your bot - * @param options { silent: boolean, loadClasses: LoadClass[] } + * @param options { silent: boolean } */ constructor(options: ClientOptions) { super(options); + MetadataStorage.classes = [ + ...MetadataStorage.classes, + ...(options?.classes || []), + ]; this._silent = !!options?.silent; - this._loadClasses = options?.classes || []; this.guards = options.guards || []; this.requiredByDefault = options.requiredByDefault ?? false; this.slashGuilds = options.slashGuilds || []; @@ -150,12 +150,8 @@ export class Client extends ClientJS { * @param token The bot token * @param loadClasses A list of glob path or classes */ - async login(token: string, ...loadClasses: LoadClass[]) { - if (loadClasses.length) { - this._loadClasses = loadClasses; - } - - await this.build(); + async login(token: string) { + await this.decorators.build(); if (!this.silent) { console.log("Events"); @@ -552,16 +548,6 @@ export class Client extends ClientJS { return slash.execute(interaction, this); } - /** - * Manually build the app - */ - async build() { - if (Client.isBuilt) return; - Client.isBuilt = true; - this.loadClasses(); - await this.decorators.build(); - } - /** * Manually trigger an event (used for tests) * @param event The event @@ -571,19 +557,4 @@ export class Client extends ClientJS { trigger(event: DiscordEvents, params?: any, once = false): Promise { return this.decorators.trigger(event, this, once)(params); } - - private loadClasses() { - if (!this._loadClasses) { - return; - } - - this._loadClasses.forEach((file) => { - if (typeof file === "string") { - const files = Glob.sync(file); - files.forEach((file) => { - require(file); - }); - } - }); - } } diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 8420e651..b9af7cd5 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -13,8 +13,11 @@ import { } from "../.."; import { DButton, DGroup } from "../../decorators"; import { DSelectMenu } from "../../decorators/classes/DSelectMenu"; +import * as glob from "glob"; export class MetadataStorage { + private static isBuilt = false; + private static _classesToLoad: string[] = []; private static _instance: MetadataStorage; private _events: DOn[] = []; private _guards: DGuard[] = []; @@ -60,6 +63,14 @@ export class MetadataStorage { }, []) as readonly DOn[]; } + static get classes() { + return this._classesToLoad; + } + + static set classes(files: string[]) { + this._classesToLoad = files; + } + get discords() { return this._discords as readonly DDiscord[]; } @@ -139,7 +150,28 @@ export class MetadataStorage { DIService.instance.addService(discord.classRef); } + private loadClasses() { + // collect all import paths + const imports: string[] = []; + MetadataStorage.classes.forEach((path) => { + const files = glob.sync(path).filter((file) => typeof file === "string"); + files.forEach((file) => { + if (!imports.includes(file)) imports.push(file); + }); + }); + + // import all files + imports.forEach((file) => require(file)); + } + async build() { + // build the instance if not already built + if (MetadataStorage.isBuilt) return; + MetadataStorage.isBuilt = true; + + // load the classes + this.loadClasses(); + // Link the events with @Discord class instances this.discordMembers.forEach((member) => { // Find the linked @Discord of an event diff --git a/src/types/core/ClientOptions.ts b/src/types/core/ClientOptions.ts index 96802b29..c0330848 100644 --- a/src/types/core/ClientOptions.ts +++ b/src/types/core/ClientOptions.ts @@ -1,6 +1,5 @@ import { ClientOptions as DiscordJSClientOptions } from "discord.js"; import { GuardFunction } from "../public/GuardFunction"; -import { LoadClass } from "./LoadClass"; export interface ClientOptions extends DiscordJSClientOptions { /** @@ -16,7 +15,7 @@ export interface ClientOptions extends DiscordJSClientOptions { /** * The classes to load for your discord bot */ - classes?: LoadClass[]; + classes?: string[]; /** * The global guards diff --git a/src/types/core/LoadClass.ts b/src/types/core/LoadClass.ts deleted file mode 100644 index bdf4fb58..00000000 --- a/src/types/core/LoadClass.ts +++ /dev/null @@ -1 +0,0 @@ -export type LoadClass = string | Function; diff --git a/src/types/index.ts b/src/types/index.ts index e01b2037..4a917dc2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,5 +1,4 @@ export * from "./core/DiscordEvents"; -export * from "./core/LoadClass"; export * from "./core/InstanceOf"; export * from "./core/ClientOptions"; export * from "./core/Next"; From a7587f4f73418da9cd31b3aa9589194c2e991326 Mon Sep 17 00:00:00 2001 From: iorp Date: Mon, 5 Jul 2021 23:59:29 +0530 Subject: [PATCH 088/106] removed unused variable --- src/Client.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index acc67ced..f933fa70 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -17,7 +17,6 @@ import { DButton, DDiscord, DOption, DSelectMenu, DSlash } from "./decorators"; import { GuildNotFoundError } from "./errors"; export class Client extends ClientJS { - private static isBuilt = false; private _botId: string; private _silent: boolean; private static _requiredByDefault = false; From d8ab4f9dbe77f3fa3b9f676d54af64186ac93d0f Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 00:05:19 +0530 Subject: [PATCH 089/106] regular update based on discord.js * fixed interaction.customId --- src/Client.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index f933fa70..022577a6 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -498,7 +498,7 @@ export class Client extends ClientJS { // if interaction is a button if (interaction.isButton()) { - const button = this.buttons.find((s) => s.id === interaction.customID); + const button = this.buttons.find((s) => s.id === interaction.customId); if ( !button || (button.guilds.length && @@ -506,7 +506,7 @@ export class Client extends ClientJS { (button.botIds.length && !button.botIds.includes(this.botId)) ) return console.log( - `button interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` + `button interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customId}` ); return button.execute(interaction, this); @@ -514,7 +514,7 @@ export class Client extends ClientJS { // if interaction is a button if (interaction.isSelectMenu()) { - const menu = this.selectMenus.find((s) => s.id === interaction.customID); + const menu = this.selectMenus.find((s) => s.id === interaction.customId); if ( !menu || (menu.guilds.length && @@ -522,7 +522,7 @@ export class Client extends ClientJS { (menu.botIds.length && !menu.botIds.includes(this.botId)) ) return console.log( - `selectMenu interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customID}` + `selectMenu interaction not found, interactionID: ${interaction.id} | customID: ${interaction.customId}` ); return menu.execute(interaction, this); From 60f40087fd1f4396300bb8dd2d643eab9bce1ebe Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 01:08:33 +0530 Subject: [PATCH 090/106] jest slash test fix --- src/Client.ts | 7 +++++++ tests/slash.test.ts | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 022577a6..63d6a8de 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -556,4 +556,11 @@ export class Client extends ClientJS { trigger(event: DiscordEvents, params?: any, once = false): Promise { return this.decorators.trigger(event, this, once)(params); } + + /** + * Manually build the app + */ + async build() { + await this.decorators.build(); + } } diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 32db380f..3ed5e6bf 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -100,7 +100,7 @@ export abstract class AppDiscord { }) export abstract class AppDiscord1 { @Slash("hello") - @Permission("123", "USER") + @Permission({ id: "123", type: "USER", permission: true }) add( @Option("text", { required: false }) text: string, @@ -199,6 +199,7 @@ describe("Slash", () => { { id: "123", type: "USER", + permission: true, }, ]); @@ -217,7 +218,7 @@ describe("Slash", () => { options: [], }, ], - defaultPermission: false, + defaultPermission: true, }, { name: "inferance", From f30173920388e4d80151a5cfbfd5362b593d18a1 Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 19:12:23 +0530 Subject: [PATCH 091/106] simple command support --- docs/src/general/client.md | 22 ++-- src/Client.ts | 114 +++++++++++++++- src/decorators/classes/DCommand.ts | 123 ++++++++++++++++++ src/decorators/classes/DCommandOption.ts | 46 +++++++ src/decorators/classes/DDiscord.ts | 9 ++ src/decorators/classes/DSlash.ts | 2 +- src/decorators/decorators/Bot.ts | 20 ++- src/decorators/decorators/Command.ts | 28 ++++ src/decorators/decorators/CommandOption.ts | 43 ++++++ .../decorators/DefaultPermission.ts | 2 + src/decorators/decorators/Description.ts | 11 +- src/decorators/decorators/Guard.ts | 2 + src/decorators/decorators/Guild.ts | 11 +- src/decorators/decorators/Name.ts | 4 +- src/decorators/decorators/Permission.ts | 4 +- src/decorators/index.ts | 2 + src/decorators/params/CommandParams.ts | 8 ++ src/logic/metadatas/MetadataStorage.ts | 24 +++- src/types/core/ClientOptions.ts | 9 +- src/types/index.ts | 1 + src/types/public/CommandMessage.ts | 6 + 21 files changed, 465 insertions(+), 26 deletions(-) create mode 100644 src/decorators/classes/DCommand.ts create mode 100644 src/decorators/classes/DCommandOption.ts create mode 100644 src/decorators/decorators/Command.ts create mode 100644 src/decorators/decorators/CommandOption.ts create mode 100644 src/decorators/params/CommandParams.ts create mode 100644 src/types/public/CommandMessage.ts diff --git a/docs/src/general/client.md b/docs/src/general/client.md index 3b879fa1..cba7edac 100644 --- a/docs/src/general/client.md +++ b/docs/src/general/client.md @@ -5,20 +5,24 @@ It manage all the operations between your app, Discord's API and discord.js In order to start your application, you must use the discord.**ts**'s Client (not the client that is provided by discord.**js**!). It works the same as the discord.**js**'s Client (same methods, properties, ...). -- **`botId` (required)** - `string` - a bot id, help you manage your bot interactions, events (this is important in case there are more than one bot running in single instance) - - **`intents` (required)** - `Intents[]` + `Intents[]` [see Intents](#intents) -- **`classes`** - `string[]` +- **`botId`** + `string` (`bot` by default) + a bot id, help you manage your bot interactions, events (this is important in case there are more than one bot running in single instance) + +- **`prefix`** + `string | ((message: Message) => Promise)` (`!` by default) + simple commands use use this prefix by default, use function to fetch different prefix for different guilds + +- **`classes`** + `string[]` Indicate the class jacket of your classes containing the `@Discord` decorator. It accepts a list of classes or of (glob) paths -- **`silent`** - `boolean` (`false` by default) +- **`silent`** + `boolean` (`true` by default) Allows you to disable your event information at startup - **`requiredByDefault`** diff --git a/src/Client.ts b/src/Client.ts index 63d6a8de..1f441580 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -4,6 +4,7 @@ import { CommandInteraction, CommandInteractionOption, Interaction, + Message, Snowflake, } from "discord.js"; import { @@ -14,10 +15,13 @@ import { GuardFunction, } from "."; import { DButton, DDiscord, DOption, DSelectMenu, DSlash } from "./decorators"; +import { DCommand } from "./decorators/classes/DCommand"; import { GuildNotFoundError } from "./errors"; +import { CommandMessage } from "./types/public/CommandMessage"; export class Client extends ClientJS { private _botId: string; + private _prefix: string | ((message: Message) => Promise); private _silent: boolean; private static _requiredByDefault = false; private static _slashGuilds: string[] = []; @@ -30,6 +34,13 @@ export class Client extends ClientJS { Client._slashGuilds = value; } + get prefix() { + return this._prefix; + } + set prefix(value) { + this._prefix = value; + } + get botId() { return this._botId; } @@ -77,6 +88,13 @@ export class Client extends ClientJS { return Client.slashes; } + static get commands() { + return MetadataStorage.instance.commands as readonly DCommand[]; + } + get commands() { + return Client.commands; + } + static get buttons() { return MetadataStorage.instance.buttons as readonly DButton[]; } @@ -141,7 +159,8 @@ export class Client extends ClientJS { this.guards = options.guards || []; this.requiredByDefault = options.requiredByDefault ?? false; this.slashGuilds = options.slashGuilds || []; - this._botId = options.botId; + this._botId = options.botId || "bot"; + this._prefix = options.prefix || "!"; } /** @@ -547,6 +566,99 @@ export class Client extends ClientJS { return slash.execute(interaction, this); } + /** + * Fetch prefix for message + * @param message messsage instance + * @returns prefix + */ + private async getMessagePrefix(message: Message) { + if (typeof this.prefix === "string") return this.prefix; + else return await this.prefix(message); + } + + /** + * + * @param prefix command prefix + * @param message original message + * @returns { isCommand: boolean; commandName?: string; commandArgs?: string } + */ + private parseCommand( + prefix: string, + message: Message + ): { isCommand: boolean; commandName: string; commandArgs: string } { + const escapePrefix = prefix.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + const prefixRegex = RegExp(`^${escapePrefix}`); + const isCommand = prefixRegex.test(message.content); + if (!isCommand) + return { isCommand: false, commandName: "", commandArgs: "" }; + + const contentWithoutPrefix = message.content + .replace(prefixRegex, "") + .trim(); + + const commandName = contentWithoutPrefix.split(" ")[0]; + if (!commandName) + return { isCommand: false, commandName: "", commandArgs: "" }; + + const commandArgs = contentWithoutPrefix.split(" ").splice(1).join(" "); + + return { + isCommand: true, + commandName, + commandArgs, + }; + } + + /** + * Execute the corresponding @Command based on an message instance + * @param message The discord.js message instance + * @returns void + */ + async executeCommand(message: Message) { + if (!message) { + if (!this.silent) { + console.log("message is undefined"); + } + return; + } + + const prefix = await this.getMessagePrefix(message); + if (!prefix) { + if (!this.silent) console.log("command prefix not found"); + return; + } + + const commandInfo = this.parseCommand(prefix, message); + if (!commandInfo.isCommand) return; + + const command = this.commands.find( + (cmd) => cmd.name === commandInfo.commandName + ); + + if (!command) { + return console.log("command not found:", commandInfo.commandName); + } + + // validate bot id + if (command.botIds.length && !command.botIds.includes(this.botId)) return; + + // validate guild id + if ( + command.guilds.length && + message.guild?.id && + !command.guilds.includes(message.guild.id) + ) + return; + + // check dm allowed or not + if (!command.directMessage && !message.guild) return; + + const msg = message as CommandMessage; + msg.commandName = commandInfo.commandName; + msg.commandArgString = commandInfo.commandArgs; + command.execute(msg, this); + } + /** * Manually trigger an event (used for tests) * @param event The event diff --git a/src/decorators/classes/DCommand.ts b/src/decorators/classes/DCommand.ts new file mode 100644 index 00000000..30daf0c6 --- /dev/null +++ b/src/decorators/classes/DCommand.ts @@ -0,0 +1,123 @@ +import { ApplicationCommandPermissionData } from "discord.js"; +import { Client } from "../.."; +import { CommandMessage } from "../../types/public/CommandMessage"; +import { DCommandOption } from "./DCommandOption"; +import { Method } from "./Method"; + +export class DCommand extends Method { + private _description!: string; + private _name!: string; + private _defaultPermission!: boolean; + private _directMessage!: boolean; + private _argSplitter!: string; + private _options: DCommandOption[] = []; + private _permissions: ApplicationCommandPermissionData[] = []; + private _guilds!: string[]; + private _botIds!: string[]; + + get botIds() { + return this._botIds; + } + set botIds(value) { + this._botIds = value; + } + + get permissions() { + return this._permissions; + } + set permissions(value) { + this._permissions = value; + } + + get guilds() { + return this._guilds; + } + set guilds(value) { + this._guilds = value; + } + + get argSplitter() { + return this._argSplitter; + } + set argSplitter(value) { + this._argSplitter = value; + } + + get directMessage() { + return this._directMessage; + } + set directMessage(value) { + this._directMessage = value; + } + + get defaultPermission() { + return this._defaultPermission; + } + set defaultPermission(value) { + this._defaultPermission = value; + } + + get name() { + return this._name; + } + set name(value: string) { + this._name = value; + } + + get description() { + return this._description; + } + set description(value: string) { + this._description = value; + } + + get options() { + return this._options; + } + set options(value: DCommandOption[]) { + this._options = value; + } + + protected constructor() { + super(); + } + + static create( + name: string, + description?: string, + argSplitter?: string, + directMessage?: boolean, + defaultPermission?: boolean, + guilds?: string[], + botIds?: string[] + ) { + const cmd = new DCommand(); + + cmd.name = name.toLowerCase(); + cmd.description = description || cmd.name; + cmd.directMessage = directMessage ?? true; + cmd.defaultPermission = defaultPermission ?? true; + cmd.argSplitter = argSplitter ?? " "; + cmd.guilds = guilds || Client.slashGuilds; + cmd.botIds = botIds || []; + + return cmd; + } + + parseParams(message: CommandMessage) { + if (!this.options.length) return []; + const args = message.commandArgString.split(this.argSplitter); + + return this.options + .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)) + .map((op, index) => + !args?.[index]?.length + ? undefined + : op.type === "boolean" + ? Boolean(args[index]) + : op.type === "number" + ? Number(args[index]) + : args[index] + ); + } +} diff --git a/src/decorators/classes/DCommandOption.ts b/src/decorators/classes/DCommandOption.ts new file mode 100644 index 00000000..10ab2157 --- /dev/null +++ b/src/decorators/classes/DCommandOption.ts @@ -0,0 +1,46 @@ +import { Decorator } from "./Decorator"; + +export class DCommandOption extends Decorator { + private _name!: string; + private _description!: string; + private _type!: "string" | "number" | "boolean"; + + get name() { + return this._name; + } + set name(value) { + this._name = value; + } + + get type() { + return this._type; + } + set type(value) { + this._type = value; + } + + get description() { + return this._description; + } + set description(value) { + this._description = value; + } + + protected constructor() { + super(); + } + + static create( + name: string, + type: "string" | "number" | "boolean", + description?: string + ) { + const option = new DCommandOption(); + + option._name = name.toLowerCase(); + option._type = type || "string"; + option._description = description || `${name} - ${option.type}`; + + return option; + } +} diff --git a/src/decorators/classes/DDiscord.ts b/src/decorators/classes/DDiscord.ts index d8032243..4757f649 100644 --- a/src/decorators/classes/DDiscord.ts +++ b/src/decorators/classes/DDiscord.ts @@ -3,12 +3,14 @@ import { DGuard, DSlash, DIService, DOn } from "../.."; import { DButton } from "./DButton"; import { DSelectMenu } from "./DSelectMenu"; import { ApplicationCommandPermissionData } from "discord.js"; +import { DCommand } from "./DCommand"; export class DDiscord extends Decorator { private _guards: DGuard[] = []; private _buttons: DButton[] = []; private _selectMenus: DSelectMenu[] = []; private _slashes: DSlash[] = []; + private _commands: DCommand[] = []; private _events: DOn[] = []; private _description!: string; private _name!: string; @@ -73,6 +75,13 @@ export class DDiscord extends Decorator { this._slashes = value; } + get commands() { + return this._commands; + } + set commands(value) { + this._commands = value; + } + get buttons() { return this._buttons; } diff --git a/src/decorators/classes/DSlash.ts b/src/decorators/classes/DSlash.ts index 3b96899f..6284c917 100644 --- a/src/decorators/classes/DSlash.ts +++ b/src/decorators/classes/DSlash.ts @@ -10,7 +10,7 @@ import { Method } from "./Method"; export class DSlash extends Method { private _description!: string; private _name!: string; - private _defaultPermission = true; + private _defaultPermission!: boolean; private _options: DOption[] = []; private _permissions: ApplicationCommandPermissionData[] = []; private _guilds!: string[]; diff --git a/src/decorators/decorators/Bot.ts b/src/decorators/decorators/Bot.ts index 42947f8e..9ad09c82 100644 --- a/src/decorators/decorators/Bot.ts +++ b/src/decorators/decorators/Bot.ts @@ -1,5 +1,6 @@ import { MetadataStorage, Modifier } from "../.."; import { DButton } from "../classes/DButton"; +import { DCommand } from "../classes/DCommand"; import { DDiscord } from "../classes/DDiscord"; import { DOn } from "../classes/DOn"; import { DSelectMenu } from "../classes/DSelectMenu"; @@ -14,7 +15,9 @@ export function Bot(...botIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create< + DSlash | DCommand | DDiscord | DButton | DSelectMenu | DOn + >( (original) => { original.botIds = [ ...original.botIds, @@ -22,15 +25,22 @@ export function Bot(...botIDs: string[]) { ]; if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { - slash.botIds = [ - ...slash.botIds, - ...botIDs.filter((botID) => !slash.botIds.includes(botID)), + [ + ...original.slashes, + ...original.commands, + ...original.buttons, + ...original.selectMenus, + ...original.events, + ].forEach((ob) => { + ob.botIds = [ + ...ob.botIds, + ...botIDs.filter((botID) => !ob.botIds.includes(botID)), ]; }); } }, DSlash, + DCommand, DDiscord, DButton, DSelectMenu, diff --git a/src/decorators/decorators/Command.ts b/src/decorators/decorators/Command.ts new file mode 100644 index 00000000..f8dbaf87 --- /dev/null +++ b/src/decorators/decorators/Command.ts @@ -0,0 +1,28 @@ +import { MetadataStorage } from "../.."; +import { DCommand } from "../classes/DCommand"; +import { CommandParams } from "../params/CommandParams"; + +const testName = RegExp(/^[a-z0-9]+$/); + +export function Command(); +export function Command(name: string); +export function Command(name: string, params: CommandParams); +export function Command(name?: string, params?: CommandParams) { + return (target: Object, key: string) => { + name = name || key; + name = name.toLocaleLowerCase(); + if (!testName.test(name)) throw Error("invalid command name"); + + const cmd = DCommand.create( + name, + params?.description, + params?.argSplitter, + params?.directMessage, + params?.defaultPermission, + params?.guilds, + params?.botIds + ).decorate(target.constructor, key, target[key]); + + MetadataStorage.instance.addCommand(cmd); + }; +} diff --git a/src/decorators/decorators/CommandOption.ts b/src/decorators/decorators/CommandOption.ts new file mode 100644 index 00000000..3830169b --- /dev/null +++ b/src/decorators/decorators/CommandOption.ts @@ -0,0 +1,43 @@ +import "reflect-metadata"; +import { MetadataStorage, Modifier } from "../.."; +import { DCommand } from "../classes/DCommand"; +import { DCommandOption } from "../classes/DCommandOption"; + +export function CommandOption(name: string); +export function CommandOption( + name: string, + params: { description?: string; type?: "string" | "number" | "boolean" } +); +export function CommandOption( + name: string, + params?: { description?: string; type?: "string" | "number" | "boolean" } +) { + return (target: Object, key: string, index: number) => { + const type = + params?.type ?? + (( + Reflect.getMetadata("design:paramtypes", target, key)[index] + .name as string + ).toLowerCase() as "string" | "number" | "boolean"); + + const option = DCommandOption.create( + name || key, + type, + params?.description + ).decorate(target.constructor, key, target[key], target.constructor, index); + + MetadataStorage.instance.addModifier( + Modifier.create((original) => { + original.options = [...original.options, option]; + }, DCommand).decorate( + target.constructor, + key, + target[key], + target.constructor, + index + ) + ); + + MetadataStorage.instance.addCommandOption(option); + }; +} diff --git a/src/decorators/decorators/DefaultPermission.ts b/src/decorators/decorators/DefaultPermission.ts index 8b582794..3763a121 100644 --- a/src/decorators/decorators/DefaultPermission.ts +++ b/src/decorators/decorators/DefaultPermission.ts @@ -1,4 +1,5 @@ import { MetadataStorage, Modifier } from "../.."; +import { DCommand } from "../classes/DCommand"; import { DDiscord } from "../classes/DDiscord"; import { DSlash } from "../classes/DSlash"; @@ -18,6 +19,7 @@ export function DefaultPermission(permission?: boolean) { } }, DSlash, + DCommand, DDiscord ).decorateUnknown(target, key, descriptor) ); diff --git a/src/decorators/decorators/Description.ts b/src/decorators/decorators/Description.ts index 820ba92c..fac2a270 100644 --- a/src/decorators/decorators/Description.ts +++ b/src/decorators/decorators/Description.ts @@ -1,4 +1,5 @@ import { MetadataStorage, Modifier } from "../.."; +import { DCommand } from "../classes/DCommand"; import { DSlash } from "../classes/DSlash"; export function Description(description: string); @@ -9,9 +10,13 @@ export function Description(description: string) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create((original) => { - original.description = description; - }, DSlash).decorate(target.constructor, key, descriptor.value) + Modifier.create( + (original) => { + original.description = description; + }, + DSlash, + DCommand + ).decorate(target.constructor, key, descriptor.value) ); }; } diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index d9037297..89e61bce 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -6,6 +6,7 @@ import { Method, } from "../.."; import { DButton } from "../classes/DButton"; +import { DCommand } from "../classes/DCommand"; import { DDiscord } from "../classes/DDiscord"; import { DOn } from "../classes/DOn"; import { DSelectMenu } from "../classes/DSelectMenu"; @@ -31,6 +32,7 @@ export function Guard( DSelectMenu, DButton, DSlash, + DCommand, DOn, DDiscord ).decorateUnknown(target, key, descriptor) diff --git a/src/decorators/decorators/Guild.ts b/src/decorators/decorators/Guild.ts index b4efb366..41940417 100644 --- a/src/decorators/decorators/Guild.ts +++ b/src/decorators/decorators/Guild.ts @@ -1,5 +1,6 @@ import { MetadataStorage, Modifier } from "../.."; import { DButton } from "../classes/DButton"; +import { DCommand } from "../classes/DCommand"; import { DDiscord } from "../classes/DDiscord"; import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; @@ -13,7 +14,7 @@ export function Guild(...guildIDs: string[]) { descriptor: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( (original) => { original.guilds = [ ...original.guilds, @@ -21,7 +22,12 @@ export function Guild(...guildIDs: string[]) { ]; if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { + [ + ...original.slashes, + ...original.commands, + ...original.buttons, + ...original.selectMenus, + ].forEach((slash) => { slash.guilds = [ ...slash.guilds, ...guildIDs.filter( @@ -32,6 +38,7 @@ export function Guild(...guildIDs: string[]) { } }, DSlash, + DCommand, DDiscord, DButton, DSelectMenu diff --git a/src/decorators/decorators/Name.ts b/src/decorators/decorators/Name.ts index 95eb8ce3..46782347 100644 --- a/src/decorators/decorators/Name.ts +++ b/src/decorators/decorators/Name.ts @@ -1,4 +1,5 @@ import { MetadataStorage, DSlash, Modifier, DDiscord } from "../.."; +import { DCommand } from "../classes/DCommand"; export function Name(name: string); export function Name(name: string) { @@ -8,11 +9,12 @@ export function Name(name: string) { descriptor?: PropertyDescriptor ): void => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( (original) => { original.name = name; }, DSlash, + DCommand, DDiscord ).decorateUnknown(target, key, descriptor) ); diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index 6e04eed2..b85c07a0 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -1,5 +1,6 @@ import { ApplicationCommandPermissionData } from "discord.js"; import { MetadataStorage, Modifier } from "../.."; +import { DCommand } from "../classes/DCommand"; import { DDiscord } from "../classes/DDiscord"; import { DSlash } from "../classes/DSlash"; @@ -8,7 +9,7 @@ export function Permission(...permission: ApplicationCommandPermissionData[]); export function Permission(...permission: ApplicationCommandPermissionData[]) { return (target: Object, key: string, descriptor: PropertyDescriptor) => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( (original) => { original.permissions = [...original.permissions, ...permission]; @@ -19,6 +20,7 @@ export function Permission(...permission: ApplicationCommandPermissionData[]) { } }, DSlash, + DCommand, DDiscord ).decorateUnknown(target, key, descriptor) ); diff --git a/src/decorators/index.ts b/src/decorators/index.ts index 4683c42b..ab0e0dfa 100644 --- a/src/decorators/index.ts +++ b/src/decorators/index.ts @@ -15,6 +15,8 @@ export * from "./decorators/Guild"; export * from "./decorators/Bot"; export * from "./decorators/Button"; export * from "./decorators/SelectMenu"; +export * from "./decorators/Command"; +export * from "./decorators/CommandOption"; export * from "./params/DiscordParams"; export * from "./params/OptionParams"; diff --git a/src/decorators/params/CommandParams.ts b/src/decorators/params/CommandParams.ts new file mode 100644 index 00000000..d0179ea8 --- /dev/null +++ b/src/decorators/params/CommandParams.ts @@ -0,0 +1,8 @@ +export interface CommandParams { + argSplitter?: string; + description?: string; + directMessage?: boolean; + defaultPermission?: boolean; + guilds?: string[]; + botIds?: string[]; +} diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index b9af7cd5..3b2ad1e1 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -14,6 +14,8 @@ import { import { DButton, DGroup } from "../../decorators"; import { DSelectMenu } from "../../decorators/classes/DSelectMenu"; import * as glob from "glob"; +import { DCommand } from "../../decorators/classes/DCommand"; +import { DCommandOption } from "../../decorators/classes/DCommandOption"; export class MetadataStorage { private static isBuilt = false; @@ -28,6 +30,8 @@ export class MetadataStorage { private _options: DOption[] = []; private _discords: DDiscord[] = []; private _modifiers: Modifier[] = []; + private _commands: DCommand[] = []; + private _commandsOptions: DCommandOption[] = []; private _groups: DGroup[] = []; private _subGroups: DGroup[] = []; @@ -79,6 +83,10 @@ export class MetadataStorage { return this._slashes as readonly DSlash[]; } + get commands() { + return this._commands as readonly DCommand[]; + } + get buttons() { return this._buttons as readonly DButton[]; } @@ -102,6 +110,7 @@ export class MetadataStorage { private get discordMembers(): readonly Method[] { return [ ...this._slashes, + ...this._commands, ...this._events, ...this._buttons, ...this._selectMenu, @@ -120,6 +129,14 @@ export class MetadataStorage { this._slashes.push(slash); } + addCommand(cmd: DCommand) { + this._commands.push(cmd); + } + + addCommandOption(cmdOption: DCommandOption) { + this._commandsOptions.push(cmdOption); + } + addButton(button: DButton) { this._buttons.push(button); } @@ -189,6 +206,10 @@ export class MetadataStorage { discord.slashes.push(member); } + if (member instanceof DCommand) { + discord.commands.push(member); + } + if (member instanceof DOn) { discord.events.push(member); } @@ -205,6 +226,7 @@ export class MetadataStorage { await Modifier.applyFromModifierListToList(this._modifiers, this._discords); await Modifier.applyFromModifierListToList(this._modifiers, this._events); await Modifier.applyFromModifierListToList(this._modifiers, this._slashes); + await Modifier.applyFromModifierListToList(this._modifiers, this._commands); await Modifier.applyFromModifierListToList(this._modifiers, this._buttons); await Modifier.applyFromModifierListToList(this._modifiers, this._options); await Modifier.applyFromModifierListToList( @@ -361,7 +383,7 @@ export class MetadataStorage { return async (...params: ArgsOf) => { for (const on of eventsToExecute) { - const botIDs = [...on.botIds, ...on.discord.botIds]; + const botIDs = on.botIds; if (botIDs.length && !botIDs.includes(client.botId)) return; const res = await on.execute(params, client); responses.push(res); diff --git a/src/types/core/ClientOptions.ts b/src/types/core/ClientOptions.ts index c0330848..89f067d9 100644 --- a/src/types/core/ClientOptions.ts +++ b/src/types/core/ClientOptions.ts @@ -1,11 +1,16 @@ -import { ClientOptions as DiscordJSClientOptions } from "discord.js"; +import { ClientOptions as DiscordJSClientOptions, Message } from "discord.js"; import { GuardFunction } from "../public/GuardFunction"; export interface ClientOptions extends DiscordJSClientOptions { /** * Specifiy bot id (added for multiple bot support) */ - botId: string; + botId?: string; + + /** + * bot prefix resolver + */ + prefix?: string | ((message: Message) => Promise); /** * Do not log anything in the console diff --git a/src/types/index.ts b/src/types/index.ts index 4a917dc2..ef20fa47 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,5 +7,6 @@ export * from "./core/ChoicesType"; export * from "./public/GuardFunction"; export * from "./public/CommandType"; +export * from "./public/CommandMessage"; export * from "./public/ArgsOf"; export * from "./public/PermissionType"; diff --git a/src/types/public/CommandMessage.ts b/src/types/public/CommandMessage.ts new file mode 100644 index 00000000..ea27dc96 --- /dev/null +++ b/src/types/public/CommandMessage.ts @@ -0,0 +1,6 @@ +import { Message } from "discord.js"; + +export interface CommandMessage extends Message { + commandName: string; + commandArgString: string; +} From 3f9ddd389de945e66230381e3a141698f6e12a0f Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 19:33:20 +0530 Subject: [PATCH 092/106] fix examples --- examples/button/Main.ts | 11 +++++------ examples/button/discords/AppDiscord.ts | 10 +++++----- examples/event/Main.ts | 11 +++++------ examples/guards/Main.ts | 11 +++++------ examples/guards/guards/Say.ts | 12 ++++-------- examples/menu/Main.ts | 11 +++++------ examples/menu/discords/AppDiscord.ts | 2 +- examples/multiple-discord-instances/Main.ts | 11 +++++------ examples/slash/Main.ts | 11 +++++------ 9 files changed, 40 insertions(+), 50 deletions(-) diff --git a/examples/button/Main.ts b/examples/button/Main.ts index d4cae955..6aaeed38 100644 --- a/examples/button/Main.ts +++ b/examples/button/Main.ts @@ -11,7 +11,10 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, @@ -19,11 +22,7 @@ export class Main { // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOU_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOU_TOKEN"); this._client.once("ready", async () => { await this._client.initSlashes(); diff --git a/examples/button/discords/AppDiscord.ts b/examples/button/discords/AppDiscord.ts index 3f74c1ff..7d6037c2 100644 --- a/examples/button/discords/AppDiscord.ts +++ b/examples/button/discords/AppDiscord.ts @@ -92,25 +92,25 @@ export abstract class StonePaperScissor { .setLabel("Stone") .setEmoji("💎") .setStyle("PRIMARY") - .setCustomID("spc-stone"); + .setCustomId("spc-stone"); const buttonPaper = new MessageButton() .setLabel("Paper") .setEmoji("🧻") .setStyle("PRIMARY") - .setCustomID("spc-paper"); + .setCustomId("spc-paper"); const buttonScissor = new MessageButton() .setLabel("Scissor") .setEmoji("✂️") .setStyle("PRIMARY") - .setCustomID("spc-scissor"); + .setCustomId("spc-scissor"); const buttonWell = new MessageButton() .setLabel("Well") .setEmoji("❓") .setStyle("DANGER") - .setCustomID("spc-well") + .setCustomId("spc-well") .setDisabled(true); const buttonRow = new MessageActionRow().addComponents( @@ -140,7 +140,7 @@ export abstract class StonePaperScissor { await interaction.defer(); const playerChoice = spcProposition.buttonCustomIDToClass( - interaction.customID + interaction.customId ); const botChoice = StonePaperScissor.spcPlayBot(); const result = StonePaperScissor.isWinSpc(playerChoice, botChoice); diff --git a/examples/event/Main.ts b/examples/event/Main.ts index e0c9c080..ffab46ba 100644 --- a/examples/event/Main.ts +++ b/examples/event/Main.ts @@ -11,18 +11,17 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // slashGuilds: [YOUR_GUILD_ID], }); // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOUR_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOUR_TOKEN"); } } diff --git a/examples/guards/Main.ts b/examples/guards/Main.ts index 41fc2845..911cfdc3 100644 --- a/examples/guards/Main.ts +++ b/examples/guards/Main.ts @@ -10,7 +10,10 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, @@ -18,11 +21,7 @@ export class Main { // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOUR_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOUR_TOKEN"); this._client.once("ready", async () => { await this._client.initSlashes(); diff --git a/examples/guards/guards/Say.ts b/examples/guards/guards/Say.ts index 58f45215..0172da99 100644 --- a/examples/guards/guards/Say.ts +++ b/examples/guards/guards/Say.ts @@ -2,14 +2,10 @@ import { CommandInteraction } from "discord.js"; import { ArgsOf, GuardFunction } from "../../../src"; export const Say = (text: string) => { - const guard: GuardFunction | CommandInteraction> = async ( - messageOrCommand, - client, - next, - nextObj - ) => { - await next(); - }; + const guard: GuardFunction | CommandInteraction> = + async (messageOrCommand, client, next, nextObj) => { + await next(); + }; return guard; }; diff --git a/examples/menu/Main.ts b/examples/menu/Main.ts index d4cae955..dbebd39e 100644 --- a/examples/menu/Main.ts +++ b/examples/menu/Main.ts @@ -11,19 +11,18 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, }); // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOU_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOU_TOKEN"); this._client.once("ready", async () => { await this._client.initSlashes(); diff --git a/examples/menu/discords/AppDiscord.ts b/examples/menu/discords/AppDiscord.ts index 3aadf074..97a2e4aa 100644 --- a/examples/menu/discords/AppDiscord.ts +++ b/examples/menu/discords/AppDiscord.ts @@ -39,7 +39,7 @@ export abstract class buttons { // create menu for roels const menu = new MessageSelectMenu() .addOptions(roles) - .setCustomID("role-menu"); + .setCustomId("role-menu"); // create a row for meessage actions const buttonRow = new MessageActionRow().addComponents(menu); diff --git a/examples/multiple-discord-instances/Main.ts b/examples/multiple-discord-instances/Main.ts index 41fc2845..4206ef7f 100644 --- a/examples/multiple-discord-instances/Main.ts +++ b/examples/multiple-discord-instances/Main.ts @@ -10,19 +10,18 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], }); // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOUR_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOUR_TOKEN"); this._client.once("ready", async () => { await this._client.initSlashes(); diff --git a/examples/slash/Main.ts b/examples/slash/Main.ts index d4cae955..dbebd39e 100644 --- a/examples/slash/Main.ts +++ b/examples/slash/Main.ts @@ -11,19 +11,18 @@ export class Main { static async start() { this._client = new Client({ - botId: "test", intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], // slashGuilds: [YOUR_GUILD_ID], requiredByDefault: true, }); // In the login method, you must specify the glob string to load your classes (for the framework). // In this case that's not necessary because the entry point of your application is this file. - await this._client.login( - "YOU_TOKEN", - `${__dirname}/discords/*.ts`, // glob string to load the classes - `${__dirname}/discords/*.js` // If you compile your bot, the file extension will be .js - ); + await this._client.login("YOU_TOKEN"); this._client.once("ready", async () => { await this._client.initSlashes(); From 1c8ff7a5ed658d2e0673bb58f53730a75f40f2ec Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 19:56:13 +0530 Subject: [PATCH 093/106] fixed event execute --- src/logic/metadatas/MetadataStorage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/metadatas/MetadataStorage.ts b/src/logic/metadatas/MetadataStorage.ts index 3b2ad1e1..d8754b28 100644 --- a/src/logic/metadatas/MetadataStorage.ts +++ b/src/logic/metadatas/MetadataStorage.ts @@ -384,7 +384,7 @@ export class MetadataStorage { return async (...params: ArgsOf) => { for (const on of eventsToExecute) { const botIDs = on.botIds; - if (botIDs.length && !botIDs.includes(client.botId)) return; + if (botIDs.length && !botIDs.includes(client.botId)) continue; const res = await on.execute(params, client); responses.push(res); } From dcdab5d0326b2f524858ff7b4d70ad61db90a6d8 Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 20:21:21 +0530 Subject: [PATCH 094/106] simple command example --- examples/command/Main.ts | 39 ++++++++++++++++++++++++ examples/command/discords/AppDiscord.ts | 40 +++++++++++++++++++++++++ examples/command/tsconfig.json | 17 +++++++++++ src/Client.ts | 8 +++-- src/types/public/CommandMessage.ts | 9 ++++-- 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 examples/command/Main.ts create mode 100644 examples/command/discords/AppDiscord.ts create mode 100644 examples/command/tsconfig.json diff --git a/examples/command/Main.ts b/examples/command/Main.ts new file mode 100644 index 00000000..dbebd39e --- /dev/null +++ b/examples/command/Main.ts @@ -0,0 +1,39 @@ +import "reflect-metadata"; +import { Client } from "../../src"; +import { Intents } from "discord.js"; + +export class Main { + private static _client: Client; + + static get Client(): Client { + return this._client; + } + + static async start() { + this._client = new Client({ + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + classes: [ + `${__dirname}/discords/*.ts`, // glob string to load the classes + `${__dirname}/discords/*.js`, // If you compile your bot, the file extension will be .js + ], + // slashGuilds: [YOUR_GUILD_ID], + requiredByDefault: true, + }); + + // In the login method, you must specify the glob string to load your classes (for the framework). + // In this case that's not necessary because the entry point of your application is this file. + await this._client.login("YOU_TOKEN"); + + this._client.once("ready", async () => { + await this._client.initSlashes(); + + console.log("Bot started"); + }); + + this._client.on("interactionCreate", (interaction) => { + this._client.executeInteraction(interaction); + }); + } +} + +Main.start(); diff --git a/examples/command/discords/AppDiscord.ts b/examples/command/discords/AppDiscord.ts new file mode 100644 index 00000000..a907287c --- /dev/null +++ b/examples/command/discords/AppDiscord.ts @@ -0,0 +1,40 @@ +import { Discord, Command, CommandOption, CommandMessage } from "../../../src"; + +@Discord() +export abstract class commandTest { + @Command("math") + async cmd( + @CommandOption("num1") num1: number, // + @CommandOption("a") operation: string, // + @CommandOption("num2") num2: number, + message: CommandMessage + ) { + if ( + !num1 || + !operation || + !num2 || + !["+", "-", "*", "/"].includes(operation) + ) + return message.reply( + `usage: ${message.command.prefix}${message.command.name} number operation number` + + `${message.command.prefix}${message.command.name} 4 + 3` + ); + + let out = 0; + switch (operation) { + case "+": + out = num1 + num2; + break; + case "-": + out = num1 - num2; + break; + case "*": + out = num1 * num2; + break; + case "/": + out = num1 / num2; + break; + } + message.reply(`${num1} ${operation} ${num2} = ${out}`); + } +} diff --git a/examples/command/tsconfig.json b/examples/command/tsconfig.json new file mode 100644 index 00000000..e53b01d4 --- /dev/null +++ b/examples/command/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "noImplicitAny": false, + "sourceMap": true, + "outDir": "build", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "declaration": true, + "importHelpers": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2017", "esnext.asynciterable"], + "moduleResolution": "node" + }, + "exclude": ["node_modules", "tests", "examples"] +} diff --git a/src/Client.ts b/src/Client.ts index 1f441580..3d16c07d 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -654,8 +654,12 @@ export class Client extends ClientJS { if (!command.directMessage && !message.guild) return; const msg = message as CommandMessage; - msg.commandName = commandInfo.commandName; - msg.commandArgString = commandInfo.commandArgs; + msg.command = { + prefix, + object: command, + name: commandInfo.commandName, + argString: commandInfo.commandArgs, + }; command.execute(msg, this); } diff --git a/src/types/public/CommandMessage.ts b/src/types/public/CommandMessage.ts index ea27dc96..5f1c57f4 100644 --- a/src/types/public/CommandMessage.ts +++ b/src/types/public/CommandMessage.ts @@ -1,6 +1,11 @@ import { Message } from "discord.js"; +import { DCommand } from "../../decorators/classes/DCommand"; export interface CommandMessage extends Message { - commandName: string; - commandArgString: string; + command: { + prefix: string; + object: DCommand; + name: string; + argString: string; + }; } From 9d5bd0e83a4256c3ecd0dc210770e3b4b259af88 Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 20:27:31 +0530 Subject: [PATCH 095/106] update command example --- examples/command/Main.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/command/Main.ts b/examples/command/Main.ts index dbebd39e..9a73675b 100644 --- a/examples/command/Main.ts +++ b/examples/command/Main.ts @@ -24,6 +24,10 @@ export class Main { // In this case that's not necessary because the entry point of your application is this file. await this._client.login("YOU_TOKEN"); + this._client.on("messageCreate", (message) => { + this._client.executeCommand(message); + }); + this._client.once("ready", async () => { await this._client.initSlashes(); From d04e31af31ac15e915517db90e61ece43584e236 Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 20:28:47 +0530 Subject: [PATCH 096/106] fix ``@Commad`` executation --- src/decorators/classes/DCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decorators/classes/DCommand.ts b/src/decorators/classes/DCommand.ts index 30daf0c6..3ec87816 100644 --- a/src/decorators/classes/DCommand.ts +++ b/src/decorators/classes/DCommand.ts @@ -106,7 +106,7 @@ export class DCommand extends Method { parseParams(message: CommandMessage) { if (!this.options.length) return []; - const args = message.commandArgString.split(this.argSplitter); + const args = message.command.argString.split(this.argSplitter); return this.options .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)) From ae2b055c0b09cece8745edc782e27cf9780e2dcb Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 20:47:17 +0530 Subject: [PATCH 097/106] update example command --- examples/command/discords/AppDiscord.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/command/discords/AppDiscord.ts b/examples/command/discords/AppDiscord.ts index a907287c..c40a65fa 100644 --- a/examples/command/discords/AppDiscord.ts +++ b/examples/command/discords/AppDiscord.ts @@ -2,7 +2,8 @@ import { Discord, Command, CommandOption, CommandMessage } from "../../../src"; @Discord() export abstract class commandTest { - @Command("math") + // single whitespace will be used to split options + @Command("math", { argSplitter: " " }) async cmd( @CommandOption("num1") num1: number, // @CommandOption("a") operation: string, // From 2eb57d018825a6dff45ccd3e9dce57009d9d8cfb Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 21:03:43 +0530 Subject: [PATCH 098/106] example command update --- examples/command/discords/AppDiscord.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/command/discords/AppDiscord.ts b/examples/command/discords/AppDiscord.ts index c40a65fa..bfc24782 100644 --- a/examples/command/discords/AppDiscord.ts +++ b/examples/command/discords/AppDiscord.ts @@ -17,8 +17,8 @@ export abstract class commandTest { !["+", "-", "*", "/"].includes(operation) ) return message.reply( - `usage: ${message.command.prefix}${message.command.name} number operation number` + - `${message.command.prefix}${message.command.name} 4 + 3` + `**Command Usage:** \`\`${message.command.prefix}${message.command.name} num1 operator num2\`\` ` + // + `\`\`\`${message.command.prefix}${message.command.name} 1 + 3\`\`\`` ); let out = 0; From 01fa0bba133c6b668c49d2ca7bb0d4ca77e8c888 Mon Sep 17 00:00:00 2001 From: iorp Date: Tue, 6 Jul 2021 21:08:30 +0530 Subject: [PATCH 099/106] update executecommand --- src/Client.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Client.ts b/src/Client.ts index 3d16c07d..bd1196d3 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -636,7 +636,10 @@ export class Client extends ClientJS { ); if (!command) { - return console.log("command not found:", commandInfo.commandName); + if (!this.silent) { + console.log("command not found:", commandInfo.commandName); + } + return; } // validate bot id From 19162291738052867ff35ab7d3cdf5c972ec8b98 Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 00:34:24 +0530 Subject: [PATCH 100/106] fix permissions decorator for commands --- src/Client.ts | 41 +++++++++++++++++++ .../decorators/DefaultPermission.ts | 6 +-- src/decorators/decorators/Permission.ts | 4 +- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index bd1196d3..305874b6 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -656,6 +656,47 @@ export class Client extends ClientJS { // check dm allowed or not if (!command.directMessage && !message.guild) return; + // check for member permissions + if (command.defaultPermission) { + // when default perm is on + const permissions = command.permissions.filter( + (perm) => !perm.permission + ); + const userPermissions = permissions.filter( + (perm) => perm.type === "USER" + ); + const rolePermissions = permissions.filter( + (perm) => perm.type === "ROLE" + ); + + const isUserIdAllowed = + userPermissions.some((perm) => perm.id === message.member?.id) || + rolePermissions.some((perm) => + message.member?.roles.cache.has(perm.id) + ); + + // user is not allowed to access this command + if (isUserIdAllowed) return; + } else { + // when default perm is off + const permissions = command.permissions.filter((perm) => perm.permission); + const userPermissions = permissions.filter( + (perm) => perm.type === "USER" + ); + const rolePermissions = permissions.filter( + (perm) => perm.type === "ROLE" + ); + + const isUserIdAllowed = + userPermissions.some((perm) => perm.id === message.member?.id) || + rolePermissions.some((perm) => + message.member?.roles.cache.has(perm.id) + ); + + // user does not have any permission to access this command + if (!isUserIdAllowed) return; + } + const msg = message as CommandMessage; msg.command = { prefix, diff --git a/src/decorators/decorators/DefaultPermission.ts b/src/decorators/decorators/DefaultPermission.ts index 3763a121..886ecf71 100644 --- a/src/decorators/decorators/DefaultPermission.ts +++ b/src/decorators/decorators/DefaultPermission.ts @@ -8,13 +8,13 @@ export function DefaultPermission(permission: boolean); export function DefaultPermission(permission?: boolean) { return (target: Object, key: string, descriptor: PropertyDescriptor) => { MetadataStorage.instance.addModifier( - Modifier.create( + Modifier.create( (original) => { original.defaultPermission = permission ?? true; if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { - slash.defaultPermission = permission ?? true; + [...original.slashes, ...original.commands].forEach((obj) => { + obj.defaultPermission = permission ?? true; }); } }, diff --git a/src/decorators/decorators/Permission.ts b/src/decorators/decorators/Permission.ts index b85c07a0..dbb602c0 100644 --- a/src/decorators/decorators/Permission.ts +++ b/src/decorators/decorators/Permission.ts @@ -14,8 +14,8 @@ export function Permission(...permission: ApplicationCommandPermissionData[]) { original.permissions = [...original.permissions, ...permission]; if (original instanceof DDiscord) { - original.slashes.forEach((slash) => { - slash.permissions = [...slash.permissions, ...permission]; + [...original.slashes, ...original.commands].forEach((obj) => { + obj.permissions = [...obj.permissions, ...permission]; }); } }, From b01b90d70dc822fb2cc085da2f1c6a9c67ea891e Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 01:07:35 +0530 Subject: [PATCH 101/106] update commands private to public for external use --- src/Client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 305874b6..9800ce26 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -571,7 +571,7 @@ export class Client extends ClientJS { * @param message messsage instance * @returns prefix */ - private async getMessagePrefix(message: Message) { + async getMessagePrefix(message: Message) { if (typeof this.prefix === "string") return this.prefix; else return await this.prefix(message); } @@ -582,7 +582,7 @@ export class Client extends ClientJS { * @param message original message * @returns { isCommand: boolean; commandName?: string; commandArgs?: string } */ - private parseCommand( + parseCommand( prefix: string, message: Message ): { isCommand: boolean; commandName: string; commandArgs: string } { From 6215c2ab9d9179856c2ea0bcd31ad084734249df Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 11:43:15 +0530 Subject: [PATCH 102/106] guard type update --- src/decorators/decorators/Guard.ts | 2 +- src/types/public/GuardFunction.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index 89e61bce..fd67bc71 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -12,7 +12,7 @@ import { DOn } from "../classes/DOn"; import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; -export function Guard( +export function Guard( ...fns: GuardFunction[] ) { return ( diff --git a/src/types/public/GuardFunction.ts b/src/types/public/GuardFunction.ts index 409f431f..48427bb6 100644 --- a/src/types/public/GuardFunction.ts +++ b/src/types/public/GuardFunction.ts @@ -1,4 +1,8 @@ import { Client, Next } from "../.."; -export type GuardFunction = (params: Type, client: Client, next: Next, datas: DatasType) => any; - +export type GuardFunction = ( + params: Type, + client: Client, + next: Next, + datas: DatasType +) => any; From a741e2d2733af436a72a404906ef94fb70ba90bf Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 12:25:06 +0530 Subject: [PATCH 103/106] type fix --- README.md | 15 +++++++++++---- examples/guards/discords/AppDiscord.ts | 6 ++++-- examples/guards/guards/Say.ts | 19 +++++++++++++------ src/decorators/decorators/Guard.ts | 2 +- src/types/index.ts | 1 - src/types/public/CommandType.ts | 17 +++++++++++------ src/types/public/GuardFunction.ts | 2 +- src/types/public/PermissionType.ts | 1 - tests/create-on-events.test.ts | 25 +++++++++++-------------- tests/slash.test.ts | 2 +- 10 files changed, 53 insertions(+), 37 deletions(-) delete mode 100644 src/types/public/PermissionType.ts diff --git a/README.md b/README.md index 4ff76813..1923e1c1 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,17 @@

# 🎻 Introduction + This module is an extension of **[discord.**js**](https://discordjs.guide/)**, so the internal behavior (methods, properties, ...) is the same. This library allows you to use TypeScript decorators on discord.**js**, it simplify your code and improve the readability ! # 📜 Documentation + **[https://owencalvin.github.io/discord.ts/](https://owencalvin.github.io/discord.ts/)** # 📟 @Slash - Discord commands + Discord has it's own command system now, you can simply declare commands and use Slash commands this way ```ts @@ -46,7 +49,9 @@ abstract class AppDiscord { ``` ## Decorators related to Slash commands + There is a whole system that allows you to implement complex Slash commands + - `@Choice` - `@Choices` - `@Option` @@ -57,9 +62,10 @@ There is a whole system that allows you to implement complex Slash commands - `@Guard` # 💡@On / @Once - Discord events -We can declare methods that will be executed whenever a Discord event is triggered. -Our methods must be decorated with the `@On(event: string)` or `@Once(event: string)` decorator. +We can declare methods that will be executed whenever a Discord event is triggered. + +Our methods must be decorated with the `@On(event: string)` or `@Once(event: string)` decorator. That's simple, when the event is triggered, the method is called: @@ -81,6 +87,7 @@ abstract class AppDiscord { ``` # ⚔️ Guards + We implemented a guard system thats work pretty like the [Koa](https://koajs.com/) middleware system You can use functions that are executed before your event to determine if it's executed. For example, if you want to apply a prefix to the messages, you can simply use the `@Guard` decorator. @@ -115,13 +122,13 @@ abstract class AppDiscord { ``` # 📡 Installation + Use [npm](https://www.npmjs.com/package/@typeit/discord) or yarn to install **@typeit/discord@slash** with **discord.js** **[Please refer to the documentation](https://owencalvin.github.io/discord.ts/installation/#installation)** - # ☎️ Need help? -**[Simply join the Discord server](https://discord.gg/VDjwu8E)** +**[Simply join the Discord server](https://discord.gg/VDjwu8E)** You can also find help with the [different projects that use discord.ts](https://github.com/OwenCalvin/discord.ts/network/dependents?package_id=UGFja2FnZS00Njc1MzYwNzU%3D) and in the [examples folder](https://github.com/OwenCalvin/discord.ts/tree/master/examples) diff --git a/examples/guards/discords/AppDiscord.ts b/examples/guards/discords/AppDiscord.ts index 5636e00f..ca719431 100644 --- a/examples/guards/discords/AppDiscord.ts +++ b/examples/guards/discords/AppDiscord.ts @@ -6,13 +6,15 @@ import { Say } from "../guards/Say"; export abstract class AppDiscord { @On("messageCreate") @Guard(Say("hello")) - onMessage([message]: ArgsOf<"messageCreate">, client: Client) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + onMessage([message]: ArgsOf<"messageCreate">, _client: Client) { console.log(message.content); } @Slash("hello") @Guard(Say("hello")) - hello(interaction: CommandInteraction, client: Client) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + hello(interaction: CommandInteraction, _client: Client) { console.log(interaction); } } diff --git a/examples/guards/guards/Say.ts b/examples/guards/guards/Say.ts index 0172da99..2b678d37 100644 --- a/examples/guards/guards/Say.ts +++ b/examples/guards/guards/Say.ts @@ -1,11 +1,18 @@ -import { CommandInteraction } from "discord.js"; -import { ArgsOf, GuardFunction } from "../../../src"; +import { CommandInteraction, Message } from "discord.js"; +import { GuardFunction } from "../../../src"; export const Say = (text: string) => { - const guard: GuardFunction | CommandInteraction> = - async (messageOrCommand, client, next, nextObj) => { - await next(); - }; + // do not use ArgOf it will throw undefined error cause of type error + const guard: GuardFunction = async ( + messageOrCommand, + _client, + next, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _nextObj + ) => { + messageOrCommand.channel.send(text); + await next(); + }; return guard; }; diff --git a/src/decorators/decorators/Guard.ts b/src/decorators/decorators/Guard.ts index fd67bc71..89e61bce 100644 --- a/src/decorators/decorators/Guard.ts +++ b/src/decorators/decorators/Guard.ts @@ -12,7 +12,7 @@ import { DOn } from "../classes/DOn"; import { DSelectMenu } from "../classes/DSelectMenu"; import { DSlash } from "../classes/DSlash"; -export function Guard( +export function Guard( ...fns: GuardFunction[] ) { return ( diff --git a/src/types/index.ts b/src/types/index.ts index ef20fa47..1a651f52 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -9,4 +9,3 @@ export * from "./public/GuardFunction"; export * from "./public/CommandType"; export * from "./public/CommandMessage"; export * from "./public/ArgsOf"; -export * from "./public/PermissionType"; diff --git a/src/types/public/CommandType.ts b/src/types/public/CommandType.ts index 0222eeb9..be356ff2 100644 --- a/src/types/public/CommandType.ts +++ b/src/types/public/CommandType.ts @@ -1,8 +1,15 @@ -import { Channel, ClientUser, Role, TextChannel, User, VoiceChannel } from "discord.js"; +import { + Channel, + ClientUser, + Role, + TextChannel, + User, + VoiceChannel, +} from "discord.js"; export type SubCommand = { - [key: string]: string -} + [key: string]: string; +}; export type StringOptionType = | "STRING" @@ -27,9 +34,7 @@ export enum OptionType { SUB_COMMAND_GROUP = "SUB_COMMAND_GROUP", } -export type StringSubType = - | "SUB_COMMAND" - | "SUB_COMMAND_GROUP"; +export type StringSubType = "SUB_COMMAND" | "SUB_COMMAND_GROUP"; export enum SubType { SUB_COMMAND = "SUB_COMMAND", diff --git a/src/types/public/GuardFunction.ts b/src/types/public/GuardFunction.ts index 48427bb6..34a1b2d4 100644 --- a/src/types/public/GuardFunction.ts +++ b/src/types/public/GuardFunction.ts @@ -1,6 +1,6 @@ import { Client, Next } from "../.."; -export type GuardFunction = ( +export type GuardFunction = ( params: Type, client: Client, next: Next, diff --git a/src/types/public/PermissionType.ts b/src/types/public/PermissionType.ts deleted file mode 100644 index 7ad3164d..00000000 --- a/src/types/public/PermissionType.ts +++ /dev/null @@ -1 +0,0 @@ -export type PermissionType = "USER" | "ROLE"; diff --git a/tests/create-on-events.test.ts b/tests/create-on-events.test.ts index 906d7bde..af1a2f42 100644 --- a/tests/create-on-events.test.ts +++ b/tests/create-on-events.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { Discord, On, Client, Guard, GuardFunction } from "../src"; const guard1: GuardFunction = @@ -9,19 +10,15 @@ const guard1: GuardFunction = } }; -const guard2: GuardFunction = async ( - [message]: [string], - client, - next, - mwDatas -) => { - if (mwDatas.original === "hello0") { - mwDatas.message += "1"; - await next(); - } else { - mwDatas.message += "2"; - } -}; +const guard2: GuardFunction<[string], { original: string; message: string }> = + async ([message]: [string], client, next, mwDatas) => { + if (mwDatas.original === "hello0") { + mwDatas.message += "1"; + await next(); + } else { + mwDatas.message += "2"; + } + }; @Discord() abstract class Bot { @@ -46,7 +43,7 @@ abstract class Bot { } } -const client = new Client({ botId: "test", intents: [] }); +const client = new Client({ intents: [] }); beforeAll(async () => { await client.build(); diff --git a/tests/slash.test.ts b/tests/slash.test.ts index 3ed5e6bf..b4b5f3d5 100644 --- a/tests/slash.test.ts +++ b/tests/slash.test.ts @@ -145,7 +145,7 @@ export abstract class AppDiscord1 { } } -const client = new Client({ botId: "test", intents: [] }); +const client = new Client({ intents: [] }); beforeAll(async () => { await client.build(); From fe33ac7b02aa31d36b4ec973ff6bb67dd0ae3c11 Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 12:32:14 +0530 Subject: [PATCH 104/106] doc formated --- docs/src/decorators/bot.md | 2 +- docs/src/decorators/button.md | 2 +- docs/src/decorators/choice.md | 7 ++- docs/src/decorators/choices.md | 3 +- docs/src/decorators/defaultpermission.md | 2 +- docs/src/decorators/description.md | 5 ++- docs/src/decorators/discord.md | 8 ++-- docs/src/decorators/group.md | 31 +++++++------ docs/src/decorators/guard.md | 23 +++++++--- docs/src/decorators/guild.md | 19 ++++---- docs/src/decorators/on.md | 14 +++--- docs/src/decorators/once.md | 12 +++--- docs/src/decorators/option.md | 52 ++++++++++++++-------- docs/src/decorators/permission.md | 18 +++++--- docs/src/decorators/selectmenu.md | 2 +- docs/src/decorators/slash.md | 55 +++++++++++++----------- docs/src/general/argsof.md | 12 ++---- docs/src/general/client.md | 43 +++++++++--------- docs/src/general/debugging.md | 42 +++++++++--------- docs/src/general/events.md | 4 +- docs/src/general/metadatastorage.md | 3 +- docs/src/general/sharding.md | 23 ++++------ docs/src/index.md | 12 +++--- docs/src/installation/README.md | 23 +++++++--- 24 files changed, 233 insertions(+), 184 deletions(-) diff --git a/docs/src/decorators/bot.md b/docs/src/decorators/bot.md index 1229f6e5..b8b1f2aa 100644 --- a/docs/src/decorators/bot.md +++ b/docs/src/decorators/bot.md @@ -2,4 +2,4 @@ ::: danger doc for `@Bot` is not ready -::: \ No newline at end of file +::: diff --git a/docs/src/decorators/button.md b/docs/src/decorators/button.md index 4f453492..53fb816d 100644 --- a/docs/src/decorators/button.md +++ b/docs/src/decorators/button.md @@ -2,4 +2,4 @@ ::: danger doc for `@Button` is not ready -::: \ No newline at end of file +::: diff --git a/docs/src/decorators/choice.md b/docs/src/decorators/choice.md index e5ab710b..dbd9b539 100644 --- a/docs/src/decorators/choice.md +++ b/docs/src/decorators/choice.md @@ -1,10 +1,12 @@ # @Choice + An option of a Slash command can implement an autocompletion feature for `string` and `number` types ![](/discord.ts/choices.png) ## Setup autocompletion -You just decorate your parameter with one or multiple @Choice ! + +You just decorate your parameter with one or multiple @Choice ! ```ts @Discord() @@ -25,12 +27,15 @@ class DiscordBot { ``` ## Params + `@Choice(name: string, value: string | number)` ### Name + `string` You have to set a diplayed name for your Choice ### Value + `string | number` You have to set a value for your choice, if the user select "Astraunot", you will receive the value "astro" diff --git a/docs/src/decorators/choices.md b/docs/src/decorators/choices.md index 5dfe5985..268972a7 100644 --- a/docs/src/decorators/choices.md +++ b/docs/src/decorators/choices.md @@ -1,4 +1,5 @@ # @Choices + It works exactly like [@Choice](/decorators/choice/) except that you can directly pass an object or enum to define all the choices at once > The key of the object or enum is what discord shows and the value is the property value (object[key]) @@ -7,7 +8,7 @@ It works exactly like [@Choice](/decorators/choice/) except that you can directl enum TextChoices { // WhatDiscordShows = value Hello = "Hello", - "Good Bye" = "GoodBye" + "Good Bye" = "GoodBye", } // Could be diff --git a/docs/src/decorators/defaultpermission.md b/docs/src/decorators/defaultpermission.md index ffc1262a..31edb1c9 100644 --- a/docs/src/decorators/defaultpermission.md +++ b/docs/src/decorators/defaultpermission.md @@ -2,4 +2,4 @@ ::: danger doc for `@DefaultPermission` is not ready -::: \ No newline at end of file +::: diff --git a/docs/src/decorators/description.md b/docs/src/decorators/description.md index 17f0821e..65423a4e 100644 --- a/docs/src/decorators/description.md +++ b/docs/src/decorators/description.md @@ -1,9 +1,10 @@ # @Description + This decorator is a shortcut to set the description property ```typescript import { ClassCommand, Command, CommandMessage } from "@typeit/discord"; -import { CommandInteraction } from "discord.js" +import { CommandInteraction } from "discord.js"; @Discord() export abstract class DiscordBot { @@ -19,7 +20,7 @@ Is equivalent to: ```typescript import { ClassCommand, Command, CommandMessage } from "@typeit/discord"; -import { CommandInteraction } from "discord.js" +import { CommandInteraction } from "discord.js"; @Discord() export abstract class DiscordBot { diff --git a/docs/src/decorators/discord.md b/docs/src/decorators/discord.md index 6036aa12..faed9c0b 100644 --- a/docs/src/decorators/discord.md +++ b/docs/src/decorators/discord.md @@ -1,4 +1,5 @@ # @Discord + This decorator instanciate the class inside the discord.**ts** library to access to the class members or to call the methods ::: danger @@ -11,10 +12,9 @@ import { Discord, Slash } from "@typeit/discord"; @Discord() abstract class AppDiscord { // We can use member decorators - // because we decorated the class with @Discord - @Slash("hello") - private hello( - ) { + // because we decorated the class with @Discord + @Slash("hello") + private hello() { // ... } } diff --git a/docs/src/decorators/group.md b/docs/src/decorators/group.md index 890fedc1..92b9c673 100644 --- a/docs/src/decorators/group.md +++ b/docs/src/decorators/group.md @@ -1,5 +1,7 @@ # @Group + You can group your command like this + ``` command | @@ -8,6 +10,7 @@ command |__ subcommand ``` + ``` command | @@ -21,17 +24,21 @@ command ``` ## Example -Here you create a Slash command group that groups "permissions" commands + +Here you create a Slash command group that groups "permissions" commands The permissions commands also grouped by "user" or "role" ![](https://discord.com/assets/4cfea1bfc6d3ed0396c16cd47e0a7154.png) ## Create a Group + We use @Group at two level, on the class and on methods ### Group on class level + When @Group decorate a class it groups all the Slash commands in the class + ``` maths | @@ -42,10 +49,7 @@ maths ```ts @Discord() -@Group( - "maths", - "maths group description", -) +@Group("maths", "maths group description") export abstract class AppDiscord { @Slash("add") add( @@ -70,12 +74,15 @@ export abstract class AppDiscord { } } ``` + ![](/discord.ts/group1.png) ### Group on method level + When @Group decorate a method it creates sub-groups inside the class group **You have to list the groups that are in the class in the @Group parameters that decorate the class, or they will not appear** + ```ts @Group( "testing", @@ -102,16 +109,13 @@ testing | |__ root ``` + ```ts @Discord() -@Group( - "testing", - "Testing group description", - { - maths: "maths group description", - text: "text group description" - } -) +@Group("testing", "Testing group description", { + maths: "maths group description", + text: "text group description", +}) export abstract class AppDiscord { @Slash("add") @Group("maths") @@ -155,4 +159,3 @@ export abstract class AppDiscord { ``` ![](/discord.ts/group2.png) - diff --git a/docs/src/decorators/guard.md b/docs/src/decorators/guard.md index 8d949670..fabae3c5 100644 --- a/docs/src/decorators/guard.md +++ b/docs/src/decorators/guard.md @@ -1,4 +1,5 @@ # @Guard + ::: warning add example for slash, argof message does not apply on interactions ::: @@ -68,7 +69,7 @@ abstract class AppDiscord { When can setup some guards globaly by assigning `Client.guards` -> The global guards are set statically, you can access it by `Client.guards` +> The global guards are set statically, you can access it by `Client.guards` > > Global guards are executed before @Discord guards @@ -99,7 +100,7 @@ start(); ## The guard functions -Here is a simple example of a guard function (the payload and the client instance are injected like for events) +Here is a simple example of a guard function (the payload and the client instance are injected like for events) Guards work like `Koa`'s, it's a function passed in parameter (third parameter in the guard function) and you will have to call if the guard is passed. @@ -108,7 +109,11 @@ Guards work like `Koa`'s, it's a function passed in parameter (third parameter i ```typescript import { GuardFunction, ArgsOf } from "@typeit/discord"; -export const NotBot: GuardFunction> = ([message], client, next) => { +export const NotBot: GuardFunction> = ( + [message], + client, + next +) => { if (client.user.id !== message.author.id) { await next(); } @@ -121,7 +126,11 @@ If you have to indicate parameters for a guard function you can simple use the " import { GuardFunction } from "@typeit/discord"; export function Prefix(text: string, replace: boolean = true) { - const guard: GuardFunction> = ([message], client, next) => { + const guard: GuardFunction> = ( + [message], + client, + next + ) => { const startWith = message.content.startsWith(text); if (replace) { message.content = message.content.replace(text, ""); @@ -165,7 +174,11 @@ import { Prefix } from "./Prefix"; abstract class AppDiscord { @Slash() @Guard(NotBot, Prefix("!")) - async hello(interaction: CommandInteraction, client: Client, guardDatas: any) { + async hello( + interaction: CommandInteraction, + client: Client, + guardDatas: any + ) { console.log(guardDatas.message); // > the NotBot guard passed } diff --git a/docs/src/decorators/guild.md b/docs/src/decorators/guild.md index 84620a40..f462b73e 100644 --- a/docs/src/decorators/guild.md +++ b/docs/src/decorators/guild.md @@ -1,48 +1,49 @@ # @Guild -You can specify in which guilds your @Slash commands are created by decorating the method with @Slash and @Guild + +You can specify in which guilds your @Slash commands are created by decorating the method with @Slash and @Guild ```ts @Discord() abstract class AppDiscord { @Guild("GUILD_ID") // Only created on the guild GUILD_ID @Slash("hello") - private hello( - ) { + private hello() { // ... } @Guild("GUILD_ID", "GUILD_ID2") // Only created on the guild GUILD_ID and GUILD_ID2 @Slash("bye") - private bye( - ) { + private bye() { // ... } } ``` ## Guild at class level + You can set the guild IDs for all @Slash inside the class by decorating the class with @Guild + ```ts @Discord() @Guild("GUILD_ID", "GUILD_ID2") class DiscordBot { @Slash("hello") // Only created on the guild GUILD_ID and GUILD_ID2 - private hello( - ) { + private hello() { // ... } @Slash("hello2") // Only created on the guild GUILD_ID and GUILD_ID2 - private hello2( - ) { + private hello2() { // ... } } ``` ## Params + `@Guild(...guildIDs: string[])` ### roleIDs + `string[]` The guilds IDs list diff --git a/docs/src/decorators/on.md b/docs/src/decorators/on.md index 800c3867..7ab2a3bf 100644 --- a/docs/src/decorators/on.md +++ b/docs/src/decorators/on.md @@ -1,7 +1,8 @@ # @On - Discord events -We can declare methods that will be executed whenever a Discord event is triggered. -Our methods must be decorated with the `@On(event: string)` or [@Once(event: string)](/decorators/once) decorator. +We can declare methods that will be executed whenever a Discord event is triggered. + +Our methods must be decorated with the `@On(event: string)` or [@Once(event: string)](/decorators/once) decorator. That's simple, when the event is triggered, the method is called: @@ -23,9 +24,11 @@ abstract class AppDiscord { ``` ## Get the event payload + For each event a list of arguments is injected in your decorated method, you can type this list thanks to the `ArgsOf<"YOUR_EVENT">` type provided by discord.**ts**. You also receive other useful arguments after that: + 1. The event payload (`ArgsOf<"YOUR_EVENT">`) 2. The `Client` instance 3. The [guards](/decorators/guards/) payload @@ -33,12 +36,7 @@ You also receive other useful arguments after that: > You should use JS desctructuring for `ArgsOf<"YOUR_EVENT">` like in this example ```typescript -import { - Discord, - On, - Client, - ArgsOf -} from "@typeit/discord"; +import { Discord, On, Client, ArgsOf } from "@typeit/discord"; @Discord() abstract class AppDiscord { diff --git a/docs/src/decorators/once.md b/docs/src/decorators/once.md index aacec76d..23eef009 100644 --- a/docs/src/decorators/once.md +++ b/docs/src/decorators/once.md @@ -1,4 +1,5 @@ # @Once - Discord events + It's exactly the same behavior as [@On](/decorators/on) but the method is only executed once ```typescript @@ -14,9 +15,11 @@ abstract class AppDiscord { ``` ## Get the event payload + For each event a list of arguments is injected in your decorated method, you can type this list thanks to the `ArgsOf<"YOUR_EVENT">` type provided by discord.**ts**. You also receive other useful arguments after that: + 1. The event payload (`ArgsOf<"YOUR_EVENT">`) 2. The `Client` instance 3. The [guards](/decorators/guards/) payload @@ -24,12 +27,7 @@ You also receive other useful arguments after that: > You should use JS desctructuring for `ArgsOf<"YOUR_EVENT">` like in this example ```typescript -import { - Discord, - On, - Client, - ArgsOf -} from "@typeit/discord"; +import { Discord, On, Client, ArgsOf } from "@typeit/discord"; @Discord() abstract class AppDiscord { @@ -42,4 +40,4 @@ abstract class AppDiscord { // ... } } -``` \ No newline at end of file +``` diff --git a/docs/src/decorators/option.md b/docs/src/decorators/option.md index e5bc7587..4b9d6d74 100644 --- a/docs/src/decorators/option.md +++ b/docs/src/decorators/option.md @@ -1,4 +1,5 @@ # Option + A Slash Command can have multiple options (parameters) > query is an option in this image @@ -6,7 +7,9 @@ A Slash Command can have multiple options (parameters) ![](/discord.ts/options.png) ## Declare an option + To declare an option you simply use the `@Option` decorator before a method parameter + ```ts @Discord() class DiscordBot { @@ -25,6 +28,7 @@ class DiscordBot { ``` ## Automatic typing + An option infer the type from TypeScript in this example, discord.**ts** knows that your options are both `number` because you typed the parameters discord.**ts** convert automatically the infered type into discord.**js** options types @@ -47,9 +51,11 @@ class DiscordBot { ``` ## Manual typing + If you want to specify the type manually you can do it: + ```ts -import { TextChannel, VoiceChannel, CommandInteraction } from "discord.js" +import { TextChannel, VoiceChannel, CommandInteraction } from "discord.js"; @Discord() class DiscordBot { @@ -66,8 +72,10 @@ class DiscordBot { ``` ## Type inferance + - `"STRING"` - **Infered from `String`** + **Infered from `String`** + ```ts fn( @Option("x") @@ -76,7 +84,8 @@ class DiscordBot { ``` - `"BOOLEAN"` - **Infered from `Boolean`** + **Infered from `Boolean`** + ```ts fn( @Option("x") @@ -85,7 +94,8 @@ class DiscordBot { ``` - `"INTEGER"` - **Infered from `Number`** + **Infered from `Number`** + ```ts fn( @Option("x") @@ -94,7 +104,8 @@ class DiscordBot { ``` - `"ROLE"` - **Infered from `Role`** + **Infered from `Role`** + ```ts fn( @Option("x") @@ -103,7 +114,8 @@ class DiscordBot { ``` - `"USER"` - **Infered from `User` (or `ClientUser`, not recommended)** + **Infered from `User` (or `ClientUser`, not recommended)** + ```ts fn( @Option("x") @@ -112,7 +124,8 @@ class DiscordBot { ``` - `"CHANNEL"` - **Infered from `Channel` (or `TextChannel` / `VoiceChannel`, not recommended)** + **Infered from `Channel` (or `TextChannel` / `VoiceChannel`, not recommended)** + ```ts fn( @Option("x") @@ -120,7 +133,8 @@ class DiscordBot { ``` - `"MENTIONABLE"` - **No inferance, use:** + **No inferance, use:** + ```ts fn( @Option("x", "MENTIONABLE") @@ -130,11 +144,11 @@ class DiscordBot { - `"SUB_COMMAND"` No inferance, use [@Group](/decorators/group/) - - `"SUB_COMMAND_GROUP"` No inferance, use [@Group](/decorators/group/) ## Signature + ```ts Option(name: string); Option(name: string, type: OptionValueType | OptionType); @@ -143,45 +157,49 @@ Option(name: string, type: OptionValueType | OptionType, params: OptionParams); ``` ## Params + The parameters of an @Option is an object as the last parameter ### Description + `string` -`OPTION_NAME - OPTION_TYPE` by default +`OPTION_NAME - OPTION_TYPE` by default You can set the description of the option ### Required + `bool` -`false` by default +`false` by default The option is required or not ## Set the default required value + if you want to set the default required value, you can use `client.requiredByDefault` ```ts const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], classes: [ `${__dirname}/*Discord.ts`, // glob string to load the classes `${__dirname}/*Discord.js`, // If you compile using "tsc" the file extension change to .js ], silent: false, - requiredByDefault: true + requiredByDefault: true, }); ``` ## Autocompletion (Option's choices) + You can use the [@Choice](/decorators/choice/) decorator ## Option order + **You have to put required options before optional ones** -Or you will get this error: +Or you will get this error: + ``` (node:64399) UnhandledPromiseRejectionWarning: DiscordAPIError: Invalid Form Body options[1]: Required options must be placed before non-required options diff --git a/docs/src/decorators/permission.md b/docs/src/decorators/permission.md index bbaa6feb..01c58918 100644 --- a/docs/src/decorators/permission.md +++ b/docs/src/decorators/permission.md @@ -1,4 +1,5 @@ # @Permission + You can set some permissions to your Slash commands The permissions are based on a **role id** or **user id** that you specify on the @Permission decorator @@ -13,7 +14,8 @@ Permissions are only available for Guild specific Slash commands > You can manage it by yourself using your own the Slashes `Client` API and creating your own `client.initSlashes()` implementation ## Setup permissions -You just decorate your parameter with one or multiple @Permission ! + +You just decorate your parameter with one or multiple @Permission ! ```ts @Discord() @@ -21,41 +23,43 @@ class DiscordBot { @Permission("USER_ID", "USER") // Only the role that has this USER_ID can use this command @Permission("ROLE_ID", "ROLE") // Only the role that has this ROLE_ID can use this command @Slash("hello") - private hello( - ) { + private hello() { // ... } } ``` ## Permissions at class level + You can set the permissions for all @Slash inside the class by decorating the class with @Permission + ```ts @Discord() @Permission("USER_ID", "USER") // Only the role that has this USER_ID can use this command @Permission("ROLE_ID", "ROLE") // Only the role that has this ROLE_ID can use this command class DiscordBot { @Slash("hello") // Only the role that has this ROLE_ID can use this command - private hello( - ) { + private hello() { // ... } @Slash("hello2") // Only the role that has this ROLE_ID can use this command - private hello2( - ) { + private hello2() { // ... } } ``` ## Params + `@Permission(id: string, type: "USER" | "ROLE")` ### id + `string` The id if the user or role ### type + `"ROLE" | "USER"` It specify if the permission is given to a user or a role diff --git a/docs/src/decorators/selectmenu.md b/docs/src/decorators/selectmenu.md index 2be83cd8..2edc18ca 100644 --- a/docs/src/decorators/selectmenu.md +++ b/docs/src/decorators/selectmenu.md @@ -2,4 +2,4 @@ ::: danger doc for `@SelectMenu` is not ready -::: \ No newline at end of file +::: diff --git a/docs/src/decorators/slash.md b/docs/src/decorators/slash.md index f8d60668..0096dab2 100644 --- a/docs/src/decorators/slash.md +++ b/docs/src/decorators/slash.md @@ -1,4 +1,5 @@ # @Slash - Discord commands + Discord has it's own command system now, you can simply declare commands and use Slash commands this way ```ts @@ -7,8 +8,7 @@ import { Discord, Slash } from "@typeit/discord"; @Discord() abstract class AppDiscord { @Slash("hello") - private hello( - ) { + private hello() { // ... } } @@ -18,6 +18,7 @@ abstract class AppDiscord { It require a bit of configuration at you Client initialization. You have to manualy execute and initialize your Slash commands by using: + - `client.initSlashes()` - `client.executeInteraction(interaction)` @@ -29,10 +30,7 @@ import { Client } from "@typeit/discord"; async function start() { const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], }); client.once("ready", async () => { @@ -55,19 +53,19 @@ start(); ```ts const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], - slashGuilds: process.DEV ? ["GUILD_ID"] : undefined + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + slashGuilds: process.DEV ? ["GUILD_ID"] : undefined, }); ``` + ::: ## Slash API + By using the Client class you can access and manage to Slashes ### Clear slashes from Discord cache + You can remove Slash commands from the Discord cache by using `client.clearSlashes(...guildIDs: string[])` > If you do not specify the guild id you operate on global Slash commands @@ -81,7 +79,9 @@ client.once("ready", async () => { ``` ### Fetch slashes from Discord + or fetch them by using `client.fetchSlashes(guildID: string)` + > If you do not specify the guild id you operate on global Slash commands ```ts @@ -92,12 +92,15 @@ client.once("ready", async () => { ``` ### Get declared slashes + You can retrieve the list of declared Slashes on your application (declared using @Slash) + ```ts const slashes = client.slashes; ``` ### Apply Slash to specific guild globaly + Instead on doing this for all of your @Slash: > You can manage it by yourself using your own the Slashes `Client` API and creating your own `client.initSlashes()` implementation @@ -107,15 +110,13 @@ Instead on doing this for all of your @Slash: abstract class AppDiscord { @Guild("GUILD_ID") @Slash("hello") - private hello( - ) { + private hello() { // ... } @Guild("GUILD_ID") @Slash("bye") - private bye( - ) { + private bye() { // ... } } @@ -126,25 +127,21 @@ You can do: ```ts const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], - slashGuilds: ["GUILD_ID"] + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + slashGuilds: ["GUILD_ID"], }); ``` + ```ts @Discord() abstract class AppDiscord { @Slash("hello") // Applied on GUILD_ID - private hello( - ) { + private hello() { // ... } @Slash("bye") // Applied on GUILD_ID - private bye( - ) { + private bye() { // ... } } @@ -153,28 +150,34 @@ abstract class AppDiscord { ## Params ### Name + `string` The Slash command name ### Description + `string` The Slash command description ### Guilds -`string[]` + +`string[]` The guilds where the command is created ### defaultPermission + `boolean` -`true` by default +`true` by default "You can also set a default_permission on your commands if you want them to be disabled by default when your app is added to a new guild. Setting default_permission to false will disallow anyone in a guild from using the command--even Administrators and guild owners--unless a specific overwrite is configured. It will also disable the command from being usable in DMs." ## Authorize your bot to use Slash commands + On the Discord's developer portal, select your bot, go to the OAuth2 tab and check the box **bot** AND **applications.commands** ![](/discord.ts/authorize1.png) ![](/discord.ts/authorize2.png) ## See also + - [discord.js's documentation with Interactions (Slash commands)](https://discord.js.org/#/docs/main/master/general/welcome) - [Discord's Slash commands interactions](https://discord.com/developers/docs/interactions/slash-commands) diff --git a/docs/src/general/argsof.md b/docs/src/general/argsof.md index fc4610e7..83fda299 100644 --- a/docs/src/general/argsof.md +++ b/docs/src/general/argsof.md @@ -1,15 +1,11 @@ -# ArgsOf +# ArgsOf + `ArgsOf` type your events payload as an array, just pass an event (as string) in the type parameter and it types your array with the related event's parameters You can get the list of the events and the payload type in the ["List of events" section](/general/events/) ```ts -import { - Discord, - On, - Client, - ArgsOf -} from "@typeit/discord"; +import { Discord, On, Client, ArgsOf } from "@typeit/discord"; @Discord() abstract class AppDiscord { @@ -24,7 +20,7 @@ abstract class AppDiscord { @On("channelUpdate") private onMessage( // The type of channel1 and channel2 is TextChannel - [channel1, channel2]: ArgsOf<"channelUpdate">, + [channel1, channel2]: ArgsOf<"channelUpdate"> ) { // ... } diff --git a/docs/src/general/client.md b/docs/src/general/client.md index cba7edac..1abf60b4 100644 --- a/docs/src/general/client.md +++ b/docs/src/general/client.md @@ -1,13 +1,15 @@ # Client + It manage all the operations between your app, Discord's API and discord.js ## Setup and start your application + In order to start your application, you must use the discord.**ts**'s Client (not the client that is provided by discord.**js**!). It works the same as the discord.**js**'s Client (same methods, properties, ...). - **`intents` (required)** `Intents[]` - [see Intents](#intents) + [see Intents](#intents) - **`botId`** `string` (`bot` by default) @@ -22,19 +24,19 @@ It works the same as the discord.**js**'s Client (same methods, properties, ...) Indicate the class jacket of your classes containing the `@Discord` decorator. It accepts a list of classes or of (glob) paths - **`silent`** - `boolean` (`true` by default) + `boolean` (`true` by default) Allows you to disable your event information at startup -- **`requiredByDefault`** +- **`requiredByDefault`** `boolean` (`false` by default) - The `@Option` are required by default + The `@Option` are required by default -- **`guards`** +- **`guards`** `GuardFunction[]` Global guards, it's an array of functions -- **`slashGuilds`** - `string[]` +- **`slashGuilds`** + `string[]` The slash commands are executed only on this list of guilds by default **You must specify the glob path(s) where your decorated classes are** @@ -48,10 +50,7 @@ import { Client } from "@typeit/discord"; async function start() { const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], classes: [ `${__dirname}/*Discord.ts`, // glob string to load the classes `${__dirname}/*Discord.js`, // If you compile using "tsc" the file extension change to .js @@ -66,31 +65,31 @@ start(); ``` ## Intents + You must specify the "**intents**" of your bot when you initialize the Client, it specify which informations your bot receive from the Discord's servers, **it's different from the permissions** -*Maintaining a stateful application can be difficult when it comes to the amount of data you're expected to process, especially at scale. Gateway Intents are a system to help you lower that computational burden.* +_Maintaining a stateful application can be difficult when it comes to the amount of data you're expected to process, especially at scale. Gateway Intents are a system to help you lower that computational burden._ -*When identifying to the gateway, you can specify an intents parameter which allows you to conditionally subscribe to pre-defined "intents", groups of events defined by Discord. If you do not specify a certain intent, you will not receive any of the gateway events that are batched into that group.* +_When identifying to the gateway, you can specify an intents parameter which allows you to conditionally subscribe to pre-defined "intents", groups of events defined by Discord. If you do not specify a certain intent, you will not receive any of the gateway events that are batched into that group._ ::: danger If an event of your app isn't triggered, you probably missed an Intent ::: ### Basic intents, just text messages + ```ts import { Intents } from "discord.js"; const client = new Client({ botId: "test", - intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - ], + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], // ... }); ``` ### Voice activity intent, the ability to speak + ```ts import { Intents } from "discord.js"; @@ -106,9 +105,11 @@ const client = new Client({ ``` ### List of all the intents -[You can find the complete list here](https://discord.com/developers/docs/topics/gateway#list-of-intents) -**Most used ones** +[You can find the complete list here](https://discord.com/developers/docs/topics/gateway#list-of-intents) + +**Most used ones** + - GUILDS - GUILD_MEMBERS - GUILD_BANS @@ -123,7 +124,7 @@ const client = new Client({ - GUILD_MESSAGE_TYPING - DIRECT_MESSAGES - DIRECT_MESSAGE_REACTIONS -- DIRECT_MESSAGE_TYPING +- DIRECT_MESSAGE_TYPING ```ts import { Intents } from "discord.js"; @@ -150,8 +151,10 @@ const client = new Client({ ``` ## Slashes API + It also implements an [API for your @Slash](/decorators/slash.html#slash-api) ## See also + - [discord.js documentation](https://discord.js.org/#/docs/main/stable/class/Intents) - [Discord's documentation](https://discord.com/developers/docs/topics/gateway#list-of-intents) diff --git a/docs/src/general/debugging.md b/docs/src/general/debugging.md index 55ba60e6..83e3c924 100644 --- a/docs/src/general/debugging.md +++ b/docs/src/general/debugging.md @@ -1,33 +1,33 @@ # Use the VSCode debugger to debug your bot 1. Create the `.vscode/launch.json` file at your project root directory if the file do not already exists - 2. Install ts-node as a dev dependency + ``` npm i -D ts-node ``` 3. Copy paste this into your `launch.json` file + ```json - { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Debug bot", - "protocol": "inspector", - "args": ["${workspaceRoot}/PATH_TO_YOUR_MAIN.ts"], - "cwd": "${workspaceRoot}", - "runtimeArgs": ["-r", "ts-node/register/transpile-only"], - "internalConsoleOptions": "neverOpen" - } - ] - } + { + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Debug bot", + "protocol": "inspector", + "args": ["${workspaceRoot}/PATH_TO_YOUR_MAIN.ts"], + "cwd": "${workspaceRoot}", + "runtimeArgs": ["-r", "ts-node/register/transpile-only"], + "internalConsoleOptions": "neverOpen" + } + ] + } ``` - -4. You can now put some breakpoints, go to the debug tab in VSCode and launch your bot +4. You can now put some breakpoints, go to the debug tab in VSCode and launch your bot diff --git a/docs/src/general/events.md b/docs/src/general/events.md index ec2de92a..08cc96e9 100644 --- a/docs/src/general/events.md +++ b/docs/src/general/events.md @@ -1,9 +1,9 @@ # List of the discord.js events + Here is all the `DiscordEvents` and their parameters (`discord.js`) - **channelCreate** `[Channel]` - - **channelDelete** `[Channel | PartialDMChannel]` @@ -15,10 +15,8 @@ Here is all the `DiscordEvents` and their parameters (`discord.js`) - **debug** `[string]` - - **warn** `[string]` - - **disconnect** `[any, number]` diff --git a/docs/src/general/metadatastorage.md b/docs/src/general/metadatastorage.md index e245f918..d4e6d022 100644 --- a/docs/src/general/metadatastorage.md +++ b/docs/src/general/metadatastorage.md @@ -1,8 +1,9 @@ # MetadataStorage + The MetadataStorage store all the informations about your decorators, you can get the informations related to them by using `MetadataStorage.instance` ```ts -import { MetadataStorage } from "@typeit/discord.ts" +import { MetadataStorage } from "@typeit/discord.ts"; MetadataStorage.instance.slashes; MetadataStorage.instance.events; diff --git a/docs/src/general/sharding.md b/docs/src/general/sharding.md index 7a50a213..99c23b1b 100644 --- a/docs/src/general/sharding.md +++ b/docs/src/general/sharding.md @@ -6,9 +6,9 @@ Sharding your bot with `@typeit/discord`. ## Purpose -Sharding is the process of splitting your main discord process into multiple shards to help with the load when your bot is in 2,500+ guilds. discord.**js** has recommended to start making updates for sharding at around 2,000 guilds. +Sharding is the process of splitting your main discord process into multiple shards to help with the load when your bot is in 2,500+ guilds. discord.**js** has recommended to start making updates for sharding at around 2,000 guilds. -[Discord.js Sharding Guide](https://discordjs.guide/sharding/#when-to-shard) +[Discord.js Sharding Guide](https://discordjs.guide/sharding/#when-to-shard) When you hit that milestone and need to begin the sharding process this guide will serve as a starting document to help you get set up. @@ -19,9 +19,9 @@ When you hit that milestone and need to begin the sharding process this guide wi ### What if my bot is in less than 2,000 servers? -discord.**js** has stated +discord.**js** has stated -"*Sharding is only necessary at 2,500 guilds—at that point, Discord will not allow your bot to login without sharding. With that in mind, you should consider this when your bot is around 2,000 guilds, which should be enough time to get this working. Contrary to popular belief, sharding itself is very simple. It can be complex depending on your bot's needs, however. If your bot is in a total of 2,000 or more servers, then please continue with this guide. Otherwise, it may be a good idea to wait until then.*" +"_Sharding is only necessary at 2,500 guilds—at that point, Discord will not allow your bot to login without sharding. With that in mind, you should consider this when your bot is around 2,000 guilds, which should be enough time to get this working. Contrary to popular belief, sharding itself is very simple. It can be complex depending on your bot's needs, however. If your bot is in a total of 2,000 or more servers, then please continue with this guide. Otherwise, it may be a good idea to wait until then._" However if you are curious you may continue to read this doc! But don't worry about sharding until 2,000 guilds. Focus on building a quality bot as sharding adds more complexity. @@ -44,12 +44,11 @@ I found success with using this `tsconfig.json` "forceConsistentCasingInFileNames": true, "lib": ["es2020", "esnext.asynciterable"], "moduleResolution": "node", - "outDir": "./src/build", + "outDir": "./src/build" }, "exclude": ["node_modules"], "indent": [true, "spaces", 2] } - ``` If you are receiving errors that complain about imports. Try using the following import where the compiler complains about the import. @@ -94,17 +93,14 @@ Read the [discord.js sharding docs](https://discordjs.guide/sharding/). You will make a new class in the `shard.bot.ts` file. I have named my class ShardBot ```typescript -export class ShardBot { - -} +export class ShardBot {} ``` Inside this class I have defined a `static start` method that gets called outside of the ShardBot class. ```typescript export class ShardBot { - static start(): void { - } + static start(): void {} } ShardBot.start(); @@ -118,7 +114,6 @@ import { environment } from "../../environments/environment"; export class ShardBot { static start(): void { - const manager = new ShardingManager("./src/build/src/app/entry.bot.js", { token: environment.DISCORD_TOKEN, }); @@ -126,7 +121,7 @@ export class ShardBot { manager.on("shardCreate", (shard) => { console.log(`Launched shard ${shard.id}`); }); - + manager.spawn(); } } @@ -143,7 +138,7 @@ Now that your bot compiles and has the shard file we can run the bot with the sh `node build/app/shard.bot.js` -will start the shard here. +will start the shard here. ::: warning Make sure you provide the correct path to the shard file when running with node. diff --git a/docs/src/index.md b/docs/src/index.md index b9c5a8d8..ffa90601 100755 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -6,11 +6,11 @@ title: discord.ts actionText: Quick Start → actionLink: /installation/ features: -- title: Decorators - details: Create your bot using Typescript decorators ! -- title: Slash commands - details: Implement a Discord's Slash commands system simply ! -- title: discord.js support - details: You can use discord.js along discord.ts without any problems ! + - title: Decorators + details: Create your bot using Typescript decorators ! + - title: Slash commands + details: Implement a Discord's Slash commands system simply ! + - title: discord.js support + details: You can use discord.js along discord.ts without any problems ! footer: Made by discord.ts team with ❤️ --- diff --git a/docs/src/installation/README.md b/docs/src/installation/README.md index 1b8f6a8c..7996453e 100644 --- a/docs/src/installation/README.md +++ b/docs/src/installation/README.md @@ -24,14 +24,15 @@ This module is an extension of **[discord.**js**](https://discordjs.guide/)**, s This library allows you to use TypeScript decorators on discord.**js**, it simplify your code and improve the readability ! ## Easy setup - starter project + 1. Clone this project `git clone https://github.com/owencalvin/discord.js-template` 2. Run `npm i` - 3. And let's go, everything was done for you! 🚀 ## Installation + Use [npm](https://www.npmjs.com/package/@typeit/discord) or yarn to install **@typeit/discord** with **discord.js** > You use the npm @slash tag to install version of discord.ts **@typeit/discord** that includes Slash commands (this version) @@ -39,11 +40,13 @@ Use [npm](https://www.npmjs.com/package/@typeit/discord) or yarn to install **@t ::: danger For the moment discord.**js** didn't release the v13 on npm, you have to install it this way (You also have to install "reflect-metadata" for the decorators) + ```sh -npm i @typeit/discord@slash reflect-metadata https://github.com/discordjs/discord.js +npm i @typeit/discord@slash reflect-metadata https://github.com/discordjs/discord.js ``` Install your TypeScript dev dependencies too + ```sh npm i -D @types/node typescript tslib ``` @@ -56,7 +59,7 @@ And you should see this in your package.json "dependencies": { "@typeit/discord": "^X.X.X", "discord.js": "github:discordjs/discord.js", - "reflect-metadata": "^0.1.13", + "reflect-metadata": "^0.1.13" }, "devDependencies": { "@types/node": "^15.0.3", @@ -66,10 +69,12 @@ And you should see this in your package.json // ... } ``` + ::: ## Execution environnement -To start your bot you can compile your code into JavaScript with TypeScript using the `tsc` command or simple use [ts-node](https://www.npmjs.com/package/ts-node). + +To start your bot you can compile your code into JavaScript with TypeScript using the `tsc` command or simple use [ts-node](https://www.npmjs.com/package/ts-node). ::: danger Be aware that if you compile your code into JavaScript with `tsc` you have to specify .js files when you instanciate your Client @@ -87,9 +92,11 @@ const client = new Client({ guards: [NotBot, Prefix("!")], }); ``` + ::: ## tsconfig.json + Your tsconfig.json file should look like this: ```json @@ -112,7 +119,9 @@ Your tsconfig.json file should look like this: ``` ## reflect-metadata + You have to import the reflect-metadata module on your main file for the decorators (for the reflection) + ```ts import "reflect-metadata"; import { Client } from "@typeit/discord"; @@ -125,14 +134,16 @@ start(); ``` ## Need help? -**[Simply join the Discord server](https://discord.gg/VDjwu8E)** + +**[Simply join the Discord server](https://discord.gg/VDjwu8E)** You can also find help with the [different projects that use discord.ts](https://github.com/OwenCalvin/discord.ts/network/dependents?package_id=UGFja2FnZS00Njc1MzYwNzU%3D) and in the [examples folder](https://github.com/OwenCalvin/discord.ts/tree/master/examples) ## See also + - [discord.js's documentation with Interactions (Slash commands)](https://discord.js.org/#/docs/main/master/general/welcome) - [Discord's Slash commands interactions](https://discord.com/developers/docs/interactions/slash-commands) ## Next step -[Setup and start your application 🚀](/general/client/) +[Setup and start your application 🚀](/general/client/) From bb30bb82c124513adc45299a34a5fc0c4d9064c3 Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 12:54:46 +0530 Subject: [PATCH 105/106] guard example update --- examples/guards/discords/AppDiscord.ts | 6 ++--- examples/guards/guards/Say.ts | 32 ++++++++++++++------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/examples/guards/discords/AppDiscord.ts b/examples/guards/discords/AppDiscord.ts index ca719431..802202b2 100644 --- a/examples/guards/discords/AppDiscord.ts +++ b/examples/guards/discords/AppDiscord.ts @@ -1,18 +1,18 @@ import { CommandInteraction } from "discord.js"; import { Discord, On, Client, ArgsOf, Guard, Slash } from "../../../src"; -import { Say } from "../guards/Say"; +import { NotBot } from "../guards/Say"; @Discord() export abstract class AppDiscord { @On("messageCreate") - @Guard(Say("hello")) + @Guard(NotBot) // eslint-disable-next-line @typescript-eslint/no-unused-vars onMessage([message]: ArgsOf<"messageCreate">, _client: Client) { console.log(message.content); } @Slash("hello") - @Guard(Say("hello")) + @Guard(NotBot) // eslint-disable-next-line @typescript-eslint/no-unused-vars hello(interaction: CommandInteraction, _client: Client) { console.log(interaction); diff --git a/examples/guards/guards/Say.ts b/examples/guards/guards/Say.ts index 2b678d37..008bcb9a 100644 --- a/examples/guards/guards/Say.ts +++ b/examples/guards/guards/Say.ts @@ -1,18 +1,20 @@ -import { CommandInteraction, Message } from "discord.js"; -import { GuardFunction } from "../../../src"; +import { CommandInteraction, MessageReaction, VoiceState } from "discord.js"; +import { ArgsOf, GuardFunction } from "../../../src"; -export const Say = (text: string) => { - // do not use ArgOf it will throw undefined error cause of type error - const guard: GuardFunction = async ( - messageOrCommand, - _client, - next, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _nextObj - ) => { - messageOrCommand.channel.send(text); +export const NotBot: GuardFunction< + | ArgsOf<"messageCreate" | "messageReactionAdd" | "voiceStateUpdate"> + | CommandInteraction +> = async (arg, client, next) => { + const argObj = arg instanceof Array ? arg[0] : arg; + const user = + argObj instanceof CommandInteraction + ? argObj.user + : argObj instanceof MessageReaction + ? argObj.message.author + : argObj instanceof VoiceState + ? argObj.member.user + : argObj.author; + if (!user?.bot) { await next(); - }; - - return guard; + } }; From 150a23938f631b709ebe9e961cfc32e9f7f40942 Mon Sep 17 00:00:00 2001 From: iorp Date: Wed, 7 Jul 2021 13:13:00 +0530 Subject: [PATCH 106/106] update guard example --- examples/guards/discords/AppDiscord.ts | 2 +- examples/guards/guards/{Say.ts => NotBot.ts} | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) rename examples/guards/guards/{Say.ts => NotBot.ts} (95%) diff --git a/examples/guards/discords/AppDiscord.ts b/examples/guards/discords/AppDiscord.ts index 802202b2..48e52941 100644 --- a/examples/guards/discords/AppDiscord.ts +++ b/examples/guards/discords/AppDiscord.ts @@ -1,6 +1,6 @@ import { CommandInteraction } from "discord.js"; import { Discord, On, Client, ArgsOf, Guard, Slash } from "../../../src"; -import { NotBot } from "../guards/Say"; +import { NotBot } from "../guards/NotBot"; @Discord() export abstract class AppDiscord { diff --git a/examples/guards/guards/Say.ts b/examples/guards/guards/NotBot.ts similarity index 95% rename from examples/guards/guards/Say.ts rename to examples/guards/guards/NotBot.ts index 008bcb9a..782ea41f 100644 --- a/examples/guards/guards/Say.ts +++ b/examples/guards/guards/NotBot.ts @@ -1,6 +1,8 @@ import { CommandInteraction, MessageReaction, VoiceState } from "discord.js"; import { ArgsOf, GuardFunction } from "../../../src"; +// Example by @AndyClausen + export const NotBot: GuardFunction< | ArgsOf<"messageCreate" | "messageReactionAdd" | "voiceStateUpdate"> | CommandInteraction