You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
demoncord-rewrite/src/api/patcher.ts

114 lines
2.6 KiB

type BeforeFunc = (args: any[]) => void;
type InsteadFunc = (args: any[], orig: (...args: any) => any, ctx: any) => any;
type AfterFunc = (args: any[], res: any) => any;
function wackyPatch(
parentObj: any,
name: string,
patches: {
before?: BeforeFunc;
instead?: InsteadFunc;
after?: AfterFunc;
}
) {
if (typeof parentObj === "string") {
//assume parentObj and name are switched around (for backcompat/convienence)
const tmp = parentObj;
parentObj = name;
name = tmp;
}
const injId = Symbol();
const before = patches["before"];
const instead = patches["instead"];
const after = patches["after"];
const handler = {
apply: (
target: () => any,
thisArg: any,
[ctx, args]: [ctx: any, args: []]
) => {
console.log(thisArg);
if (before !== undefined) before.apply(ctx, [args]);
const res =
patches["instead"] !== undefined
? instead?.apply(ctx, [args, target.bind(ctx), ctx])
: target.apply(ctx, args);
if (after === undefined) return res;
return after.apply(ctx, [args, res]);
}
};
const prox = new Proxy(parentObj[name], handler);
const orig = parentObj[name];
parentObj[name] = function () {
return prox(this, arguments);
};
const unpatch = () => {
parentObj[name] = orig;
};
parentObj[injId] = {
name: name,
orig: orig,
unpatch: unpatch
};
return unpatch;
}
function before(parentObj: any, name: string, func: BeforeFunc) {
return wackyPatch(parentObj, name, { before: func });
}
function instead(parentObj: any, name: string, func: InsteadFunc) {
return wackyPatch(parentObj, name, { instead: func });
}
function after(parentObj: any, name: string, func: AfterFunc) {
return wackyPatch(parentObj, name, { after: func });
}
//idea shamelessly ripped from vencord, but done slightly differently (ie allowing for targetting specific webpack functions)
function regexPatch(
match: RegExp | string,
replace: string,
obj: any,
prop: string
) {
const oldFunc = obj[prop];
const injId = Symbol();
const handler = {
apply: (
target: () => any,
thisArg: any,
[ctx, args]: [ctx: any, args: []]
) => {
let oldfunc = target;
let str: string = oldFunc.toString();
str = str.replaceAll(match, replace);
console.log("(" + str + ")");
let newfunc = eval.apply(ctx, ["(" + str + ")"]);
console.log(ctx);
return newfunc.apply(ctx, args);
}
};
const prox = new Proxy(obj[prop], handler);
const orig = obj[prop];
obj[prop] = prox;
const unpatch = () => {
obj[prop] = orig;
};
obj[injId] = {
name: prop,
orig: orig,
unpatch: unpatch
};
return unpatch;
}
export { instead, before, after, regexPatch };
export default {
instead,
before,
after,
regexPatch
};