more cleanup and slight rearrange

This commit is contained in:
Zack Rauen 2019-06-19 15:24:05 -04:00
parent e3ce238440
commit c56710569b
23 changed files with 717 additions and 286 deletions

File diff suppressed because one or more lines are too long

View File

@ -106,10 +106,6 @@ export default new class CustomCSS extends Builtin {
insertCSS(newCss) {
if (typeof(newCss) === "undefined") newCss = this.insertedCss;
else this.insertedCss = newCss;
// if ($("#customcss").length == 0) {
// $("head").append("<style id=\"customcss\"></style>");
// }
// $("#customcss").text(newCss).detach().appendTo(document.head);
DOMManager.updateCustomCSS(newCss);
}
@ -133,7 +129,7 @@ export default new class CustomCSS extends Builtin {
openNative: this.openNative.bind(this),
onChange: this.onChange.bind(this)
});
FloatingWindowContainer.open({
onClose: () => {
this.isDetached = false;

View File

@ -6,10 +6,10 @@ export default new class DarkMode extends Builtin {
get id() {return "darkMode";}
enabled() {
$("#app-mount").addClass("bda-dark").addClass("bd-dark");
document.getElementById("app-mount").classList.add("bda-dark", "bda-dark");
}
disabled() {
$("#app-mount").removeClass("bda-dark").removeClass("bd-dark");
document.getElementById("app-mount").classList.remove("bda-dark", "bda-dark");
}
};

View File

@ -159,18 +159,19 @@ export default new class EmoteModule extends Builtin {
if (exists && this.isCacheValid()) {
Toasts.show("Loading emotes from cache.", {type: "info"});
Utilities.log("Emotes", "Loading emotes from local cache.");
this.log("Loading emotes from local cache.");
const data = await new Promise(resolve => {
_fs.readFile(file, "utf8", (err, content) => {
Utilities.log("Emotes", "Emotes loaded from cache.");
this.log("Emotes loaded from cache.");
if (err) content = {};
resolve(content);
});
});
let isValid = Utilities.testJSON(data);
if (isValid) Object.assign(Emotes, JSON.parse(data));
const parsed = Utilities.testJSON(data);
let isValid = !!parsed;
if (isValid) Object.assign(Emotes, parsed);
for (const e in emoteInfo) {
isValid = Object.keys(Emotes[emoteInfo[e].variable]).length > 0;
@ -183,7 +184,7 @@ export default new class EmoteModule extends Builtin {
return;
}
Utilities.log("Emotes", "Cache was corrupt, downloading...");
this.log("Cache was corrupt, downloading...");
_fs.unlinkSync(file);
}
@ -199,7 +200,7 @@ export default new class EmoteModule extends Builtin {
Toasts.show("All emotes successfully downloaded.", {type: "success"});
try { _fs.writeFileSync(file, JSON.stringify(Emotes), "utf8"); }
catch (err) { Utilities.err("Emotes", "Could not save emote data.", err); }
catch (err) { this.stacktrace("Could not save emote data.", err); }
this.emotesLoaded = true;
Events.dispatch("emotes-loaded");
@ -209,15 +210,16 @@ export default new class EmoteModule extends Builtin {
const request = require("request");
const options = {
url: emoteMeta.url,
timeout: emoteMeta.timeout ? emoteMeta.timeout : 5000
timeout: emoteMeta.timeout ? emoteMeta.timeout : 5000,
json: true
};
Utilities.log("Emotes", `Downloading: ${emoteMeta.variable} (${emoteMeta.url})`);
this.log(`Downloading: ${emoteMeta.variable} (${emoteMeta.url})`);
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
request(options, (error, response, parsedData) => {
if (error) {
Utilities.err("Emotes", "Could not download " + emoteMeta.variable, error);
this.stacktrace("Could not download " + emoteMeta.variable, error);
if (emoteMeta.backup) {
emoteMeta.url = emoteMeta.backup;
emoteMeta.backup = null;
@ -227,20 +229,6 @@ export default new class EmoteModule extends Builtin {
return reject({});
}
let parsedData = {};
try {
parsedData = JSON.parse(body);
}
catch (err) {
Utilities.err("Emotes", "Could not download " + emoteMeta.variable, err);
if (emoteMeta.backup) {
emoteMeta.url = emoteMeta.backup;
emoteMeta.backup = null;
if (emoteMeta.backupParser) emoteMeta.parser = emoteMeta.backupParser;
return resolve(this.downloadEmotes(emoteMeta));
}
return reject({});
}
if (typeof(emoteMeta.parser) === "function") parsedData = emoteMeta.parser(parsedData);
for (const emote in parsedData) {
@ -251,7 +239,7 @@ export default new class EmoteModule extends Builtin {
parsedData[emote] = emoteMeta.getEmoteURL(parsedData[emote]);
}
resolve(parsedData);
Utilities.log("Emotes", "Downloaded: " + emoteMeta.variable);
this.log("Downloaded: " + emoteMeta.variable);
});
});
}

View File

@ -8,6 +8,7 @@ import Events from "./modules/emitter";
import Settings from "./modules/settingsmanager";
import DataStore from "./modules/datastore";
import EmoteModule from "./builtins/emotes";
import DomManager from "./modules/dommanager";
// Perform some setup
// proxyLocalStorage();
@ -33,6 +34,9 @@ window.settingsModule = Settings;
window.DataStore = DataStore;
window.DomManager = DomManager;
window.BDEvents = Events;
window.bdConfig = Config;

View File

@ -1,4 +1,5 @@
import WebpackModules, {DiscordModules} from "./webpackmodules";
import WebpackModules from "./webpackmodules";
import DiscordModules from "./discordmodules";
import Utilities from "./utilities";
import BDLogo from "../ui/icons/bdlogo";

View File

@ -1,4 +1,5 @@
import Utilities from "./utilities";
import Logger from "./logger";
import Settings from "./settingsmanager";
import Events from "./emitter";
import DataStore from "./datastore";
@ -58,8 +59,8 @@ export default class ContentManager {
}
watchContent() {
if (this.watcher) return Utilities.err(this.name, "Already watching content.");
Utilities.log(this.name, "Starting to watch content.");
if (this.watcher) return Logger.error(this.name, "Already watching content.");
Logger.log(this.name, "Starting to watch content.");
this.watcher = fs.watch(this.contentFolder, {persistent: false}, async (eventType, filename) => {
if (!eventType || !filename || !filename.endsWith(this.extension)) return;
await new Promise(r => setTimeout(r, 50));
@ -81,10 +82,10 @@ export default class ContentManager {
}
unwatchContent() {
if (!this.watcher) return Utilities.err(this.name, "Was not watching content.");
if (!this.watcher) return Logger.error(this.name, "Was not watching content.");
this.watcher.close();
delete this.watcher;
Utilities.log(this.name, "No longer watching content.");
Logger.log(this.name, "No longer watching content.");
}
extractMeta(content) {
@ -99,9 +100,8 @@ export default class ContentManager {
parseOldMeta(content) {
const meta = content.split("\n")[0];
const metaData = meta.substring(meta.lastIndexOf("//META") + 6, meta.lastIndexOf("*//"));
if (!Utilities.testJSON(metaData)) throw new MetaError("META could not be parsed.");
const parsed = JSON.parse(metaData);
const parsed = Utilities.testJSON(metaData);
if (!parsed) throw new MetaError("META could not be parsed.");
if (!parsed.name) throw new MetaError("META missing name data.");
return parsed;
}

View File

@ -1,5 +1,6 @@
import BDV2 from "./bdv2";
import Utilities from "./utilities";
import Logger from "./logger";
import {Config} from "data";
// import EmoteModule from "./emotes";
// import QuickEmoteMenu from "../builtins/emotemenu";
@ -31,12 +32,12 @@ Core.prototype.init = async function() {
`);
}
Utilities.log("Startup", "Initializing Settings");
Logger.log("Startup", "Initializing Settings");
Settings.initialize();
Utilities.log("Startup", "Initializing EmoteModule");
Logger.log("Startup", "Initializing EmoteModule");
// window.emotePromise = EmoteModule.init().then(() => {
// EmoteModule.initialized = true;
// Utilities.log("Startup", "Initializing QuickEmoteMenu");
// Logger.log("Startup", "Initializing QuickEmoteMenu");
// Events.dispatch("emotes-loaded");
// // QuickEmoteMenu.init();
// });
@ -46,42 +47,40 @@ Core.prototype.init = async function() {
DOMManager.initialize();
await this.checkForGuilds();
BDV2.initialize();
Utilities.log("Startup", "Updating Settings");
Logger.log("Startup", "Updating Settings");
for (const module in Builtins) Builtins[module].initialize();
Utilities.log("Startup", "Loading Plugins");
Logger.log("Startup", "Loading Plugins");
const pluginErrors = PluginManager.loadAllPlugins();
Utilities.log("Startup", "Loading Themes");
Logger.log("Startup", "Loading Themes");
const themeErrors = ThemeManager.loadAllThemes();
// $("#customcss").detach().appendTo(document.head);
// PublicServers.initialize();
// EmoteModule.autoCapitalize();
Utilities.log("Startup", "Removing Loading Icon");
Logger.log("Startup", "Removing Loading Icon");
document.getElementsByClassName("bd-loaderv2")[0].remove();
Utilities.log("Startup", "Initializing Main Observer");
Logger.log("Startup", "Initializing Main Observer");
this.initObserver();
// Show loading errors
Utilities.log("Startup", "Collecting Startup Errors");
Logger.log("Startup", "Collecting Startup Errors");
Modals.showContentErrors({plugins: pluginErrors, themes: themeErrors});
};
Core.prototype.checkForGuilds = function() {
return new Promise(resolve => {
const checkForGuilds = function() {
if (document.readyState != "complete") setTimeout(checkForGuilds, 100);
const wrapper = BDV2.guildClasses.wrapper.split(" ")[0];
const guild = BDV2.guildClasses.listItem.split(" ")[0];
const blob = BDV2.guildClasses.blobContainer.split(" ")[0];
if (document.querySelectorAll(`.${wrapper} .${guild} .${blob}`).length > 0) return resolve(Config.deferLoaded = true);
setTimeout(checkForGuilds, 100);
};
$(document).ready(function () {
setTimeout(checkForGuilds, 100);
});
checkForGuilds();
});
};

View File

@ -0,0 +1,146 @@
/**
* A large list of known and useful webpack modules internal to Discord.
*
* @module DiscordModules
* @version 0.0.3
*/
import Utilities from "./utilities";
import WebpackModules from "./webpackmodules";
export default Utilities.memoizeObject({
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
get Flux() {return WebpackModules.getByProps("connectStores");},
get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
/* Guild Info, Stores, and Utilities */
get GuildStore() {return WebpackModules.getByProps("getGuild");},
get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
/* Channel Store & Actions */
get ChannelStore() {return WebpackModules.getByProps("getChannels", "getDMFromUserId");},
get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
/* Current User Info, State and Settings */
get UserInfoStore() {return WebpackModules.getByProps("getToken");},
get UserSettingsStore() {return WebpackModules.getByProps("guildPositions");},
get AccountManager() {return WebpackModules.getByProps("register", "login");},
get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
get MentionStore() {return WebpackModules.getByProps("getMentions");},
/* User Stores and Utils */
get UserStore() {return WebpackModules.getByProps("getCurrentUser");},
get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
get UserNameResolver() {return WebpackModules.getByProps("getName");},
get UserNoteStore() {return WebpackModules.getByProps("getNote");},
get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
/* Emoji Store and Utils */
get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
/* Invite Store and Utils */
get InviteStore() {return WebpackModules.getByProps("getInvites");},
get InviteResolver() {return WebpackModules.getByProps("findInvite");},
get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
/* Discord Objects & Utils */
get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
get PermissionUtils() {return WebpackModules.getByProps("getHighestRole");},
get ColorConverter() {return WebpackModules.getByProps("hex2int");},
get ColorShader() {return WebpackModules.getByProps("darken");},
get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
get ClassResolver() {return WebpackModules.getByProps("getClass");},
get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
get IconNames() {return WebpackModules.getByProps("IconNames");},
get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
/* Discord Messages */
get MessageStore() {return WebpackModules.getByProps("getMessages");},
get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
get MessageQueue() {return WebpackModules.getByProps("enqueue");},
get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
/* Text Processing */
get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
/* Experiments */
get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
/* Images, Avatars and Utils */
get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
/* Window, DOM, HTML */
get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
/* Locale/Location and Time */
get LocaleManager() {return WebpackModules.getByProps("setLocale");},
get Moment() {return WebpackModules.getByProps("parseZone");},
get LocationManager() {return WebpackModules.getByProps("createLocation");},
get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
get TimeFormatter() {return WebpackModules.getByProps("dateFormat");},
/* Strings and Utils */
get Strings() {return WebpackModules.getByProps("Messages").Messages;},
get StringFormats() {return WebpackModules.getByProps("a", "z");},
get StringUtils() {return WebpackModules.getByProps("toASCII");},
/* URLs and Utils */
get URLParser() {return WebpackModules.getByProps("Url", "parse");},
get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
/* Drag & Drop */
get DNDActions() {return WebpackModules.getByProps("beginDrag");},
get DNDSources() {return WebpackModules.getByProps("addTarget");},
get DNDObjects() {return WebpackModules.getByProps("DragSource");},
/* Media Stuff (Audio/Video) */
get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
get SoundModule() {return WebpackModules.getByProps("playSound");},
/* Electron & Other Internals with Utils*/
get ElectronModule() {return WebpackModules.getByProps("setBadge");},
get Dispatcher() {return WebpackModules.getByProps("dirtyDispatch");},
get PathUtils() {return WebpackModules.getByProps("hasBasename");},
get NotificationModule() {return WebpackModules.getByProps("showNotification");},
get RouterModule() {return WebpackModules.getByProps("Router");},
get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
get Buffers() {return WebpackModules.getByProps("Buffer", "kMaxLength");},
get DeviceStore() {return WebpackModules.getByProps("getDevices");},
get SoftwareInfo() {return WebpackModules.getByProps("os");},
get CurrentContext() {return WebpackModules.getByProps("setTagsContext");}
});

View File

@ -32,23 +32,23 @@ export default class DOMManager {
}
static removeStyle(id) {
const exists = this.getElement(id, this.bdStyles);
const exists = this.getElement(`#${id}`, this.bdStyles);
if (exists) exists.remove();
}
static injectStyle(id, css) {
const style = this.getElement(id, this.bdStyles) || this.createElement("style", {id});
const style = this.getElement(`#${id}`, this.bdStyles) || this.createElement("style", {id});
style.textContent = css;
this.bdStyles.append(style);
}
static removeTheme(id) {
const exists = this.getElement(id, this.bdThemes);
const exists = this.getElement(`#${id}`, this.bdThemes);
if (exists) exists.remove();
}
static injectTheme(id, css) {
const style = this.getElement(id, this.bdThemes) || this.createElement("style", {id});
const style = this.getElement(`#${id}`, this.bdThemes) || this.createElement("style", {id});
style.textContent = css;
this.bdThemes.append(style);
}

95
src/modules/logger.js Normal file
View File

@ -0,0 +1,95 @@
/**
* Simple logger for the lib and plugins.
*
* @module Logger
* @version 0.1.0
*/
/* eslint-disable no-console */
/**
* List of logging types.
*/
export const LogTypes = {
/** Alias for error */
err: "error",
error: "error",
/** Alias for debug */
dbg: "debug",
debug: "debug",
log: "log",
warn: "warn",
info: "info"
};
export default class Logger {
/**
* Logs an error using a collapsed error group with stacktrace.
*
* @param {string} module - Name of the calling module.
* @param {string} message - Message or error to have logged.
* @param {Error} error - Error object to log with the message.
*/
static stacktrace(module, message, error) {
console.error(`%c[${module}]%c ${message}\n\n%c`, "color: #3a71c1; font-weight: 700;", "color: red; font-weight: 700;", "color: red;", error);
}
/**
* Logs using error formatting. For logging an actual error object consider {@link module:Logger.stacktrace}
*
* @param {string} module - Name of the calling module.
* @param {string} message - Messages to have logged.
*/
static err(module, ...message) { Logger._log(module, message, "error"); }
/**
* Logs a warning message.
*
* @param {string} module - Name of the calling module.
* @param {...any} message - Messages to have logged.
*/
static warn(module, ...message) { Logger._log(module, message, "warn"); }
/**
* Logs an informational message.
*
* @param {string} module - Name of the calling module.
* @param {...any} message - Messages to have logged.
*/
static info(module, ...message) { Logger._log(module, message, "info"); }
/**
* Logs used for debugging purposes.
*
* @param {string} module - Name of the calling module.
* @param {...any} message - Messages to have logged.
*/
static debug(module, ...message) { Logger._log(module, message, "debug"); }
/**
* Logs used for basic loggin.
*
* @param {string} module - Name of the calling module.
* @param {...any} message - Messages to have logged.
*/
static log(module, ...message) { Logger._log(module, message); }
/**
* Logs strings using different console levels and a module label.
*
* @param {string} module - Name of the calling module.
* @param {any|Array<any>} message - Messages to have logged.
* @param {module:Logger.LogTypes} type - Type of log to use in console.
*/
static _log(module, message, type = "log") {
type = Logger.parseType(type);
if (!Array.isArray(message)) message = [message];
console[type](`%c[${module}]%c`, "color: #3a71c1; font-weight: 700;", "", ...message);
}
static parseType(type) {
return LogTypes.hasOwnProperty(type) ? LogTypes[type] : "log";
}
}

View File

@ -1,5 +1,6 @@
import Utilities from "./utilities";
import WebpackModules, {DiscordModules} from "./webpackmodules";
import WebpackModules from "./webpackmodules";
import DiscordModules from "./discordmodules";
import BDV2 from "./bdv2";
import BdApi from "./pluginapi";
@ -17,10 +18,11 @@ import PluginManager from "./pluginmanager";
import ThemeManager from "./thememanager";
import Settings from "./settingsmanager";
import DOMManager from "./dommanager";
import Logger from "./logger";
export const React = DiscordModules.React;
export const ReactDOM = DiscordModules.ReactDOM;
export {BDV2, BdApi, Core, ContentManager, DataStore,
export {BDV2, BdApi, Core, ContentManager, DataStore, Logger,
Events, PluginManager, DOMManager, ThemeManager,
Utilities, WebpackModules, DiscordModules, Settings};

227
src/modules/patcher.js Normal file
View File

@ -0,0 +1,227 @@
/**
* Patcher that can patch other functions allowing you to run code before, after or
* instead of the original function. Can also alter arguments and return values.
*
* This is from Zerebos' library {@link https://github.com/JsSucks/BetterDiscordApp/blob/master/client/src/modules/patcher.js}
*
* @module Patcher
* @version 0.0.2
*/
import Logger from "./logger";
import DiscordModules from "./discordmodules";
import WebpackModules from "./webpackmodules";
export default class Patcher {
static get patches() { return this._patches || (this._patches = []); }
/**
* Returns all the patches done by a specific caller
* @param {string} name - Name of the patch caller
* @method
*/
static getPatchesByCaller(name) {
if (!name) return [];
const patches = [];
for (const patch of this.patches) {
for (const childPatch of patch.children) {
if (childPatch.caller === name) patches.push(childPatch);
}
}
return patches;
}
/**
* Unpatches all patches passed, or when a string is passed unpatches all
* patches done by that specific caller.
* @param {Array|string} patches - Either an array of patches to unpatch or a caller name
*/
static unpatchAll(patches) {
if (typeof patches === "string") patches = this.getPatchesByCaller(patches);
for (const patch of patches) {
patch.unpatch();
}
}
static resolveModule(module) {
if (module instanceof Function || (module instanceof Object && !(module instanceof Array))) return module;
if (typeof module === "string") return DiscordModules[module];
if (module instanceof Array) return WebpackModules.findByUniqueProperties(module);
return null;
}
static makeOverride(patch) {
return function () {
let returnValue = undefined;
if (!patch.children || !patch.children.length) return patch.originalFunction.apply(this, arguments);
for (const superPatch of patch.children.filter(c => c.type === "before")) {
try {
superPatch.callback(this, arguments);
}
catch (err) {
Logger.err("Patcher", `Could not fire before callback of ${patch.functionName} for ${superPatch.caller}`, err);
}
}
const insteads = patch.children.filter(c => c.type === "instead");
if (!insteads.length) {returnValue = patch.originalFunction.apply(this, arguments);}
else {
for (const insteadPatch of insteads) {
try {
const tempReturn = insteadPatch.callback(this, arguments, patch.originalFunction.bind(this));
if (typeof(tempReturn) !== "undefined") returnValue = tempReturn;
}
catch (err) {
Logger.err("Patcher", `Could not fire instead callback of ${patch.functionName} for ${insteadPatch.caller}`, err);
}
}
}
for (const slavePatch of patch.children.filter(c => c.type === "after")) {
try {
const tempReturn = slavePatch.callback(this, arguments, returnValue);
if (typeof(tempReturn) !== "undefined") returnValue = tempReturn;
}
catch (err) {
Logger.err("Patcher", `Could not fire after callback of ${patch.functionName} for ${slavePatch.caller}`, err);
}
}
return returnValue;
};
}
static rePatch(patch) {
patch.proxyFunction = patch.module[patch.functionName] = this.makeOverride(patch);
}
static makePatch(module, functionName, name) {
const patch = {
name,
module,
functionName,
originalFunction: module[functionName],
proxyFunction: null,
revert: () => { // Calling revert will destroy any patches added to the same module after this
patch.module[patch.functionName] = patch.originalFunction;
patch.proxyFunction = null;
patch.children = [];
},
counter: 0,
children: []
};
patch.proxyFunction = module[functionName] = this.makeOverride(patch);
return this.patches.push(patch), patch;
}
/**
* Function with no arguments and no return value that may be called to revert changes made by {@link module:Patcher}, restoring (unpatching) original method.
* @callback module:Patcher~unpatch
*/
/**
* A callback that modifies method logic. This callback is called on each call of the original method and is provided all data about original call. Any of the data can be modified if necessary, but do so wisely.
*
* The third argument for the callback will be `undefined` for `before` patches. `originalFunction` for `instead` patches and `returnValue` for `after` patches.
*
* @callback module:Patcher~patchCallback
* @param {object} thisObject - `this` in the context of the original function.
* @param {arguments} arguments - The original arguments of the original function.
* @param {(function|*)} extraValue - For `instead` patches, this is the original function from the module. For `after` patches, this is the return value of the function.
* @return {*} Makes sense only when using an `instead` or `after` patch. If something other than `undefined` is returned, the returned value replaces the value of `returnValue`. If used for `before` the return value is ignored.
*/
/**
* 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. Using this you can undo all patches with the same name using {@link module:Patcher.unpatchAll}. Use `""` if you don't care.
* @param {object} moduleToPatch - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched
* @param {module:Patcher~patchCallback} callback - Function to run before the original method
* @param {object} options - Object used to pass additional options.
* @param {string} [options.displayName] You can provide meaningful name for class/object provided in `what` param for logging purposes. By default, this function will try to determine name automatically.
* @param {boolean} [options.forcePatch=true] Set to `true` to patch even if the function doesnt exist. (Adds noop function in place).
* @return {module:Patcher~unpatch} Function with no arguments and no return value that should be called to cancel (unpatch) this patch. You should save and run it when your plugin is stopped.
*/
static before(caller, moduleToPatch, functionName, callback, options = {}) { return this.pushChildPatch(caller, moduleToPatch, functionName, callback, Object.assign(options, {type: "before"})); }
/**
* This method patches onto another function, allowing your code to run after.
* Using this, you are also able to modify the return value, using the return of your code instead.
*
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link module:Patcher.unpatchAll}. Use `""` if you don't care.
* @param {object} moduleToPatch - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched
* @param {module:Patcher~patchCallback} callback - Function to run instead of the original method
* @param {object} options - Object used to pass additional options.
* @param {string} [options.displayName] You can provide meaningful name for class/object provided in `what` param for logging purposes. By default, this function will try to determine name automatically.
* @param {boolean} [options.forcePatch=true] Set to `true` to patch even if the function doesnt exist. (Adds noop function in place).
* @return {module:Patcher~unpatch} Function with no arguments and no return value that should be called to cancel (unpatch) this patch. You should save and run it when your plugin is stopped.
*/
static after(caller, moduleToPatch, functionName, callback, options = {}) { return this.pushChildPatch(caller, moduleToPatch, functionName, callback, Object.assign(options, {type: "after"})); }
/**
* This method patches onto another function, allowing your code to run instead.
* Using this, you are also able to modify the return value, using the return of your code instead.
*
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link module:Patcher.unpatchAll}. Use `""` if you don't care.
* @param {object} moduleToPatch - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched
* @param {module:Patcher~patchCallback} callback - Function to run after the original method
* @param {object} options - Object used to pass additional options.
* @param {string} [options.displayName] You can provide meaningful name for class/object provided in `what` param for logging purposes. By default, this function will try to determine name automatically.
* @param {boolean} [options.forcePatch=true] Set to `true` to patch even if the function doesnt exist. (Adds noop function in place).
* @return {module:Patcher~unpatch} Function with no arguments and no return value that should be called to cancel (unpatch) this patch. You should save and run it when your plugin is stopped.
*/
static instead(caller, moduleToPatch, functionName, callback, options = {}) { return this.pushChildPatch(caller, moduleToPatch, functionName, callback, Object.assign(options, {type: "instead"})); }
/**
* This method patches onto another function, allowing your code to run before, instead or after the original function.
* Using this you are able to modify the incoming arguments before the original function is run as well as the return
* value before the original function actually returns.
*
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link module:Patcher.unpatchAll}. Use `""` if you don't care.
* @param {object} moduleToPatch - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched
* @param {module:Patcher~patchCallback} callback - Function to run after the original method
* @param {object} options - Object used to pass additional options.
* @param {string} [options.type=after] - Determines whether to run the function `before`, `instead`, or `after` the original.
* @param {string} [options.displayName] You can provide meaningful name for class/object provided in `what` param for logging purposes. By default, this function will try to determine name automatically.
* @param {boolean} [options.forcePatch=true] Set to `true` to patch even if the function doesnt exist. (Adds noop function in place).
* @return {module:Patcher~unpatch} Function with no arguments and no return value that should be called to cancel (unpatch) this patch. You should save and run it when your plugin is stopped.
*/
static pushChildPatch(caller, moduleToPatch, functionName, callback, options = {}) {
const {type = "after", forcePatch = true} = options;
const module = this.resolveModule(moduleToPatch);
if (!module) return null;
if (!module[functionName] && forcePatch) module[functionName] = function() {};
if (!(module[functionName] instanceof Function)) return null;
if (typeof moduleToPatch === "string") options.displayName = moduleToPatch;
const displayName = options.displayName || module.displayName || module.name || module.constructor.displayName || module.constructor.name;
const patchId = `${displayName}.${functionName}`;
const patch = this.patches.find(p => p.module == module && p.functionName == functionName) || this.makePatch(module, functionName, patchId);
if (!patch.proxyFunction) this.rePatch(patch);
const child = {
caller,
type,
id: patch.counter,
callback,
unpatch: () => {
patch.children.splice(patch.children.findIndex(cpatch => cpatch.id === child.id && cpatch.type === type), 1);
if (patch.children.length <= 0) {
const patchNum = this.patches.findIndex(p => p.module == module && p.functionName == functionName);
this.patches[patchNum].revert();
this.patches.splice(patchNum, 1);
}
}
};
patch.children.push(child);
patch.counter++;
return child.unpatch;
}
}

View File

@ -1,5 +1,6 @@
import Utilities from "./utilities";
import WebpackModules, {DiscordModules} from "./webpackmodules";
import WebpackModules from "./webpackmodules";
import DiscordModules from "./discordmodules";
import DataStore from "./datastore";
import DOMManager from "./dommanager";
import {Toasts, Modals} from "ui";

View File

@ -1,4 +1,5 @@
import {Config} from "data";
import Logger from "./logger";
import ContentManager from "./contentmanager";
import Utilities from "./utilities";
import {Toasts, Modals} from "ui";
@ -106,7 +107,7 @@ export default new class PluginManager extends ContentManager {
catch (err) {
this.state[content.id] = false;
Toasts.error(`${content.name} v${content.version} could not be started.`);
Utilities.err("Plugins", content.name + " could not be started.", err);
Logger.stacktrace(this.name, content.name + " could not be started.", err);
return new ContentError(content.name, content.filename, "start() could not be fired.", {message: err.message, stack: err.stack});
}
}
@ -123,7 +124,7 @@ export default new class PluginManager extends ContentManager {
catch (err) {
this.state[content.id] = false;
Toasts.error(`${content.name} v${content.version} could not be stopped.`);
Utilities.err("Plugins", content.name + " could not be stopped.", err);
Logger.stacktrace(this.name, content.name + " could not be stopped.", err);
return new ContentError(content.name, content.filename, "stop() could not be fired.", {message: err.message, stack: err.stack});
}
}
@ -143,7 +144,7 @@ export default new class PluginManager extends ContentManager {
if (!this.state[this.contentList[i].id]) continue;
if (typeof(plugin.onSwitch) === "function") {
try { plugin.onSwitch(); }
catch (err) { Utilities.err("Plugins", "Unable to fire onSwitch for " + this.contentList[i].name + ".", err); }
catch (err) { Logger.stacktrace(this.name, "Unable to fire onSwitch for " + this.contentList[i].name + ".", err); }
}
}
}
@ -154,7 +155,7 @@ export default new class PluginManager extends ContentManager {
if (!this.state[this.contentList[i].id]) continue;
if (typeof plugin.observer === "function") {
try { plugin.observer(mutation); }
catch (err) { Utilities.err("Plugins", "Unable to fire observer for " + this.contentList[i].name + ".", err); }
catch (err) { Logger.stacktrace(this.name, "Unable to fire observer for " + this.contentList[i].name + ".", err); }
}
}
}

View File

@ -1,7 +1,9 @@
import {SettingsConfig} from "data";
import Logger from "./logger";
import DataStore from "./datastore";
import Events from "./emitter";
import WebpackModules, {DiscordModules} from "./webpackmodules";
import WebpackModules from "./webpackmodules";
import DiscordModules from "./discordmodules";
import {SettingsPanel as SettingsRenderer} from "ui";
import Utilities from "./utilities";
@ -22,7 +24,7 @@ export default new class SettingsManager {
}
registerCollection(id, name, settings, button = null) {
if (this.collections.find(c => c.id == id)) return Utilities.err("Settings", "Already have a collection with id " + id);
if (this.collections.find(c => c.id == id)) return Logger.error("Settings", "Already have a collection with id " + id);
this.collections.push({
type: "collection",
id: id,
@ -35,12 +37,12 @@ export default new class SettingsManager {
removeCollection(id) {
const location = this.collections.findIndex(c => c.id == id);
if (!location < 0) return Utilities.err("Settings", "No collection with id " + id);
if (!location < 0) return Logger.error("Settings", "No collection with id " + id);
this.collections.splice(location, 1);
}
registerPanel(id, name, options) {
if (this.panels.find(p => p.id == id)) return Utilities.err("Settings", "Already have a panel with id " + id);
if (this.panels.find(p => p.id == id)) return Logger.error("Settings", "Already have a panel with id " + id);
const {element, onClick, order = 1} = options;
const section = {id, order, label: name, section: name};
if (onClick) section.clickListener = onClick;
@ -50,7 +52,7 @@ export default new class SettingsManager {
removePanel(id) {
const location = this.panels.findIndex(c => c.id == id);
if (!location < 0) return Utilities.err("Settings", "No collection with id " + id);
if (!location < 0) return Logger.error("Settings", "No collection with id " + id);
this.panels.splice(location, 1);
}

View File

@ -45,9 +45,9 @@ export default new class ThemeManager extends ContentManager {
/* Overrides */
getContentModification(module, content, meta) {
meta.css = content.split("\n").slice(1).join("\n");
meta.css = content;
return `module.exports = ${JSON.stringify(meta)};`;
}
}
startContent(id) {return this.addTheme(id);}
stopContent(id) {return this.removeTheme(id);}

View File

@ -1,10 +1,6 @@
/* eslint-disable no-console */
export default class Utilities {
/** Document/window width */
static get screenWidth() { return Math.max(document.documentElement.clientWidth, window.innerWidth || 0); }
/** Document/window height */
static get screenHeight() { return Math.max(document.documentElement.clientHeight, window.innerHeight || 0); }
static stripBOM(content) {
if (content.charCodeAt(0) === 0xFEFF) {
@ -50,31 +46,13 @@ export default class Utilities {
return id.replace(/^[^a-z]+|[^\w-]+/gi, "-");
}
static log(moduleName, message) {
console.log(`%c[BandagedBD]%c [${moduleName}]%c ${message}`, "color: #3a71c1; font-weight: 700;", "color: #3a71c1;", "");
}
static warn(moduleName, message) {
console.warn(`%c[BandagedBD]%c [${moduleName}]%c ${message}`, "color: #E8A400; font-weight: 700;", "color: #E8A400;", "");
}
static err(moduleName, message, error) {
console.log(`%c[BandagedBD]%c [${moduleName}]%c ${message}`, "color: red; font-weight: 700;", "color: red;", "");
if (error) {
console.groupCollapsed("%cError: " + error.message, "color: red;");
console.error(error.stack);
console.groupEnd();
}
}
static escape(s) {
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
}
static testJSON(data) {
try {
JSON.parse(data);
return true;
return JSON.parse(data);
}
catch (err) {
return false;
@ -184,42 +162,4 @@ export default class Utilities {
return proxy;
}
/**
* Builds a classname string from any number of arguments. This includes arrays and objects.
* When given an array all values from the array are added to the list.
* When given an object they keys are added as the classnames if the value is truthy.
* Copyright (c) 2018 Jed Watson https://github.com/JedWatson/classnames MIT License
* @param {...Any} argument - anything that should be used to add classnames.
*/
static className() {
const classes = [];
const hasOwn = {}.hasOwnProperty;
for (let i = 0; i < arguments.length; i++) {
const arg = arguments[i];
if (!arg) continue;
const argType = typeof arg;
if (argType === "string" || argType === "number") {
classes.push(arg);
}
else if (Array.isArray(arg) && arg.length) {
const inner = this.classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
}
else if (argType === "object") {
for (const key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(" ");
}
}

View File

@ -4,146 +4,146 @@
* @version 0.0.2
*/
import Utilities from "./utilities";
import DiscordModules from "./discordmodules";
const DiscordModules = Utilities.memoizeObject({
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
get Flux() {return WebpackModules.getByProps("connectStores");},
get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
// const DiscordModules = Utilities.memoizeObject({
// get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
// get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
// get Flux() {return WebpackModules.getByProps("connectStores");},
// get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
/* Guild Info, Stores, and Utilities */
get GuildStore() {return WebpackModules.getByProps("getGuild");},
get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
// /* Guild Info, Stores, and Utilities */
// get GuildStore() {return WebpackModules.getByProps("getGuild");},
// get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
// get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
// get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
// get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
// get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
// get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
// get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
// get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
// get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
// get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
/* Channel Store & Actions */
get ChannelStore() {return WebpackModules.getByProps("getChannels", "getDMFromUserId");},
get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
// /* Channel Store & Actions */
// get ChannelStore() {return WebpackModules.getByProps("getChannels", "getDMFromUserId");},
// get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
// get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
// get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
// get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
/* Current User Info, State and Settings */
get UserInfoStore() {return WebpackModules.getByProps("getToken");},
get UserSettingsStore() {return WebpackModules.getByProps("guildPositions");},
get AccountManager() {return WebpackModules.getByProps("register", "login");},
get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
get MentionStore() {return WebpackModules.getByProps("getMentions");},
// /* Current User Info, State and Settings */
// get UserInfoStore() {return WebpackModules.getByProps("getToken");},
// get UserSettingsStore() {return WebpackModules.getByProps("guildPositions");},
// get AccountManager() {return WebpackModules.getByProps("register", "login");},
// get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
// get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
// get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
// get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
// get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
// get MentionStore() {return WebpackModules.getByProps("getMentions");},
/* User Stores and Utils */
get UserStore() {return WebpackModules.getByProps("getCurrentUser");},
get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
get UserNameResolver() {return WebpackModules.getByProps("getName");},
get UserNoteStore() {return WebpackModules.getByProps("getNote");},
get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
// /* User Stores and Utils */
// get UserStore() {return WebpackModules.getByProps("getCurrentUser");},
// get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
// get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
// get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
// get UserNameResolver() {return WebpackModules.getByProps("getName");},
// get UserNoteStore() {return WebpackModules.getByProps("getNote");},
// get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
/* Emoji Store and Utils */
get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
// /* Emoji Store and Utils */
// get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
// get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
// get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
/* Invite Store and Utils */
get InviteStore() {return WebpackModules.getByProps("getInvites");},
get InviteResolver() {return WebpackModules.getByProps("findInvite");},
get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
// /* Invite Store and Utils */
// get InviteStore() {return WebpackModules.getByProps("getInvites");},
// get InviteResolver() {return WebpackModules.getByProps("findInvite");},
// get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
/* Discord Objects & Utils */
get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
get PermissionUtils() {return WebpackModules.getByProps("getHighestRole");},
get ColorConverter() {return WebpackModules.getByProps("hex2int");},
get ColorShader() {return WebpackModules.getByProps("darken");},
get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
get ClassResolver() {return WebpackModules.getByProps("getClass");},
get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
get IconNames() {return WebpackModules.getByProps("IconNames");},
get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
// /* Discord Objects & Utils */
// get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
// get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
// get PermissionUtils() {return WebpackModules.getByProps("getHighestRole");},
// get ColorConverter() {return WebpackModules.getByProps("hex2int");},
// get ColorShader() {return WebpackModules.getByProps("darken");},
// get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
// get ClassResolver() {return WebpackModules.getByProps("getClass");},
// get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
// get IconNames() {return WebpackModules.getByProps("IconNames");},
// get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
/* Discord Messages */
get MessageStore() {return WebpackModules.getByProps("getMessages");},
get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
get MessageQueue() {return WebpackModules.getByProps("enqueue");},
get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
// /* Discord Messages */
// get MessageStore() {return WebpackModules.getByProps("getMessages");},
// get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
// get MessageQueue() {return WebpackModules.getByProps("enqueue");},
// get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
/* Text Processing */
get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
// /* Text Processing */
// get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
// get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
/* Experiments */
get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
// /* Experiments */
// get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
// get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
// get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
/* Images, Avatars and Utils */
get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
// /* Images, Avatars and Utils */
// get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
// get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
// get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
/* Window, DOM, HTML */
get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
// /* Window, DOM, HTML */
// get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
// get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
// get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
/* Locale/Location and Time */
get LocaleManager() {return WebpackModules.getByProps("setLocale");},
get Moment() {return WebpackModules.getByProps("parseZone");},
get LocationManager() {return WebpackModules.getByProps("createLocation");},
get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
get TimeFormatter() {return WebpackModules.getByProps("dateFormat");},
// /* Locale/Location and Time */
// get LocaleManager() {return WebpackModules.getByProps("setLocale");},
// get Moment() {return WebpackModules.getByProps("parseZone");},
// get LocationManager() {return WebpackModules.getByProps("createLocation");},
// get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
// get TimeFormatter() {return WebpackModules.getByProps("dateFormat");},
/* Strings and Utils */
get Strings() {return WebpackModules.getByProps("Messages").Messages;},
get StringFormats() {return WebpackModules.getByProps("a", "z");},
get StringUtils() {return WebpackModules.getByProps("toASCII");},
// /* Strings and Utils */
// get Strings() {return WebpackModules.getByProps("Messages").Messages;},
// get StringFormats() {return WebpackModules.getByProps("a", "z");},
// get StringUtils() {return WebpackModules.getByProps("toASCII");},
/* URLs and Utils */
get URLParser() {return WebpackModules.getByProps("Url", "parse");},
get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
// /* URLs and Utils */
// get URLParser() {return WebpackModules.getByProps("Url", "parse");},
// get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
/* Drag & Drop */
get DNDActions() {return WebpackModules.getByProps("beginDrag");},
get DNDSources() {return WebpackModules.getByProps("addTarget");},
get DNDObjects() {return WebpackModules.getByProps("DragSource");},
// /* Drag & Drop */
// get DNDActions() {return WebpackModules.getByProps("beginDrag");},
// get DNDSources() {return WebpackModules.getByProps("addTarget");},
// get DNDObjects() {return WebpackModules.getByProps("DragSource");},
/* Media Stuff (Audio/Video) */
get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
get SoundModule() {return WebpackModules.getByProps("playSound");},
// /* Media Stuff (Audio/Video) */
// get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
// get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
// get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
// get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
// get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
// get SoundModule() {return WebpackModules.getByProps("playSound");},
/* Electron & Other Internals with Utils*/
get ElectronModule() {return WebpackModules.getByProps("setBadge");},
get Dispatcher() {return WebpackModules.getByProps("dirtyDispatch");},
get PathUtils() {return WebpackModules.getByProps("hasBasename");},
get NotificationModule() {return WebpackModules.getByProps("showNotification");},
get RouterModule() {return WebpackModules.getByProps("Router");},
get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
get Buffers() {return WebpackModules.getByProps("Buffer", "kMaxLength");},
get DeviceStore() {return WebpackModules.getByProps("getDevices");},
get SoftwareInfo() {return WebpackModules.getByProps("os");},
get CurrentContext() {return WebpackModules.getByProps("setTagsContext");}
});
// /* Electron & Other Internals with Utils*/
// get ElectronModule() {return WebpackModules.getByProps("setBadge");},
// get Dispatcher() {return WebpackModules.getByProps("dirtyDispatch");},
// get PathUtils() {return WebpackModules.getByProps("hasBasename");},
// get NotificationModule() {return WebpackModules.getByProps("showNotification");},
// get RouterModule() {return WebpackModules.getByProps("Router");},
// get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
// get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
// get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
// get Buffers() {return WebpackModules.getByProps("Buffer", "kMaxLength");},
// get DeviceStore() {return WebpackModules.getByProps("getDevices");},
// get SoftwareInfo() {return WebpackModules.getByProps("os");},
// get CurrentContext() {return WebpackModules.getByProps("setTagsContext");}
// });
export {DiscordModules};
// export {DiscordModules};
/**
* Checks if a given module matches a set of parameters.

View File

@ -1,4 +1,4 @@
import Utilities from "../modules/utilities";
import Logger from "../modules/logger";
import Events from "../modules/emitter";
import Settings from "../modules/settingsmanager";
@ -67,14 +67,18 @@ export default class BuiltinModule {
async disabled() {}
log(...message) {
Utilities.log(this.name, ...message);
Logger.log(this.name, ...message);
}
warn(...message) {
Utilities.warn(this.name, ...message);
Logger.warn(this.name, ...message);
}
error(...message) {
Utilities.err(this.name, ...message);
Logger.err(this.name, ...message);
}
stacktrace(message, error) {
Logger.stacktrace(this.name, message, error);
}
}

View File

@ -10,11 +10,11 @@ class FloatingWindowContainer extends React.Component {
}
render() {
return this.state.windows.map(window =>
return this.state.windows.map(window =>
// <FloatingWindow onResize={window.onResize} close={this.close.bind(this, window.id)} title={window.title} id={window.id} height={window.height} width={window.width} center={window.center} resizable={window.resizable}>
<FloatingWindow {...window} close={this.close.bind(this, window.id)}>
{window.children}
</FloatingWindow>
</FloatingWindow>
);
}
@ -52,9 +52,10 @@ class FloatingWindowContainer extends React.Component {
const containerRef = React.createRef();
const container = <FloatingWindowContainer ref={containerRef} />;
// ReactDOM.render(container, FloatingWindowContainer.root);
const App = document.querySelector(".app-19_DXt").__reactInternalInstance$.return.return.return.return.return.return.return.return.return;
const App = document.querySelector(".app-19_DXt").__reactInternalInstance$.return.return.return.return.return.return.return.return.return.return.return;
Utilities.monkeyPatch(App.type.prototype, "render", {after: (data) => {
data.returnValue.props.children.props.children.props.children.props.children[4].props.children[1].props.children.push(container);
//returnValue.props.children.props.children.props.children.props.children[4].props.children.props.children[1].props.children
data.returnValue.props.children.props.children.props.children.props.children[4].props.children.props.children[1].props.children.push(container);
}});
App.stateNode.forceUpdate();
export default containerRef.current;

View File

@ -1,4 +1,4 @@
import {Utilities, WebpackModules, React, Settings} from "modules";
import {Logger, WebpackModules, React, Settings} from "modules";
export default class Modals {
@ -132,7 +132,7 @@ export default class Modals {
if (err.error) {
error.find("a").on("click", (e) => {
e.preventDefault();
Utilities.err("ContentManager", `Error details for ${err.name ? err.name : err.file}.`, err.error);
Logger.stacktrace("ContentError", `Error details for ${err.name ? err.name : err.file}.`, err.error);
});
}
}

View File

@ -1,5 +1,5 @@
// import {SettingsCookie, PluginCookie, Plugins} from "data";
import {React, Utilities, Settings} from "modules";
import {React, Logger, Settings} from "modules";
import CloseButton from "../icons/close";
import ReloadIcon from "../icons/reload";
@ -41,7 +41,7 @@ export default class PluginCard extends React.Component {
const eTop = element.offsetTop;
const eBottom = eTop + element.clientHeight;
return (eTop < cTop || eBottom > cBottom);
};
@ -69,7 +69,7 @@ export default class PluginCard extends React.Component {
if (this.state.settingsOpen) {
try { this.settingsPanel = content.plugin.getSettingsPanel(); }
catch (err) { Utilities.err("Plugins", "Unable to get settings panel for " + content.name + ".", err); }
catch (err) { Logger.stacktrace("Plugin Settings", "Unable to get settings panel for " + content.name + ".", err); }
const props = {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef};
if (typeof(this.settingsPanel) == "string") props.dangerouslySetInnerHTML = this.settingsPanel;