import Logger from "@common/logger"; import {default as MainPatcher} from "@modules/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 { #callerName = ""; constructor(callerName) { if (!callerName) return; this.#callerName = callerName; } /** * This method patches onto another function, allowing your code to run beforehand. * 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) { if (this.#callerName) { callback = functionName; functionName = moduleToPatch; moduleToPatch = caller; caller = this.#callerName; } return MainPatcher.pushChildPatch(caller, moduleToPatch, functionName, callback, {type: "before"}); } /** * This method patches onto another function, allowing your code to run instead. * Using this, you are able to replace the original completely. You can still call the original manually if needed. * * @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) { if (this.#callerName) { callback = functionName; functionName = moduleToPatch; moduleToPatch = caller; caller = this.#callerName; } return MainPatcher.pushChildPatch(caller, moduleToPatch, functionName, callback, {type: "instead"}); } /** * 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. * * @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) { if (this.#callerName) { callback = functionName; functionName = moduleToPatch; moduleToPatch = caller; caller = this.#callerName; } 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} Array of all the patch objects */ getPatchesByCaller(caller) { if (this.#callerName) caller = this.#callerName; 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) { if (this.#callerName) caller = this.#callerName; 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); Object.freeze(Patcher.prototype); export default Patcher;