Expose webpack to bdapi

This commit is contained in:
Zack Rauen 2022-08-01 17:53:43 -04:00
parent 29666219fd
commit 267b37ddc1
4 changed files with 77 additions and 25 deletions

View File

@ -9,7 +9,6 @@ const fs = require("fs");
const electron = require("electron");
const UserSettings = WebpackModules.getByProps("updateAccount");
const Dispatcher = WebpackModules.getByProps("dirtyDispatch");
const ActionTypes = WebpackModules.getByProps("ActionTypes", "ActivityFlags").ActionTypes;
export default new class CustomCSS extends Builtin {
get name() {return "Custom CSS";}
@ -151,6 +150,6 @@ export default new class CustomCSS extends Builtin {
});
this.isDetached = true;
UserSettings.close();
Dispatcher.dispatch({type: ActionTypes.LAYER_POP});
Dispatcher.dispatch({type: "LAYER_POP"});
}
};

View File

@ -3,7 +3,7 @@ import DiscordModules from "./discordmodules";
import Utilities from "./utilities";
import Events from "./emitter";
const {Dispatcher, DiscordConstants, UserSettingsStore} = DiscordModules;
const {Dispatcher, UserSettingsStore} = DiscordModules;
export default new class LocaleManager {
get discordLocale() {return UserSettingsStore.locale;}
@ -16,7 +16,7 @@ export default new class LocaleManager {
initialize() {
this.setLocale(this.discordLocale);
Dispatcher.subscribe(DiscordConstants.ActionTypes.USER_SETTINGS_UPDATE, ({settings}) => {
Dispatcher.subscribe("USER_SETTINGS_UPDATE", ({settings}) => {
const newLocale = settings.locale;
if (newLocale && newLocale != this.locale) this.setLocale(newLocale);
});

View File

@ -1,6 +1,6 @@
import {Config} from "data";
import Utilities from "./utilities";
import WebpackModules from "./webpackmodules";
import WebpackModules, {Filters} from "./webpackmodules";
import DiscordModules from "./discordmodules";
import DataStore from "./datastore";
import DOMManager from "./dommanager";
@ -134,7 +134,7 @@ BdApi.findModule = function(filter) {
// Finds module
BdApi.findAllModules = function(filter) {
return WebpackModules.getModule(filter, false);
return WebpackModules.getModule(filter, {first: false});
};
// Finds module
@ -282,9 +282,44 @@ BdApi.Patcher = {
}
};
BdApi.Webpack = {
Filters: Filters,
/**
* Finds a module using a filter function.
* @param {(exports, module, moduleId) => boolean} filter A function to use to filter modules
* @param {object} [options] Whether to return only the first matching module
* @param {Boolean} [options.first=true] Whether to return only the first matching module
* @param {Boolean} [options.defaultExport=true] Whether to return default export when matching the default export
* @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.");
return WebpackModules.getModule(filter, options);
},
/**
* Finds a module that lazily loaded.
* @param {(exports) => boolean} filter A function to use to filter modules.
* @param {object} [options] Whether to return only the first matching module
* @param {AbortSignal} [options.signal] AbortSignal of an AbortController to cancel the promise
* @param {Boolean} [options.defaultExport=true] Whether to return default export when matching the default export
* @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.");
return WebpackModules.getLazy(filter, options);
},
};
Object.freeze(BdApi);
Object.freeze(BdApi.Plugins);
Object.freeze(BdApi.Themes);
Object.freeze(BdApi.Patcher);
Object.freeze(BdApi.Webpack);
Object.freeze(BdApi.Webpack.Filters);
export default BdApi;

View File

@ -22,12 +22,12 @@ export class Filters {
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties
*/
static byProperties(props, filter = m => m) {
static byProps(props, filter = m => m) {
return module => {
const component = filter(module);
if (!component) return false;
for (let p = 0; p < props.length; p++) {
if (component[props[p]] === undefined) return false;
if (!Reflect.has(component, props[p])) return false;
}
return true;
};
@ -45,7 +45,7 @@ export class Filters {
if (!component) return false;
if (!component.prototype) return false;
for (let f = 0; f < fields.length; f++) {
if (component.prototype[fields[f]] === undefined) return false;
if (!Reflect.has(component.prototype, fields[f])) return false;
}
return true;
};
@ -57,7 +57,7 @@ export class Filters {
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties
*/
static byCode(search, filter = m => m) {
static byRegex(search, filter = m => m) {
return module => {
const method = filter(module);
if (!method) return false;
@ -73,7 +73,7 @@ export class Filters {
* @param {...String} search - A RegExp to check on the module
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of strings
*/
static byString(...strings) {
static byStrings(...strings) {
return module => {
let moduleString = "";
try {moduleString = module.toString([]);}
@ -137,13 +137,21 @@ export default class WebpackModules {
/**
* Finds a module using a filter function.
* @param {Function} filter A function to use to filter modules
* @param {Boolean} first Whether to return only the first matching module
* @param {object} [options] Whether to return only the first matching module
* @param {Boolean} [options.first=true] Whether to return only the first matching module
* @param {Boolean} [options.defaultExport=true] Whether to return default export when matching the default export
* @return {Any}
*/
static getModule(filter, first = true) {
const wrappedFilter = (m) => {
try {return filter(m);}
catch (err) {return false;}
static getModule(filter, options = {}) {
const {first = true, defaultExport = true} = options;
const wrappedFilter = (exports, module, moduleId) => {
try {
return filter(exports, module, moduleId);
}
catch (err) {
Logger.warn("WebpackModules~getModule", "Module filter threw an exception.", filter, err);
return false;
}
};
const modules = this.getAllModules();
const rm = [];
@ -154,8 +162,8 @@ export default class WebpackModules {
let foundModule = null;
if (!exports) continue;
if (exports.__esModule && exports.default && wrappedFilter(exports.default)) foundModule = exports.default;
if (wrappedFilter(exports)) foundModule = exports;
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) return protect(foundModule);
rm.push(protect(foundModule));
@ -186,7 +194,7 @@ export default class WebpackModules {
* @return {Any}
*/
static getByRegex(regex, first = true) {
return this.getModule(Filters.byCode(regex), first);
return this.getModule(Filters.byRegex(regex), first);
}
/**
@ -213,7 +221,7 @@ export default class WebpackModules {
* @return {Any}
*/
static getByProps(...props) {
return this.getModule(Filters.byProperties(props), true);
return this.getModule(Filters.byProps(props), true);
}
/**
@ -222,7 +230,7 @@ export default class WebpackModules {
* @return {Any}
*/
static getAllByProps(...props) {
return this.getModule(Filters.byProperties(props), false);
return this.getModule(Filters.byProps(props), false);
}
/**
@ -231,7 +239,7 @@ export default class WebpackModules {
* @return {Any}
*/
static getByString(...strings) {
return this.getModule(Filters.byString(...strings), true);
return this.getModule(Filters.byStrings(...strings), true);
}
/**
@ -240,15 +248,21 @@ export default class WebpackModules {
* @return {Any}
*/
static getAllByString(...strings) {
return this.getModule(Filters.byString(...strings), false);
return this.getModule(Filters.byStrings(...strings), false);
}
/**
* Finds a module that lazily loaded.
* @param {(m) => boolean} filter A function to use to filter modules.
* @param {object} [options] Whether to return only the first matching module
* @param {AbortSignal} [options.signal] AbortSignal of an AbortController to cancel the promise
* @param {Boolean} [options.defaultExport=true] Whether to return default export when matching the default export
* @returns {Promise<any>}
*/
static getLazy(filter) {
static getLazy(filter, options = {}) {
/** @type {AbortSignal} */
const abortSignal = options.signal;
const defaultExport = options.defaultExport;
const fromCache = this.getModule(filter);
if (fromCache) return Promise.resolve(fromCache);
@ -266,10 +280,14 @@ export default class WebpackModules {
if (!defaultMatch) return;
cancel();
resolve(m.default);
resolve(defaultExport ? m.default : defaultExport);
};
this.addListener(listener);
abortSignal?.addEventListener("abort", () => {
cancel();
resolve();
});
});
}