From 877291964c872f9cd0a8188016bfe3abf595255b Mon Sep 17 00:00:00 2001 From: Evo <85353424+EvolutionX-10@users.noreply.github.com> Date: Sat, 2 Sep 2023 10:59:59 +0530 Subject: [PATCH] feat: awesome automations (#104) --- .github/workflows/gen-list.yml | 31 ++-- JavaScript/assertFields.js | 61 ------- JavaScript/buttonConfirmation.js | 86 --------- JavaScript/channelType.js | 41 ----- JavaScript/confirmation.js | 115 ------------ JavaScript/cooldown.js | 133 -------------- JavaScript/disable.js | 63 ------- JavaScript/dmOnly.js | 33 ---- JavaScript/nsfwOnly.js | 59 ------- JavaScript/ownerOnly.js | 31 ---- JavaScript/permCheck.js | 39 ---- JavaScript/publish.js | 166 ------------------ JavaScript/requirePermission.js | 91 ---------- JavaScript/serverOnly.js | 43 ----- pluginlist.json | 28 +-- {TypeScript => plugins}/assertFields.ts | 0 {TypeScript => plugins}/buttonConfirmation.ts | 0 {TypeScript => plugins}/channelType.ts | 0 {TypeScript => plugins}/confirmation.ts | 0 {TypeScript => plugins}/cooldown.ts | 0 {TypeScript => plugins}/disable.ts | 0 {TypeScript => plugins}/dmOnly.ts | 0 {TypeScript => plugins}/filter.ts | 0 {TypeScript => plugins}/nsfwOnly.ts | 0 {TypeScript => plugins}/ownerOnly.ts | 0 {TypeScript => plugins}/permCheck.ts | 0 {TypeScript => plugins}/publish.ts | 0 {TypeScript => plugins}/requirePermission.ts | 0 {TypeScript => plugins}/serverOnly.ts | 0 scripts/gen-list.clj | 14 +- 30 files changed, 35 insertions(+), 999 deletions(-) delete mode 100644 JavaScript/assertFields.js delete mode 100644 JavaScript/buttonConfirmation.js delete mode 100644 JavaScript/channelType.js delete mode 100644 JavaScript/confirmation.js delete mode 100644 JavaScript/cooldown.js delete mode 100644 JavaScript/disable.js delete mode 100644 JavaScript/dmOnly.js delete mode 100644 JavaScript/nsfwOnly.js delete mode 100644 JavaScript/ownerOnly.js delete mode 100644 JavaScript/permCheck.js delete mode 100644 JavaScript/publish.js delete mode 100644 JavaScript/requirePermission.js delete mode 100644 JavaScript/serverOnly.js rename {TypeScript => plugins}/assertFields.ts (100%) rename {TypeScript => plugins}/buttonConfirmation.ts (100%) rename {TypeScript => plugins}/channelType.ts (100%) rename {TypeScript => plugins}/confirmation.ts (100%) rename {TypeScript => plugins}/cooldown.ts (100%) rename {TypeScript => plugins}/disable.ts (100%) rename {TypeScript => plugins}/dmOnly.ts (100%) rename {TypeScript => plugins}/filter.ts (100%) rename {TypeScript => plugins}/nsfwOnly.ts (100%) rename {TypeScript => plugins}/ownerOnly.ts (100%) rename {TypeScript => plugins}/permCheck.ts (100%) rename {TypeScript => plugins}/publish.ts (100%) rename {TypeScript => plugins}/requirePermission.ts (100%) rename {TypeScript => plugins}/serverOnly.ts (100%) diff --git a/.github/workflows/gen-list.yml b/.github/workflows/gen-list.yml index 19b96c5..f3014a0 100644 --- a/.github/workflows/gen-list.yml +++ b/.github/workflows/gen-list.yml @@ -1,6 +1,11 @@ name: "Generate Plugin Listing" on: + push: + branches: + - main + paths: + - 'plugins/**' workflow_dispatch: jobs: @@ -20,21 +25,13 @@ jobs: babashka-version: 1.1.173 - name: gen-list run: bb scripts/gen-list.clj - - name: Create Pull Request - id: cpr - uses: peter-evans/create-pull-request@v5-beta + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 with: - commit-message: "chore: Update plugins listing" - branch: js - delete-branch: true - branch-suffix: short-commit-hash - title: "chore: Update Plugin Listing" - body: "asfl;asdkcng;lfkv;lajf;bflglfsafs;af" - reviewers: jacoobes - - name: Enable Pull Request Automerge - if: steps.cpr.outputs.pull-request-operation == 'created' - uses: peter-evans/enable-pull-request-automerge@v2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - pull-request-number: ${{ steps.cpr.outputs.pull-request-number }} - merge-method: squash \ No newline at end of file + commit_message: "chore: update plugin listing" + commit_options: '--no-verify --signoff' + repository: . + commit_user_name: "GitHub Actions" + file_pattern: "plugins.json" + status_options: '--untracked-files=no' + push_options: '--force' \ No newline at end of file diff --git a/JavaScript/assertFields.js b/JavaScript/assertFields.js deleted file mode 100644 index 816cbe3..0000000 --- a/JavaScript/assertFields.js +++ /dev/null @@ -1,61 +0,0 @@ -//@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, controller } from "@sern/handler"; -export function assertFields(config) { - 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) => 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(); - }); -} diff --git a/JavaScript/buttonConfirmation.js b/JavaScript/buttonConfirmation.js deleted file mode 100644 index d8b4b3e..0000000 --- a/JavaScript/buttonConfirmation.js +++ /dev/null @@ -1,86 +0,0 @@ -//@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! - * Credits to original plugin of confirmation using reactions and its author! - * - * @author @EvolutionX-10 [<@697795666373640213>] - * @version 1.0.0 - * @example - * ```ts - * import { buttonConfirmation } from "../plugins/buttonConfirmation"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ buttonConfirmation() ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - ComponentType, -} from "discord.js"; -export function buttonConfirmation(options) { - 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 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()); - }); - 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, - }); - }); - }); - }); -} diff --git a/JavaScript/channelType.js b/JavaScript/channelType.js deleted file mode 100644 index 0a8278e..0000000 --- a/JavaScript/channelType.js +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-nocheck - -/** - * This plugin checks if a channel is the specified type - * - * @author @Benzo-Fury [<@762918086349029386>] - * @version 1.0.0 - * @example - * ```ts - * import { channelType } from "../plugins/channelType"; - * import { ChannelType } from "discord.js" - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ channelType([ChannelType.GuildText], 'This cannot be used here') ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { ChannelType } from "discord.js"; -import { CommandControlPlugin, controller } from "@sern/handler"; -export function channelType(channelType, onFail) { - 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(); - }); -} diff --git a/JavaScript/confirmation.js b/JavaScript/confirmation.js deleted file mode 100644 index 56cf0a3..0000000 --- a/JavaScript/confirmation.js +++ /dev/null @@ -1,115 +0,0 @@ -//@ts-nocheck - -/** - * Asks the user for a confirmation message before executing the command - * - * @author @trueharuu [<@504698587221852172>] - * @version 1.0.0 - * @example - * ```ts - * import { confirmation } from "../plugins/confirmation"; - * import { CommandType, commandModule } from "@sern/handler"; - * - * // YOU MUST HAVE GUILD MESSAGE REACTION INTENTS ON YOUR CLIENT!!!! - * export default commandModule({ - * type : CommandType.Both - * plugins: [confirmation()], - * execute: (ctx, args) => { - * ctx.interaction.followUp('Hello welcome to the secret club') - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -const defaultOptions = { - timeout: 5000, - message: "Are you sure you want to proceed?", - onTimeout: "confirmation timed out", - onCancel: "confirmation cancelled", - onConfirm: (_, result) => { - try { - result.delete(); - } catch (e) {} - }, - emojis: { - no: "❌", - yes: "✅", - }, -}; -export function confirmation(raw = {}) { - const options = Object.assign({}, defaultOptions, raw); - 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; - - if (typeof yes === "function") { - yes = await yes(context); - } - - if (typeof no === "function") { - no = await no(context); - } - - await response.react(await yes); - await response.react(await no); - - function filter(reaction, user) { - return ( - ([yes, no].includes(reaction.emoji.name) || - [yes, no].includes(reaction.emoji.identifier)) && - user.id === context.user.id - ); - } - - const recieved = await response.awaitReactions({ - filter, - max: 1, - time: options.timeout, - }); - - if (recieved.size === 0) { - if (typeof options.onTimeout === "function") { - await options.onTimeout(context, response); - } else { - await response.edit(await options.onTimeout); - await response.reactions.removeAll(); - } - - return controller.stop(); - } - - const reaction = recieved.first(); - - if (!reaction) { - return controller.stop(); - } - - switch (reaction.emoji.name) { - case await yes: - if (typeof options.onConfirm === "function") { - await options.onConfirm(context, response); - } else { - await response.edit(await options.onConfirm); - await response.reactions.removeAll(); - } - - return controller.next(); - - case await no: - if (typeof options.onCancel === "function") { - await options.onCancel(context, response); - } else { - await response.edit(await options.onCancel); - await response.reactions.removeAll(); - } - - return controller.stop(); - } - - return controller.next(); - }); -} diff --git a/JavaScript/cooldown.js b/JavaScript/cooldown.js deleted file mode 100644 index f543b60..0000000 --- a/JavaScript/cooldown.js +++ /dev/null @@ -1,133 +0,0 @@ -// @ts-nocheck - -/** - * Allows you to set cooldowns (or "ratelimits") for commands - * limits user/channel/guild actions, - * @author @trueharuu [<@504698587221852172>] - * @version 1.0.0 - * @example - * ```ts - * import { cooldown } from "../plugins/cooldown"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [cooldown.add( [ ['channel', '1/4'] ] )], // limit to 1 action every 4 seconds per channel - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -import { GuildMember } from "discord.js"; -/** - * actions/seconds - */ - -export let CooldownLocation; - -(function (CooldownLocation) { - CooldownLocation["channel"] = "channel"; - CooldownLocation["user"] = "user"; - CooldownLocation["guild"] = "guild"; -})(CooldownLocation || (CooldownLocation = {})); - -export class ExpiryMap extends Map { - constructor(expiry = Infinity, iterable = []) { - super(iterable); - this.expiry = expiry; - } - - set(key, value, expiry = this.expiry) { - super.set(key, value); - if (expiry !== Infinity) - setTimeout(() => { - super.delete(key); - }, expiry); - return this; - } -} -export const map = new ExpiryMap(); - -function parseCooldown(location, cooldown) { - const [actions, seconds] = cooldown.split("/").map((s) => Number(s)); - - if ( - !Number.isSafeInteger(actions) || - !Number.isSafeInteger(seconds) || - actions === undefined || - seconds === undefined - ) { - throw new Error(`Invalid cooldown string: ${cooldown}`); - } - - return { - actions, - seconds, - location, - }; -} - -function getPropertyForLocation(context, location) { - switch (location) { - case CooldownLocation.channel: - return context.channel.id; - - case CooldownLocation.user: - if (!context.member || !(context.member instanceof GuildMember)) { - throw new Error("context.member is not a GuildMember"); - } - - return context.member.id; - - case CooldownLocation.guild: - return context.guildId; - } -} - -function add(items, message) { - const raw = items.map((c) => { - if (!Array.isArray(c)) return c; - return parseCooldown(c[0], c[1]); - }); - return CommandControlPlugin(async (context, args) => { - 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); - } - - return controller.next(); - }); -} - -const locations = { - [CooldownLocation.channel]: (value) => - add([[CooldownLocation.channel, value]]), - [CooldownLocation.user]: (value) => add([[CooldownLocation.user, value]]), - [CooldownLocation.guild]: (value) => add([[CooldownLocation.guild, value]]), -}; -export const cooldown = { - add, - locations, - map, -}; diff --git a/JavaScript/disable.js b/JavaScript/disable.js deleted file mode 100644 index 0da784a..0000000 --- a/JavaScript/disable.js +++ /dev/null @@ -1,63 +0,0 @@ -// @ts-nocheck - -/** - * Disables a command entirely, for whatever reasons you may need. - * - * @author @jacoobes [<@182326315813306368>] - * @author @Peter-MJ-Parker [<@371759410009341952>] - * @version 2.0.0 - * @example - * ```ts - * import { disable } from "../plugins/disable"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ disable() ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -export function disable(onFail) { - return CommandControlPlugin(async (ctx, [args]) => { - if (onFail !== undefined) { - switch (args) { - case "text": - //reply to text command - const msg = await ctx.reply(onFail); - setTimeout(() => { - //deletes the bots reply to the user - msg.delete(); //deletes the original authors message (text command). - - ctx.message.delete(); //waits 5 seconds before deleting messages - }, 5000).catch((e) => { - //logs error to console (if any). - console.log(e); - }); - break; - - case "slash": - //ephemeral response to say the command is disabled with users response. - await ctx.reply({ - content: onFail, - ephemeral: true, - }); - break; - - default: - break; - } - } //this function tells the bot to reply to an interaction so it doesn't seem like it fails (in case there is no onFail message). - - if (onFail === undefined && args === "slash") { - onFail = "This command is disabled."; - await ctx.reply({ - content: onFail, - ephemeral: true, - }); - } //stop the command from running - - return controller.stop(); - }); -} diff --git a/JavaScript/dmOnly.js b/JavaScript/dmOnly.js deleted file mode 100644 index 5a2fe2f..0000000 --- a/JavaScript/dmOnly.js +++ /dev/null @@ -1,33 +0,0 @@ -// @ts-nocheck - -/** - * This is dmOnly plugin, it allows commands to be run only in DMs. - * - * @author @EvolutionX-10 [<@697795666373640213>] - * @version 1.0.0 - * @example - * ```ts - * import { dmOnly } from "../plugins/dmOnly"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [dmOnly()], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -export function dmOnly(content, ephemeral) { - // 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(); - }); -} diff --git a/JavaScript/nsfwOnly.js b/JavaScript/nsfwOnly.js deleted file mode 100644 index 138d371..0000000 --- a/JavaScript/nsfwOnly.js +++ /dev/null @@ -1,59 +0,0 @@ -//@ts-nocheck - -/** - * This plugin checks if the channel is nsfw and responds to user with a specified response if not nsfw - * - * @author @Benzo-Fury [<@762918086349029386>] - * @version 1.0.0 - * @example - * ```ts - * import { nsfwOnly } from "../plugins/nsfwOnly"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ nsfwOnly('response', true) ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { ChannelType } from "discord.js"; -import { CommandControlPlugin, controller } from "@sern/handler"; - -function isGuildText(channel) { - return ( - channel?.type == ChannelType.GuildPublicThread || - channel?.type == ChannelType.GuildPrivateThread - ); -} - -export function nsfwOnly(onFail, ephemeral) { - 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.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/JavaScript/ownerOnly.js b/JavaScript/ownerOnly.js deleted file mode 100644 index 03114f0..0000000 --- a/JavaScript/ownerOnly.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-nocheck - -/** - * This is OwnerOnly plugin, it allows only bot owners to run the command, like eval. - * - * @author @EvolutionX-10 [<@697795666373640213>] - * @version 1.2.0 - * @example - * ```ts - * import { ownerOnly } from "../plugins/ownerOnly"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ ownerOnly() ], // can also pass array of IDs to override default owner IDs - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -const ownerIDs = ["697795666373640213"]; //! Fill your ID - -export function ownerOnly(override) { - return CommandControlPlugin((ctx) => { - if ((override ?? 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/JavaScript/permCheck.js b/JavaScript/permCheck.js deleted file mode 100644 index b57ee21..0000000 --- a/JavaScript/permCheck.js +++ /dev/null @@ -1,39 +0,0 @@ -// @ts-nocheck - -/** - * This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check user for that perm). - * - * @author @Benzo-Fury [<@762918086349029386>] - * @version 1.0.1 - * @example - * ```ts - * import { permCheck } from "../plugins/permCheck"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ permCheck('permission', 'No permission response') ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; -export function permCheck(perm, response) { - 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.permissions.has(perm)) { - await ctx.reply(response); - return controller.stop(); - } - - return controller.next(); - }); -} diff --git a/JavaScript/publish.js b/JavaScript/publish.js deleted file mode 100644 index 86f23b9..0000000 --- a/JavaScript/publish.js +++ /dev/null @@ -1,166 +0,0 @@ -// @ts-nocheck - -/** - * This is publish plugin, it allows you to publish your application commands using the discord.js library with ease. - * - * @author @EvolutionX-10 [<@697795666373640213>] - * @version 2.0.0 - * @example - * ```ts - * import { publish } from "../plugins/publish"; - * import { commandModule } from "@sern/handler"; - * export default commandModule({ - * plugins: [ publish() ], // put an object containing permissions, ids for guild commands, boolean for dmPermission - * // plugins: [ publish({ guildIds: ['guildId'], defaultMemberPermissions: 'Administrator'})] - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandInitPlugin, CommandType, controller } from "@sern/handler"; -import { - ApplicationCommandType, - ApplicationCommandOptionType, -} from "discord.js"; -import { useContainer } from "../index.js"; -export const CommandTypeRaw = { - [CommandType.Both]: ApplicationCommandType.ChatInput, - [CommandType.CtxUser]: ApplicationCommandType.User, - [CommandType.CtxMsg]: ApplicationCommandType.Message, - [CommandType.Slash]: ApplicationCommandType.ChatInput, -}; -export function publish(options) { - return CommandInitPlugin(async ({ module }) => { - // Users need to provide their own useContainer function. - const [client] = useContainer("@sern/client"); - const defaultOptions = { - guildIds: [], - dmPermission: undefined, - defaultMemberPermissions: null, - }; - options = { ...defaultOptions, ...options }; - let { defaultMemberPermissions, dmPermission, guildIds } = options; - - function c(e) { - console.error("publish command didnt work for", module.name); - console.error(e); - } - - const log = - (...message) => - () => - console.log(...message); - - const logged = (...message) => 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) => { - return (is, els) => ((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.options ?? []), []), - defaultMemberPermissions, - dmPermission, - }; - }; - - 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) { - return ops.map((el) => { - switch (el.type) { - case ApplicationCommandOptionType.String: - case ApplicationCommandOptionType.Number: - case ApplicationCommandOptionType.Integer: { - return el.autocomplete && "command" in el - ? (({ command, ...el }) => el)(el) - : el; - } - - default: - return el; - } - }); -} diff --git a/JavaScript/requirePermission.js b/JavaScript/requirePermission.js deleted file mode 100644 index 8b8dc3d..0000000 --- a/JavaScript/requirePermission.js +++ /dev/null @@ -1,91 +0,0 @@ -// @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). - * - * @author @Benzo-Fury [<@762918086349029386>] - * @author @needhamgary [<@342314924804014081>] - * @version 1.2.0 - * @example - * ```ts - * import { requirePermission } from "../plugins/myPermCheck"; - * import { commandModule, CommandType } from "@sern/handler"; - * export default commandModule({ - * plugins: [ requirePermission('target', 'permission', 'No response (optional)') ], - * execute: (ctx) => { - * //your code here - * } - * }) - * ``` - */ -import { CommandControlPlugin, controller } from "@sern/handler"; - -function payload(resp) { - return { - fetchReply: true, - content: resp, - allowedMentions: { - repliedUser: false, - }, - ephemeral: true, - }; -} - -export function requirePermission(target, perm, response) { - 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, - }); - const memm = ctx.member; - - 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(); - } - }); -} diff --git a/JavaScript/serverOnly.js b/JavaScript/serverOnly.js deleted file mode 100644 index b93ec4e..0000000 --- a/JavaScript/serverOnly.js +++ /dev/null @@ -1,43 +0,0 @@ -// @ts-nocheck - -/** - * Checks if a command is available in a specific server. - * - * @author @Peter-MJ-Parker [<@371759410009341952>] - * @version 1.0.0 - * @example - * ```ts - * import { commandModule, CommandType } from "@sern/handler"; - * import { serverOnly } from "../plugins/serverOnly"; - * export default commandModule({ - * type: CommandType.Both, - * plugins: [serverOnly(["guildId"], failMessage)], // fail message is the message you will see when the command is ran in the wrong server. - * description: "command description", - * execute: async (ctx, args) => { - * // your code here - * }, - * }); - * ``` - */ -import { controller, CommandControlPlugin } from "@sern/handler"; -export function serverOnly( - guildId, - 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(); - }); -} diff --git a/pluginlist.json b/pluginlist.json index d7d0e87..dccb252 100644 --- a/pluginlist.json +++ b/pluginlist.json @@ -3,7 +3,7 @@ "hash" : "2da46f3202e2b209ab24620d4f890da2", "name" : "assertFields", "author" : [ "@jacoobes [<@182326315813306368>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/assertFields.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/assertFields.ts", "example" : "\n\n ```ts\n export default commandModule({\n type: CommandType.Modal,\n plugins: [\n assertFields({\n fields: {\n // check the modal field \"mcUsernameInput\" with the regex /a+b+c/\n mcUsernameInput: /a+b+c+/\n },\n failure: (errors, interaction) => {\n interaction.reply(errors.join(\"\\n\"))\n }\n }),\n ],\n execute: ctx => {\n ctx.reply(\"nice!\")\n }\n })\n ```\n\n/", "version" : "1.0.0" }, { @@ -11,7 +11,7 @@ "hash" : "d752596f5d9871e469d142ccf5569691", "name" : "buttonConfirmation", "author" : [ "@EvolutionX-10 [<@697795666373640213>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/buttonConfirmation.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/buttonConfirmation.ts", "example" : "\n\n ```ts\n import { buttonConfirmation } from \"../plugins/buttonConfirmation\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ buttonConfirmation() ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```", "version" : "1.0.0" }, { @@ -19,7 +19,7 @@ "hash" : "a3f95ec62e1480b8c3318443cc8184c0", "name" : "channelType", "author" : [ "@Benzo-Fury [<@762918086349029386>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/channelType.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/channelType.ts", "example" : "\n\n ```ts\n import { channelType } from \"../plugins/channelType\";\n import { ChannelType } from \"discord.js\"\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ channelType([ChannelType.GuildText], 'This cannot be used here') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```", "version" : "1.0.0" }, { @@ -27,7 +27,7 @@ "hash" : "77e7cc0e4f9706183d2debb918056809", "name" : "confirmation", "author" : [ "@trueharuu [<@504698587221852172>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/confirmation.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/confirmation.ts", "example" : "\n\n ```ts\n import { confirmation } from \"../plugins/confirmation\";\n import { CommandType, commandModule } from \"@sern/handler\";\n\n // YOU MUST HAVE GUILD MESSAGE REACTION INTENTS ON YOUR CLIENT!!!!\n export default commandModule({\n type : CommandType.Both\n plugins: [confirmation()],\n \texecute: (ctx, args) => {\n \t\tctx.interaction.followUp('Hello welcome to the secret club')\n \t}\n })\n ```", "version" : "1.0.0" }, { @@ -35,7 +35,7 @@ "hash" : "5dfb3c2f533878a15cf9764ffb921d1e", "name" : "cooldown", "author" : [ "@trueharuu [<@504698587221852172>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/cooldown.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/cooldown.ts", "example" : "\n\n ```ts\n import { cooldown } from \"../plugins/cooldown\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [cooldown.add( [ ['channel', '1/4'] ] )], // limit to 1 action every 4 seconds per channel\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```", "version" : "1.0.0" }, { @@ -43,7 +43,7 @@ "hash" : "96e4b5b562500b0bcdc442fbf130a555", "name" : "disable", "author" : [ "@jacoobes [<@182326315813306368>]", "@Peter-MJ-Parker [<@371759410009341952>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/disable.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/disable.ts", "example" : "\n\n ```ts\n import { disable } from \"../plugins/disable\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ disable() ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "2.0.0" }, { @@ -51,7 +51,7 @@ "hash" : "844e68aa0c9147c98930b34a5d716a22", "name" : "dmOnly", "author" : [ "@EvolutionX-10 [<@697795666373640213>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/dmOnly.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/dmOnly.ts", "example" : "\n\n ```ts\n import { dmOnly } from \"../plugins/dmOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [dmOnly()],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "1.0.0" }, { @@ -59,7 +59,7 @@ "hash" : "ba85e67d23bbfacc337f82e9fade283c", "name" : "filter", "author" : [ "@trueharuu [<@504698587221852172>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/filter.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/filter.ts", "example" : "\n\n import { filter, not, isGuildOwner, canMentionEveryone } from '../plugins/filter';\n import { commandModule } from '@sern/handler';\n\n export default commandModule({\n plugins: [filter({ condition: [not(isGuildOwner()), canMentionEveryone()] })],\n async execute(context) {\n // your code here\n }\n });", "version" : "2.0.0" }, { @@ -67,7 +67,7 @@ "hash" : "65ff8138fd20486d6eeff17cdb7b93cf", "name" : "nsfwOnly", "author" : [ "@Benzo-Fury [<@762918086349029386>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/nsfwOnly.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/nsfwOnly.ts", "example" : "\n\n ```ts\n import { nsfwOnly } from \"../plugins/nsfwOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ nsfwOnly('response', true) ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "1.0.0" }, { @@ -75,7 +75,7 @@ "hash" : "5ffb76d3a2ecdb0516fa98a93dd1d15d", "name" : "ownerOnly", "author" : [ "@EvolutionX-10 [<@697795666373640213>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/ownerOnly.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/ownerOnly.ts", "example" : "\n\n ```ts\n import { ownerOnly } from \"../plugins/ownerOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ ownerOnly() ], // can also pass array of IDs to override default owner IDs\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "1.2.0" }, { @@ -83,7 +83,7 @@ "hash" : "45fb62d9ffe908469ea58aabb550daf7", "name" : "permCheck", "author" : [ "@Benzo-Fury [<@762918086349029386>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/permCheck.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/permCheck.ts", "example" : "\n\n ```ts\n import { permCheck } from \"../plugins/permCheck\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ permCheck('permission', 'No permission response') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```", "version" : "1.0.1" }, { @@ -91,7 +91,7 @@ "hash" : "3f76c395a51cccc9c66de9ea65d28b19", "name" : "publish", "author" : [ "@EvolutionX-10 [<@697795666373640213>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/publish.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/publish.ts", "example" : "\n\n ```ts\n import { publish } from \"../plugins/publish\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ publish() ], // put an object containing permissions, ids for guild commands, boolean for dmPermission\n // plugins: [ publish({ guildIds: ['guildId'], defaultMemberPermissions: 'Administrator'})]\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "2.0.0" }, { @@ -99,7 +99,7 @@ "hash" : "bad95c4cf2105d9f60363ddf16ab7b82", "name" : "requirePermission", "author" : [ "@Benzo-Fury [<@762918086349029386>]", "@needhamgary [<@342314924804014081>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/requirePermission.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/requirePermission.ts", "example" : "\n\n ```ts\n import { requirePermission } from \"../plugins/myPermCheck\";\n import { commandModule, CommandType } from \"@sern/handler\";\n export default commandModule({\n plugins: [ requirePermission('target', 'permission', 'No response (optional)') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ", "version" : "1.2.0" }, { @@ -107,7 +107,7 @@ "hash" : "b1d78678451c260286a97de8f1cb9e07", "name" : "serverOnly", "author" : [ "@Peter-MJ-Parker [<@371759410009341952>]" ], - "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/serverOnly.ts", + "link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/serverOnly.ts", "example" : "\n\n ```ts\n import { commandModule, CommandType } from \"@sern/handler\";\n import { serverOnly } from \"../plugins/serverOnly\";\n export default commandModule({\n type: CommandType.Both,\n plugins: [serverOnly([\"guildId\"], failMessage)], // fail message is the message you will see when the command is ran in the wrong server.\n description: \"command description\",\n execute: async (ctx, args) => {\n // your code here\n },\n });\n ```", "version" : "1.0.0" } ] \ No newline at end of file diff --git a/TypeScript/assertFields.ts b/plugins/assertFields.ts similarity index 100% rename from TypeScript/assertFields.ts rename to plugins/assertFields.ts diff --git a/TypeScript/buttonConfirmation.ts b/plugins/buttonConfirmation.ts similarity index 100% rename from TypeScript/buttonConfirmation.ts rename to plugins/buttonConfirmation.ts diff --git a/TypeScript/channelType.ts b/plugins/channelType.ts similarity index 100% rename from TypeScript/channelType.ts rename to plugins/channelType.ts diff --git a/TypeScript/confirmation.ts b/plugins/confirmation.ts similarity index 100% rename from TypeScript/confirmation.ts rename to plugins/confirmation.ts diff --git a/TypeScript/cooldown.ts b/plugins/cooldown.ts similarity index 100% rename from TypeScript/cooldown.ts rename to plugins/cooldown.ts diff --git a/TypeScript/disable.ts b/plugins/disable.ts similarity index 100% rename from TypeScript/disable.ts rename to plugins/disable.ts diff --git a/TypeScript/dmOnly.ts b/plugins/dmOnly.ts similarity index 100% rename from TypeScript/dmOnly.ts rename to plugins/dmOnly.ts diff --git a/TypeScript/filter.ts b/plugins/filter.ts similarity index 100% rename from TypeScript/filter.ts rename to plugins/filter.ts diff --git a/TypeScript/nsfwOnly.ts b/plugins/nsfwOnly.ts similarity index 100% rename from TypeScript/nsfwOnly.ts rename to plugins/nsfwOnly.ts diff --git a/TypeScript/ownerOnly.ts b/plugins/ownerOnly.ts similarity index 100% rename from TypeScript/ownerOnly.ts rename to plugins/ownerOnly.ts diff --git a/TypeScript/permCheck.ts b/plugins/permCheck.ts similarity index 100% rename from TypeScript/permCheck.ts rename to plugins/permCheck.ts diff --git a/TypeScript/publish.ts b/plugins/publish.ts similarity index 100% rename from TypeScript/publish.ts rename to plugins/publish.ts diff --git a/TypeScript/requirePermission.ts b/plugins/requirePermission.ts similarity index 100% rename from TypeScript/requirePermission.ts rename to plugins/requirePermission.ts diff --git a/TypeScript/serverOnly.ts b/plugins/serverOnly.ts similarity index 100% rename from TypeScript/serverOnly.ts rename to plugins/serverOnly.ts diff --git a/scripts/gen-list.clj b/scripts/gen-list.clj index 20c28e9..8c073eb 100644 --- a/scripts/gen-list.clj +++ b/scripts/gen-list.clj @@ -8,8 +8,8 @@ (io/file (str "./" name))) (defn make-link [name] - (str "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/" name)) - + (str "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/plugins/" name)) + (defn name-without-extension [name] (if-let [last-dot-index (str/last-index-of name ".")] (subs name 0 last-dot-index) @@ -59,7 +59,7 @@ (defn file-data [plugin-name] "gets all jsdoc content. Transforms into lazy seq of data" - (let [file (io/file (str "./TypeScript/" plugin-name)) + (let [file (io/file (str "./plugins/" plugin-name)) ; We start a plugin metadata block. ; this will transform the first JSDOC block that ; starts with a @plugin tag @@ -97,16 +97,16 @@ (map (fn [file] (let [ fname (get-filename file) - file-data (file-data fname)] - (conj (hash-map + file-data (file-data fname)] + (conj (hash-map :name (name-without-extension fname) :link (make-link fname) :hash (copy+md5 file (java.io.OutputStream/nullOutputStream))) file-data )))))) -(def json (generate-content "./TypeScript") ) +(def json (generate-content "./plugins") ) (json/generate-stream json (io/writer "pluginlist.json") { :pretty true }) -(println "\nGenerated Plugins!") +(println "Generated Plugins!")