Fix api and some oom issues

This commit is contained in:
Zack Rauen 2022-09-28 16:30:59 -04:00
parent b2aae545c4
commit feb3bb792f
8 changed files with 9 additions and 273 deletions

View File

@ -40,6 +40,10 @@ export function rename(oldPath, newPath) {
return fs.renameSync(oldPath, newPath);
}
export function renameSync(oldPath, newPath) {
return fs.renameSync(oldPath, newPath);
}
export function unlinkSync(fileToDelete) {
return fs.unlinkSync(fileToDelete);
}

View File

@ -1,13 +1,11 @@
import require from "./polyfill"; // eslint-disable-line no-unused-vars
import secure from "./secure";
import patchModuleLoad from "./moduleloader";
import LoadingIcon from "./loadingicon";
import BetterDiscord from "./modules/core";
import BdApi from "./modules/pluginapi";
// Perform some setup
secure();
patchModuleLoad();
window.BdApi = BdApi;
window.global = window;

View File

@ -1,25 +0,0 @@
import BdApi from "./modules/pluginapi";
export default function() {
const namespace = "betterdiscord";
const prefix = `${namespace}/`;
const Module = require("module");
const load = Module._load;
Module._load = function(request) {
if (request === "process") {
return window.process;
}
if (request === namespace || request.startsWith(prefix)) {
const requested = request.slice(prefix.length);
if (requested == "bdapi") return BdApi;
}
return load.apply(this, arguments);
};
return function() {
Module._load = load;
};
}

View File

@ -1,119 +0,0 @@
import {Config} from "data";
import WebpackModules from "./webpackmodules";
import DiscordModules from "./discordmodules";
import DiscordClasses from "./discordclasses";
import Utilities from "./utilities";
import Patcher from "./patcher";
import BDLogo from "../ui/icons/bdlogo";
import Logger from "common/logger";
const React = DiscordModules.React;
const Tooltip = WebpackModules.getByPrototypes("renderTooltip");
const Anchor = WebpackModules.getByProps("Link");
const Developers = [
/* Zerebos#7790 */
"249746236008169473",
/* Strencher#1044 */
"415849376598982656"
];
const DeveloperBadge = function DeveloperBadge({type, size = 16}) {
return React.createElement(Tooltip, {color: "primary", position: "top", text: "BetterDiscord Developer"},
props => React.createElement(Anchor.Link, Object.assign({className: `bd-${type}-badge`, href: "https://github.com/BetterDiscord/BetterDiscord", title: "BetterDiscord", target: "_blank"}, props),
React.createElement(BDLogo, {size, className: "bd-logo"})
)
);
};
export default new class ComponentPatcher {
warn(...message) {return Logger.warn("ComponentPatcher", ...message);}
error(...message) {return Logger.error("ComponentPatcher", ...message);}
debug(...message) {return Logger.debug("ComponentPatcher", ...message);}
initialize() {
// Utilities.suppressErrors(this.patchSocial.bind(this), "BD Social Patch")();
// Utilities.suppressErrors(this.patchMemberList.bind(this), "BD Member List Patch")();
// Utilities.suppressErrors(this.patchProfile.bind(this), "BD Profile Badges Patch")();
}
patchSocial() {
if (this.socialPatch) return;
const TabBar = WebpackModules.getByProps("Types", "Looks", "Header");
if (!TabBar) return;
this.socialPatch = Patcher.after("ComponentPatcher", TabBar.prototype, "render", (thisObject, args, returnValue) => {
const children = returnValue.props.children;
if (!children || !children.length || children.length < 3) return;
if (children[children.length - 3].type.displayName !== "Separator") return;
if (!children[children.length - 2].type.toString().includes("socialLinks")) return;
if (Anchor) {
const original = children[children.length - 2].type;
const newOne = function() {
const returnVal = original(...arguments);
returnVal.props.children.push(
DiscordModules.React.createElement(Anchor, {className: "bd-social-link", href: "https://twitter.com/_BetterDiscord_", title: "BetterDiscord", target: "_blank"},
DiscordModules.React.createElement(BDLogo, {size: "16px", className: "bd-social-logo"})
)
);
return returnVal;
};
children[children.length - 2].type = newOne;
}
const additional = DiscordModules.React.createElement("div", {className: `${DiscordClasses.Text.colorMuted} ${DiscordClasses.Text.size12}`}, `BetterDiscord ${Config.version}`);
const originalVersions = children[children.length - 1].type;
children[children.length - 1].type = function() {
const returnVal = originalVersions(...arguments);
returnVal.props.children.splice(1, 0, additional);
return returnVal;
};
});
}
async patchMemberList() {
if (this.memberListPatch) return;
const memo = WebpackModules.find(m => m?.type?.toString().includes("useGlobalHasAvatarDecorations"));
if (!memo?.type) return;
const MemberListItem = await new Promise(resolve => {
const cancelFindListItem = Patcher.after("ComponentPatcher", memo, "type", (_, props, returnValue) => {
cancelFindListItem();
resolve(returnValue?.type);
});
});
if (!MemberListItem?.prototype?.renderDecorators) return;
this.memberListPatch = Patcher.after("ComponentPatcher", MemberListItem.prototype, "renderDecorators", (thisObject, args, returnValue) => {
const user = Utilities.getNestedProp(thisObject, "props.user");
const children = Utilities.getNestedProp(returnValue, "props.children");
if (!children || Developers.indexOf(user?.id) < 0) return;
if (!Array.isArray(children)) return;
children.push(
React.createElement(DeveloperBadge, {
type: "member"
})
);
});
}
patchProfile() {
if (this.profilePatch) return;
const UserProfileBadgeLists = WebpackModules.getModule(m => m?.toString()?.includes("PROFILE_USER_BADGES"), {first: false});
for (const UserProfileBadgeList of UserProfileBadgeLists) {
this.profilePatch = Patcher.after("ComponentPatcher", UserProfileBadgeList, "default", (_, [{user}], res) => {
if (Developers.indexOf(user?.id) < 0) return;
const children = Utilities.getNestedProp(res, "props.children");
if (!Array.isArray(children)) return;
children.unshift(
React.createElement(DeveloperBadge, {
type: "profile",
size: 18
})
);
});
}
}
};

