remove virus
This commit is contained in:
parent
ec4e8ff39a
commit
39750cb2b5
6 changed files with 253 additions and 318 deletions
6
.prettierrc.json
Normal file
6
.prettierrc.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"useTabs": false,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false
|
||||||
|
}
|
|
@ -24,10 +24,21 @@ export default function UserpluginInstallButton({ props }: any) {
|
||||||
}}
|
}}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
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;
|
if (e.toString().includes("silentStop")) return;
|
||||||
Alerts.show({
|
Alerts.show({
|
||||||
title: "Install error",
|
title: "Install error",
|
||||||
|
|
|
@ -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: <>
|
|
||||||
<div className={cl("title")}>
|
|
||||||
Review userplugin
|
|
||||||
</div>
|
|
||||||
</>,
|
|
||||||
body: <>
|
|
||||||
<div className={cl("body")}>
|
|
||||||
<Text className={cl("subheader")}>
|
|
||||||
Plugin info
|
|
||||||
</Text>
|
|
||||||
<Card className={cl(["card", "lead-card"])}>
|
|
||||||
<Text>
|
|
||||||
<Text className={cl("name")}>{meta.name}</Text>
|
|
||||||
<Text className={cl("desc")}>{meta.description}</Text>
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
<Text className={cl("subheader")}>
|
|
||||||
Notes & warnings
|
|
||||||
</Text>
|
|
||||||
{
|
|
||||||
meta.usesPreSend && <Card className={cl(["card", "warning-card"])}>
|
|
||||||
<Text>
|
|
||||||
<Text className={cl("name")}>Has pre-send listeners</Text>
|
|
||||||
<Text className={cl("desc")}>This plugin is able to intercept and edit messages before sending them.</Text>
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
}
|
|
||||||
<Card className={cl(["card"])}>
|
|
||||||
<Text>
|
|
||||||
<Text className={cl("name")}>Refresh and enable required</Text>
|
|
||||||
<Text className={cl("desc")}>After the install is completed, Discord will be reloaded and you will need to enable the plugin yourself.</Text>
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
<Text style={{ color: "var(--text-danger) !important", margin: "3px 0" }}>Make sure that the plugin author is trustworthy before installing {meta.name}.</Text>
|
|
||||||
</div>
|
|
||||||
</>,
|
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
23
index.tsx
23
index.tsx
|
@ -8,7 +8,6 @@ import "./style.css";
|
||||||
|
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { PluginNative } from "@utils/types";
|
import definePlugin, { PluginNative } from "@utils/types";
|
||||||
import { Alerts, TextInput } from "@webpack/common";
|
|
||||||
|
|
||||||
import UserpluginInstallButton from "./UserpluginInstallButton";
|
import UserpluginInstallButton from "./UserpluginInstallButton";
|
||||||
|
|
||||||
|
@ -23,27 +22,7 @@ export default definePlugin({
|
||||||
name: "UserpluginInstaller",
|
name: "UserpluginInstaller",
|
||||||
description: "Install userplugins with a simple button click",
|
description: "Install userplugins with a simple button click",
|
||||||
authors: [Devs.nin0dev],
|
authors: [Devs.nin0dev],
|
||||||
renderMessageAccessory: (props) => {
|
renderMessageAccessory: props => {
|
||||||
return <UserpluginInstallButton props={props} />;
|
return <UserpluginInstallButton props={props} />;
|
||||||
},
|
|
||||||
toolboxActions: {
|
|
||||||
"Install Plugin": () => {
|
|
||||||
let gitUrl = "";
|
|
||||||
Alerts.show({
|
|
||||||
title: "Install plugin",
|
|
||||||
body: <>
|
|
||||||
<TextInput onChange={v => { 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": () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
165
native.ts
165
native.ts
|
@ -10,12 +10,17 @@ import { existsSync, readdirSync, readFileSync } from "fs";
|
||||||
import { rm } from "fs/promises";
|
import { rm } from "fs/promises";
|
||||||
import { join } from "path";
|
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 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)?(?:\/)?/;
|
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) {
|
export async function initPluginInstall(_, link: string, source: string, owner: string, repo: string): Promise<string> {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
const verifiedRegex = link.match(CLONE_LINK_REGEX)!;
|
const verifiedRegex = link.match(CLONE_LINK_REGEX)!;
|
||||||
if (verifiedRegex.length !== 4 || verifiedRegex[0] !== link || verifiedRegex[1] !== source || verifiedRegex[2] !== owner || verifiedRegex[3] !== repo) return;
|
if (verifiedRegex.length !== 4 || verifiedRegex[0] !== link || verifiedRegex[1] !== source || verifiedRegex[2] !== owner || verifiedRegex[3] !== repo) return reject("Invalid link");
|
||||||
|
|
||||||
// Ask for clone
|
// Ask for clone
|
||||||
const cloneDialog = await dialog.showMessageBox({
|
const cloneDialog = await dialog.showMessageBox({
|
||||||
|
@ -27,7 +32,7 @@ export async function initPluginInstall(_, link: string, source: string, owner:
|
||||||
});
|
});
|
||||||
switch (cloneDialog.response) {
|
switch (cloneDialog.response) {
|
||||||
case 0: {
|
case 0: {
|
||||||
throw "Rejected by user";
|
return reject("Rejected by user");
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
await cloneRepo(link, repo);
|
await cloneRepo(link, repo);
|
||||||
|
@ -35,7 +40,7 @@ export async function initPluginInstall(_, link: string, source: string, owner:
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
await shell.openExternal(link);
|
await shell.openExternal(link);
|
||||||
throw "silentStop";
|
return reject("silentStop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,23 +80,18 @@ export async function initPluginInstall(_, link: string, source: string, owner:
|
||||||
await rm(join(__dirname, "..", "src", "userplugins", repo), {
|
await rm(join(__dirname, "..", "src", "userplugins", repo), {
|
||||||
recursive: true
|
recursive: true
|
||||||
});
|
});
|
||||||
throw "Rejected by user";
|
return reject("Rejected by user");
|
||||||
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": {
|
case "install": {
|
||||||
win.close();
|
win.close();
|
||||||
await build();
|
await build();
|
||||||
|
resolve(meta.name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
win.show();
|
win.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function build(): Promise<any> {
|
async function build(): Promise<any> {
|
||||||
|
@ -169,146 +169,7 @@ function generateReviewPluginContent(meta: {
|
||||||
usesPreSend: boolean;
|
usesPreSend: boolean;
|
||||||
usesNative: boolean;
|
usesNative: boolean;
|
||||||
}): string {
|
}): string {
|
||||||
const template = `
|
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; }");
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Review userplugin</title>
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
document.querySelector("#abort").addEventListener("click", () => {
|
|
||||||
document.title = "abortInstall";
|
|
||||||
})
|
|
||||||
document.querySelector("#review").addEventListener("click", () => {
|
|
||||||
document.title = "reviewCode";
|
|
||||||
})
|
|
||||||
document.querySelector("#install").addEventListener("click", () => {
|
|
||||||
if(!document.querySelector("style").innerHTML.includes("#native-ts-warning { display: none !important; }") && !document.querySelector("input[type='checkbox']").checked) return alert("Make sure to acknowledge all warnings before installing.");
|
|
||||||
document.title = "install";
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
font-family: sans-serif;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
background-color: #202020;
|
|
||||||
padding: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.card {
|
|
||||||
padding: 10px 12px;
|
|
||||||
border: 1px solid grey;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-bottom: 10px; /* Added margin for better spacing */
|
|
||||||
}
|
|
||||||
.warn-card {
|
|
||||||
border-color: #ffde00;
|
|
||||||
background-color: #ffde0011;
|
|
||||||
}
|
|
||||||
.danger-card {
|
|
||||||
border-color: #ff0000;
|
|
||||||
background-color: #ff000022;
|
|
||||||
h3 {
|
|
||||||
color: #ffaaaa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.card * {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.card h3 {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
input[type="checkbox"] {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
#validate {
|
|
||||||
color: #ffaaaa;
|
|
||||||
}
|
|
||||||
#btn-row {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
#btn-row * {
|
|
||||||
flex:1;
|
|
||||||
margin: 5px;
|
|
||||||
padding: 10px 5px;
|
|
||||||
border: 1px solid white;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
#abort {
|
|
||||||
background-color: #aa3030;
|
|
||||||
}
|
|
||||||
#review {
|
|
||||||
background-color: #303030;
|
|
||||||
}
|
|
||||||
#install {
|
|
||||||
background-color: #002000;
|
|
||||||
}
|
|
||||||
#abort:hover {
|
|
||||||
background-color: #bb3030;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
#review:hover {
|
|
||||||
background-color: #404040;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
#install:hover {
|
|
||||||
background-color: #003000;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
%WARNINGHIDER%
|
|
||||||
%NATIVETSHIDER%
|
|
||||||
%PRESENDHIDER%
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Plugin info</h2>
|
|
||||||
<div class="card" id="plugin-info-card">
|
|
||||||
<h3>%PLUGINNAME%</h3>
|
|
||||||
<p>%PLUGINDESC%</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 data-useless="warning">Warnings</h2>
|
|
||||||
<div data-useless="warning" class="card danger-card" id="native-ts-warning">
|
|
||||||
<h3>Uses a native.ts file</h3>
|
|
||||||
<p>
|
|
||||||
Use of this file allows the plugin to escape the browser sandbox and
|
|
||||||
potentially do anything to your system and data.
|
|
||||||
<b
|
|
||||||
>ONLY INSTALL THIS PLUGIN AFTER REVIEWING THE CODE AND BEING 100% SURE
|
|
||||||
THAT NOTHING BAD CAN BE DONE!</b
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<input type="checkbox" /> Acknowledge warning (required to allow install)
|
|
||||||
</div>
|
|
||||||
<div data-useless="warning" class="card warn-card" id="pre-send-warning">
|
|
||||||
<h3>Has pre-send listeners</h3>
|
|
||||||
<p>This allows the plugin to edit your messages before they are sent.</p>
|
|
||||||
</div>
|
|
||||||
<p id="validate">
|
|
||||||
Reminder: installing a userplugin can be a destructive action. Make sure that you know and trust the developer before installing any.
|
|
||||||
</p>
|
|
||||||
<div id="btn-row">
|
|
||||||
<button id="abort">
|
|
||||||
Cancel installation
|
|
||||||
</button>
|
|
||||||
<button id="review">
|
|
||||||
Review source code
|
|
||||||
</button>
|
|
||||||
<button id="install">
|
|
||||||
Install plugin
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`.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");
|
const buf = Buffer.from(template).toString("base64");
|
||||||
return `data:text/html;base64,${buf}`;
|
return `data:text/html;base64,${buf}`;
|
||||||
}
|
}
|
||||||
|
|
158
pluginValidate.txt
Normal file
158
pluginValidate.txt
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Review userplugin</title>
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
document
|
||||||
|
.querySelector("#abort")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
document.title = "abortInstall";
|
||||||
|
});
|
||||||
|
document
|
||||||
|
.querySelector("#install")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
if (
|
||||||
|
!document
|
||||||
|
.querySelector("style")
|
||||||
|
.innerHTML.includes(
|
||||||
|
"#native-ts-warning { display: none !important; }"
|
||||||
|
) &&
|
||||||
|
!document.querySelector("input[type='checkbox']")
|
||||||
|
.checked
|
||||||
|
)
|
||||||
|
return alert(
|
||||||
|
"Make sure to acknowledge all warnings before installing."
|
||||||
|
);
|
||||||
|
document.title = "install";
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("style").innerHTML +=
|
||||||
|
document.querySelector("addAtRuntimeStyle").innerHTML;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
addAtRuntimeStyle {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #cdd6f4;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: #1e1e2e;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #9399b2;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 10px; /* Added margin for better spacing */
|
||||||
|
}
|
||||||
|
.warn-card {
|
||||||
|
border-color: #f38ba8;
|
||||||
|
background-color: #313244;
|
||||||
|
}
|
||||||
|
.danger-card {
|
||||||
|
border-color: #f38ba8;
|
||||||
|
background-color: #313244;
|
||||||
|
h3 {
|
||||||
|
color: #cdd6f4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.card h3 {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
#validate {
|
||||||
|
color: #f38ba8;
|
||||||
|
}
|
||||||
|
#btn-row {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
#btn-row * {
|
||||||
|
flex: 1;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 10px 5px;
|
||||||
|
border: 1px solid #cdd6f4;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
#abort {
|
||||||
|
background-color: #f38ba8;
|
||||||
|
color: #11111b;
|
||||||
|
}
|
||||||
|
#install {
|
||||||
|
color: #a6e3a1;
|
||||||
|
border-color: #a6e3a1;
|
||||||
|
background-color: #00000000;
|
||||||
|
}
|
||||||
|
#abort:hover {
|
||||||
|
background-color: #ec9393;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#install:hover {
|
||||||
|
background-color: #425040;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<addAtRuntimeStyle>
|
||||||
|
%WARNINGHIDER% %NATIVETSHIDER% %PRESENDHIDER%
|
||||||
|
</addAtRuntimeStyle>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Plugin info</h2>
|
||||||
|
<div class="card" id="plugin-info-card">
|
||||||
|
<h3>%PLUGINNAME%</h3>
|
||||||
|
<p>%PLUGINDESC%</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 data-useless="warning">Warnings</h2>
|
||||||
|
<div
|
||||||
|
data-useless="warning"
|
||||||
|
class="card danger-card"
|
||||||
|
id="native-ts-warning"
|
||||||
|
>
|
||||||
|
<h3>Uses a native.ts file</h3>
|
||||||
|
<p>
|
||||||
|
Use of this file allows the plugin to escape the browser sandbox
|
||||||
|
and potentially do anything to your system and data.
|
||||||
|
<b
|
||||||
|
>ONLY INSTALL THIS PLUGIN AFTER REVIEWING THE CODE AND BEING
|
||||||
|
100% SURE THAT NOTHING BAD CAN BE DONE!</b
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" /> Acknowledge warning (required to allow
|
||||||
|
install)
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-useless="warning"
|
||||||
|
class="card warn-card"
|
||||||
|
id="pre-send-warning"
|
||||||
|
>
|
||||||
|
<h3>Has pre-send listeners</h3>
|
||||||
|
<p>
|
||||||
|
This allows the plugin to edit your messages before they are
|
||||||
|
sent.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p id="validate">
|
||||||
|
Reminder: installing a userplugin can be a destructive action. Make
|
||||||
|
sure that you know and trust the developer before installing any.
|
||||||
|
</p>
|
||||||
|
<div id="btn-row">
|
||||||
|
<button id="abort">Cancel installation</button>
|
||||||
|
<button id="install">Install plugin</button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Reference in a new issue