From 39750cb2b56ada4b7d1e90f6f8f70a5c3906603b Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sat, 8 Mar 2025 23:24:08 -0500 Subject: [PATCH] remove virus --- .prettierrc.json | 6 + UserpluginInstallButton.tsx | 17 ++- UserpluginInstallModal.tsx | 80 ---------- index.tsx | 23 +-- native.ts | 287 ++++++++++-------------------------- pluginValidate.txt | 158 ++++++++++++++++++++ 6 files changed, 253 insertions(+), 318 deletions(-) create mode 100644 .prettierrc.json delete mode 100644 UserpluginInstallModal.tsx create mode 100644 pluginValidate.txt diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..c92f75e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "useTabs": false, + "tabWidth": 4, + "semi": true, + "singleQuote": false +} diff --git a/UserpluginInstallButton.tsx b/UserpluginInstallButton.tsx index 71032a9..0e6c570 100644 --- a/UserpluginInstallButton.tsx +++ b/UserpluginInstallButton.tsx @@ -24,10 +24,21 @@ export default function UserpluginInstallButton({ props }: any) { }} onClick={async () => { try { - await Native.initPluginInstall(gitLink[0], gitLink[1], gitLink[2], gitLink[3]); - + const pluginToEnable = await Native.initPluginInstall(gitLink[0], gitLink[1], gitLink[2], gitLink[3]); + Alerts.show({ + title: "Done!", + body: `${pluginToEnable} has been successfully installed. What now?`, + confirmText: "Enable & refresh", + cancelText: "Refresh", + secondaryConfirmText: "I'll refresh later", + onConfirm() { + !Vencord.Plugins.plugins[pluginToEnable] ? Vencord.Settings.plugins[pluginToEnable] = { enabled: true } : Vencord.Settings.plugins[pluginToEnable].enabled = true; + window.location.reload(); + }, + onCancel: window.location.reload + }); } - catch (e) { + catch (e: any) { if (e.toString().includes("silentStop")) return; Alerts.show({ title: "Install error", diff --git a/UserpluginInstallModal.tsx b/UserpluginInstallModal.tsx deleted file mode 100644 index 0427870..0000000 --- a/UserpluginInstallModal.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { classNameFactory } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { PluginCard } from "@components/PluginSettings"; -import { ModalCloseButton, ModalContent, ModalHeader, ModalRoot, ModalSize, openModal, closeModal } from "@utils/modal"; -import { Alerts, Button, Card, Parser, Text, Toasts } from "@webpack/common"; -import { Native } from "."; - -const cl = classNameFactory("vc-userplugininstaller-"); - -export function showInstallModal(meta: any, pluginPath: string) { - console.log(meta); - Alerts.show({ - title: <> -
- Review userplugin -
- , - body: <> -
- - Plugin info - - - - {meta.name} - {meta.description} - - - - Notes & warnings - - { - meta.usesPreSend && - - Has pre-send listeners - This plugin is able to intercept and edit messages before sending them. - - - } - - - Refresh and enable required - After the install is completed, Discord will be reloaded and you will need to enable the plugin yourself. - - - Make sure that the plugin author is trustworthy before installing {meta.name}. -
- , - cancelText: "Cancel install", - confirmText: `Install plugin`, - onCancel() { - Native.deleteFolder(pluginPath); - }, - onCloseCallback() { - setTimeout(() => { - Native.deleteFolder(pluginPath); - }, 20000); - }, - async onConfirm() { - Toasts.pop(); - Toasts.show({ - message: "Rebuilding Vencord, please wait...", - id: Toasts.genId(), - type: Toasts.Type.MESSAGE - }); - try { - await Native.build(pluginPath); - window.location.reload(); - } - catch { - Toasts.pop(); - return Toasts.show({ - message: "Something bad has happened while building Vencord.", - id: Toasts.genId(), - type: Toasts.Type.FAILURE - }); - } - }, - }); -} diff --git a/index.tsx b/index.tsx index 07611de..f6e7012 100644 --- a/index.tsx +++ b/index.tsx @@ -8,7 +8,6 @@ import "./style.css"; import { Devs } from "@utils/constants"; import definePlugin, { PluginNative } from "@utils/types"; -import { Alerts, TextInput } from "@webpack/common"; import UserpluginInstallButton from "./UserpluginInstallButton"; @@ -23,27 +22,7 @@ export default definePlugin({ name: "UserpluginInstaller", description: "Install userplugins with a simple button click", authors: [Devs.nin0dev], - renderMessageAccessory: (props) => { + renderMessageAccessory: props => { return ; - }, - toolboxActions: { - "Install Plugin": () => { - let gitUrl = ""; - Alerts.show({ - title: "Install plugin", - body: <> - { gitUrl = v; }} placeholder="Git link (https://github.com/...)" /> - , - confirmText: "Install", - async onConfirm() { - const gitLink = gitUrl.match(CLONE_LINK_REGEX)!; - await Native.initPluginInstall(gitLink[0], gitLink[1], gitLink[2], gitLink[3]); - window.location.reload(); - } - }); - }, - "Uninstall Plugin": () => { - - } } }); diff --git a/native.ts b/native.ts index d417258..1f40b9c 100644 --- a/native.ts +++ b/native.ts @@ -10,88 +10,88 @@ import { existsSync, readdirSync, readFileSync } from "fs"; import { rm } from "fs/promises"; import { join } from "path"; +// @ts-ignore fuck off +import pluginValidateContent from "./pluginValidate.txt"; // i would use HTML but esbuild is being whiny + const PLUGIN_META_REGEX = /export default definePlugin\((?:\s|\/(?:\/|\*).*)*{\s*(?:\s|\/(?:\/|\*).*)*name:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*,(?:\s|\/(?:\/|\*).*)*(?:\s|\/(?:\/|\*).*)*description:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*/; const CLONE_LINK_REGEX = /https:\/\/((?:git(?:hub|lab)\.com|git\.(?:[a-zA-Z0-9]|\.)+|codeberg\.org))\/(?!user-attachments)((?:[a-zA-Z0-9]|-)+)\/((?:[a-zA-Z0-9]|-)+)(?:\.git)?(?:\/)?/; -export async function initPluginInstall(_, link: string, source: string, owner: string, repo: string) { - const verifiedRegex = link.match(CLONE_LINK_REGEX)!; - if (verifiedRegex.length !== 4 || verifiedRegex[0] !== link || verifiedRegex[1] !== source || verifiedRegex[2] !== owner || verifiedRegex[3] !== repo) return; +export async function initPluginInstall(_, link: string, source: string, owner: string, repo: string): Promise { + // eslint-disable-next-line + return new Promise(async (resolve, reject) => { + const verifiedRegex = link.match(CLONE_LINK_REGEX)!; + if (verifiedRegex.length !== 4 || verifiedRegex[0] !== link || verifiedRegex[1] !== source || verifiedRegex[2] !== owner || verifiedRegex[3] !== repo) return reject("Invalid link"); - // Ask for clone - const cloneDialog = await dialog.showMessageBox({ - title: "Clone userplugin", - message: `You are about to clone a userplugin from ${source}.`, - type: "question", - detail: `The repository name is "${repo}" and it is owned by "${owner}".\nThe repository URL is ${link}\n\n(If you did not request this intentionally, choose Cancel)`, - buttons: ["Cancel", "Clone repository and continue install", "Open repository in browser"] - }); - switch (cloneDialog.response) { - case 0: { - throw "Rejected by user"; - } - case 1: { - await cloneRepo(link, repo); - break; - } - case 2: { - await shell.openExternal(link); - throw "silentStop"; - } - } - - // Get plugin meta - const meta = await getPluginMeta(join(__dirname, "..", "src", "userplugins", repo)); - - // Review plugin - const win = new BrowserWindow({ - maximizable: false, - minimizable: false, - width: 560, - height: meta.usesNative || meta.usesPreSend ? 650 : 360, - resizable: false, - webPreferences: { - devTools: true - }, - title: "Review userplugin", - modal: true, - parent: BrowserWindow.getAllWindows()[0], - show: false, - autoHideMenuBar: true - }); - const reView /* haha got it */ = new BrowserView({ - webPreferences: { - devTools: true, - nodeIntegration: true - } - }); - win.setBrowserView(reView); - win.addBrowserView(reView); - win.setTopBrowserView(reView); - win.loadURL(generateReviewPluginContent(meta)); - win.on("page-title-updated", async e => { - switch (win.webContents.getTitle() as "abortInstall" | "reviewCode" | "install") { - case "abortInstall": { - win.close(); - await rm(join(__dirname, "..", "src", "userplugins", repo), { - recursive: true - }); - throw "Rejected by user"; + // Ask for clone + const cloneDialog = await dialog.showMessageBox({ + title: "Clone userplugin", + message: `You are about to clone a userplugin from ${source}.`, + type: "question", + detail: `The repository name is "${repo}" and it is owned by "${owner}".\nThe repository URL is ${link}\n\n(If you did not request this intentionally, choose Cancel)`, + buttons: ["Cancel", "Clone repository and continue install", "Open repository in browser"] + }); + switch (cloneDialog.response) { + case 0: { + return reject("Rejected by user"); + } + case 1: { + await cloneRepo(link, repo); break; } - case "reviewCode": { - win.close(); - shell.openPath(join(__dirname, "..", "src", "userplugins", repo)); - throw "A file explorer window should've been opened with your plugin"; - break; - } - case "install": { - win.close(); - await build(); - break; + case 2: { + await shell.openExternal(link); + return reject("silentStop"); } } + + // Get plugin meta + const meta = await getPluginMeta(join(__dirname, "..", "src", "userplugins", repo)); + + // Review plugin + const win = new BrowserWindow({ + maximizable: false, + minimizable: false, + width: 560, + height: meta.usesNative || meta.usesPreSend ? 650 : 360, + resizable: false, + webPreferences: { + devTools: true + }, + title: "Review userplugin", + modal: true, + parent: BrowserWindow.getAllWindows()[0], + show: false, + autoHideMenuBar: true + }); + const reView /* haha got it */ = new BrowserView({ + webPreferences: { + devTools: true, + nodeIntegration: true + } + }); + win.setBrowserView(reView); + win.addBrowserView(reView); + win.setTopBrowserView(reView); + win.loadURL(generateReviewPluginContent(meta)); + win.on("page-title-updated", async e => { + switch (win.webContents.getTitle() as "abortInstall" | "reviewCode" | "install") { + case "abortInstall": { + win.close(); + await rm(join(__dirname, "..", "src", "userplugins", repo), { + recursive: true + }); + return reject("Rejected by user"); + } + case "install": { + win.close(); + await build(); + resolve(meta.name); + break; + } + } + }); + win.show(); }); - win.show(); } async function build(): Promise { @@ -169,146 +169,7 @@ function generateReviewPluginContent(meta: { usesPreSend: boolean; usesNative: boolean; }): string { - const template = ` - - - - - - Review userplugin - - - - -

Plugin info

-
-

%PLUGINNAME%

-

%PLUGINDESC%

-
- -

Warnings

-
-

Uses a native.ts file

-

- Use of this file allows the plugin to escape the browser sandbox and - potentially do anything to your system and data. - ONLY INSTALL THIS PLUGIN AFTER REVIEWING THE CODE AND BEING 100% SURE - THAT NOTHING BAD CAN BE DONE! -

-
- Acknowledge warning (required to allow install) -
-
-

Has pre-send listeners

-

This allows the plugin to edit your messages before they are sent.

-
-

- Reminder: installing a userplugin can be a destructive action. Make sure that you know and trust the developer before installing any. -

-
- - - -
- - -`.replace("%PLUGINNAME%", meta.name.replaceAll("<", "<")).replace("%PLUGINDESC%", meta.description.replaceAll("<", "<")).replace("%WARNINGHIDER%", !meta.usesNative && !meta.usesPreSend ? "[data-useless=\"warning\"] { display: none !important; }" : "").replace("%NATIVETSHIDER%", meta.usesNative ? "" : "#native-ts-warning { display: none !important; }").replace("%PRESENDHIDER%", meta.usesPreSend ? "" : "#pre-send-warning { display: none !important; }"); + const template = pluginValidateContent.replace("%PLUGINNAME%", meta.name.replaceAll("<", "<")).replace("%PLUGINDESC%", meta.description.replaceAll("<", "<")).replace("%WARNINGHIDER%", !meta.usesNative && !meta.usesPreSend ? "[data-useless=\"warning\"] { display: none !important; }" : "").replace("%NATIVETSHIDER%", meta.usesNative ? "" : "#native-ts-warning { display: none !important; }").replace("%PRESENDHIDER%", meta.usesPreSend ? "" : "#pre-send-warning { display: none !important; }"); const buf = Buffer.from(template).toString("base64"); return `data:text/html;base64,${buf}`; } diff --git a/pluginValidate.txt b/pluginValidate.txt new file mode 100644 index 0000000..9486605 --- /dev/null +++ b/pluginValidate.txt @@ -0,0 +1,158 @@ + + + + + + Review userplugin + + + + %WARNINGHIDER% %NATIVETSHIDER% %PRESENDHIDER% + + + +

Plugin info

+
+

%PLUGINNAME%

+

%PLUGINDESC%

+
+ +

Warnings

+
+

Uses a native.ts file

+

+ Use of this file allows the plugin to escape the browser sandbox + and potentially do anything to your system and data. + ONLY INSTALL THIS PLUGIN AFTER REVIEWING THE CODE AND BEING + 100% SURE THAT NOTHING BAD CAN BE DONE! +

+
+ Acknowledge warning (required to allow + install) +
+
+

Has pre-send listeners

+

+ This allows the plugin to edit your messages before they are + sent. +

+
+

+ Reminder: installing a userplugin can be a destructive action. Make + sure that you know and trust the developer before installing any. +

+
+ + +
+ +