From 0bff31afd1737140c4bceeff1e0d9eaeb50776e5 Mon Sep 17 00:00:00 2001 From: Evo <85353424+EvolutionX-10@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:18:21 +0530 Subject: [PATCH] feat: updated plugins to co-ordinate with automations (#36) --- .gitignore | 1 + src/commands/handlers/falseTrigger.ts | 2 +- src/commands/handlers/tagCreate.ts | 5 +- src/commands/handlers/tagEdit.ts | 5 +- src/commands/plugin.ts | 67 +++++++++++---------------- src/commands/refresh.ts | 46 ++++++++---------- src/commands/tag.ts | 17 +++---- src/commands/tags.ts | 12 ++--- src/constants.ts | 3 ++ src/events/tagDetect.ts | 5 +- src/index.ts | 4 +- src/plugins/index.ts | 1 - src/plugins/refreshCache.ts | 26 ----------- src/types/index.ts | 1 - src/utils/FuzzyMatcher.ts | 2 +- src/utils/cutText.ts | 6 +++ src/utils/index.ts | 2 + src/utils/require.ts | 2 + {src/types => typings}/Tags.ts | 0 typings/index.ts | 3 ++ typings/plugin.ts | 9 ++++ 21 files changed, 99 insertions(+), 120 deletions(-) delete mode 100644 src/plugins/refreshCache.ts delete mode 100644 src/types/index.ts create mode 100644 src/utils/cutText.ts create mode 100644 src/utils/require.ts rename {src/types => typings}/Tags.ts (100%) create mode 100644 typings/index.ts create mode 100644 typings/plugin.ts diff --git a/.gitignore b/.gitignore index b10a080..26e1ee3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .env .vscode/ .idea/ +pluginlist.json # Yarn files .yarn/install-state.gz .yarn/build-state.yml diff --git a/src/commands/handlers/falseTrigger.ts b/src/commands/handlers/falseTrigger.ts index 9808638..140b687 100644 --- a/src/commands/handlers/falseTrigger.ts +++ b/src/commands/handlers/falseTrigger.ts @@ -1,5 +1,5 @@ import { commandModule, CommandType } from "@sern/handler"; -import type { TagMessage } from "../../types"; +import type { TagMessage } from "typings"; export default commandModule({ type: CommandType.Button, diff --git a/src/commands/handlers/tagCreate.ts b/src/commands/handlers/tagCreate.ts index 5c6776c..f00d4c0 100644 --- a/src/commands/handlers/tagCreate.ts +++ b/src/commands/handlers/tagCreate.ts @@ -1,7 +1,8 @@ import { commandModule, CommandType } from "@sern/handler"; import { existsSync, writeFileSync } from "fs"; -import type { TagData } from "../../types"; +import type { TagData } from "typings"; import { createRequire } from "module"; +import { TagList } from "#constants"; const require = createRequire(import.meta.url); export default commandModule({ @@ -32,7 +33,7 @@ export default commandModule({ const tags = [tag]; writeFileSync(filePath, JSON.stringify(tags, null, 2)); } else { - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); if (file.find((t) => t.name === tagName)) { return ctx.reply(`Tag __${tagName}__ already exists`); diff --git a/src/commands/handlers/tagEdit.ts b/src/commands/handlers/tagEdit.ts index be7ba1e..7b11e12 100644 --- a/src/commands/handlers/tagEdit.ts +++ b/src/commands/handlers/tagEdit.ts @@ -1,7 +1,8 @@ +import { TagList } from "#constants"; import { commandModule, CommandType } from "@sern/handler"; import { writeFileSync } from "fs"; import { createRequire } from "module"; -import type { TagData } from "../../types"; +import type { TagData } from "typings"; const require = createRequire(import.meta.url); export default commandModule({ @@ -25,7 +26,7 @@ export default commandModule({ : [], }; const filePath = `./tags.json`; - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const oldTag = file.find((t) => t.name === (ctx.user.data as { tag: string }).tag)!; const similarKeywords = file.filter( diff --git a/src/commands/plugin.ts b/src/commands/plugin.ts index 17c3572..b661723 100644 --- a/src/commands/plugin.ts +++ b/src/commands/plugin.ts @@ -1,7 +1,8 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; import { cooldown, publish } from "#plugins"; -import { parse } from "jsdoc-parse-plus"; -import { slashCommand } from "#utils"; +import { slashCommand, require, cutText } from "#utils"; +import type { Plugin } from "typings"; +import { PluginList } from "#constants"; export default slashCommand({ description: "View sern plugins", @@ -15,17 +16,20 @@ export default slashCommand({ command: { onEvent: [], async execute(ctx) { - const { cache } = ctx.client; - const focus = ctx.options.getFocused(); - if (!cache) return ctx.respond([{ name: "No plugins found", value: "" }]); - const data = [...cache.values()] as Data[]; + const plugins = require(PluginList) as Plugin[]; + + const focus = ctx.options.getFocused(); + if (!plugins.length) return ctx.respond([{ name: "No plugins found", value: "" }]); + + const filtered = plugins.filter((p) => + p.name.toLowerCase().includes(focus.toLowerCase()) + ); - const plugins = data.map((d) => { - const name = d.name.replace(".ts", ""); - return { name, value: d.download_url }; - }); return ctx.respond( - plugins.filter((p) => p.name.toLowerCase().includes(focus?.toLowerCase())) + filtered.map((p) => ({ + name: p.name, + value: p.link, + })) ); }, }, @@ -41,38 +45,38 @@ export default slashCommand({ ), ], async execute(ctx, [, options]) { - if (!ctx.client.cache) return ctx.reply("Plugins are uncached, contact Evo!"); + const plugins = require(PluginList) as Plugin[]; + + if (!plugins.length) return ctx.reply("Plugins are uncached, contact Evo!"); const url = options.getString("plugin", true); - const name = ctx.client.cache.findKey((d) => d.download_url === url) as string; + const plugin = plugins.find((p) => p.link === url); - if (!name || !ctx.client.cache.get(name)!.rawData) + if (!plugin) { return ctx.reply(`No plugin found at this [link](<${url}>)`); - - const JSdoc = parse(ctx.client.cache.get(name)!.rawData) as A; - const github = `https://github.com/sern-handler/awesome-plugins/blob/main/TypeScript/${name}.ts`; + } const embed = new EmbedBuilder() .setColor("Random") .setTimestamp() - .setTitle(`${name}`) - .setURL(github) + .setTitle(plugin.name) + .setURL(plugin.link) .setFields( { name: "Description", - value: JSdoc.description.value, + value: plugin.description, }, { name: "Version", - value: JSdoc.version.value, + value: plugin.version, }, { name: "Author", - value: parseAuthor(JSdoc.author.value), + value: plugin.author.map(parseAuthor).join("\n"), }, { name: "Example", - value: (JSdoc as unknown as B).example[0].value, + value: plugin.example, } ); @@ -94,20 +98,3 @@ export interface Data { download_url: string; rawData: string; } - -interface ParsedData { - author: DocData; - description: DocData; - version: DocData; - example: DocData[]; - requires?: DocData[]; -} - -interface DocData { - tag: string; - value: string; - raw: string; -} - -type A = Record; -type B = Record; diff --git a/src/commands/refresh.ts b/src/commands/refresh.ts index 28b9960..f467313 100644 --- a/src/commands/refresh.ts +++ b/src/commands/refresh.ts @@ -1,13 +1,11 @@ -import { Collection, Client } from "discord.js"; -import { fetch } from "undici"; -import type { Data } from "./plugin.js"; -import { ownerOnly, publish, refreshCache } from "#plugins"; -import { Evo } from "#constants"; +import { writeFileSync } from "fs"; +import { ownerOnly, publish } from "#plugins"; +import { Evo, PluginList } from "#constants"; import { slashCommand } from "#utils"; +import type { Plugin } from "typings"; export default slashCommand({ plugins: [ - refreshCache(), publish({ dmPermission: false, defaultMemberPermissions: ["Administrator"], @@ -16,31 +14,25 @@ export default slashCommand({ ], description: "refresh plugins cache", async execute(ctx) { - const success = await cp(ctx.client); - if (!success) - return ctx.reply({ - content: "Fetch failed!", - ephemeral: true, - }); - return ctx.reply({ - content: `Refreshed Plugins! [${success.size} plugins]`, - ephemeral: true, + await ctx.interaction.deferReply({ ephemeral: true }); + const size = await cp(); + if (!size) return ctx.interaction.editReply({ content: "Fetch failed!" }); + return ctx.interaction.editReply({ + content: `Refreshed ${size} Plugins!`, }); }, }); -export async function cp(client: Client) { - const cache: Collection = new Collection(); - const link = `https://api.github.com/repos/sern-handler/awesome-plugins/contents/TypeScript`; +/** + * Downloads the plugin list from github and writes it to the cache + * @returns {Promise} The number of plugins fetched + */ +export async function cp(): Promise { + const link = `https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/pluginlist.json`; const resp = await fetch(link).catch(() => null); if (!resp) return null; - const dataArray = (await resp.json()) as Data[]; - // TODO: use octokit instead of fetch - for (const data of dataArray) { - const name = data.name.replace(".ts", ""); - data.rawData = await (await fetch(data.download_url)).text().catch(() => ""); - cache.set(name, data); - } - client.cache = cache; - return cache; + const dataArray = (await resp.json()) as Plugin[]; + + writeFileSync(PluginList, JSON.stringify(dataArray, null, 2), { flag: "w" }); + return dataArray.length; } diff --git a/src/commands/tag.ts b/src/commands/tag.ts index d246381..51862cb 100644 --- a/src/commands/tag.ts +++ b/src/commands/tag.ts @@ -1,11 +1,9 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; import { existsSync } from "fs"; import { publish } from "#plugins"; -import { Paginator, slashCommand } from "#utils"; - -import { createRequire } from "module"; -import type { TagData } from "../types/index.js"; -const require = createRequire(import.meta.url); +import { Paginator, slashCommand, require } from "#utils"; +import { Tag, type TagData } from "typings"; +import { TagList } from "#constants"; export default slashCommand({ description: "Send a tag", @@ -30,12 +28,11 @@ export default slashCommand({ command: { onEvent: [], execute(ctx) { - const filePath = `./tags.json`; const focus = ctx.options.getFocused(); - if (!existsSync(filePath)) { + if (!existsSync(`./tags.json`)) { return ctx.respond([{ name: "No tags found", value: "" }]); } else { - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const tags = file.map((t) => t.name); return ctx.respond( tags @@ -62,7 +59,7 @@ export default slashCommand({ const subCmd = options.getSubcommand(); switch (subCmd) { case "list": { - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const embeds = file.map((tag) => { const embed = new EmbedBuilder() .setTitle(tag.name) @@ -91,7 +88,7 @@ export default slashCommand({ const user = options.getUser("target"); const mention = user ? `**Tag suggestion for:** ${user}\n\n` : ""; const tag = options.getString("tag", true); - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const tagData = file.find((t) => t.name === tag); if (!tagData) { return ctx.reply(`No tag found with name __${tag}__`); diff --git a/src/commands/tags.ts b/src/commands/tags.ts index eb8f0ff..a3ac301 100644 --- a/src/commands/tags.ts +++ b/src/commands/tags.ts @@ -7,9 +7,9 @@ import { } from "discord.js"; import { existsSync, writeFileSync } from "fs"; import { createRequire } from "module"; -import { Evo, Seren } from "#constants"; +import { Evo, Seren, TagList } from "#constants"; import { ownerOnly, publish } from "#plugins"; -import type { TagData } from "../types"; +import type { TagData } from "typings"; import { slashCommand } from "#utils"; const require = createRequire(import.meta.url); @@ -41,7 +41,7 @@ export default slashCommand({ if (!existsSync(filePath)) { return ctx.respond([{ name: "No tags found", value: "" }]); } else { - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const tags = file.map((t) => t.name); return ctx.respond( tags @@ -75,7 +75,7 @@ export default slashCommand({ if (!existsSync(filePath)) { return ctx.respond([{ name: "No tags found", value: "" }]); } else { - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); const tags = file.map((t) => t.name); return ctx.respond( tags @@ -95,7 +95,7 @@ export default slashCommand({ const [, options] = args; const subcmd = options.getSubcommand(); - const file: TagData[] = require(`${process.cwd()}/tags.json`); + const file: TagData[] = require(TagList); if (subcmd === "create") { const modal = new ModalBuilder().setTitle("Tag Creation").setCustomId("@sern/tag/create"); @@ -185,7 +185,7 @@ export default slashCommand({ return context.reply("Tag not found"); } file.splice(file.indexOf(tagData), 1); - writeFileSync(`${process.cwd()}/tags.json`, JSON.stringify(file, null, 2)); + writeFileSync(TagList, JSON.stringify(file, null, 2)); return context.reply(`Tag ${tag} deleted`); } diff --git a/src/constants.ts b/src/constants.ts index e43dcf0..d24d31c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,3 +13,6 @@ export const enum Emojis { IssueClosed = "<:issue_closed:1101716515771920424>", IssueNotPlanned = "<:issue_notplanned:1101719419434045540>", } + +export const PluginList = `${process.cwd()}/pluginlist.json`; +export const TagList = `${process.cwd()}/tags.json`; \ No newline at end of file diff --git a/src/events/tagDetect.ts b/src/events/tagDetect.ts index c85c0f8..8649a02 100644 --- a/src/events/tagDetect.ts +++ b/src/events/tagDetect.ts @@ -2,9 +2,10 @@ import { eventModule, EventType } from "@sern/handler"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, Message } from "discord.js"; import { createRequire } from "module"; import { FuzzyMatcher } from "../utils/FuzzyMatcher.js"; -import type { TagData, TagMessage } from "../types/index.js"; +import type { TagData, TagMessage } from "typings"; +import { TagList } from "#constants"; const require = createRequire(import.meta.url); -const file: TagData[] = require(`${process.cwd()}/tags.json`); +const file: TagData[] = require(TagList); export default eventModule({ type: EventType.Discord, diff --git a/src/index.ts b/src/index.ts index 1d92ca7..ce3582d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { Dependencies, Sern, single, Singleton } from "@sern/handler"; import "dotenv/config"; import { randomStatus, SernLogger /*CommandSyncer*/ } from "#utils"; import { Octokit } from "@octokit/rest"; +import { cp } from "./commands/refresh.js"; const client = new Client({ intents: [ @@ -48,10 +49,11 @@ Sern.init({ }, }); -client.once("ready", (client) => { +client.once("ready", async (client) => { randomStatus(client); const [logger] = useContainer("@sern/logger"); logger.info({ message: `[✅]: Logged in as ${client.user.username}` }); + await cp(); }); await client.login(); diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 86fd3c5..6bdc183 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -2,4 +2,3 @@ export * from "./channelOnly.js"; export * from "./cooldown.js"; export * from "./ownerOnly.js"; export * from "./publish.js"; -export * from "./refreshCache.js"; diff --git a/src/plugins/refreshCache.ts b/src/plugins/refreshCache.ts deleted file mode 100644 index 2d0eb97..0000000 --- a/src/plugins/refreshCache.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { - CommandInitPlugin, - CommandPlugin, - CommandType, - controller, - PluginType, -} from "@sern/handler"; -import type { Collection } from "discord.js"; -import { cp } from "../commands/refresh.js"; -import type { Data } from "../commands/plugin.js"; -import { useContainer } from "../../src/index.js"; -export function refreshCache() { - return CommandInitPlugin(async (payload) => { - const [client] = useContainer("@sern/client"); - const cache = await cp(client); - client.cache = cache; - return controller.next(); - }); -} - -declare module "discord.js" { - interface Client { - cache: Collection | null; - data: unknown; - } -} diff --git a/src/types/index.ts b/src/types/index.ts deleted file mode 100644 index a37b5a5..0000000 --- a/src/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Tags.js"; diff --git a/src/utils/FuzzyMatcher.ts b/src/utils/FuzzyMatcher.ts index 3f22937..70ec806 100644 --- a/src/utils/FuzzyMatcher.ts +++ b/src/utils/FuzzyMatcher.ts @@ -1,6 +1,6 @@ import type { Message, User } from "discord.js"; import { findBestMatch } from "string-similarity"; -import type { TagData } from "../types/index.js"; +import type { TagData } from "typings"; export class FuzzyMatcher { public constructor(private readonly message: Message, private readonly tags: TagData[]) {} diff --git a/src/utils/cutText.ts b/src/utils/cutText.ts new file mode 100644 index 0000000..4a15b88 --- /dev/null +++ b/src/utils/cutText.ts @@ -0,0 +1,6 @@ +export function cutText(text: string) { + if (text.length > 100) { + return text.slice(0, 97) + "..."; + } + return text; +} \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts index 04e6641..6a62dcc 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,4 +8,6 @@ export * from "./randomStatus.js"; export * from "./codeUpload.js"; export * from "./Logger.js"; export * from "./composable/slashCommand.js"; +export * from "./require.js"; +export * from "./cutText.js"; //export * from './SyncCommands.js'; diff --git a/src/utils/require.ts b/src/utils/require.ts new file mode 100644 index 0000000..a5ff0f3 --- /dev/null +++ b/src/utils/require.ts @@ -0,0 +1,2 @@ +import { createRequire } from "module"; +export const require = createRequire(import.meta.url); diff --git a/src/types/Tags.ts b/typings/Tags.ts similarity index 100% rename from src/types/Tags.ts rename to typings/Tags.ts diff --git a/typings/index.ts b/typings/index.ts new file mode 100644 index 0000000..ba3ab85 --- /dev/null +++ b/typings/index.ts @@ -0,0 +1,3 @@ +export * from './docs.js' +export * from './plugin.js' +export * from './Tags.js' \ No newline at end of file diff --git a/typings/plugin.ts b/typings/plugin.ts new file mode 100644 index 0000000..9ab6ec1 --- /dev/null +++ b/typings/plugin.ts @@ -0,0 +1,9 @@ +export interface Plugin { + description: string; + hash: string; + name: string; + author: string[]; + link: string; + example: string; + version: string; +}