//META{"name":"BDFDB","authorId":"278543574059057154","invite":"Jx3TjNS","donate":"https://www.paypal.me/MircoWittrien","patreon":"https://www.patreon.com/MircoWittrien","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/0BDFDB.plugin.js"}*// var BDFDB = (_ => { const myId = "278543574059057154", myGuildId = "410787888507256842"; if (window.BDFDB && window.BDFDB.PluginUtils && typeof window.BDFDB.PluginUtils.cleanUp == "function") window.BDFDB.PluginUtils.cleanUp(window.BDFDB); const BDFDB = { name: "BDFDB", patchPriority: 0, started: true }; const InternalBDFDB = Object.assign({}, BDFDB); const Plugin = function(config) { return class Plugin { getName() {return config.name;} getAuthor() {return config.author;} getVersion() {return config.version;} getDescription() {return config.description;} load() { Object.assign(this, BDFDB.ObjectUtils.extract(config, "name", "author", "version", "description")); BDFDB.PluginUtils.load(this, config); if (typeof this.onLoad == "function") this.onLoad(); } start() { if (this.started) return; BDFDB.PluginUtils.init(this, config); if (typeof this.onStart == "function") this.onStart(); this.started = true; delete this.stopping; } stop() { if (this.stopping) return; this.stopping = true; BDFDB.TimeUtils.timeout(_ => {delete this.stopping;}); if (typeof this.onStop == "function") this.onStop(); BDFDB.PluginUtils.clear(this, config); delete this.started; } }; }; const updateTimeouts = [], plugins = []; BDFDB.PluginUtils = {}; BDFDB.PluginUtils.buildPlugin = function (config) { return [Plugin(config), Object.assign({}, BDFDB)]; }; BDFDB.PluginUtils.load = function (plugin, config) { if (!updateTimeouts.includes(config.name)) { updateTimeouts.push(config.name); let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (config.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${config.name}/${config.name}.plugin.js`); BDFDB.PluginUtils.checkUpdate(config.name, url); if (!window.PluginUpdates || typeof window.PluginUpdates !== "object") window.PluginUpdates = {plugins: {} }; window.PluginUpdates.plugins[url] = {name: config.name, raw: url, version: config.version}; if (typeof window.PluginUpdates.interval === "undefined") window.PluginUpdates.interval = BDFDB.TimeUtils.interval(_ => { BDFDB.PluginUtils.checkAllUpdates(); }, 1000*60*60*2); BDFDB.TimeUtils.timeout(_ => {BDFDB.ArrayUtils.remove(updateTimeouts, config.name, true);}, 30000); } }; BDFDB.PluginUtils.init = BDFDB.loadMessage = function (plugin, config) { BDFDB.PluginUtils.load(plugin, config); if (!plugins.includes(plugin)) plugins.push(plugin); let startMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", "v" + config.version); BDFDB.LogUtils.log(startMsg, config.name); if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${config.name} ${startMsg}`, {nopointer: true}); if (typeof plugin.initConstructor === "function") BDFDB.TimeUtils.suppress(plugin.initConstructor.bind(plugin), "Could not initiate constructor!", config.name)(); if (typeof plugin.css === "string") BDFDB.DOMUtils.appendLocalStyle(config.name, plugin.css); InternalBDFDB.patchPlugin(plugin); InternalBDFDB.addSpecialListeners(plugin); BDFDB.PluginUtils.translate(plugin); BDFDB.PluginUtils.checkChangeLog(plugin); }; BDFDB.PluginUtils.clear = BDFDB.unloadMessage = function (plugin, config) { InternalBDFDB.clearStartTimeout(plugin); let stopMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_stopped", "v" + config.version); BDFDB.LogUtils.log(stopMsg, config.name); if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${config.name} ${stopMsg}`, {nopointer: true}); let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (config.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${config.name}/${config.name}.plugin.js`); if (typeof plugin.css === "string") BDFDB.DOMUtils.removeLocalStyle(plugin.name); BDFDB.PluginUtils.cleanUp(plugin); for (let type in BDFDB.InternalData.componentPatchQueries) BDFDB.ArrayUtils.remove(BDFDB.InternalData.componentPatchQueries[type].query, plugin, true); for (let modal of document.querySelectorAll(`.${config.name}-modal, .${config.name.toLowerCase()}-modal, .${config.name}-settingsmodal, .${plugin.name.toLowerCase()}-settingsmodal`)) { let closeButton = modal.querySelector(BDFDB.dotCN.modalclose); if (closeButton) closeButton.click(); } delete BDFDB.DataUtils.cached[config.name] delete window.PluginUpdates.plugins[url]; }; BDFDB.PluginUtils.translate = function (plugin) { plugin.labels = {}; if (typeof plugin.setLabelsByLanguage === "function" || typeof plugin.changeLanguageStrings === "function") { if (LibraryModules.LanguageStore.chosenLocale) translate(); else BDFDB.TimeUtils.interval(interval => { if (LibraryModules.LanguageStore.chosenLocale) { BDFDB.TimeUtils.clear(interval); translate(); } }, 100); function translate() { let language = BDFDB.LanguageUtils.getLanguage(); if (typeof plugin.setLabelsByLanguage === "function") plugin.labels = plugin.setLabelsByLanguage(language.id); if (typeof plugin.changeLanguageStrings === "function") plugin.changeLanguageStrings(); BDFDB.LogUtils.log(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_translated", language.ownlang), plugin.name); } } }; BDFDB.PluginUtils.cleanUp = function (plugin) { return; if (!BDFDB.ObjectUtils.is(plugin)) return; if (plugin.name == "BDFDB") { plugin = BDFDB; } BDFDB.ListenerUtils.remove(plugin); BDFDB.StoreChangeUtils.remove(plugin); BDFDB.ObserverUtils.disconnect(plugin); BDFDB.ModuleUtils.unpatch(plugin); BDFDB.WindowUtils.closeAll(plugin); BDFDB.WindowUtils.removeListener(plugin); }; BDFDB.PluginUtils.checkUpdate = function (pluginName, url) { if (pluginName && url) return new Promise(callback => { LibraryRequires.request(url, (error, response, body) => { if (error) return callback(null); let newName = (body.match(/"name"\s*:\s*"([^"]+)"/) || [])[1] || pluginName; let newVersion = body.match(/['"][0-9]+\.[0-9]+\.[0-9]+['"]/i); if (!newVersion) return callback(null); if (pluginName == newName && BDFDB.NumberUtils.getVersionDifference(newVersion[0], window.PluginUpdates.plugins[url].version) > 0.2) { BDFDB.NotificationUtils.toast(`${pluginName} will be force updated, because your version is heavily outdated.`, { type: "warn", nopointer: true }); BDFDB.PluginUtils.downloadUpdate(pluginName, url); return callback(2); } else if (BDFDB.NumberUtils.compareVersions(newVersion[0], window.PluginUpdates.plugins[url].version)) { BDFDB.PluginUtils.showUpdateNotice(pluginName, url); return callback(1); } else { BDFDB.PluginUtils.removeUpdateNotice(pluginName); return callback(0); } }); }); return new Promise(_ => {callback(null);}); }; BDFDB.PluginUtils.checkAllUpdates = function () { return new Promise(callback => { let finished = 0, amount = 0; for (let url in window.PluginUpdates.plugins) { let plugin = window.PluginUpdates.plugins[url]; if (plugin) BDFDB.PluginUtils.checkUpdate(plugin.name, plugin.raw).then(state => { finished++; if (state == 1) amount++; if (finished >= Object.keys(window.PluginUpdates.plugins).length) callback(amount); }); } }); }; BDFDB.PluginUtils.showUpdateNotice = function (pluginName, url) { if (!pluginName || !url) return; let updateNotice = document.querySelector("#pluginNotice"); if (!updateNotice) { updateNotice = BDFDB.NotificationUtils.notice(`${BDFDB.LanguageUtils.LibraryStrings.update_notice_update} `, {html:true, id:"pluginNotice", type:"info", btn:!BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.automaticLoading) ? BDFDB.LanguageUtils.LanguageStrings.ERRORS_RELOAD : "", customicon:``}); updateNotice.style.setProperty("z-index", "100000", "important"); updateNotice.style.setProperty("display", "block", "important"); updateNotice.style.setProperty("visibility", "visible", "important"); updateNotice.style.setProperty("opacity", "1", "important"); let reloadButton = updateNotice.querySelector(BDFDB.dotCN.noticebutton); if (reloadButton) { BDFDB.DOMUtils.toggle(reloadButton, true); reloadButton.addEventListener("click", _ => { LibraryRequires.electron.remote.getCurrentWindow().reload(); }); reloadButton.addEventListener("mouseenter", _ => { if (window.PluginUpdates.downloaded) BDFDB.TooltipUtils.create(reloadButton, window.PluginUpdates.downloaded.join(", "), {type:"bottom", selector:"update-notice-tooltip", style: "max-width: 420px"}); }); } } if (updateNotice) { let updateNoticeList = updateNotice.querySelector("#outdatedPlugins"); if (updateNoticeList && !updateNoticeList.querySelector(`#${pluginName}-notice`)) { if (updateNoticeList.querySelector("span")) updateNoticeList.appendChild(BDFDB.DOMUtils.create(`, `)); let updateEntry = BDFDB.DOMUtils.create(`${pluginName}`); updateEntry.addEventListener("click", _ => { if (!updateEntry.wasClicked) { updateEntry.wasClicked = true; BDFDB.PluginUtils.downloadUpdate(pluginName, url); } }); updateNoticeList.appendChild(updateEntry); if (!updateNoticeList.hasTooltip) { updateNoticeList.hasTooltip = true; updateNotice.tooltip = BDFDB.TooltipUtils.create(updateNoticeList, BDFDB.LanguageUtils.LibraryStrings.update_notice_click, { type: "bottom", unhideable: true, zIndex: 100001, delay: 500, onHide: _ => {updateNoticeList.hasTooltip = false;} }); } } } }; BDFDB.PluginUtils.removeUpdateNotice = function (pluginName, updateNotice = document.querySelector("#pluginNotice")) { if (!pluginName || !updateNotice) return; let updateNoticeList = updateNotice.querySelector("#outdatedPlugins"); if (updateNoticeList) { let noticeEntry = updateNoticeList.querySelector(`#${pluginName}-notice`); if (noticeEntry) { let nextSibling = noticeEntry.nextSibling; let prevSibling = noticeEntry.prevSibling; if (nextSibling && BDFDB.DOMUtils.containsClass(nextSibling, "separator")) nextSibling.remove(); else if (prevSibling && BDFDB.DOMUtils.containsClass(prevSibling, "separator")) prevSibling.remove(); noticeEntry.remove(); } if (!updateNoticeList.querySelector("span")) { let reloadButton = updateNotice.querySelector(BDFDB.dotCN.noticebutton); if (reloadButton) { updateNotice.querySelector(".notice-message").innerText = BDFDB.LanguageUtils.LibraryStrings.update_notice_reload; BDFDB.DOMUtils.toggle(reloadButton, false); } else updateNotice.querySelector(BDFDB.dotCN.noticedismiss).click(); } } }; BDFDB.PluginUtils.downloadUpdate = function (pluginName, url) { if (pluginName && url) LibraryRequires.request(url, (error, response, body) => { if (error) { let updateNotice = document.querySelector("#pluginNotice"); if (updateNotice) BDFDB.PluginUtils.removeUpdateNotice(pluginName, updateNotice); BDFDB.LogUtils.warn("Unable to get update for " + pluginName); } else { BDFDB.InternalData.creationTime = 0; let wasEnabled = BDFDB.BDUtils.isPluginEnabled(pluginName); let newName = (body.match(/"name"\s*:\s*"([^"]+)"/) || [])[1] || pluginName; let newVersion = body.match(/['"][0-9]+\.[0-9]+\.[0-9]+['"]/i).toString().replace(/['"]/g, ""); let oldVersion = window.PluginUpdates.plugins[url].version; LibraryRequires.fs.writeFile(LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), newName + ".plugin.js"), body, _ => { if (pluginName != newName) { url = url.replace(new RegExp(pluginName, "g"), newName); LibraryRequires.fs.unlink(LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), pluginName + ".plugin.js"), _ => {}); let configPath = LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), pluginName + ".config.json"); LibraryRequires.fs.exists(configPath, exists => { if (exists) LibraryRequires.fs.rename(configPath, LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), newName + ".config.json"), _ => {}); }); BDFDB.TimeUtils.timeout(_ => {if (wasEnabled && !BDFDB.BDUtils.isPluginEnabled(newName)) BDFDB.BDUtils.enablePlugin(newName);}, 3000); } BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_updated", pluginName, "v" + oldVersion, newName, "v" + newVersion), {nopointer:true, selector:"plugin-updated-toast"}); let updateNotice = document.querySelector("#pluginNotice"); if (updateNotice) { if (updateNotice.querySelector(BDFDB.dotCN.noticebutton)) { window.PluginUpdates.plugins[url].version = newVersion; if (!window.PluginUpdates.downloaded) window.PluginUpdates.downloaded = []; if (!window.PluginUpdates.downloaded.includes(pluginName)) window.PluginUpdates.downloaded.push(pluginName); } BDFDB.PluginUtils.removeUpdateNotice(pluginName, updateNotice); } }); } }); }; BDFDB.PluginUtils.checkChangeLog = function (plugin) { if (!BDFDB.ObjectUtils.is(plugin) || !plugin.changelog) return; let changeLog = BDFDB.DataUtils.load(plugin, "changelog"); if (!changeLog.currentversion || BDFDB.NumberUtils.compareVersions(plugin.version, changeLog.currentversion)) { changeLog.currentversion = plugin.version; BDFDB.DataUtils.save(changeLog, plugin, "changelog"); BDFDB.PluginUtils.openChangeLog(plugin); } }; BDFDB.PluginUtils.openChangeLog = function (plugin) { if (!BDFDB.ObjectUtils.is(plugin) || !plugin.changelog) return; let changeLogHTML = "", headers = { added: "New Features", fixed: "Bug Fixes", improved: "Improvements", progress: "Progress" }; for (let type in plugin.changelog) { type = type.toLowerCase(); let className = BDFDB.disCN["changelog" + type]; if (className) { changeLogHTML += `