//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.8.2";} 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 = { "fixed":[["Refetch","Fixed refetching occuring every x hours"]] }; 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.pluginRepoIconMarkup = ` `; 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 experience 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; } ${BDFDB.dotCN.app} > .repo-loadingwrapper > * { margin: 0 5px; } @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#BDFDBLibraryScript'); if (!libraryScript || (performance.now() - libraryScript.getAttribute("date")) > 600000) { if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("id", "BDFDBLibraryScript"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); libraryScript.setAttribute("date", performance.now()); libraryScript.addEventListener("load", () => {this.initialize();}); document.head.appendChild(libraryScript); this.libLoadTimeout = setTimeout(() => { libraryScript.remove(); require("request")("https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js", (error, response, body) => { if (body) { libraryScript = document.createElement("script"); libraryScript.setAttribute("id", "BDFDBLibraryScript"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("date", performance.now()); libraryScript.innerText = body; document.head.appendChild(libraryScript); } this.initialize(); }); }, 15000); } 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 tabbar = pluginRepoModal.querySelector(BDFDB.dotCN.tabbar); tabbar.parentElement.insertBefore(BDFDB.createSearchBar("small"), tabbar.nextElementSibling); 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 == 0) 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").filter(n => 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.pluginRepoIconMarkup); BDFDB.addClass(loadingicon, "pluginrepo-loadingicon"); loadingicon.addEventListener("mouseenter", () => {BDFDB.createTooltip(this.getLoadingTooltipText(),loadingicon,{type:"left",delay:500,style:"max-width:unset;",selector:"pluginrepo-loading-tooltip"});}) 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", customicon:this.pluginRepoIconMarkup.replace(/#7289da/gi,"#FFF").replace(/#7f8186/gi,"#B9BBBE")}); 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 ${newentries == 1 ? "is" : "are"} ${newentries} new Plugin${newentries == 1 ? "" : "s"} in the Repo. Check:`,{type:"success",btn:"PluginRepo",selector:"pluginrepo-notice pluginrepo-newentries-notice", customicon:this.pluginRepoIconMarkup.replace(/#7289da/gi,"#FFF").replace(/#7f8186/gi,"#B9BBBE")}); 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", customicon:this.pluginRepoIconMarkup.replace(/#7289da/gi,"#FFF").replace(/#7f8186/gi,"#B9BBBE")}); 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(/}/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(/\\n/g, "
      ").replace(/\\/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++; var loadingtooltip = document.querySelector(".pluginrepo-loading-tooltip"); if (loadingtooltip) { BDFDB.setInnerText(loadingtooltip.firstElementChild, this.getLoadingTooltipText()); BDFDB.updateTooltipPosition(loadingtooltip); } 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 (!document.contains(frame)) { window.removeEventListener("message", frame.messageReceived); } else 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(/\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; }` },"*"); } } } getLoadingTooltipText () { return `Loading PluginRepo - [${Object.keys(this.loadedPlugins).length}/${Object.keys(this.grabbedPlugins).length}]`; } 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 () { require("request")("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => { if (response && !BDFDB.equals(result.replace(/\t|\r/g, "").split("\n").filter(n => n), this.grabbedPlugins)) { this.loading = {is:false, timeout:null, amount:0}; this.loadPlugins(); } }); } downloadPlugin (data) { require("request")(data.url, (error, response, body) => { if (error) BDFDB.showToast(`Unable to download Plugin "${plugin.getName}".`, {type:"danger"}); else this.createPluginFile(data.url.split("/").pop(), body); }); } createPluginFile (filename, content) { require("fs").writeFile(require("path").join(BDFDB.getPluginsFolder(), filename), content, (error) => { if (error) BDFDB.showToast(`Unable to save Plugin "${filename}".`, {type:"danger"}); else BDFDB.showToast(`Successfully saved Plugin "${filename}".`, {type:"success"}); }); } startPlugin (data) { if (BDFDB.isPluginEnabled(data.name) == false) { window.bdplugins[data.name].plugin.start(); window.pluginCookie[data.name] = true; window.pluginModule.savePluginData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Started Plugin " + data.name + "."); } } deletePluginFile (data) { let filename = data.url.split("/").pop(); require("fs").unlink(require("path").join(BDFDB.getPluginsFolder(), filename), (error) => { if (error) BDFDB.showToast(`Unable to delete Plugin "${filename}".`, {type:"danger"}); else BDFDB.showToast(`Successfully deleted Plugin "${filename}".`); }); } stopPlugin (data) { if (BDFDB.isPluginEnabled(data.name) == true) { window.bdplugins[data.name].plugin.stop(); window.pluginCookie[data.name] = false; delete window.bdplugins[data.name]; window.pluginModule.savePluginData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Stopped Plugin " + data.name + "."); } } }