-
- 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.
-
+ 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.
+