//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.4";} 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":[["BDContextMenu","Fixed compatibility with the newest version of BDContextMenu"]] }; this.patchModules = { "V2C_List":"componentDidMount" }; this.sortings = { sort: { name: "Name", author: "Author", version: "Version", description: "Description", state: "Update State", fav: "Favorites" }, order: { asc: "Ascending", desc: "Descending" } }; this.loading = {is:false, timeout:null, amount:0}; this.grabbedPlugins = []; this.foundPlugins = []; this.loadedPlugins = {}; this.updateInterval; this.settingsContextEntryMarkup = `
Plugin Repo
`; this.pluginRepoLoadingIconMarkup = ` `; 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.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 settingshtml = `
      ${this.name}
      `; 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("webview[webview-pluginrepo]",".pluginrepo-notice",".bd-pluginrepobutton",".pluginrepo-loadingicon",BDFDB.dotCN.app + " > .repo-loadingwrapper:empty"); 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) instance._reactInternalFiber.return.memoizedProps.closeContextMenu(); 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 (showOnlyOutdated = false) { 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 || showOnlyOutdated; pluginRepoModal.querySelector("#input-hideoutdated").checked = hiddenSettings.outdated && !showOnlyOutdated; pluginRepoModal.querySelector("#input-hidedownloadable").checked = hiddenSettings.downloadable || showOnlyOutdated; if (!BDFDB.isRestartNoMoreEnabled()) pluginRepoModal.querySelector("#RNMoption").remove(); else pluginRepoModal.querySelector("#input-rnmstart").checked = BDFDB.loadData("RNMstart", this, "settings"); 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, "settings"); }); 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 && instPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase()) plugin.getState = instPlugin.getVersion() != plugin.getVersion ? 1 : 0; else plugin.getState = 2; plugin.getFav = favorites[url] ? 0 : 1; 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: plugin.getFav, 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; 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;}); entries = BDFDB.sortObject(entries, pluginRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option")); 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("webview[webview-pluginrepo]",".pluginrepo-loadingicon"); var getPluginInfo, createWebview, runInWebview; var webview, webviewrunning = false, webviewqueue = [], outdated = 0, i = 0; var tags = ["getName", "getVersion", "getAuthor", "getDescription"]; var seps = ["\"", "\'", "\`"]; let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => { if (response) { this.loadedPlugins = {}; this.grabbedPlugins = result.split("\n"); this.foundPlugins = this.grabbedPlugins.concat(BDFDB.loadData("ownlist", this, "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); createWebview().then(() => { getPluginInfo(() => { if (!this.started) { clearTimeout(this.loading.timeout); BDFDB.removeEles(webview); return; } var finishCounter = 0, finishInterval = setInterval(() => { if ((webviewqueue.length == 0 && !webviewrunning) || finishCounter > 300 || !this.loading.is) { clearInterval(finishInterval); BDFDB.removeEles(webview, loadingicon, ".pluginrepo-loadingicon"); 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 (outdated > 0) { var bar = BDFDB.createNotificationsBar(`${outdated} of your Plugins ${outdated == 1 ? "is" : "are"} outdated. Check:`,{type:"danger",btn:"PluginRepo",selector:"pluginrepo-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openPluginRepoModal(true); 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"}); 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].replace(new RegExp("[\\r|\\n|\\t]", "g"), ""); this.foundPlugins[i] = url; 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"); } if (url != "https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PluginRepo/PluginRepo.plugin.js" && body.indexOf("const config = {") > -1 && body.indexOf("index.js") > -1 && body.indexOf("discord_id") > -1 && body.indexOf("github_raw") > -1) { let configstring = body.split("const config = {")[1].split("};")[0].replace(/[\n\r\t]/g, "").replace(/:\s|\s:/g, ":").replace(/["'`]:/g, ":").replace(/([{,])["'`]/g, "$1").split("info:{")[1].split(",github:")[0]; for (let tag of tags) { let result = tag != "getAuthor" ? new RegExp(tag.replace("get", "").toLowerCase() + ":([\"|\'|\`]).*\\1","gi").exec(configstring) : /authors:\[{name:([\"|\'|\`]).*\1/gi.exec(configstring); if (result) { var separator = result[1]; result = result[0].replace(new RegExp("\\\\" + separator, "g"), separator).split(separator); if (result.length > 2) { result = tag != "getDescription" ? result[1] : 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; } } } } else if (url.indexOf("https://raw.githubusercontent.com/samogot/") > -1) { let configstring = body.replace(/[\n\r\t]/g, "").split('module.exports = {"info": {')[1].split("};")[0].replace(/:\s|\s:/g, ":").replace(/["'`]:/g, ":").replace(/([{,])["'`]/g, "$1"); for (let tag of tags) { let result = tag != "getAuthor" ? new RegExp(tag.replace("get", "").toLowerCase() + ":([\"|\'|\`]).*\\1","gi").exec(configstring) : /authors:\[([\"|\'|\`]).*\1/gi.exec(configstring); if (result) { var separator = result[1]; result = result[0].replace(new RegExp("\\\\" + separator, "g"), separator).split(separator); if (result.length > 2) { plugin[tag] = tag != "getVersion" ? result[1].charAt(0).toUpperCase() + result[1].slice(1) : result[1]; } } } } 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 && instPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase() && instPlugin.getVersion() != plugin.getVersion) { if (PluginUpdates && PluginUpdates.plugins && !PluginUpdates.plugins[url]) outdated++; } } else { webviewqueue.push({body, url}); runInWebview(); } } i++; getPluginInfo(callback); }); } createWebview = () => { return new Promise(function(callback) { webview = document.createElement("webview"); webview.src = "https://discordapp.com/"; webview.setAttribute("webview-PluginRepo", null); webview.style.setProperty("opacity", "0", "important"); webview.style.setProperty("pointer-events", "none", "important"); webview.startTimeout = setTimeout(() => { callback(); },600000); webview.addEventListener("dom-ready", () => { clearTimeout(webview.startTimeout); callback(); }); document.body.appendChild(webview); }); } runInWebview = () => { if (webviewrunning) return; let webviewdata = webviewqueue.shift(); if (!webviewdata) return; webviewrunning = true; let {body, url} = webviewdata; let name = body.replace(new RegExp("\\s*\:\\s*", "g"), ":").split('"name":"'); if (name.length > 1) { name = name[1].split('"')[0]; webview.getWebContents().executeJavaScript(body).then(() => { webview.getWebContents().executeJavaScript(` var p = new ` + name + `(); var data = { "getName":p.getName(), "getAuthor":p.getAuthor(), "getVersion":p.getVersion(), "getDescription":p.getDescription() }; Promise.resolve(data);` ).then((plugin) => { plugin.url = url; this.loadedPlugins[url] = plugin; var instPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null; if (instPlugin && instPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase() && instPlugin.getVersion() != plugin.getVersion) outdated++; webview.getWebContents().reload(); webviewrunning = false; runInWebview(); }); }); } } } 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 + "."); } } }