Add getbulk and patcher bind

This commit is contained in:
Zack Rauen 2022-08-01 20:52:07 -04:00
parent 267b37ddc1
commit 2018f691e6
5 changed files with 85 additions and 10 deletions

View File

@ -155,7 +155,7 @@ export default class AddonManager {
for (const line of block.split(splitRegex)) {
if (line.length === 0) continue;
if (line.charAt(0) === "@" && line.charAt(1) !== " ") {
out[field] = accum;
out[field] = accum.trim();
const l = line.indexOf(" ");
field = line.substring(1, l);
accum = line.substring(l + 1);

View File

@ -135,7 +135,7 @@ export default new class ComponentPatcher {
patchGuildPills() {
if (this.guildPillPatch) return;
const guildPill = WebpackModules.find(m => m.default.displayName === "AnimatedHalfPill");
const guildPill = WebpackModules.find(m => m?.default?.displayName === "AnimatedHalfPill");
if (!guildPill) return;
this.guildPillPatch = Patcher.after("ComponentPatcher", guildPill, "default", (_, args, returnValue) => {
const props = args[0];

View File

@ -38,7 +38,7 @@ const DiscordClasses = new Proxy(DiscordClassModules, {
return new Proxy(list[item], {
get(obj, prop) {
if (!Reflect.has(obj, prop)) return "";
if (!(prop in obj)) return "";
return new ClassName(obj[prop]);
}

View File

@ -264,6 +264,16 @@ const makeAddonAPI = (manager) => new class AddonAPI {
BdApi.Plugins = makeAddonAPI(PluginManager);
BdApi.Themes = makeAddonAPI(ThemeManager);
BdApi.Patcher = {
bind: (id) => {
return {
patch: BdApi.Patcher.patch.bind(BdApi.Patcher, id),
before: BdApi.Patcher.before.bind(BdApi.Patcher, id),
instead: BdApi.Patcher.instead.bind(BdApi.Patcher, id),
after: BdApi.Patcher.after.bind(BdApi.Patcher, id),
getPatchesByCaller: BdApi.Patcher.getPatchesByCaller.bind(BdApi.Patcher, id),
unpatchAll: BdApi.Patcher.unpatchAll.bind(BdApi.Patcher, id),
};
},
patch: (caller, moduleToPatch, functionName, callback, options = {}) => {
if (typeof(caller) !== "string") return Logger.err("BdApi.Patcher", "Parameter 0 of patch must be a string representing the caller");
if (options.type !== "before" && options.type !== "instead" && options.type !== "after") return Logger.err("BdApi.Patcher", "options.type must be one of: before, instead, after");
@ -295,11 +305,22 @@ BdApi.Webpack = {
* @return {Any}
*/
getModule(filter, options = {}) {
if (Reflect.has(options, "first") && typeof(options.first) !== "boolean") return Logger.error("BdApi.Webpack~getModule", "Unsupported type used for options.first", options.first, "boolean expected.");
if (Reflect.has(options, "defaultExport") && typeof(options.defaultExport) !== "boolean") return Logger.error("BdApi.Webpack~getModule", "Unsupported type used for options.defaultExport", options.defaultExport, "boolean expected.");
if (("first" in options) && typeof(options.first) !== "boolean") return Logger.error("BdApi.Webpack~getModule", "Unsupported type used for options.first", options.first, "boolean expected.");
if (("defaultExport" in options) && typeof(options.defaultExport) !== "boolean") return Logger.error("BdApi.Webpack~getModule", "Unsupported type used for options.defaultExport", options.defaultExport, "boolean expected.");
return WebpackModules.getModule(filter, options);
},
/**
* Finds multiple modules using multiple filters.
*
* @param {...object} queries Whether to return only the first matching module
* @param {Function} queries.filter A function to use to filter modules
* @param {Boolean} [queries.first=true] Whether to return only the first matching module
* @param {Boolean} [queries.defaultExport=true] Whether to return default export when matching the default export
* @return {Any}
*/
getBulk(...queries) {return WebpackModules.getBulk(...queries);},
/**
* Finds a module that lazily loaded.
* @param {(exports) => boolean} filter A function to use to filter modules.
@ -309,8 +330,8 @@ BdApi.Webpack = {
* @returns {Promise<any>}
*/
waitForModule(filter, options = {}) {
if (Reflect.has(options, "defaultExport") && typeof(options.defaultExport) !== "boolean") return Logger.error("BdApi.Webpack~waitForModule", "Unsupported type used for options.defaultExport", options.defaultExport, "boolean expected.");
if (Reflect.has(options, "signal") && !(options.signal instanceof AbortSignal)) return Logger.error("BdApi.Webpack~waitForModule", "Unsupported type used for options.signal", options.signal, "AbortSignal expected.");
if (("defaultExport" in options) && typeof(options.defaultExport) !== "boolean") return Logger.error("BdApi.Webpack~waitForModule", "Unsupported type used for options.defaultExport", options.defaultExport, "boolean expected.");
if (("signal" in options) && !(options.signal instanceof AbortSignal)) return Logger.error("BdApi.Webpack~waitForModule", "Unsupported type used for options.signal", options.signal, "AbortSignal expected.");
return WebpackModules.getLazy(filter, options);
},
};

View File

@ -24,10 +24,12 @@ export class Filters {
*/
static byProps(props, filter = m => m) {
return module => {
if (!module) return false;
if (typeof(module) !== "object" && typeof(module) !== "function") return false;
const component = filter(module);
if (!component) return false;
for (let p = 0; p < props.length; p++) {
if (!Reflect.has(component, props[p])) return false;
if (!(props[p] in component)) return false;
}
return true;
};
@ -41,11 +43,13 @@ export class Filters {
*/
static byPrototypeFields(fields, filter = m => m) {
return module => {
if (!module) return false;
if (typeof(module) !== "object" && typeof(module) !== "function") return false;
const component = filter(module);
if (!component) return false;
if (!component.prototype) return false;
for (let f = 0; f < fields.length; f++) {
if (!Reflect.has(component.prototype, fields[f])) return false;
if (!(fields[f] in component.prototype)) return false;
}
return true;
};
@ -155,7 +159,9 @@ export default class WebpackModules {
};
const modules = this.getAllModules();
const rm = [];
for (const index in modules) {
const indices = Object.keys(modules);
for (let i = 0; i < indices.length; i++) {
const index = indices[i];
if (!modules.hasOwnProperty(index)) continue;
const module = modules[index];
const {exports} = module;
@ -172,6 +178,54 @@ export default class WebpackModules {
return first || rm.length == 0 ? undefined : rm;
}
/**
* Finds multiple modules using multiple filters.
*
* @param {...object} queries Whether to return only the first matching module
* @param {Function} queries.filter A function to use to filter modules
* @param {Boolean} [queries.first=true] Whether to return only the first matching module
* @param {Boolean} [queries.defaultExport=true] Whether to return default export when matching the default export
* @return {Any}
*/
static getBulk(...queries) {
const modules = this.getAllModules();
const returnedModules = Array(queries.length);
const indices = Object.keys(modules);
for (let i = 0; i < indices.length; i++) {
const index = indices[i];
if (!modules.hasOwnProperty(index)) continue;
const module = modules[index];
const {exports} = module;
if (!exports) continue;
for (let q = 0; q < queries.length; q++) {
const query = queries[q];
const {filter, first = true, defaultExport = true} = query;
if (first && returnedModules[q]) continue; // If they only want the first, and we already found it, move on
if (!first && !returnedModules[q]) returnedModules[q] = []; // If they want multiple and we haven't setup the subarry, do it now
const wrappedFilter = (ex, mod, moduleId) => {
try {
return filter(ex, mod, moduleId);
}
catch (err) {
Logger.warn("WebpackModules~getModule", "Module filter threw an exception.", filter, err);
return false;
}
};
let foundModule = null;
if (exports.__esModule && exports.default && wrappedFilter(exports.default, module, index)) foundModule = defaultExport ? exports.default : exports;
if (wrappedFilter(exports, module, index)) foundModule = exports;
if (!foundModule) continue;
if (first) returnedModules[q] = protect(foundModule);
else returnedModules[q].push(protect(foundModule));
}
}
return returnedModules;
}
/**
* Finds all modules matching a filter function.
* @param {Function} filter A function to use to filter modules