diff --git a/TypeScript/assertFields.ts b/TypeScript/assertFields.ts new file mode 100644 index 0000000..16b3518 --- /dev/null +++ b/TypeScript/assertFields.ts @@ -0,0 +1,58 @@ +//@ts-nocheck +/** + * This plugin checks the fields of a ModalSubmitInteraction + * with regex or a custom callback + * + * @author @jacoobes [<@182326315813306368>] + * @version 1.0.0 + * @example + * ```ts + * export default commandModule({ + * type: CommandType.Modal, + * plugins: [ + * assertFields({ + * fields: { + * // check the modal field "mcUsernameInput" with the regex /a+b+c/ + * mcUsernameInput: /a+b+c+/ + * }, + * failure: (errors, interaction) => { + * interaction.reply(errors.join("\n")) + * } + * }), + * ], + * execute: ctx => { + * ctx.reply("nice!") + * } + * }) + * ``` + */ +import { CommandControlPlugin, CommandType, controller } from "@sern/handler"; +import type { ModalSubmitInteraction } from "discord.js"; + +type Assertion = + | RegExp + | ((value : string) => boolean); + +export function assertFields(config: { + fields: Record, + failure: (errors: string[], interaction: ModalSubmitInteraction) => any +}) { + return CommandControlPlugin(modal => { + const pairs = Object.entries(config.fields); + const errors = []; + for(const [ field, assertion ] of pairs) { + // Keep in mind this doesn't check for typos! + // feel free to add more checks. + const input = modal.fields.getTextInputValue(field) + const resolvedAssertion = assertion instanceof RegExp ? (value: string) => assertion.test(value) : assertion; + if(!resolvedAssertion(input)) { + errors.push(input + " failed to pass assertion " + resolvedAssertion.toString() ) + } + } + if(errors.length > 0) { + config.failure(errors, modal); + return controller.stop(); + } + return controller.next(); + }) +} \ No newline at end of file diff --git a/TypeScript/buttonConfirmation.ts b/TypeScript/buttonConfirmation.ts index 7ebeab2..1c44158 100644 --- a/TypeScript/buttonConfirmation.ts +++ b/TypeScript/buttonConfirmation.ts @@ -1,4 +1,4 @@ -// @ts-nocheck +//@ts-nocheck /** * This is buttonConfirmation plugin, it runs confirmation prompt in the form of buttons. * Note that you need to use edit/editReply in the command itself because we are already replying in the plugin! @@ -19,94 +19,91 @@ * ``` */ -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, controller} from "@sern/handler"; import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - ComponentType, + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + ComponentType, } from "discord.js"; export function confirmation( - options?: Partial -): EventPlugin { - return { - type: PluginType.Event, - description: "Confirms", - async execute([ctx], controller) { - options = { - content: "Do you want to proceed?", - denialMessage: "Cancelled", - labels: ["No", "Yes"], - time: 60_000, - wrongUserResponse: "Not for you!", - ...options, - }; + options?: Partial +) { + return CommandControlPlugin(async (ctx, args) => { + options = { + content: "Do you want to proceed?", + denialMessage: "Cancelled", + labels: ["No", "Yes"], + time: 60_000, + wrongUserResponse: "Not for you!", + ...options, + }; - const buttons = options.labels!.map((l, i) => { - return new ButtonBuilder() - .setCustomId(l) - .setLabel(l) - .setStyle( - i === 0 ? ButtonStyle.Danger : ButtonStyle.Success - ); - }); - const sent = await ctx.reply({ - content: options.content, - components: [ - new ActionRowBuilder().setComponents( - buttons - ), - ], - }); + const buttons = options.labels!.map((l, i) => { + return new ButtonBuilder() + .setCustomId(l) + .setLabel(l) + .setStyle( + i === 0 ? ButtonStyle.Danger : ButtonStyle.Success + ); + }); + const sent = await ctx.reply({ + content: options.content, + components: [ + new ActionRowBuilder().setComponents( + buttons + ), + ], + }); - const collector = sent.createMessageComponentCollector({ - componentType: ComponentType.Button, - filter: (i) => i.user.id === ctx.user.id, - time: options.time, - }); + const collector = sent.createMessageComponentCollector({ + componentType: ComponentType.Button, + filter: (i) => i.user.id === ctx.user.id, + time: options.time, + }); - return new Promise((resolve) => { - collector.on("collect", async (i) => { - await i.update({ components: [] }); - collector.stop(); - if (i.customId === options!.labels![1]) { - resolve(controller.next()); - return; - } - await i.editReply({ - content: options?.denialMessage, - }); - resolve(controller.stop()); - }); + return new Promise((resolve) => { + collector.on("collect", async (i) => { + await i.update({ components: [] }); + collector.stop(); + if (i.customId === options!.labels![1]) { + resolve(controller.next()); + return; + } + await i.editReply({ + content: options?.denialMessage, + }); + resolve(controller.stop()); + }); - collector.on("end", async (c) => { - if (c.size) return; - buttons.forEach((b) => b.setDisabled()); - await sent.edit({ - components: [ - new ActionRowBuilder().setComponents( - buttons - ), - ], - }); - }); + collector.on("end", async (c) => { + if (c.size) return; + buttons.forEach((b) => b.setDisabled()); + await sent.edit({ + components: [ + new ActionRowBuilder().setComponents( + buttons + ), + ], + }); + }); - collector.on("ignore", async (i) => { - await i.reply({ - content: options?.wrongUserResponse, - ephemeral: true, - }); - }); - }); - }, - }; + collector.on("ignore", async (i) => { + await i.reply({ + content: options?.wrongUserResponse, + ephemeral: true, + }); + }); + }); + }); } interface ConfirmationOptions { - content: string; - denialMessage: string; - time: number; - labels: [string, string]; - wrongUserResponse: string; + content: string; + denialMessage: string; + time: number; + labels: [string, string]; + wrongUserResponse: string; } + diff --git a/TypeScript/channelType.ts b/TypeScript/channelType.ts index cd41954..8b960bf 100644 --- a/TypeScript/channelType.ts +++ b/TypeScript/channelType.ts @@ -18,28 +18,23 @@ * ``` */ import { ChannelType } from "discord.js"; -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, controller } from "@sern/handler"; export function channelType( - channelType: ChannelType[], - onFail?: string -): EventPlugin { - return { - type: PluginType.Event, - description: "Checks the channel type.", - async execute(event, controller) { - const [ctx] = event; - let channel = ctx.channel?.type; - //for some reason the dm channel type was returning undefined at some points - if (channel === undefined) { - channel = ChannelType.DM; - } - if (channelType.includes(channel)) { - return controller.next(); - } - if (onFail) { - await ctx.reply(onFail); - } - return controller.stop(); - }, - }; -} + channelType: ChannelType[], + onFail?: string +){ + return CommandControlPlugin(async (ctx, args) => { + let channel = ctx.channel?.type; + //for some reason the dm channel type was returning undefined at some points + if (channel === undefined) { + channel = ChannelType.DM; + } + if (channelType.includes(channel)) { + return controller.next(); + } + if (onFail) { + await ctx.reply(onFail); + } + return controller.stop(); + }) +} \ No newline at end of file diff --git a/TypeScript/confirmation.ts b/TypeScript/confirmation.ts index d5f4633..3b3a8fa 100644 --- a/TypeScript/confirmation.ts +++ b/TypeScript/confirmation.ts @@ -14,13 +14,13 @@ * type : CommandType.Both * plugins: [confirmation()], * execute: (ctx, args) => { - * ctx.reply('hola'); + * ctx.interaction.followUp('Hello welcome to the secret club') * } * }) * ``` */ -import { CommandType, Context, EventPlugin, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, Context, controller } from "@sern/handler"; import type { Awaitable, Message, MessageReaction, User } from "discord.js"; type Callback = Awaitable | ((context: Context) => Awaitable); @@ -43,7 +43,7 @@ interface Emojis { } const defaultOptions: ConfirmationOptions = { - timeout: 1000, + timeout: 5000, message: "Are you sure you want to proceed?", onTimeout: "confirmation timed out", onCancel: "confirmation cancelled", @@ -60,18 +60,15 @@ const defaultOptions: ConfirmationOptions = { export function confirmation( raw: Partial = {} -): EventPlugin { +) { const options: ConfirmationOptions = Object.assign({}, defaultOptions, raw); - return { - name: "confirmation", - type: PluginType.Event, - async execute([context], controller) { + return CommandControlPlugin(async (context, _) => { if (typeof options.message === "function") { options.message = await options.message(context); } const response = await context.reply(await options.message); - let { yes, no } = options.emojis; + let {yes, no} = options.emojis; if (typeof yes === "function") { yes = await yes(context); } @@ -103,10 +100,8 @@ export function confirmation( await response.edit(await options.onTimeout); await response.reactions.removeAll(); } - return controller.stop(); } - const reaction = recieved.first(); if (!reaction) { return controller.stop(); @@ -132,8 +127,7 @@ export function confirmation( return controller.stop(); } - - return controller.next(); - }, - }; + return controller.next() + } + ) } diff --git a/TypeScript/cooldown.ts b/TypeScript/cooldown.ts index 08c0cf8..c1412e7 100644 --- a/TypeScript/cooldown.ts +++ b/TypeScript/cooldown.ts @@ -1,7 +1,7 @@ // @ts-nocheck /** * Allows you to set cooldowns (or "ratelimits") for commands - * + * limits user/channel/guild actions, * @author @trueharuu [<@504698587221852172>] * @version 1.0.0 * @example @@ -17,7 +17,7 @@ * ``` */ -import { CommandType, Context, EventPlugin, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, Context, controller } from "@sern/handler"; import { GuildMember } from "discord.js"; /** * actions/seconds @@ -107,44 +107,38 @@ function add( | Cooldown >, message?: CooldownResponse -): EventPlugin { +) { const raw = items.map((c) => { if (!Array.isArray(c)) return c; return parseCooldown(c[0] as CooldownLocation, c[1]); }) as Array; + return CommandControlPlugin(async (context, args) => { + for (const { location, actions, seconds } of raw) { + const id = getPropertyForLocation(context, location); + const cooldown = map.get(id!); - return { - name: "cooldown", - description: "limits user/channel/guild actions", - type: PluginType.Event, - async execute([context], controller) { - for (const { location, actions, seconds } of raw) { - const id = getPropertyForLocation(context, location); - const cooldown = map.get(id); - - if (!cooldown) { - map.set(id, 1, seconds * 1000); - continue; - } - - if (cooldown >= actions) { - if (message) { - await message({ - location, - actions: cooldown, - maxActions: actions, - seconds, - context, - }); - } - return controller.stop(); - } - - map.set(id, cooldown + 1, seconds * 1000); + if (!cooldown) { + map.set(id!, 1, seconds * 1000); + continue; } - return controller.next(); - }, - }; + + if (cooldown >= actions) { + if (message) { + await message({ + location, + actions: cooldown, + maxActions: actions, + seconds, + context, + }); + } + return controller.stop(); + } + + map.set(id!, cooldown + 1, seconds * 1000); + } + return controller.next(); + }); } type Location = (value: CooldownString) => ReturnType; diff --git a/TypeScript/dmOnly.ts b/TypeScript/dmOnly.ts index 4294b6f..a01fc64 100644 --- a/TypeScript/dmOnly.ts +++ b/TypeScript/dmOnly.ts @@ -16,20 +16,16 @@ * }) * ``` */ -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, controller } from "@sern/handler"; export function dmOnly( - content?: string, - ephemeral?: boolean -): EventPlugin { - return { - type: PluginType.Event, - description: "Allows commands to be run in DM only", - async execute(event, controller) { - const [ctx] = event; - if (ctx.channel?.isDMBased()) return controller.next(); + content?: string, + ephemeral?: boolean +) { + // For discord.js you should have the Partials.Channel and DirectMessages intent enabled. + return CommandControlPlugin(async (ctx, _) => { + if (ctx.channel?.isDMBased()) return controller.next(); - if (content) await ctx.reply({ content, ephemeral }); // Change this if you want or remove it for silent deny - return controller.stop(); - }, - }; + if (content) await ctx.reply({ content, ephemeral }); // Change this if you want or remove it for silent deny + return controller.stop(); + }) } diff --git a/TypeScript/nsfwOnly.ts b/TypeScript/nsfwOnly.ts index 2cf7536..8f1d23e 100644 --- a/TypeScript/nsfwOnly.ts +++ b/TypeScript/nsfwOnly.ts @@ -17,46 +17,40 @@ * ``` */ import { - ChannelType, - GuildTextBasedChannel, - TextBasedChannel, - TextChannel, + ChannelType, + GuildTextBasedChannel, + TextBasedChannel, + TextChannel, } from "discord.js"; -import { CommandType, EventPlugin, Nullish, PluginType } from "@sern/handler"; +import {CommandControlPlugin, CommandType, controller } from "@sern/handler"; function isGuildText( - channel: Nullish + channel: TextBasedChannel | null ): channel is GuildTextBasedChannel { - return ( - channel?.type == ChannelType.GuildPublicThread || - channel?.type == ChannelType.GuildPrivateThread - ); + return ( + channel?.type == ChannelType.GuildPublicThread || + channel?.type == ChannelType.GuildPrivateThread + ); } export function nsfwOnly( - onFail: string, - ephemeral: boolean -): EventPlugin { - return { - type: PluginType.Event, - description: "Checks if the channel is nsfw or not.", - async execute(event, controller) { - const [ctx] = event; - //checking if command was executed in dms - if (ctx.guild === null) { - await ctx.reply({ content: onFail, ephemeral }); - return controller.stop(); - } - //channel is thread (not supported by nsfw) - if (isGuildText(ctx.channel) == true) { - await ctx.reply({ content: onFail, ephemeral }); - return controller.stop(); - } - if (!(ctx.channel! as TextChannel).nsfw) { - //channel is not nsfw - await ctx.reply({ content: onFail, ephemeral }); - return controller.stop(); - } - //continues to command if nsfw - return controller.next(); - }, - }; + onFail: string, + ephemeral: boolean +) { + return CommandControlPlugin(async (ctx, _) => { + if (ctx.guild === null) { + await ctx.reply({ content: onFail, ephemeral }); + return controller.stop(); + } + //channel is thread (not supported by nsfw) + if (isGuildText(ctx.channel) == true) { + await ctx.reply({ content: onFail, ephemeral }); + return controller.stop(); + } + if (!(ctx.channel! as TextChannel).nsfw) { + //channel is not nsfw + await ctx.reply({ content: onFail, ephemeral }); + return controller.stop(); + } + //continues to command if nsfw + return controller.next(); + }); } diff --git a/TypeScript/ownerOnly.ts b/TypeScript/ownerOnly.ts index 5a5ef42..136bf60 100644 --- a/TypeScript/ownerOnly.ts +++ b/TypeScript/ownerOnly.ts @@ -17,18 +17,13 @@ * ``` */ -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import { CommandType, CommandControlPlugin, controller } from "@sern/handler"; const ownerIDs = ["697795666373640213"]; //! Fill your ID -export function ownerOnly(): EventPlugin { - return { - type: PluginType.Event, - description: "Allows only bot owner to run command", - async execute(event, controller) { - const [ctx] = event; - if (ownerIDs.includes(ctx.user.id)) return controller.next(); - //* If you want to reply when the command fails due to user not being owner, you can use following - // await ctx.reply("Only owner can run it!!!"); - return controller.stop(); //! Important: It stops the execution of command! - }, - }; +export function ownerOnly() { + return CommandControlPlugin((ctx,args) => { + if (ownerIDs.includes(ctx.user.id)) return controller.next(); + //* If you want to reply when the command fails due to user not being owner, you can use following + // await ctx.reply("Only owner can run it!!!"); + return controller.stop(); //! Important: It stops the execution of command! + }) } diff --git a/TypeScript/permCheck.ts b/TypeScript/permCheck.ts index c3c223f..3a86bac 100644 --- a/TypeScript/permCheck.ts +++ b/TypeScript/permCheck.ts @@ -17,29 +17,24 @@ * ``` */ -import { type GuildMember, PermissionResolvable } from "discord.js"; -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import type { GuildMember, PermissionResolvable } from "discord.js"; +import {CommandControlPlugin, CommandType, controller } from "@sern/handler"; export function permCheck( perm: PermissionResolvable, response: string -): EventPlugin { - return { - type: PluginType.Event, - description: "Checks for specified perm", - async execute(event, controller) { - const [ctx] = event; - if (ctx.guild === null) { - ctx.reply("This command cannot be used here"); - console.warn( - "PermCheck > A command stopped because we couldn't check a users permissions (was used in dms)" - ); //delete this line if you dont want to be notified when a command is used outside of a guild/server - return controller.stop(); - } - if (!(ctx.member! as GuildMember).permissions.has(perm)) { - await ctx.reply(response); - return controller.stop(); - } - return controller.next(); - }, - }; +) { + return CommandControlPlugin(async (ctx, args) => { + if (ctx.guild === null) { + await ctx.reply("This command cannot be used here"); + console.warn( + "PermCheck > A command stopped because we couldn't check a users permissions (was used in dms)" + ); //delete this line if you dont want to be notified when a command is used outside of a guild/server + return controller.stop(); + } + if (!(ctx.member! as GuildMember).permissions.has(perm)) { + await ctx.reply(response); + return controller.stop(); + } + return controller.next(); + }) } diff --git a/TypeScript/publish.ts b/TypeScript/publish.ts index 95a4a97..e8f024f 100644 --- a/TypeScript/publish.ts +++ b/TypeScript/publish.ts @@ -17,200 +17,184 @@ * }) * ``` */ -import { - CommandPlugin, - CommandType, - PluginType, - SernOptionsData, - SlashCommand, -} from "@sern/handler"; -import { - ApplicationCommandData, - ApplicationCommandType, - PermissionResolvable, -} from "discord.js"; -/** - * This is the dependency getter that is created from Sern.makeDependencies. - * import it here so that this plugin has access to your bot's dependencies - */ -import { useContainer } from "../index.js"; +import {CommandInitPlugin, CommandType, controller, SernOptionsData, SlashCommand} from '@sern/handler' +import {ApplicationCommandData, ApplicationCommandType, PermissionResolvable} from "discord.js"; +import {useContainer} from "../index.js"; -export function publish( - options?: PublishOptions -): CommandPlugin< - | CommandType.Slash - | CommandType.Both - | CommandType.CtxUser - | CommandType.CtxMsg -> { - return { - type: PluginType.Command, - description: "Manage Application Commands", - name: "slash-auto-publish", - async execute({ mod: module }, controller) { - // Users need to provide their own useContainer function. - const [client] = useContainer("@sern/client"); - const defaultOptions = { - guildIds: [], - dmPermission: undefined, - defaultMemberPermissions: null, - }; +export const CommandTypeRaw = { + [CommandType.Both]: ApplicationCommandType.ChatInput, + [CommandType.CtxUser]: ApplicationCommandType.Message, + [CommandType.CtxMsg]: ApplicationCommandType.User, + [CommandType.Slash]: ApplicationCommandType.ChatInput, +} as const; - options = { ...defaultOptions, ...options } as PublishOptions & - ValidPublishOptions; - let { defaultMemberPermissions, dmPermission, guildIds } = - options as unknown as ValidPublishOptions; +export function publish( + options?: PublishOptions +) { + return CommandInitPlugin(async ({ module }) => { + // Users need to provide their own useContainer function. + const [client] = useContainer("@sern/client"); + const defaultOptions = { + guildIds: [], + dmPermission: undefined, + defaultMemberPermissions: null, + }; - function c(e: unknown) { - console.error("publish command didnt work for", module.name); - console.error(e); - } - const log = - (...message: any[]) => - () => - console.log(...message); - const logged = (...message: any[]) => log(message); - /** - * a local function that returns either one value or the other, - * depending on {t}'s CommandType. If the commandtype of - * this module is CommandType.Both or CommandType.Text or CommandType.Slash, - * return 'is', else return 'els' - * @param t - * @returns S | T - */ - const appCmd = (t: V) => { - return (is: S, els: T) => - (t & CommandType.Both) !== 0 ? is : els; - }; - const curAppType = CommandTypeRaw[module.type]; - const createCommandData = () => { - const cmd = appCmd(module.type); - return { - name: module.name, - type: curAppType, - description: cmd(module.description, ""), - options: cmd( - optionsTransformer( - (module as SlashCommand).options ?? [] - ), - [] - ), - defaultMemberPermissions, - dmPermission, - } as ApplicationCommandData; - }; + options = {...defaultOptions, ...options} as PublishOptions & + ValidPublishOptions; + let {defaultMemberPermissions, dmPermission, guildIds} = + options as unknown as ValidPublishOptions; - try { - const commandData = createCommandData(); + function c(e: unknown) { + console.error("publish command didnt work for", module.name); + console.error(e); + } - if (!guildIds.length) { - const cmd = ( - await client.application!.commands.fetch() - ).find( - (c) => c.name === module.name && c.type === curAppType - ); - if (cmd) { - if (!cmd.equals(commandData, true)) { - logged( - `Found differences in global command ${module.name}` - ); - cmd.edit(commandData).then( - log( - `${module.name} updated with new data successfully!` - ) - ); - } - return controller.next(); - } - client - .application!.commands.create(commandData) - .then(log("Command created", module.name)) - .catch(c); - return controller.next(); - } + const log = + (...message: any[]) => + () => + console.log(...message); + const logged = (...message: any[]) => log(message); + /** + * a local function that returns either one value or the other, + * depending on {t}'s CommandType. If the commandtype of + * this module is CommandType.Both or CommandType.Text or CommandType.Slash, + * return 'is', else return 'els' + * @param t + * @returns S | T + */ + const appCmd = (t: V) => { + return (is: S, els: T) => + (t & CommandType.Both) !== 0 ? is : els; + }; + const curAppType = CommandTypeRaw[module.type]; + const createCommandData = () => { + const cmd = appCmd(module.type); + return { + name: module.name, + type: curAppType, + description: cmd(module.description, ""), + options: cmd( + optionsTransformer( + (module as SlashCommand).options ?? [] + ), + [] + ), + defaultMemberPermissions, + dmPermission, + } as ApplicationCommandData; + }; - for (const id of guildIds) { - const guild = await client.guilds.fetch(id).catch(c); - if (!guild) continue; - const guildCmd = (await guild.commands.fetch()).find( - (c) => c.name === module.name && c.type === curAppType - ); - if (guildCmd) { - if (!guildCmd.equals(commandData, true)) { - logged( - `Found differences in command ${module.name}` - ); - guildCmd - .edit(commandData) - .then( - log( - `${module.name} updated with new data successfully!` - ) - ) - .catch(c); - continue; - } - continue; - } - guild.commands - .create(commandData) - .then( - log( - "Guild Command created", - module.name, - guild.name - ) - ) - .catch(c); - } - return controller.next(); - } catch (e) { - logged("Command did not register" + module.name); - logged(e); - return controller.stop(); - } - }, - }; + try { + const commandData = createCommandData(); + + if (!guildIds.length) { + const cmd = ( + await client.application!.commands.fetch() + ).find( + (c) => c.name === module.name && c.type === curAppType + ); + if (cmd) { + if (!cmd.equals(commandData, true)) { + logged( + `Found differences in global command ${module.name}` + ); + cmd.edit(commandData).then( + log( + `${module.name} updated with new data successfully!` + ) + ); + } + return controller.next(); + } + client + .application!.commands.create(commandData) + .then(log("Command created", module.name)) + .catch(c); + return controller.next(); + } + + for (const id of guildIds) { + const guild = await client.guilds.fetch(id).catch(c); + if (!guild) continue; + const guildCmd = (await guild.commands.fetch()).find( + (c) => c.name === module.name && c.type === curAppType + ); + if (guildCmd) { + if (!guildCmd.equals(commandData, true)) { + logged( + `Found differences in command ${module.name}` + ); + guildCmd + .edit(commandData) + .then( + log( + `${module.name} updated with new data successfully!` + ) + ) + .catch(c); + continue; + } + continue; + } + guild.commands + .create(commandData) + .then( + log( + "Guild Command created", + module.name, + guild.name + ) + ) + .catch(c); + } + return controller.next(); + } catch (e) { + logged("Command did not register" + module.name); + logged(e); + return controller.stop(); + } + }) } export function optionsTransformer(ops: Array) { - return ops.map((el) => - el.autocomplete ? (({ command, ...el }) => el)(el) : el - ); + return ops.map((el) => + el.autocomplete ? (({command, ...el}) => el)(el) : el + ); } -export const CommandTypeRaw = { - [CommandType.Both]: ApplicationCommandType.ChatInput, - [CommandType.CtxUser]: ApplicationCommandType.Message, - [CommandType.CtxMsg]: ApplicationCommandType.User, - [CommandType.Slash]: ApplicationCommandType.ChatInput, -} as const; - export type NonEmptyArray = [T, ...T[]]; export interface ValidPublishOptions { - guildIds: string[]; - dmPermission: boolean; - defaultMemberPermissions: PermissionResolvable; + guildIds: string[]; + dmPermission: boolean; + defaultMemberPermissions: PermissionResolvable; } + interface GuildPublishOptions { - guildIds?: NonEmptyArray; - defaultMemberPermissions?: PermissionResolvable; - dmPermission?: never; + guildIds?: NonEmptyArray; + defaultMemberPermissions?: PermissionResolvable; + dmPermission?: never; } + interface GlobalPublishOptions { - defaultMemberPermissions?: PermissionResolvable; - dmPermission?: false; - guildIds?: never; + defaultMemberPermissions?: PermissionResolvable; + dmPermission?: false; + guildIds?: never; } type BasePublishOptions = GuildPublishOptions | GlobalPublishOptions; export type PublishOptions = BasePublishOptions & - ( - | Required> - | ( - | Required> - | Required> - ) - ); + ( + | Required> + | ( + | Required> + | Required> + ) + ); \ No newline at end of file diff --git a/TypeScript/requirePermission.ts b/TypeScript/requirePermission.ts index 958b3d3..ca02a96 100644 --- a/TypeScript/requirePermission.ts +++ b/TypeScript/requirePermission.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /** * This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check bot or user for that perm). * @@ -19,10 +20,7 @@ import type { GuildMember, PermissionResolvable } from "discord.js"; import { - CommandType, - Controller, - EventPlugin, - PluginType, + CommandType, CommandControlPlugin, controller, } from "@sern/handler"; function payload(resp?: string) { @@ -33,72 +31,68 @@ function payload(resp?: string) { } as const; } -export function requirePermission( +export function requirePermission( target: "user" | "bot" | "both", perm: PermissionResolvable[], response?: string -): EventPlugin { - return { - type: PluginType.Event, - description: "Checks bot/user perms", - async execute(event, controller: Controller) { - const [ctx] = event; - if (ctx.guild === null) { - ctx.reply(payload("This command cannot be used here")); - console.warn( - "PermCheck > A command stopped because we couldn't check a users permissions (was used in dms)" - ); //delete this line if you dont want to be notified when a command is used outside of a guild/server - return controller.stop(); - } - const bot = (await ctx.guild.members.fetchMe({ - cache: false, - })!) as GuildMember; - const memm = ctx.member! as GuildMember; - switch (target) { - //*********************************************************************************************************************// - case "bot": - if (!bot.permissions.has(perm)) { - if (!response) - response = `I cannot use this command, please give me \`${perm.join( - ", " - )}\` permission(s).`; - await ctx.reply(payload(response)); - return controller.stop(); - } - return controller.next(); - //*********************************************************************************************************************// - case "user": - if (!memm.permissions.has(perm)) { - if (!response) - response = `You cannot use this command because you are missing \`${perm.join( - ", " - )}\` permission(s).`; - await ctx.reply(payload(response)); - return controller.stop(); - } - return controller.next(); - //*********************************************************************************************************************// - case "both": - if ( - !bot.permissions.has(perm) || - !memm.permissions.has(perm) - ) { - if (!response) - response = `Please ensure <@${bot.user.id}> and <@${ - memm.user.id - }> both have \`${perm.join(", ")}\` permission(s).`; - await ctx.reply(payload(response)); - return controller.stop(); - } - return controller.next(); - //*********************************************************************************************************************// - default: - console.warn( - "Perm Check >>> You didn't specify user or bot." - ); - ctx.reply(payload("User or Bot was not specified.")); +) { + return CommandControlPlugin(async (ctx, args) => { + if (ctx.guild === null) { + ctx.reply(payload("This command cannot be used here")); + console.warn( + "PermCheck > A command stopped because we couldn't check a users permissions (was used in dms)" + ); //delete this line if you dont want to be notified when a command is used outside of a guild/server + return controller.stop(); + } + const bot = (await ctx.guild.members.fetchMe({ + cache: false, + })!) as GuildMember; + const memm = ctx.member! as GuildMember; + switch (target) { + //*********************************************************************************************************************// + case "bot": + if (!bot.permissions.has(perm)) { + if (!response) + response = `I cannot use this command, please give me \`${perm.join( + ", " + )}\` permission(s).`; + await ctx.reply(payload(response)); return controller.stop(); - } - }, - }; + } + return controller.next(); + //*********************************************************************************************************************// + case "user": + if (!memm.permissions.has(perm)) { + if (!response) + response = `You cannot use this command because you are missing \`${perm.join( + ", " + )}\` permission(s).`; + await ctx.reply(payload(response)); + return controller.stop(); + } + return controller.next(); + //*********************************************************************************************************************// + case "both": + if ( + !bot.permissions.has(perm) || + !memm.permissions.has(perm) + ) { + if (!response) + response = `Please ensure <@${bot.user.id}> and <@${ + memm.user.id + }> both have \`${perm.join(", ")}\` permission(s).`; + await ctx.reply(payload(response)); + return controller.stop(); + } + return controller.next(); + //*********************************************************************************************************************// + default: + console.warn( + "Perm Check >>> You didn't specify user or bot." + ); + ctx.reply(payload("User or Bot was not specified.")); + return controller.stop(); + } + }); } + diff --git a/TypeScript/serverOnly.ts b/TypeScript/serverOnly.ts index a253a68..0445162 100644 --- a/TypeScript/serverOnly.ts +++ b/TypeScript/serverOnly.ts @@ -19,25 +19,24 @@ * ``` */ -import { CommandType, EventPlugin, PluginType } from "@sern/handler"; +import { CommandType, controller, CommandControlPlugin } from "@sern/handler"; export function serverOnly( - guildId: string[], - failMessage = "This command is not available in this guild. \nFor permission to use in your server, please contact my developer." -): EventPlugin { - return { - type: PluginType.Event, - description: "Checks if a command is available in a specific server.", - async execute([ctx, args], controller) { - if (!guildId.includes(ctx.guildId)) { - await ctx.reply(failMessage).then(async (m) => { - setTimeout(async () => { - await m.delete(); - }, 3000); - }); - return controller.stop(); - } - return controller.next(); - }, - }; + guildId: string[], + failMessage = "This command is not available in this guild. \nFor permission to use in your server, please contact my developer." +) { + return CommandControlPlugin(async ( ctx, _) => { + if(ctx.guildId == null) { + return controller.stop() + } + if (!guildId.includes(ctx.guildId)) { + ctx.reply(failMessage).then(async (m) => { + setTimeout(async () => { + await m.delete(); + }, 3000); + }); + return controller.stop(); + } + return controller.next(); + }) }