View File

@ -3,17 +3,14 @@ import LocaleManager from "./localemanager";
import Logger from "common/logger";
import {Config, Changelog} from "data";
import WebpackModules from "./webpackmodules";
import DOMManager from "./dommanager";
import PluginManager from "./pluginmanager";
import ThemeManager from "./thememanager";
import Settings from "./settingsmanager";
import * as Builtins from "builtins";
import Modals from "../ui/modals";
import ReactComponents from "./reactcomponents";
import DataStore from "./datastore";
import DiscordModules from "./discordmodules";
import ComponentPatcher from "./componentpatcher";
import Strings from "./strings";
import IPC from "./ipc";
import LoadingIcon from "../loadingicon";
@ -39,16 +36,11 @@ export default new class Core {
Logger.log("Startup", "Initializing LocaleManager");
LocaleManager.initialize();
Logger.log("Startup", "Performing incompatibility checks");
if (window.ED) return Modals.alert(Strings.Startup.notSupported, Strings.Startup.incompatibleApp.format({app: "EnhancedDiscord"}));
if (window.WebSocket && window.WebSocket.name && window.WebSocket.name.includes("Patched")) return Modals.alert(Strings.Startup.notSupported, Strings.Startup.incompatibleApp.format({app: "Powercord"}));
Logger.log("Startup", "Getting update information");
this.checkForUpdate();
Logger.log("Startup", "Initializing Settings");
Settings.initialize();
// SettingsRenderer.patchSections();
Logger.log("Startup", "Initializing DOMManager");
DOMManager.initialize();
@ -56,12 +48,6 @@ export default new class Core {
Logger.log("Startup", "Waiting for connection...");
await this.waitForConnection();
Logger.log("Startup", "Initializing ReactComponents");
ReactComponents.initialize();
Logger.log("Startup", "Initializing ComponentPatcher");
ComponentPatcher.initialize();
Logger.log("Startup", "Initializing Editor");
await Editor.initialize();
@ -70,7 +56,6 @@ export default new class Core {
Builtins[module].initialize();
}
this.polyfillWebpack();
Logger.log("Startup", "Loading Plugins");
// const pluginErrors = [];
const pluginErrors = PluginManager.initialize();
@ -88,7 +73,6 @@ export default new class Core {
const previousVersion = DataStore.getBDData("version");
if (Config.version > previousVersion) {
// Modals.showChangelogModal(Changelog);
const md = [Changelog.description];
for (const type of Changelog.changes) {
md.push(`**${type.title}**`);
@ -99,19 +83,6 @@ export default new class Core {
Modals.showConfirmationModal(`BetterDiscord v${Config.version}`, md, {cancelText: ""});
DataStore.setBDData("version", Config.version);
}
// SettingsRenderer.patchSections();
}
polyfillWebpack() {
if (typeof(webpackJsonp) !== "undefined") return;
window.webpackJsonp = [];
window.webpackJsonp.length = 10000; // In case plugins are waiting for that.
window.webpackJsonp.flat = () => window.webpackJsonp;
// eslint-disable-next-line no-empty-pattern
window.webpackJsonp.push = ([[], module, [[id]]]) => {
return module[id]({}, {}, WebpackModules.require);
};
}
waitForConnection() {

View File

@ -12,7 +12,6 @@ export {default as Settings} from "./settingsmanager";
export {default as DOMManager} from "./dommanager";
export {default as DOM} from "./domtools";
export {default as Patcher} from "./patcher";
export {default as ReactComponents} from "./reactcomponents";
export {default as LocaleManager} from "./localemanager";
export {default as Strings} from "./strings";
export {default as IPC} from "./ipc";

View File

@ -617,7 +617,7 @@ BdApi.Webpack = {
* @param {...String} strings A list of strings
* @returns {function} A filter that checks for a set of strings
*/
byStrings(...strings) {return Filters.byStrings(strings);},
byStrings(...strings) {return Filters.byStrings(...strings);},
/**
* Generates a function that filters by the `displayName` property.
@ -631,13 +631,13 @@ BdApi.Webpack = {
* @param {...function} filters A list of filters
* @returns {function} Combinatory filter of all arguments
*/
combine(...filters) {return Filters.combine(filters);},
combine(...filters) {return Filters.combine(...filters);},
},
/**
* Finds a module using a filter function.
* @param {function} filter A function to use to filter modules. It is given exports, module, and moduleID. Return `true` to signify match.
* @param {object} [options] Whether to return only the first matching module
* @param {object} [options] Options object to configure the search
* @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}
@ -651,7 +651,7 @@ BdApi.Webpack = {
/**
* Finds multiple modules using multiple filters.
*
* @param {...object} queries Whether to return only the first matching module
* @param {...object} queries Object representing the query
* @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
@ -662,7 +662,7 @@ BdApi.Webpack = {
/**
* Finds a module that is lazily loaded.
* @param {function} filter A function to use to filter modules. It is given exports. Return `true` to signify match.
* @param {object} [options] Whether to return only the first matching module
* @param {object} [options] Options object to configure the listener
* @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>}

View File

@ -1,92 +0,0 @@
import DiscordModules from "./discordmodules";
import Patcher from "./patcher";
const React = DiscordModules.React;
const components = {};
const unknownComponents = new Set();
const listeners = new Set();
export default new class ReactComponents {
get named() {return components;}
get unknown() {return unknownComponents;}
get listeners() {return listeners;}
constructor() {
Patcher.after("ReactComponents", React, "createElement", (_, __, returnValue) => {
this.walkRenderTree(returnValue);
});
Patcher.instead("ReactComponents", React.Component.prototype, "componentWillMount", (thisObject) => {
this.addComponent(thisObject.constructor);
});
Patcher.instead("ReactComponents", React.Component.prototype, "UNSAFE_componentWillMount", (thisObject) => {
this.addComponent(thisObject.constructor);
});
Patcher.instead("ReactComponents", React.PureComponent.prototype, "componentWillMount", (thisObject) => {
this.addComponent(thisObject.constructor);
});
Patcher.instead("ReactComponents", React.PureComponent.prototype, "UNSAFE_componentWillMount", (thisObject) => {
this.addComponent(thisObject.constructor);
});
}
initialize() {
this.walkReactTree(document.querySelector("#app-mount")._reactRootContainer._internalRoot.current);
}
get(name, filter) {
return new Promise(resolve => {
if (components[name]) return resolve(components[name]);
listeners.add({name, filter, resolve});
if (!filter) return;
for (const component of unknownComponents) {
if (!filter(component)) continue;
component.displayName = name;
unknownComponents.delete(component);
this.addNamedComponent(component);
}
});
}
addNamedComponent(component) {
const name = component.displayName;
if (!components[name]) {
components[name] = component;
for (const listener of listeners) {
if (listener.name !== name) continue;
listener.resolve(component);
listeners.delete(listener);
}
}
}
addUnknownComponent(component) {
if (unknownComponents.has(component)) return;
for (const listener of listeners) {
if (!listener.filter || !listener.filter(component)) continue;
component.displayName = listener.name;
this.addNamedComponent(component);
}
if (!component.displayName) unknownComponents.add(component);
}
addComponent(component) {
if (component.displayName) return this.addNamedComponent(component);
return this.addUnknownComponent(component);
}
walkRenderTree(tree) {
if (!tree) return;
if (typeof(tree.type) == "function") this.addComponent(tree.type);
if (Array.isArray(tree)) for (const value of tree) this.walkRenderTree(value);
if (tree.props && tree.props.children) this.walkRenderTree(tree.props.children);
}
walkReactTree(tree) {
if (!tree) return;
if (typeof(tree.type) == "function") this.addComponent(tree.type);
if (tree.child) this.walkReactTree(tree.child);
if (tree.sibling) this.walkReactTree(tree.sibling);
}
};