From f6baa8dcfbc549ed188b0ba1270c76d1da28312a Mon Sep 17 00:00:00 2001 From: kmmiio99o <164557248+kmmiio99o@users.noreply.github.com> Date: Sat, 27 Sep 2025 19:40:15 +0200 Subject: [PATCH] Add plugin-list and theme-list commands with detailed options --- package.json | 52 +++--- plugins/all-in-one/index.ts | 273 +++++++++++++++++++++++++++++--- plugins/all-in-one/settings.tsx | 145 +++++++++-------- 3 files changed, 354 insertions(+), 116 deletions(-) diff --git a/package.json b/package.json index a4d53bb..750821e 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,29 @@ { - "scripts": { - "build": "node build.mjs", - "watch": "node build.mjs -w", - "lint": "eslint plugins", - "make": "node make.mjs" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^24.1.0", - "@rollup/plugin-node-resolve": "^15.0.2", - "@swc/core": "^1.3.51", - "@types/react": "^18.0.37", - "@types/react-native": "^0.70.13", - "@typescript-eslint/eslint-plugin": "^5.59.0", - "@typescript-eslint/parser": "^5.59.0", - "esbuild": "^0.17.17", - "eslint": "^8.38.0", - "eslint-plugin-react": "^7.32.2", - "rollup": "^3.20.6", - "rollup-plugin-esbuild": "^5.0.0", - "typescript": "^4.9.5", - "vendetta-types": "^2.4.18" - }, - "dependencies": { - "@swc/helpers": "^0.5.0" - } + "scripts": { + "build": "node build.mjs", + "watch": "node build.mjs -w", + "lint": "eslint plugins", + "make": "node make.mjs", + "serve": "node serve.mjs" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "@swc/core": "^1.3.51", + "@types/react": "^18.0.37", + "@types/react-native": "^0.70.13", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "esbuild": "^0.17.17", + "eslint": "^8.38.0", + "eslint-plugin-react": "^7.32.2", + "rollup": "^3.20.6", + "rollup-plugin-esbuild": "^5.0.0", + "typescript": "^4.9.5", + "vendetta-types": "^2.4.18" + }, + "dependencies": { + "@swc/helpers": "^0.5.0", + "serve": "^14.2.5" + } } diff --git a/plugins/all-in-one/index.ts b/plugins/all-in-one/index.ts index e8c6549..eb860b7 100644 --- a/plugins/all-in-one/index.ts +++ b/plugins/all-in-one/index.ts @@ -1,27 +1,30 @@ import { registerCommand } from "@vendetta/commands"; import { findByStoreName, findByProps } from "@vendetta/metro"; import { storage } from "@vendetta/plugin"; +import { themes } from "@vendetta/themes"; +import { plugins } from "@vendetta/plugins"; +import { alerts } from "@vendetta/ui"; import settings from "./settings"; const UserStore = findByStoreName("UserStore"); const MessageActions = findByProps("sendMessage"); +const Clyde = findByProps("sendBotMessage"); + +const maxMessageLength = + UserStore.getCurrentUser()?.premiumType === 2 ? 4000 : 2000; let commands: Array<() => void> = []; -// Initialize storage with default values if not set -if (!storage.factSettings) { - storage.factSettings = { - sendAsReply: true, - includeCitation: false, - }; -} +// Constants +const STATUS = { + ENABLED: "🟢", + DISABLED: "🔴", + SELECTED: "🔶", + NOT_SELECTED: "🔷", +} as const; -if (!storage.listSettings) { - storage.listSettings = { - pluginListAlwaysDetailed: false, - themeListAlwaysDetailed: false, - }; -} +const SPLIT_LARGE_MESSAGES_PLUGIN = + "https://vd-plugins.github.io/proxy/actuallythesun.github.io/vendetta-plugins/SplitLargeMessages/"; // API Functions const uselessFact = async () => { @@ -61,16 +64,15 @@ async function getPetPetData(image: string) { return body; } -// Helper function to format fact response +// Helper Functions const formatFactResponse = (fact: { text: string; source?: string }) => { let response = fact.text; - if (storage.factSettings.includeCitation && fact.source) { + if (storage.factSettings?.includeCitation && fact.source) { response += `\n\nSource: ${fact.source}`; } return response; }; -// Helper function to send message const sendMessage = ( channelId: string, content: string, @@ -79,17 +81,173 @@ const sendMessage = ( const fixNonce = Date.now().toString(); const message = { content, - ...(replyToId && storage.factSettings.sendAsReply + ...(replyToId && storage.factSettings?.sendAsReply ? { messageReference: { messageId: replyToId } } : {}), }; - MessageActions.sendMessage(channelId, message, undefined, { - nonce: fixNonce, - }); + + MessageActions.sendMessage(channelId, message, void 0, { nonce: fixNonce }); return { type: 4 }; // Acknowledge the command }; -// Command Definitions +const addonAuthors = (authors: Array<{ name: string }>) => + authors.map((author) => author.name).join(", "); + +const formatList = (list: string[]) => list.join("\n").trimEnd(); + +const getListLength = (list: string[]) => formatList(list).length; + +const sendList = async (channelID: string, list: string[]) => { + const fixNonce = Date.now().toString(); + await MessageActions.sendMessage( + channelID, + { content: formatList(list) }, + void 0, + { nonce: fixNonce }, + ); +}; + +const isSLMPluginInstalled = () => + Object.keys(plugins).includes(SPLIT_LARGE_MESSAGES_PLUGIN); + +const isSLMPluginEnabled = () => { + const plugin = Object.values(plugins).find( + (p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN, + ); + return plugin?.enabled ?? false; +}; + +// Command Handlers +async function handleThemeList(detailed: boolean, ctx: any) { + const alwaysDetailed = storage.themeListAlwaysDetailed ?? false; + const themeList = [ + `**My Theme List | ${Object.keys(themes).length} Themes**`, + "", + ]; + + const themeValues = Object.values(themes); + if (themeValues.length) { + for (const theme of themeValues) { + const { selected, data, id } = theme; + const { name, description, authors } = data; + + if (detailed || alwaysDetailed) { + themeList.push( + `> **Name**: ${name}`, + `> **Selected**: ${selected ? STATUS.SELECTED : STATUS.NOT_SELECTED}`, + `> **Description**: ${description}`, + `> **Authors**: ${addonAuthors(authors)}`, + `> **[Install!](${id})**`, + "", + ); + } else { + themeList.push( + `> ${selected ? STATUS.SELECTED : STATUS.NOT_SELECTED} **${name}** by ${addonAuthors(authors)}`, + ); + } + } + } else { + themeList.push("Nothing to see here, huh..."); + } + + const isListTooLong = getListLength(themeList) > maxMessageLength; + + if (isListTooLong && !isSLMPluginInstalled()) { + const fixNonce = Date.now().toString(); + Clyde.sendBotMessage( + ctx.channel.id, + `Your list is too long to send it! Please install the [Split Large Messages](${SPLIT_LARGE_MESSAGES_PLUGIN}) plugin.`, + void 0, + { nonce: fixNonce }, + ); + return { type: 4 }; + } else if (isListTooLong && !isSLMPluginEnabled()) { + const fixNonce = Date.now().toString(); + Clyde.sendBotMessage( + ctx.channel.id, + "Your list is too long to send it! You have the Split Large Messages plugin installed, but it's not enabled!\n> Please enable it in order to send the list.", + void 0, + { nonce: fixNonce }, + ); + return { type: 4 }; + } + + if (getListLength(themeList) > 2000) { + return alerts.showConfirmationAlert({ + content: "Your list is over than 2000 characters. Are you sure?", + confirmText: "Yes", + cancelText: "No", + onConfirm: async () => await sendList(ctx.channel.id, themeList), + }); + } + + await sendList(ctx.channel.id, themeList); + return { type: 4 }; +} + +async function handlePluginList(detailed: boolean, ctx: any) { + const alwaysDetailed = storage.pluginListAlwaysDetailed ?? false; + const pluginList = [ + `**My Plugin List | ${Object.keys(plugins).length} Plugins**`, + "", + ]; + + for (const plugin of Object.values(plugins)) { + const { enabled, manifest, id } = plugin; + const { name, description, authors } = manifest; + + if (detailed || alwaysDetailed) { + pluginList.push( + `> **Name**: ${name}`, + `> **Status**: ${enabled ? STATUS.ENABLED : STATUS.DISABLED}`, + `> **Description**: ${description}`, + `> **Authors**: ${addonAuthors(authors)}`, + `> **[Install!](${id})**`, + "", + ); + } else { + pluginList.push( + `> ${enabled ? STATUS.ENABLED : STATUS.DISABLED} **${name}** by ${addonAuthors(authors)}`, + ); + } + } + + const isListTooLong = getListLength(pluginList) > maxMessageLength; + + if (isListTooLong && !isSLMPluginInstalled()) { + const fixNonce = Date.now().toString(); + Clyde.sendBotMessage( + ctx.channel.id, + `Your list is too long to send it! Please install the [Split Large Messages](${SPLIT_LARGE_MESSAGES_PLUGIN}) plugin.`, + void 0, + { nonce: fixNonce }, + ); + return { type: 4 }; + } else if (isListTooLong && !isSLMPluginEnabled()) { + const fixNonce = Date.now().toString(); + Clyde.sendBotMessage( + ctx.channel.id, + "Your list is too long to send it! You have the Split Large Messages plugin installed, but it's not enabled!\n> Please enable it in order to send the list.", + void 0, + { nonce: fixNonce }, + ); + return { type: 4 }; + } + + if (getListLength(pluginList) > 2000) { + return alerts.showConfirmationAlert({ + content: "Your list is over than 2000 characters. Are you sure?", + confirmText: "Yes", + cancelText: "No", + onConfirm: async () => await sendList(ctx.channel.id, pluginList), + }); + } + + await sendList(ctx.channel.id, pluginList); + return { type: 4 }; +} + +// Register Commands const registerCommands = () => { // Cat Facts Command commands.push( @@ -182,8 +340,81 @@ const registerCommands = () => { type: 1, }), ); + + // Plugin List Command + commands.push( + registerCommand({ + name: "plugin-list", + displayName: "plugin list", + description: "Send your plugin list to the current channel", + displayDescription: "Send your plugin list to the current channel", + options: [ + { + name: "detailed", + description: "Whether to send a list with detailed information.", + type: 5, + required: false, + displayName: "detailed", + displayDescription: + "Whether to send a list with detailed information.", + }, + ], + execute: async (args, ctx) => { + const detailed = + args.find((arg) => arg.name === "detailed")?.value ?? false; + return handlePluginList(detailed, ctx); + }, + applicationId: "-1", + inputType: 1, + type: 1, + }), + ); + + // Theme List Command + commands.push( + registerCommand({ + name: "theme-list", + displayName: "theme list", + description: "Send your theme list to the current channel", + displayDescription: "Send your theme list to the current channel", + options: [ + { + name: "detailed", + description: "Whether to send a list with detailed information.", + type: 5, + required: false, + displayName: "detailed", + displayDescription: + "Whether to send a list with detailed information.", + }, + ], + execute: async (args, ctx) => { + const detailed = + args.find((arg) => arg.name === "detailed")?.value ?? false; + return handleThemeList(detailed, ctx); + }, + applicationId: "-1", + inputType: 1, + type: 1, + }), + ); }; +// Initialize storage +if (!storage.factSettings) { + storage.factSettings = { + sendAsReply: true, + includeCitation: false, + }; +} + +if (!storage.listSettings) { + storage.listSettings = { + pluginListAlwaysDetailed: false, + themeListAlwaysDetailed: false, + }; +} + export default { onLoad: () => { console.log("[All-In-One Commands] Plugin loaded!"); diff --git a/plugins/all-in-one/settings.tsx b/plugins/all-in-one/settings.tsx index 48acc0e..3a84421 100644 --- a/plugins/all-in-one/settings.tsx +++ b/plugins/all-in-one/settings.tsx @@ -5,80 +5,85 @@ import { getAssetIDByName } from "@vendetta/ui/assets"; import { ErrorBoundary, Forms } from "@vendetta/ui/components"; const { FormSwitchRow, FormIcon, FormSection, FormDivider } = Forms; + const Icons = { - List: getAssetIDByName('ic_list'), - Copy: getAssetIDByName('ic_copy_message_link'), - Settings: getAssetIDByName('ic_settings'), - Fact: getAssetIDByName('ic_info') + List: getAssetIDByName("ic_list"), + Message: getAssetIDByName("ic_message"), + Copy: getAssetIDByName("ic_copy_message_link"), + Info: getAssetIDByName("ic_info"), + Theme: getAssetIDByName("ic_theme"), + Plugin: getAssetIDByName("ic_plugins"), }; -// Initialize storage with default values if not set -if (!storage.factSettings) { - storage.factSettings = { - sendAsReply: true, - includeCitation: false - }; -} - -if (!storage.listSettings) { - storage.listSettings = { - pluginListAlwaysDetailed: false, - themeListAlwaysDetailed: false - }; -} - export default () => { - useProxy(storage); + useProxy(storage); - return ( - - - {/* Plugin List Settings */} - - } - onValueChange={(value: boolean) => { - storage.listSettings.pluginListAlwaysDetailed = value; - }} - value={storage.listSettings.pluginListAlwaysDetailed} - /> - - } - onValueChange={(value: boolean) => { - storage.listSettings.themeListAlwaysDetailed = value; - }} - value={storage.listSettings.themeListAlwaysDetailed} - /> - + if (!storage.factSettings) { + storage.factSettings = { + sendAsReply: true, + includeCitation: false, + }; + } - {/* Fact Command Settings */} - - } - onValueChange={(value: boolean) => { - storage.factSettings.sendAsReply = value; - }} - value={storage.factSettings.sendAsReply} - /> - - } - onValueChange={(value: boolean) => { - storage.factSettings.includeCitation = value; - }} - value={storage.factSettings.includeCitation} - /> - - - - ); + if (!storage.listSettings) { + storage.listSettings = { + pluginListAlwaysDetailed: false, + themeListAlwaysDetailed: false, + }; + } + + return ( + + + {/* Fact Commands Settings */} + + } + onValueChange={(value: boolean) => { + storage.factSettings.sendAsReply = value; + }} + value={storage.factSettings.sendAsReply} + /> + + } + onValueChange={(value: boolean) => { + storage.factSettings.includeCitation = value; + }} + value={storage.factSettings.includeCitation} + /> + + + {/* Plugin List Settings */} + + } + onValueChange={(value: boolean) => { + storage.listSettings.pluginListAlwaysDetailed = value; + }} + value={storage.listSettings.pluginListAlwaysDetailed} + /> + + + {/* Theme List Settings */} + + } + onValueChange={(value: boolean) => { + storage.listSettings.themeListAlwaysDetailed = value; + }} + value={storage.listSettings.themeListAlwaysDetailed} + /> + + + + ); };