Equicord/src/plugins/devCompanion.dev/util.tsx

163 lines
5.5 KiB
TypeScript
Raw Normal View History

2024-08-19 23:13:21 -04:00
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
2024-08-28 01:35:47 -04:00
import { showNotice } from "@api/Notices";
import { Settings } from "@api/Settings";
import { canonicalizeMatch } from "@utils/patches";
2024-08-19 23:13:21 -04:00
import { CodeFilter, stringMatches, wreq } from "@webpack";
2024-08-28 01:35:47 -04:00
import { Toasts } from "@webpack/common";
2024-08-19 23:13:21 -04:00
2024-08-28 01:35:47 -04:00
import { settings as companionSettings } from ".";
2025-01-09 10:37:02 -05:00
import { Recieve } from "./types";
2024-08-19 23:13:21 -04:00
/**
* extracts the patched module, if there is no patched module, throws an error
* @param id module id
*/
2025-01-09 02:58:32 -05:00
export function extractOrThrow(id: number): string {
2024-08-19 23:13:21 -04:00
const module = wreq.m[id];
if (!module?.$$vencordPatchedSource)
throw new Error("No patched module found for module id " + id);
return module.$$vencordPatchedSource;
}
/**
* attempts to extract the module, throws if not found
*
*
* if patched is true and no patched module is found fallsback to the non-patched module
* @param id module id
* @param patched return the patched module
*/
2024-08-28 01:35:47 -04:00
export function extractModule(id: number, patched = companionSettings.store.usePatchedModule): string {
2024-08-19 23:13:21 -04:00
const module = wreq.m[id];
if (!module)
throw new Error("No module found for module id:" + id);
return patched ? module.$$vencordPatchedSource ?? module.original.toString() : module.original.toString();
2024-08-27 17:02:04 -04:00
}
2025-01-09 10:37:02 -05:00
export function parseNode(node: Recieve.FindNode): any {
2024-08-19 23:13:21 -04:00
switch (node.type) {
case "string":
return node.value;
case "regex":
return new RegExp(node.value.pattern, node.value.flags);
case "function":
// We LOVE remote code execution
// Safety: This comes from localhost only, which actually means we have less permissions than the source,
// since we're running in the browser sandbox, whereas the sender has host access
return (0, eval)(node.value);
default:
throw new Error("Unknown Node Type " + (node as any).type);
}
}
// we need to have our own because the one in webpack returns the first with no handling of more than one module
export function findModuleId(find: CodeFilter) {
const matches: string[] = [];
for (const id in wreq.m) {
if (stringMatches(wreq.m[id].toString(), find)) matches.push(id);
}
if (matches.length === 0) {
throw new Error("No Matches Found");
}
if (matches.length !== 1) {
throw new Error(`This filter matches ${matches.length} modules. Make it more specific!`);
2024-08-19 23:13:21 -04:00
}
return matches[0];
}
export function mkRegexFind(idOrSearch: string): RegExp[] {
const regex = idOrSearch.substring(1, idOrSearch.lastIndexOf("/"));
const flags = idOrSearch.substring(idOrSearch.lastIndexOf("/") + 1);
return [canonicalizeMatch(RegExp(regex, flags))];
}
2024-08-28 01:35:47 -04:00
// the next two functions are copied from components/pluginSettings
function showErrorToast(message: string) {
Toasts.show({
message,
type: Toasts.Type.FAILURE,
id: Toasts.genId(),
options: {
position: Toasts.Position.BOTTOM
}
});
}
2025-01-09 02:58:32 -05:00
export function toggleEnabled(name: string, beforeReload: (error?: string) => void) {
2024-08-28 01:35:47 -04:00
let restartNeeded = false;
function onRestartNeeded() {
restartNeeded = true;
}
function beforeReturn() {
if (restartNeeded) {
if (companionSettings.store.reloadAfterToggle) {
beforeReload();
window.location.reload();
}
Toasts.show({
id: Toasts.genId(),
message: "Reload Needed",
type: Toasts.Type.MESSAGE,
options: {
duration: 5000,
position: Toasts.Position.TOP
}
});
}
}
const plugin = Vencord.Plugins.plugins[name];
const settings = Settings.plugins[plugin.name];
const isEnabled = () => settings.enabled ?? false;
const wasEnabled = isEnabled();
// If we're enabling a plugin, make sure all deps are enabled recursively.
if (!wasEnabled) {
const { restartNeeded, failures } = Vencord.Plugins.startDependenciesRecursive(plugin);
if (failures.length) {
console.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`);
showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null);
beforeReturn();
return;
} else if (restartNeeded) {
// If any dependencies have patches, don't start the plugin yet.
settings.enabled = true;
onRestartNeeded();
beforeReturn();
return;
}
}
2024-08-19 23:13:21 -04:00
2024-08-28 01:35:47 -04:00
// if the plugin has patches, dont use stopPlugin/startPlugin. Wait for restart to apply changes.
if (plugin.patches?.length) {
settings.enabled = !wasEnabled;
onRestartNeeded();
beforeReturn();
return;
}
// If the plugin is enabled, but hasn't been started, then we can just toggle it off.
if (wasEnabled && !plugin.started) {
settings.enabled = !wasEnabled;
beforeReturn();
return;
}
const result = wasEnabled ? Vencord.Plugins.stopPlugin(plugin) : Vencord.Plugins.startPlugin(plugin);
if (!result) {
settings.enabled = false;
const msg = `Error while ${wasEnabled ? "stopping" : "starting"} plugin ${plugin.name}`;
console.error(msg);
showErrorToast(msg);
beforeReturn();
return;
}
settings.enabled = !wasEnabled;
beforeReturn();
}