mirror of
https://github.com/Equicord/Equicord.git
synced 2025-01-18 13:23:28 -05:00
Update Dev Companion
This commit is contained in:
parent
c4d64a6043
commit
872f67c19e
6 changed files with 372 additions and 133 deletions
|
@ -47,7 +47,7 @@ export const settings = definePluginSettings({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "DevCompanion",
|
name: "UserDevCompanion",
|
||||||
description: "Dev Companion Plugin",
|
description: "Dev Companion Plugin",
|
||||||
authors: [Devs.Ven, Devs.sadan, Devs.Samwich],
|
authors: [Devs.Ven, Devs.sadan, Devs.Samwich],
|
||||||
reporterTestable: ReporterTestable.None,
|
reporterTestable: ReporterTestable.None,
|
||||||
|
@ -62,8 +62,9 @@ export default definePlugin({
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
// if we're running the reporter, we need to initws in the reporter file to avoid a race condition
|
// if we're running the reporter, we need to initws in the reporter file to avoid a race condition
|
||||||
if (!IS_COMPANION_TEST)
|
if (!IS_DEV) throw new Error("This plugin requires dev mode to run, please build with pnpm build --dev");
|
||||||
initWs();
|
if (Vencord.Settings.plugins.DevCompanion?.enabled) throw new Error("Disable DevCompanion");
|
||||||
|
initWs();
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: stopWs,
|
stop: stopWs,
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { popNotice, showNotice } from "@api/Notices";
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches";
|
||||||
import { filters, findAll, search, wreq } from "@webpack";
|
import { filters, findAll, search, wreq } from "@webpack";
|
||||||
import { Toasts } from "@webpack/common";
|
import { React, Toasts, useState } from "@webpack/common";
|
||||||
import { reporterData } from "debug/reporterData";
|
import { loadLazyChunks } from "debug/loadLazyChunks";
|
||||||
import { Settings } from "Vencord";
|
import { Settings } from "Vencord";
|
||||||
|
|
||||||
import { logger, PORT, settings } from ".";
|
import { logger, PORT, settings } from ".";
|
||||||
import { extractModule, extractOrThrow, FindData, findModuleId, FindType, mkRegexFind, parseNode, PatchData, SendData, toggleEnabled, } from "./util";
|
import { Recieve } from "./types";
|
||||||
|
import { FullOutgoingMessage, OutgoingMessage } from "./types/send";
|
||||||
|
import { extractModule, extractOrThrow, findModuleId, mkRegexFind, parseNode, toggleEnabled, } from "./util";
|
||||||
|
|
||||||
export function stopWs() {
|
export function stopWs() {
|
||||||
socket?.close(1000, "Plugin Stopped");
|
socket?.close(1000, "Plugin Stopped");
|
||||||
|
@ -25,7 +29,7 @@ export function initWs(isManual = false) {
|
||||||
let hasErrored = false;
|
let hasErrored = false;
|
||||||
const ws = socket = new WebSocket(`ws://localhost:${PORT}`);
|
const ws = socket = new WebSocket(`ws://localhost:${PORT}`);
|
||||||
|
|
||||||
function replyData<T extends SendData>(data: T) {
|
function replyData(data: OutgoingMessage) {
|
||||||
ws.send(JSON.stringify(data));
|
ws.send(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,33 +41,27 @@ export function initWs(isManual = false) {
|
||||||
// send module cache to vscode
|
// send module cache to vscode
|
||||||
replyData({
|
replyData({
|
||||||
type: "moduleList",
|
type: "moduleList",
|
||||||
data: Object.keys(wreq.m),
|
data: {
|
||||||
ok: true,
|
modules: Object.keys(wreq.m)
|
||||||
|
},
|
||||||
|
ok: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (IS_COMPANION_TEST) {
|
try {
|
||||||
const toSend = JSON.stringify(reporterData, (_k, v) => {
|
if (settings.store.notifyOnAutoConnect || isManual) {
|
||||||
if (v instanceof RegExp)
|
Toasts.show({
|
||||||
return String(v);
|
message: "Connected to WebSocket",
|
||||||
return v;
|
id: Toasts.genId(),
|
||||||
});
|
type: Toasts.Type.SUCCESS,
|
||||||
|
options: {
|
||||||
socket?.send(JSON.stringify({
|
position: Toasts.Position.TOP
|
||||||
type: "report",
|
}
|
||||||
data: JSON.parse(toSend),
|
});
|
||||||
ok: true
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
(settings.store.notifyOnAutoConnect || isManual) && Toasts.show({
|
|
||||||
message: "Connected to WebSocket",
|
|
||||||
id: Toasts.genId(),
|
|
||||||
type: Toasts.Type.SUCCESS,
|
|
||||||
options: {
|
|
||||||
position: Toasts.Position.TOP
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.addEventListener("error", e => {
|
ws.addEventListener("error", e => {
|
||||||
|
@ -100,77 +98,83 @@ export function initWs(isManual = false) {
|
||||||
|
|
||||||
ws.addEventListener("message", e => {
|
ws.addEventListener("message", e => {
|
||||||
try {
|
try {
|
||||||
var { nonce, type, data } = JSON.parse(e.data);
|
var d = JSON.parse(e.data) as Recieve.FullIncomingMessage;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error("Invalid JSON:", err, "\n" + e.data);
|
logger.error("Invalid JSON:", err, "\n" + e.data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param error the error to reply with. if there is no error, the reply is a sucess
|
||||||
|
*/
|
||||||
function reply(error?: string) {
|
function reply(error?: string) {
|
||||||
const data = { nonce, ok: !error } as Record<string, unknown>;
|
const data = { nonce: d.nonce, ok: !error } as Record<string, unknown>;
|
||||||
if (error) data.error = error;
|
if (error) data.error = error;
|
||||||
|
|
||||||
ws.send(JSON.stringify(data));
|
ws.send(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
function replyData<T extends SendData>(data: T) {
|
function replyData(data: OutgoingMessage) {
|
||||||
data.nonce = nonce;
|
const toSend: FullOutgoingMessage = {
|
||||||
ws.send(JSON.stringify(data));
|
...data,
|
||||||
|
nonce: d.nonce
|
||||||
|
};
|
||||||
|
// data.nonce = d.nonce;
|
||||||
|
ws.send(JSON.stringify(toSend));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Received Message:", type, "\n", data);
|
logger.info("Received Message:", d.type, "\n", d.data);
|
||||||
|
|
||||||
switch (type) {
|
switch (d.type) {
|
||||||
case "disable": {
|
case "disable": {
|
||||||
const { enabled, pluginName } = data;
|
const m = d.data;
|
||||||
const settings = Settings.plugins[pluginName];
|
const settings = Settings.plugins[m.pluginName];
|
||||||
if (enabled !== settings.enabled)
|
if (m.enabled !== settings.enabled)
|
||||||
toggleEnabled(pluginName, reply);
|
toggleEnabled(m.pluginName, reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "rawId": {
|
case "rawId": {
|
||||||
const { id } = data;
|
const m = d.data;
|
||||||
replyData({
|
replyData({
|
||||||
|
type: "rawId",
|
||||||
ok: true,
|
ok: true,
|
||||||
data: extractModule(id),
|
data: extractModule(m.id),
|
||||||
type: "ret"
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "diff": {
|
case "diff": {
|
||||||
try {
|
try {
|
||||||
const { extractType, idOrSearch } = data;
|
const m = d.data;
|
||||||
switch (extractType) {
|
switch (m.extractType) {
|
||||||
case "id": {
|
case "id": {
|
||||||
if (typeof idOrSearch !== "number")
|
if (typeof m.idOrSearch !== "number")
|
||||||
throw new Error("Id is not a number, got :" + typeof idOrSearch);
|
throw new Error("Id is not a number, got :" + typeof m.idOrSearch);
|
||||||
replyData({
|
replyData({
|
||||||
type: "diff",
|
type: "diff",
|
||||||
ok: true,
|
ok: true,
|
||||||
data: {
|
data: {
|
||||||
patched: extractOrThrow(idOrSearch),
|
patched: extractOrThrow(m.idOrSearch),
|
||||||
source: extractModule(idOrSearch, false)
|
source: extractModule(m.idOrSearch, false),
|
||||||
|
moduleNumber: m.idOrSearch
|
||||||
},
|
},
|
||||||
moduleNumber: idOrSearch
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "search": {
|
case "search": {
|
||||||
let moduleId;
|
let moduleId: number;
|
||||||
if (data.findType === FindType.STRING)
|
if (m.findType === "string")
|
||||||
moduleId = +findModuleId([idOrSearch.toString()]);
|
moduleId = +findModuleId([m.idOrSearch.toString()]);
|
||||||
|
|
||||||
else
|
else
|
||||||
moduleId = +findModuleId(mkRegexFind(idOrSearch));
|
moduleId = +findModuleId(mkRegexFind(m.idOrSearch));
|
||||||
const p = extractOrThrow(moduleId);
|
const p = extractOrThrow(moduleId);
|
||||||
const p2 = extractModule(moduleId, false);
|
const p2 = extractModule(moduleId, false);
|
||||||
console.log(p, p2, "done");
|
|
||||||
replyData({
|
replyData({
|
||||||
type: "diff",
|
type: "diff",
|
||||||
ok: true,
|
ok: true,
|
||||||
data: {
|
data: {
|
||||||
patched: p,
|
patched: p,
|
||||||
source: p2
|
source: p2,
|
||||||
|
moduleNumber: moduleId
|
||||||
},
|
},
|
||||||
moduleNumber: moduleId
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,48 +191,51 @@ export function initWs(isManual = false) {
|
||||||
}
|
}
|
||||||
case "extract": {
|
case "extract": {
|
||||||
try {
|
try {
|
||||||
const { extractType, idOrSearch } = data;
|
const m = d.data;
|
||||||
switch (extractType) {
|
switch (m.extractType) {
|
||||||
case "id": {
|
case "id": {
|
||||||
if (typeof idOrSearch !== "number")
|
if (typeof m.idOrSearch !== "number")
|
||||||
throw new Error("Id is not a number, got :" + typeof idOrSearch);
|
throw new Error("Id is not a number, got :" + typeof m.idOrSearch);
|
||||||
|
|
||||||
else
|
else
|
||||||
replyData({
|
replyData({
|
||||||
type: "extract",
|
type: "extract",
|
||||||
ok: true,
|
ok: true,
|
||||||
data: extractModule(idOrSearch),
|
data: {
|
||||||
moduleNumber: idOrSearch
|
module: extractModule(m.idOrSearch),
|
||||||
|
moduleNumber: m.idOrSearch,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "search": {
|
case "search": {
|
||||||
let moduleId;
|
let moduleId;
|
||||||
if (data.findType === FindType.STRING)
|
if (m.findType === "string")
|
||||||
moduleId = +findModuleId([idOrSearch.toString()]);
|
moduleId = +findModuleId([m.idOrSearch.toString()]);
|
||||||
|
|
||||||
else
|
else
|
||||||
moduleId = +findModuleId(mkRegexFind(idOrSearch));
|
moduleId = +findModuleId(mkRegexFind(m.idOrSearch));
|
||||||
replyData({
|
replyData({
|
||||||
type: "extract",
|
type: "extract",
|
||||||
ok: true,
|
ok: true,
|
||||||
data: extractModule(moduleId),
|
data: {
|
||||||
moduleNumber: moduleId
|
module: extractModule(moduleId),
|
||||||
|
moduleNumber: moduleId
|
||||||
|
},
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "find": {
|
case "find": {
|
||||||
const { findType, findArgs } = data;
|
|
||||||
try {
|
try {
|
||||||
var parsedArgs = findArgs.map(parseNode);
|
var parsedArgs = m.findArgs.map(parseNode);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return reply("Failed to parse args: " + err);
|
return reply("Failed to parse args: " + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let results: any[];
|
let results: any[];
|
||||||
switch (findType.replace("find", "").replace("Lazy", "")) {
|
switch (m.findType.replace("find", "").replace("Lazy", "")) {
|
||||||
case "":
|
case "":
|
||||||
case "Component":
|
case "Component":
|
||||||
results = findAll(parsedArgs[0]);
|
results = findAll(parsedArgs[0]);
|
||||||
|
@ -249,7 +256,7 @@ export function initWs(isManual = false) {
|
||||||
results = findAll(filters.componentByCode(...parsedArgs));
|
results = findAll(filters.componentByCode(...parsedArgs));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return reply("Unknown Find Type " + findType);
|
return reply("Unknown Find Type " + m.findType);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uniqueResultsCount = new Set(results).size;
|
const uniqueResultsCount = new Set(results).size;
|
||||||
|
@ -260,9 +267,11 @@ export function initWs(isManual = false) {
|
||||||
replyData({
|
replyData({
|
||||||
type: "extract",
|
type: "extract",
|
||||||
ok: true,
|
ok: true,
|
||||||
find: true,
|
data: {
|
||||||
data: foundFind,
|
module: foundFind,
|
||||||
moduleNumber: +findModuleId([foundFind])
|
find: true,
|
||||||
|
moduleNumber: +findModuleId([foundFind])
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return reply("Failed to find: " + err);
|
return reply("Failed to find: " + err);
|
||||||
|
@ -270,7 +279,7 @@ export function initWs(isManual = false) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
reply(`Unknown Extract type. Got: ${extractType}`);
|
reply(`Unknown Extract type. Got: ${d.data.extractType}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -279,14 +288,14 @@ export function initWs(isManual = false) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "testPatch": {
|
case "testPatch": {
|
||||||
const { find, replacement } = data as PatchData;
|
const m = d.data;
|
||||||
|
|
||||||
let candidates;
|
let candidates;
|
||||||
if (data.findType === FindType.REGEX)
|
console.log(m.find.toString());
|
||||||
candidates = search(...mkRegexFind(find));
|
if (d.data.findType === "string")
|
||||||
|
candidates = search(m.find.toString());
|
||||||
|
|
||||||
else
|
else
|
||||||
candidates = search(find.toString());
|
candidates = search(...mkRegexFind(m.find));
|
||||||
|
|
||||||
// const candidates = search(find);
|
// const candidates = search(find);
|
||||||
const keys = Object.keys(candidates);
|
const keys = Object.keys(candidates);
|
||||||
|
@ -302,7 +311,7 @@ export function initWs(isManual = false) {
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
for (const { match, replace } of replacement) {
|
for (const { match, replace } of m.replacement) {
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -319,22 +328,20 @@ export function initWs(isManual = false) {
|
||||||
return reply(`Replacement ${i} failed: ${err}`);
|
return reply(`Replacement ${i} failed: ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reply();
|
reply();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "testFind": {
|
case "testFind": {
|
||||||
const { type, args } = data as FindData;
|
const m = d.data;
|
||||||
let parsedArgs;
|
|
||||||
try {
|
try {
|
||||||
parsedArgs = args.map(parseNode);
|
var parsedArgs = m.args.map(parseNode);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return reply("Failed to parse args: " + err);
|
return reply("Failed to parse args: " + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let results: any[];
|
let results: any[];
|
||||||
switch (type.replace("find", "").replace("Lazy", "")) {
|
switch (m.type.replace("find", "").replace("Lazy", "")) {
|
||||||
case "":
|
case "":
|
||||||
case "Component":
|
case "Component":
|
||||||
results = findAll(parsedArgs[0]);
|
results = findAll(parsedArgs[0]);
|
||||||
|
@ -355,7 +362,7 @@ export function initWs(isManual = false) {
|
||||||
results = findAll(filters.componentByCode(...parsedArgs));
|
results = findAll(filters.componentByCode(...parsedArgs));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return reply("Unknown Find Type " + type);
|
return reply("Unknown Find Type " + m.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uniqueResultsCount = new Set(results).size;
|
const uniqueResultsCount = new Set(results).size;
|
||||||
|
@ -368,9 +375,67 @@ export function initWs(isManual = false) {
|
||||||
reply();
|
reply();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "allModules": {
|
||||||
|
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
||||||
|
// wrap in try/catch to prevent crashing if notice api is not loaded
|
||||||
|
try {
|
||||||
|
let closed = false;
|
||||||
|
const close = () => {
|
||||||
|
if (closed) return;
|
||||||
|
closed = true;
|
||||||
|
popNotice();
|
||||||
|
};
|
||||||
|
// @ts-expect-error it accepts react components
|
||||||
|
showNotice(<AllModulesNoti done={promise} close={close} />, "OK", () => {
|
||||||
|
closed = true;
|
||||||
|
popNotice();
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
loadLazyChunks()
|
||||||
|
.then(() => {
|
||||||
|
resolve();
|
||||||
|
replyData({
|
||||||
|
type: "moduleList",
|
||||||
|
data: {
|
||||||
|
modules: Object.keys(wreq.m)
|
||||||
|
},
|
||||||
|
ok: true
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
replyData({
|
||||||
|
type: "moduleList",
|
||||||
|
ok: false,
|
||||||
|
error: String(e),
|
||||||
|
data: null
|
||||||
|
});
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
reply("Unknown Type " + type);
|
reply("Unknown Type " + (d as any).type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AllModulesNotiProps {
|
||||||
|
done: Promise<unknown>;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AllModulesNoti = ErrorBoundary.wrap(function ({ done, close }: AllModulesNotiProps) {
|
||||||
|
const [state, setState] = useState<0 | 1 | -1>(0);
|
||||||
|
done.then(setState.bind(null, 1)).catch(setState.bind(null, -1));
|
||||||
|
console.log("test");
|
||||||
|
if (state === 1) setTimeout(close, 5000);
|
||||||
|
return (<>
|
||||||
|
{state === 0 && "Loading lazy modules, restarting could lead to errors"}
|
||||||
|
{state === 1 && "Loaded all lazy modules"}
|
||||||
|
{state === -1 && "Failed to load lazy modules, check console for errors"}
|
||||||
|
</>);
|
||||||
|
}, { noop: true });
|
||||||
|
|
7
src/plugins/devCompanion/types/index.ts
Normal file
7
src/plugins/devCompanion/types/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * as Recieve from "./recieve";
|
140
src/plugins/devCompanion/types/recieve.ts
Normal file
140
src/plugins/devCompanion/types/recieve.ts
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
// should be the same types as ./server/types/send.ts in the companion
|
||||||
|
export type SearchData =
|
||||||
|
| {
|
||||||
|
extractType: "id";
|
||||||
|
idOrSearch: number;
|
||||||
|
}
|
||||||
|
| (
|
||||||
|
| {
|
||||||
|
extractType: "search";
|
||||||
|
/**
|
||||||
|
* stringified regex
|
||||||
|
*/
|
||||||
|
idOrSearch: string;
|
||||||
|
findType: "regex";
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
extractType: "search";
|
||||||
|
idOrSearch: string;
|
||||||
|
findType: "string";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export type FindOrSearchData =
|
||||||
|
| SearchData
|
||||||
|
| ({
|
||||||
|
extractType: "find";
|
||||||
|
} & _PrefixKeys<_CapitalizeKeys<FindData>, "find">);
|
||||||
|
|
||||||
|
export type AnyFindType =
|
||||||
|
`find${"Component" | "ByProps" | "Store" | "ByCode" | "ModuleId" | "ComponentByCode" | ""}${"Lazy" | ""}`;
|
||||||
|
|
||||||
|
export type StringNode = {
|
||||||
|
type: "string";
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RegexNode = {
|
||||||
|
type: "regex";
|
||||||
|
value: {
|
||||||
|
pattern: string;
|
||||||
|
flags: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FunctionNode = {
|
||||||
|
type: "function";
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FindNode = StringNode | RegexNode | FunctionNode;
|
||||||
|
|
||||||
|
export type FindData = {
|
||||||
|
type: AnyFindType;
|
||||||
|
args: FindNode[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IncomingMessage = DisablePlugin | RawId | DiffPatch | Reload | ExtractModule | TestPatch | TestFind | AllModules;
|
||||||
|
export type FullIncomingMessage = IncomingMessage & { nonce: number; };
|
||||||
|
|
||||||
|
export type DisablePlugin = {
|
||||||
|
type: "disable";
|
||||||
|
data: {
|
||||||
|
enabled: boolean;
|
||||||
|
pluginName: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RawId = {
|
||||||
|
type: "rawId";
|
||||||
|
data: {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DiffPatch = {
|
||||||
|
type: "diff";
|
||||||
|
data: SearchData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Reload = {
|
||||||
|
type: "reload";
|
||||||
|
data: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtractModule = {
|
||||||
|
type: "extract";
|
||||||
|
// FIXME: update client code so you can just pass FindData here
|
||||||
|
data: FindOrSearchData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TestPatch = {
|
||||||
|
type: "testPatch";
|
||||||
|
data: (
|
||||||
|
| {
|
||||||
|
findType: "string";
|
||||||
|
find: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
findType: "regex";
|
||||||
|
/**
|
||||||
|
* stringified regex
|
||||||
|
*/
|
||||||
|
find: string;
|
||||||
|
}
|
||||||
|
) & {
|
||||||
|
replacement: {
|
||||||
|
match: StringNode | RegexNode;
|
||||||
|
replace: StringNode | RegexNode;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TestFind = {
|
||||||
|
type: "testFind";
|
||||||
|
data: FindData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AllModules = {
|
||||||
|
type: "allModules";
|
||||||
|
data: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type _PrefixKeys<
|
||||||
|
T extends Record<string, any>,
|
||||||
|
P extends string,
|
||||||
|
> = string extends P
|
||||||
|
? never
|
||||||
|
: {
|
||||||
|
[K in keyof T as K extends string ? `${P}${K}` : never]: T[K];
|
||||||
|
};
|
||||||
|
|
||||||
|
type _CapitalizeKeys<T extends Record<string, any>> = {
|
||||||
|
[K in keyof T as K extends string ? Capitalize<K> : never]: T[K];
|
||||||
|
};
|
63
src/plugins/devCompanion/types/send.ts
Normal file
63
src/plugins/devCompanion/types/send.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
// should be the same types as src/server/types/recieve.ts in the companion
|
||||||
|
import { reporterData } from "debug/reporterData";
|
||||||
|
export type ReporterData = typeof reporterData;
|
||||||
|
|
||||||
|
export type OutgoingMessage = (Report | DiffModule | ExtractModule | ModuleList | RawId) & Base;
|
||||||
|
export type FullOutgoingMessage = OutgoingMessage & Nonce;
|
||||||
|
|
||||||
|
export type Base = {
|
||||||
|
ok: true;
|
||||||
|
} | {
|
||||||
|
ok: false;
|
||||||
|
data?: any;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
export type Nonce = {
|
||||||
|
nonce: number;
|
||||||
|
};
|
||||||
|
export type ModuleResult = {
|
||||||
|
moduleNumber: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// #region valid payloads
|
||||||
|
export type Report = {
|
||||||
|
type: "report";
|
||||||
|
data: ReporterData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DiffModule = {
|
||||||
|
type: "diff";
|
||||||
|
data: {
|
||||||
|
source: string;
|
||||||
|
patched: string;
|
||||||
|
} & ModuleResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtractModule = {
|
||||||
|
type: "extract";
|
||||||
|
data: {
|
||||||
|
module: string;
|
||||||
|
/**
|
||||||
|
* if the module is incomplete. ie: from a find
|
||||||
|
*/
|
||||||
|
find?: boolean;
|
||||||
|
} & ModuleResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ModuleList = {
|
||||||
|
type: "moduleList";
|
||||||
|
data: {
|
||||||
|
modules: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RawId = {
|
||||||
|
type: "rawId";
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
// #endregion
|
|
@ -11,50 +11,13 @@ import { CodeFilter, stringMatches, wreq } from "@webpack";
|
||||||
import { Toasts } from "@webpack/common";
|
import { Toasts } from "@webpack/common";
|
||||||
|
|
||||||
import { settings as companionSettings } from ".";
|
import { settings as companionSettings } from ".";
|
||||||
|
import { FindNode } from "./types/recieve";
|
||||||
|
|
||||||
type Node = StringNode | RegexNode | FunctionNode;
|
|
||||||
|
|
||||||
|
|
||||||
export interface StringNode {
|
|
||||||
type: "string";
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
export interface RegexNode {
|
|
||||||
type: "regex";
|
|
||||||
value: {
|
|
||||||
pattern: string;
|
|
||||||
flags: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export enum FindType {
|
|
||||||
STRING,
|
|
||||||
REGEX
|
|
||||||
}
|
|
||||||
export interface FunctionNode {
|
|
||||||
type: "function";
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
export interface PatchData {
|
|
||||||
find: string;
|
|
||||||
replacement: {
|
|
||||||
match: StringNode | RegexNode;
|
|
||||||
replace: StringNode | FunctionNode;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
export interface FindData {
|
|
||||||
type: string;
|
|
||||||
args: Array<StringNode | FunctionNode>;
|
|
||||||
}export interface SendData {
|
|
||||||
type: string;
|
|
||||||
data: any;
|
|
||||||
ok: boolean;
|
|
||||||
nonce?: number;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* extracts the patched module, if there is no patched module, throws an error
|
* extracts the patched module, if there is no patched module, throws an error
|
||||||
* @param id module id
|
* @param id module id
|
||||||
*/
|
*/
|
||||||
export function extractOrThrow(id) {
|
export function extractOrThrow(id: number): string {
|
||||||
const module = wreq.m[id];
|
const module = wreq.m[id];
|
||||||
if (!module?.$$vencordPatchedSource)
|
if (!module?.$$vencordPatchedSource)
|
||||||
throw new Error("No patched module found for module id " + id);
|
throw new Error("No patched module found for module id " + id);
|
||||||
|
@ -74,7 +37,7 @@ export function extractModule(id: number, patched = companionSettings.store.useP
|
||||||
throw new Error("No module found for module id:" + id);
|
throw new Error("No module found for module id:" + id);
|
||||||
return patched ? module.$$vencordPatchedSource ?? module.original.toString() : module.original.toString();
|
return patched ? module.$$vencordPatchedSource ?? module.original.toString() : module.original.toString();
|
||||||
}
|
}
|
||||||
export function parseNode(node: Node) {
|
export function parseNode(node: FindNode): any {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case "string":
|
case "string":
|
||||||
return node.value;
|
return node.value;
|
||||||
|
@ -120,7 +83,7 @@ function showErrorToast(message: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleEnabled(name: string, beforeReload: () => void) {
|
export function toggleEnabled(name: string, beforeReload: (error?: string) => void) {
|
||||||
let restartNeeded = false;
|
let restartNeeded = false;
|
||||||
function onRestartNeeded() {
|
function onRestartNeeded() {
|
||||||
restartNeeded = true;
|
restartNeeded = true;
|
||||||
|
|
Loading…
Reference in a new issue