feat: awesome automations (#104)

This commit is contained in:
Evo
2023-09-02 10:59:59 +05:30
committed by GitHub
parent 63253dce8f
commit 877291964c
30 changed files with 35 additions and 999 deletions

View File

@@ -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
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'

View File

@@ -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();
});
}

View File

@@ -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,
});
});
});
});
}

View File

@@ -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();
});
}

View File

@@ -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();
});
}

View File

@@ -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,
};

View File

@@ -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();
});
}

View File

@@ -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();
});
}

View File

@@ -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();
});
}

View File

@@ -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!
});
}

View File

@@ -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();
});
}

View File

@@ -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;
}
});
}

View File

@@ -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<CommandType>('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();
}
});
}

View File

@@ -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();
});
}

View File

@@ -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<CommandType>('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"
} ]

View File

@@ -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!")