discordthing 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/build/bot.d.ts +37 -0
- package/build/bot.js +166 -0
- package/build/bot.js.map +1 -0
- package/build/commands/command.d.ts +111 -0
- package/build/commands/command.js +176 -0
- package/build/commands/command.js.map +1 -0
- package/build/commands/diff.d.ts +5 -0
- package/build/commands/diff.js +42 -0
- package/build/commands/diff.js.map +1 -0
- package/build/commands/index.d.ts +2 -0
- package/build/commands/index.js +2 -0
- package/build/commands/index.js.map +1 -0
- package/build/commands/registration.d.ts +10 -0
- package/build/commands/registration.js +40 -0
- package/build/commands/registration.js.map +1 -0
- package/build/context.d.ts +9 -0
- package/build/context.js +9 -0
- package/build/context.js.map +1 -0
- package/build/events/index.d.ts +2 -0
- package/build/events/index.js +2 -0
- package/build/events/index.js.map +1 -0
- package/build/events/listener.d.ts +24 -0
- package/build/events/listener.js +14 -0
- package/build/events/listener.js.map +1 -0
- package/build/index.d.ts +7 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/logger.d.ts +8 -0
- package/build/logger.js +2 -0
- package/build/logger.js.map +1 -0
- package/build/options/index.d.ts +3 -0
- package/build/options/index.js +2 -0
- package/build/options/index.js.map +1 -0
- package/build/options/option.d.ts +116 -0
- package/build/options/option.js +101 -0
- package/build/options/option.js.map +1 -0
- package/build/options/options.d.ts +78 -0
- package/build/options/options.js +169 -0
- package/build/options/options.js.map +1 -0
- package/build/permissions.d.ts +17 -0
- package/build/permissions.js +38 -0
- package/build/permissions.js.map +1 -0
- package/build/plugin.d.ts +20 -0
- package/build/plugin.js +22 -0
- package/build/plugin.js.map +1 -0
- package/build/utility-types.d.ts +15 -0
- package/build/utility-types.js +2 -0
- package/build/utility-types.js.map +1 -0
- package/build/utils.d.ts +2 -0
- package/build/utils.js +19 -0
- package/build/utils.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/commands/command.ts"],"names":[],"mappings":"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","sourcesContent":["import { err, NONE, type ReturnResult } from \"@l3dev/result\";\nimport {\n\tApplicationCommandOptionType,\n\tInteractionContextType,\n\tSlashCommandBuilder,\n\tSlashCommandSubcommandBuilder,\n\ttype ChatInputCommandInteraction,\n\ttype CommandInteractionOptionResolver,\n\ttype SharedNameAndDescription,\n\ttype SharedSlashCommandOptions\n} from \"discord.js\";\n\nimport type { GenericCtx } from \"../context.js\";\nimport type { Args, OptionDefinitions } from \"../options/index.js\";\nimport {\n\tAttachmentOption,\n\tBooleanOption,\n\tBuilderOption,\n\tChannelOption,\n\tIntegerOption,\n\tMentionableOption,\n\tNumberOption,\n\tRoleOption,\n\tStringOption,\n\tUserOption\n} from \"../options/options.js\";\nimport type { Expand, MaybePromise } from \"../utility-types.js\";\n\nexport type CommandCtx = Expand<\n\tGenericCtx & {\n\t\tinteraction: ChatInputCommandInteraction;\n\t}\n>;\n\nexport type ArgsArrayForOptions<Options extends OptionDefinitions> = [Options] extends [\n\tOptionDefinitions\n]\n\t? [args: Args<Options>]\n\t: [];\n\nexport type CommandMeta<Name extends string> = {\n\t/**\n\t * The name of the command.\n\t */\n\tname: Name;\n\t/**\n\t * The description of the command.\n\t */\n\tdescription?: string;\n\t/**\n\t * Whether the command is NSFW.\n\t */\n\tnsfw?: boolean;\n\t/**\n\t * The contexts in which the command can be used.\n\t *\n\t * @default [InteractionContextType.Guild]\n\t */\n\tcontexts?: InteractionContextType[];\n};\n\nexport type SubcommandMeta<Name extends string> = {\n\t/**\n\t * The name of the command.\n\t */\n\tname: Name;\n\t/**\n\t * The description of the command.\n\t */\n\tdescription?: string;\n};\n\ntype GenericCommandHandler = (\n\tctx: CommandCtx,\n\t...args: any[]\n) => MaybePromise<ReturnResult<any, any>>;\n\nexport class Command<\n\tName extends string,\n\tBuilder extends SharedNameAndDescription & SharedSlashCommandOptions<any>\n> {\n\treadonly name: Name;\n\n\tprivate options: OptionDefinitions | null = null;\n\tprivate subcommands: Record<string, Command<string, SlashCommandSubcommandBuilder>> | null = null;\n\tprivate handler: GenericCommandHandler | null = null;\n\n\tconstructor(\n\t\tprotected builder: Builder,\n\t\tmeta: CommandMeta<Name>\n\t) {\n\t\tthis.name = meta.name;\n\n\t\tbuilder = builder.setName(meta.name);\n\t\tif (meta.description) {\n\t\t\tbuilder = builder.setDescription(meta.description);\n\t\t}\n\t\tif (builder instanceof SlashCommandBuilder) {\n\t\t\tlet commandBuilder = builder as SlashCommandBuilder;\n\t\t\tif (meta.nsfw) {\n\t\t\t\tcommandBuilder = commandBuilder.setNSFW(meta.nsfw);\n\t\t\t}\n\t\t\tcommandBuilder = commandBuilder.setContexts(meta.contexts ?? [InteractionContextType.Guild]);\n\t\t\tbuilder = commandBuilder as Builder & SlashCommandBuilder;\n\t\t}\n\t\tthis.builder = builder;\n\t}\n\n\tasync execute(ctx: CommandCtx): Promise<ReturnResult<any, any>> {\n\t\tif (this.subcommands) {\n\t\t\tconst continueResult = this.handler ? await this.handler(ctx) : NONE;\n\t\t\tif (!continueResult.ok || !continueResult.value) {\n\t\t\t\treturn continueResult;\n\t\t\t}\n\n\t\t\tconst subcommandName = ctx.interaction.options.getSubcommand(true);\n\t\t\tconst subcommand = this.subcommands[subcommandName];\n\t\t\tif (!subcommand) {\n\t\t\t\treturn err(\"UNKNOWN_SUBCOMMAND\", {\n\t\t\t\t\tname: subcommandName\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn await subcommand.execute(ctx);\n\t\t}\n\n\t\tconst args = this.parseOptions(ctx.interaction.options);\n\n\t\treturn await this.handler!(ctx, args);\n\t}\n\n\t/** @internal */\n\tprivate parseOptions(options: Partial<CommandInteractionOptionResolver>) {\n\t\tconst args: Record<string, any> = {};\n\n\t\tfor (const [name, option] of Object.entries(this.options ?? {})) {\n\t\t\tconst required = option.isOptional === \"required\";\n\n\t\t\tlet value: any = null;\n\t\t\tif (options.getAttachment && option instanceof AttachmentOption) {\n\t\t\t\tvalue = options.getAttachment(name, required);\n\t\t\t} else if (options.getBoolean && option instanceof BooleanOption) {\n\t\t\t\tvalue = options.getBoolean(name, required);\n\t\t\t} else if (options.getChannel && option instanceof ChannelOption) {\n\t\t\t\tvalue = options.getChannel(name, required, option.getBuilder().channel_types);\n\t\t\t} else if (options.getInteger && option instanceof IntegerOption) {\n\t\t\t\tvalue = options.getInteger(name, required);\n\t\t\t} else if (options.getMentionable && option instanceof MentionableOption) {\n\t\t\t\tvalue = options.getMentionable(name, required);\n\t\t\t} else if (options.getNumber && option instanceof NumberOption) {\n\t\t\t\tvalue = options.getNumber(name, required);\n\t\t\t} else if (options.getRole && option instanceof RoleOption) {\n\t\t\t\tvalue = options.getRole(name, required);\n\t\t\t} else if (options.getString && option instanceof StringOption) {\n\t\t\t\tvalue = options.getString(name, required);\n\t\t\t} else if (options.getUser && option instanceof UserOption) {\n\t\t\t\tvalue = options.getUser(name, required);\n\t\t\t}\n\n\t\t\tif (value === null || value === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\targs[name] = value;\n\t\t}\n\n\t\treturn args;\n\t}\n\n\t/** @internal */\n\tgetContexts() {\n\t\tif (!(this.builder instanceof SlashCommandBuilder)) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this.builder.contexts ?? [InteractionContextType.Guild];\n\t}\n\n\t/** @internal */\n\tgetBuilder() {\n\t\treturn this.builder;\n\t}\n\n\t/** @internal */\n\tsetOptions(options: OptionDefinitions) {\n\t\tthis.options = options;\n\n\t\tfor (const [name, option] of Object.entries(options)) {\n\t\t\tif (option instanceof BuilderOption) {\n\t\t\t\tthis.addOption(name, option);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tprivate addOption(name: string, option: BuilderOption<any, any, any>) {\n\t\tlet optionBuilder = option.getBuilder().setName(name);\n\t\tif (!optionBuilder.description) {\n\t\t\toptionBuilder = optionBuilder.setDescription(`${name} option.`);\n\t\t}\n\n\t\tif (optionBuilder.type === ApplicationCommandOptionType.Attachment) {\n\t\t\tthis.builder = this.builder.addAttachmentOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Boolean) {\n\t\t\tthis.builder = this.builder.addBooleanOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Channel) {\n\t\t\tthis.builder = this.builder.addChannelOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Integer) {\n\t\t\tthis.builder = this.builder.addIntegerOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Mentionable) {\n\t\t\tthis.builder = this.builder.addMentionableOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Number) {\n\t\t\tthis.builder = this.builder.addNumberOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.Role) {\n\t\t\tthis.builder = this.builder.addRoleOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.String) {\n\t\t\tthis.builder = this.builder.addStringOption(optionBuilder);\n\t\t} else if (optionBuilder.type === ApplicationCommandOptionType.User) {\n\t\t\tthis.builder = this.builder.addUserOption(optionBuilder);\n\t\t}\n\t}\n\n\t/** @internal */\n\tsetSubcommands(subcommands: Command<string, SlashCommandSubcommandBuilder>[]) {\n\t\tif (!(this.builder instanceof SlashCommandBuilder)) {\n\t\t\tthrow new Error(\"Subcommands can only be set on a SlashCommandBuilder\");\n\t\t}\n\n\t\tthis.subcommands = subcommands.reduce(\n\t\t\t(acc, subcommand) => ({\n\t\t\t\t...acc,\n\t\t\t\t[subcommand.name]: subcommand\n\t\t\t}),\n\t\t\t{}\n\t\t);\n\t}\n\n\t/** @internal */\n\tsetHandler(handler: GenericCommandHandler) {\n\t\tthis.handler = handler;\n\t}\n}\n\nexport function command<Name extends string, Options extends OptionDefinitions>(command: {\n\t/**\n\t * Metadata for this command.\n\t */\n\tmeta: CommandMeta<Name>;\n\t/**\n\t * Options for the command.\n\t *\n\t * Examples:\n\t *\n\t * ```\n\t * options: {}\n\t * options: { message: o.string() }\n\t * options: { message: o.string().union(o.choice(\"hello\"), o.choice(\"world\")) }\n\t * options: { message: o.string(), count: o.integer() }\n\t * ```\n\t */\n\toptions?: Options;\n\t/**\n\t * The implementation for this command.\n\t */\n\thandler: (\n\t\tctx: CommandCtx,\n\t\t...args: ArgsArrayForOptions<Options>\n\t) => MaybePromise<ReturnResult<any, any>>;\n}): Command<Name, SlashCommandBuilder>;\nexport function command<Name extends string>(command: {\n\t/**\n\t * Metadata for this command.\n\t */\n\tmeta: CommandMeta<Name>;\n\t/**\n\t * Subcommands for the command.\n\t */\n\tsubcommands: Command<string, SlashCommandSubcommandBuilder>[];\n\t/**\n\t * The middleware for this command with subcommands.\n\t */\n\tmiddleware?: (ctx: CommandCtx) => MaybePromise<ReturnResult<boolean, any>>;\n}): Command<Name, SlashCommandBuilder>;\nexport function command<Name extends string, Options extends OptionDefinitions>(\n\tdata: {\n\t\tmeta: CommandMeta<Name>;\n\t} & (\n\t\t| {\n\t\t\t\toptions?: Options;\n\t\t\t\thandler: (\n\t\t\t\t\tctx: CommandCtx,\n\t\t\t\t\t...args: ArgsArrayForOptions<Options>\n\t\t\t\t) => MaybePromise<ReturnResult<any, any>>;\n\t\t }\n\t\t| {\n\t\t\t\tsubcommands: Command<string, SlashCommandSubcommandBuilder>[];\n\t\t\t\tmiddleware?: (ctx: CommandCtx) => MaybePromise<ReturnResult<boolean, any>>;\n\t\t }\n\t)\n): Command<Name, SlashCommandBuilder> {\n\tconst command = new Command(new SlashCommandBuilder(), data.meta);\n\n\tif (\"options\" in data && data.options) {\n\t\tcommand.setOptions(data.options);\n\t\tcommand.setHandler(data.handler);\n\t} else if (\"subcommands\" in data) {\n\t\tcommand.setSubcommands(data.subcommands);\n\t\tif (data.middleware) {\n\t\t\tcommand.setHandler(data.middleware);\n\t\t}\n\t}\n\n\treturn command;\n}\n\nexport function subcommand<Name extends string, Options extends OptionDefinitions>(command: {\n\t/**\n\t * Metadata for this command.\n\t */\n\tmeta: SubcommandMeta<Name>;\n\t/**\n\t * Options for the command.\n\t *\n\t * Examples:\n\t *\n\t * ```\n\t * options: {}\n\t * options: { message: o.string() }\n\t * options: { message: o.string().union(o.choice(\"hello\"), o.choice(\"world\")) }\n\t * options: { message: o.string(), count: o.integer() }\n\t * ```\n\t */\n\toptions?: Options;\n\t/**\n\t * The implementation for this command.\n\t */\n\thandler: (\n\t\tctx: CommandCtx,\n\t\t...args: ArgsArrayForOptions<Options>\n\t) => MaybePromise<ReturnResult<any, any>>;\n}): Command<Name, SlashCommandSubcommandBuilder> {\n\tconst subcommand = new Command(new SlashCommandSubcommandBuilder(), command.meta);\n\tif (command.options) {\n\t\tsubcommand.setOptions(command.options);\n\t}\n\tsubcommand.setHandler(command.handler);\n\n\treturn subcommand;\n}\n\nexport type CommandFilter = (\n\tinteraction: ChatInputCommandInteraction,\n\tcommand: Command<string, SlashCommandBuilder>\n) => boolean;\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { APIApplicationCommand, RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord.js";
|
|
2
|
+
export declare function diffCheck({ prev, next }: {
|
|
3
|
+
prev: Omit<APIApplicationCommand, "dm_permission">;
|
|
4
|
+
next: RESTPostAPIChatInputApplicationCommandsJSONBody;
|
|
5
|
+
}): boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function diffCheck({ prev, next }) {
|
|
2
|
+
if (next.name !== prev.name)
|
|
3
|
+
return true;
|
|
4
|
+
if (next.description !== prev.description)
|
|
5
|
+
return true;
|
|
6
|
+
if ((next.nsfw ?? false) !== (prev.nsfw ?? false))
|
|
7
|
+
return true;
|
|
8
|
+
for (const nextOption of next.options ?? []) {
|
|
9
|
+
const prevOption = prev.options?.find((opt) => opt.name === nextOption.name);
|
|
10
|
+
if (!prevOption)
|
|
11
|
+
return true;
|
|
12
|
+
if (nextOption.type !== prevOption.type)
|
|
13
|
+
return true;
|
|
14
|
+
if (nextOption.description !== prevOption.description)
|
|
15
|
+
return true;
|
|
16
|
+
if ((nextOption.required ?? false) !== (prevOption.required ?? false))
|
|
17
|
+
return true;
|
|
18
|
+
if ((nextOption.autocomplete ?? false) !==
|
|
19
|
+
(prevOption.autocomplete ?? false)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (!!nextOption.choices !== !!prevOption.choices) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
if ("choices" in nextOption &&
|
|
26
|
+
"choices" in prevOption &&
|
|
27
|
+
nextOption.choices &&
|
|
28
|
+
prevOption.choices) {
|
|
29
|
+
for (const nextChoice of nextOption.choices) {
|
|
30
|
+
const prevChoice = prevOption.choices.find((choice) => choice.name === nextChoice.name);
|
|
31
|
+
if (!prevChoice)
|
|
32
|
+
return true;
|
|
33
|
+
if (nextChoice.name !== prevChoice.name)
|
|
34
|
+
return true;
|
|
35
|
+
if (nextChoice.value !== prevChoice.value)
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS,CAAC,EACzB,IAAI,EACJ,IAAI,EAIJ;IACA,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/D,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAE7B,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACrD,IAAI,UAAU,CAAC,WAAW,KAAK,UAAU,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QACnE,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEnF,IACC,CAAE,UAAyC,CAAC,YAAY,IAAI,KAAK,CAAC;YAClE,CAAE,UAAyC,CAAC,YAAY,IAAI,KAAK,CAAC,EACjE,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,CAAC,CAAE,UAA+B,CAAC,OAAO,KAAK,CAAC,CAAE,UAA+B,CAAC,OAAO,EAAE,CAAC;YAC/F,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IACC,SAAS,IAAI,UAAU;YACvB,SAAS,IAAI,UAAU;YACvB,UAAU,CAAC,OAAO;YAClB,UAAU,CAAC,OAAO,EACjB,CAAC;YACF,KAAK,MAAM,UAAU,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC7C,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,CAAC,CAAC;gBACxF,IAAI,CAAC,UAAU;oBAAE,OAAO,IAAI,CAAC;gBAE7B,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC;gBACrD,IAAI,UAAU,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK;oBAAE,OAAO,IAAI,CAAC;YACxD,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC","sourcesContent":["import type {\n\tAPIApplicationCommand,\n\tRESTPostAPIChatInputApplicationCommandsJSONBody\n} from \"discord.js\";\n\nexport function diffCheck({\n\tprev,\n\tnext\n}: {\n\tprev: Omit<APIApplicationCommand, \"dm_permission\">;\n\tnext: RESTPostAPIChatInputApplicationCommandsJSONBody;\n}) {\n\tif (next.name !== prev.name) return true;\n\tif (next.description !== prev.description) return true;\n\tif ((next.nsfw ?? false) !== (prev.nsfw ?? false)) return true;\n\n\tfor (const nextOption of next.options ?? []) {\n\t\tconst prevOption = prev.options?.find((opt) => opt.name === nextOption.name);\n\t\tif (!prevOption) return true;\n\n\t\tif (nextOption.type !== prevOption.type) return true;\n\t\tif (nextOption.description !== prevOption.description) return true;\n\t\tif ((nextOption.required ?? false) !== (prevOption.required ?? false)) return true;\n\n\t\tif (\n\t\t\t((nextOption as { autocomplete?: boolean }).autocomplete ?? false) !==\n\t\t\t((prevOption as { autocomplete?: boolean }).autocomplete ?? false)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!!(nextOption as { choices?: [] }).choices !== !!(prevOption as { choices?: [] }).choices) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\n\t\t\t\"choices\" in nextOption &&\n\t\t\t\"choices\" in prevOption &&\n\t\t\tnextOption.choices &&\n\t\t\tprevOption.choices\n\t\t) {\n\t\t\tfor (const nextChoice of nextOption.choices) {\n\t\t\t\tconst prevChoice = prevOption.choices.find((choice) => choice.name === nextChoice.name);\n\t\t\t\tif (!prevChoice) return true;\n\n\t\t\t\tif (nextChoice.name !== prevChoice.name) return true;\n\t\t\t\tif (nextChoice.value !== prevChoice.value) return true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { command, subcommand } from \"./command.js\";\nexport type { CommandCtx, CommandMeta, SubcommandMeta, Command, CommandFilter } from \"./command.js\";\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Client, type REST, type SlashCommandBuilder, type Snowflake } from "discord.js";
|
|
2
|
+
import type { Command } from "./command.js";
|
|
3
|
+
export declare class CommandRegistration {
|
|
4
|
+
private rest;
|
|
5
|
+
private client;
|
|
6
|
+
constructor(rest: REST, client: Client<true>);
|
|
7
|
+
registerGlobalCommands(commands: Command<string, SlashCommandBuilder>[]): Promise<void>;
|
|
8
|
+
registerGuildCommands(guildId: Snowflake, commands: Command<string, SlashCommandBuilder>[]): Promise<void>;
|
|
9
|
+
private registerCommands;
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Routes } from "discord.js";
|
|
2
|
+
import { diffCheck } from "./diff.js";
|
|
3
|
+
export class CommandRegistration {
|
|
4
|
+
rest;
|
|
5
|
+
client;
|
|
6
|
+
constructor(rest, client) {
|
|
7
|
+
this.rest = rest;
|
|
8
|
+
this.client = client;
|
|
9
|
+
}
|
|
10
|
+
async registerGlobalCommands(commands) {
|
|
11
|
+
await this.registerCommands(commands, Routes.applicationCommands(this.client.user.id), (id) => Routes.applicationCommand(this.client.user.id, id));
|
|
12
|
+
}
|
|
13
|
+
async registerGuildCommands(guildId, commands) {
|
|
14
|
+
await this.registerCommands(commands, Routes.applicationGuildCommands(this.client.user.id, guildId), (id) => Routes.applicationGuildCommand(this.client.user.id, guildId, id));
|
|
15
|
+
}
|
|
16
|
+
async registerCommands(commands, route, deleteRoute) {
|
|
17
|
+
const registeredCommands = (await this.rest.get(route));
|
|
18
|
+
const commandsToAdd = [];
|
|
19
|
+
for (const command of commands) {
|
|
20
|
+
const body = command.getBuilder().toJSON();
|
|
21
|
+
const registeredCommand = registeredCommands.find((registeredCommand) => registeredCommand.name === command.name);
|
|
22
|
+
if (registeredCommand && !diffCheck({ prev: registeredCommand, next: body })) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
commandsToAdd.push(body);
|
|
26
|
+
}
|
|
27
|
+
const commandsToRemove = [];
|
|
28
|
+
for (const registeredCommand of registeredCommands) {
|
|
29
|
+
const command = commands.find((command) => command.name === registeredCommand.name);
|
|
30
|
+
if (command) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
commandsToRemove.push(registeredCommand.id);
|
|
34
|
+
}
|
|
35
|
+
const addPromises = commandsToAdd.map((body) => this.rest.post(route, { body }));
|
|
36
|
+
const removePromises = commandsToRemove.map((id) => this.rest.delete(deleteRoute(id)));
|
|
37
|
+
await Promise.all([...addPromises, ...removePromises]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../src/commands/registration.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,MAAM,EAON,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,OAAO,mBAAmB;IAEtB;IACA;IAFT,YACS,IAAU,EACV,MAAoB;QADpB,SAAI,GAAJ,IAAI,CAAM;QACV,WAAM,GAAN,MAAM,CAAc;IAC1B,CAAC;IAEJ,KAAK,CAAC,sBAAsB,CAAC,QAAgD;QAC5E,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAC7F,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAClD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,CAC1B,OAAkB,EAClB,QAAgD;QAEhD,MAAM,IAAI,CAAC,gBAAgB,CAC1B,QAAQ,EACR,MAAM,CAAC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,EAC7D,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CACxE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC7B,QAAgD,EAChD,KAAmB,EACnB,WAAyC;QAEzC,MAAM,kBAAkB,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAGnD,CAAC;QAEJ,MAAM,aAAa,GAAsD,EAAE,CAAC;QAC5E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,CAAC;YAE3C,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,IAAI,CAChD,CAAC,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAC9D,CAAC;YACF,IAAI,iBAAiB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC9E,SAAS;YACV,CAAC;YAED,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpF,IAAI,OAAO,EAAE,CAAC;gBACb,OAAO;YACR,CAAC;YAED,gBAAgB,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACjF,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEvF,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;IACxD,CAAC;CACD","sourcesContent":["import {\n\tRoutes,\n\ttype APIApplicationCommand,\n\ttype Client,\n\ttype REST,\n\ttype RESTPostAPIChatInputApplicationCommandsJSONBody,\n\ttype SlashCommandBuilder,\n\ttype Snowflake\n} from \"discord.js\";\n\nimport type { Command } from \"./command.js\";\nimport { diffCheck } from \"./diff.js\";\n\nexport class CommandRegistration {\n\tconstructor(\n\t\tprivate rest: REST,\n\t\tprivate client: Client<true>\n\t) {}\n\n\tasync registerGlobalCommands(commands: Command<string, SlashCommandBuilder>[]) {\n\t\tawait this.registerCommands(commands, Routes.applicationCommands(this.client.user.id), (id) =>\n\t\t\tRoutes.applicationCommand(this.client.user.id, id)\n\t\t);\n\t}\n\n\tasync registerGuildCommands(\n\t\tguildId: Snowflake,\n\t\tcommands: Command<string, SlashCommandBuilder>[]\n\t) {\n\t\tawait this.registerCommands(\n\t\t\tcommands,\n\t\t\tRoutes.applicationGuildCommands(this.client.user.id, guildId),\n\t\t\t(id) => Routes.applicationGuildCommand(this.client.user.id, guildId, id)\n\t\t);\n\t}\n\n\tprivate async registerCommands(\n\t\tcommands: Command<string, SlashCommandBuilder>[],\n\t\troute: `/${string}`,\n\t\tdeleteRoute: (id: string) => `/${string}`\n\t) {\n\t\tconst registeredCommands = (await this.rest.get(route)) as Omit<\n\t\t\tAPIApplicationCommand,\n\t\t\t\"dm_permission\"\n\t\t>[];\n\n\t\tconst commandsToAdd: RESTPostAPIChatInputApplicationCommandsJSONBody[] = [];\n\t\tfor (const command of commands) {\n\t\t\tconst body = command.getBuilder().toJSON();\n\n\t\t\tconst registeredCommand = registeredCommands.find(\n\t\t\t\t(registeredCommand) => registeredCommand.name === command.name\n\t\t\t);\n\t\t\tif (registeredCommand && !diffCheck({ prev: registeredCommand, next: body })) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcommandsToAdd.push(body);\n\t\t}\n\n\t\tconst commandsToRemove: string[] = [];\n\t\tfor (const registeredCommand of registeredCommands) {\n\t\t\tconst command = commands.find((command) => command.name === registeredCommand.name);\n\t\t\tif (command) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcommandsToRemove.push(registeredCommand.id);\n\t\t}\n\n\t\tconst addPromises = commandsToAdd.map((body) => this.rest.post(route, { body }));\n\t\tconst removePromises = commandsToRemove.map((id) => this.rest.delete(deleteRoute(id)));\n\n\t\tawait Promise.all([...addPromises, ...removePromises]);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Bot } from "./bot.js";
|
|
2
|
+
import type { ILogger } from "./logger.js";
|
|
3
|
+
import { PermissionsResolver } from "./permissions.js";
|
|
4
|
+
export type GenericCtx = {
|
|
5
|
+
bot: Bot;
|
|
6
|
+
permissions: PermissionsResolver;
|
|
7
|
+
logger: ILogger;
|
|
8
|
+
};
|
|
9
|
+
export declare function createContext(bot: Bot, logger: ILogger): GenericCtx;
|
package/build/context.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAQvD,MAAM,UAAU,aAAa,CAAC,GAAQ,EAAE,MAAe;IACtD,OAAO;QACN,GAAG;QACH,WAAW,EAAE,IAAI,mBAAmB,CAAC,GAAG,CAAC;QACzC,MAAM;KACN,CAAC;AACH,CAAC","sourcesContent":["import type { Bot } from \"./bot.js\";\nimport type { ILogger } from \"./logger.js\";\nimport { PermissionsResolver } from \"./permissions.js\";\n\nexport type GenericCtx = {\n\tbot: Bot;\n\tpermissions: PermissionsResolver;\n\tlogger: ILogger;\n};\n\nexport function createContext(bot: Bot, logger: ILogger): GenericCtx {\n\treturn {\n\t\tbot,\n\t\tpermissions: new PermissionsResolver(bot),\n\t\tlogger\n\t};\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { listen } from \"./listener.js\";\nexport type { Listener } from \"./listener.js\";\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ClientEvents } from "discord.js";
|
|
2
|
+
import type { GenericCtx } from "../context.js";
|
|
3
|
+
type ListenerHandler<Event extends keyof ClientEvents> = (ctx: GenericCtx, ...args: ClientEvents[Event]) => void | Promise<void>;
|
|
4
|
+
export declare class Listener<Event extends keyof ClientEvents> {
|
|
5
|
+
readonly event: Event;
|
|
6
|
+
readonly handler: ListenerHandler<Event>;
|
|
7
|
+
readonly once: boolean;
|
|
8
|
+
constructor(event: Event, handler: ListenerHandler<Event>, once?: boolean);
|
|
9
|
+
}
|
|
10
|
+
export declare function listen<Event extends keyof ClientEvents>(listener: {
|
|
11
|
+
/**
|
|
12
|
+
* The type of discord event to listen to.
|
|
13
|
+
*/
|
|
14
|
+
event: Event;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the event should only be handled once.
|
|
17
|
+
*/
|
|
18
|
+
once?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The handler for the event.
|
|
21
|
+
*/
|
|
22
|
+
handler: (ctx: GenericCtx, ...args: ClientEvents[Event]) => void | Promise<void>;
|
|
23
|
+
}): Listener<Event>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export class Listener {
|
|
2
|
+
event;
|
|
3
|
+
handler;
|
|
4
|
+
once;
|
|
5
|
+
constructor(event, handler, once = false) {
|
|
6
|
+
this.event = event;
|
|
7
|
+
this.handler = handler;
|
|
8
|
+
this.once = once;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function listen(listener) {
|
|
12
|
+
return new Listener(listener.event, listener.handler, listener.once);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/events/listener.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,QAAQ;IAEV;IACA;IACA;IAHV,YACU,KAAY,EACZ,OAA+B,EAC/B,OAAgB,KAAK;QAFrB,UAAK,GAAL,KAAK,CAAO;QACZ,YAAO,GAAP,OAAO,CAAwB;QAC/B,SAAI,GAAJ,IAAI,CAAiB;IAC5B,CAAC;CACJ;AAED,MAAM,UAAU,MAAM,CAAmC,QAaxD;IACA,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC","sourcesContent":["import type { ClientEvents } from \"discord.js\";\n\nimport type { GenericCtx } from \"../context.js\";\n\ntype ListenerHandler<Event extends keyof ClientEvents> = (\n\tctx: GenericCtx,\n\t...args: ClientEvents[Event]\n) => void | Promise<void>;\n\nexport class Listener<Event extends keyof ClientEvents> {\n\tconstructor(\n\t\treadonly event: Event,\n\t\treadonly handler: ListenerHandler<Event>,\n\t\treadonly once: boolean = false\n\t) {}\n}\n\nexport function listen<Event extends keyof ClientEvents>(listener: {\n\t/**\n\t * The type of discord event to listen to.\n\t */\n\tevent: Event;\n\t/**\n\t * Whether the event should only be handled once.\n\t */\n\tonce?: boolean;\n\t/**\n\t * The handler for the event.\n\t */\n\thandler: (ctx: GenericCtx, ...args: ClientEvents[Event]) => void | Promise<void>;\n}) {\n\treturn new Listener(listener.event, listener.handler, listener.once);\n}\n"]}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Bot } from "./bot.js";
|
|
2
|
+
export type { BotOptions } from "./bot.js";
|
|
3
|
+
export type { GenericCtx } from "./context.js";
|
|
4
|
+
export type { PermissionName, SinglePermissionResolvable } from "./permissions.js";
|
|
5
|
+
export { plugin, ResolvedPlugin } from "./plugin.js";
|
|
6
|
+
export type { Plugin, PluginOptions } from "./plugin.js";
|
|
7
|
+
export * from "./utility-types.js";
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAI/B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErD,cAAc,oBAAoB,CAAC","sourcesContent":["export { Bot } from \"./bot.js\";\nexport type { BotOptions } from \"./bot.js\";\nexport type { GenericCtx } from \"./context.js\";\nexport type { PermissionName, SinglePermissionResolvable } from \"./permissions.js\";\nexport { plugin, ResolvedPlugin } from \"./plugin.js\";\nexport type { Plugin, PluginOptions } from \"./plugin.js\";\nexport * from \"./utility-types.js\";\n"]}
|
package/build/logger.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"","sourcesContent":["export interface ILogger {\n\ttrace(...args: unknown[]): any;\n\tdebug(...args: unknown[]): any;\n\tinfo(...args: unknown[]): any;\n\twarn(...args: unknown[]): any;\n\terror(...args: unknown[]): any;\n\tfatal(...args: unknown[]): any;\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { o, optionsToJson } from "./option.js";
|
|
2
|
+
export type { GenericOption, OptionDefinitions, Args, Infer } from "./option.js";
|
|
3
|
+
export type { OptionalType, Choice, AttachmentOption, BooleanOption, ChannelOption, IntegerOption, NumberOption, MentionableOption, RoleOption, StringOption, UserOption, AsOptional } from "./options.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/options/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { o, optionsToJson } from \"./option.js\";\nexport type { GenericOption, OptionDefinitions, Args, Infer } from \"./option.js\";\nexport type {\n\tOptionalType,\n\tChoice,\n\tAttachmentOption,\n\tBooleanOption,\n\tChannelOption,\n\tIntegerOption,\n\tNumberOption,\n\tMentionableOption,\n\tRoleOption,\n\tStringOption,\n\tUserOption,\n\tAsOptional\n} from \"./options.js\";\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type APIApplicationCommandOption, type ApplicationCommandOptionAllowedChannelTypes, type RestOrArray } from "discord.js";
|
|
2
|
+
import { AttachmentOption, BooleanOption, ChannelOption, Choice, IntegerOption, MentionableOption, NumberOption, RoleOption, StringOption, UserOption, type AsOptional, type Option, type OptionalType } from "./options.js";
|
|
3
|
+
import type { Expand } from "../utility-types.js";
|
|
4
|
+
export type GenericOption = Option<any, any>;
|
|
5
|
+
export declare function optionsToJson(options: OptionDefinitions): APIApplicationCommandOption[];
|
|
6
|
+
/**
|
|
7
|
+
* The option builder.
|
|
8
|
+
*
|
|
9
|
+
* This builder allows you to build options for Discord commands.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare const o: {
|
|
14
|
+
/**
|
|
15
|
+
* A command attachment option.
|
|
16
|
+
*/
|
|
17
|
+
attachment: () => AttachmentOption<import("discord.js").Attachment, "required">;
|
|
18
|
+
/**
|
|
19
|
+
* A command boolean option.
|
|
20
|
+
*/
|
|
21
|
+
boolean: () => BooleanOption<boolean, "required">;
|
|
22
|
+
/**
|
|
23
|
+
* A command channel option.
|
|
24
|
+
* @param channelTypes The channel types.
|
|
25
|
+
*/
|
|
26
|
+
channel: <T extends ApplicationCommandOptionAllowedChannelTypes>(...channelTypes: RestOrArray<T>) => ChannelOption<Extract<import("discord.js").CategoryChannel, {
|
|
27
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
28
|
+
}> | Extract<import("discord.js").NewsChannel, {
|
|
29
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
30
|
+
}> | Extract<import("discord.js").StageChannel, {
|
|
31
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
32
|
+
}> | Extract<import("discord.js").TextChannel, {
|
|
33
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
34
|
+
}> | Extract<import("discord.js").PublicThreadChannel<boolean>, {
|
|
35
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
36
|
+
}> | Extract<import("discord.js").PrivateThreadChannel, {
|
|
37
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
38
|
+
}> | Extract<import("discord.js").VoiceChannel, {
|
|
39
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
40
|
+
}> | Extract<import("discord.js").ForumChannel, {
|
|
41
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
42
|
+
}> | Extract<import("discord.js").MediaChannel, {
|
|
43
|
+
type: T | (T extends readonly (infer InnerArr)[] ? InnerArr : T);
|
|
44
|
+
}>, "required">;
|
|
45
|
+
/**
|
|
46
|
+
* A choice for a command option.
|
|
47
|
+
* @param name The name of the choice.
|
|
48
|
+
* @param value The value of the choice.
|
|
49
|
+
*/
|
|
50
|
+
choice: <T extends number | string>(value: T, name?: string) => Choice<T>;
|
|
51
|
+
/**
|
|
52
|
+
* A command integer option.
|
|
53
|
+
*/
|
|
54
|
+
integer: () => IntegerOption<number, "required">;
|
|
55
|
+
/**
|
|
56
|
+
* A command number option.
|
|
57
|
+
*/
|
|
58
|
+
number: () => NumberOption<number, "required">;
|
|
59
|
+
/**
|
|
60
|
+
* A command mentionable option.
|
|
61
|
+
*/
|
|
62
|
+
mentionable: () => MentionableOption<import("discord.js").GuildMember | import("discord.js").User | import("discord.js").Role, "required">;
|
|
63
|
+
/**
|
|
64
|
+
* A command role option.
|
|
65
|
+
*/
|
|
66
|
+
role: () => RoleOption<import("discord.js").Role, "required">;
|
|
67
|
+
/**
|
|
68
|
+
* A command string option.
|
|
69
|
+
*/
|
|
70
|
+
string: () => StringOption<string, "required">;
|
|
71
|
+
/**
|
|
72
|
+
* A command user option.
|
|
73
|
+
*/
|
|
74
|
+
user: () => UserOption<import("discord.js").User, "required">;
|
|
75
|
+
/**
|
|
76
|
+
* Allows not specifying an option for a command.
|
|
77
|
+
* @param option The option to make optional.
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* {
|
|
81
|
+
* requiredOption: o.string(),
|
|
82
|
+
* optionalOption: o.optional(o.string())
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
optional: <T extends GenericOption>(option: T) => AsOptional<T>;
|
|
87
|
+
};
|
|
88
|
+
export type OptionDefinitions = Record<string, Option<any, OptionalType>>;
|
|
89
|
+
/**
|
|
90
|
+
* Compute the args object type from {@link OptionDefinitions}.
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
export type Args<Options extends OptionDefinitions> = Expand<{
|
|
95
|
+
[Name in OptionalKeys<Options>]?: Exclude<Infer<Options[Name]>, undefined>;
|
|
96
|
+
} & {
|
|
97
|
+
[Name in RequiredKeys<Options>]: Infer<Options[Name]>;
|
|
98
|
+
}>;
|
|
99
|
+
type OptionalKeys<Options extends Record<string, GenericOption>> = {
|
|
100
|
+
[Name in keyof Options]: Options[Name]["isOptional"] extends "optional" ? Name : never;
|
|
101
|
+
}[keyof Options];
|
|
102
|
+
type RequiredKeys<Options extends Record<string, GenericOption>> = Exclude<keyof Options, OptionalKeys<Options>>;
|
|
103
|
+
/**
|
|
104
|
+
* Extract the TypeScript type from an option.
|
|
105
|
+
*
|
|
106
|
+
* Example usage:
|
|
107
|
+
* ```ts
|
|
108
|
+
* const option = o.string().union(o.choice("hello"), o.choice("world"));
|
|
109
|
+
* type MyOption = Infer<typeof option>; // "hello" | "world"
|
|
110
|
+
* ```
|
|
111
|
+
* @typeParam T - The type of a {@link Option} constructed with {@link o}.
|
|
112
|
+
*
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
115
|
+
export type Infer<T extends Option<any, OptionalType>> = T["type"];
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { SlashCommandAttachmentOption, SlashCommandBooleanOption, SlashCommandChannelOption, SlashCommandIntegerOption, SlashCommandMentionableOption, SlashCommandNumberOption, SlashCommandRoleOption, SlashCommandStringOption, SlashCommandUserOption } from "discord.js";
|
|
2
|
+
import { AttachmentOption, BooleanOption, BuilderOption, ChannelOption, Choice, IntegerOption, MentionableOption, NumberOption, RoleOption, StringOption, UserOption } from "./options.js";
|
|
3
|
+
export function optionsToJson(options) {
|
|
4
|
+
return Object.entries(options)
|
|
5
|
+
.map(([name, option]) => {
|
|
6
|
+
if (option instanceof BuilderOption) {
|
|
7
|
+
const builder = option.getBuilder();
|
|
8
|
+
return builder.setName(name).toJSON();
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
})
|
|
12
|
+
.filter((json) => json !== null);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The option builder.
|
|
16
|
+
*
|
|
17
|
+
* This builder allows you to build options for Discord commands.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export const o = {
|
|
22
|
+
/**
|
|
23
|
+
* A command attachment option.
|
|
24
|
+
*/
|
|
25
|
+
attachment: () => {
|
|
26
|
+
return new AttachmentOption(new SlashCommandAttachmentOption(), "required");
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* A command boolean option.
|
|
30
|
+
*/
|
|
31
|
+
boolean: () => {
|
|
32
|
+
return new BooleanOption(new SlashCommandBooleanOption(), "required");
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* A command channel option.
|
|
36
|
+
* @param channelTypes The channel types.
|
|
37
|
+
*/
|
|
38
|
+
channel: (...channelTypes) => {
|
|
39
|
+
const option = new ChannelOption(new SlashCommandChannelOption(), "required");
|
|
40
|
+
return option.union(channelTypes.flat());
|
|
41
|
+
},
|
|
42
|
+
/**
|
|
43
|
+
* A choice for a command option.
|
|
44
|
+
* @param name The name of the choice.
|
|
45
|
+
* @param value The value of the choice.
|
|
46
|
+
*/
|
|
47
|
+
choice: (value, name) => {
|
|
48
|
+
return new Choice(value, name);
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* A command integer option.
|
|
52
|
+
*/
|
|
53
|
+
integer: () => {
|
|
54
|
+
return new IntegerOption(new SlashCommandIntegerOption(), "required");
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* A command number option.
|
|
58
|
+
*/
|
|
59
|
+
number: () => {
|
|
60
|
+
return new NumberOption(new SlashCommandNumberOption(), "required");
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* A command mentionable option.
|
|
64
|
+
*/
|
|
65
|
+
mentionable: () => {
|
|
66
|
+
return new MentionableOption(new SlashCommandMentionableOption(), "required");
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* A command role option.
|
|
70
|
+
*/
|
|
71
|
+
role: () => {
|
|
72
|
+
return new RoleOption(new SlashCommandRoleOption(), "required");
|
|
73
|
+
},
|
|
74
|
+
/**
|
|
75
|
+
* A command string option.
|
|
76
|
+
*/
|
|
77
|
+
string: () => {
|
|
78
|
+
return new StringOption(new SlashCommandStringOption(), "required");
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* A command user option.
|
|
82
|
+
*/
|
|
83
|
+
user: () => {
|
|
84
|
+
return new UserOption(new SlashCommandUserOption(), "required");
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Allows not specifying an option for a command.
|
|
88
|
+
* @param option The option to make optional.
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* {
|
|
92
|
+
* requiredOption: o.string(),
|
|
93
|
+
* optionalOption: o.optional(o.string())
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
optional: (option) => {
|
|
98
|
+
return option.asOptional();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=option.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"option.js","sourceRoot":"","sources":["../../src/options/option.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tSlashCommandAttachmentOption,\n\tSlashCommandBooleanOption,\n\tSlashCommandChannelOption,\n\tSlashCommandIntegerOption,\n\tSlashCommandMentionableOption,\n\tSlashCommandNumberOption,\n\tSlashCommandRoleOption,\n\tSlashCommandStringOption,\n\tSlashCommandUserOption,\n\ttype APIApplicationCommandOption,\n\ttype ApplicationCommandOptionAllowedChannelTypes,\n\ttype RestOrArray\n} from \"discord.js\";\n\nimport {\n\tAttachmentOption,\n\tBooleanOption,\n\tBuilderOption,\n\tChannelOption,\n\tChoice,\n\tIntegerOption,\n\tMentionableOption,\n\tNumberOption,\n\tRoleOption,\n\tStringOption,\n\tUserOption,\n\ttype AsOptional,\n\ttype Option,\n\ttype OptionalType\n} from \"./options.js\";\nimport type { Expand } from \"../utility-types.js\";\n\nexport type GenericOption = Option<any, any>;\n\nexport function optionsToJson(options: OptionDefinitions): APIApplicationCommandOption[] {\n\treturn Object.entries(options)\n\t\t.map(([name, option]) => {\n\t\t\tif (option instanceof BuilderOption) {\n\t\t\t\tconst builder = option.getBuilder();\n\t\t\t\treturn builder.setName(name).toJSON();\n\t\t\t}\n\t\t\treturn null;\n\t\t})\n\t\t.filter((json) => json !== null);\n}\n\n/**\n * The option builder.\n *\n * This builder allows you to build options for Discord commands.\n *\n * @public\n */\nexport const o = {\n\t/**\n\t * A command attachment option.\n\t */\n\tattachment: () => {\n\t\treturn new AttachmentOption(new SlashCommandAttachmentOption(), \"required\");\n\t},\n\n\t/**\n\t * A command boolean option.\n\t */\n\tboolean: () => {\n\t\treturn new BooleanOption(new SlashCommandBooleanOption(), \"required\");\n\t},\n\n\t/**\n\t * A command channel option.\n\t * @param channelTypes The channel types.\n\t */\n\tchannel: <T extends ApplicationCommandOptionAllowedChannelTypes>(\n\t\t...channelTypes: RestOrArray<T>\n\t) => {\n\t\tconst option = new ChannelOption(new SlashCommandChannelOption(), \"required\");\n\t\treturn option.union(channelTypes.flat());\n\t},\n\n\t/**\n\t * A choice for a command option.\n\t * @param name The name of the choice.\n\t * @param value The value of the choice.\n\t */\n\tchoice: <T extends number | string>(value: T, name?: string) => {\n\t\treturn new Choice(value, name);\n\t},\n\n\t/**\n\t * A command integer option.\n\t */\n\tinteger: () => {\n\t\treturn new IntegerOption(new SlashCommandIntegerOption(), \"required\");\n\t},\n\n\t/**\n\t * A command number option.\n\t */\n\tnumber: () => {\n\t\treturn new NumberOption(new SlashCommandNumberOption(), \"required\");\n\t},\n\n\t/**\n\t * A command mentionable option.\n\t */\n\tmentionable: () => {\n\t\treturn new MentionableOption(new SlashCommandMentionableOption(), \"required\");\n\t},\n\n\t/**\n\t * A command role option.\n\t */\n\trole: () => {\n\t\treturn new RoleOption(new SlashCommandRoleOption(), \"required\");\n\t},\n\n\t/**\n\t * A command string option.\n\t */\n\tstring: () => {\n\t\treturn new StringOption(new SlashCommandStringOption(), \"required\");\n\t},\n\n\t/**\n\t * A command user option.\n\t */\n\tuser: () => {\n\t\treturn new UserOption(new SlashCommandUserOption(), \"required\");\n\t},\n\n\t/**\n\t * Allows not specifying an option for a command.\n\t * @param option The option to make optional.\n\t *\n\t * ```ts\n\t * {\n\t * requiredOption: o.string(),\n\t * optionalOption: o.optional(o.string())\n\t * }\n\t * ```\n\t */\n\toptional: <T extends GenericOption>(option: T) => {\n\t\treturn option.asOptional() as AsOptional<T>;\n\t}\n};\n\nexport type OptionDefinitions = Record<string, Option<any, OptionalType>>;\n\n/**\n * Compute the args object type from {@link OptionDefinitions}.\n *\n * @public\n */\nexport type Args<Options extends OptionDefinitions> = Expand<\n\t{\n\t\t// This `Exclude<..., undefined>` does nothing unless\n\t\t// the tsconfig.json option `\"exactOptionalPropertyTypes\": true,`\n\t\t// is used. When it is set it results in a more accurate type.\n\t\t// When it is not the `Exclude` removes `undefined` but it is\n\t\t// added again by the optional property.\n\t\t[Name in OptionalKeys<Options>]?: Exclude<Infer<Options[Name]>, undefined>;\n\t} & {\n\t\t[Name in RequiredKeys<Options>]: Infer<Options[Name]>;\n\t}\n>;\n\ntype OptionalKeys<Options extends Record<string, GenericOption>> = {\n\t[Name in keyof Options]: Options[Name][\"isOptional\"] extends \"optional\" ? Name : never;\n}[keyof Options];\n\ntype RequiredKeys<Options extends Record<string, GenericOption>> = Exclude<\n\tkeyof Options,\n\tOptionalKeys<Options>\n>;\n\n/**\n * Extract the TypeScript type from an option.\n *\n * Example usage:\n * ```ts\n * const option = o.string().union(o.choice(\"hello\"), o.choice(\"world\"));\n * type MyOption = Infer<typeof option>; // \"hello\" | \"world\"\n * ```\n * @typeParam T - The type of a {@link Option} constructed with {@link o}.\n *\n * @public\n */\nexport type Infer<T extends Option<any, OptionalType>> = T[\"type\"];\n"]}
|