rewrite webpack with known modules
This commit is contained in:
parent
0cd70e5da3
commit
7b578dcc56
|
@ -21,7 +21,6 @@
|
|||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-loader": "^7.1.2",
|
||||
"moment": "^2.20.1",
|
||||
"jquery": "^3.2.1",
|
||||
"vue": "^2.5.13",
|
||||
"vue-loader": "^13.7.0",
|
||||
|
@ -34,4 +33,4 @@
|
|||
"build": "webpack --progress --colors",
|
||||
"watch": "webpack --progress --colors --watch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ if (window.BetterDiscord) {
|
|||
'vendor': {
|
||||
jQuery: require('jquery'),
|
||||
$: require('jquery'),
|
||||
moment: require('moment')
|
||||
moment: window.wpm.getModuleByNameSync('Moment')
|
||||
}
|
||||
};
|
||||
}
|
|
@ -9,7 +9,6 @@
|
|||
*/
|
||||
|
||||
const { Module } = require('./modulebase');
|
||||
const moment = require('moment');
|
||||
const fs = window.require('fs');
|
||||
const path = window.require('path');
|
||||
|
||||
|
@ -20,7 +19,7 @@ class Logger {
|
|||
static log(module, message, level = 'log') {
|
||||
level = this.parseLevel(level);
|
||||
console[level]('[%cBetter%cDiscord:%s] %s', 'color: #3E82E5', '', `${module}${level === 'debug' ? '|DBG' : ''}`, message);
|
||||
logs.push(`[${moment().format('DD/MM/YY hh:mm:ss')}|${module}|${level}] ${message}`);
|
||||
logs.push(`[${BetterDiscord.vendor.moment().format('DD/MM/YY hh:mm:ss')}|${module}|${level}] ${message}`);
|
||||
window.bdlogs = logs;
|
||||
}
|
||||
|
||||
|
@ -151,5 +150,49 @@ class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
class Filters {
|
||||
static byProperties(props, selector = m => m) {
|
||||
return module => {
|
||||
const component = selector(module);
|
||||
if (!component) return false;
|
||||
return props.every(property => component[property] !== undefined);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Logger, Utils, FileUtils }
|
||||
static byPrototypeFields(fields, selector = m => m) {
|
||||
return module => {
|
||||
const component = selector(module);
|
||||
if (!component) return false;
|
||||
if (!component.prototype) return false;
|
||||
for (const field of fields) {
|
||||
if (!component.prototype[field]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static byCode(search, selector = m => m) {
|
||||
return module => {
|
||||
const method = selector(module);
|
||||
if (!method) return false;
|
||||
return method.toString().search(search) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
static byDisplayName(name) {
|
||||
return module => {
|
||||
return module && module.displayName === name;
|
||||
}
|
||||
}
|
||||
|
||||
static combine(...filters) {
|
||||
return module => {
|
||||
for (const filter of filters) {
|
||||
if (!filter(module)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { Logger, Utils, FileUtils, Filters }
|
|
@ -7,85 +7,210 @@
|
|||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
const { Filters } = require('./utils');
|
||||
|
||||
const KnownModules = {
|
||||
'React': ('createElement', 'cloneElement'),
|
||||
'react-dom': ('render', 'findDOMNode')
|
||||
React: Filters.byProperties(['createElement', 'cloneElement']),
|
||||
ReactDOM: Filters.byProperties(['render', 'findDOMNode']),
|
||||
|
||||
/* Guild Info, Stores, and Utilities */
|
||||
GuildStore: Filters.byProperties(['getGuild']),
|
||||
SortedGuildStore: Filters.byProperties(['getSortedGuilds']),
|
||||
SelectedGuildStore: Filters.byProperties(['getLastSelectedGuildId']),
|
||||
GuildSync: Filters.byProperties(["getSyncedGuilds"]),
|
||||
GuildInfo: Filters.byProperties(["getAcronym"]),
|
||||
GuildChannelsStore: Filters.byProperties(['getChannels', 'getDefaultChannel']),
|
||||
GuildMemberStore: Filters.byProperties(['getMember']),
|
||||
MemberCountStore: Filters.byProperties(["getMemberCounts"]),
|
||||
GuildEmojiStore: Filters.byProperties(['getEmojis']),
|
||||
GuildActions: Filters.byProperties(['markGuildAsRead']),
|
||||
GuildPermissions: Filters.byProperties(['getGuildPermissions']),
|
||||
|
||||
/* Channel Store & Actions */
|
||||
ChannelStore: Filters.byProperties(['getChannels', 'getDMFromUserId']),
|
||||
SelectedChannelStore: Filters.byProperties(['getLastSelectedChannelId']),
|
||||
ChannelActions: Filters.byProperties(["selectChannel"]),
|
||||
|
||||
/* Current User Info, State and Settings */
|
||||
CurrentUserInfo: Filters.byProperties(["getToken"]),
|
||||
CurrentUserState: Filters.byProperties(["guildPositions"]),
|
||||
AccountManager: Filters.byProperties(['register', 'login']),
|
||||
UserSettingsUpdater: Filters.byProperties(['updateRemoteSettings']),
|
||||
OnlineWatcher: Filters.byProperties(['isOnline']),
|
||||
CurrentUserIdle: Filters.byProperties(['getIdleTime']),
|
||||
RelationshipStore: Filters.byProperties(['isBlocked']),
|
||||
MentionStore: Filters.byProperties(["getMentions"]),
|
||||
|
||||
/* User Stores and Utils */
|
||||
UserStore: Filters.byProperties(['getCurrentUser']),
|
||||
UserStatusStore: Filters.byProperties(['getStatuses']),
|
||||
UserTypingStore: Filters.byProperties(['isTyping']),
|
||||
UserActivityStore: Filters.byProperties(['getActivity']),
|
||||
UserNameResolver: Filters.byProperties(['getName']),
|
||||
|
||||
|
||||
/* Emoji Store and Utils */
|
||||
EmojiInfo: Filters.byProperties(['isEmojiDisabled']),
|
||||
EmojiUtils: Filters.byProperties(['diversitySurrogate']),
|
||||
EmojiStore: Filters.byProperties(['getByCategory', 'EMOJI_NAME_RE']),
|
||||
|
||||
/* Invite Store and Utils */
|
||||
InviteStore: Filters.byProperties(["getInvites"]),
|
||||
InviteResolver: Filters.byProperties(['findInvite']),
|
||||
InviteActions: Filters.byProperties(['acceptInvite']),
|
||||
|
||||
|
||||
/* Discord Objects & Utils */
|
||||
DiscordConstants: Filters.byProperties(["Permissions", "ActivityTypes", "StatusTypes"]),
|
||||
Permissions: Filters.byProperties(['getHighestRole']),
|
||||
ColorConverter: Filters.byProperties(['hex2int']),
|
||||
ColorShader: Filters.byProperties(['darken']),
|
||||
ClassResolver: Filters.byProperties(["getClass"]),
|
||||
ButtonData: Filters.byProperties(["ButtonSizes"]),
|
||||
IconNames: Filters.byProperties(["IconNames"]),
|
||||
|
||||
/* Discord Messages */
|
||||
HistoryUtils: Filters.byProperties(['transitionTo', 'replaceWith', 'getHistory']),
|
||||
MessageActions: Filters.byProperties(['jumpToMessage', '_sendMessage']),
|
||||
MessageQueue: Filters.byProperties(['enqueue']),
|
||||
MessageParser: Filters.byProperties(['createMessage', 'parse', 'unparse']),
|
||||
|
||||
/* In-Game Overlay */
|
||||
OverlayUserPopoutSettings: Filters.byProperties(['openUserPopout']),
|
||||
OverlayUserPopoutInfo: Filters.byProperties(['getOpenedUserPopout']),
|
||||
|
||||
/* Experiments */
|
||||
ExperimentStore: Filters.byProperties(['getExperimentOverrides']),
|
||||
ExperimentsManager: Filters.byProperties(['isDeveloper']),
|
||||
CurrentExperiment: Filters.byProperties(['getExperimentId']),
|
||||
|
||||
|
||||
/* Images, Avatars and Utils */
|
||||
ImageResolver: Filters.byProperties(["getUserAvatarURL"]),
|
||||
ImageUtils: Filters.byProperties(['getSizedImageSrc']),
|
||||
AvatarDefaults: Filters.byProperties(["getUserAvatarURL", "DEFAULT_AVATARS"]),
|
||||
|
||||
/* Drag & Drop */
|
||||
DNDActions: Filters.byProperties(["beginDrag"]),
|
||||
DNDSources: Filters.byProperties(["addTarget"]),
|
||||
DNDObjects: Filters.byProperties(["DragSource"]),
|
||||
|
||||
/* Electron & Other Internals with Utils*/
|
||||
ElectronModule: Filters.byProperties(["_getMainWindow"]),
|
||||
Dispatcher: Filters.byProperties(['dirtyDispatch']),
|
||||
PathUtils: Filters.byProperties(["hasBasename"]),
|
||||
NotificationModule: Filters.byProperties(["showNotification"]),
|
||||
RouterModule: Filters.byProperties(["Router"]),
|
||||
APIModule: Filters.byProperties(["getAPIBaseURL"]),
|
||||
AnalyticEvents: Filters.byProperties(["AnalyticEventConfigs"]),
|
||||
KeyGenerator: Filters.byCode(/"binary"/),
|
||||
Buffers: Filters.byProperties(['Buffer', 'kMaxLength']),
|
||||
DeviceStore: Filters.byProperties(['getDevices']),
|
||||
SoftwareInfo: Filters.byProperties(["os"]),
|
||||
CurrentContext: Filters.byProperties(["setTagsContext"]),
|
||||
|
||||
/* Media Stuff (Audio/Video) */
|
||||
MediaDeviceInfo: Filters.byProperties(["Codecs", "SUPPORTED_BROWSERS"]),
|
||||
MediaInfo: Filters.byProperties(["getOutputVolume"]),
|
||||
MediaEngineInfo: Filters.byProperties(['MediaEngineFeatures']),
|
||||
VoiceInfo: Filters.byProperties(["EchoCancellation"]),
|
||||
VideoStream: Filters.byProperties(["getVideoStream"]),
|
||||
SoundModule: Filters.byProperties(["playSound"]),
|
||||
|
||||
/* Window, DOM, HTML */
|
||||
WindowInfo: Filters.byProperties(['isFocused', 'windowSize']),
|
||||
TagInfo: Filters.byProperties(['VALID_TAG_NAMES']),
|
||||
DOMInfo: Filters.byProperties(['canUseDOM']),
|
||||
HTMLUtils: Filters.byProperties(['htmlFor', 'sanitizeUrl']),
|
||||
|
||||
/* Locale/Location and Time */
|
||||
LocaleManager: Filters.byProperties(['setLocale']),
|
||||
Moment: Filters.byProperties(['parseZone']),
|
||||
LocationManager: Filters.byProperties(["createLocation"]),
|
||||
Timestamps: Filters.byProperties(["fromTimestamp"]),
|
||||
|
||||
/* Strings and Utils */
|
||||
Strings: Filters.byProperties(["TEXT", "TEXTAREA_PLACEHOLDER"]),
|
||||
StringFormats: Filters.byProperties(['a', 'z']),
|
||||
StringUtils: Filters.byProperties(["toASCII"]),
|
||||
|
||||
/* URLs and Utils */
|
||||
URLParser: Filters.byProperties(['Url', 'parse']),
|
||||
ExtraURLs: Filters.byProperties(['getArticleURL']),
|
||||
|
||||
|
||||
/* DOM/React Components */
|
||||
/* ==================== */
|
||||
UserSettingsWindow: Filters.byProperties(['open', 'updateAccount']),
|
||||
LayerManager: Filters.byProperties(['popLayer', 'pushLayer']),
|
||||
|
||||
/* Modals */
|
||||
ModalStack: Filters.byProperties(['push', 'update', 'pop', 'popWithKey']),
|
||||
UserProfileModals: Filters.byProperties(['fetchMutualFriends', 'setSection']),
|
||||
ConfirmModal: Filters.byPrototypeFields(['handleCancel', 'handleSubmit', 'handleMinorConfirm']),
|
||||
|
||||
/* Popouts */
|
||||
PopoutStack: Filters.byProperties(['open', 'close', 'closeAll']),
|
||||
PopoutOpener: Filters.byProperties(['openPopout']),
|
||||
EmojiPicker: Filters.byPrototypeFields(['onHoverEmoji', 'selectEmoji']),
|
||||
|
||||
/* Context Menus */
|
||||
ContextMenuActions: Filters.byCode(/CONTEXT_MENU_CLOSE/, c => c.close),
|
||||
ContextMenuItemsGroup: Filters.byCode(/itemGroup/),
|
||||
ContextMenuItem: Filters.byCode(/\.label\b.*\.hint\b.*\.action\b/),
|
||||
|
||||
/* In-Message Links */
|
||||
ExternalLink: Filters.byCode(/\.trusted\b/)
|
||||
};
|
||||
|
||||
const Cache = {};
|
||||
|
||||
|
||||
class WebpackModules {
|
||||
|
||||
static getModuleByNameSync(name, first, fallback) {
|
||||
//TODO return not first from cache?
|
||||
/* Synchronous */
|
||||
static getModuleByNameSync(name, fallback) {
|
||||
if (Cache.hasOwnProperty(name)) return Cache[name];
|
||||
if (KnownModules.hasOwnProperty(name)) fallback = KnownModules[name];
|
||||
if (!fallback) return null;
|
||||
return Cache[name] = this.getModuleByPropsSync(fallback, first);
|
||||
return Cache[name] = this.getModuleSync(fallback, true);
|
||||
}
|
||||
|
||||
static getModuleByPropsSync(props, first) {
|
||||
static getModuleByDisplayNameSync(name) {
|
||||
return this.getModuleSync(Filters.byDisplayName(name), true);
|
||||
}
|
||||
|
||||
static getModuleByRegexSync(regex, first = true) {
|
||||
return this.getModuleSync(Filters.byCode(regex), first);
|
||||
}
|
||||
|
||||
static getModuleByPrototypesSync(prototypes, first = true) {
|
||||
return this.getModuleSync(Filters.byPrototypeFields(prototypes), first);
|
||||
}
|
||||
|
||||
static getModuleByPropsSync(props, first = true) {
|
||||
return this.getModuleSync(Filters.byProperties(props), first);
|
||||
}
|
||||
|
||||
static getModuleSync(filter, first = true) {
|
||||
const modules = this.getAllModulesSync();
|
||||
const rm = [];
|
||||
for (let index in modules) {
|
||||
if (!modules.hasOwnProperty(index)) continue;
|
||||
const module = modules[index];
|
||||
const { exports } = module;
|
||||
let foundModule = null;
|
||||
|
||||
if (!exports || typeof exports !== 'object') continue;
|
||||
if (!(props in exports)) continue;
|
||||
rm.push(module);
|
||||
if (!exports) continue;
|
||||
if (exports.__esModule && exports.default && filter(exports.default)) foundModule = exports.default;
|
||||
if (filter(exports)) foundModule = exports;
|
||||
if (!foundModule) continue;
|
||||
if (first) return foundModule;
|
||||
rm.push(foundModule);
|
||||
}
|
||||
return first ? rm[0].exports : rm;
|
||||
return rm;
|
||||
}
|
||||
|
||||
static async getModuleByName(name, first, fallback) {
|
||||
if (Cache.hasOwnProperty(name)) return Cache[name];
|
||||
if (KnownModules.hasOwnProperty(name)) fallback = KnownModules[name];
|
||||
if (!fallback) return null;
|
||||
return Cache[name] = await this.getModuleByProps(fallback, first);
|
||||
}
|
||||
|
||||
static async getModuleByProps(props, first) {
|
||||
const modules = await this.getAllModules();
|
||||
|
||||
const rm = [];
|
||||
for (let index in modules) {
|
||||
if (!modules.hasOwnProperty(index)) continue;
|
||||
const module = modules[index];
|
||||
const { exports } = module;
|
||||
|
||||
if (!exports || typeof exports !== 'object') continue;
|
||||
if (!(props in exports)) continue;
|
||||
rm.push(module);
|
||||
}
|
||||
return first ? rm[0].exports : rm;
|
||||
}
|
||||
|
||||
/*This will most likely not work for most modules*/
|
||||
/* static async getModuleByName(name) {
|
||||
const modules = await this.getAllModules();
|
||||
return new Promise((resolve, reject) => {
|
||||
for (let index in modules) {
|
||||
if (!modules.hasOwnProperty(index)) continue;
|
||||
const module = modules[index];
|
||||
const { exports } = module;
|
||||
if (!exports) continue;
|
||||
|
||||
if (typeof exports === 'object' && (name in exports || exports.name === name)) {
|
||||
resolve(module.exports);
|
||||
break;
|
||||
} else if (typeof exports === 'function' && exports.name === name) {
|
||||
resolve(module.exports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reject(null);
|
||||
});
|
||||
}*/
|
||||
|
||||
static getAllModulesSync() {
|
||||
const id = 'bd-webpackmodulessync';
|
||||
const __webpack_require__ = window['webpackJsonp'](
|
||||
|
@ -99,6 +224,49 @@ class WebpackModules {
|
|||
return __webpack_require__.c;
|
||||
}
|
||||
|
||||
/* Asynchronous */
|
||||
static async getModuleByName(name, first = true, fallback) {
|
||||
if (Cache.hasOwnProperty(name)) return Cache[name];
|
||||
if (KnownModules.hasOwnProperty(name)) fallback = KnownModules[name];
|
||||
if (!fallback) return null;
|
||||
return Cache[name] = await this.getModule(fallback, first);
|
||||
}
|
||||
|
||||
static async getModuleByDisplayNameSync(name) {
|
||||
return await this.getModule(Filters.byDisplayName(name), true);
|
||||
}
|
||||
|
||||
static async getModuleByRegexSync(regex, first = true) {
|
||||
return await this.getModule(Filters.byCode(regex), first);
|
||||
}
|
||||
|
||||
static async getModuleByPrototypes(prototypes, first = true) {
|
||||
return await this.getModule(Filters.byPrototypeFields(prototypes), first);
|
||||
}
|
||||
|
||||
static async getModuleByProps(props, first = true) {
|
||||
return await this.getModule(Filters.byProperties(props), first);
|
||||
}
|
||||
|
||||
static async getModule(filter, first = true) {
|
||||
const modules = await this.getAllModules();
|
||||
const rm = [];
|
||||
for (let index in modules) {
|
||||
if (!modules.hasOwnProperty(index)) continue;
|
||||
const module = modules[index];
|
||||
const { exports } = module;
|
||||
let foundModule = null;
|
||||
|
||||
if (!exports) continue;
|
||||
if (exports.__esModule && exports.default && filter(exports.default)) foundModule = exports.default;
|
||||
if (filter(exports)) foundModule = exports;
|
||||
if (!foundModule) continue;
|
||||
if (first) return foundModule;
|
||||
rm.push(foundModule);
|
||||
}
|
||||
return rm;
|
||||
}
|
||||
|
||||
static async getAllModules() {
|
||||
return new Promise(resolve => {
|
||||
const id = 'bd-webpackmodules';
|
||||
|
|
|
@ -22,5 +22,8 @@
|
|||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"pump": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"gulp": "gulp"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue