BetterDiscordAddons/Plugins/PluginRepo/PluginRepo.plugin.js

1061 lines
51 KiB
JavaScript
Raw Normal View History

2020-10-20 23:25:34 +02:00
/**
* @name PluginRepo
2021-03-05 13:26:41 +01:00
* @author DevilBro
2020-10-20 23:25:34 +02:00
* @authorId 278543574059057154
2023-11-04 10:33:32 +01:00
* @version 2.5.4
2021-05-03 07:49:46 +02:00
* @description Allows you to download all Plugins from BD's Website within Discord
2020-10-20 23:25:34 +02:00
* @invite Jx3TjNS
* @donate https://www.paypal.me/MircoWittrien
* @patreon https://www.patreon.com/MircoWittrien
2021-03-09 15:10:55 +01:00
* @website https://mwittrien.github.io/
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/PluginRepo/
2021-03-10 09:17:37 +01:00
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/PluginRepo.plugin.js
2020-10-20 23:25:34 +02:00
*/
2020-09-19 20:49:33 +02:00
module.exports = (_ => {
2022-09-01 14:40:11 +02:00
const changeLog = {
2023-11-04 10:33:32 +01:00
2020-09-04 11:25:48 +02:00
};
2020-11-13 19:47:44 +01:00
2022-02-05 21:14:17 +01:00
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
2022-09-01 14:55:22 +02:00
constructor (meta) {for (let key in meta) this[key] = meta[key];}
getName () {return this.name;}
getAuthor () {return this.author;}
getVersion () {return this.version;}
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
2021-02-01 17:13:13 +01:00
downloadLibrary () {
2023-11-18 18:31:04 +01:00
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
if (!r || r.status != 200) throw new Error();
else return r.text();
}).then(b => {
if (!b) throw new Error();
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.showToast("Finished downloading BDFDB Library", {type: "success"}));
}).catch(error => {
BdApi.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
2021-02-01 17:13:13 +01:00
});
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
load () {
2020-11-19 16:51:14 +01:00
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
2020-09-19 20:49:33 +02:00
if (!window.BDFDB_Global.downloadModal) {
window.BDFDB_Global.downloadModal = true;
2022-09-01 14:55:22 +02:00
BdApi.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
2020-09-19 20:49:33 +02:00
confirmText: "Download Now",
cancelText: "Cancel",
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
2020-09-20 08:15:13 +02:00
onConfirm: _ => {
delete window.BDFDB_Global.downloadModal;
2021-02-01 17:13:13 +01:00
this.downloadLibrary();
2020-09-20 08:15:13 +02:00
}
2020-09-19 20:49:33 +02:00
});
2020-09-04 11:25:48 +02:00
}
2022-09-01 14:55:22 +02:00
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
2020-10-09 21:09:35 +02:00
}
2021-01-06 12:38:36 +01:00
start () {this.load();}
stop () {}
getSettingsPanel () {
2020-11-28 23:12:09 +01:00
let template = document.createElement("template");
2022-09-01 14:55:22 +02:00
template.innerHTML = `<div style="color: var(--header-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
2021-02-01 17:13:13 +01:00
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
2020-11-28 23:12:09 +01:00
return template.content.firstElementChild;
}
2020-10-09 21:09:35 +02:00
} : (([Plugin, BDFDB]) => {
2020-09-19 20:49:33 +02:00
var _this;
2021-05-03 12:26:32 +02:00
2022-10-11 11:14:32 +02:00
var list;
2021-05-03 12:26:32 +02:00
var loading, cachedPlugins, grabbedPlugins, updateInterval;
2021-05-03 19:20:03 +02:00
var searchString, searchTimeout, forcedSort, forcedOrder, showOnlyOutdated;
2021-05-03 12:26:32 +02:00
var favorites = [];
2020-09-19 20:49:33 +02:00
const pluginStates = {
2021-05-03 12:26:32 +02:00
INSTALLED: 0,
2020-09-19 20:49:33 +02:00
OUTDATED: 1,
DOWNLOADABLE: 2
};
const buttonData = {
2021-05-03 12:26:32 +02:00
INSTALLED: {
2022-12-11 17:40:07 +01:00
backgroundColor: "var(--status-positive)",
2020-11-12 17:48:14 +01:00
icon: "CHECKMARK",
2022-02-16 15:54:37 +01:00
text: "installed"
2020-09-19 20:49:33 +02:00
},
OUTDATED: {
2022-12-11 17:40:07 +01:00
backgroundColor: "var(--status-danger)",
2020-11-12 17:48:14 +01:00
icon: "CLOSE",
2021-01-22 21:01:58 +01:00
text: "outdated"
2020-09-19 20:49:33 +02:00
},
DOWNLOADABLE: {
2020-12-22 17:41:09 +01:00
backgroundColor: "var(--bdfdb-blurple)",
2020-11-12 17:48:14 +01:00
icon: "DOWNLOAD",
2021-01-22 21:01:58 +01:00
text: "download"
2020-09-19 20:49:33 +02:00
}
};
2021-05-03 12:26:32 +02:00
const reverseSorts = [
2021-05-12 19:44:23 +02:00
"RELEASEDATE", "DOWNLOADS", "LIKES", "FAV"
2021-05-03 12:26:32 +02:00
];
2020-09-19 20:49:33 +02:00
const sortKeys = {
NAME: "Name",
2021-05-12 19:44:23 +02:00
AUTHORNAME: "Author",
2020-09-19 20:49:33 +02:00
VERSION: "Version",
DESCRIPTION: "Description",
2021-05-12 19:44:23 +02:00
RELEASEDATE: "Release Date",
2020-09-19 20:49:33 +02:00
STATE: "Update State",
2021-05-03 12:26:32 +02:00
DOWNLOADS: "Downloads",
LIKES: "Likes",
2021-05-12 19:44:23 +02:00
FAV: "Favorites"
2020-09-19 20:49:33 +02:00
};
const orderKeys = {
ASC: "ascending",
DESC: "descending"
};
2021-02-05 23:24:38 +01:00
const pluginRepoIcon = `<svg width="37" height="32" viewBox="0 0 37 32"><path fill="COLOR_1" d="m 0,0 v 32 h 8.1672381 v -9.355469 h 4.7914989 c 7.802754,0 11.77368,-5.650788 11.77368,-11.345703 C 24.732417,5.6491106 20.8074,0 12.913386,0 Z m 8.1672381,7.5488281 h 4.7461479 c 4.928055,-0.045198 4.928055,7.9534009 0,7.9082029 H 8.1672381 Z"/><path fill="COLOR_2" d="M 23.173828 0 C 26.168987 2.3031072 27.920961 5.6614952 28.433594 9.2128906 C 29.159183 10.362444 29.181906 11.885963 28.511719 13.064453 C 28.098967 17.002739 26.191156 20.761973 22.810547 23.197266 L 29.287109 32 L 37 32 L 37 28.941406 L 30.65625 21.017578 C 34.580442 19.797239 37 16.452154 37 10.53125 C 36.81748 3.0284249 31.662 0 25 0 L 23.173828 0 z M 20.34375 24.603516 C 18.404231 25.464995 16.135462 25.970703 13.521484 25.970703 L 12.085938 25.970703 L 12.085938 32 L 20.34375 32 L 20.34375 24.603516 z"/></svg>`;
2020-09-19 20:49:33 +02:00
const RepoListComponent = class PluginList extends BdApi.React.Component {
2021-01-20 16:00:29 +01:00
componentDidMount() {
2020-09-19 20:49:33 +02:00
list = this;
BDFDB.TimeUtils.timeout(_ => {
forcedSort = null;
forcedOrder = null;
showOnlyOutdated = false;
}, 5000);
}
2021-02-04 15:53:49 +01:00
componentWillUnmount() {
list = null;
}
filterPlugins() {
2021-05-03 12:26:32 +02:00
let plugins = grabbedPlugins.map(plugin => {
2022-12-07 11:31:44 +01:00
if (plugin.failed) return;
2021-05-03 16:37:43 +02:00
const installedPlugin = _this.getInstalledPlugin(plugin);
2023-05-26 12:12:06 +02:00
const state = installedPlugin ? (plugin.version && _this.compareVersions(plugin.version, _this.getString(installedPlugin.plugin && installedPlugin.plugin.version || installedPlugin.version)) ? pluginStates.OUTDATED : pluginStates.INSTALLED) : pluginStates.DOWNLOADABLE;
2021-05-07 22:22:36 +02:00
return Object.assign(plugin, {
2021-05-12 19:44:23 +02:00
search: [plugin.name, plugin.version, plugin.authorname, plugin.description, plugin.tags].flat(10).filter(n => typeof n == "string").join(" ").toUpperCase(),
2021-05-03 12:26:32 +02:00
description: plugin.description || "No Description found",
fav: favorites.includes(plugin.id) && 1,
new: state == pluginStates.DOWNLOADABLE && !cachedPlugins.includes(plugin.id) && 1,
state: state
2021-05-07 22:22:36 +02:00
});
2022-12-07 11:31:44 +01:00
}).filter(n => n);
2021-05-03 12:26:32 +02:00
if (!this.props.updated) plugins = plugins.filter(plugin => plugin.state != pluginStates.INSTALLED);
2020-09-19 20:49:33 +02:00
if (!this.props.outdated) plugins = plugins.filter(plugin => plugin.state != pluginStates.OUTDATED);
if (!this.props.downloadable) plugins = plugins.filter(plugin => plugin.state != pluginStates.DOWNLOADABLE);
2021-05-03 19:20:03 +02:00
if (searchString) {
let usedSearchString = searchString.toUpperCase();
2021-07-28 20:00:56 +02:00
let spacelessUsedSearchString = usedSearchString.replace(/\s/g, "");
plugins = plugins.filter(plugin => plugin.search.indexOf(usedSearchString) > -1 || plugin.search.indexOf(spacelessUsedSearchString) > -1);
2020-09-04 11:25:48 +02:00
}
2021-05-03 12:26:32 +02:00
2021-05-12 19:44:23 +02:00
BDFDB.ArrayUtils.keySort(plugins, this.props.sortKey.toLowerCase());
2020-09-19 20:49:33 +02:00
if (this.props.orderKey == "DESC") plugins.reverse();
2021-05-12 19:44:23 +02:00
if (reverseSorts.includes(this.props.sortKey)) plugins.reverse();
2020-09-19 20:49:33 +02:00
return plugins;
}
2021-01-20 16:00:29 +01:00
render() {
2020-09-19 20:49:33 +02:00
if (!this.props.tab) this.props.tab = "Plugins";
2021-05-03 12:26:32 +02:00
2022-10-12 11:12:24 +02:00
const entries = (!loading.is && grabbedPlugins.length ? this.filterPlugins() : []);
2020-09-19 20:49:33 +02:00
2022-10-11 11:14:32 +02:00
return BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN._repo,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCNS._repolistheader + BDFDB.disCN.settingswindowcontentcolumndefault,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
className: BDFDB.disCN.marginbottom4,
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
grow: 1,
shrink: 0,
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormTitle, {
2022-11-22 01:30:30 +01:00
tag: BDFDB.LibraryComponents.FormComponents.FormTags.H1,
2022-10-11 11:14:32 +02:00
className: BDFDB.disCN.marginreset,
2022-10-12 11:12:24 +02:00
children: `Plugin Repo — ${loading.is ? 0 : entries.length || 0}/${loading.is ? 0 : grabbedPlugins.length}`
2022-10-11 11:14:32 +02:00
})
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SearchBar, {
autoFocus: true,
query: searchString,
onChange: value => {
if (loading.is) return;
BDFDB.TimeUtils.clear(searchTimeout);
searchTimeout = BDFDB.TimeUtils.timeout(_ => {
searchString = value.replace(/[<|>]/g, "");
BDFDB.ReactUtils.forceUpdate(this);
}, 1000);
},
onClear: _ => {
if (loading.is) return;
searchString = "";
BDFDB.ReactUtils.forceUpdate(this);
}
})
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Button, {
size: BDFDB.LibraryComponents.Button.Sizes.TINY,
children: BDFDB.LanguageUtils.LibraryStrings.check_for_updates,
onClick: _ => {
if (loading.is) return;
loading = {is: false, timeout: null, amount: 0};
2023-04-15 17:03:37 +02:00
_this.loadPlugins(true);
2022-10-11 11:14:32 +02:00
}
})
]
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
className: BDFDB.disCNS.tabbarcontainer + BDFDB.disCN.tabbarcontainerbottom,
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TabBar, {
className: BDFDB.disCN.tabbar,
itemClassName: BDFDB.disCN.tabbaritem,
type: BDFDB.LibraryComponents.TabBar.Types.TOP,
selectedItem: this.props.tab,
items: [{value: "Plugins"}, {value: BDFDB.LanguageUtils.LanguageStrings.SETTINGS}],
onItemSelect: value => {
this.props.tab = value;
BDFDB.ReactUtils.forceUpdate(this);
}
})
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.QuickSelect, {
label: BDFDB.LanguageUtils.LibraryStrings.sort_by + ":",
value: {
label: sortKeys[this.props.sortKey],
value: this.props.sortKey
},
options: Object.keys(sortKeys).map(key => ({
label: sortKeys[key],
value: key
})),
onChange: key => {
this.props.sortKey = key;
BDFDB.ReactUtils.forceUpdate(this);
}
})
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.QuickSelect, {
label: BDFDB.LanguageUtils.LibraryStrings.order + ":",
value: {
label: BDFDB.LanguageUtils.LibraryStrings[orderKeys[this.props.orderKey]],
value: this.props.orderKey
},
options: Object.keys(orderKeys).map(key => ({
label: BDFDB.LanguageUtils.LibraryStrings[orderKeys[key]],
value: key
})),
onChange: key => {
this.props.orderKey = key;
BDFDB.ReactUtils.forceUpdate(this);
}
})
})
]
})
]
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Scrollers.Auto, {
className: BDFDB.disCNS._repolistscroller + BDFDB.disCN.settingswindowcontentcolumndefault,
2020-09-19 20:49:33 +02:00
children: [
2022-10-11 11:14:32 +02:00
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ModalComponents.ModalTabContent, {
tab: "Plugins",
open: this.props.tab == "Plugins",
render: false,
children: loading.is ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
direction: BDFDB.LibraryComponents.Flex.Direction.VERTICAL,
justify: BDFDB.LibraryComponents.Flex.Justify.CENTER,
style: {marginTop: "50%"},
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SpinnerComponents.Spinner, {
type: BDFDB.LibraryComponents.SpinnerComponents.Types.WANDERING_CUBES
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextElement, {
className: BDFDB.disCN.margintop20,
style: {textAlign: "center"},
children: `${BDFDB.LanguageUtils.LibraryStringsFormat("loading", "Plugin Repo")} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`
})
]
}) : BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycards,
2022-10-12 11:12:24 +02:00
children: entries.map(plugin => BDFDB.ReactUtils.createElement(RepoCardComponent, {
data: plugin
})).filter(n => n)
2022-10-11 11:14:32 +02:00
})
2020-09-19 20:49:33 +02:00
}),
2022-10-11 11:14:32 +02:00
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ModalComponents.ModalTabContent, {
tab: BDFDB.LanguageUtils.LanguageStrings.SETTINGS,
open: this.props.tab == BDFDB.LanguageUtils.LanguageStrings.SETTINGS,
render: false,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, {
title: "Show following Plugins",
children: Object.keys(_this.defaults.filters).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
type: "Switch",
plugin: _this,
keys: ["filters", key],
label: _this.defaults.filters[key].description,
value: _this.settings.filters[key],
onChange: value => {
this.props[key] = _this.settings.filters[key] = value;
BDFDB.ReactUtils.forceUpdate(this);
}
}))
}),
Object.keys(_this.defaults.general).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
type: "Switch",
plugin: _this,
keys: ["general", key],
label: _this.defaults.general[key].description,
value: _this.settings.general[key],
onChange: value => {
_this.settings.general[key] = value;
BDFDB.ReactUtils.forceUpdate(this);
}
}))
].flat(10).filter(n => n)
2020-09-19 20:49:33 +02:00
})
]
2021-05-03 12:26:32 +02:00
})
2022-10-11 11:14:32 +02:00
]
});
2020-09-19 20:49:33 +02:00
}
};
const RepoCardComponent = class PluginCard extends BdApi.React.Component {
2021-01-20 16:00:29 +01:00
render() {
2021-05-03 12:26:32 +02:00
return BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycard,
2022-10-12 11:12:24 +02:00
onMouseEnter: _ => {
this.props.hovered = true;
BDFDB.ReactUtils.forceUpdate(this);
},
2021-05-03 12:26:32 +02:00
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardheader,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardcoverwrapper,
children: [
2022-10-12 11:12:24 +02:00
this.props.data.thumbnailUrl && this.props.hovered && BDFDB.ReactUtils.createElement("img", {
2021-05-03 12:26:32 +02:00
className: BDFDB.disCN.discoverycardcover,
2021-05-03 19:20:03 +02:00
src: this.props.data.thumbnailUrl,
2021-05-03 12:26:32 +02:00
onClick: _ => {
2022-10-12 11:12:24 +02:00
const url = this.props.data.thumbnailUrl;
2021-05-03 19:20:03 +02:00
const img = document.createElement("img");
2021-05-03 12:26:32 +02:00
img.addEventListener("load", function() {
2022-10-12 11:12:24 +02:00
BDFDB.LibraryModules.ModalUtils.openModal(modalData => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ModalComponents.ModalRoot, Object.assign({
className: BDFDB.disCN.imagemodal
}, modalData, {
size: BDFDB.LibraryComponents.ModalComponents.ModalSize.DYNAMIC,
"aria-label": BDFDB.LanguageUtils.LanguageStrings.IMAGE,
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ImageModal, {
animated: false,
src: url,
original: url,
width: this.width,
height: this.height,
className: BDFDB.disCN.imagemodalimage,
shouldAnimate: true,
renderLinkComponent: props => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Anchor, props)
})
}), true));
2021-05-03 12:26:32 +02:00
});
2021-05-03 19:20:03 +02:00
img.src = url;
2021-05-03 12:26:32 +02:00
}
}),
2021-05-03 13:55:51 +02:00
this.props.data.new && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Badges.TextBadge, {
2021-05-03 12:26:32 +02:00
className: BDFDB.disCN.discoverycardcoverbadge,
style: {
borderRadius: 3,
textTransform: "uppercase",
2023-02-22 15:34:45 +01:00
background: BDFDB.DiscordConstants.Colors.YELLOW
2021-05-03 12:26:32 +02:00
},
text: BDFDB.LanguageUtils.LanguageStrings.NEW
})
]
}),
2022-10-12 11:12:24 +02:00
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardiconwrapper,
children: BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardicon,
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
nativeClass: true,
iconSVG: `<svg width="100%" height="100%" viewBox="0 0 24 24"><path fill="currentColor" d="${BDFDB.ArrayUtils.is(this.props.data.tags) && this.props.data.tags.includes("library") ? "m 7.3125,2.625 c -0.3238672,0 -0.5859375,0.2620703 -0.5859375,0.5859375 V 14.929687 c 0,0.323868 0.2620703,0.585938 0.5859375,0.585938 2.710313,0 3.840547,1.498711 4.101563,1.914062 V 3.9905599 C 10.603047,3.3127865 9.3007813,2.625 7.3125,2.625 Z M 4.96875,3.796875 c -0.3238672,0 -0.5859375,0.2620703 -0.5859375,0.5859375 V 17.273437 c 0,0.323868 0.2620703,0.585938 0.5859375,0.585938 h 5.30599 C 9.9465755,17.461602 9.0865625,16.6875 7.3125,16.6875 c -0.9692969,0 -1.7578125,-0.788516 -1.7578125,-1.757813 V 3.796875 Z m 9.375,0 c -0.662031,0 -1.266641,0.2287891 -1.757812,0.6005859 V 18.445312 c 0,-0.323281 0.262656,-0.585937 0.585937,-0.585937 h 5.859375 c 0.323868,0 0.585937,-0.26207 0.585937,-0.585938 V 4.3828125 c 0,-0.3238672 -0.262069,-0.5859375 -0.585937,-0.5859375 z M 2.5859375,4.96875 C 2.2620703,4.96875 2,5.2308203 2,5.5546875 V 19.617187 c 0,0.323868 0.2620703,0.585938 0.5859375,0.585938 H 9.171224 c 0.2420313,0.68207 0.892995,1.171875 1.656901,1.171875 h 2.34375 c 0.763906,0 1.414831,-0.489805 1.656901,-1.171875 h 6.585286 C 21.73793,20.203125 22,19.941055 22,19.617187 V 5.5546875 C 22,5.2308203 21.73793,4.96875 21.414062,4.96875 h -0.585937 v 12.304687 c 0,0.969297 -0.827578,1.757813 -1.796875,1.757813 H 13.656901 C 13.41487,19.71332 12.763907,20.203125 12,20.203125 c -0.763906,0 -1.414831,-0.489805 -1.656901,-1.171875 H 4.96875 c -0.9692968,0 -1.796875,-0.788516 -1.796875,-1.757813 V 4.96875 Z" : "m 11.470703,0.625 c -1.314284,0 -2.3808593,1.0666594 -2.3808592,2.3808594 V 4.4335938 H 5.2792969 c -1.0476168,0 -1.8945313,0.85855 -1.8945313,1.90625 v 3.6191406 h 1.4179688 c 1.41905,0 2.5722656,1.1512126 2.5722656,2.5703126 0,1.4191 -1.1532156,2.572266 -2.5722656,2.572265 H 3.375 v 3.619141 c 0,1.0477 0.8566801,1.904297 1.9042969,1.904297 h 3.6191406 v -1.427734 c 0,-1.4189 1.1532235,-2.572266 2.5722655,-2.572266 1.41905,0 2.570313,1.153366 2.570313,2.572266 V 20.625 h 3.61914 c 1.047626,0 1.90625,-0.856597 1.90625,-1.904297 v -3.810547 h 1.427735 c 1.314292,0 2.380859,-1.066559 2.380859,-2.380859 0,-1.3143 -1.066567,-2.38086 -2.380859,-2.380859 H 19.566406 V 6.3398438 c 0,-1.0477002 -0.858624,-1.90625 -1.90625,-1.90625 H 13.851562 V 3.0058594 c 0,-1.3142 -1.066568,-2.3808594 -2.380859,-2.3808594 z"}"/></svg>`
})
})
})
2021-05-03 12:26:32 +02:00
]
2020-11-12 17:48:14 +01:00
}),
2021-05-03 12:26:32 +02:00
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardinfo,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardtitle,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardname,
2021-05-03 13:55:51 +02:00
children: this.props.data.name
2021-05-03 12:26:32 +02:00
}),
2021-06-14 19:28:10 +02:00
this.props.data.latestSourceUrl &&
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
text: BDFDB.LanguageUtils.LanguageStrings.SCREENSHARE_SOURCE,
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, {
className: BDFDB.disCN.discoverycardtitlebutton,
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
nativeClass: true,
width: 16,
height: 16,
name: BDFDB.LibraryComponents.SvgIcon.Names.GITHUB
})
}),
onClick: _ => BDFDB.DiscordUtils.openLink(this.props.data.latestSourceUrl)
}),
2021-05-03 12:26:32 +02:00
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FavButton, {
2021-05-03 15:26:32 +02:00
className: BDFDB.disCN.discoverycardtitlebutton,
2021-05-03 13:55:51 +02:00
isFavorite: this.props.data.fav,
2021-05-03 12:26:32 +02:00
onClick: value => {
2021-05-03 13:55:51 +02:00
this.props.data.fav = value && 1;
if (value) favorites.push(this.props.data.id);
else BDFDB.ArrayUtils.remove(favorites, this.props.data.id, true);
2021-05-03 12:26:32 +02:00
BDFDB.DataUtils.save(BDFDB.ArrayUtils.numSort(favorites).join(" "), _this, "favorites");
}
})
]
}),
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardauthor,
2021-05-12 19:44:23 +02:00
children: `by ${this.props.data.authorname}`
2021-05-03 12:26:32 +02:00
}),
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Scrollers.Thin, {
className: BDFDB.disCN.discoverycarddescription,
2021-05-03 13:55:51 +02:00
children: this.props.data.description
2021-05-03 12:26:32 +02:00
}),
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardfooter,
children: [
2021-05-03 14:02:13 +02:00
BDFDB.ArrayUtils.is(this.props.data.tags) && this.props.data.tags.length && BDFDB.ReactUtils.createElement("div", {
2021-05-03 12:26:32 +02:00
className: BDFDB.disCN.discoverycardtags,
2021-05-03 13:55:51 +02:00
children: this.props.data.tags.map(tag => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Badges.TextBadge, {
2021-05-03 12:26:32 +02:00
className: BDFDB.disCN.discoverycardtag,
style: {background: "var(--background-accent)"},
text: tag
}))
}),
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardcontrols,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardstats,
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardstat,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
className: BDFDB.disCN.discoverycardstaticon,
2021-05-03 13:55:51 +02:00
width: 16,
height: 16,
2021-05-03 12:26:32 +02:00
name: BDFDB.LibraryComponents.SvgIcon.Names.DOWNLOAD
}),
2021-05-03 13:55:51 +02:00
this.props.data.downloads
2021-05-03 12:26:32 +02:00
]
}),
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN.discoverycardstat,
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
className: BDFDB.disCN.discoverycardstaticon,
2021-05-03 13:55:51 +02:00
width: 16,
height: 16,
2021-05-03 12:26:32 +02:00
name: BDFDB.LibraryComponents.SvgIcon.Names.HEART
}),
2021-05-03 13:55:51 +02:00
this.props.data.likes
2021-05-03 12:26:32 +02:00
]
})
]
}),
2021-05-03 13:55:51 +02:00
BDFDB.ReactUtils.createElement(RepoCardDownloadButtonComponent, {
...buttonData[(Object.entries(pluginStates).find(n => n[1] == this.props.data.state) || [])[0]],
installed: this.props.data.state == pluginStates.INSTALLED,
2021-06-15 14:06:15 +02:00
outdated: this.props.data.state == pluginStates.OUTDATED,
2021-05-03 13:55:51 +02:00
onDownload: _ => {
2022-04-29 14:52:56 +02:00
if (this.props.downloading) return;
this.props.downloading = true;
let loadingToast = BDFDB.NotificationUtils.toast(`${BDFDB.LanguageUtils.LibraryStringsFormat("loading", this.props.data.name)} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {timeout: 0, ellipsis: true});
2022-06-29 16:18:49 +02:00
let autoloadKey = this.props.data.state == pluginStates.OUTDATED ? "startUpdated" : "startDownloaded";
2023-11-04 10:33:32 +01:00
BDFDB.LibraryRequires.request(this.props.data.rawSourceUrl, (error, response, body) => {
if (error || !body) {
2022-04-29 14:52:56 +02:00
delete this.props.downloading;
loadingToast.close();
BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("download_fail", `Plugin "${this.props.data.name}"`), {type: "danger"});
}
2023-11-04 10:33:32 +01:00
else BDFDB.LibraryRequires.fs.writeFile(BDFDB.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), this.props.data.rawSourceUrl.split("/").pop()), body, error2 => {
2022-12-07 11:31:44 +01:00
delete this.props.downloading;
loadingToast.close();
if (error2) BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("save_fail", `Plugin "${this.props.data.name}"`), {type: "danger"});
else {
BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("save_success", `Plugin "${this.props.data.name}"`), {type: "success"});
if (_this.settings.general[autoloadKey]) BDFDB.TimeUtils.timeout(_ => {
if (this.props.data.state == pluginStates.INSTALLED && BDFDB.BDUtils.isPluginEnabled(this.props.data.name) == false) {
BDFDB.BDUtils.enablePlugin(this.props.data.name, false);
BDFDB.LogUtils.log(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", this.props.data.name), _this);
}
}, 3000);
this.props.data.state = pluginStates.INSTALLED;
BDFDB.ReactUtils.forceUpdate(this);
}
});
2022-04-29 14:52:56 +02:00
});
2021-05-03 13:55:51 +02:00
},
onDelete: _ => {
2022-04-29 14:52:56 +02:00
if (this.props.deleting) return;
this.props.deleting = true;
2022-10-27 14:45:51 +02:00
BDFDB.LibraryRequires.fs.unlinkSync(BDFDB.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), this.props.data.rawSourceUrl.split("/").pop()));
delete this.props.deleting;
BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("delete_success", `Plugin "${this.props.data.name}"`));
this.props.data.state = pluginStates.DOWNLOADABLE;
BDFDB.ReactUtils.forceUpdate(this);
2021-05-03 13:55:51 +02:00
}
2021-05-03 12:26:32 +02:00
})
]
})
]
2020-09-04 11:25:48 +02:00
})
2021-05-03 12:26:32 +02:00
]
2020-09-19 20:49:33 +02:00
})
]
});
}
};
2021-05-03 13:55:51 +02:00
const RepoCardDownloadButtonComponent = class PluginCardDownloadButton extends BdApi.React.Component {
render() {
2021-06-15 14:06:15 +02:00
const backgroundColor = this.props.doDelete ? buttonData.OUTDATED.backgroundColor : this.props.doUpdate ? buttonData.INSTALLED.backgroundColor : this.props.backgroundColor;
2021-05-03 13:55:51 +02:00
return BDFDB.ReactUtils.createElement("button", {
className: BDFDB.disCN.discoverycardbutton,
2021-06-15 14:06:15 +02:00
style: {backgroundColor: BDFDB.DiscordConstants.Colors[backgroundColor] || backgroundColor},
2021-05-03 13:55:51 +02:00
children: [
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
className: BDFDB.disCN.discoverycardstaticon,
width: 16,
height: 16,
2021-06-15 14:06:15 +02:00
name: this.props.doDelete ? BDFDB.LibraryComponents.SvgIcon.Names.TRASH : this.props.doUpdate ? BDFDB.LibraryComponents.SvgIcon.Names.DOWNLOAD : BDFDB.LibraryComponents.SvgIcon.Names[this.props.icon]
2021-05-03 13:55:51 +02:00
}),
2021-06-15 14:06:15 +02:00
this.props.doDelete ? BDFDB.LanguageUtils.LanguageStrings.APPLICATION_CONTEXT_MENU_UNINSTALL : this.props.doUpdate ? BDFDB.LanguageUtils.LanguageStrings.GAME_ACTION_BUTTON_UPDATE : (BDFDB.LanguageUtils.LibraryStringsCheck[this.props.text] ? BDFDB.LanguageUtils.LibraryStrings[this.props.text] : BDFDB.LanguageUtils.LanguageStrings[this.props.text])
2021-05-03 13:55:51 +02:00
],
onClick: _ => {
2021-06-15 14:06:15 +02:00
if (this.props.doDelete) typeof this.props.onDelete == "function" && this.props.onDelete();
2022-06-29 16:18:49 +02:00
else if (!this.props.installed) typeof this.props.onDownload == "function" && this.props.onDownload();
2021-05-03 13:55:51 +02:00
},
2021-06-15 14:06:15 +02:00
onMouseEnter: this.props.installed ? (_ => {
this.props.doDelete = true;
2021-05-03 13:55:51 +02:00
BDFDB.ReactUtils.forceUpdate(this);
2021-06-15 14:06:15 +02:00
}) : this.props.outdated ? (_ => {
this.props.doUpdate = true;
2021-05-03 13:55:51 +02:00
BDFDB.ReactUtils.forceUpdate(this);
2021-06-15 14:06:15 +02:00
}) : (_ => {}),
onMouseLeave: this.props.installed ? (_ => {
this.props.doDelete = false;
BDFDB.ReactUtils.forceUpdate(this);
}) : this.props.outdated ? (_ => {
this.props.doUpdate = false;
BDFDB.ReactUtils.forceUpdate(this);
}) : (_ => {})
2021-05-03 13:55:51 +02:00
});
}
};
2020-09-19 20:49:33 +02:00
2020-10-09 21:09:35 +02:00
return class PluginRepo extends Plugin {
2021-01-06 12:38:36 +01:00
onLoad () {
2020-09-19 20:49:33 +02:00
_this = this;
2020-11-19 16:51:14 +01:00
loading = {is: false, timeout: null, amount: 0};
2020-09-19 20:49:33 +02:00
cachedPlugins = [];
grabbedPlugins = [];
2021-05-03 19:20:03 +02:00
searchString = "";
2020-09-19 20:49:33 +02:00
this.defaults = {
2021-05-03 12:26:32 +02:00
general: {
2022-12-07 11:31:44 +01:00
notifyOutdated: {value: true, autoload: false, description: "Shows a Notification when one of your Plugins is outdated"},
notifyNewEntries: {value: true, autoload: false, description: "Shows a Notification when there are new Entries in the Repo"},
startDownloaded: {value: false, autoload: true, description: "Starts new Plugins after Download"},
startUpdated: {value: false, autoload: true, description: "Starts updated Plugins after Download"}
2020-09-04 11:25:48 +02:00
},
2021-05-03 12:26:32 +02:00
filters: {
2023-11-18 18:31:04 +01:00
updated: {value: true, description: "Updated"},
outdated: {value: true, description: "Outdated"},
2021-05-03 12:26:32 +02:00
downloadable: {value: true, description: "Downloadable"},
2020-09-19 20:49:33 +02:00
}
};
2020-09-04 11:25:48 +02:00
2022-10-11 11:14:32 +02:00
this.modulePatches = {
before: [
"SettingsView",
"StandardSidebarView"
],
componentWillUnmount: [
"SettingsView"
]
2020-09-19 20:49:33 +02:00
};
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
2022-02-16 15:54:37 +01:00
onStart () {
2020-09-04 11:25:48 +02:00
this.forceUpdateAll();
this.loadPlugins();
2022-02-16 15:54:37 +01:00
updateInterval = BDFDB.TimeUtils.interval(_ => this.checkForNewPlugins(), 1000*60*30);
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStop () {
2020-09-04 11:25:48 +02:00
BDFDB.TimeUtils.clear(updateInterval);
2022-02-16 15:54:37 +01:00
BDFDB.TimeUtils.clear(loading.timeout);
2020-09-04 11:25:48 +02:00
this.forceUpdateAll();
2021-01-22 21:01:58 +01:00
BDFDB.DOMUtils.remove(BDFDB.dotCN._pluginreponotice, BDFDB.dotCN._pluginrepoloadingicon);
2020-09-04 11:25:48 +02:00
}
2021-01-06 12:38:36 +01:00
onSettingsClosed () {
2020-09-19 20:49:33 +02:00
if (this.SettingsUpdated) {
delete this.SettingsUpdated;
this.forceUpdateAll();
}
}
2021-01-06 12:38:36 +01:00
forceUpdateAll () {
2020-09-19 20:49:33 +02:00
favorites = BDFDB.DataUtils.load(this, "favorites");
2021-05-03 12:26:32 +02:00
favorites = (typeof favorites == "string" ? favorites.split(" ") : []).map(n => parseInt(n)).filter(n => !isNaN(n));
2020-09-19 20:49:33 +02:00
BDFDB.PatchUtils.forceAllUpdates(this);
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
onUserSettingsCogContextMenu (e) {
BDFDB.TimeUtils.timeout(_ => {
2020-10-24 10:45:35 +02:00
let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {props: [["label", ["BandagedBD", "BetterDiscord"]]]});
2023-03-18 12:07:50 +01:00
if (index > -1 && BDFDB.ArrayUtils.is(children[index].props.children)) {
let item = BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
label: "Plugin Repo",
id: BDFDB.ContextMenuUtils.createItemId(this.name, "repo"),
action: _ => BDFDB.LibraryModules.UserSettingsUtils.open("pluginrepo")
});
if (children[index].props.children.find(n => n && n.props && n.props.id == "themerepo-repo")) children[index].props.children.splice(children[index].props.children.length-1, 0, item);
else children[index].props.children.push(item);
}
2020-09-19 20:49:33 +02:00
});
}
processSettingsView (e) {
2021-05-03 19:20:03 +02:00
if (e.node) searchString = "";
2022-10-11 11:14:32 +02:00
else if (e.component.prototype && !BDFDB.PatchUtils.isPatched(this, e.component.prototype, "getPredicateSections")) {
BDFDB.PatchUtils.patch(this, e.component.prototype, "getPredicateSections", {after: e2 => {
2022-02-16 15:54:37 +01:00
if (BDFDB.ArrayUtils.is(e2.returnValue) && e2.returnValue.findIndex(n => n.section && (n.section.toLowerCase() == "changelog" || n.section == BDFDB.DiscordConstants.UserSettingsSections.CHANGE_LOG || n.section.toLowerCase() == "logout" || n.section == BDFDB.DiscordConstants.UserSettingsSections.LOGOUT))) {
e2.returnValue = e2.returnValue.filter(n => n.section != "pluginrepo");
let index = e2.returnValue.indexOf(e2.returnValue.find(n => n.section == "themes") || e2.returnValue.find(n => n.section == BDFDB.DiscordConstants.UserSettingsSections.DEVELOPER_OPTIONS) || e2.returnValue.find(n => n.section == BDFDB.DiscordConstants.UserSettingsSections.HYPESQUAD_ONLINE));
if (index > -1) {
e2.returnValue.splice(index + 1, 0, {
2022-08-21 19:05:37 +02:00
className: "pluginrepo-tab",
2022-02-16 15:54:37 +01:00
section: "pluginrepo",
label: "Plugin Repo",
element: _ => {
let options = Object.assign({}, this.settings.filters);
options.updated = options.updated && !showOnlyOutdated;
options.outdated = options.outdated || showOnlyOutdated;
options.downloadable = options.downloadable && !showOnlyOutdated;
options.sortKey = forcedSort || Object.keys(sortKeys)[0];
options.orderKey = forcedOrder || Object.keys(orderKeys)[0];
return BDFDB.ReactUtils.createElement(RepoListComponent, options, true);
}
});
if (!e2.returnValue.find(n => n.section == "plugins")) e2.returnValue.splice(index + 1, 0, {section: "DIVIDER"});
}
}
}});
}
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
processStandardSidebarView (e) {
2022-11-26 13:43:14 +01:00
if (e.instance.props && e.instance.props.section == "pluginrepo") e.instance.props.contentType = "custom";
2020-09-04 11:25:48 +02:00
}
2023-04-15 17:03:37 +02:00
loadPlugins (forceBanner) {
2021-01-22 21:01:58 +01:00
BDFDB.DOMUtils.remove(BDFDB.dotCN._pluginrepoloadingicon);
2021-05-03 12:26:32 +02:00
cachedPlugins = BDFDB.DataUtils.load(this, "cached");
cachedPlugins = (typeof cachedPlugins == "string" ? cachedPlugins.split(" ") : []).map(n => parseInt(n)).filter(n => !isNaN(n));
let loadingIcon;
let newEntries = 0, outdatedEntries = 0, checkIndex = 0, checksRunning = 0, callbackCalled = false;
2021-05-03 19:20:03 +02:00
const checkPlugin = _ => {
2021-05-03 12:26:32 +02:00
if (checksRunning > 20) return;
2021-05-12 19:44:23 +02:00
else if (grabbedPlugins.every(p => p.loaded || (!p.latestSourceUrl && !p.latest_source_url)) || !this.started || !loading.is) {
2021-05-03 12:26:32 +02:00
if (!callbackCalled) {
callbackCalled = true;
if (!this.started) return BDFDB.TimeUtils.clear(loading.timeout);
2021-04-01 12:28:24 +02:00
BDFDB.TimeUtils.clear(loading.timeout);
BDFDB.DOMUtils.remove(loadingIcon, BDFDB.dotCN._pluginrepoloadingicon);
loading = {is: false, timeout: null, amount: loading.amount};
BDFDB.LogUtils.log("Finished fetching Plugins", this);
2021-05-03 12:26:32 +02:00
BDFDB.ReactUtils.forceUpdate(list);
2021-04-01 12:28:24 +02:00
2023-04-15 17:03:37 +02:00
if ((this.settings.general.notifyOutdated || forceBanner) && outdatedEntries > 0) {
2021-04-01 12:28:24 +02:00
let notice = document.querySelector(BDFDB.dotCN._pluginrepooutdatednotice);
if (notice) notice.close();
2021-05-03 12:26:32 +02:00
BDFDB.NotificationUtils.notice(this.labels.notice_outdated_plugins.replace("{{var0}}", outdatedEntries), {
2021-04-01 12:28:24 +02:00
type: "danger",
className: BDFDB.disCNS._pluginreponotice + BDFDB.disCN._pluginrepooutdatednotice,
customIcon: pluginRepoIcon.replace(/COLOR_[0-9]+/gi, "currentColor"),
buttons: [{
contents: BDFDB.LanguageUtils.LanguageStrings.OPEN,
close: true,
onClick: _ => {
showOnlyOutdated = true;
BDFDB.LibraryModules.UserSettingsUtils.open("pluginrepo");
2020-09-19 20:49:33 +02:00
}
2021-04-01 12:28:24 +02:00
}]
});
}
2021-05-03 12:26:32 +02:00
if (this.settings.general.notifyNewEntries && newEntries > 0) {
2021-04-01 12:28:24 +02:00
let notice = document.querySelector(BDFDB.dotCN._pluginreponewentriesnotice);
if (notice) notice.close();
BDFDB.NotificationUtils.notice(this.labels.notice_new_plugins.replace("{{var0}}", newEntries), {
type: "success",
className: BDFDB.disCNS._pluginreponotice + BDFDB.disCN._pluginreponewentriesnotice,
customIcon: pluginRepoIcon.replace(/COLOR_[0-9]+/gi, "currentColor"),
buttons: [{
contents: BDFDB.LanguageUtils.LanguageStrings.OPEN,
close: true,
onClick: _ => {
2021-05-12 19:44:23 +02:00
forcedSort = "RELEASEDATE";
2021-04-01 12:28:24 +02:00
forcedOrder = "ASC";
BDFDB.LibraryModules.UserSettingsUtils.open("pluginrepo");
2020-09-04 11:25:48 +02:00
}
2021-04-01 12:28:24 +02:00
}]
});
}
2021-05-03 12:26:32 +02:00
}
2020-09-19 20:49:33 +02:00
return;
2020-09-04 11:25:48 +02:00
}
2021-05-03 12:26:32 +02:00
else if (checkIndex > grabbedPlugins.length) return;
const plugin = grabbedPlugins[checkIndex++];
2021-05-12 19:44:23 +02:00
if (!plugin || (!plugin.latestSourceUrl && !plugin.latest_source_url)) checkPlugin();
2021-05-03 12:26:32 +02:00
else {
checksRunning++;
2021-05-12 19:44:23 +02:00
plugin.releasedate = new Date(plugin.releaseDate || plugin.release_date || 0).getTime();
plugin.latestSourceUrl = plugin.latestSourceUrl || plugin.latest_source_url;
2021-05-03 19:20:03 +02:00
plugin.rawSourceUrl = plugin.latestSourceUrl.replace("https://github.com/", "https://raw.githubusercontent.com/").replace(/\/blob\/(.{32,})/i, "/$1");
2021-05-12 19:44:23 +02:00
plugin.thumbnailUrl = plugin.thumbnailUrl || plugin.thumbnail_url;
2021-05-03 19:20:03 +02:00
plugin.thumbnailUrl = plugin.thumbnailUrl ? (plugin.thumbnailUrl.startsWith("https://") ? plugin.thumbnailUrl : `https://betterdiscord.app${plugin.thumbnailUrl}`) : "";
2021-05-12 19:44:23 +02:00
delete plugin.release_date;
delete plugin.latest_source_url;
delete plugin.thumbnail_url;
2023-11-04 10:33:32 +01:00
BDFDB.LibraryRequires.request(plugin.rawSourceUrl, (error, response, body) => {
if (error || !body || body.indexOf("404: Not Found") == 0) plugin.failed = true;
2022-12-07 11:31:44 +01:00
else {
2023-11-04 10:33:32 +01:00
const META = body.split("*/")[0];
plugin.name = BDFDB.StringUtils.upperCaseFirstChar((/@name\s+([^\t^\r^\n]+)|\/\/\**META.*["']name["']\s*:\s*["'](.+?)["']/i.exec(META) || []).filter(n => n)[1] || plugin.name || "");
plugin.authorname = (/@author\s+(.+)|\/\/\**META.*["']author["']\s*:\s*["'](.+?)["']/i.exec(META) || []).filter(n => n)[1] || plugin.author.display_name || plugin.author;
const version = (/@version\s+(.+)|\/\/\**META.*["']version["']\s*:\s*["'](.+?)["']/i.exec(META) || []).filter(n => n)[1];
if (version) {
plugin.version = version;
const installedPlugin = this.getInstalledPlugin(plugin);
if (installedPlugin && this.compareVersions(version, this.getString(installedPlugin.plugin && installedPlugin.plugin.version || installedPlugin.version))) outdatedEntries++;
2020-09-04 11:25:48 +02:00
}
2022-12-07 11:31:44 +01:00
if (!cachedPlugins.includes(plugin.id)) newEntries++;
2020-09-04 11:25:48 +02:00
}
2021-02-25 08:17:51 +01:00
2021-05-03 12:26:32 +02:00
plugin.loaded = true;
let loadingTooltip = document.querySelector(BDFDB.dotCN._pluginrepoloadingtooltip);
if (loadingTooltip) loadingTooltip.update(this.getLoadingTooltipText());
2020-09-19 20:49:33 +02:00
2021-05-03 12:26:32 +02:00
checksRunning--;
2021-05-03 19:20:03 +02:00
checkPlugin();
2021-05-03 12:26:32 +02:00
});
}
};
2023-10-20 14:32:21 +02:00
BDFDB.TimeUtils.timeout(_ => BDFDB.LibraryRequires.request("https://api.betterdiscord.app/v1/store/plugins", {bdVersion: true}, (error, response, body) => {
2022-02-22 09:49:27 +01:00
if (!error && body && response.statusCode == 200) try {
2021-05-03 12:26:32 +02:00
grabbedPlugins = BDFDB.ArrayUtils.keySort(JSON.parse(body).filter(n => n), "name");
BDFDB.DataUtils.save(BDFDB.ArrayUtils.numSort(grabbedPlugins.map(n => n.id)).join(" "), this, "cached");
loading = {is: true, timeout: BDFDB.TimeUtils.timeout(_ => {
BDFDB.TimeUtils.clear(loading.timeout);
if (this.started) {
if (loading.is && loading.amount < 4) BDFDB.TimeUtils.timeout(_ => this.loadPlugins(), 10000);
loading = {is: false, timeout: null, amount: loading.amount};
2020-09-19 20:49:33 +02:00
}
2021-05-03 12:26:32 +02:00
}, 1200000), amount: loading.amount + 1};
loadingIcon = BDFDB.DOMUtils.create(pluginRepoIcon.replace(/COLOR_1/gi, "var(--bdfdb-blurple)").replace(/COLOR_2/gi, "#72767d"));
BDFDB.DOMUtils.addClass(loadingIcon, BDFDB.disCN._pluginrepoloadingicon);
loadingIcon.addEventListener("mouseenter", _ => {
BDFDB.TooltipUtils.create(loadingIcon, this.getLoadingTooltipText(), {
type: "left",
className: BDFDB.disCN._pluginrepoloadingtooltip,
delay: 500,
style: "max-width: unset;"
});
});
BDFDB.PluginUtils.addLoadingIcon(loadingIcon);
2020-09-04 11:25:48 +02:00
2022-10-11 11:14:32 +02:00
BDFDB.ReactUtils.forceUpdate(list);
2020-09-19 20:49:33 +02:00
2021-05-03 19:20:03 +02:00
for (let i = 0; i <= 20; i++) checkPlugin();
2021-05-03 12:26:32 +02:00
}
catch (err) {BDFDB.NotificationUtils.toast("Failed to load Plugin Store", {type: "danger"});}
2022-02-22 09:49:27 +01:00
if (response && response.statusCode == 403) BDFDB.NotificationUtils.toast("Failed to fetch Plugin Store from the Website Api due to DDoS Protection", {type: "danger"});
else if (response && response.statusCode == 404) BDFDB.NotificationUtils.toast("Failed to fetch Plugin Store from the Website Api due to Connection Issue", {type: "danger"});
2023-10-20 14:32:21 +02:00
}), 10000);
2020-09-04 11:25:48 +02:00
}
2021-01-06 12:38:36 +01:00
getLoadingTooltipText () {
2021-05-03 12:26:32 +02:00
return BDFDB.LanguageUtils.LibraryStringsFormat("loading", `Plugin Repo - [${grabbedPlugins.filter(n => n.loaded).length}/${grabbedPlugins.length}]`);
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
getString (obj) {
let 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);
2020-09-04 11:25:48 +02:00
}
2020-09-19 20:49:33 +02:00
return string;
}
2022-06-08 17:08:40 +02:00
compareVersions (v1, v2) {
return !(v1 == v2 || !BDFDB.NumberUtils.compareVersions(v1, v2));
}
2021-05-03 12:26:32 +02:00
getInstalledPlugin (plugin) {
2021-05-12 19:44:23 +02:00
if (!plugin || typeof plugin.authorname != "string") return;
2021-05-03 12:26:32 +02:00
const iPlugin = BDFDB.BDUtils.getPlugin(plugin.name, false, true);
2023-03-21 20:00:39 +01:00
if (iPlugin && (plugin.authorname.toUpperCase().indexOf(this.getString(iPlugin.author).toUpperCase()) > -1 || this.getString(iPlugin.author).toUpperCase().indexOf(plugin.authorname.toUpperCase()) > -1)) return iPlugin;
2021-05-03 12:26:32 +02:00
else if (plugin.rawSourceUrl && window.BdApi && BdApi.Plugins && typeof BdApi.Plugins.getAll == "function") {
const filename = plugin.rawSourceUrl.split("/").pop();
2023-03-21 20:00:39 +01:00
for (let p of BdApi.Plugins.getAll()) if (p.filename == filename && (plugin.authorname.toUpperCase().indexOf(this.getString(p.author).toUpperCase()) > -1 || this.getString(p.author).toUpperCase().indexOf(plugin.authorname.toUpperCase()) > -1)) return p;
2020-09-19 20:49:33 +02:00
}
}
2020-09-04 11:25:48 +02:00
2021-05-03 12:26:32 +02:00
checkForNewPlugins () {
2023-10-20 14:25:24 +02:00
BDFDB.LibraryRequires.request("https://api.betterdiscord.app/v1/store/plugins", {bdVersion: true}, (error, response, body) => {
2021-05-03 12:26:32 +02:00
if (!error && body) try {
if (JSON.parse(body).filter(n => n).length != grabbedPlugins.length) {
loading = {is: false, timeout: null, amount: 0};
this.loadPlugins();
}
}
catch (err) {BDFDB.NotificationUtils.toast("Failed to load Plugin Store", {type: "danger"});}
2020-09-19 20:49:33 +02:00
});
2020-09-04 11:25:48 +02:00
}
2021-01-23 20:15:58 +01:00
setLabelsByLanguage () {
switch (BDFDB.LanguageUtils.getLanguage().id) {
case "bg": // Bulgarian
return {
list: "Списък",
notice_failed_plugins: "Някои Plugins [{{var0}}] не можаха да бъдат заредени",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Новите Plugins [{{var0}}] бяха добавени към Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Някои Plugins [{{var0}}] са остарели"
};
case "da": // Danish
return {
list: "Liste",
notice_failed_plugins: "Nogle Plugins [{{var0}}] kunne ikke indlæses",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Nye Plugins [{{var0}}] er blevet føjet til Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Nogle Plugins [{{var0}}] er forældede"
};
case "de": // German
return {
list: "Liste",
notice_failed_plugins: "Einige Plugins [{{var0}}] konnten nicht geladen werden",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Neue Plugins [{{var0}}] wurden zur Plugin Repo hinzugefügt",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Einige Plugins [{{var0}}] sind veraltet"
};
case "el": // Greek
return {
list: "Λίστα",
2023-03-29 08:08:51 +02:00
notice_failed_plugins: "Δεν ήταν δυνατή η φόρτωση ορισμένων Πρόσθετων [{{var0}}] ",
notice_new_plugins: "Προστέθηκαν νέα Πρόσθετα [{{var0}}] στο Αποθετήριο Προσθέτων",
notice_outdated_plugins: "Ορισμένα Πρόσθετα [{{var0}}] είναι παλαιά"
2021-01-23 20:15:58 +01:00
};
case "es": // Spanish
return {
list: "Lista",
notice_failed_plugins: "Algunos Plugins [{{var0}}] no se pudieron cargar",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Se han agregado nuevos Plugins [{{var0}}] a Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Algunas Plugins [{{var0}}] están desactualizadas"
};
case "fi": // Finnish
return {
list: "Lista",
notice_failed_plugins: "Joitain kohdetta Plugins [{{var0}}] ei voitu ladata",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Uusi Plugins [{{var0}}] on lisätty Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Jotkut Plugins [{{var0}}] ovat vanhentuneita"
};
case "fr": // French
return {
list: "Liste",
notice_failed_plugins: "Certains Plugins [{{var0}}] n'ont pas pu être chargés",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "De nouveaux Plugins [{{var0}}] ont été ajoutés à Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Certains Plugins [{{var0}}] sont obsolètes"
};
case "hr": // Croatian
return {
list: "Popis",
notice_failed_plugins: "Neke datoteke Plugins [{{var0}}] nije moguće učitati",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Novi Plugins [{{var0}}] dodani su u Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Neki su Plugins [{{var0}}] zastarjeli"
};
case "hu": // Hungarian
return {
list: "Lista",
notice_failed_plugins: "Néhány Plugins [{{var0}}] nem sikerült betölteni",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Új Plugins [{{var0}}] hozzáadva a következőhöz: Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Néhány Plugins [{{var0}}] elavult"
};
case "it": // Italian
return {
list: "Elenco",
notice_failed_plugins: "Impossibile caricare alcuni Plugins [{{var0}}] ",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Il nuovo Plugins [{{var0}}] è stato aggiunto a Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Alcuni Plugins [{{var0}}] non sono aggiornati"
};
case "ja": // Japanese
return {
list: "リスト",
notice_failed_plugins: "一部の Plugins [{{var0}}] を読み込めませんでした",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "新しい Plugins [{{var0}}] が Plugin Repo に追加されました",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "一部の Plugins [{{var0}}] は古くなっています"
};
case "ko": // Korean
return {
list: "명부",
notice_failed_plugins: "일부 Plugins [{{var0}}] 을 (를)로드 할 수 없습니다.",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "새 Plugins [{{var0}}] 이 Plugin Repo 에 추가되었습니다.",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "일부 Plugins [{{var0}}] 이 오래되었습니다."
};
case "lt": // Lithuanian
return {
list: "Sąrašas",
notice_failed_plugins: "Kai kurių Plugins [{{var0}}] nepavyko įkelti",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Naujas Plugins [{{var0}}] pridėtas prie Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Kai kurie Plugins [{{var0}}] yra pasenę"
};
case "nl": // Dutch
return {
list: "Lijst",
notice_failed_plugins: "Sommige Plugins [{{var0}}] konden niet worden geladen",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Nieuwe Plugins [{{var0}}] zijn toegevoegd aan de Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Sommige Plugins [{{var0}}] zijn verouderd"
};
case "no": // Norwegian
return {
list: "Liste",
notice_failed_plugins: "Noen Plugins [{{var0}}] kunne ikke lastes inn",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Nye Plugins [{{var0}}] er lagt til i Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Noen Plugins [{{var0}}] er utdaterte"
};
case "pl": // Polish
return {
list: "Lista",
notice_failed_plugins: "Nie można załadować niektórych Plugins [{{var0}}] ",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Nowe Plugins [{{var0}}] zostały dodane do Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Niektóre Plugins [{{var0}}] są nieaktualne"
};
case "pt-BR": // Portuguese (Brazil)
return {
list: "Lista",
notice_failed_plugins: "Algum Plugins [{{var0}}] não pôde ser carregado",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Novo Plugins [{{var0}}] foi adicionado ao Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Alguns Plugins [{{var0}}] estão desatualizados"
};
case "ro": // Romanian
return {
list: "Listă",
notice_failed_plugins: "Unele Plugins [{{var0}}] nu au putut fi încărcate",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Plugins [{{var0}}] nou au fost adăugate la Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Unele Plugins [{{var0}}] sunt învechite"
};
case "ru": // Russian
return {
list: "Список",
notice_failed_plugins: "Не удалось загрузить некоторые Plugins [{{var0}}] ",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Новые Plugins [{{var0}}] добавлены в Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Некоторые Plugins [{{var0}}] устарели"
};
case "sv": // Swedish
return {
list: "Lista",
notice_failed_plugins: "Vissa Plugins [{{var0}}] kunde inte laddas",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Nya Plugins [{{var0}}] har lagts till i Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Vissa Plugins [{{var0}}] är föråldrade"
};
case "th": // Thai
return {
list: "รายการ",
notice_failed_plugins: "ไม่สามารถโหลด Plugins [{{var0}}] บางรายการได้",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "เพิ่ม Plugins [{{var0}}] ใหม่ใน Plugin Repo แล้ว",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Plugins [{{var0}}] บางรายการล้าสมัย"
};
case "tr": // Turkish
return {
list: "Liste",
notice_failed_plugins: "Bazı Plugins [{{var0}}] yüklenemedi",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Yeni Plugins [{{var0}}], Plugin Repo 'ye eklendi",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Bazı Plugins [{{var0}}] güncel değil"
};
case "uk": // Ukrainian
return {
list: "Список",
notice_failed_plugins: "Деякі Plugins [{{var0}}] не вдалося завантажити",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Нові Plugins [{{var0}}] були додані до Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Деякі Plugins [{{var0}}] застарілі"
};
case "vi": // Vietnamese
return {
list: "Danh sách",
notice_failed_plugins: "Không thể tải một số Plugins [{{var0}}] ",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "Plugins [{{var0}}] mới đã được thêm vào Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Một số Plugins [{{var0}}] đã lỗi thời"
};
case "zh-CN": // Chinese (China)
return {
list: "清单",
notice_failed_plugins: "某些 Plugins [{{var0}}] 无法加载",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "新的 Plugins [{{var0}}] 已添加到 Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "一些 Plugins [{{var0}}] 已过时"
};
case "zh-TW": // Chinese (Taiwan)
return {
list: "清單",
notice_failed_plugins: "某些 Plugins [{{var0}}] 無法加載",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "新的 Plugins [{{var0}}] 已添加到 Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "一些 Plugins [{{var0}}] 已過時"
};
default: // English
return {
list: "List",
notice_failed_plugins: "Some Plugins [{{var0}}] could not be loaded",
2021-04-01 14:01:59 +02:00
notice_new_plugins: "New Plugins [{{var0}}] have been added to the Plugin Repo",
2021-01-23 20:15:58 +01:00
notice_outdated_plugins: "Some Plugins [{{var0}}] are outdated"
};
}
}
2020-09-19 20:49:33 +02:00
};
2022-09-01 14:40:11 +02:00
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
2021-05-08 09:19:43 +02:00
})();