2022-10-02 09:34:34 +02:00
|
|
|
import Logger from "common/logger";
|
|
|
|
import {default as MainPatcher} from "../patcher";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `Patcher` is a utility class for modifying existing functions. Instance is accessible through the {@link BdApi}.
|
|
|
|
* This is extremely useful for modifying the internals of Discord by adjusting return value or React renders, or arguments of internal functions.
|
|
|
|
* @type Patcher
|
|
|
|
* @summary {@link Patcher} is a utility class for modifying existing functions.
|
|
|
|
* @name Patcher
|
|
|
|
*/
|
|
|
|
class Patcher {
|
|
|
|
|
2022-10-08 23:00:18 +02:00
|
|
|
#callerName = "";
|
2022-10-02 09:34:34 +02:00
|
|
|
constructor(callerName) {
|
|
|
|
if (!callerName) return;
|
2022-10-08 23:00:18 +02:00
|
|
|
this.#callerName = callerName;
|
2022-10-02 09:34:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-10 20:33:36 +02:00
|
|
|
* This method patches onto another function, allowing your code to run beforehand.
|
2022-10-02 09:34:34 +02:00
|
|
|
* Using this, you are also able to modify the incoming arguments before the original method is run.
|
|
|
|
* @param {string} caller Name of the caller of the patch function.
|
|
|
|
* @param {object} moduleToPatch Object with the function to be patched. Can also be an object's prototype.
|
|
|
|
* @param {string} functionName Name of the function to be patched.
|
|
|
|
* @param {function} callback Function to run before the original method. The function is given the `this` context and the `arguments` of the original function.
|
|
|
|
* @returns {function} Function that cancels the original patch.
|
|
|
|
*/
|
|
|
|
before(caller, moduleToPatch, functionName, callback) {
|
2022-10-08 23:00:18 +02:00
|
|
|
if (this.#callerName) {
|
|
|
|
callback = functionName;
|
|
|
|
functionName = moduleToPatch;
|
|
|
|
moduleToPatch = caller;
|
|
|
|
caller = this.#callerName;
|
|
|
|
}
|
2022-10-02 09:34:34 +02:00
|
|
|
return MainPatcher.pushChildPatch(caller, moduleToPatch, functionName, callback, {type: "before"});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-10 20:33:36 +02:00
|
|
|
* This method patches onto another function, allowing your code to run instead.
|
2022-10-14 03:53:41 +02:00
|
|
|
* Using this, you are able to replace the original completely. You can still call the original manually if needed.
|
2022-10-02 09:34:34 +02:00
|
|
|
* @param {string} caller Name of the caller of the patch function.
|
|
|
|
* @param {object} moduleToPatch Object with the function to be patched. Can also be an object's prototype.
|
|
|
|
* @param {string} functionName Name of the function to be patched.
|
|
|
|
* @param {function} callback Function to run before the original method. The function is given the `this` context, `arguments` of the original function, and also the original function.
|
|
|
|
* @returns {function} Function that cancels the original patch.
|
|
|
|
*/
|
|
|
|
instead(caller, moduleToPatch, functionName, callback) {
|
2022-10-08 23:00:18 +02:00
|
|
|
if (this.#callerName) {
|
|
|
|
callback = functionName;
|
|
|
|
functionName = moduleToPatch;
|
|
|
|
moduleToPatch = caller;
|
|
|
|
caller = this.#callerName;
|
|
|
|
}
|
2022-10-02 09:34:34 +02:00
|
|
|
return MainPatcher.pushChildPatch(caller, moduleToPatch, functionName, callback, {type: "instead"});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-14 03:53:41 +02:00
|
|
|
* This method patches onto another function, allowing your code to run afterwards.
|
|
|
|
* Using this, you are able to modify the return value after the original method is run.
|
2022-10-02 09:34:34 +02:00
|
|
|
* @param {string} caller Name of the caller of the patch function.
|
|
|
|
* @param {object} moduleToPatch Object with the function to be patched. Can also be an object's prototype.
|
|
|
|
* @param {string} functionName Name of the function to be patched.
|
|
|
|
* @param {function} callback Function to run after the original method. The function is given the `this` context, the `arguments` of the original function, and the `return` value of the original function.
|
|
|
|
* @returns {function} Function that cancels the original patch.
|
|
|
|
*/
|
|
|
|
after(caller, moduleToPatch, functionName, callback) {
|
2022-10-08 23:00:18 +02:00
|
|
|
if (this.#callerName) {
|
|
|
|
callback = functionName;
|
|
|
|
functionName = moduleToPatch;
|
|
|
|
moduleToPatch = caller;
|
|
|
|
caller = this.#callerName;
|
|
|
|
}
|
2022-10-02 09:34:34 +02:00
|
|
|
return MainPatcher.pushChildPatch(caller, moduleToPatch, functionName, callback, {type: "after"});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all patches by a particular caller. The patches all have an `unpatch()` method.
|
|
|
|
* @param {string} caller ID of the original patches
|
|
|
|
* @returns {Array<function>} Array of all the patch objects.
|
|
|
|
*/
|
|
|
|
getPatchesByCaller(caller) {
|
2022-10-08 23:00:18 +02:00
|
|
|
if (this.#callerName) caller = this.#callerName;
|
2022-10-02 09:34:34 +02:00
|
|
|
if (typeof(caller) !== "string") return Logger.err("BdApi.Patcher", "Parameter 0 of getPatchesByCaller must be a string representing the caller");
|
|
|
|
return MainPatcher.getPatchesByCaller(caller);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Automatically cancels all patches created with a specific ID.
|
|
|
|
* @param {string} caller ID of the original patches
|
|
|
|
*/
|
|
|
|
unpatchAll(caller) {
|
2022-10-08 23:00:18 +02:00
|
|
|
if (this.#callerName) caller = this.#callerName;
|
2022-10-02 09:34:34 +02:00
|
|
|
if (typeof(caller) !== "string") return Logger.err("BdApi.Patcher", "Parameter 0 of unpatchAll must be a string representing the caller");
|
|
|
|
MainPatcher.unpatchAll(caller);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object.freeze(Patcher);
|
2022-10-08 23:00:18 +02:00
|
|
|
Object.freeze(Patcher.prototype);
|
2022-10-02 09:34:34 +02:00
|
|
|
export default Patcher;
|