const path = require('path'); const fs = require('fs'); const Module = require('module').Module; const originalRequire = Module._extensions['.js']; const EDPlugin = require('./plugin'); module.exports = class BDManager { static async setup(currentWindow) { this.currentWindow = currentWindow; this.defineGlobals(); this.jqueryElement = document.createElement('script'); this.jqueryElement.src = `//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js`; await new Promise(resolve => { this.jqueryElement.onload = resolve; document.head.appendChild(this.jqueryElement); }); this.observer = new MutationObserver((mutations) => { for (let i = 0, mlen = mutations.length; i < mlen; i++) this.fireEvent('observer', mutations[i]); }); this.observer.observe(document, {childList: true, subtree: true}); this.currentWindow.webContents.on('did-navigate-in-page', BDManager.onSwitch); fs.readFile(path.join(process.env.injDir, 'bd.css'), (err, text) => { if (err) return console.error(err); window.EDApi.injectCSS('BDManager', text); }) Module._extensions['.js'] = this.pluginRequire(); } static destroy() { window.EDApi.clearCSS('BDManager'); this.observer.disconnect(); this.currentWindow.webContents.removeEventListener('did-navigate-in-page', BDManager.onSwitch); this.jqueryElement.remove(); Module._extensions['.js'] = originalRequire; } static onSwitch() { BDManager.fireEvent('onSwitch'); } static extractMeta(content) { const meta = content.split('\n')[0]; const rawMeta = meta.substring(meta.lastIndexOf('//META') + 6, meta.lastIndexOf('*//')); if (meta.indexOf('META') < 0) throw new Error('META was not found.'); if (!window.EDApi.testJSON(rawMeta)) throw new Error('META could not be parsed.'); const parsed = JSON.parse(rawMeta); if (!parsed.name) throw new Error('META missing name data.'); return parsed; } static pluginRequire() { return function(moduleWrap, filename) { if (!filename.endsWith('.plugin.js') || path.dirname(filename) !== path.resolve(process.env.injDir, 'plugins')) return Reflect.apply(originalRequire, this, arguments); let content = fs.readFileSync(filename, 'utf8'); if (content.charCodeAt(0) === 0xFEFF) content = content.slice(1); // Strip BOM const meta = BDManager.extractMeta(content); meta.filename = path.basename(filename); content += `\nmodule.exports = ${meta.name};`; moduleWrap._compile(content, filename); moduleWrap.exports = BDManager.convertPlugin(new moduleWrap.exports()); }; } static fireEvent(event, ...args) { const plugins = Object.values(window.ED.plugins); for (let p = 0; p < plugins.length; p++) { const plugin = plugins[p]; if (!plugin[event] || typeof plugin[event] !== 'function') continue; try { plugin[event](...args); } catch (error) { throw new Error(`Could not fire ${event} for plugin ${plugin.name}.`); } } } static convertPlugin(plugin) { const newPlugin = new EDPlugin({ name: plugin.getName(), load: function() {plugin.start();}, unload: function() {plugin.stop();}, bdplugin: plugin }); Object.defineProperties(newPlugin, { name: { enumerable: true, configurable: true, get() {return plugin.getName();} }, author: { enumerable: true, configurable: true, get() {return plugin.getAuthor();} }, description: { enumerable: true, configurable: true, get() {return plugin.getDescription();} } }); if (typeof plugin.getSettingsPanel == 'function') newPlugin.getSettingsPanel = function() {return plugin.getSettingsPanel();}; if (typeof plugin.onSwitch == 'function') newPlugin.onSwitch = function() {return plugin.onSwitch();}; if (typeof plugin.observer == 'function') newPlugin.observer = function(e) {return plugin.observer(e);}; return newPlugin; } static defineGlobals() { window.bdConfig = {dataPath: process.env.injDir}; window.bdplugins = window.bdthemes = window.pluginCookie = window.themeCookie = window.settingsCookie = {}; window.bdpluginErrors = window.bdthemeErrors = []; window.bdPluginStorage = {get: window.EDApi.getData, set: window.EDApi.setData}; window.Utils = {monkeyPatch: window.EDApi.monkeyPatch, suppressErrors: window.EDApi.suppressErrors, escapeID: window.EDApi.escapeID}; window.BDV2 = class V2 { static get WebpackModules() {return {find: window.EDApi.findModule, findAll: window.EDApi.findAllModules, findByUniqueProperties: window.EDApi.findModuleByProps, findByDisplayName: window.EDApi.findModuleByDisplayName};} static getInternalInstance(node) {return window.EDApi.getInternalInstance(node);} static get react() {return window.EDApi.React;} static get reactDom() {return window.EDApi.ReactDOM;} }; } static showSettingsModal(plugin) { const baseModalClasses = window.EDApi.findModule(m => m.modal && m.inner && !m.sizeMedium) || {modal: "modal-36zFtW", inner: "inner-2VEzy9"}; const modalClasses = window.EDApi.findModuleByProps("modal", "sizeMedium") || {modal: "backdrop-1wrmKb", sizeMedium: "sizeMedium-ctncE5", content: "content-2KoCOZ", header: "header-2nhbou", footer: "footer-30ewN8", close: "close-hhyjWJ", inner: "inner-2Z5QZX"}; const backdrop = window.EDApi.findModuleByProps("backdrop") || {backdrop: "backdrop-1wrmKb"}; const modalHTML = `