//META{"name":"PluginRepo","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/PluginRepo","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PluginRepo/PluginRepo.plugin.js"}*// class PluginRepo { getName () {return "PluginRepo";} getVersion () {return "1.7.9";} getAuthor () {return "DevilBro";} getDescription () {return "Allows you to look at all plugins from the plugin repo and download them on the fly. Repo button is in the plugins settings.";} initConstructor () { this.changelog = { "added":[["New Entries","Plugin Repo now tells you when there is a new entry, which hasn't been loaded before"]], "improved":[["New/Outdated Entries Notification","Notification for new or outdated entries can be disabled"]] }; this.patchModules = { "V2C_List":"componentDidMount" }; this.sortings = { sort: { name: "Name", author: "Author", version: "Version", description: "Description", state: "Update State", fav: "Favorites", new: "New Plugins" }, order: { asc: "Ascending", desc: "Descending" } }; this.loading = {is:false, timeout:null, amount:0}; this.cachedPlugins = []; this.grabbedPlugins = []; this.foundPlugins = []; this.loadedPlugins = {}; this.updateInterval; this.settingsContextEntryMarkup = `
Plugin Repo
`; this.pluginRepoLoadingIconMarkup = ` `; this.frameMarkup = ``; this.pluginEntryMarkup = `
  • v by
  • `; this.pluginRepoModalMarkup = `

    Plugin Repository

    Plugins
    Settings
    Sort by:
    ${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}
    Order:
    ${this.sortings.order[Object.keys(this.sortings.order)[0]]}

      To expierence PluginRepo in the best way. I would recommend you to enable BD intern reload function, that way all downloaded files are loaded into Discord without the need to reload.

      Hide updated Plugins.

      Hide outdated Plugins.

      Hide downloadable Plugins.

      Start Plugin after Download (Automatic Loading needed)

      `; this.sortPopoutMarkup = `
      ${Object.keys(this.sortings.sort).map((key, i) => `
      ${this.sortings.sort[key]}
      `).join("")}
      `; this.orderPopoutMarkup = `
      ${Object.keys(this.sortings.order).map((key, i) => `
      ${this.sortings.order[key]}
      `).join("")}
      `; this.defaults = { settings: { notifyOutdated: {value:true, description:"Notifies you when one of your Plugins is outdated."}, notifyNewentries: {value:true, description:"Notifies you when there are new entries in the Repo."} } }; this.css = ` ${BDFDB.dotCN.app} > .repo-loadingwrapper { position: absolute; bottom: 0; right: 0; z-index: 1000; animation: repo-loadingwrapper-fade 3s infinite ease; } @keyframes repo-loadingwrapper-fade { from {opacity: 0.1;} 50% {opacity: 0.9;} to {opacity: 0.1;} } .${this.name}-modal.Repo-modal ${BDFDB.dotCN.modalinner} { min-height: 100%; min-width: 800px; width: 50%; } .${this.name}-modal .pluginEntry ${BDFDB.dotCN._repocontrols} > * { margin-right: 5px !important; } .${this.name}-modal .pluginEntry svg[fill="currentColor"], .${this.name}-modal .pluginEntry ${BDFDB.dotCN.giffavoritebutton} { cursor: pointer; } .${this.name}-modal .pluginEntry svg[fill="currentColor"], .${this.name}-modal .pluginEntry ${BDFDB.dotCN.giffavoritebutton + BDFDB.notCN.giffavoriteselected} { color: #72767d !important; } ${BDFDB.dotCN.themedark} .${this.name}-modal .pluginEntry svg[fill="currentColor"], ${BDFDB.dotCN.themedark} .${this.name}-modal .pluginEntry ${BDFDB.dotCN.giffavoritebutton + BDFDB.notCN.giffavoriteselected} { color: #dcddde !important; } .${this.name}-modal .pluginEntry.downloadable .trashIcon { opacity: 0 !important; pointer-events: none !important; }`; } getSettingsPanel () { if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return; var settings = BDFDB.getAllData(this, "settings"); var settingshtml = `
      ${this.name}
      `; for (let key in settings) { settingshtml += `

      ${this.defaults.settings[key].description}

      `; } settingshtml += `

      Add Plugin:

      `; settingshtml += `

      Your additional Plugin List:

      `; var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; for (let url of ownlist) { settingshtml += `
      ${url}
      `; } settingshtml += `
      `; settingshtml += `

      Force all Plugins to be fetched again.

      `; settingshtml += `

      Remove all added Plugins from your own list.

      `; settingshtml += `
      `; let settingspanel = BDFDB.htmlToElement(settingshtml); BDFDB.initElements(settingspanel, this); BDFDB.addEventListener(this, settingspanel, "click", ".btn-addplugin", () => {this.addPluginToOwnList(settingspanel);}); BDFDB.addEventListener(this, settingspanel, "click", "#input-pluginurl", e => {if (e.which == 13) this.addPluginToOwnList(settingspanel);}); BDFDB.addEventListener(this, settingspanel, "click", ".remove-plugin", e => {this.removePluginFromOwnList(e);}); BDFDB.addEventListener(this, settingspanel, "click", ".remove-all", () => {this.removeAllFromOwnList(settingspanel);}) BDFDB.addEventListener(this, settingspanel, "click", ".refresh-button", () => { this.loading = {is:false, timeout:null, amount:0}; this.loadPlugins(); }); return settingspanel; } //legacy load () {} start () { if (!global.BDFDB) global.BDFDB = {myPlugins:{}}; if (global.BDFDB && global.BDFDB.myPlugins && typeof global.BDFDB.myPlugins == "object") global.BDFDB.myPlugins[this.getName()] = this; var libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]'); if (!libraryScript || performance.now() - libraryScript.getAttribute("date") > 600000) { if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); libraryScript.setAttribute("date", performance.now()); libraryScript.addEventListener("load", () => {if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();}); document.head.appendChild(libraryScript); } else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize(); this.startTimeout = setTimeout(() => {this.initialize();}, 30000); } initialize () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { if (this.started) return; BDFDB.loadMessage(this); this.loadPlugins(); this.updateInterval = setInterval(() => {this.checkForNewPlugins();},1000*60*30); BDFDB.WebModules.forceAllUpdates(this); } else { console.error(`%c[${this.getName()}]%c`, 'color: #3a71c1; font-weight: 700;', '', 'Fatal Error: Could not load BD functions!'); } } stop () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { clearInterval(this.updateInterval); clearTimeout(this.loading.timeout); BDFDB.removeEles(".pluginrepo-notice",".bd-pluginrepobutton",".pluginrepo-loadingicon",BDFDB.dotCN.app + " > .repo-loadingwrapper:empty"); var frame = document.querySelector("iframe.discordSandbox"); if (frame) { window.removeEventListener("message", frame.messageReceived); frame.remove(); } BDFDB.unloadMessage(this); } } // begin of own functions onUserSettingsCogContextMenu (instance, menu) { let observer = new MutationObserver(changes => { changes.forEach(change => { if (change.addedNodes) change.addedNodes.forEach(node => { if (node.tagName && BDFDB.containsClass(node, BDFDB.disCN.contextmenu) && BDFDB.getReactValue(node, "return.return.return.memoizedProps.label") == "BandagedBD" && !node.querySelector(".pluginrepo-item")) { let item = node.querySelectorAll(BDFDB.dotCN.contextmenuitem); item = item[item.length-1]; var settingsContextEntry = BDFDB.htmlToElement(this.settingsContextEntryMarkup); settingsContextEntry.addEventListener("click", () => { if (!this.loading.is) BDFDB.closeContextMenu(menu); this.openPluginRepoModal(); }); item.parentElement.insertBefore(settingsContextEntry, item.nextElementSibling); var menurects = BDFDB.getRects(menu); node.style.setProperty("top", (menurects.top - BDFDB.getRects(node).height + menurects.height) + "px"); } }); }); }); observer.observe(menu, {childList: true, subtree:true}); } processV2CList (instance, wrapper) { if (!document.querySelector(".bd-pluginrepobutton") && window.PluginUpdates && window.PluginUpdates.plugins && instance._reactInternalFiber.key && instance._reactInternalFiber.key.split("-")[0] == "plugin") { var folderbutton = document.querySelector(BDFDB.dotCN._repofolderbutton); if (folderbutton) { var repoButton = BDFDB.htmlToElement(``); repoButton.addEventListener("click", () => { this.openPluginRepoModal() }); repoButton.addEventListener("mouseenter", () => { BDFDB.createTooltip("Open Plugin Repo", repoButton, {type:"top",selector:"pluginrepo-button-tooltip"}); }); folderbutton.parentElement.insertBefore(repoButton, folderbutton.nextSibling); } } }; addPluginToOwnList (settingspanel) { var pluginUrlInput = settingspanel.querySelector("#input-pluginurl"); var pluginList = settingspanel.querySelector(".plugin-list"); if (pluginUrlInput && pluginList) { var url = pluginUrlInput.value; pluginUrlInput.value = null; var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; if (!ownlist.includes(url)) { ownlist.push(url); BDFDB.saveData("ownlist", ownlist, this, "ownlist"); let entry = BDFDB.htmlToElement(`
      ${url}
      `); BDFDB.addChildEventListener(entry, "click", ".remove-plugin", e => {this.removePluginFromOwnList(e);}); pluginList.appendChild(entry); } } } removePluginFromOwnList (e) { var entry = e.currentTarget.parentElement; var url = entry.querySelector(".entryurl").textContent; entry.remove(); var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; BDFDB.removeFromArray(ownlist, url); BDFDB.saveData("ownlist", ownlist, this, "ownlist"); } removeAllFromOwnList (settingspanel) { BDFDB.openConfirmModal(this, "Are you sure you want to remove all added Plugins from your own list?", () => { BDFDB.saveData("ownlist", [], this, "ownlist"); BDFDB.removeEles(settingspanel.querySelector(BDFDB.dotCN.hovercard)); }); } openPluginRepoModal (options = {}) { if (this.loading.is) { BDFDB.showToast(`Plugins are still being fetched. Try again in some seconds.`, {type:"danger"}); return; } var pluginRepoModal = BDFDB.htmlToElement(this.pluginRepoModalMarkup); var hiddenSettings = BDFDB.loadAllData(this, "hidden"); pluginRepoModal.querySelector("#input-hideupdated").checked = hiddenSettings.updated || options.showOnlyOutdated; pluginRepoModal.querySelector("#input-hideoutdated").checked = hiddenSettings.outdated && !options.showOnlyOutdated; pluginRepoModal.querySelector("#input-hidedownloadable").checked = hiddenSettings.downloadable || options.showOnlyOutdated; if (!BDFDB.isRestartNoMoreEnabled()) pluginRepoModal.querySelector("#RNMoption").remove(); else pluginRepoModal.querySelector("#input-rnmstart").checked = BDFDB.loadData("RNMstart", this, "RNMstart"); if (options.forcedSort && this.sortings.sort[options.forcedSort]) { var sortinput = pluginRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue); orderinput.innerText = this.sortings.sort[options.forcedSort]; orderinput.setAttribute('option', options.forcedSort); } if (options.forcedOrder && this.sortings.order[options.forcedOrder]) { var orderinput = pluginRepoModal.querySelector(".order-filter " + BDFDB.dotCN.quickselectvalue); orderinput.innerText = this.sortings.order[options.forcedOrder]; orderinput.setAttribute('option', options.forcedOrder); } BDFDB.addChildEventListener(pluginRepoModal, "keyup", BDFDB.dotCN.searchbarinput, () => { clearTimeout(pluginRepoModal.searchTimeout); pluginRepoModal.searchTimeout = setTimeout(() => {this.sortEntries(pluginRepoModal);},1000); }); BDFDB.addChildEventListener(pluginRepoModal, "click", BDFDB.dotCN.searchbarclear, () => { clearTimeout(pluginRepoModal.searchTimeout); pluginRepoModal.searchTimeout = setTimeout(() => {this.sortEntries(pluginRepoModal);},1000); }); BDFDB.addChildEventListener(pluginRepoModal, "change", ".hide-checkbox", e => { pluginRepoModal.updateHidden = true; BDFDB.saveData(e.currentTarget.value, e.currentTarget.checked, this, "hidden"); }); BDFDB.addChildEventListener(pluginRepoModal, "change", "#input-rnmstart", e => { BDFDB.saveData("RNMstart", e.currentTarget.checked, this, "RNMstart"); }); BDFDB.addChildEventListener(pluginRepoModal, "click", ".sort-filter", e => { BDFDB.createSortPopout(e.currentTarget, this.sortPopoutMarkup, () => {this.sortEntries(pluginRepoModal);}); }); BDFDB.addChildEventListener(pluginRepoModal, "click", ".order-filter", e => { BDFDB.createSortPopout(e.currentTarget, this.orderPopoutMarkup, () => {this.sortEntries(pluginRepoModal);}); }); BDFDB.addChildEventListener(pluginRepoModal, "click", BDFDB.dotCN.tabbaritem + "[tab=plugins]", e => { if (!BDFDB.containsClass(e.currentTarget, BDFDB.disCN.settingsitemselected) && pluginRepoModal.updateHidden) { delete pluginRepoModal.updateHidden; this.sortEntries(pluginRepoModal); } }); let favorites = BDFDB.loadAllData(this, "favorites"); let container = pluginRepoModal.querySelector(".plugins"); pluginRepoModal.entries = {}; for (let url in this.loadedPlugins) { let plugin = this.loadedPlugins[url]; let instPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null; if (instPlugin && this.getString(instPlugin.getAuthor()).toUpperCase() == plugin.getAuthor.toUpperCase()) plugin.getState = this.getString(instPlugin.getVersion()) != plugin.getVersion ? 1 : 0; else plugin.getState = 2; let data = { url: plugin.url, search: (plugin.getName + " " + plugin.getVersion + " " + plugin.getAuthor + " " + plugin.getDescription).toUpperCase(), name: plugin.getName, version: plugin.getVersion, author: plugin.getAuthor, description: plugin.getDescription ? plugin.getDescription : "No Description found.", fav: favorites[url] ? 0 : 1, new: !this.cachedPlugins.includes(url) ? 0 : 1, state: plugin.getState }; pluginRepoModal.entries[url] = data; this.addEntry(pluginRepoModal, container, data); } this.sortEntries(pluginRepoModal); BDFDB.appendModal(pluginRepoModal); pluginRepoModal.querySelector(BDFDB.dotCN.searchbarinput).focus(); } addEntry (pluginRepoModal, container, data) { if (!pluginRepoModal || !container || !data) return; let entry = BDFDB.htmlToElement(this.pluginEntryMarkup); setEntryState(data.state); entry.setAttribute("data-name", data.name); entry.setAttribute("data-version", data.version); entry.setAttribute("data-url", data.url); entry.querySelector(BDFDB.dotCN._reponame).innerHTML = data.name; entry.querySelector(BDFDB.dotCN._repoversion).innerHTML = data.version; entry.querySelector(BDFDB.dotCN._repoauthor).innerHTML = data.author; entry.querySelector(BDFDB.dotCN._repodescription).innerHTML = data.description; if (data.new) entry.querySelector(BDFDB.dotCN._repoheadertitle).appendChild(BDFDB.htmlToElement(`NEW`)); let favbutton = entry.querySelector(BDFDB.dotCN.giffavoritebutton); BDFDB.toggleClass(favbutton, BDFDB.disCN.giffavoriteselected, data.fav == 0); favbutton.addEventListener("click", e => { let favorize = data.fav == 1; data.fav = favorize ? 0 : 1; if (favorize) BDFDB.saveData(data.url, true, this, "favorites"); else BDFDB.removeData(data.url, this, "favorites"); pluginRepoModal.entries[data.url] = data; }); favbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Favorize", favbutton, {type:"top",selector:"pluginrepo-favicon-tooltip"}); }); let gitbutton = entry.querySelector(".gitIcon"); gitbutton.addEventListener("click", e => { var giturl = null; if (data.url.indexOf("https://raw.githubusercontent.com") == 0) { var temp = data.url.replace("//raw.githubusercontent", "//github").split("/"); temp.splice(5, 0, "blob"); giturl = temp.join("/"); } else if (data.url.indexOf("https://gist.githubusercontent.com/") == 0) { giturl = data.url.replace("//gist.githubusercontent", "//gist.github").split("/raw/")[0]; } if (giturl) window.open(giturl, "_blank"); }); gitbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Go to Git", gitbutton, {type:"top",selector:"pluginrepo-giticon-tooltip"}); }); let trashbutton = entry.querySelector(".trashIcon"); trashbutton.addEventListener("click", e => { if (BDFDB.containsClass(entry, "outdated", "updated", false)) { setEntryState(2); this.deletePluginFile(data); if (!BDFDB.isRestartNoMoreEnabled()) this.stopPlugin(data); } }); trashbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Delete Pluginfile", trashbutton, {type:"top",selector:"pluginrepo-trashicon-tooltip"}); }); entry.querySelector(".btn-download").addEventListener("click", e => { setEntryState(0); this.downloadPlugin(data); if (pluginRepoModal.querySelector("#input-rnmstart").checked) setTimeout(() => {this.startPlugin(data);},3000); }); container.appendChild(entry); function setEntryState (state) { data.state = state; BDFDB.toggleClass(entry, "downloadable", state > 1); BDFDB.toggleClass(entry, "outdated", state == 1); BDFDB.toggleClass(entry, "updated", state < 1); let downloadbutton = entry.querySelector(".btn-download"); downloadbutton.innerText = state < 1 ? "Updated" : (state > 1 ? "Download" : "Outdated"); downloadbutton.style.setProperty("background-color", "rgb(" + (state < 1 ? "67,181,129" : (state > 1 ? "114,137,218" : "241,71,71")) + ")", state > 1 ? "" : "important"); pluginRepoModal.entries[data.url] = data; }; } sortEntries (pluginRepoModal) { if (!pluginRepoModal || typeof pluginRepoModal.entries != "object") return; let container = pluginRepoModal.querySelector(".plugins"); if (!container) return; let searchstring = pluginRepoModal.querySelector(BDFDB.dotCN.searchbarinput).value.replace(/[<|>]/g, "").toUpperCase(); let entries = pluginRepoModal.entries; if (pluginRepoModal.querySelector("#input-hideupdated").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state < 1 ? null : entry;}); if (pluginRepoModal.querySelector("#input-hideoutdated").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state == 1 ? null : entry;}); if (pluginRepoModal.querySelector("#input-hidedownloadable").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state > 1 ? null : entry;}); entries = BDFDB.filterObject(entries, entry => {return entry.search.indexOf(searchstring) > -1 ? entry : null;}); let sortfilter = pluginRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option"); entries = BDFDB.sortObject(entries, sortfilter == "new" && !pluginRepoModal.querySelector(".newentries-tag") ? "name" : sortfilter); if (pluginRepoModal.querySelector(".order-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option") == "desc") entries = BDFDB.reverseObject(entries); let entrypositions = Object.keys(entries); pluginRepoModal.querySelector(".pluginAmount").innerText = "PluginRepo Repository " + entrypositions.length + "/" + Object.keys(this.loadedPlugins).length + " Plugins"; for (let li of container.children) { let pos = entrypositions.indexOf(li.getAttribute("data-url")); if (pos > -1) { li.querySelectorAll(BDFDB.dotCNC._reponame + BDFDB.dotCNC._repoversion + BDFDB.dotCNC._repoauthor + BDFDB.dotCN._repodescription).forEach(ele => { if (searchstring && searchstring.length > 2 || ele.querySelector(BDFDB.dotCN.highlight)) ele.innerHTML = BDFDB.highlightText(ele.innerText, searchstring); }); li.style.setProperty("order", pos, "important"); } else li.style.removeProperty("order"); BDFDB.toggleEles(li, pos > -1); } } loadPlugins () { BDFDB.removeEles("iframe.discordSandbox",".pluginrepo-loadingicon"); var settings = BDFDB.loadAllData(this, "settings"); var getPluginInfo, createFrame, runInFrame; var frame, framerunning = false, framequeue = [], outdated = 0, newentries = 0, i = 0; var tags = ["getName", "getVersion", "getAuthor", "getDescription"]; var seps = ["\"", "\'", "\`"]; var newentriesdata = BDFDB.loadAllData(this, "newentriesdata"), ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; this.cachedPlugins = (newentriesdata.urlbase64 ? atob(newentriesdata.urlbase64).split("\n") : []).concat(ownlist); let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => { if (!error && result) { result = result.replace(/[\r\t]/g, ""); BDFDB.saveData("urlbase64", btoa(result), this, "newentriesdata"); this.loadedPlugins = {}; this.grabbedPlugins = result.split("\n"); this.foundPlugins = this.grabbedPlugins.concat(ownlist); this.loading = {is:true, timeout:setTimeout(() => { clearTimeout(this.loading.timeout); if (this.started) { if (this.loading.is && this.loading.amount < 4) setTimeout(() => {this.loadPlugins();},10000); this.loading = {is: false, timeout:null, amount:this.loading.amount}; } },1200000), amount:this.loading.amount+1}; var loadingiconwrapper = document.querySelector(BDFDB.dotCN.app + "> .repo-loadingwrapper"); if (!loadingiconwrapper) { loadingiconwrapper = BDFDB.htmlToElement(`
      `); document.querySelector(BDFDB.dotCN.app).appendChild(loadingiconwrapper); } var loadingicon = BDFDB.htmlToElement(this.pluginRepoLoadingIconMarkup); loadingicon.addEventListener("mouseenter", () => {BDFDB.createTooltip("Loading PluginRepo",loadingicon,{type:"left",delay:500});}) loadingiconwrapper.appendChild(loadingicon); createFrame().then(() => { getPluginInfo(() => { if (!this.started) { clearTimeout(this.loading.timeout); BDFDB.removeEles(frame); if (frame && frame.messageReceived) window.removeEventListener("message", frame.messageReceived); return; } var finishCounter = 0, finishInterval = setInterval(() => { if ((framequeue.length == 0 && !framerunning) || finishCounter > 300 || !this.loading.is) { clearInterval(finishInterval); BDFDB.removeEles(frame, loadingicon, ".pluginrepo-loadingicon"); if (frame && frame.messageReceived) window.removeEventListener("message", frame.messageReceived); if (!loadingiconwrapper.firstChild) BDFDB.removeEles(loadingiconwrapper); clearTimeout(this.loading.timeout); this.loading = {is:false, timeout:null, amount:this.loading.amount}; console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Finished fetching Plugins."); if (document.querySelector(".bd-pluginrepobutton")) BDFDB.showToast(`Finished fetching Plugins.`, {type:"success"}); if ((settings.notifyOutdated || settings.notifyOutdated == undefined) && outdated > 0) { var oldbarbutton = document.querySelector(".pluginrepo-outdate-notice " + BDFDB.dotCN.noticedismiss); if (oldbarbutton) oldbarbutton.click(); var bar = BDFDB.createNotificationsBar(`${outdated} of your Plugins ${outdated == 1 ? "is" : "are"} outdated. Check:`,{type:"danger",btn:"PluginRepo",selector:"pluginrepo-notice pluginrepo-outdate-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openPluginRepoModal({showOnlyOutdated:true}); bar.querySelector(BDFDB.dotCN.noticedismiss).click(); }); } if ((settings.notifyNewentries || settings.notifyNewentries == undefined) && newentries > 0) { var oldbarbutton = document.querySelector(".pluginrepo-newentries-notice " + BDFDB.dotCN.noticedismiss); if (oldbarbutton) oldbarbutton.click(); var bar = BDFDB.createNotificationsBar(`There are ${newentries} new Plugin${newentries == 1 ? "" : "s"} in the Repo. Check:`,{type:"success",btn:"PluginRepo",selector:"pluginrepo-notice pluginrepo-newentries-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openPluginRepoModal({forcedSort:"new",forcedOrder:"asc"}); bar.querySelector(BDFDB.dotCN.noticedismiss).click(); }); } if (BDFDB.myData.id == "278543574059057154") { let wrongUrls = []; for (let url of this.foundPlugins) if (url && !this.loadedPlugins[url] && !wrongUrls.includes(url)) wrongUrls.push(url); if (wrongUrls.length > 0) { var bar = BDFDB.createNotificationsBar(`PluginRepo: ${wrongUrls.length} Plugin${wrongUrls.length > 1 ? "s" : ""} could not be loaded.`, {type:"danger",btn:"List",selector:"pluginrepo-notice pluginrepo-fail-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { var toast = BDFDB.showToast(wrongUrls.join("\n"),{type:"error"}); toast.style.overflow = "hidden"; console.log(wrongUrls.length == 1 ? wrongUrls[0] : wrongUrls); }); } } } else finishCounter++; },1000); }); }); } }); getPluginInfo = (callback) => { if (i >= this.foundPlugins.length || !this.started || !this.loading.is) { callback(); return; } let url = this.foundPlugins[i]; request(url, (error, response, body) => { if (!response) { if (url && BDFDB.getAllIndexes(this.foundPlugins, url).length < 2) this.foundPlugins.push(url); } else if (body && body.indexOf("404: Not Found") != 0 && response.statusCode == 200) { let plugin = {}; let bodycopy = body; if (body.length / body.split("\n").length > 1000) { /* code is minified -> add newlines */ bodycopy = body.replace(new RegExp("}", "g"), "}\n"); } let configreg = /(module\.exports|config)\s*=\s*\{\n*\r*\t*["'`]*info["'`]*\s*:\s*/i.exec(bodycopy); if (url != "https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PluginRepo/PluginRepo.plugin.js" && configreg) { try { let config = JSON.parse('{"info":' + bodycopy.substring(configreg.index).split(configreg[0])[1].split("};")[0] + '}'); plugin.getName = config.info.name.charAt(0).toUpperCase() + config.info.name.slice(1); plugin.getDescription = config.info.description.charAt(0).toUpperCase() + config.info.description.slice(1); plugin.getVersion = config.info.version; plugin.getAuthor = ""; if (typeof config.info.author == "string") plugin.getAuthor = config.info.author.charAt(0).toUpperCase() + config.info.author.slice(1); else if (typeof config.info.authors == "string") plugin.getAuthor = config.info.authors.charAt(0).toUpperCase() + config.info.authors.slice(1); else if (Array.isArray(config.info.authors)) for (let author of config.info.authors) { plugin.getAuthor += (plugin.getAuthor + (plugin.getAuthor ? ", " : "") + (typeof author == "string" ? author : author.name)); } } catch (err) {} } else { for (let tag of tags) { let result = new RegExp(tag + "[\\s|\\t|\\n|\\r|=|>|_|:|function|\(|\)|\{|return]*([\"|\'|\`]).*\\1","gi").exec(bodycopy); if (!result) result = new RegExp("get " + tag.replace("get", "").toLowerCase() + "[\\s|\\t|\\n|\\r|=|>|_|:|function|\(|\)|\{|return]*([\"|\'|\`]).*\\1","gi").exec(bodycopy); if (result) { let separator = result[1]; result = result[0].replace(new RegExp("\\\\" + separator, "g"), separator).split(separator); if (result.length > 2) { result = result.slice(1, -1).join(separator).replace(new RegExp("\\\\n", "g"), "
      ").replace(new RegExp("\\\\", "g"), ""); plugin[tag] = tag != "getVersion" ? result.charAt(0).toUpperCase() + result.slice(1) : result; } } } } let valid = true; for (let tag of tags) if (!plugin[tag] || plugin[tag].length > 10000) valid = false; if (valid) { plugin.url = url; this.loadedPlugins[url] = plugin; var instPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null; if (instPlugin && this.getString(instPlugin.getAuthor()).toUpperCase() == plugin.getAuthor.toUpperCase() && this.getString(instPlugin.getVersion()) != plugin.getVersion && PluginUpdates && PluginUpdates.plugins && !PluginUpdates.plugins[url]) outdated++; if (!this.cachedPlugins.includes(url)) newentries++; } else if (frame && frame.contentWindow) { framequeue.push({body, url}); runInFrame(); } } i++; getPluginInfo(callback); }); } createFrame = () => { var markup = this.frameMarkup; return new Promise(function(callback) { frame = BDFDB.htmlToElement(markup); frame.startTimeout = setTimeout(() => { callback(); },600000); frame.messageReceived = e => { if (typeof e.data === "object" && e.data.origin == "DiscordPreview") { switch (e.data.reason) { case "OnLoad": frame.contentWindow.postMessage({origin:"PluginRepo",reason:"OnLoad"},"*"); callback(); break; } } }; window.addEventListener("message", frame.messageReceived); document.body.appendChild(frame); }); } runInFrame = () => { if (framerunning) return; let framedata = framequeue.shift(); if (!framedata) return; framerunning = true; let {body, url} = framedata; let name = body.replace(new RegExp("\\s*\:\\s*", "g"), ":").split('"name":"'); if (name.length > 1) { name = name[1].split('"')[0]; var processResult = plugin => { if (BDFDB.isObject(plugin)) { plugin.url = url; this.loadedPlugins[url] = plugin; var instPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null; if (instPlugin && this.getString(instPlugin.getAuthor()).toUpperCase() == plugin.getAuthor.toUpperCase() && this.getString(instPlugin.getVersion()) != plugin.getVersion) outdated++; if (!this.cachedPlugins.includes(url)) newentries++; } framerunning = false; runInFrame(); }; var evalResultReceived = e => { if (typeof e.data === "object" && e.data.origin == "DiscordPreview") { switch (e.data.reason) { case "EvalResult": window.removeEventListener("message", evalResultReceived); processResult(e.data.result); break; } } }; window.addEventListener("message", evalResultReceived); frame.contentWindow.postMessage({origin:"PluginRepo",reason:"Eval",jsstring:` try { ${body} var p = new ${name}(); var data = { "getName":getString(p.getName()), "getAuthor":getString(p.getAuthor()), "getVersion":getString(p.getVersion()), "getDescription":getString(p.getDescription()) }; window.evalResult = data; } catch (err) { window.evalResult = null; }` },"*"); } } } getString (obj) { var string = ""; if (typeof obj == "string") string = obj; else if (obj && obj.props) { if (typeof obj.props.children == "string") string = obj.props.children; else if (Array.isArray(obj.props.children)) for (let c of obj.props.children) string += typeof c == "string" ? c : this.getString(c); } return string; } checkForNewPlugins () { let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => { if (response && !BDFDB.equals(result.split("\n"), this.grabbedPlugins)) { this.loading = {is:false, timeout:null, amount:0}; this.loadPlugins(); } }); } downloadPlugin (data) { let request = require("request"); request(data.url, (error, response, body) => { if (error) { BDFDB.showToast(`Unable to download Plugin "${plugin.getName}".`, {type:"danger"}); } else { let filename = data.url.split("/"); this.createPluginFile(filename[filename.length - 1], body); } }); } createPluginFile (filename, content) { let fileSystem = require("fs"); let path = require("path"); var file = path.join(BDFDB.getPluginsFolder(), filename); fileSystem.writeFile(file, content, (error) => { if (error) { BDFDB.showToast(`Unable to save Plugin "${filename}".`, {type:"danger"}); } else { BDFDB.showToast(`Successfully saved Plugin "${filename}".`, {type:"success"}); } }); } startPlugin (data) { var name = data.name; if (BDFDB.isPluginEnabled(name) == false) { bdplugins[name].plugin.start(); pluginCookie[name] = true; pluginModule.savePluginData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Started Plugin " + name + "."); } } deletePluginFile (data) { let fileSystem = require("fs"); let path = require("path"); let filename = data.url.split("/"); filename = filename[filename.length - 1]; var file = path.join(BDFDB.getPluginsFolder(), filename); fileSystem.unlink(file, (error) => { if (error) BDFDB.showToast(`Unable to delete Plugin "${filename}".`, {type:"danger"}); else BDFDB.showToast(`Successfully deleted Plugin "${filename}".`, {type:"success"}); }); } stopPlugin (data) { var name = data.name; if (BDFDB.isPluginEnabled(name) == true) { bdplugins[name].plugin.stop(); pluginCookie[name] = false; delete bdplugins[name]; pluginModule.savePluginData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Stopped Plugin " + name + "."); } } }