/**
 * @name BDFDB
 * @author DevilBro
 * @authorId 278543574059057154
 * @version 4.4.6
 * @description Required Library for DevilBro's Plugins
 * @invite Jx3TjNS
 * @donate https://www.paypal.me/MircoWittrien
 * @patreon https://www.patreon.com/MircoWittrien
 * @website https://mwittrien.github.io/
 * @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Library/
 * @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js
 */

module.exports = (_ => {
	if (window.BDFDB_Global && window.BDFDB_Global.PluginUtils && typeof window.BDFDB_Global.PluginUtils.cleanUp == "function") window.BDFDB_Global.PluginUtils.cleanUp(window.BDFDB_Global);
	
	const fs = require("fs"), path = require("path");
	
	var BDFDB, Internal;
	var LibraryRequires = {};
	var DiscordObjects = {}, DiscordConstants = {};
	var LibraryStores = {}, LibraryModules = {};
	var LibraryComponents = {}, NativeSubComponents = {}, CustomComponents = {};
	var PluginStores = {};
	
	BDFDB = {
		started: true,
		changeLog: {}
	};
	
	return class BDFDB_Frame {
		constructor (meta) {for (let key in meta) {
			if (!this[key]) this[key] = meta[key];
			if (!BDFDB[key]) BDFDB[key] = meta[key];
		}}
		getName () {return this.name;}
		getAuthor () {return this.author;}
		getVersion () {return this.version;}
		getDescription () {return this.description;}
		
		load () {
			const BdApi = window.BdApi;
			
			const Cache = {data: {}, modules: {}};
			
			var changeLogs = {};
			
			Internal = Object.assign({}, BDFDB, {
				patchPriority: 0,
				forceSyncData: true,
				settings: {},
				defaults: {
					general: {
						shareData: {
							value: true,
							onChange: _ => Cache.data = {}
						},
						showToasts: {
							value: true,
							isDisabled: data => data.nativeValue,
							hasNote: data => data.disabled && data.value
						},
						checkForUpdates: {
							value: false,
							hasNote: true
						},
						showSupportBadges: {
							value: false
						},
						useChromium: {
							value: false,
							isHidden: data => !Internal.LibraryRequires.electron || !Internal.LibraryRequires.electron.remote,
							getValue: data => !data.disabled
						}
					},
					choices: {
						toastPosition: {
							value: "right",
							items: "ToastPositions"
						}
					}
				},
			});
			for (let key in Internal.defaults) Internal.settings[key] = {};
			
			PluginStores = {
				loaded: {},
				delayed: {
					loads: [],
					starts: []
				},
				updateData: {
					plugins: {},
					timeouts: [],
					downloaded: [],
					interval: null
				},
				modulePatches: {}
			};
			
			const Plugin = function (changeLog) {
				return class Plugin {
					constructor (meta) {for (let key in meta) if (!this[key]) this[key] = meta[key];}
					getName () {return this.name;}
					getAuthor () {return this.author;}
					getVersion () {return this.version;}
					getDescription () {return this.description;}
					load () {
						this.changeLog = changeLog;
						this.loaded = true;
						this.defaults = {};
						this.labels = {};
						if (window.BDFDB_Global.loading) {
							if (!PluginStores.delayed.loads.includes(this)) PluginStores.delayed.loads.push(this);
						}
						else BDFDB.TimeUtils.suppress(_ => {
							PluginStores.loaded[this.name] = this;
							BDFDB.PluginUtils.load(this);
							if (typeof this.onLoad == "function") this.onLoad();
						}, "Failed to load Plugin!", this)();
					}
					start () {
						if (!this.loaded) this.load();
						if (window.BDFDB_Global.loading) {
							if (!PluginStores.delayed.starts.includes(this)) PluginStores.delayed.starts.push(this);
						}
						else {
							if (this.started) return;
							this.started = true;
							BDFDB.TimeUtils.suppress(_ => {
								BDFDB.PluginUtils.init(this);
								if (typeof this.onStart == "function") this.onStart();
							}, "Failed to start Plugin!", this)();
							delete this.stopping;
						}
					}
					stop () {
						if (window.BDFDB_Global.loading) {
							if (PluginStores.delayed.starts.includes(this)) PluginStores.delayed.starts.splice(PluginStores.delayed.starts.indexOf(this), 1);
						}
						else {
							if (this.stopping) return;
							this.stopping = true;
							BDFDB.TimeUtils.timeout(_ => {delete this.stopping;});
							
							BDFDB.TimeUtils.suppress(_ => {
								if (typeof this.onStop == "function") this.onStop();
								BDFDB.PluginUtils.clear(this);
							}, "Failed to stop Plugin!", this)();

							delete this.started;
						}
					}
				};
			};

			const requestFunction = function (...args) {
				let url = typeof args[0] == "string" && args[0];
				if (!url) return;
				let callback = typeof args[1] == "function" && args[1] || typeof args[2] == "function" && args[2];
				if (typeof callback != "function") return;
				if (url.indexOf("data:") == 0) callback(null, {
					aborted: false,
					complete: true,
					end: undefined,
					headers: {"content-type": url.slice(5).split(";")[0]},
					method: null,
					rawHeaders: [],
					statusCode: 200,
					statusMessage: "OK",
					url: ""
				}, url);
				else {
					let config = args[1] && typeof args[1] == "object" ? args[1] : {};
					let timeout = 600000;
					if (!isNaN(parseInt(config.timeout)) && config.timeout > 0) timeout = config.timeout;
					if (config.form && typeof config.form == "object") {
						let query = Object.entries(config.form).map(n => n[0] + "=" + n[1]).join("&");
						if (query) url += `?${query}`;
					}
					if (config.method) config.method = config.method.toUpperCase();
					let killed = false, timeoutObj = BDFDB.TimeUtils.timeout(_ => {
						killed = true;
						BDFDB.TimeUtils.clear(timeoutObj);
						callback(new Error(`Request Timeout after ${timeout}ms`), {
							aborted: false,
							complete: true,
							end: undefined,
							headers: {},
							method: null,
							rawHeaders: [],
							statusCode: 408,
							statusMessage: "OK",
							url: ""
						}, null);
					}, timeout);
					let response = null, isFallback = false;
					return (config.bdVersion && BdApi && BdApi.Net && BdApi.Net.fetch ? BdApi.Net.fetch : fetch)(url, config).catch(error => {
						BDFDB.TimeUtils.clear(timeoutObj);
						if (!config.bdVersion) return requestFunction(url, Object.assign({}, config, {bdVersion: true}), callback);
						else callback(new Error(error), {
							aborted: false,
							complete: true,
							end: undefined,
							headers: {},
							method: null,
							rawHeaders: [],
							statusCode: 408,
							statusMessage: "OK",
							url: ""
						}, null);
					}).then(r => {
						response = r;
						if (!response) return;
						response.statusCode = response.status;
						if (response.headers) response.headers["content-type"] = response.headers.get("content-type");
						BDFDB.TimeUtils.clear(timeoutObj);
						return config.toBase64 ? response.blob() : config.toBuffer ? response.arrayBuffer() : response.text();
					}).then(result => {
						if (!killed && response) {
							if (!config.toBase64 || response.status != 200) callback(response.status != 200 ? new Error(response.statusText || "Fetch Failed") : null, response, result);
							else {
								let reader = new FileReader();
								reader.onload = _ => callback(null, response, reader.result);
								reader.readAsDataURL(result);
							}
						}
					});
				}
			};

			BDFDB.LogUtils = {};
			Internal.console = function (type, config = {}) {
				if (!console[type]) return;
				let name, version;
				if (typeof config.name == "string" && config.name) {
					name = config.name;
					version = typeof config.version == "string" ? config.version : "";
				}
				else {
					name = BDFDB.name;
					version = BDFDB.version;
				}
				console[type](...[[name && `%c[${name}]`, version && `%c(v${version})`].filter(n => n).join(" "), name && "color: #3a71c1; font-weight: 700;", version && "color: #666; font-weight: 600; font-size: 11px;", [config.strings].flat(10).filter(n => n).join(" ").trim()].filter(n => n));
			};
			BDFDB.LogUtils.log = function (strings, config = {}) {
				Internal.console("log", Object.assign({}, config, {name: typeof config == "string" ? config : config.name, strings}));
			};
			BDFDB.LogUtils.warn = function (strings, config = {}) {
				Internal.console("warn", Object.assign({}, config, {name: typeof config == "string" ? config : config.name, strings}));
			};
			BDFDB.LogUtils.error = function (strings, config = {}) {
				Internal.console("error", Object.assign({}, config, {name: typeof config == "string" ? config : config.name, strings: ["Fatal Error:", strings]}));
			};

			BDFDB.TimeUtils = {};
			BDFDB.TimeUtils.interval = function (callback, delay, ...args) {
				if (typeof callback != "function" || typeof delay != "number" || delay < 1) return;
				else {
					let count = 0, interval = setInterval(_ => BDFDB.TimeUtils.suppress(callback, "Interval")(...[interval, count++, args].flat()), delay);
					return interval;
				}
			};
			BDFDB.TimeUtils.timeout = function (callback, delay, ...args) {
				delay = parseFloat(delay);
				if (typeof callback != "function") return;
				if (isNaN(delay) || typeof delay != "number" || delay < 1) {
					let immediate = setImmediate(_ => BDFDB.TimeUtils.suppress(callback, "Immediate")(...[immediate, args].flat()));
					return immediate;
				}
				else {
					let start, paused = true, timeout = {
						pause: _ => {
							if (paused) return;
							paused = true;
							BDFDB.TimeUtils.clear(timeout.timer);
							delay -= performance.now() - start;
						},
						resume: _ => {
							if (!paused) return;
							paused = false;
							start = performance.now();
							timeout.timer = setTimeout(_ => BDFDB.TimeUtils.suppress(callback, "Timeout")(...[timeout, args].flat()), delay)
						}
					};
					timeout.resume();
					return timeout;
				}
			};
			BDFDB.TimeUtils.clear = function (...timeObjects) {
				for (let t of timeObjects.flat(10).filter(n => n)) {
					t = t.timer != undefined ? t.timer : t;
					if (typeof t == "number") {
						clearInterval(t);
						clearTimeout(t);
					}
					else if (typeof t == "object") clearImmediate(t);
				}
			};
			BDFDB.TimeUtils.suppress = function (callback, strings, config) {return function (...args) {
				try {return callback(...args);}
				catch (err) {(!config || !config.ignoreErrors) && BDFDB.LogUtils.error([strings, err], config);}
			}};

			BDFDB.LogUtils.log("Loading Library");
			
			BDFDB.sameProto = function (a, b) {
				if (a != null && typeof a == "object") return a.constructor && a.constructor.prototype && typeof a.constructor.prototype.isPrototypeOf == "function" && a.constructor.prototype.isPrototypeOf(b);
				else return typeof a == typeof b;
			};
			BDFDB.equals = function (mainA, mainB, sorted) {
				let i = -1;
				if (sorted === undefined || typeof sorted !== "boolean") sorted = false;
				return equal(mainA, mainB);
				function equal(a, b) {
					i++;
					let result = true;
					if (i > 1000) result = null;
					else {
						if (typeof a !== typeof b) result = false;
						else if (typeof a == "function") result = a.toString() == b.toString();
						else if (typeof a === "undefined") result = true;
						else if (typeof a === "symbol") result = true;
						else if (typeof a === "boolean") result = a == b;
						else if (typeof a === "string") result = a == b;
						else if (typeof a === "number") {
							if (isNaN(a) || isNaN(b)) result = isNaN(a) == isNaN(b);
							else result = a == b;
						}
						else if (!a && !b) result = true;
						else if (!a || !b) result = false;
						else if (typeof a === "object") {
							let keysA = Object.getOwnPropertyNames(a);
							let keysB = Object.getOwnPropertyNames(b);
							if (keysA.length !== keysB.length) result = false;
							else for (let j = 0; result === true && j < keysA.length; j++) {
								if (sorted) result = equal(a[keysA[j]], b[keysB[j]]);
								else result = equal(a[keysA[j]], b[keysA[j]]);
							}
						}
					}
					i--;
					return result;
				}
			};

			BDFDB.ObjectUtils = {};
			BDFDB.ObjectUtils.is = function (obj) {
				return obj && !Array.isArray(obj) && !Set.prototype.isPrototypeOf(obj) && (typeof obj == "function" || typeof obj == "object");
			};
			BDFDB.ObjectUtils.get = function (nodeOrObj, valuePath) {
				if (!nodeOrObj || !valuePath) return null;
				let obj = Node.prototype.isPrototypeOf(nodeOrObj) ? BDFDB.ReactUtils.getInstance(nodeOrObj) : nodeOrObj;
				if (!BDFDB.ObjectUtils.is(obj)) return null;
				let found = obj;
				for (const value of valuePath.split(".").filter(n => n)) {
					if (!found) return null;
					found = found[value];
				}
				return found;
			};
			BDFDB.ObjectUtils.invert = function (obj) {
				let newObj = {};
				if (BDFDB.ObjectUtils.is(obj)) for (let entry of Object.entries(obj)) newObj[entry[1]] = entry[0];
				return newObj;
			};
			BDFDB.ObjectUtils.extract = function (obj, ...keys) {
				let newObj = {};
				if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) if (obj[key] != null) newObj[key] = obj[key];
				return newObj;
			};
			BDFDB.ObjectUtils.exclude = function (obj, ...keys) {
				let newObj = Object.assign({}, obj);
				BDFDB.ObjectUtils.delete(newObj, ...keys)
				return newObj;
			};
			BDFDB.ObjectUtils.delete = function (obj, ...keys) {
				if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) delete obj[key];
			};
			BDFDB.ObjectUtils.sort = function (obj, sort, except) {
				if (!BDFDB.ObjectUtils.is(obj)) return {};
				let newObj = {};
				if (sort === undefined || !sort) for (let key of Object.keys(obj).sort()) newObj[key] = obj[key];
				else {
					let values = [];
					for (let key in obj) values.push(obj[key]);
					values = BDFDB.ArrayUtils.keySort(values, sort, except);
					for (let value of values) for (let key in obj) if (BDFDB.equals(value, obj[key])) {
						newObj[key] = value;
						break;
					}
				}
				return newObj;
			};
			BDFDB.ObjectUtils.filter = function (obj, filter, byKey = false) {
				if (!BDFDB.ObjectUtils.is(obj)) return {};
				if (typeof filter != "function") return obj;
				return Object.keys(obj).filter(key => filter(byKey ? key : obj[key])).reduce((newObj, key) => (newObj[key] = obj[key], newObj), {});
			};
			BDFDB.ObjectUtils.map = function (obj, mapFunc) {
				if (!BDFDB.ObjectUtils.is(obj)) return {};
				if (typeof mapFunc != "string" && typeof mapFunc != "function") return obj;
				let newObj = {};
				for (let key in obj) if (BDFDB.ObjectUtils.is(obj[key])) newObj[key] = typeof mapFunc == "string" ? obj[key][mapFunc] : mapFunc(obj[key], key);
				return newObj;
			};
			BDFDB.ObjectUtils.toArray = function (obj) {
				if (!BDFDB.ObjectUtils.is(obj)) return [];
				return Object.entries(obj).map(n => n[1]);
			};
			BDFDB.ObjectUtils.deepAssign = function (obj, ...objs) {
				if (!objs.length) return obj;
				let nextObj = objs.shift();
				if (BDFDB.ObjectUtils.is(obj) && BDFDB.ObjectUtils.is(nextObj)) {
					for (let key in nextObj) {
						if (BDFDB.ObjectUtils.is(nextObj[key])) {
							if (!obj[key]) Object.assign(obj, {[key]:{}});
							BDFDB.ObjectUtils.deepAssign(obj[key], nextObj[key]);
						}
						else Object.assign(obj, {[key]:nextObj[key]});
					}
				}
				return BDFDB.ObjectUtils.deepAssign(obj, ...objs);
			};
			BDFDB.ObjectUtils.isEmpty = function (obj) {
				return !BDFDB.ObjectUtils.is(obj) || Object.getOwnPropertyNames(obj).length == 0;
			};
			BDFDB.ObjectUtils.copy = function (obj) {
				if (!BDFDB.ObjectUtils.is(obj)) return obj;
				let copy = {};
				for (let key of Object.getOwnPropertyNames(obj)) copy[key] = obj[key];
				for (let key of Reflect.ownKeys(obj.constructor.prototype)) if (!copy[key] && obj[key] !== undefined) copy[key] = obj[key];
				return copy;
			};

			BDFDB.ArrayUtils = {};
			BDFDB.ArrayUtils.is = function (array) {
				return array && Array.isArray(array);
			};
			BDFDB.ArrayUtils.sum = function (array) {
				return Array.isArray(array) ? array.reduce((total, num) => total + Math.round(num), 0) : 0;
			};
			BDFDB.ArrayUtils.keySort = function (array, key, except) {
				if (!BDFDB.ArrayUtils.is(array)) return [];
				if (key == null) return array;
				if (except === undefined) except = null;
				return array.sort((x, y) => {
					let xValue = x[key], yValue = y[key];
					if (xValue !== except) return xValue < yValue ? -1 : xValue > yValue ? 1 : 0;
				});
			};
			BDFDB.ArrayUtils.numSort = function (array) {
				return array.sort((x, y) => (x < y ? -1 : x > y ? 1 : 0));
			};
			BDFDB.ArrayUtils.includes = function (array, ...values) {
				if (!BDFDB.ArrayUtils.is(array)) return null;
				if (!array.length) return false;
				let all = values.pop();
				if (typeof all != "boolean") {
					values.push(all);
					all = true;
				}
				if (!values.length) return false;
				let contained = undefined;
				for (let v of values) {
					if (contained === undefined) contained = all;
					if (all && !array.includes(v)) contained = false;
					if (!all && array.includes(v)) contained = true;
				}
				return contained;
			};
			BDFDB.ArrayUtils.remove = function (array, value, all = false) {
				if (!BDFDB.ArrayUtils.is(array)) return [];
				if (!array.includes(value)) return array;
				if (!all) array.splice(array.indexOf(value), 1);
				else while (array.indexOf(value) > -1) array.splice(array.indexOf(value), 1);
				return array;
			};
			BDFDB.ArrayUtils.removeCopies = function (array) {
				if (!BDFDB.ArrayUtils.is(array)) return [];
				return [...new Set(array)];
			};
			BDFDB.ArrayUtils.getAllIndexes = function (array, value) {
				if (!BDFDB.ArrayUtils.is(array) && typeof array != "string") return [];
				var indexes = [], index = -1;
				while ((index = array.indexOf(value, index + 1)) !== -1) indexes.push(index);
				return indexes;
			};

			BDFDB.BDUtils = {};
			BDFDB.BDUtils.getPluginsFolder = function () {
				if (BdApi && BdApi.Plugins && BdApi.Plugins.folder && typeof BdApi.Plugins.folder == "string") return BdApi.Plugins.folder;
				else if (Internal.LibraryRequires.process.env.BETTERDISCORD_DATA_PATH) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.BETTERDISCORD_DATA_PATH, "plugins/");
				else if (Internal.LibraryRequires.process.env.injDir) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.injDir, "plugins/");
				else switch (Internal.LibraryRequires.process.platform) {
					case "win32":
						return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.appdata, "BetterDiscord/plugins/");
					case "darwin":
						return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.HOME, "Library/Preferences/BetterDiscord/plugins/");
					default:
						if (Internal.LibraryRequires.process.env.XDG_CONFIG_HOME) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.XDG_CONFIG_HOME, "BetterDiscord/plugins/");
						else if (Internal.LibraryRequires.process.env.HOME) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.HOME, ".config/BetterDiscord/plugins/");
						else return "";
					}
			};
			BDFDB.BDUtils.getThemesFolder = function () {
				if (BdApi && BdApi.Themes && BdApi.Themes.folder && typeof BdApi.Themes.folder == "string") return BdApi.Themes.folder;
				else if (Internal.LibraryRequires.process.env.BETTERDISCORD_DATA_PATH) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.BETTERDISCORD_DATA_PATH, "themes/");
				else if (Internal.LibraryRequires.process.env.injDir) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.injDir, "plugins/");
				else switch (Internal.LibraryRequires.process.platform) {
					case "win32": 
						return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.appdata, "BetterDiscord/themes/");
					case "darwin": 
						return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.HOME, "Library/Preferences/BetterDiscord/themes/");
					default:
						if (Internal.LibraryRequires.process.env.XDG_CONFIG_HOME) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.XDG_CONFIG_HOME, "BetterDiscord/themes/");
						else if (Internal.LibraryRequires.process.env.HOME) return Internal.LibraryRequires.path.resolve(Internal.LibraryRequires.process.env.HOME, ".config/BetterDiscord/themes/");
						else return "";
					}
			};
			BDFDB.BDUtils.isPluginEnabled = function (pluginName) {
				if (BdApi && BdApi.Plugins && typeof BdApi.Plugins.isEnabled == "function") return BdApi.Plugins.isEnabled(pluginName);
			};
			BDFDB.BDUtils.reloadPlugin = function (pluginName) {
				if (BdApi && BdApi.Plugins && typeof BdApi.Plugins.reload == "function") BdApi.Plugins.reload(pluginName);
			};
			BDFDB.BDUtils.enablePlugin = function (pluginName) {
				if (BdApi && BdApi.Plugins && typeof BdApi.Plugins.enable == "function") BdApi.Plugins.enable(pluginName);
			};
			BDFDB.BDUtils.disablePlugin = function (pluginName) {
				if (BdApi && BdApi.Plugins && typeof BdApi.Plugins.disable == "function") BdApi.Plugins.disable(pluginName);
			};
			BDFDB.BDUtils.getPlugin = function (pluginName, hasToBeEnabled = false, overHead = false) {
				if (BdApi && !hasToBeEnabled || BDFDB.BDUtils.isPluginEnabled(pluginName) && BdApi.Plugins && typeof BdApi.Plugins.get == "function") {
					let plugin = BdApi.Plugins.get(pluginName);
					if (!plugin) return null;
					if (overHead) return plugin.filename && plugin.exports && plugin.instance ? plugin : {filename: Internal.LibraryRequires.fs.existsSync(Internal.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), `${pluginName}.plugin.js`)) ? `${pluginName}.plugin.js` : null, id: pluginName, name: pluginName, plugin: plugin};
					else return plugin.filename && plugin.exports && plugin.instance ? plugin.instance : plugin;
				}
				return null;
			};
			BDFDB.BDUtils.isThemeEnabled = function (themeName) {
				if (BdApi && BdApi.Themes && typeof BdApi.Themes.isEnabled == "function") return BdApi.Themes.isEnabled(themeName);
			};
			BDFDB.BDUtils.enableTheme = function (themeName) {
				if (BdApi && BdApi.Themes && typeof BdApi.Themes.enable == "function") BdApi.Themes.enable(themeName);
			};
			BDFDB.BDUtils.disableTheme = function (themeName) {
				if (BdApi && BdApi.Themes && typeof BdApi.Themes.disable == "function") BdApi.Themes.disable(themeName);
			};
			BDFDB.BDUtils.getTheme = function (themeName, hasToBeEnabled = false) {
				if (BdApi && !hasToBeEnabled || BDFDB.BDUtils.isThemeEnabled(themeName) && BdApi.Themes && typeof BdApi.Themes.get == "function") return BdApi.Themes.get(themeName);
				return null;
			};
			BDFDB.BDUtils.settingsIds = {
				automaticLoading: "settings.addons.autoReload",
				coloredText: "settings.appearance.coloredText",
				normalizedClasses: "settings.general.classNormalizer",
				showToasts: "settings.general.showToasts"
			};
			BDFDB.BDUtils.toggleSettings = function (key, state) {
				if (BdApi && typeof key == "string") {
					let path = key.split(".");
					let currentState = BDFDB.BDUtils.getSettings(key);
					if (state === true) {
						if (currentState === false && typeof BdApi.enableSetting == "function") BdApi.enableSetting(...path);
					}
					else if (state === false) {
						if (currentState === true && typeof BdApi.disableSetting == "function") BdApi.disableSetting(...path);
					}
					else if (currentState === true || currentState === false) BDFDB.BDUtils.toggleSettings(key, !currentState);
				}
			};
			BDFDB.BDUtils.getSettings = function (key) {
				if (!BdApi) return {};
				if (typeof key == "string") return typeof BdApi.isSettingEnabled == "function" && BdApi.isSettingEnabled(...key.split("."));
				else return BDFDB.ArrayUtils.is(BdApi.settings) ? BdApi.settings.map(n => n.settings.map(m => m.settings.map(l => ({id: [n.id, m.id, l.id].join("."), value: l.value})))).flat(10).reduce((newObj, setting) => (newObj[setting.id] = setting.value, newObj), {}) : {};
			};
			BDFDB.BDUtils.getSettingsProperty = function (property, key) {
				if (!BdApi || !BDFDB.ArrayUtils.is(BdApi.settings)) return key ? "" : {};
				else {
					let settingsMap = BdApi.settings.map(n => n.settings.map(m => m.settings.map(l => ({id: [n.id, m.id, l.id].join("."), value: l[property]})))).flat(10).reduce((newObj, setting) => (newObj[setting.id] = setting.value, newObj), {});
					return key ? (settingsMap[key] != null ? settingsMap[key] : "") : "";
				}
			};
			
			const cssFileName = "0BDFDB.raw.css", dataFileName = "0BDFDB.data.json";
			const cssFilePath = path.join(BDFDB.BDUtils.getPluginsFolder(), cssFileName), dataFilePath = path.join(BDFDB.BDUtils.getPluginsFolder(), dataFileName);
			BDFDB.PluginUtils = {};
			BDFDB.PluginUtils.buildPlugin = function (changeLog) {
				return [Plugin(changeLog), BDFDB];
			};
			BDFDB.PluginUtils.load = function (plugin) {
				if (!PluginStores.updateData.timeouts.includes(plugin.name)) {
					PluginStores.updateData.timeouts.push(plugin.name);
					const url = Internal.getPluginURL(plugin);

					PluginStores.updateData.plugins[url] = {name: plugin.name, raw: url, version: plugin.version};
					
					BDFDB.PluginUtils.checkUpdate(plugin.name, url);
					
					if (plugin.changeLog && !BDFDB.ObjectUtils.isEmpty(plugin.changeLog) && typeof plugin.getSettingsPanel != "function") plugin.getSettingsPanel = _ => BDFDB.PluginUtils.createSettingsPanel(plugin, {
						children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.MessagesPopoutComponents.EmptyState, {
							msg: "No Settings available for this Plugin",
							image: BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themelight ? "/assets/9b0d90147f7fab54f00dd193fe7f85cd.svg" : "/assets/308e587f3a68412f137f7317206e92c2.svg"
						})
					});
					
					if (!PluginStores.updateData.interval) PluginStores.updateData.interval = BDFDB.TimeUtils.interval(_ => {
						BDFDB.PluginUtils.checkAllUpdates();
					}, 1000*60*60*4);
					
					BDFDB.TimeUtils.timeout(_ => BDFDB.ArrayUtils.remove(PluginStores.updateData.timeouts, plugin.name, true), 30000);
				}
			};
			BDFDB.PluginUtils.init = function (plugin) {
				BDFDB.PluginUtils.load(plugin);
				
				plugin.settings = BDFDB.DataUtils.get(plugin);
				
				BDFDB.LogUtils.log(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", ""), plugin);
				if (Internal.settings.general.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", `${plugin.name} v${plugin.version}`), {
					disableInteractions: true,
					barColor: BDFDB.DiscordConstants.ColorsCSS.STATUS_POSITIVE
				});
				
				if (plugin.css) BDFDB.DOMUtils.appendLocalStyle(plugin.name, plugin.css);
				
				BDFDB.PatchUtils.unpatch(plugin);
				Internal.addModulePatches(plugin);
				Internal.addContextPatches(plugin);

				BDFDB.PluginUtils.translate(plugin);

				BDFDB.PluginUtils.checkChangeLog(plugin);
			};
			BDFDB.PluginUtils.clear = function (plugin) {
				BDFDB.LogUtils.log(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_stopped", ""), plugin);
				if (Internal.settings.general.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_stopped", `${plugin.name} v${plugin.version}`), {
					disableInteractions: true,
					barColor: BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER
				});
				
				const url = Internal.getPluginURL(plugin);

				BDFDB.PluginUtils.cleanUp(plugin);
				
				for (const modal of document.querySelectorAll(`.${plugin.name}-modal, .${plugin.name.toLowerCase()}-modal, .${plugin.name}-settingsmodal, .${plugin.name.toLowerCase()}-settingsmodal`)) {
					const closeButton = modal.querySelector(BDFDB.dotCN.modalclose);
					if (closeButton) closeButton.click();
				}
				
				delete Cache.data[plugin.name]
				delete PluginStores.updateData.plugins[url];
			};
			BDFDB.PluginUtils.translate = function (plugin) {
				if (typeof plugin.setLabelsByLanguage == "function" || typeof plugin.changeLanguageStrings == "function") {
					const translate = _ => {
						if (typeof plugin.setLabelsByLanguage == "function") plugin.labels = plugin.setLabelsByLanguage();
						if (typeof plugin.changeLanguageStrings == "function") plugin.changeLanguageStrings();
					};
					if (BDFDB.DiscordUtils.getLanguage()) translate();
					else BDFDB.TimeUtils.interval(interval => {
						if (BDFDB.DiscordUtils.getLanguage()) {
							BDFDB.TimeUtils.clear(interval);
							translate();
						}
					}, 100);
				}
			};
			BDFDB.PluginUtils.cleanUp = function (plugin) {
				BDFDB.TimeUtils.suppress(_ => {
					if (!BDFDB.ObjectUtils.is(plugin)) return;
					if (plugin == window.BDFDB_Global) {
						plugin = BDFDB;
						let updateNotice = BDFDB.dotCN && document.querySelector(BDFDB.dotCN.noticeupdate);
						if (updateNotice) updateNotice.close();
						BDFDB.TimeUtils.clear(PluginStores && PluginStores.updateData && PluginStores.updateData.interval);
						delete window.BDFDB_Global.loaded;
						if (PluginStores) BDFDB.TimeUtils.interval((interval, count) => {
							if (count > 60 || window.BDFDB_Global.loaded) BDFDB.TimeUtils.clear(interval);
							if (window.BDFDB_Global.loaded) for (let pluginName in BDFDB.ObjectUtils.sort(PluginStores.loaded)) BDFDB.TimeUtils.timeout(_ => {
								if (PluginStores.loaded[pluginName].started) BDFDB.BDUtils.reloadPlugin(pluginName);
							});
						}, 1000);
					}
					if (BDFDB.DOMUtils && BDFDB.DOMUtils.removeLocalStyle) BDFDB.DOMUtils.removeLocalStyle(plugin.name);
					if (BDFDB.ListenerUtils && BDFDB.ListenerUtils.remove) BDFDB.ListenerUtils.remove(plugin);
					if (BDFDB.ListenerUtils && BDFDB.ListenerUtils.removeGlobal) BDFDB.ListenerUtils.removeGlobal(plugin);
					if (BDFDB.StoreChangeUtils && BDFDB.StoreChangeUtils.remove) BDFDB.StoreChangeUtils.remove(plugin);
					if (BDFDB.PatchUtils && BDFDB.PatchUtils.unpatch) BDFDB.PatchUtils.unpatch(plugin);
					
					for (const patchType in PluginStores.modulePatches) {
						for (const type in PluginStores.modulePatches[patchType]) {
							for (const priority in PluginStores.modulePatches[patchType][type]) BDFDB.ArrayUtils.remove(PluginStores.modulePatches[patchType][type][priority], plugin, true);
							if (!PluginStores.modulePatches[patchType][type].flat(10).length) delete PluginStores.modulePatches[patchType][type];
						}
						if (BDFDB.ObjectUtils.isEmpty(PluginStores.modulePatches[patchType])) delete PluginStores.modulePatches[patchType];
					}
				}, "Failed to clean up Plugin!", plugin)();
			};
			BDFDB.PluginUtils.checkUpdate = function (pluginName, url) {
				if (pluginName && url && Internal.settings.general.checkForUpdates && PluginStores.updateData.plugins[url]) return new Promise(callback => {
					requestFunction(url, {timeout: 60000}, (error, response, body) => {
						if (error || !PluginStores.updateData.plugins[url]) return callback(null);
						let newName = (body.match(/"name"\s*:\s*"([^"]+)"/) || [])[1] || pluginName;
						let newVersion = (body.match(/@version ([0-9]+\.[0-9]+\.[0-9]+)|['"]([0-9]+\.[0-9]+\.[0-9]+)['"]/i) || []).filter(n => n)[1];
						if (!newVersion) return callback(null);
						if (BDFDB.NumberUtils.compareVersions(newVersion, PluginStores.updateData.plugins[url].version)) {
							if (PluginStores.updateData.plugins[url]) PluginStores.updateData.plugins[url].outdated = true;
							BDFDB.PluginUtils.showUpdateNotice(pluginName, url);
							return callback(1);
						}
						else {
							BDFDB.PluginUtils.removeUpdateNotice(pluginName);
							return callback(0);
						}
					});
				});
				return new Promise(callback => callback(null));
			};
			BDFDB.PluginUtils.checkAllUpdates = function () {
				return new Promise(callback => {
					let finished = 0, amount = 0;
					for (let url in PluginStores.updateData.plugins) {
						let plugin = PluginStores.updateData.plugins[url];
						if (plugin) BDFDB.PluginUtils.checkUpdate(plugin.name, plugin.raw).then(state => {
							finished++;
							if (state == 1) amount++;
							if (finished >= Object.keys(PluginStores.updateData.plugins).length) callback(amount);
						});
					}
				});
			};
			BDFDB.PluginUtils.hasUpdateCheck = function (url) {
				if (!url || typeof url != "string") return false;
				let updateStore = Object.assign({}, window.PluginUpdates && window.PluginUpdates.plugins, PluginStores.updateData.plugins);
				if (updateStore[url]) return true;
				else {
					let temp = url.replace("//raw.githubusercontent.com", "//").split("/");
					let gitName = temp.splice(3, 1);
					temp.splice(4, 1);
					temp.splice(2, 1, gitName + ".github.io");
					let pagesUrl = temp.join("/");
					return !!updateStore[pagesUrl];
				}
			};
			BDFDB.PluginUtils.showUpdateNotice = function (pluginName, url) {
				if (!pluginName || !url) return;
				let updateNotice = document.querySelector(BDFDB.dotCN.noticeupdate);
				if (!updateNotice) {
					let vanishObserver = new MutationObserver(changes => {
						if (!document.contains(updateNotice)) {
							if (updateNotice && updateNotice.querySelector(BDFDB.dotCN.noticeupdateentry)) {
								let layers = document.querySelector(BDFDB.dotCN.layers) || document.querySelector(BDFDB.dotCN.appmount);
								if (layers) layers.parentElement.insertBefore(updateNotice, layers);
							}
							else vanishObserver.disconnect();
						}
						else if (document.contains(updateNotice) && !updateNotice.querySelector(BDFDB.dotCNC.noticeupdateentry + BDFDB.dotCN.noticebutton)) vanishObserver.disconnect();
					});
					vanishObserver.observe(document.body, {childList: true, subtree: true});
					updateNotice = BDFDB.NotificationUtils.notice(`${BDFDB.LanguageUtils.LibraryStrings.update_notice_update}&nbsp;&nbsp;&nbsp;&nbsp;<div class="${BDFDB.disCN.noticeupdateentries}"></div>`, {
						type: "info",
						className: BDFDB.disCN.noticeupdate,
						html: true,
						customIcon: `<svg width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M 15.46875 0.859375 C 15.772992 1.030675 16.059675 1.2229406 16.326172 1.4316406 C 17.134815 2.0640406 17.768634 2.8677594 18.208984 3.8183594 C 18.665347 4.8050594 18.913286 5.9512625 18.945312 7.2265625 L 18.945312 7.2421875 L 18.945312 7.2597656 L 18.945312 16.753906 L 18.945312 16.769531 L 18.945312 16.785156 C 18.914433 18.060356 18.666491 19.206759 18.208984 20.193359 C 17.768634 21.144059 17.135961 21.947578 16.326172 22.580078 C 16.06768 22.782278 15.790044 22.967366 15.496094 23.134766 L 16.326172 23.134766 C 20.285895 23.158766 24 20.930212 24 15.820312 L 24 8.3535156 C 24.021728 3.1431156 20.305428 0.86132812 16.345703 0.86132812 L 15.46875 0.859375 z M 0 0.8671875 L 0 10.064453 L 4.4492188 15.191406 L 4.4492188 5.4394531 L 8.4394531 5.4394531 C 11.753741 5.4394531 11.753741 9.8828125 8.4394531 9.8828125 L 7.0234375 9.8828125 L 7.0234375 14.126953 L 8.4394531 14.126953 C 11.753741 14.126953 11.753741 18.568359 8.4394531 18.568359 L 0 18.568359 L 0 23.138672 L 8.3457031 23.138672 C 12.647637 23.138672 15.987145 21.3021 16.105469 16.75 C 16.105469 14.6555 15.567688 13.090453 14.621094 12.001953 C 15.567688 10.914853 16.105469 9.3502594 16.105469 7.2558594 C 15.988351 2.7036594 12.648845 0.8671875 8.3457031 0.8671875 L 0 0.8671875 z"/></svg>`,
						buttons: [{
							className: BDFDB.disCN.noticeupdatebuttonall,
							contents: BDFDB.LanguageUtils.LanguageStrings.ALL,
							onClick: _ => {for (let notice of updateNotice.querySelectorAll(BDFDB.dotCN.noticeupdateentry)) notice.click();}
						}],
						onClose: _ => vanishObserver.disconnect()
					});
					updateNotice.style.setProperty("position", "relative", "important");
					updateNotice.style.setProperty("visibility", "visible", "important");
					updateNotice.style.setProperty("opacity", "1", "important");
					updateNotice.style.setProperty("z-index", "100000", "important");
					let reloadButton = updateNotice.querySelector(BDFDB.dotCN.noticeupdatebuttonreload);
					if (reloadButton) BDFDB.DOMUtils.hide(reloadButton);
				}
				if (updateNotice) {
					let updateNoticeList = updateNotice.querySelector(BDFDB.dotCN.noticeupdateentries);
					if (updateNoticeList && !updateNoticeList.querySelector(`#${pluginName}-notice`)) {
						if (updateNoticeList.childElementCount) updateNoticeList.appendChild(BDFDB.DOMUtils.create(`<div class="${BDFDB.disCN.noticeupdateseparator}">, </div>`));
						let updateEntry = BDFDB.DOMUtils.create(`<div class="${BDFDB.disCN.noticeupdateentry}" id="${pluginName}-notice">${pluginName}</div>`);
						updateEntry.addEventListener("click", _ => {
							if (!updateEntry.wasClicked) {
								updateEntry.wasClicked = true;
								BDFDB.PluginUtils.downloadUpdate(pluginName, url);
							}
						});
						updateNoticeList.appendChild(updateEntry);
						if (!updateNoticeList.hasTooltip) {
							updateNoticeList.hasTooltip = true;
							updateNotice.tooltip = BDFDB.TooltipUtils.create(updateNoticeList, BDFDB.LanguageUtils.LibraryStrings.update_notice_click, {
								type: "bottom",
								zIndex: 100001,
								delay: 500,
								onHide: _ => {updateNoticeList.hasTooltip = false;}
							});
						}
					}
				}
			};
			BDFDB.PluginUtils.removeUpdateNotice = function (pluginName, updateNotice = document.querySelector(BDFDB.dotCN.noticeupdate)) {
				if (!pluginName || !updateNotice) return;
				let updateNoticeList = updateNotice.querySelector(BDFDB.dotCN.noticeupdateentries);
				if (updateNoticeList) {
					let noticeEntry = updateNoticeList.querySelector(`#${pluginName}-notice`);
					if (noticeEntry) {
						let nextSibling = noticeEntry.nextSibling;
						let prevSibling = noticeEntry.prevSibling;
						if (nextSibling && BDFDB.DOMUtils.containsClass(nextSibling, BDFDB.disCN.noticeupdateseparator)) nextSibling.remove();
						else if (prevSibling && BDFDB.DOMUtils.containsClass(prevSibling, BDFDB.disCN.noticeupdateseparator)) prevSibling.remove();
						noticeEntry.remove();
					}
					if (!updateNoticeList.childElementCount) {
						let reloadButton = updateNotice.querySelector(BDFDB.dotCN.noticeupdatebuttonreload);
						if (reloadButton) {
							updateNotice.querySelector(BDFDB.dotCN.noticetext).innerText = BDFDB.LanguageUtils.LibraryStrings.update_notice_reload;
							BDFDB.DOMUtils.show(reloadButton);
						}
						else updateNotice.querySelector(BDFDB.dotCN.noticedismiss).click();
					}
				}
			};
			BDFDB.PluginUtils.downloadUpdate = function (pluginName, url) {
				if (pluginName && url) requestFunction(url, {timeout: 60000}, (error, response, body) => {
					if (error) {
						BDFDB.PluginUtils.removeUpdateNotice(pluginName);
						BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_update_failed", pluginName), {
							type: "danger",
							disableInteractions: true
						});
					}
					else {
						let wasEnabled = BDFDB.BDUtils.isPluginEnabled(pluginName);
						let newName = (body.match(/@name ([^"^\n^\t^\t]+)|['"]([^"^\n^\t^\t]+)['"]/i) || []).filter(n => n)[1] || pluginName;
						let newVersion = (body.match(/@version ([0-9]+\.[0-9]+\.[0-9]+)|['"]([0-9]+\.[0-9]+\.[0-9]+)['"]/i) || []).filter(n => n)[1];
						let oldVersion = PluginStores.updateData.plugins[url].version;
						let fileName = pluginName == "BDFDB" ? "0BDFDB" : pluginName;
						let newFileName = newName == "BDFDB" ? "0BDFDB" : newName;
						Internal.LibraryRequires.fs.writeFile(Internal.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), newFileName + ".plugin.js"), body, _ => {
							if (PluginStores.updateData.plugins[url]) PluginStores.updateData.plugins[url].version = newVersion;
							if (fileName != newFileName) {
								Internal.LibraryRequires.fs.unlink(Internal.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), fileName + ".plugin.js"), _ => {});
								let configPath = Internal.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), fileName + ".config.json");
								Internal.LibraryRequires.fs.exists(configPath, exists => {
									if (exists) Internal.LibraryRequires.fs.rename(configPath, Internal.LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), newFileName + ".config.json"), _ => {});
								});
								BDFDB.TimeUtils.timeout(_ => {if (wasEnabled && !BDFDB.BDUtils.isPluginEnabled(newName)) BDFDB.BDUtils.enablePlugin(newName);}, 3000);
							}
							BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_updated", pluginName, "v" + oldVersion, newName, "v" + newVersion), {
								disableInteractions: true
							});
							let updateNotice = document.querySelector(BDFDB.dotCN.noticeupdate);
							if (updateNotice) {
								if (updateNotice.querySelector(BDFDB.dotCN.noticebutton) && !PluginStores.updateData.downloaded.includes(pluginName)) {
									PluginStores.updateData.downloaded.push(pluginName);
								}
								BDFDB.PluginUtils.removeUpdateNotice(pluginName, updateNotice);
							}
						});
					}
				});
			};
			BDFDB.PluginUtils.checkChangeLog = function (plugin) {
				if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(plugin.changeLog) || plugin.changeLog.info) return;
				if (!changeLogs[plugin.name] || BDFDB.NumberUtils.compareVersions(plugin.version, changeLogs[plugin.name])) {
					changeLogs[plugin.name] = plugin.version;
					BDFDB.DataUtils.save(changeLogs, BDFDB, "changeLogs");
					BDFDB.PluginUtils.openChangeLog(plugin);
				}
			};
			BDFDB.PluginUtils.openChangeLog = function (plugin) {
				if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(plugin.changeLog)) return;
				let changeLogEntries = [], headers = {
					added: "New Features",
					fixed: "Bug Fixes",
					improved: "Improvements",
					progress: "Progress"
				};
				for (let type in plugin.changeLog) {
					type = type.toLowerCase();
					if (InternalData.DiscordClasses["changelog" + type]) changeLogEntries.push([
						BDFDB.ReactUtils.createElement("h1", {
							className: BDFDB.disCNS["changelog" + type] + BDFDB.disCN.margintop20,
							style: {"margin-top": !changeLogEntries.length ? 0 : null},
							children: BDFDB.LanguageUtils && BDFDB.LanguageUtils.LibraryStrings && BDFDB.LanguageUtils.LibraryStrings["changelog_" + type] || headers[type]
						}),
						BDFDB.ReactUtils.createElement("ul", {
							children: Object.keys(plugin.changeLog[type]).map(key => BDFDB.ReactUtils.createElement("li", {
								children: [
									BDFDB.ReactUtils.createElement("strong", {children: key}),
									plugin.changeLog[type][key] ? `: ${plugin.changeLog[type][key]}.` : ""
								]
							}))
						})
					]);
				}
				if (changeLogEntries.length) BDFDB.ModalUtils.open(plugin, {
					header: `${plugin.name} ${BDFDB.LanguageUtils.LanguageStrings.CHANGE_LOG}`,
					subHeader: `Version ${plugin.version}`,
					className: BDFDB.disCN.modalchangelogmodal,
					contentClassName: BDFDB.disCNS.changelogcontainer + BDFDB.disCN.modalminicontent,
					footerDirection: Internal.LibraryComponents.Flex.Direction.HORIZONTAL,
					children: changeLogEntries.flat(10).filter(n => n),
					footerChildren: (plugin == BDFDB || plugin == this || PluginStores.loaded[plugin.name] && PluginStores.loaded[plugin.name] == plugin && plugin.author == "DevilBro") && BDFDB.ReactUtils.createElement("div", {
						className: BDFDB.disCN.changelogfooter,
						children: [{
							href: "https://www.paypal.me/MircoWittrien",
							name: "PayPal",
							icon: "PAYPAL"
						}, {
							href: "https://www.patreon.com/MircoWittrien",
							name: "Patreon",
							icon: "PATREON"
						}, {
							name: BDFDB.LanguageUtils.LibraryStringsFormat("send", "Solana"),
							icon: "PHANTOM",
							onClick: _ => {
								BDFDB.LibraryModules.WindowUtils.copy(InternalData.mySolana);
								BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("clipboard_success", "Phantom Wallet Key"), {
									type: "success"
								});
							}
						}, {
							name: BDFDB.LanguageUtils.LibraryStringsFormat("send", "Ethereum"),
							icon: "METAMASK",
							onClick: _ => {
								BDFDB.LibraryModules.WindowUtils.copy(InternalData.myEthereum);
								BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("clipboard_success", "MetaMask Wallet Key"), {
									type: "success"
								});
							}
						}].map(data => BDFDB.ReactUtils.createElement(data.href ? Internal.LibraryComponents.Anchor : Internal.LibraryComponents.Clickable, {
							className: BDFDB.disCN.changelogsociallink,
							href: data.href || "",
							onClick: !data.onClick ? (_ => {}) : data.onClick,
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
								text: data.name,
								children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
									name: Internal.LibraryComponents.SvgIcon.Names[data.icon],
									width: 16,
									height: 16
								})
							})
						})).concat(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
							size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
							children: BDFDB.LanguageUtils.LibraryStrings.donate_message
						}))
					})
				});
			};
			BDFDB.PluginUtils.addLoadingIcon = function (icon) {
				if (!Node.prototype.isPrototypeOf(icon)) return;
				let app = document.querySelector(BDFDB.dotCN.app);
				if (!app) return;
				BDFDB.DOMUtils.addClass(icon, BDFDB.disCN.loadingicon);
				let loadingIconWrapper = document.querySelector(BDFDB.dotCN.app + ">" + BDFDB.dotCN.loadingiconwrapper);
				if (!loadingIconWrapper) {
					loadingIconWrapper = BDFDB.DOMUtils.create(`<div class="${BDFDB.disCN.loadingiconwrapper}"></div>`);
					app.appendChild(loadingIconWrapper);
					let killObserver = new MutationObserver(changes => {
						if (!loadingIconWrapper.firstElementChild) {
							killObserver.disconnect();
							BDFDB.DOMUtils.remove(loadingIconWrapper);
						}
					});
					killObserver.observe(loadingIconWrapper, {childList: true});
				}
				loadingIconWrapper.appendChild(icon);
			};
			BDFDB.PluginUtils.createSettingsPanel = function (addon, props) {
				if (!window.BDFDB_Global.loaded) return BdApi.React.createElement("div", {
					style: {"color": BDFDB.DiscordConstants.ColorsCSS.HEADER_SECONDARY, "white-space": "pre-wrap"},
					children: [
						"Could not initiate BDFDB Library Plugin! Can not create Settings Panel!\n\nTry deleting the ",
						BdApi.React.createElement("strong", {children: dataFileName}),
						" File in your ",
						BdApi.React.createElement("strong", {children: BDFDB.BDUtils.getPluginsFolder()}),
						"\nDirectory and reload Discord afterwards!"
					]
				});
				addon = addon == BDFDB && Internal || addon;
				if (!BDFDB.ObjectUtils.is(addon)) return;
				let settingsProps = props;
				if (settingsProps && !BDFDB.ObjectUtils.is(settingsProps) && (BDFDB.ReactUtils.isValidElement(settingsProps) || BDFDB.ArrayUtils.is(settingsProps))) settingsProps = {
					children: settingsProps
				};
				return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsPanel, Object.assign({
					addon: addon,
					collapseStates: settingsProps && settingsProps.collapseStates
				}, settingsProps));
			};
			BDFDB.PluginUtils.refreshSettingsPanel = function (plugin, settingsPanel, ...args) {
				if (BDFDB.ObjectUtils.is(plugin)) {
					if (settingsPanel && settingsPanel.props && BDFDB.ObjectUtils.is(settingsPanel.props._instance)) {
						settingsPanel.props._instance.props = Object.assign({}, settingsPanel.props._instance.props, ...args);
						BDFDB.ReactUtils.forceUpdate(settingsPanel.props._instance);
					}
					else if (typeof plugin.getSettingsPanel == "function" && Node.prototype.isPrototypeOf(settingsPanel) && settingsPanel.parentElement) {
						settingsPanel.parentElement.appendChild(plugin.getSettingsPanel(...args));
						settingsPanel.remove();
					}
				}
			};

			window.BDFDB_Global = Object.assign({
				started: true,
				loading: true,
				PluginUtils: {
					buildPlugin: BDFDB.PluginUtils.buildPlugin,
					cleanUp: BDFDB.PluginUtils.cleanUp
				}
			}, window.BDFDB_Global);
			
			Internal.writeConfig = function (plugin, path, config) {
				let allData = {};
				try {allData = JSON.parse(fs.readFileSync(path));}
				catch (err) {allData = {};}
				try {fs.writeFileSync(path, JSON.stringify(Object.assign({}, allData, {[Internal.shouldSyncConfig(plugin) ? "all" : BDFDB.UserUtils.me.id]: config}), null, "	"));}
				catch (err) {}
			};
			Internal.readConfig = function (plugin, path) {
				let sync = Internal.shouldSyncConfig(plugin);
				try {
					let config = JSON.parse(fs.readFileSync(path));
					if (config && Object.keys(config).some(n => !(n == "all" || parseInt(n)))) {
						config = {[Internal.shouldSyncConfig(plugin) ? "all" : BDFDB.UserUtils.me.id]: config};
						try {fs.writeFileSync(path, JSON.stringify(config, null, "	"));}
						catch (err) {}
					}
					return config && config[sync ? "all" : BDFDB.UserUtils.me.id] || {};
				}
				catch (err) {return {};}
			};
			Internal.shouldSyncConfig = function (plugin) {
				return plugin.neverSyncData !== undefined ? !plugin.neverSyncData : (plugin.forceSyncData || Internal.settings.general.shareData);
			};
			
			BDFDB.DataUtils = {};
			BDFDB.DataUtils.save = function (data, plugin, key, id) {
				plugin = plugin == BDFDB && Internal || plugin;
				let pluginName = typeof plugin === "string" ? plugin : plugin.name;
				let fileName = pluginName == "BDFDB" ? "0BDFDB" : pluginName;
				let configPath = path.join(BDFDB.BDUtils.getPluginsFolder(), fileName + ".config.json");
				
				let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (Internal.readConfig(plugin, configPath) || {});
				
				if (key === undefined) config = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data;
				else {
					if (id === undefined) config[key] = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data;
					else {
						if (!BDFDB.ObjectUtils.is(config[key])) config[key] = {};
						config[key][id] = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data;
					}
				}
				
				let configIsObject = BDFDB.ObjectUtils.is(config);
				if (key !== undefined && configIsObject && BDFDB.ObjectUtils.is(config[key]) && BDFDB.ObjectUtils.isEmpty(config[key])) delete config[key];
				if (BDFDB.ObjectUtils.isEmpty(config)) {
					delete Cache.data[pluginName];
					if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
				}
				else {
					if (configIsObject) config = BDFDB.ObjectUtils.sort(config);
					Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config;
					Internal.writeConfig(plugin, configPath, config);
				}
			};

			BDFDB.DataUtils.load = function (plugin, key, id) {
				plugin = plugin == BDFDB && Internal || plugin;
				let pluginName = typeof plugin === "string" ? plugin : plugin.name;
				let fileName = pluginName == "BDFDB" ? "0BDFDB" : pluginName;
				let configPath = path.join(BDFDB.BDUtils.getPluginsFolder(), fileName + ".config.json");
				
				let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (Internal.readConfig(plugin, configPath) || {});
				let configIsObject = BDFDB.ObjectUtils.is(config);
				Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config;
				
				if (key === undefined) return config;
				else {
					let keyData = configIsObject ? (BDFDB.ObjectUtils.is(config[key]) || config[key] === undefined ? BDFDB.ObjectUtils.deepAssign({}, config[key]) : config[key]) : null;
					if (id === undefined) return keyData;
					else return !BDFDB.ObjectUtils.is(keyData) || keyData[id] === undefined ? null : keyData[id];
				}
			};
			BDFDB.DataUtils.remove = function (plugin, key, id) {
				plugin = plugin == BDFDB && Internal || plugin;
				let pluginName = typeof plugin === "string" ? plugin : plugin.name;
				let fileName = pluginName == "BDFDB" ? "0BDFDB" : pluginName;
				let configPath = path.join(BDFDB.BDUtils.getPluginsFolder(), fileName + ".config.json");
				
				let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (Internal.readConfig(plugin, configPath) || {});
				let configIsObject = BDFDB.ObjectUtils.is(config);
				
				if (key === undefined || !configIsObject) config = {};
				else {
					if (id === undefined) delete config[key];
					else if (BDFDB.ObjectUtils.is(config[key])) delete config[key][id];
				}
				
				if (BDFDB.ObjectUtils.is(config[key]) && BDFDB.ObjectUtils.isEmpty(config[key])) delete config[key];
				if (BDFDB.ObjectUtils.isEmpty(config)) {
					delete Cache.data[pluginName];
					if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
				}
				else {
					if (configIsObject) config = BDFDB.ObjectUtils.sort(config);
					Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config;
					Internal.writeConfig(plugin, configPath, config);
				}
			};
			BDFDB.DataUtils.get = function (plugin, key, id) {
				plugin = plugin == BDFDB && Internal || plugin;
				plugin = typeof plugin == "string" ? BDFDB.BDUtils.getPlugin(plugin) : plugin;
				const defaults = plugin && plugin.defaults;
				if (!BDFDB.ObjectUtils.is(defaults) || key && !BDFDB.ObjectUtils.is(defaults[key])) return id === undefined ? {} : null;
				let oldC = BDFDB.DataUtils.load(plugin), newC = {}, update = false;
				const checkLayer = (i, j) => {
					let isObj = BDFDB.ObjectUtils.is(defaults[i][j].value);
					if (!newC[i]) newC[i] = {};
					if (oldC[i] == null || oldC[i][j] == null || isObj && (!BDFDB.ObjectUtils.is(oldC[i][j]) || Object.keys(defaults[i][j].value).some(n => defaults[i][j].value[n] != null && !BDFDB.sameProto(defaults[i][j].value[n], oldC[i][j][n])))) {
						newC[i][j] = isObj ? BDFDB.ObjectUtils.deepAssign({}, defaults[i][j].value) : defaults[i][j].value;
						update = true;
					}
					else newC[i][j] = oldC[i][j];
				};
				if (key) {for (let j in defaults[key]) checkLayer(key, j);}
				else {for (let i in defaults) if (BDFDB.ObjectUtils.is(defaults[i])) for (let j in defaults[i]) checkLayer(i, j);}
				if (update) BDFDB.DataUtils.save(Object.assign({}, oldC, newC), plugin);
				
				if (key === undefined) return newC;
				else if (id === undefined) return newC[key] === undefined ? {} : newC[key];
				else return newC[key] === undefined || newC[key][id] === undefined ? null : newC[key][id];
			};
			let InternalData, libHashes = {}, oldLibHashes = BDFDB.DataUtils.load(BDFDB, "hashes"), libraryCSS;
			
			const getBackup = (fileName, path) => {
				return {backup: fs.existsSync(path) && (fs.readFileSync(path) || "").toString(), hashIsSame: libHashes[fileName] && oldLibHashes[fileName] && libHashes[fileName] == oldLibHashes[fileName]};
			};
			const requestLibraryHashes = tryAgain => {
				requestFunction("https://api.github.com/repos/mwittrien/BetterDiscordAddons/contents/Library/_res/", {timeout: 60000}, (e, r, b) => {
					if ((e || !b || r.statusCode != 200) && tryAgain) return BDFDB.TimeUtils.timeout(_ => requestLibraryHashes(), 10000);
					else {
						try {
							b = JSON.parse(b);
							libHashes[cssFileName] = (b.find(n => n && n.name == cssFileName) || {}).sha;
							libHashes[dataFileName] = (b.find(n => n && n.name == dataFileName) || {}).sha;
							BDFDB.DataUtils.save(libHashes, BDFDB, "hashes");
						}
						catch (err) {}
						requestLibraryData(true);
					}
				});
			};
			const requestLibraryData = tryAgain => {
				const parseCSS = css => {
					libraryCSS = css;
					
					const backupObj = getBackup(dataFileName, dataFilePath);
					const UserStore = BdApi.Webpack && BdApi.Webpack.getModule && BdApi.Webpack.Filters && BdApi.Webpack.Filters.byKeys && BdApi.Webpack.getModule(BdApi.Webpack.Filters.byKeys("getCurrentUser"));
					if (backupObj.backup && backupObj.hashIsSame || UserStore && UserStore.getCurrentUser().id == "278543574059057154") parseData(backupObj.backup);
					else requestFunction(`https://mwittrien.github.io/BetterDiscordAddons/Library/_res/${dataFileName}`, {timeout: 60000}, (e, r, b) => {
						if ((e || !b || r.statusCode != 200) && tryAgain) return BDFDB.TimeUtils.timeout(_ => requestLibraryData(), 10000);
						if (!e && b && r.statusCode == 200) {
							if (backupObj.backup && backupObj.backup.replace(/\s/g, "") == b.replace(/\s/g, "")) {
								libHashes[dataFileName] = oldLibHashes[dataFileName];
								BDFDB.DataUtils.save(libHashes, BDFDB, "hashes");
							}
							parseData(b, true);
						}
						else parseData(fs.existsSync(dataFilePath) && (fs.readFileSync(dataFilePath) || "").toString());
					});
				};
				const parseData = (dataString, fetched) => {
					try {InternalData = JSON.parse(dataString);}
					catch (err) {
						if (fetched) {
							try {
								dataString = fs.existsSync(dataFilePath) && (fs.readFileSync(dataFilePath) || "").toString();
								InternalData = JSON.parse(dataString);
							}
							catch (err2) {BDFDB.LogUtils.error(["Failed to initiate Library!", "Failed Fetch!", dataString ? "Corrupt Backup." : "No Backup.", , err2]);}
						}
						else BDFDB.LogUtils.error(["Failed to initiate Library!", dataString ? "Corrupt Backup." : "No Backup.", err]);
					}
					if (fetched && dataString) fs.writeFile(dataFilePath, dataString, _ => {});
					
					Internal.getWebModuleReq = function () {
						if (!Internal.getWebModuleReq.req) {
							const id = "BDFDB-WebModules_" + Math.floor(Math.random() * 10000000000000000);
							let req;
							webpackChunkdiscord_app.push([[id], {}, r => {if ("b" in r) req = r;}]);
							delete req.m[id];
							delete req.c[id];
							Internal.getWebModuleReq.req = req;
						}
						return Internal.getWebModuleReq.req;
					};
					
					if (InternalData) loadLibrary();
					else BdApi.UI.alert("Error", "Could not initiate BDFDB Library Plugin. Check your Internet Connection and make sure GitHub isn't blocked by your Network or try disabling your VPN/Proxy.");
				};
				
				const backupObj = getBackup(cssFileName, cssFilePath);
				if (backupObj.backup && backupObj.hashIsSame) parseCSS(backupObj.backup);
				else requestFunction(`https://mwittrien.github.io/BetterDiscordAddons/Library/_res/${cssFileName}`, {timeout: 60000}, (e, r, b) => {
					if ((e || !b || r.statusCode != 200) && tryAgain) return BDFDB.TimeUtils.timeout(_ => requestLibraryData(), 10000);
					if (!e && b && r.statusCode == 200) {
						if (backupObj.backup && backupObj.backup.replace(/\s/g, "") == b.replace(/\s/g, "")) {
							libHashes[cssFileName] = oldLibHashes[cssFileName];
							BDFDB.DataUtils.save(libHashes, BDFDB, "hashes");
						}
						fs.writeFile(cssFilePath, b, _ => {});
						parseCSS(b);
					}
					else parseCSS(fs.existsSync(cssFilePath) && (fs.readFileSync(cssFilePath) || "").toString());
				});
			};
			const loadLibrary = _ => {
				Internal.getPluginURL = function (plugin) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (BDFDB.ObjectUtils.is(plugin)) {
						if (InternalData.PluginUrlMap && InternalData.PluginUrlMap[plugin.name]) return InternalData.PluginUrlMap[plugin.name];
						else if (plugin.updateUrl) return plugin.updateUrl;
						else {
							let name = InternalData.PluginNameMap && InternalData.PluginNameMap[plugin.name] || plugin.name;
							return `https://mwittrien.github.io/BetterDiscordAddons/Plugins/${name}/${name}.plugin.js`;
						}
					}
					else return "";
				};
				
				Internal.findModule = function (type, cacheString, filter, config = {}) {
					if (!BDFDB.ObjectUtils.is(Cache.modules[type])) Cache.modules[type] = {module: {}, export: {}};
					let defaultExport = typeof config.defaultExport != "boolean" ? true : config.defaultExport;
					if (!config.all && defaultExport && Cache.modules[type].export[cacheString]) return Cache.modules[type].export[cacheString];
					else if (!config.all && !defaultExport && Cache.modules[type].module[cacheString]) return Cache.modules[type].module[cacheString];
					else {
						let m = BDFDB.ModuleUtils.find(filter, config);
						if (m) {
							if (!config.all) {
								if (defaultExport) Cache.modules[type].export[cacheString] = m;
								else Cache.modules[type].module[cacheString] = m;
							}
							return m;
						}
						else if (!config.noWarnings) BDFDB.LogUtils.warn(`${cacheString} [${type}] not found in WebModules`);
					}
				};
				Internal.checkModuleStrings = function (module, strings, config = {}) {
					const check = (s1, s2) => {
						s1 = config.ignoreCase ? s1.toString().toLowerCase() : s1.toString();
						return config.hasNot ? s1.indexOf(s2) == -1 : s1.indexOf(s2) > -1;
					};
					return [strings].flat(10).filter(n => typeof n == "string").map(config.ignoreCase ? (n => n.toLowerCase()) : (n => n)).every(string => module && ((typeof module == "function" || typeof module == "string") && (check(module, string) || typeof module.__originalFunction == "function" && check(module.__originalFunction, string)) || typeof module.type == "function" && check(module.type, string) || (typeof module == "function" || typeof module == "object") && module.prototype && Object.keys(module.prototype).filter(n => n.indexOf("render") == 0).some(n => check(module.prototype[n], string))));
				};
				Internal.checkModuleProps = function (module, properties, config = {}) {
					return [properties].flat(10).filter(n => typeof n == "string").every(prop => {
						const value = module[prop];
						return config.hasNot ? value === undefined : (value !== undefined && !(typeof value == "string" && !value));
					});
				};
				Internal.checkModuleProtos = function (module, protoProps, config = {}) {
					return module.prototype && [protoProps].flat(10).filter(n => typeof n == "string").every(prop => {
						const value = module.prototype[prop];
						return config.hasNot ? value === undefined : (value !== undefined && !(typeof value == "string" && !value));
					});
				};
				Internal.getModuleString = function (module) {
					const id = (BDFDB.ModuleUtils.find(m => m == module && m, {defaultExport: false}) || {}).id;
					if (!id) return "";
					const req = Internal.getWebModuleReq();
					return (req.m[id] || "").toString();
				};
				
				BDFDB.ModuleUtils = {};
				BDFDB.ModuleUtils.lazyLoadModuleImports = function (moduleString) {
					return new Promise(callback => {
						if (typeof moduleString !== "string") moduleString = Internal.getModuleString(moduleString);
						if (!moduleString || typeof moduleString !== "string") {
							BDFDB.LogUtils.error("Trying to lazy load Imports but Module is not a String");
							return callback(null);
						}
						let run = true, imports = [], menuIndexes = [];
						while (run) {
							const [matchString, promiseMatch, menuRequest] = moduleString.match(/await .+?(\(.+?\))\.then\(.{1}\.bind\((.+?)\)\)/) ?? [];
							if (!promiseMatch) run = false;
							else {
								imports = imports.concat(promiseMatch.match(/\d+/g)?.map(e => Number(e)));
								menuIndexes.push(menuRequest.match(/\d+/)?.[0]);
								moduleString = moduleString.replace(matchString, "");
							}
						}
						if (!imports.length || !menuIndexes.length) {
							BDFDB.LogUtils.error("Trying to lazy load Imports but could not find Indexes");
							return callback(null);
						}
						const req = Internal.getWebModuleReq();
						Promise.all(BDFDB.ArrayUtils.removeCopies(imports).map(i => req.e(i))).then(_ => Promise.all(BDFDB.ArrayUtils.removeCopies(menuIndexes).map(i => req(i)))).then(callback);
					});
				};
				
				BDFDB.ModuleUtils.find = function (filter, config = {}) {
					let defaultExport = typeof config.defaultExport != "boolean" ? true : config.defaultExport;
					let onlySearchUnloaded = typeof config.onlySearchUnloaded != "boolean" ? false : config.onlySearchUnloaded;
					let all = typeof config.all != "boolean" ? false : config.all;
					const req = Internal.getWebModuleReq();
					const found = [];
					const isSearchable = (m, checkObject) => {
						return m && (checkObject && typeof m == "object" || typeof m == "function") && !m.constructor.toLocaleString().startsWith("function DOMTokenList()") && typeof m.toLocaleString == "function" && m.toLocaleString().indexOf("IntlMessagesProxy") == -1;
					};
					if (!onlySearchUnloaded) for (let i in req.c) if (req.c.hasOwnProperty(i) && req.c[i].exports != window) {
						let m = req.c[i].exports, r = null;
						if (isSearchable(m, true)) {
							if (!!(r = filter(m))) {
								if (all) found.push(defaultExport ? r : req.c[i]);
								else return defaultExport ? r : req.c[i];
							}
							else if (Object.keys(m).length < 400) for (let key of Object.keys(m)) try {
								if (m[key] && isSearchable(m[key], true) && !!(r = filter(m[key]))) {
									if (all) found.push(defaultExport ? r : req.c[i]);
									else return defaultExport ? r : req.c[i];
								}
							} catch (err) {}
						}
						if (config.moduleName && isSearchable(m, true) && isSearchable(m[config.moduleName], true)) {
							if (!!(r = filter(m[config.moduleName]))) {
								if (all) found.push(defaultExport ? r : req.c[i]);
								else return defaultExport ? r : req.c[i];
							}
							else if (m[config.moduleName].type && isSearchable(m[config.moduleName].type, true) && !!(r = filter(m[config.moduleName].type))) {
								if (all) found.push(defaultExport ? r : req.c[i]);
								else return defaultExport ? r : req.c[i];
							}
						}
						if (m && m.__esModule && isSearchable(m.default, true)) {
							if (!!(r = filter(m.default))) {
								if (all) found.push(defaultExport ? r : req.c[i]);
								else return defaultExport ? r : req.c[i];
							}
							else if (isSearchable(m.default.type, true) && !!(r = filter(m.default.type))) {
								if (all) found.push(defaultExport ? r : req.c[i]);
								else return defaultExport ? r : req.c[i];
							}
						}
					}
					for (let i in req.m) if (req.m.hasOwnProperty(i)) {
						let m = req.m[i];
						if (m && isSearchable(m)) {
							if (req.c[i] && isSearchable(req.c[i].exports, true) && (!config.exportsFilter || config.exportsFilter(req.c[i].exports)) && !onlySearchUnloaded && filter(m)) {
								if (all) found.push(defaultExport ? req.c[i].exports : req.c[i]);
								else return defaultExport ? req.c[i].exports : req.c[i];
							}
							if (!req.c[i] && onlySearchUnloaded && filter(m)) {
								const resolved = {}, resolved2 = {};
								m(resolved, resolved2, req);
								const trueResolved = resolved2 && BDFDB.ObjectUtils.isEmpty(resolved2) ? resolved : resolved2;
								if (all) found.push(defaultExport ? trueResolved.exports : trueResolved);
								else return defaultExport ? trueResolved.exports : trueResolved;
							}
						}
					}
					if (all) return found;
				};
				BDFDB.ModuleUtils.findByProperties = function (...properties) {
					properties = properties.flat(10);
					let config = properties.pop();
					if (typeof config == "string") {
						properties.push(config);
						config = {};
					}
					return Internal.findModule("props", JSON.stringify(properties), m => Internal.checkModuleProps(m, properties) && m, config);
				};
				BDFDB.ModuleUtils.findByName = function (name, config = {}) {
					return Internal.findModule("name", JSON.stringify(name), m => m.displayName === name && m || m.render && m.render.displayName === name && m || m.constructor && m.constructor.displayName === name && m || m[name] && m[name].displayName === name && m[name] || typeof m.getName == "function" && m.getName() == name && m, config);
				};
				BDFDB.ModuleUtils.findByString = function (...strings) {
					strings = strings.flat(10);
					let config = strings.pop();
					if (typeof config == "string") {
						strings.push(config);
						config = {};
					}
					return Internal.findModule("string", JSON.stringify(strings), m => Internal.checkModuleStrings(m, strings) && m, config);
				};
				BDFDB.ModuleUtils.findByPrototypes = function (...protoProps) {
					protoProps = protoProps.flat(10);
					let config = protoProps.pop();
					if (typeof config == "string") {
						protoProps.push(config);
						config = {};
					}
					return Internal.findModule("proto", JSON.stringify(protoProps), m => Internal.checkModuleProtos(m, protoProps) && m, config);
				};
				BDFDB.ModuleUtils.findStringObject = function (props, config = {}) {
					let nonProps = [config.nonProps].flat(10).filter(n => n);
					let firstReturn = BDFDB.ModuleUtils.find(m => {
						let amount = Object.keys(m).length;
						return (!config.length || (config.smaller ? amount < config.length : amount == config.length)) && [props].flat(10).every(prop => typeof m[prop] == "string") && (!nonProps.length || nonProps.every(prop => typeof m[prop] == "undefined")) && m;
					}, {all: config.all, defaultExport: config.defaultExport});
					if (!config.all && firstReturn) return firstReturn;
					let secondReturn = BDFDB.ModuleUtils.find(m => {
						if (typeof m != "function") return false;
						let stringified = m.toString().replace(/\s/g, "");
						if (stringified.indexOf(".exports={") == -1 || !(/function\([A-z],[A-z],[A-z]\)\{[A-z]\.[A-z]\([A-z]\.exports=\{/.test(stringified) || /function\([A-z],[A-z],[A-z]\)\{[A-z]\.exports=\{/.test(stringified) || /function\([A-z]\)\{[A-z]\.exports=\{/.test(stringified))) return false;
						let amount = stringified.split(":\"").length - 1;
						return (!config.length || (config.smaller ? amount < config.length : amount == config.length)) && [props].flat(10).every(string => stringified.indexOf(`${string}:`) > -1) && (!nonProps.length || nonProps.every(string => stringified.indexOf(`${string}:`) == -1)) && m;
					}, {onlySearchUnloaded: true, all: config.all, defaultExport: config.defaultExport});
					if (!config.all) return secondReturn;
					return BDFDB.ArrayUtils.removeCopies([firstReturn].concat(secondReturn).flat(10));
				};
				
				const DiscordConstantsObject = BDFDB.ModuleUtils.find(m => {try {
				    if (!m || !Object.keys(m)) return;
				    if ([["CUSTOM_STATUS", "STREAMING", "WATCHING"], ["GUILD_TEXT", "GUILD_FORUM", "GUILD_STORE"], ["THREAD_CREATED", "CHAT_INPUT_COMMAND"]].every(array => Object.keys(m).some(k => {
					if (!m[k]) return false;
					let keys = Object.keys(m[k]);
					if (keys && array.every(n => keys.indexOf(n) > -1)) return true;
				    }))) return m;
				} catch (err) {}});
				if (InternalData.CustomDiscordConstants) DiscordConstants = Object.assign(DiscordConstants, InternalData.CustomDiscordConstants);
				if (DiscordConstantsObject) DiscordConstants = Object.assign(DiscordConstants, DiscordConstantsObject);
				Internal.DiscordConstants = new Proxy(DiscordConstants, {
					get: function (_, item) {
						if (DiscordConstants[item]) return DiscordConstants[item];
						if (!InternalData.DiscordConstants[item]) {
							BDFDB.LogUtils.warn([item, "Object not found in DiscordConstants"]);
							return {};
						}
						if (InternalData.DiscordConstants[item].strings) DiscordConstants[item] = BDFDB.ModuleUtils.findByString(InternalData.DiscordConstants[item].strings);
						else if (InternalData.DiscordConstants[item].props) DiscordConstants[item] = BDFDB.ModuleUtils.findByProperties(InternalData.DiscordConstants[item].props);
						else {
							if (DiscordConstantsObject) DiscordConstants[item] = DiscordConstantsObject[Object.keys(DiscordConstantsObject).find(n => {
								let keys = Object.keys(DiscordConstantsObject[n]);
								if (keys && keys.length < 10000 && InternalData.DiscordConstants[item].every && InternalData.DiscordConstants[item].every(k => keys.indexOf(k) > -1)) return true;
							})];
							if (!DiscordConstants[item]) DiscordConstants[item] = BDFDB.ModuleUtils.findByProperties(InternalData.DiscordConstants[item]);
						}
						if (DiscordConstants[item] && InternalData.DiscordConstants[item].value) DiscordConstants[item] = DiscordConstants[item][InternalData.DiscordConstants[item].value] || DiscordConstants[item];
						return DiscordConstants[item] ? DiscordConstants[item] : {};
					}
				});
				const ColorsCSS = Internal.DiscordConstants.ColorsCSS || {};
				Internal.DiscordConstants.ColorsCSS = new Proxy(ColorsCSS, {
					get: function (_, item) {
						const color = ColorsCSS[item] || ColorsCSS[item.toLowerCase()] || ColorsCSS[item.toUpperCase()];
						return color && color.css || color || "";
					}
				});
				const DiscordColors = Internal.DiscordConstants.Colors || {};
				Internal.DiscordConstants.Colors = new Proxy(DiscordColors, {
					get: function (_, item) {
						const color = DiscordColors[item] || DiscordColors[item.toLowerCase()] || DiscordColors[item.toUpperCase()];
						if (color) return color && color.hex || color || "";
						else {
							const item2 = item + "_500";
							const color2 = DiscordColors[item2] || DiscordColors[item2.toLowerCase()] || DiscordColors[item2.toUpperCase()];
							if (color2) return color2 && color2.hex || color2 || "";
							else {
								const item3 = item.replace(/-/g, "_");
								const color3 = DiscordColors[item3] || DiscordColors[item3.toLowerCase()] || DiscordColors[item3.toUpperCase()];
								if (color3) return color3 && color3.hex || color3 || "";
								else {
									const item4 = item.replace(/_/g, "-");
									const color4 = DiscordColors[item4] || DiscordColors[item4.toLowerCase()] || DiscordColors[item4.toUpperCase()];
									return color4 && color4.hex || color4 || "";
							}
							}
						}
					}
				});
				BDFDB.DiscordConstants = Internal.DiscordConstants;
				
				Internal.DiscordObjects = new Proxy(DiscordObjects, {
					get: function (_, item) {
						if (DiscordObjects[item]) return DiscordObjects[item];
						if (!InternalData.DiscordObjects[item]) return (function () {});
						let defaultExport = InternalData.DiscordObjects[item].exported == undefined ? true : InternalData.DiscordObjects[item].exported;
						if (InternalData.DiscordObjects[item].props) DiscordObjects[item] = BDFDB.ModuleUtils.findByPrototypes(InternalData.DiscordObjects[item].props, {defaultExport});
						else if (InternalData.DiscordObjects[item].strings) DiscordObjects[item] = BDFDB.ModuleUtils.findByString(InternalData.DiscordObjects[item].strings, {defaultExport});
						return DiscordObjects[item] ? DiscordObjects[item] : (function () {});
					}
				});
				BDFDB.DiscordObjects = Internal.DiscordObjects;
				
				Internal.LibraryRequires = new Proxy(LibraryRequires, {
					get: function (_, item) {
						if (item == "request") return requestFunction;
						if (LibraryRequires[item]) return LibraryRequires[item];
						if (InternalData.LibraryRequires.indexOf(item) == -1) return (function () {});
						try {LibraryRequires[item] = require(item);}
						catch (err) {}
						return LibraryRequires[item] ? LibraryRequires[item] : (function () {});
					}
				});
				BDFDB.LibraryRequires = Internal.LibraryRequires;
				
				Internal.LibraryStores = new Proxy(LibraryStores, {
					get: function (_, item) {
						if (LibraryStores[item]) return LibraryStores[item];
						LibraryStores[item] = BDFDB.ModuleUtils.find(m => m && m.constructor && typeof m.constructor.displayName == "string" && m.constructor.displayName == item && m);
						if (!LibraryStores[item]) BDFDB.LogUtils.warn([item, "could not be found in Webmodule Stores"]);
						return LibraryStores[item] ? LibraryStores[item] : null;
					}
				});
				BDFDB.LibraryStores = Internal.LibraryStores;

				BDFDB.StoreChangeUtils = {};
				BDFDB.StoreChangeUtils.add = function (plugin, store, callback) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(store) || typeof store.addChangeListener != "function" ||  typeof callback != "function") return;
					BDFDB.StoreChangeUtils.remove(plugin, store, callback);
					if (!BDFDB.ArrayUtils.is(plugin.changeListeners)) plugin.changeListeners = [];
					plugin.changeListeners.push({store, callback});
					store.addChangeListener(callback);
				};
				BDFDB.StoreChangeUtils.remove = function (plugin, store, callback) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.changeListeners)) return;
					if (!store) {
						while (plugin.changeListeners.length) {
							let listener = plugin.changeListeners.pop();
							listener.store.removeChangeListener(listener.callback);
						}
					}
					else if (BDFDB.ObjectUtils.is(store) && typeof store.addChangeListener == "function") {
						if (!callback) {
							for (let listener of plugin.changeListeners) {
								let removedListeners = [];
								if (listener.store == store) {
									listener.store.removeChangeListener(listener.callback);
									removedListeners.push(listener);
								}
								if (removedListeners.length) plugin.changeListeners = plugin.changeListeners.filter(listener => !removedListeners.includes(listener));
							}
						}
						else if (typeof callback == "function") {
							store.removeChangeListener(callback);
							plugin.changeListeners = plugin.changeListeners.filter(listener => listener.store == store && listener.callback == callback);
						}
					}
				};

				var pressedKeys = [], mousePosition;
				BDFDB.ListenerUtils = {};
				BDFDB.ListenerUtils.isPressed = function (key) {
					return pressedKeys.includes(key);
				};
				BDFDB.ListenerUtils.getPosition = function (key) {
					return mousePosition;
				};
				BDFDB.ListenerUtils.add = function (plugin, ele, actions, selectorOrCallback, callbackOrNothing) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!BDFDB.ObjectUtils.is(plugin) || (!Node.prototype.isPrototypeOf(ele) && ele !== window) || !actions) return;
					let callbackIs4th = typeof selectorOrCallback == "function";
					let selector = callbackIs4th ? undefined : selectorOrCallback;
					let callback = callbackIs4th ? selectorOrCallback : callbackOrNothing;
					if (typeof callback != "function") return;
					BDFDB.ListenerUtils.remove(plugin, ele, actions, selector);
					for (let action of actions.split(" ")) {
						action = action.split(".");
						let eventName = action.shift().toLowerCase();
						if (!eventName) return;
						let origEventName = eventName;
						eventName = eventName == "mouseenter" || eventName == "mouseleave" ? "mouseover" : eventName;
						let namespace = (action.join(".") || "") + plugin.name;
						if (!BDFDB.ArrayUtils.is(plugin.eventListeners)) plugin.eventListeners = [];
						let eventCallback = null;
						if (selector) {
							if (origEventName == "mouseenter" || origEventName == "mouseleave") eventCallback = e => {
								if (e.composedPath) for (let child of e.composedPath()) if (typeof child.matches == "function" && child.matches(selector) && !child[namespace + "BDFDB" + origEventName]) {
									child[namespace + "BDFDB" + origEventName] = true;
									if (origEventName == "mouseenter") callback(BDFDB.ListenerUtils.copyEvent(e, child));
									let mouseOut = e2 => {
										if (e2.target.contains(child) || e2.target == child || !child.contains(e2.target)) {
											if (origEventName == "mouseleave") callback(BDFDB.ListenerUtils.copyEvent(e, child));
											delete child[namespace + "BDFDB" + origEventName];
											document.removeEventListener("mouseout", mouseOut);
										}
									};
									document.addEventListener("mouseout", mouseOut);
									break;
								}
							};
							else eventCallback = e => {
								if (e.composedPath) for (let child of e.composedPath()) if (typeof child.matches == "function" && child.matches(selector)) {
									callback(BDFDB.ListenerUtils.copyEvent(e, child));
									break;
								}
							};
						}
						else eventCallback = e => callback(BDFDB.ListenerUtils.copyEvent(e, ele));
						
						let observer;
						if (Node.prototype.isPrototypeOf(ele)) {
							observer = new MutationObserver(changes => changes.forEach(change => {
								const nodes = Array.from(change.removedNodes);
								if (nodes.indexOf(ele) > -1 || nodes.some(n =>  n.contains(ele))) BDFDB.ListenerUtils.remove(plugin, ele, actions, selector);
							}));
							observer.observe(document.body, {subtree: true, childList: true});
						}

						plugin.eventListeners.push({ele, eventName, origEventName, namespace, selector, eventCallback, observer});
						ele.addEventListener(eventName, eventCallback, true);
					}
				};
				BDFDB.ListenerUtils.remove = function (plugin, ele, actions = "", selector) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.eventListeners)) return;
					if (!ele) {
						while (plugin.eventListeners.length) {
							let listener = plugin.eventListeners.pop();
							listener.ele.removeEventListener(listener.eventName, listener.eventCallback, true);
							if (listener.observer) listener.observer.disconnect();
						}
					}
					else if (Node.prototype.isPrototypeOf(ele) || ele === window) {
						for (let action of actions.split(" ")) {
							action = action.split(".");
							let eventName = action.shift().toLowerCase();
							let namespace = (action.join(".") || "") + plugin.name;
							for (let listener of plugin.eventListeners) {
								let removedListeners = [];
								if (listener.ele == ele && (!eventName || listener.origEventName == eventName) && listener.namespace == namespace && (selector === undefined || listener.selector == selector)) {
									listener.ele.removeEventListener(listener.eventName, listener.eventCallback, true);
									if (listener.observer) listener.observer.disconnect();
									removedListeners.push(listener);
								}
								if (removedListeners.length) plugin.eventListeners = plugin.eventListeners.filter(listener => !removedListeners.includes(listener));
							}
						}
					}
				};
				const leftSideMap = {
					16: 160,
					17: 170,
					18: 164
				};
				BDFDB.ListenerUtils.addGlobal = function (plugin, id, keybind, action) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!BDFDB.ObjectUtils.is(plugin) || !id || !BDFDB.ArrayUtils.is(keybind) || typeof action != "function") return;
					if (!BDFDB.ObjectUtils.is(plugin.globalKeybinds)) plugin.globalKeybinds = {};
					BDFDB.ListenerUtils.removeGlobal(plugin, id);
					plugin.globalKeybinds[id] = BDFDB.NumberUtils.generateId(Object.entries(plugin.globalKeybinds).map(n => n[1]));
					BDFDB.LibraryModules.WindowUtils.inputEventRegister(plugin.globalKeybinds[id], keybind.map(n => [0, n]), action, {blurred: true, focused: true, keydown: false, keyup: true});
					if (Object.keys(leftSideMap).some(key => keybind.indexOf(parseInt(key)) > -1)) {
						const alternativeId = id + "___ALTERNATIVE";
						plugin.globalKeybinds[alternativeId] = BDFDB.NumberUtils.generateId(Object.entries(plugin.globalKeybinds).map(n => n[1]));
						BDFDB.LibraryModules.WindowUtils.inputEventRegister(plugin.globalKeybinds[alternativeId], keybind.map(n => [0, leftSideMap[n] ?? n]), action, {blurred: true, focused: true, keydown: false, keyup: true});
					}
					return (_ => BDFDB.ListenerUtils.removeGlobal(plugin, id));
				};
				BDFDB.ListenerUtils.removeGlobal = function (plugin, id) {
					if (!BDFDB.ObjectUtils.is(plugin) || !plugin.globalKeybinds) return;
					if (!id) {
						for (let cachedId in plugin.globalKeybinds) BDFDB.LibraryModules.WindowUtils.inputEventUnregister(plugin.globalKeybinds[cachedId]);
						plugin.globalKeybinds = {};
					}
					else {
						if (plugin.globalKeybinds[id]) BDFDB.LibraryModules.WindowUtils.inputEventUnregister(plugin.globalKeybinds[id]);
						delete plugin.globalKeybinds[id];
						const alternativeId = id + "___ALTERNATIVE";
						if (plugin.globalKeybinds[alternativeId]) BDFDB.LibraryModules.WindowUtils.inputEventUnregister(plugin.globalKeybinds[alternativeId]);
						delete plugin.globalKeybinds[alternativeId];
					}
				};
				BDFDB.ListenerUtils.multiAdd = function (node, actions, callback) {
					if (!Node.prototype.isPrototypeOf(node) || !actions || typeof callback != "function") return;
					for (let action of actions.trim().split(" ").filter(n => n)) node.addEventListener(action, callback, true);
				};
				BDFDB.ListenerUtils.multiRemove = function (node, actions, callback) {
					if (!Node.prototype.isPrototypeOf(node) || !actions || typeof callback != "function") return;
					for (let action of actions.trim().split(" ").filter(n => n)) node.removeEventListener(action, callback, true);
				};
				BDFDB.ListenerUtils.addToChildren = function (node, actions, selector, callback) {
					if (!Node.prototype.isPrototypeOf(node) || !actions || !selector || !selector.trim() || typeof callback != "function") return;
					for (let action of actions.trim().split(" ").filter(n => n)) {
						let eventCallback = callback;
						if (action == "mouseenter" || action == "mouseleave") eventCallback = e => {if (e.target.matches(selector)) callback(e);};
						node.querySelectorAll(selector.trim()).forEach(child => child.addEventListener(action, eventCallback, true));
					}
				};
				BDFDB.ListenerUtils.copyEvent = function (e, ele) {
					if (!e || !e.constructor || !e.type) return e;
					let eCopy = new e.constructor(e.type, e);
					Object.defineProperty(eCopy, "originalEvent", {value: e});
					Object.defineProperty(eCopy, "composedPath", {value: e.composedPath});
					Object.defineProperty(eCopy, "which", {value: e.which});
					Object.defineProperty(eCopy, "keyCode", {value: e.keyCode});
					Object.defineProperty(eCopy, "relatedTarget", {value: e.relatedTarget});
					Object.defineProperty(eCopy, "srcElement", {value: e.srcElement});
					Object.defineProperty(eCopy, "target", {value: e.target});
					Object.defineProperty(eCopy, "toElement", {value: e.toElement});
					if (ele) Object.defineProperty(eCopy, "currentTarget", {value: ele});
					return eCopy;
				};
				BDFDB.ListenerUtils.stopEvent = function (e) {
					if (BDFDB.ObjectUtils.is(e)) {
						if (typeof e.preventDefault == "function") e.preventDefault();
						if (typeof e.stopPropagation == "function") e.stopPropagation();
						if (typeof e.stopImmediatePropagation == "function") e.stopImmediatePropagation();
						if (BDFDB.ObjectUtils.is(e.originalEvent)) {
							if (typeof e.originalEvent.preventDefault == "function") e.originalEvent.preventDefault();
							if (typeof e.originalEvent.stopPropagation == "function") e.originalEvent.stopPropagation();
							if (typeof e.originalEvent.stopImmediatePropagation == "function") e.originalEvent.stopImmediatePropagation();
						}
					}
				};
				
				var Toasts = [], NotificationBars = [];
				var ToastQueues = {}, DesktopNotificationQueue = {queue: [], running: false};
				for (let key in Internal.DiscordConstants.ToastPositions) ToastQueues[Internal.DiscordConstants.ToastPositions[key]] = {queue: [], full: false};
				
				BDFDB.NotificationUtils = {};
				BDFDB.NotificationUtils.toast = function (children, config = {}) {
					if (!children) return;
					let app = document.querySelector(BDFDB.dotCN.appmount) || document.body;
					if (!app) return;
					let position = config.position && Internal.DiscordConstants.ToastPositions[config.position] || Internal.settings.choices.toastPosition && Internal.DiscordConstants.ToastPositions[Internal.settings.choices.toastPosition] || Internal.DiscordConstants.ToastPositions.right;
					let queue = ToastQueues[position] || {};
					
					const runQueue = _ => {
						if (queue.full) return;
						let data = queue.queue.shift();
						if (!data) return;
						
						let id = BDFDB.NumberUtils.generateId(Toasts);
						let toasts = document.querySelector(BDFDB.dotCN.toasts + BDFDB.dotCN[position]);
						if (!toasts) {
							toasts = BDFDB.DOMUtils.create(`<div class="${BDFDB.DOMUtils.formatClassName(BDFDB.disCN.toasts, BDFDB.disCN[position])}"></div>`);
							app.appendChild(toasts);
						}
						
						if (data.config.id) data.toast.id = data.config.id.split(" ").join("");
						if (data.config.className) BDFDB.DOMUtils.addClass(data.toast, data.config.className);
						if (data.config.css) BDFDB.DOMUtils.appendLocalStyle("BDFDBcustomToast" + id, data.config.css);
						if (data.config.style) data.toast.style = Object.assign({}, data.toast.style, data.config.style);
						
						let backgroundColor, fontColor, barColor;
						
						let type = data.config.type && BDFDB.disCN["toast" + data.config.type];
						if (!type) {
							barColor = BDFDB.ColorUtils.getType(data.config.barColor) ? BDFDB.ColorUtils.convert(data.config.barColor, "HEX") : data.config.barColor;
							let comp = BDFDB.ColorUtils.convert(data.config.color, "RGBCOMP");
							if (comp) {
								backgroundColor = BDFDB.ColorUtils.convert(comp, "HEX");
								fontColor = comp[0] > 180 && comp[1] > 180 && comp[2] > 180 ? "#000" : "#FFF";
								BDFDB.DOMUtils.addClass(data.toast, BDFDB.disCN.toastcustom);
							}
							else BDFDB.DOMUtils.addClass(data.toast, BDFDB.disCN.toastdefault);
						}
						else BDFDB.DOMUtils.addClass(data.toast, type);
						
						let loadingInterval;
						let disableInteractions = data.config.disableInteractions && typeof data.config.onClick != "function";
						let timeout = typeof data.config.timeout == "number" && !disableInteractions ? data.config.timeout : 3000;
						timeout = (timeout > 0 ? timeout : 600000) + 300;
						if (data.config.ellipsis && typeof data.children == "string") loadingInterval = BDFDB.TimeUtils.interval(_ => data.toast.update(data.children.endsWith(".....") ? data.children.slice(0, -5) : data.children + "."), 500);
						
						let closeTimeout = BDFDB.TimeUtils.timeout(_ => data.toast.close(), timeout);
						data.toast.close = _ => {
							BDFDB.TimeUtils.clear(closeTimeout);
							if (document.contains(data.toast)) {
								BDFDB.DOMUtils.addClass(data.toast, BDFDB.disCN.toastclosing);
								data.toast.style.setProperty("pointer-events", "none", "important");
								BDFDB.TimeUtils.timeout(_ => {
									if (typeof data.config.onClose == "function") data.config.onClose();
									BDFDB.TimeUtils.clear(loadingInterval);
									BDFDB.ArrayUtils.remove(Toasts, id);
									BDFDB.DOMUtils.removeLocalStyle("BDFDBcustomToast" + id);
									data.toast.remove();
									if (!toasts.querySelectorAll(BDFDB.dotCN.toast).length) toasts.remove();
								}, 300);
							}
							queue.full = false;
							runQueue();
						};
						
						if (disableInteractions) data.toast.style.setProperty("pointer-events", "none", "important");
						else {
							BDFDB.DOMUtils.addClass(data.toast, BDFDB.disCN.toastclosable);
							data.toast.addEventListener("click", event => {
								if (typeof data.config.onClick == "function" && !BDFDB.DOMUtils.getParent(BDFDB.dotCN.toastcloseicon, event.target)) data.config.onClick();
								data.toast.close();
							});
							if (typeof closeTimeout.pause == "function") {
								let paused = false;
								data.toast.addEventListener("mouseenter", _ => {
									if (paused) return;
									paused = true;
									closeTimeout.pause();
								});
								data.toast.addEventListener("mouseleave", _ => {
									if (!paused) return;
									paused = false;
									closeTimeout.resume();
								});
							}
						}
						
						toasts.appendChild(data.toast);
						BDFDB.TimeUtils.timeout(_ => BDFDB.DOMUtils.removeClass(data.toast, BDFDB.disCN.toastopening));
						
						let icon = data.config.avatar ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Avatars.Avatar, {
							src: data.config.avatar,
							size: Internal.LibraryComponents.AvatarConstants.AvatarSizes.SIZE_24
						}) : ((data.config.icon || data.config.type && Internal.DiscordConstants.ToastIcons[data.config.type]) ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
							name: data.config.type && Internal.DiscordConstants.ToastIcons[data.config.type] && Internal.LibraryComponents.SvgIcon.Names[Internal.DiscordConstants.ToastIcons[data.config.type]],
							iconSVG: data.config.icon,
							width: 18,
							height: 18,
							nativeClass: true
						}) : null);
						
						BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(class BDFDB_Toast extends Internal.LibraryModules.React.Component {
							componentDidMount() {
								data.toast.update = newChildren => {
									if (!newChildren) return;
									data.children = newChildren;
									BDFDB.ReactUtils.forceUpdate(this);
								};
							}
							render() {
								return BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.toastbg,
											style: {backgroundColor: backgroundColor}
										}),
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.toastinner,
											style: {color: fontColor},
											children: [
												icon && BDFDB.ReactUtils.createElement("div", {
													className: BDFDB.DOMUtils.formatClassName(data.config.avatar && BDFDB.disCN.toastavatar, BDFDB.disCN.toasticon, data.config.iconClassName),
													children: icon
												}),
												BDFDB.ReactUtils.createElement("div", {
													className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.toasttext, data.config.textClassName),
													children: data.children
												}),
												!disableInteractions && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
													className: BDFDB.disCN.toastcloseicon,
													name: Internal.LibraryComponents.SvgIcon.Names.CLOSE,
													width: 16,
													height: 16
												})
											].filter(n => n)
										}),
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.toastbar, barColor && BDFDB.disCN.toastcustombar),
											style: {
												backgroundColor: barColor,
												animation: `toast-bar ${timeout}ms normal linear`
											}
										})
									]
								});
							}
						}, {}), data.toast);
						
						queue.full = (BDFDB.ArrayUtils.sum(Array.from(toasts.childNodes).map(c => {
							let height = BDFDB.DOMUtils.getRects(c).height;
							return height > 50 ? height : 50;
						})) - 100) > BDFDB.DOMUtils.getRects(app).height;
						
						if (typeof data.config.onShow == "function") data.config.onShow();
					};
					
					let toast = BDFDB.DOMUtils.create(`<div class="${BDFDB.disCNS.toast + BDFDB.disCN.toastopening}"></div>`);
					toast.update = _ => {};
					queue.queue.push({children, config, toast});
					runQueue();
					return toast;
				};
				BDFDB.NotificationUtils.desktop = function (content, config = {}) {
					if (!content) return;
					
					const queue = _ => {
						DesktopNotificationQueue.queue.push({content, config});
						runQueue();
					};
					const runQueue = _ => {
						if (DesktopNotificationQueue.running) return;
						let data = DesktopNotificationQueue.queue.shift();
						if (!data) return;
						
						DesktopNotificationQueue.running = true;
						let muted = data.config.silent;
						data.config.silent = data.config.silent || data.config.sound ? true : false;
						let audio = new Audio();
						if (!muted && data.config.sound) {
							audio.src = data.config.sound;
							audio.play();
						}
						let notification = new Notification(data.content, data.config);
						
						let disableInteractions = data.config.disableInteractions && typeof data.config.onClick != "function";
						if (disableInteractions) notification.onclick = _ => {};
						else notification.onclick = _ => {
							if (typeof data.config.onClick == "function") data.config.onClick();
							notification.close();
						};
						
						notification.onclose = _ => {
							audio.pause();
							DesktopNotificationQueue.running = false;
							BDFDB.TimeUtils.timeout(runQueue, 1000);
						}
					};
					
					if (!("Notification" in window)) {BDFDB.NotificationUtils.toast(content, config);}
					else if (Notification.permission === "granted") queue();
					else if (Notification.permission !== "denied") Notification.requestPermission(function (response) {if (response === "granted") queue();});
				};
				BDFDB.NotificationUtils.notice = function (text, config = {}) {
					if (!text) return;
					let layers = document.querySelector(BDFDB.dotCN.layers) || document.querySelector(BDFDB.dotCN.appmount);
					if (!layers) return;
					let notice = BDFDB.DOMUtils.create(`<div class="${BDFDB.disCNS.notice + BDFDB.disCN.noticewrapper}"><div class="${BDFDB.disCN.noticedismiss}"><svg class="${BDFDB.disCN.noticedismissicon}" aria-hidden="false" width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M18.4 4L12 10.4L5.6 4L4 5.6L10.4 12L4 18.4L5.6 20L12 13.6L18.4 20L20 18.4L13.6 12L20 5.6L18.4 4Z"></path></svg></div><div class="${BDFDB.disCN.noticetext}"></div></div>`);
					layers.parentElement.insertBefore(notice, layers);
					let noticeText = notice.querySelector(BDFDB.dotCN.noticetext);
					if (config.platform) for (let platform of config.platform.split(" ")) if (InternalData.DiscordClasses["noticeicon" + platform]) {
						let icon = BDFDB.DOMUtils.create(`<i class="${BDFDB.disCN["noticeicon" + platform]}"></i>`);
						BDFDB.DOMUtils.addClass(icon, BDFDB.disCN.noticeplatformicon);
						BDFDB.DOMUtils.removeClass(icon, BDFDB.disCN.noticeicon);
						notice.insertBefore(icon, noticeText);
					}
					if (config.customIcon) {
						let icon = document.createElement("i"), iconInner = BDFDB.DOMUtils.create(config.customIcon);
						if (iconInner.nodeType == Node.TEXT_NODE) icon.style.setProperty("background", `url(${config.customIcon}) center/cover no-repeat`);
						else {
							icon = iconInner;
							if ((icon.tagName || "").toUpperCase() == "SVG") {
								icon.removeAttribute("width");
								icon.setAttribute("height", "100%");
							}
						}
						BDFDB.DOMUtils.addClass(icon, BDFDB.disCN.noticeplatformicon);
						BDFDB.DOMUtils.removeClass(icon, BDFDB.disCN.noticeicon);
						notice.insertBefore(icon, noticeText);
					}
					if (BDFDB.ArrayUtils.is(config.buttons)) for (let data of config.buttons) {
						let contents = typeof data.contents == "string" && data.contents;
						if (contents) {
							let button = BDFDB.DOMUtils.create(`<button class="${BDFDB.DOMUtils.formatClassName(BDFDB.disCN.noticebutton, data.className)}">${contents}</button>`);
							button.addEventListener("click", event => {
								if (data.close) notice.close();
								if (typeof data.onClick == "function") data.onClick(event, notice);
							});
							if (typeof data.onMouseEnter == "function") button.addEventListener("mouseenter", event => data.onMouseEnter(event, notice));
							if (typeof data.onMouseLeave == "function") button.addEventListener("mouseleave", event => data.onMouseLeave(event, notice));
							notice.appendChild(button);
						}
					}
					if (config.id) notice.id = config.id.split(" ").join("");
					if (config.className) BDFDB.DOMUtils.addClass(notice, config.className);
					if (config.textClassName) BDFDB.DOMUtils.addClass(noticeText, config.textClassName);
					if (config.css) BDFDB.DOMUtils.appendLocalStyle("BDFDBcustomNotificationBar" + id, config.css);
					if (config.style) notice.style = config.style;
					if (config.html) noticeText.innerHTML = text;
					else {
						let link = document.createElement("a");
						let newText = [];
						for (let word of text.split(" ")) {
							let encodedWord = BDFDB.StringUtils.htmlEscape(word);
							link.href = word;
							newText.push(link.host && link.host !== window.location.host ? `<label class="${BDFDB.disCN.noticetextlink}">${encodedWord}</label>` : encodedWord);
						}
						noticeText.innerHTML = newText.join(" ");
					}
					let type = null;
					if (config.type && !document.querySelector(BDFDB.dotCNS.chatbase + BDFDB.dotCN.noticestreamer)) {
						if (type = BDFDB.disCN["notice" + config.type]) BDFDB.DOMUtils.addClass(notice, type);
						if (config.type == "premium") {
							let noticeButton = notice.querySelector(BDFDB.dotCN.noticebutton);
							if (noticeButton) BDFDB.DOMUtils.addClass(noticeButton, BDFDB.disCN.noticepremiumaction);
							BDFDB.DOMUtils.addClass(noticeText, BDFDB.disCN.noticepremiumtext);
							notice.insertBefore(BDFDB.DOMUtils.create(`<i class="${BDFDB.disCN.noticepremiumlogo}"></i>`), noticeText);
						}
					}
					if (!type) {
						let comp = BDFDB.ColorUtils.convert(config.color, "RGBCOMP");
						if (comp) {
							let fontColor = comp[0] > 180 && comp[1] > 180 && comp[2] > 180 ? "#000" : "#FFF";
							let backgroundColor = BDFDB.ColorUtils.convert(comp, "HEX");
							notice.style.setProperty("--custom-notice-background", backgroundColor);
							notice.style.setProperty("--custom-notice-text", fontColor);
							notice.style.setProperty("--custom-notice-button-hover", fontColor);
							BDFDB.DOMUtils.addClass(notice, BDFDB.disCN.noticecustom);
						}
						else BDFDB.DOMUtils.addClass(notice, BDFDB.disCN.noticedefault);
					}
					notice.close = _ => {
						BDFDB.DOMUtils.addClass(notice, BDFDB.disCN.noticeclosing);
						if (notice.tooltip && typeof notice.tooltip.removeTooltip == "function") notice.tooltip.removeTooltip();
						BDFDB.TimeUtils.timeout(_ => {
							if (typeof config.onClose == "function") config.onClose();
							BDFDB.DOMUtils.remove(notice);
						}, 500);
					};
					let dismiss = notice.querySelector(BDFDB.dotCN.noticedismiss);
					if (dismiss) dismiss.addEventListener("click", notice.close);
					return notice;
				};
				BDFDB.NotificationUtils.alert = function (header, body) {
					if (typeof header == "string" && typeof header == "string" && BdApi && typeof BdApi.UI.alert == "function") BdApi.UI.alert(header, body);
				};

				var Tooltips = [];
				BDFDB.TooltipUtils = {};
				BDFDB.TooltipUtils.create = function (anker, text, config = {}) {
					if (!text && !config.guild) return null;
					const itemLayerContainer = document.querySelector(`${BDFDB.dotCN.app} ~ ${BDFDB.dotCN.itemlayercontainer}:has(${BDFDB.dotCN.itemlayercontainerclicktrap})`) || document.querySelector(`${BDFDB.dotCN.app} ~ ${BDFDB.dotCN.itemlayercontainer}`) || document.querySelector(BDFDB.dotCN.itemlayercontainer);
					if (!itemLayerContainer || !Node.prototype.isPrototypeOf(anker) || !document.contains(anker)) return null;
					const id = BDFDB.NumberUtils.generateId(Tooltips);
					const wrapper = BDFDB.DOMUtils.create(`<div class="${BDFDB.disCN.itemlayercontainerclicktrap}"><div class="${BDFDB.disCNS.itemlayer + BDFDB.disCN.itemlayerdisabledpointerevents}"><div class="${BDFDB.disCN.tooltip}" tooltip-id="${id}"><div class="${BDFDB.disCN.tooltipcontent}"></div><div class="${BDFDB.disCNS.tooltippointer + BDFDB.disCN.tooltippointerbg}"></div><div class="${BDFDB.disCN.tooltippointer}"></div></div></div></div>`);
					itemLayerContainer.appendChild(wrapper);
					
					const itemLayer = wrapper.firstElementChild;
					const tooltip = wrapper.querySelector(BDFDB.dotCN.tooltip);
					const tooltipContent = wrapper.querySelector(BDFDB.dotCN.tooltipcontent);
					const tooltipPointers = Array.from(wrapper.querySelectorAll(BDFDB.dotCN.tooltippointer));
					
					if (config.id) tooltip.id = config.id.split(" ").join("");
					
					if (typeof config.type != "string" || !BDFDB.disCN["tooltip" + config.type.toLowerCase()]) config.type = "top";
					let type = config.type.toLowerCase();
					BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN["tooltip" + type], config.className);
					BDFDB.DOMUtils.addClass(tooltipContent, config.contentClassName);
					
					let fontColorIsGradient = false, customBackgroundColor = false, style = "";
					if (config.style) style += config.style;
					if (config.fontColor) {
						fontColorIsGradient = BDFDB.ObjectUtils.is(config.fontColor);
						if (!fontColorIsGradient) style = (style ? (style + " ") : "") + `color: ${BDFDB.ColorUtils.convert(config.fontColor, "RGBA")} !important;`
					}
					if (config.backgroundColor) {
						customBackgroundColor = true;
						let backgroundColorIsGradient = BDFDB.ObjectUtils.is(config.backgroundColor);
						let backgroundColor = !backgroundColorIsGradient ? BDFDB.ColorUtils.convert(config.backgroundColor, "RGBA") : BDFDB.ColorUtils.createGradient(config.backgroundColor);
						let borderColor = backgroundColorIsGradient ? BDFDB.ColorUtils.convert(config.backgroundColor[type == "left" ? 100 : 0], "RGBA") : backgroundColor;
						style = (style ? (style + " ") : "") + `background: ${backgroundColor} !important; --tooltip-pointer-bg: ${borderColor} !important;`;
					}
					if (style) tooltip.style = style;
					const zIndexed = config.zIndex && typeof config.zIndex == "number";
					if (zIndexed) {
						itemLayer.style.setProperty("z-index", config.zIndex, "important");
						tooltip.style.setProperty("z-index", config.zIndex, "important");
						tooltipContent.style.setProperty("z-index", config.zIndex, "important");
						BDFDB.DOMUtils.addClass(itemLayerContainer, BDFDB.disCN.itemlayercontainerzindexdisabled);
					}
					if (typeof config.width == "number" && config.width > 196) {
						tooltip.style.setProperty("width", `${config.width}px`, "important");
						tooltip.style.setProperty("max-width", `${config.width}px`, "important");
					}
					if (typeof config.maxWidth == "number" && config.maxWidth > 196) {
						tooltip.style.setProperty("max-width", `${config.maxWidth}px`, "important");
					}
					if (customBackgroundColor) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN.tooltipcustom);
					else if (config.color && BDFDB.disCN["tooltip" + config.color.toLowerCase()]) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN["tooltip" + config.color.toLowerCase()]);
					else BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN.tooltipprimary);
					
					if (config.list || BDFDB.ObjectUtils.is(config.guild)) BDFDB.DOMUtils.addClass(tooltipContent, BDFDB.disCN.guildlistitemtooltip);
					
					const removeTooltip = _ => {
						document.removeEventListener("wheel", wheel);
						document.removeEventListener("mousemove", mouseMove);
						document.removeEventListener("mouseleave", mouseLeave);
						BDFDB.DOMUtils.remove(wrapper);
						BDFDB.ArrayUtils.remove(Tooltips, id);
						observer.disconnect();
						if (zIndexed) BDFDB.DOMUtils.removeClass(itemLayerContainer, BDFDB.disCN.itemlayercontainerzindexdisabled);
						if (typeof config.onHide == "function") config.onHide(wrapper, anker);
					};
					const setText = newText => {
						if (BDFDB.ObjectUtils.is(config.guild)) {
							let isMuted = Internal.LibraryStores.UserGuildSettingsStore.isMuted(config.guild.id);
							let muteConfig = Internal.LibraryStores.UserGuildSettingsStore.getMuteConfig(config.guild.id);
							
							let children = [typeof newText == "function" ? newText() : newText].flat(10).filter(n => typeof n == "string" || BDFDB.ReactUtils.isValidElement(n));
							BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
								children: [
									BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowguildname),
										children: [
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildBadge, {
												guild: config.guild,
												size: 16,
												className: BDFDB.disCN.tooltiprowiconv2
											}),
											BDFDB.ReactUtils.createElement("span", {
												className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipguildnametext),
												children: fontColorIsGradient ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextGradientElement, {
													gradient: BDFDB.ColorUtils.createGradient(config.fontColor),
													children: config.guild.name
												}) : config.guild.name
											}),
										]
									}),
									children.length && BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowextra),
										children: children
									}),
									config.note && BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowextra, BDFDB.disCN.tooltipnote),
										children: config.note
									}),
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildVoiceList, {guild: config.guild}),
									isMuted && muteConfig && (muteConfig.end_time == null ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipmutetext),
										size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
										color: Internal.LibraryComponents.TextElement.Colors.MUTED,
										children: BDFDB.LanguageUtils.LanguageStrings.MUTED
									}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildTooltipMutedText, {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipmutetext),
										muteConfig: muteConfig
									}))
								].filter(n => n)
							}), tooltipContent);
						}
						else {
							let children = [typeof newText == "function" ? newText() : newText].flat(10).filter(n => typeof n == "string" || BDFDB.ReactUtils.isValidElement(n));
							children.length && BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
								children: [
									fontColorIsGradient ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextGradientElement, {
										gradient: BDFDB.ColorUtils.createGradient(config.fontColor),
										children: children
									}) : children,
									config.note && BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowextra, BDFDB.disCN.tooltipnote),
										children: config.note
									})
								]
							}), tooltipContent);
						}
					};
					const update = newText => {
						if (newText) setText(newText);
						let left, top;
						const tRects = BDFDB.DOMUtils.getRects(anker);
						const iRects = BDFDB.DOMUtils.getRects(itemLayer);
						const aRects = BDFDB.DOMUtils.getRects(document.querySelector(BDFDB.dotCN.appmount));
						const positionOffsets = {height: 10, width: 10};
						const offset = typeof config.offset == "number" ? config.offset : 0;
						switch (type) {
							case "top":
								top = tRects.top - iRects.height - positionOffsets.height + 2 - offset;
								left = tRects.left + (tRects.width - iRects.width) / 2;
								break;
							case "bottom":
								top = tRects.top + tRects.height + positionOffsets.height - 2 + offset;
								left = tRects.left + (tRects.width - iRects.width) / 2;
								break;
							case "left":
								top = tRects.top + (tRects.height - iRects.height) / 2;
								left = tRects.left - iRects.width - positionOffsets.width + 2 - offset;
								break;
							case "right":
								top = tRects.top + (tRects.height - iRects.height) / 2;
								left = tRects.left + tRects.width + positionOffsets.width - 2 + offset;
								break;
							}
							
						itemLayer.style.setProperty("top", `${top}px`, "important");
						itemLayer.style.setProperty("left", `${left}px`, "important");
						
						for (let pointer of tooltipPointers) pointer.style.removeProperty("margin-left");
						for (let pointer of tooltipPointers) pointer.style.removeProperty("margin-top");
						if (type == "top" || type == "bottom") {
							if (left < 0) {
								itemLayer.style.setProperty("left", "5px", "important");
								for (let pointer of tooltipPointers) pointer.style.setProperty("margin-left", `${left - 10}px`, "important");
							}
							else {
								const rightMargin = aRects.width - (left + iRects.width);
								if (rightMargin < 0) {
									itemLayer.style.setProperty("left", `${aRects.width - iRects.width - 5}px`, "important");
									for (let pointer of tooltipPointers) pointer.style.setProperty("margin-left", `${-1*rightMargin}px`, "important");
								}
							}
						}
						else if (type == "left" || type == "right") {
							if (top < 0) {
								const bRects = BDFDB.DOMUtils.getRects(document.querySelector(BDFDB.dotCN.titlebar));
								const barCorrection = (bRects.width || 0) >= Math.round(75 * window.outerWidth / aRects.width) ? (bRects.height + 5) : 0;
								itemLayer.style.setProperty("top", `${5 + barCorrection}px`, "important");
								for (let pointer of tooltipPointers) pointer.style.setProperty("margin-top", `${top - 10 - barCorrection}px`, "important");
							}
							else {
								const bottomMargin = aRects.height - (top + iRects.height);
								if (bottomMargin < 0) {
									itemLayer.style.setProperty("top", `${aRects.height - iRects.height - 5}px`, "important");
									for (let pointer of tooltipPointers) pointer.style.setProperty("margin-top", `${-1*bottomMargin}px`, "important");
								}
							}
						}
					};

					const wheel = e => {
						const tRects1 = BDFDB.DOMUtils.getRects(anker);
						BDFDB.TimeUtils.clear(wheel.timeout);
						wheel.timeout = BDFDB.TimeUtils.timeout(_ => {
							const tRects2 = BDFDB.DOMUtils.getRects(anker);
							if (tRects1.x != tRects2.x || tRects1.y != tRects2.y) removeTooltip();
						}, 500);
					};
					const mouseMove = e => {
						const parent = e.target.parentElement.querySelector(":hover");
						if (parent && anker != parent && !anker.contains(parent)) removeTooltip();
					};
					const mouseLeave = e => removeTooltip();
					if (!config.perssist) {
						document.addEventListener("wheel", wheel);
						document.addEventListener("mousemove", mouseMove);
						document.addEventListener("mouseleave", mouseLeave);
					}
					
					const observer = new MutationObserver(changes => changes.forEach(change => {
						const nodes = Array.from(change.removedNodes);
						if (nodes.indexOf(wrapper) > -1 || nodes.indexOf(anker) > -1 || nodes.some(n =>  n.contains(anker))) removeTooltip();
					}));
					observer.observe(document.body, {subtree: true, childList: true});
					
					tooltip.removeTooltip = wrapper.removeTooltip = removeTooltip;
					tooltip.setText = wrapper.setText = setText;
					tooltip.update = wrapper.update = update;
					setText(text);
					update();
					
					if (config.delay) {
						BDFDB.DOMUtils.toggle(wrapper);
						BDFDB.TimeUtils.timeout(_ => {
							BDFDB.DOMUtils.toggle(wrapper);
							if (typeof config.onShow == "function") config.onShow(wrapper, anker);
						}, config.delay);
					}
					else {
						if (typeof config.onShow == "function") config.onShow(wrapper, anker);
					}
					return wrapper;
				};
				
				Internal.addModulePatches = function (plugin) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!plugin || !plugin.modulePatches) return;
					let patchPriority = !isNaN(plugin.patchPriority) ? plugin.patchPriority : 5;
					patchPriority = patchPriority < 1 ? (plugin == Internal ? 0 : 1) : (patchPriority > 9 ? (plugin == Internal ? 10 : 9) : Math.round(patchPriority));
					for (let patchType in plugin.modulePatches) {
						if (!PluginStores.modulePatches[patchType]) PluginStores.modulePatches[patchType] = {};
						for (let type of plugin.modulePatches[patchType]) {
							if (InternalData.PatchModules[type]) {
								let found = false;
								if (!InternalData.PatchModules[type].noSearch && (patchType == "before" || patchType == "after")) {
									let exports = (BDFDB.ModuleUtils.find(m => Internal.isCorrectModule(m, type) && m, {defaultExport: false, moduleName: type}) || {}).exports;
									if (exports && !exports.default) for (let key of Object.keys(exports)) if (typeof exports[key] == "function" && !(exports[key].prototype && exports[key].prototype.render) && Internal.isCorrectModule(exports[key], type, false) && exports[key].toString().length < 50000) {
										found = true;
										BDFDB.PatchUtils.patch(plugin, exports, key, {[patchType]: e => Internal.initiatePatch(plugin, type, {
											arguments: e.methodArguments,
											instance: e.instance,
											returnvalue: e.returnValue,
											component: exports[key],
											name: type,
											methodname: "render",
											patchtypes: [patchType]
										})}, {name: type});
										break;
									}
								}
								if (!found) {
									if (!PluginStores.modulePatches[patchType][type]) PluginStores.modulePatches[patchType][type] = [];
									if (!PluginStores.modulePatches[patchType][type][patchPriority]) PluginStores.modulePatches[patchType][type][patchPriority] = [];
									PluginStores.modulePatches[patchType][type][patchPriority].push(plugin);
									if (PluginStores.modulePatches[patchType][type][patchPriority].length > 1) PluginStores.modulePatches[patchType][type][patchPriority] = BDFDB.ArrayUtils.keySort(PluginStores.modulePatches[patchType][type][patchPriority], "name");
								}
							}
							else BDFDB.LogUtils.warn(`[${type}] not found in PatchModules InternalData`, plugin);
						}
					}
				};
				Internal.addContextPatches = function (plugin) {
					if (!InternalData.ContextMenuTypes || !BdApi || !BdApi.ContextMenu || typeof BdApi.ContextMenu.patch != "function") return;
					plugin = plugin == BDFDB && Internal || plugin;
					if (!plugin) return;
					for (let type in InternalData.ContextMenuTypes) if (typeof plugin[`on${type}`] == "function") {
						if (!BDFDB.ArrayUtils.is(plugin.patchCancels)) plugin.patchCancels = [];
						plugin.patchCancels.push(BdApi.ContextMenu.patch(InternalData.ContextMenuTypes[type], (returnValue, props) => typeof plugin[`on${type}`] == "function" && plugin[`on${type}`]({returnvalue: returnValue, instance: {props}})));
					}
				};
				Internal.initiatePatch = function (plugin, type, e) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (BDFDB.ObjectUtils.is(plugin) && !plugin.stopping && e.instance) {
						type = BDFDB.StringUtils.upperCaseFirstChar(type).replace(/[^A-z0-9]|_/g, "");
						if (typeof plugin[`process${type}`] == "function") {
							if (typeof e.methodname == "string" && ["componentDidMount", "componentDidUpdate", "componentWillUnmount"].indexOf(e.methodname) > -1) {
								e.node = BDFDB.ReactUtils.findDOMNode(e.instance);
								if (e.node) {
									let tempReturn = plugin[`process${type}`](e);
									return tempReturn !== undefined ? tempReturn : e.returnvalue;
								}
								else BDFDB.TimeUtils.timeout(_ => {
									e.node = BDFDB.ReactUtils.findDOMNode(e.instance);
									if (e.node) plugin[`process${type}`](e);
								});
							}
							else if (e.returnvalue !== undefined || e.patchtypes.includes("before")) {
								let tempReturn = plugin[`process${type}`](e);
								return tempReturn !== undefined ? tempReturn : e.returnvalue;
							}
						}
					}
				};
				
				const PatchTypes = ["before", "instead", "after"];
				BDFDB.PatchUtils = {};
				BDFDB.PatchUtils.isPatched = function (plugin, module, methodName) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!plugin || !methodName || (!BDFDB.ObjectUtils.is(module) && !BDFDB.ArrayUtils.is(module)) || !module[methodName] || !module[methodName].BDFDB_Patches) return false;
					const pluginId = (typeof plugin === "string" ? plugin : plugin.name).toLowerCase();
					return pluginId && BDFDB.ObjectUtils.toArray(module[methodName].BDFDB_Patches).some(patchObj => BDFDB.ObjectUtils.toArray(patchObj.plugins).some(priorityObj => Object.keys(priorityObj).includes(pluginId)));
				};
				BDFDB.PatchUtils.patch = function (plugin, module, methodNames, patchMethods, config = {}) {
					if (!BdApi || !BdApi.Patcher) return;
					plugin = plugin == BDFDB && Internal || plugin;
					if (!plugin || (!BDFDB.ObjectUtils.is(module) && !BDFDB.ArrayUtils.is(module)) || !methodNames || !BDFDB.ObjectUtils.is(patchMethods)) return null;
					patchMethods = BDFDB.ObjectUtils.filter(patchMethods, type => PatchTypes.includes(type) && typeof BdApi.Patcher[type] == "function" && typeof patchMethods[type] == "function", true);
					if (BDFDB.ObjectUtils.isEmpty(patchMethods)) return null;
					
					const pluginName = (typeof plugin === "string" ? plugin : plugin.name) || "";
					const pluginVersion = typeof plugin === "string" ? "" : plugin.version;
					const pluginId = pluginName.toLowerCase();
					
					let patchPriority = !isNaN(config.priority) ? config.priority : (BDFDB.ObjectUtils.is(plugin) && !isNaN(plugin.patchPriority) ? plugin.patchPriority : 5);
					patchPriority = patchPriority < 1 ? (plugin == Internal ? 0 : 1) : (patchPriority > 9 ? (plugin == Internal ? 10 : 9) : Math.round(patchPriority));
					
					methodNames = [methodNames].flat(10).filter(n => n);
					let cancel = _ => BDFDB.PatchUtils.unpatch(plugin, module, methodNames);
					
					for (let methodName of methodNames) if (module[methodName] == null || typeof module[methodName] == "function") {
						if (!module[methodName]) module[methodName] = _ => {return null};
						let patches = module[methodName].BDFDB_Patches || {};
						for (let type in patchMethods) {
							const internalData = (Object.entries(InternalData.LibraryModules).find(n => n && n[0] && LibraryModules[n[0]] == module && n[1] && n[1]._originalModule && n[1]._mappedItems[methodName]) || [])[1];
							const name = internalData && internalData[0] || config.name || (module.constructor ? (module.constructor.displayName || module.constructor.name) : "module");
							try {
								if (!patches[type]) {
									const originalMethod = module[methodName].__originalFunction || module[methodName];
									const mainCancel = BdApi.Patcher[type](Internal.name, internalData && internalData._originalModule || module, internalData && internalData._mappedItems[methodName] || methodName, function(...args) {
										let callInsteadAfterwards = false, stopInsteadCall = false;
										const data = {
											component: module,
											methodArguments: args[1],
											returnValue: args[2],
											originalMethod: originalMethod,
											originalMethodName: methodName
										};
										if (type == "instead") {
											data.callOriginalMethod = _ => data.returnValue = data.originalMethod.apply(this && this !== window ? this : {}, data.methodArguments);
											data.callOriginalMethodAfterwards = _ => (callInsteadAfterwards = true, data.returnValue);
											data.stopOriginalMethodCall = _ => stopInsteadCall = true;
										}
										if (args[0] != module) data.instance = args[0] || {props: args[1][0]};
										if (module == LibraryModules.MessageToolbarUtils) data.instance = {props: args[1][0]};
										for (let priority in patches[type].plugins) for (let id in BDFDB.ObjectUtils.sort(patches[type].plugins[priority])) {
											let tempReturn = BDFDB.TimeUtils.suppress(patches[type].plugins[priority][id], `"${type}" callback of ${methodName} in ${name}`, {name: patches[type].plugins[priority][id].pluginName, version: patches[type].plugins[priority][id].pluginVersion, ignoreErrors: config.ignoreErrors})(data);
											if (type != "before" && tempReturn !== undefined) data.returnValue = tempReturn;
										}
										if (type == "instead" && callInsteadAfterwards && !stopInsteadCall) BDFDB.TimeUtils.suppress(data.callOriginalMethod, `originalMethod of ${methodName} in ${name}`, {name: "Discord", ignoreErrors: config.ignoreErrors})();
										
										if (type != "before") return (methodName == "render" || methodName == "type") && data.returnValue === undefined ? null : data.returnValue;
									});
									module[methodName].BDFDB_Patches = patches;
									patches[type] = {plugins: {}, cancel: _ => {
										if (!config.noCache) BDFDB.ArrayUtils.remove(Internal.patchCancels, patches[type].cancel, true);
										delete patches[type];
										if (!config.noCache && BDFDB.ObjectUtils.isEmpty(patches)) delete module[methodName].BDFDB_Patches;
										mainCancel();
									}};
									if (!config.noCache) {
										if (!BDFDB.ArrayUtils.is(Internal.patchCancels)) Internal.patchCancels = [];
										Internal.patchCancels.push(patches[type].cancel);
									}
								}
								if (!patches[type].plugins[patchPriority]) patches[type].plugins[patchPriority] = {};
								patches[type].plugins[patchPriority][pluginId] = (...args) => {
									if (config.once || !plugin.started) cancel();
									return patchMethods[type](...args);
								};
								patches[type].plugins[patchPriority][pluginId].pluginName = pluginName;
								patches[type].plugins[patchPriority][pluginId].pluginVersion = pluginVersion;
							} catch (err) {BDFDB.LogUtils.error(["Could not patch Component!", `"${type}" Patch of ${methodName} in ${name}`, err], plugin);}
						}
					}
					if (BDFDB.ObjectUtils.is(plugin) && !config.once && !config.noCache) {
						if (!BDFDB.ArrayUtils.is(plugin.patchCancels)) plugin.patchCancels = [];
						plugin.patchCancels.push(cancel);
					}
					return cancel;
				};
				BDFDB.PatchUtils.unpatch = function (plugin, module, methodNames) {
					plugin = plugin == BDFDB && Internal || plugin;
					if (!module || !methodNames) {
						if (BDFDB.ObjectUtils.is(plugin) && BDFDB.ArrayUtils.is(plugin.patchCancels)) while (plugin.patchCancels.length) (plugin.patchCancels.pop())();
					}
					else {
						const pluginId = !plugin ? null : (typeof plugin === "string" ? plugin : plugin.name).toLowerCase();
						for (let methodName of [methodNames].flat(10).filter(n => n)) if (module[methodName] && module[methodName].BDFDB_Patches) {
							let patches = module[methodName].BDFDB_Patches;
							for (let type in patches) {
								if (pluginId) for (let priority in patches[type].plugins) {
									delete patches[type].plugins[priority][pluginId];
									if (BDFDB.ObjectUtils.isEmpty(patches[type].plugins[priority])) delete patches[type].plugins[priority];
								}
								else patches[type].plugins = {};
								if (BDFDB.ObjectUtils.isEmpty(patches[type].plugins)) patches[type].cancel();
							}
						}
					}
				};
				Internal.forceUpdate = function (pluginDataObjs, instance, type) {
					pluginDataObjs = [pluginDataObjs].flat(10).filter(n => n);
					if (pluginDataObjs.length && instance && type) {
						let forceRender = false;
						for (let pluginData of pluginDataObjs) {
							let plugin = pluginData.plugin == BDFDB && Internal || pluginData.plugin, methodNames = [];
							for (let patchType in plugin.modulePatches) {
								if (plugin.modulePatches[patchType].indexOf(type) > -1) methodNames.push(patchType);
							}
							methodNames = BDFDB.ArrayUtils.removeCopies(methodNames).flat(10).filter(n => n);
							if (methodNames.indexOf("componentDidMount") > -1) Internal.initiatePatch(plugin, type, {
								arguments: [],
								instance: instance,
								returnvalue: undefined,
								component: undefined,
								methodname: "componentDidMount",
								patchtypes: pluginData.patchTypes[type]
							});
							if (methodNames.indexOf("before") > -1 || methodNames.indexOf("after") > -1) forceRender = true;
							else if (!forceRender && methodNames.includes("componentDidUpdate") > -1) Internal.initiatePatch(plugin, type, {
								arguments: [],
								instance: instance,
								returnvalue: undefined,
								component: undefined,
								methodname: "componentDidUpdate",
								patchtypes: pluginData.patchTypes[type]
							});
						}
						if (forceRender) BDFDB.ReactUtils.forceUpdate(instance);
					}
				};
				BDFDB.PatchUtils.forceAllUpdates = function (plugins, selectedTypes) {
					plugins = [plugins].flat(10).map(n => n == BDFDB && Internal || n).filter(n => BDFDB.ObjectUtils.is(n.modulePatches));
					if (!plugins.length) return;
					const app = document.querySelector(BDFDB.dotCN.app);
					if (!app) return;
					selectedTypes = [selectedTypes].flat(10).filter(n => n);
					let toBeUpdatedModulesObj = {};
					let patchTypes = {};
					for (let plugin of plugins) {
						toBeUpdatedModulesObj[plugin.name] = [];
						patchTypes[plugin.name] = {};
						for (let patchType in plugin.modulePatches) for (let type of plugin.modulePatches[patchType]) if (!selectedTypes.length || selectedTypes.includes(type)) {
							toBeUpdatedModulesObj[plugin.name].push(type);
							if (!patchTypes[plugin.name][type]) patchTypes[plugin.name][type] = [];
							patchTypes[plugin.name][type].push(patchType);
						}
					}
					let toBeUpdatedModules = BDFDB.ArrayUtils.removeCopies(BDFDB.ObjectUtils.toArray(toBeUpdatedModulesObj).flat(10));
					if (!BDFDB.ArrayUtils.sum(toBeUpdatedModules.map(n => n.length))) return;
					try {
						const appInsDown = BDFDB.ReactUtils.findOwner(app, {name: toBeUpdatedModules, all: true, unlimited: true, group: true});
						const appInsUp = BDFDB.ReactUtils.findOwner(app, {name: toBeUpdatedModules, all: true, unlimited: true, group: true, up: true});
						for (let type in appInsDown) {
							let filteredPlugins = plugins.filter(n => toBeUpdatedModulesObj[n.name].includes(type)).map(n => ({plugin: n, patchTypes: patchTypes[n.name]}));
							for (let ins of appInsDown[type]) Internal.forceUpdate(filteredPlugins, ins, type);
						}
						for (let type in appInsUp) {
							let filteredPlugins = plugins.filter(n => toBeUpdatedModulesObj[n.name].includes(type)).map(n => ({plugin: n, patchTypes: patchTypes[n.name]}));
							for (let ins of appInsUp[type]) Internal.forceUpdate(filteredPlugins, ins, type);
						}
					}
					catch (err) {for (let plugin of plugins) BDFDB.LogUtils.error(["Could not force update Components!", err], plugin);}
				};
				
				Internal.isCorrectModule = function (module, type, useCache = false) {
					if (!InternalData.PatchModules || !InternalData.PatchModules[type]) return false;
					else if (useCache && Cache && Cache.modules && Cache.modules.patch && Cache.modules.patch[type] == module) return true;
					else {
						let foundModule = null;
						if (InternalData.PatchModules[type].strings) foundModule = Internal.checkModuleStrings(module._originalFunction || module, InternalData.PatchModules[type].strings) ? module : null;
						if (InternalData.PatchModules[type].props) foundModule = Internal.checkModuleProps(module, InternalData.PatchModules[type].props) ? module : null;
						if (InternalData.PatchModules[type].protos) foundModule = Internal.checkModuleProtos(module, InternalData.PatchModules[type].protos) ? module : null;
						if (foundModule) {
							if (InternalData.PatchModules[type].nonStrings) foundModule = Internal.checkModuleStrings(module._originalFunction || module, InternalData.PatchModules[type].nonStrings, {hasNot: true}) ? module : null;
							if (InternalData.PatchModules[type].nonProps) foundModule = Internal.checkModuleProps(module, InternalData.PatchModules[type].nonProps, {hasNot: true}) ? module : null;
							if (InternalData.PatchModules[type].nonProtos) foundModule = Internal.checkModuleProtos(module, InternalData.PatchModules[type].nonProtos, {hasNot: true}) ? module : null;
						}
						if (foundModule) {
							if (useCache) {
								if (!Cache.modules.patch) Cache.modules.patch = {};
								Cache.modules.patch[type] = foundModule;
							}
							return true;
						}
					}
					return false;
				};
				Internal.isCorrectModuleButDontPatch = function (type) {
					if (type == "MessageToolbar" && document.querySelector(BDFDB.dotCN.emojipicker)) return true;
					return false;
				};
				Internal.findModuleViaData = (moduleStorage, dataStorage, item) => {
					if (!dataStorage[item]) return;
					let defaultExport = typeof dataStorage[item].exported != "boolean" ? true : dataStorage[item].exported;
					if (dataStorage[item].props) moduleStorage[item] = BDFDB.ModuleUtils.findByProperties(dataStorage[item].props, {defaultExport: defaultExport, moduleName: item});
					else if (dataStorage[item].protos) moduleStorage[item] = BDFDB.ModuleUtils.findByPrototypes(dataStorage[item].protos, {defaultExport: defaultExport, moduleName: item});
					else if (dataStorage[item].name) moduleStorage[item] = BDFDB.ModuleUtils.findByName(dataStorage[item].name, {defaultExport: defaultExport, moduleName: item});
					else if (dataStorage[item].strings) {
						if (dataStorage[item].nonStrings) {
							moduleStorage[item] = Internal.findModule("strings + nonStrings", JSON.stringify([dataStorage[item].strings, dataStorage[item].nonStrings].flat(10)), m => Internal.checkModuleStrings(m, dataStorage[item].strings) && Internal.checkModuleStrings(m, dataStorage[item].nonStrings, {hasNot: true}) && m, {defaultExport: defaultExport, moduleName: item});
						}
						else moduleStorage[item] = BDFDB.ModuleUtils.findByString(dataStorage[item].strings, {defaultExport: defaultExport, moduleName: item});
					}
					if (dataStorage[item].value) moduleStorage[item] = (moduleStorage[item] || {})[dataStorage[item].value];
					if (dataStorage[item].assign) moduleStorage[item] = Object.assign({}, moduleStorage[item]);
					if (!moduleStorage[item]) return;
					if (moduleStorage[item][item]) moduleStorage[item] = moduleStorage[item][item];
					if (dataStorage[item].funcStrings) moduleStorage[item] = (Object.entries(moduleStorage[item]).find(n => {
						if (!n || !n[1]) return;
						let funcString = typeof n[1] == "function" ? n[1].toString() : (_ => {try {return JSON.stringify(n[1])}catch(err){return n[1].toString()}})();
						let renderFuncString = typeof n[1].render == "function" && n[1].render.toString() || "";
						return (funcString || renderFuncString) && [dataStorage[item].funcStrings].flat(10).filter(s => s && typeof s == "string").every(string => funcString && funcString.indexOf(string) > -1 || renderFuncString && renderFuncString.indexOf(string) > -1);
					}) || [])[1];
					if (dataStorage[item].map) {
						dataStorage[item]._originalModule = moduleStorage[item];
						dataStorage[item]._mappedItems = {};
						moduleStorage[item] = new Proxy(Object.assign({}, dataStorage[item]._originalModule, dataStorage[item].map), {
							get: function (_, item2) {
								if (dataStorage[item]._originalModule[item2]) return dataStorage[item]._originalModule[item2];
								if (dataStorage[item]._mappedItems[item2]) return dataStorage[item]._originalModule[dataStorage[item]._mappedItems[item2]];
								if (!dataStorage[item].map[item2]) return dataStorage[item]._originalModule[item2];
								let foundFunc = dataStorage[item].map[item2] && dataStorage[item].map[item2].length == 1 && dataStorage[item]._originalModule[dataStorage[item].map[item2][0]] ? [dataStorage[item].map[item2][0], dataStorage[item]._originalModule[dataStorage[item].map[item2][0]]] : Object.entries(dataStorage[item]._originalModule).find(n => {
									if (!n || !n[1]) return;
									let funcString = typeof n[1] == "function" ? n[1].toString() : (_ => {try {return JSON.stringify(n[1])}catch(err){return n[1].toString()}})();
									let renderFuncString = typeof n[1].render == "function" && n[1].render.toString() || "";
									return [dataStorage[item].map[item2]].flat(10).filter(s => s && typeof s == "string").every(string => funcString && funcString.replace(/[\n\t\r]/g, "").indexOf(string) > -1 || renderFuncString && renderFuncString.replace(/[\n\t\r]/g, "").indexOf(string) > -1);
								});
								if (foundFunc) {
									dataStorage[item]._mappedItems[item2] = foundFunc[0];
									return foundFunc[1];
								}
								return "div";
							}
						});
					}
				};
				const hasDiscordStringHash = m => {
					return m && [InternalData.LanguageStringHashes.DISCORD].flat(10).some(hash => m[hash] && typeof m[hash] != "function");
				};
				const LanguageStores = BDFDB.ModuleUtils.find(m => (hasDiscordStringHash(m) || hasDiscordStringHash(m.default)) && m, {all: true, defaultExport: false});
				
				LibraryModules.EngLanguageStore = (LanguageStores.find(n => n && n.exports && hasDiscordStringHash(n.exports.default)) || {}).exports || {};
				LibraryModules.EngLanguageStore = LibraryModules.EngLanguageStore.default || LibraryModules.EngLanguageStore;
				
				LibraryModules.LanguageStore = (LanguageStores.find(n => n && hasDiscordStringHash(n.exports)) || LanguageStores.find(n => n && n.exports && hasDiscordStringHash(n.exports.default)) || {}).exports || {};
				LibraryModules.LanguageStore = LibraryModules.LanguageStore.default || LibraryModules.LanguageStore;
				
				LibraryModules.React = BDFDB.ModuleUtils.findByProperties("createElement", "cloneElement");
				LibraryModules.ReactDOM = BDFDB.ModuleUtils.findByProperties("render", "findDOMNode", {noWarnings: true}) || BDFDB.ModuleUtils.findByProperties("createRoot");
				LibraryModules.ReactPortal = BDFDB.ModuleUtils.findByProperties("flushSync", "createPortal");
				
				Internal.LibraryModules = new Proxy(LibraryModules, {
					get: function (_, item) {
						if (LibraryModules[item]) return LibraryModules[item];
						if (!InternalData.LibraryModules[item]) return null;
						
						if (item == "HTTPUtils") {
							const APIUtils = Internal.LibraryModules.APIUtils;
							if (APIUtils && InternalData.LibraryModules.HTTPUtils.props) LibraryModules[item] = (Object.entries(APIUtils).find(entry => InternalData.LibraryModules.HTTPUtils.props.every(prop => entry[1][prop] !== undefined)) || [])[1];
						}
						else if (item == "MessageToolbarUtils") return LibraryModules.MessageToolbarUtils;
						else Internal.findModuleViaData(LibraryModules, InternalData.LibraryModules, item);
						
						return LibraryModules[item] ? LibraryModules[item] : null;
					}
				});
				BDFDB.LibraryModules = Internal.LibraryModules;
				
				LibraryModules.MessageToolbarUtils = {};
				LibraryModules.MessageToolbarUtils.useMessageMenu = (props, returnValue) => {return returnValue;};
				
				if (Internal.LibraryModules.KeyCodeUtils && Internal.LibraryModules.PlatformUtils) {
					let originalModule = LibraryModules.KeyCodeUtils;
					LibraryModules.KeyCodeUtils = new Proxy(originalModule, {
						get: function (_, item) {
							if (item == "getString") return getString;
							else if (item == "_originalModule") return originalModule;
							else if (originalModule[item]) return originalModule[item];
							else return null;
						}
					});
					
					let codeMap = BDFDB.ObjectUtils.invert(Internal.LibraryModules.PlatformUtils.isLinux && Internal.LibraryModules.PlatformUtils.isLinux() ? Internal.DiscordConstants.LinuxKeyToCode : Internal.LibraryModules.PlatformUtils.isMac && Internal.LibraryModules.PlatformUtils.isMac() ? Internal.DiscordConstants.MacosKeyToCode : Internal.LibraryModules.PlatformUtils && Internal.LibraryModules.PlatformUtils.isWindows && Internal.LibraryModules.PlatformUtils.isWindows() ? Internal.DiscordConstants.WindowsKeyToCode : {});
					let keyMap = [["META", "⌘"], ["RIGHT META", "RIGHT ⌘"], ["SHIFT", "⇧"], ["RIGHT SHIFT", "RIGHT ⇧"], ["ALT", "⌥"], ["RIGHT ALT", "RIGHT ⌥"], ["CTRL", "⌃"], ["RIGHT CTRL", "RIGHT ⌃"], ["ENTER", "↵"], ["BACKSPACE", "⌫"], ["DEL", "⌦"], ["ESC", "⎋"], ["PAGEUP", "⇞"], ["PAGEDOWN", "⇟"], ["UP", "↑"], ["DOWN", "↓"], ["LEFT", "←"], ["RIGHT", "→"], ["HOME", "↖"], ["END", "↘"], ["TAB", "⇥"], ["SPACE", "␣"]];
					let mapKeys = key => {
						let upperCaseKey = key.toUpperCase();
						for (let [name, mappedKey] of mapKeys) if (name === upperCaseKey) return mappedKey;
						return key;
					};
					const getString = function (keyArray, upperCase = true) {
						let strings = [keyArray].flat(10).filter(n => n).map(keyCode => {
							let code = Internal.LibraryModules.KeyCodeUtils.keyToCode((Object.entries(Internal.LibraryModules.KeyEvents.codes).find(n => n[1] == keyCode && Internal.LibraryModules.KeyCodeUtils.keyToCode(n[0], null)) || [])[0], null) || keyCode;
							return codeMap[code] || "UNK".concat(code)
						}).filter(n => n != null);
						if (!upperCase) return strings.join("+"); 
						else {
							strings = window.navigator.appVersion.indexOf("Mac OS X") != -1 ? strings.map(mapKeys) : strings;
							return strings.join(" + ").toUpperCase();
						}
					};
				}
				
				const MyReact = {};
				MyReact.childrenToArray = function (parent) {
					if (parent && parent.props && parent.props.children && !BDFDB.ArrayUtils.is(parent.props.children)) {
						const child = parent.props.children;
						parent.props.children = [];
						parent.props.children.push(child);
					}
					return parent.props.children;
				}
				MyReact.createElement = function (component, props = {}, errorWrap = false, ignoreErrors = false) {
					if (component && component.defaultProps) for (let key in component.defaultProps) if (props[key] == null) props[key] = component.defaultProps[key];
					try {
						let child = Internal.LibraryModules.React.createElement(component || "div", props) || null;
						if (errorWrap) return Internal.LibraryModules.React.createElement(Internal.ErrorBoundary, {key: child && child.key || ""}, child) || null;
						else return child;
					}
					catch (err) {!ignoreErrors && BDFDB.LogUtils.error(["Could not create React Element!", err]);}
					return null;
				};
				MyReact.objectToReact = function (obj) {
					if (!obj) return null;
					else if (typeof obj == "string") return obj;
					else if (BDFDB.ObjectUtils.is(obj)) return BDFDB.ReactUtils.createElement(obj.type && typeof obj.type == "function" || typeof obj.type == "string" ? obj.type : (obj.props && obj.props.href && "a" || "div"), !obj.props ? {} : Object.assign({}, obj.props, {
						children: obj.props.children ? MyReact.objectToReact(obj.props.children) : null
					}));
					else if (BDFDB.ArrayUtils.is(obj)) return obj.map(n => MyReact.objectToReact(n));
					else return null;
				};
				MyReact.markdownParse = function (str) {
					if (!Internal.LibraryModules.SimpleMarkdownParser) return null;
					if (!MyReact.markdownParse.parser || !MyReact.markdownParse.render) {
						MyReact.markdownParse.parser = Internal.LibraryModules.SimpleMarkdownParser.parserFor(Internal.LibraryModules.SimpleMarkdownParser.defaultRules);
						MyReact.markdownParse.render = Internal.LibraryModules.SimpleMarkdownParser.reactFor(Internal.LibraryModules.SimpleMarkdownParser.ruleOutput(Internal.LibraryModules.SimpleMarkdownParser.defaultRules, "react"));
					}
					return MyReact.render && MyReact.parser ? MyReact.render(MyReact.parser(str, {inline: true})) : null;
				};
				MyReact.elementToReact = function (node, ref) {
					if (BDFDB.ReactUtils.isValidElement(node)) return node;
					else if (!Node.prototype.isPrototypeOf(node)) return null;
					else if (node.nodeType == Node.TEXT_NODE) return node.nodeValue;
					let attributes = {}, importantStyles = [];
					if (typeof ref == "function") attributes.ref = ref;
					if (node.attributes) {
						for (let attr of node.attributes) attributes[attr.name] = attr.value;
						if (node.attributes.style) attributes.style = BDFDB.ObjectUtils.filter(node.style, n => node.style[n] && isNaN(parseInt(n)), true);
					}
					attributes.children = [];
					if (node.style && node.style.cssText) for (let propStr of node.style.cssText.split(";")) if (propStr.endsWith("!important")) {
						let key = propStr.split(":")[0];
						let camelprop = key.replace(/-([a-z]?)/g, (m, g) => g.toUpperCase());
						if (attributes.style[camelprop] != null) importantStyles.push(key);
					}
					for (let child of node.childNodes) attributes.children.push(MyReact.elementToReact(child));
					attributes.className = BDFDB.DOMUtils.formatClassName(attributes.className, attributes.class);
					delete attributes.class;
					return BDFDB.ReactUtils.forceStyle(BDFDB.ReactUtils.createElement(node.tagName, attributes), importantStyles);
				};
				MyReact.forceStyle = function (reactEle, styles) {
					if (!BDFDB.ReactUtils.isValidElement(reactEle)) return null;
					if (!BDFDB.ObjectUtils.is(reactEle.props.style) || !BDFDB.ArrayUtils.is(styles) || !styles.length) return reactEle;
					let ref = reactEle.ref;
					reactEle.ref = instance => {
						if (typeof ref == "function") ref(instance);
						let node = BDFDB.ReactUtils.findDOMNode(instance);
						if (Node.prototype.isPrototypeOf(node)) for (let key of styles) {
							let propValue = reactEle.props.style[key.replace(/-([a-z]?)/g, (m, g) => g.toUpperCase())];
							if (propValue != null) node.style.setProperty(key, propValue, "important");
						}
					};
					return reactEle;
				};
				MyReact.findDOMNode = function (instance, onlyChildren) {
					if (Node.prototype.isPrototypeOf(instance)) return instance;
					if (!instance || !instance.updater) return null;
					let node = Internal.LibraryModules.ReactDOM.findDOMNode && Internal.LibraryModules.ReactDOM.findDOMNode(instance);
					for (let path of ["child.stateNode", "child.ref.current", !onlyChildren && "return.stateNode", !onlyChildren && "return.return.stateNode"]) if (!node && path) {
						node = BDFDB.ObjectUtils.get(instance[BDFDB.ReactUtils.instanceKey] || instance, path);
						node = Node.prototype.isPrototypeOf(node) ? node : null;
					}
					if (!node) {
						if (!onlyChildren) node = BDFDB.ReactUtils.findValue(instance[BDFDB.ReactUtils.instanceKey] || instance, "containerInfo", {up: true});
						else {
							let child = (instance[BDFDB.ReactUtils.instanceKey] || instance);
							while (child && !node) {
								if (child && Node.prototype.isPrototypeOf(child.stateNode)) node = child.stateNode;
								else child = child.child;
							}
						}
					}
					return Node.prototype.isPrototypeOf(node) ? node : null;
				};
				MyReact.findParent = function (nodeOrInstance, config) {
					if (!nodeOrInstance || !BDFDB.ObjectUtils.is(config) || !config.name && !config.type && !config.key && !config.props && !config.filter) return [null, -1];
					let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance;
					if (!BDFDB.ObjectUtils.is(instance) && !BDFDB.ArrayUtils.is(instance) || instance.props && typeof instance.props.children == "function") return [null, -1];
					
					config.name = config.name && [config.name].flat().filter(n => n);
					config.type = config.type && [config.type].flat().filter(n => n);
					config.key = config.key && [config.key].flat().filter(n => n);
					config.props = config.props && [config.props].flat().filter(n => n);
					config.filter = typeof config.filter == "function" && config.filter;
					
					let parent, firstArray;
					parent = firstArray = instance;
					while (!BDFDB.ArrayUtils.is(firstArray) && firstArray.props && firstArray.props.children) firstArray = firstArray.props.children;
					if (!BDFDB.ArrayUtils.is(firstArray)) {
						if (parent && parent.props) {
							parent.props.children = [parent.props.children];
							firstArray = parent.props.children;
						}
						else firstArray = [];
					}
					return getParent(instance);
					
					function getParent (children) {
						let result = [firstArray, -1];
						if (!children) return result;
						if (!BDFDB.ArrayUtils.is(children)) {
							if (check(children)) result = found(children);
							else {
								if (children.props && children.props.children) {
									parent = children;
									result = getParent(children.props.children);
								}
								if (!(result && result[1] > -1) && children.props && children.props.child) {
									parent = children;
									result = getParent(children.props.child);
								}
							}
						}
						else {
							for (let i = 0; result[1] == -1 && i < children.length; i++) if (children[i]) {
								if (BDFDB.ArrayUtils.is(children[i])) {
									parent = children;
									result = getParent(children[i]);
								}
								else if (check(children[i])) {
									parent = children;
									result = found(children[i]);
								}
								else {
									if (children[i].props && children[i].props.children) {
										parent = children[i];
										result = getParent(children[i].props.children);
									}
									if (!(result && result[1] > -1) && children[i].props && children[i].props.child) {
										parent = children[i];
										result = getParent(children[i].props.child);
									}
								}
							}
						}
						return result;
					}
					function found (child) {
						if (BDFDB.ArrayUtils.is(parent)) return [parent, parent.indexOf(child)];
						else {
							parent.props.children = [];
							parent.props.children.push(child);
							return [parent.props.children, 0];
						}
					}
					function check (instance) {
						if (!instance || instance == parent) return false;
						let props = instance.stateNode ? instance.stateNode.props : instance.props;
						if (config.name && instance.type && config.name.some(name => instance.type.displayName == name || instance.type.name == name || Internal.isCorrectModule(instance.type.render || instance.type.type || instance.type, name))) return true;
						if (config.type && config.type.some(type => instance.type == type)) return true;
						if (config.key && config.key.some(key => instance.key == key)) return true;
						if (config.props && props && config.props[config.someProps ? "some" : "every"](prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => propCheck(props, prop[0], checkValue)) : propCheck(props, prop[0], prop[1])) : props[prop] !== undefined)) return true;
						if (config.filter && config.filter(instance)) return true;
						return false;
					}
					function propCheck (props, key, value) {
						return key != null && props[key] != null && value != null && (key == "className" ? (" " + props[key] + " ").indexOf(" " + value + " ") > -1 : BDFDB.equals(props[key], value));
					}
				};
				MyReact.findChild = function (nodeOrInstance, config) {
					if (!nodeOrInstance || !BDFDB.ObjectUtils.is(config) || !config.name && !config.type && !config.key && !config.props && !config.filter) return config.all ? [] : null;
					let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance;
					if (!BDFDB.ObjectUtils.is(instance) && !BDFDB.ArrayUtils.is(instance)) return null;
					
					config.name = config.name && [config.name].flat().filter(n => n);
					config.type = config.type && [config.type].flat().filter(n => n);
					config.key = config.key && [config.key].flat().filter(n => n);
					config.props = config.props && [config.props].flat().filter(n => n);
					config.filter = typeof config.filter == "function" && config.filter;
					
					let depth = -1;
					let start = performance.now();
					let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth);
					let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time);
					
					let foundChildren = [];
					let singleChild = getChild(instance);
					if (config.all) {
						for (let i in foundChildren) delete foundChildren[i].BDFDBreactSearch;
						return foundChildren;
					}
					else return singleChild;
					
					function getChild (children) {
						let result = null;
						if (!children || depth >= maxDepth || performance.now() - start >= maxTime) return result;
						if (!BDFDB.ArrayUtils.is(children)) {
							if (check(children)) {
								if (config.all === undefined || !config.all) result = children;
								else if (config.all) {
									if (!children.BDFDBreactSearch) {
										children.BDFDBreactSearch = true;
										foundChildren.push(children);
									}
								}
							}
							else {
								if (children.props && children.props.children) {
									depth++;
									result = getChild(children.props.children);
									depth--;
								}
								if (!result && children.props && children.props.child) {
									depth++;
									result = getChild(children.props.child);
									depth--;
								}
							}
						}
						else {
							for (let child of children) if (child) {
								if (BDFDB.ArrayUtils.is(child)) result = getChild(child);
								else if (check(child)) {
									if (config.all === undefined || !config.all) result = child;
									else if (config.all) {
										if (!child.BDFDBreactSearch) {
											child.BDFDBreactSearch = true;
											foundChildren.push(child);
										}
									}
								}
								else {
									if (child.props && child.props.children) {
										depth++;
										result = getChild(child.props.children);
										depth--;
									}
									if (!result && child.props && child.props.child) {
										depth++;
										result = getChild(child.props.child);
										depth--;
									}
								}
								if (result) break;
							}
						}
						return result;
					}
					function check (instance) {
						if (!instance || instance == parent) return false;
						let props = instance.stateNode ? instance.stateNode.props : instance.props;
						if (config.name && instance.type && config.name.some(name => instance.type.displayName == name || instance.type.name == name || Internal.isCorrectModule(instance.type.render || instance.type.type || instance.type, name))) return true;
						if (config.type && config.type.some(type => instance.type == type)) return true;
						if (config.key && config.key.some(key => instance.key == key)) return true;
						if (config.props && props && config.props[config.someProps ? "some" : "every"](prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => propCheck(props, prop[0], checkValue)) : propCheck(props, prop[0], prop[1])) : props[prop] !== undefined)) return true;
						if (config.filter && config.filter(instance)) return true;
						return false;
					}
					function propCheck (props, key, value) {
						return key != null && props[key] != null && value != null && (key == "className" ? (" " + props[key] + " ").indexOf(" " + value + " ") > -1 : BDFDB.equals(props[key], value));
					}
				};
				MyReact.findOwner = function (nodeOrInstance, config) {
					if (!BDFDB.ObjectUtils.is(config)) return null;
					if (!nodeOrInstance || !config.name && !config.type && !config.key && !config.props && !config.filter) return config.all ? (config.group ? {} : []) : null;
					let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance;
					if (!BDFDB.ObjectUtils.is(instance)) return config.all ? (config.group ? {} : []) : null;
					
					config.name = config.name && [config.name].flat().filter(n => n);
					config.type = config.type && [config.type].flat().filter(n => n);
					config.key = config.key && [config.key].flat().filter(n => n);
					config.props = config.props && [config.props].flat().filter(n => n);
					config.filter = typeof config.filter == "function" && config.filter;
					
					let depth = -1;
					let start = performance.now();
					let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth);
					let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time);
					let whitelist = config.up ? {
						return: true,
						sibling: true,
						default: true
					} : {
						child: true,
						sibling: true,
						default: true
					};
					whitelist[BDFDB.ReactUtils.instanceKey] = true;
					
					let foundInstances = config.group ? {} : [];
					let singleInstance = getOwner(instance);
					if (config.all) {
						for (let i in foundInstances) {
							if (config.group) for (let j in foundInstances[i]) delete foundInstances[i][j].BDFDBreactSearch;
							else delete foundInstances[i].BDFDBreactSearch;
						}
						return foundInstances;
					}
					else return singleInstance;

					function getOwner (instance) {
						depth++;
						let result = undefined;
						if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) {
							let props = instance.stateNode ? instance.stateNode.props : instance.props;
							let foundName = "";
							if (instance.stateNode && !Node.prototype.isPrototypeOf(instance.stateNode) && (
								config.name && instance.type && config.name.some(name => {if (instance.type.displayName == name || instance.type.name == name || Internal.isCorrectModule(instance.type.render || instance.type.type || instance.type, name)) {
									foundName = name; return true;
								}}) ||
								config.type && instance.type && config.type.some(type => instance.type == type) ||
								config.key && instance.key && config.key.some(key => instance.key == key) ||
								config.props && props && config.props.every(prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => BDFDB.equals(props[prop[0]], checkValue)) : BDFDB.equals(props[prop[0]], prop[1])) : props[prop] !== undefined) ||
								config.filter && config.filter(instance)
							)) {
								if (config.all === undefined || !config.all) result = instance.stateNode;
								else if (config.all) {
									if (!instance.stateNode.BDFDBreactSearch) {
										instance.stateNode.BDFDBreactSearch = true;
										if (config.group) {
											if (foundName) {
												if (!BDFDB.ArrayUtils.is(foundInstances[foundName])) foundInstances[foundName] = [];
												foundInstances[foundName].push(instance.stateNode);
											}
										}
										else foundInstances.push(instance.stateNode);
									}
								}
							}
							if (result === undefined) {
								let keys = Object.getOwnPropertyNames(instance);
								for (let i = 0; result === undefined && i < keys.length; i++) {
									let key = keys[i];
									if (key && whitelist[key] && (typeof instance[key] === "object" || typeof instance[key] == "function")) result = getOwner(instance[key]);
								}
							}
						}
						depth--;
						return result;
					}
				};
				MyReact.findValue = function (nodeOrInstance, searchKey, config = {}) {
					if (!BDFDB.ObjectUtils.is(config)) return null;
					if (!nodeOrInstance || typeof searchKey != "string") return config.all ? [] : null;
					let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance;
					if (!BDFDB.ObjectUtils.is(instance)) return config.all ? [] : null;
					instance = instance[BDFDB.ReactUtils.instanceKey] || instance;
					
					let depth = -1;
					let start = performance.now();
					let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth);
					let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time);
					let whitelist = {
						props: true,
						state: true,
						stateNode: true,
						updater: true,
						prototype: true,
						type: true,
						children: config.up ? false : true,
						memoizedProps: true,
						memoizedState: true,
						child: config.up ? false : true,
						return: config.up ? true : false,
						sibling: config.up ? false : true
					};
					let whitelistKeys = Object.keys(whitelist);
					let blacklist = {
						contextSection: true
					};
					if (BDFDB.ObjectUtils.is(config.whitelist)) Object.assign(whitelist, config.whiteList);
					if (BDFDB.ObjectUtils.is(config.blacklist)) Object.assign(blacklist, config.blacklist);
					return getKey(instance);
					
					function getKey(instance) {
						depth++;
						let result = undefined;
						if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) {
							let keys = Object.keys(instance).sort((x, y) => whitelistKeys.indexOf(x) < whitelistKeys.indexOf(y) ? -1 : 1);
							for (let i = 0; result === undefined && i < keys.length; i++) {
								let key = keys[i];
								if (key && !blacklist[key]) {
									let value = instance[key];
									if (searchKey === key && (config.notNull === undefined || value !== null) && (config.value === undefined || BDFDB.equals(config.value, value))) result = value;
									else if ((typeof value === "object" || typeof value == "function") && (whitelist[key] || key[0] == "." || !isNaN(key[0]))) result = getKey(value);
								}
							}
						}
						depth--;
						return result;
					}
				};
				MyReact.forceUpdate = function (...instances) {
					for (let ins of instances.flat(10).filter(n => n)) if (ins.updater) ins.forceUpdate();
				};
				MyReact.getInstance = function (node) {
					if (!BDFDB.ObjectUtils.is(node)) return null;
					return node[Object.keys(node).find(key => key.startsWith("__reactInternalInstance") || key.startsWith("__reactFiber"))];
				};
				MyReact.render = function (component, node, ignoreErrors = false) {
					if (!BDFDB.ReactUtils.isValidElement(component) || !Node.prototype.isPrototypeOf(node)) return;
					try {
						let root;
						if (Internal.LibraryModules.ReactDOM.render) Internal.LibraryModules.ReactDOM.render(component, node);
						else {
							root = BDFDB.ReactUtils.createRoot(node);
							BDFDB.ReactUtils.flushSync(_ => root.render(component));
						}
						let observer = new MutationObserver(changes => changes.forEach(change => {
							let nodes = Array.from(change.removedNodes);
							if (nodes.indexOf(node) > -1 || nodes.some(n =>  n.contains(node))) {
								observer.disconnect();
								BDFDB.ReactUtils.unmountComponentAtNode(node);
							}
						}));
						observer.observe(document.body, {subtree: true, childList: true});
						if (root) node.root = root;
					}
					catch (err) {
						!ignoreErrors && BDFDB.LogUtils.error(["Could not render React Element!", err]);
					}
				};
				MyReact.hookCall = function (callback, args, ignoreErrors = false) {
					if (typeof callback != "function") return null;
					let returnValue = null, tempNode = document.createElement("div");
					BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(_ => {
						returnValue = callback(args);
						return null;
					}, {}, false, ignoreErrors), tempNode, ignoreErrors);
					BDFDB.ReactUtils.unmountComponentAtNode(tempNode);
					return returnValue;
				};
				MyReact.unmountComponentAtNode = function (node) {
					node && node.root && node.root.unmount ? node.root.unmount() : (Internal.LibraryModules.ReactDOM.unmountComponentAtNode && Internal.LibraryModules.ReactDOM.unmountComponentAtNode(node));
				};
				BDFDB.ReactUtils = new Proxy({}, {
					get: function (_, item) {
						if (MyReact[item]) return MyReact[item];
						else if (LibraryModules.React[item]) return LibraryModules.React[item];
						else if (LibraryModules.ReactDOM[item]) return LibraryModules.ReactDOM[item];
						else if (LibraryModules.ReactPortal[item]) return LibraryModules.ReactPortal[item];
						else return null;
					}
				});

				BDFDB.MessageUtils = {};
				BDFDB.MessageUtils.isSystemMessage = function (message) {
					return message && !Internal.DiscordConstants.MessageTypeGroups.USER_MESSAGE.has(message.type) && (message.type !== Internal.DiscordConstants.MessageTypes.CHAT_INPUT_COMMAND || message.interaction == null);
				};
				BDFDB.MessageUtils.rerenderAll = function (instant) {
					BDFDB.TimeUtils.clear(BDFDB.MessageUtils.rerenderAll.timeout);
					BDFDB.MessageUtils.rerenderAll.timeout = BDFDB.TimeUtils.timeout(_ => {
						let channelId = Internal.LibraryStores.SelectedChannelStore.getChannelId();
						if (channelId) {
							if (BDFDB.DMUtils.isDMChannel(channelId)) BDFDB.DMUtils.markAsRead(channelId);
							else BDFDB.ChannelUtils.markAsRead(channelId);
						}
						let LayerProviderIns = BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.chatcontent), {name: "LayerProvider", unlimited: true, up: true});
						let LayerProviderPrototype = BDFDB.ObjectUtils.get(LayerProviderIns, `${BDFDB.ReactUtils.instanceKey}.type.prototype`);
						if (LayerProviderIns && LayerProviderPrototype) {
							BDFDB.PatchUtils.patch({name: "BDFDB MessageUtils"}, LayerProviderPrototype, "render", {after: e => {
								e.returnValue.props.children = typeof e.returnValue.props.children == "function" ? (_ => {return null;}) : [];
								BDFDB.ReactUtils.forceUpdate(LayerProviderIns);
								let messagesScroller = document.querySelector(BDFDB.dotCN.messagesscroller);
								let scrollTop = messagesScroller && messagesScroller.scrollTop;
								if (scrollTop) requestAnimationFrame(() => messagesScroller.scrollTo({top: scrollTop}));
							}}, {once: true});
							BDFDB.ReactUtils.forceUpdate(LayerProviderIns);
						}
					}, instant ? 0 : 1000);
				};
				BDFDB.MessageUtils.openMenu = function (message, e = mousePosition, slim = false) {
					if (!message) return;
					let channel = Internal.LibraryStores.ChannelStore.getChannel(message.channel_id);
					if (!channel) return;
					e = BDFDB.ListenerUtils.copyEvent(e.nativeEvent || e, (e.nativeEvent || e).currentTarget);
					let type = slim ? "MessageSearchResultContextMenu" : "MessageContextMenu";
					let moduleFindData = InternalData.PatchModules[type] && InternalData.PatchModules[type].strings;
					if (!moduleFindData) return;
					let menu = BDFDB.ModuleUtils.findByString(moduleFindData, {noWarnings: true});
					if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {message, channel})));
					else BDFDB.ModuleUtils.lazyLoadModuleImports(BDFDB.ModuleUtils.findByString(slim ? InternalData.PatchModules.SearchResult && InternalData.PatchModules.SearchResult.strings : InternalData.LibraryModules.MessageComponentUtils && InternalData.LibraryModules.MessageComponentUtils.strings)).then(_ => {
						menu = BDFDB.ModuleUtils.findByString(moduleFindData);
						if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {message, channel})));
					});
				};
					
				BDFDB.UserUtils = {};
				BDFDB.UserUtils.is = function (user) {
					return user && user instanceof Internal.DiscordObjects.User;
				};
				const myDataUser = Internal.LibraryStores.UserStore && Internal.LibraryStores.UserStore.getCurrentUser && Internal.LibraryStores.UserStore.getCurrentUser();
				if (myDataUser && BDFDB.UserUtils._id != myDataUser.id) BDFDB.UserUtils._id = myDataUser.id;
				BDFDB.UserUtils.me = new Proxy(myDataUser || {}, {
					get: function (list, item) {
						const user = Internal.LibraryStores.UserStore && Internal.LibraryStores.UserStore.getCurrentUser && Internal.LibraryStores.UserStore.getCurrentUser();
						if (user && BDFDB.UserUtils._id != user.id) {
							Cache.data = {};
							BDFDB.UserUtils._id = user.id;
						}
						return user ? user[item] : null;
					}
				});
				BDFDB.UserUtils.getStatus = function (id = BDFDB.UserUtils.me.id) {
					id = typeof id == "number" ? id.toFixed() : id;
					let activity = BDFDB.UserUtils.getActivity(id);
					return activity && activity.type == Internal.DiscordConstants.ActivityTypes.STREAMING ? "streaming" : Internal.LibraryStores.PresenceStore.getStatus(id);
				};
				BDFDB.UserUtils.getStatusColor = function (status, useColor) {
					if (!Internal.DiscordConstants.Colors || !Internal.DiscordConstants.ColorsCSS) return null;
					status = typeof status == "string" ? status.toLowerCase() : null;
					let color = "";
					switch (status) {
						case "online": color = (useColor ? Internal.DiscordConstants.Colors.GREEN_360 : BDFDB.DiscordConstants.ColorsCSS.STATUS_POSITIVE); break;
						case "idle": color = (useColor ? Internal.DiscordConstants.Colors.YELLOW_300 : BDFDB.DiscordConstants.ColorsCSS.STATUS_WARNING); break;
						case "dnd": color = (useColor ? Internal.DiscordConstants.Colors.RED_400 : BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER); break;
						case "playing": color = (useColor ? Internal.DiscordConstants.Colors.BRAND : "var(--bdfdb-blurple)"); break;
						case "listening": color = Internal.DiscordConstants.Colors.SPOTIFY; break;
						case "streaming": color = Internal.DiscordConstants.Colors.TWITCH; break;
						default: color = Internal.DiscordConstants.Colors.PRIMARY_400; break;
					}
					return (color || Internal.DiscordConstants.Colors.GREEN_360).replace(/calc\(.+\s*\*\s*([0-9\.\%]+)\)/g, "$1");
				};
				BDFDB.UserUtils.getActivity = function (id = BDFDB.UserUtils.me.id) {
					for (let activity of Internal.LibraryStores.PresenceStore.getActivities(id)) if (activity.type != Internal.DiscordConstants.ActivityTypes.CUSTOM_STATUS) return activity;
					return null;
				};
				BDFDB.UserUtils.getCustomStatus = function (id = BDFDB.UserUtils.me.id) {
					for (let activity of Internal.LibraryStores.PresenceStore.getActivities(id)) if (activity.type == Internal.DiscordConstants.ActivityTypes.CUSTOM_STATUS) return activity;
					return null;
				};
				BDFDB.UserUtils.getAvatar = function (id = BDFDB.UserUtils.me.id) {
					let user = Internal.LibraryStores.UserStore.getUser(id);
					if (!user) return window.location.origin + "/assets/1f0bfc0865d324c2587920a7d80c609b.png";
					else return ((user.avatar ? "" : window.location.origin) + Internal.LibraryModules.IconUtils.getUserAvatarURL(user)).split("?")[0];
				};
				BDFDB.UserUtils.getBanner = function (id = BDFDB.UserUtils.me.id, guildId = Internal.LibraryStores.SelectedGuildStore.getGuildId(), canAnimate = false) {
					let displayProfile = Internal.LibraryModules.MemberDisplayUtils.getDisplayProfile(id, guildId);
					return ((!guildId ? Internal.LibraryModules.IconUtils.getUserBannerURL({banner: displayProfile && displayProfile.banner, id, canAnimate}) : Internal.LibraryModules.IconUtils.getGuildMemberBannerURL({banner: displayProfile && displayProfile.banner, id, guildId, canAnimate})) || "").split("?")[0];
				};
				BDFDB.UserUtils.can = function (permission, id = BDFDB.UserUtils.me.id, channelId = Internal.LibraryStores.SelectedChannelStore.getChannelId()) {
					if (!Internal.DiscordConstants.Permissions[permission]) BDFDB.LogUtils.warn([permission, "not found in Permissions"]);
					else {
						let channel = Internal.LibraryStores.ChannelStore.getChannel(channelId);
						if (channel) return Internal.LibraryModules.PermissionRoleUtils.can({permission: Internal.DiscordConstants.Permissions[permission], user: id, context: channel});
					}
					return false;
				};
				BDFDB.UserUtils.openMenu = function (user, guildId, channelId, e = mousePosition) {
					if (!user) return;
					if (guildId && !channelId) channelId = (BDFDB.LibraryStores.GuildChannelStore.getDefaultChannel(guildId) || {}).id;
					e = BDFDB.ListenerUtils.copyEvent(e.nativeEvent || e, (e.nativeEvent || e).currentTarget);
					let type = channelId ? "UserMemberContextMenu" : "UserGenericContextMenu";
					let moduleFindData = InternalData.PatchModules[type] && InternalData.PatchModules[type].strings;
					if (!moduleFindData) return;
					let menu = BDFDB.ModuleUtils.findByString(moduleFindData, {noWarnings: true});
					if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {user, guildId, channelId})));
					else BDFDB.ModuleUtils.lazyLoadModuleImports(BDFDB.ModuleUtils.findByString(channelId ? InternalData.LibraryModules.UserPopoutUtils && InternalData.LibraryModules.UserPopoutUtils.strings : InternalData.PatchModules.ParticipantsForSelectedParticipant && InternalData.PatchModules.ParticipantsForSelectedParticipant.strings)).then(_ => {
						menu = BDFDB.ModuleUtils.findByString(moduleFindData);
						if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {user, guildId, channelId})));
					});
				};

				BDFDB.GuildUtils = {};
				BDFDB.GuildUtils.is = function (guild) {
					if (!BDFDB.ObjectUtils.is(guild)) return false;
					let keys = Object.keys(guild);
					return guild instanceof Internal.DiscordObjects.Guild || Object.keys(new Internal.DiscordObjects.Guild({})).every(key => keys.indexOf(key) > -1);
				};
				BDFDB.GuildUtils.getIcon = function (id, size, canAnimate) {
					let guild = Internal.LibraryStores.GuildStore.getGuild(id);
					if (!guild || !guild.icon) return "";
					return size ? Internal.LibraryModules.IconUtils.getGuildIconURL({id, size, canAnimate, icon: guild.icon}) : Internal.LibraryModules.IconUtils.getGuildIconURL({id, size, canAnimate, icon: guild.icon}).split("?")[0];
				};
				BDFDB.GuildUtils.getBanner = function (id) {
					let guild = Internal.LibraryStores.GuildStore.getGuild(id);
					if (!guild || !guild.banner) return "";
					return Internal.LibraryModules.IconUtils.getGuildBannerURL(guild).split("?")[0];
				};
				BDFDB.GuildUtils.getFolder = function (id) {
					return Internal.LibraryStores.SortedGuildStore.getGuildFolders().filter(n => n.folderId).find(n => n.guildIds.includes(id));
				};
				BDFDB.GuildUtils.openMenu = function (guild, e = mousePosition) {
					if (!guild) return;
					e = BDFDB.ListenerUtils.copyEvent(e.nativeEvent || e, (e.nativeEvent || e).currentTarget);
					let moduleFindData = InternalData.PatchModules.GuildContextMenu && InternalData.PatchModules.GuildContextMenu.strings;
					if (!moduleFindData) return;
					let menu = BDFDB.ModuleUtils.findByString(moduleFindData, {noWarnings: true});
					if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {guild})));
					else BDFDB.ModuleUtils.lazyLoadModuleImports(BDFDB.ModuleUtils.findByString(InternalData.PatchModules.GuildSidebar && InternalData.PatchModules.GuildSidebar.strings)).then(_ => {
						menu = BDFDB.ModuleUtils.findByString(moduleFindData);
						if (menu) Internal.LibraryModules.ContextMenuUtils.openContextMenu(e, e2 => BDFDB.ReactUtils.createElement(menu.default || menu, Object.assign({}, e2, {guild})));
					});
				};
				BDFDB.GuildUtils.markAsRead = function (guildIds) {
					guildIds = [guildIds].flat(10).filter(id => id && typeof id == "string" && Internal.LibraryStores.GuildStore.getGuild(id));
					if (!guildIds) return;
					let channels = guildIds.map(id => [BDFDB.ObjectUtils.toArray(Internal.LibraryStores.GuildChannelStore.getChannels(id)), BDFDB.ObjectUtils.toArray(Internal.LibraryStores.ActiveThreadsStore.getThreadsForGuild(id)).map(BDFDB.ObjectUtils.toArray).flat(), Internal.LibraryStores.GuildScheduledEventStore.getGuildScheduledEventsForGuild(id)]).flat(10).map(n => n && (n.channel && n.channel.id || n.id)).flat().filter(n => n);
					if (channels.length) BDFDB.ChannelUtils.markAsRead(channels);
					let eventChannels = guildIds.map(id => ({
						channelId: id,
						readStateType: Internal.DiscordConstants.ReadStateTypes.GUILD_EVENT,
						messageId: Internal.LibraryStores.ReadStateStore.lastMessageId(id, Internal.DiscordConstants.ReadStateTypes.GUILD_EVENT)
					})).filter(n => n.messageId);
					if (eventChannels.length) Internal.LibraryModules.AckUtils.bulkAck(eventChannels);
				};

				BDFDB.FolderUtils = {};
				BDFDB.FolderUtils.getId = function (div) {
					if (!Node.prototype.isPrototypeOf(div) || !BDFDB.ReactUtils.getInstance(div)) return;
					div = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildfolderwrapper, div);
					if (!div) return;
					return BDFDB.ReactUtils.findValue(div, "folderId", {up: true});
				};
				BDFDB.FolderUtils.getDefaultName = function (folderId) {
					let folder = Internal.LibraryStores.SortedGuildStore.getGuildFolderById(folderId);
					if (!folder) return "";
					let rest = 2 * Internal.DiscordConstants.MAX_GUILD_FOLDER_NAME_LENGTH;
					let names = [], allNames = folder.guildIds.map(guildId => (Internal.LibraryStores.GuildStore.getGuild(guildId) || {}).name).filter(n => n);
					for (let name of allNames) if (name.length < rest || names.length === 0) {
						names.push(name);
						rest -= name.length;
					}
					return names.join(", ") + (names.length < allNames.length ? ", ..." : "");
				};

				BDFDB.ChannelUtils = {};
				BDFDB.ChannelUtils.is = function (channel) {
					if (!BDFDB.ObjectUtils.is(channel)) return false;
					let keys = Object.keys(channel);
					return channel instanceof Internal.DiscordObjects.Channel || Object.keys(new Internal.DiscordObjects.Channel({})).every(key => keys.indexOf(key) > -1);
				};
				BDFDB.ChannelUtils.isTextChannel = function (channelOrId) {
					let channel = typeof channelOrId == "string" ? Internal.LibraryStores.ChannelStore.getChannel(channelOrId) : channelOrId;
					return BDFDB.ObjectUtils.is(channel) && (channel.type == Internal.DiscordConstants.ChannelTypes.GUILD_TEXT || channel.type == Internal.DiscordConstants.ChannelTypes.GUILD_STORE || channel.type == Internal.DiscordConstants.ChannelTypes.GUILD_ANNOUNCEMENT);
				};
				BDFDB.ChannelUtils.isThread = function (channelOrId) {
					let channel = typeof channelOrId == "string" ? Internal.LibraryStores.ChannelStore.getChannel(channelOrId) : channelOrId;
					return channel && channel.isThread();
				};
				BDFDB.ChannelUtils.isForumPost = function (channelOrId) {
					let channel = typeof channelOrId == "string" ? Internal.LibraryStores.ChannelStore.getChannel(channelOrId) : channelOrId;
					return channel && channel.parentChannelThreadType && channel.parentChannelThreadType == Internal.DiscordConstants.ChannelTypes.GUILD_FORUM;
				};
				BDFDB.ChannelUtils.isEvent = function (channelOrId) {
					let channel = typeof channelOrId == "string" ? Internal.LibraryStores.GuildScheduledEventStore.getGuildScheduledEvent(channelOrId) : channelOrId;
					return channel && Internal.LibraryStores.GuildScheduledEventStore.getGuildScheduledEvent(channel.id) && true;
				};
				BDFDB.ChannelUtils.markAsRead = function (channelIds) {
					let unreadChannels = [channelIds].flat(10).filter(id => id && typeof id == "string" && (BDFDB.LibraryStores.ChannelStore.getChannel(id) || {}).type != Internal.DiscordConstants.ChannelTypes.GUILD_CATEGORY && (Internal.LibraryStores.ReadStateStore.hasUnread(id) || Internal.LibraryStores.ReadStateStore.getMentionCount(id) > 0)).map(id => ({
						channelId: id,
						readStateType: Internal.DiscordConstants.ReadStateTypes.CHANNEL,
						messageId: Internal.LibraryStores.ReadStateStore.lastMessageId(id)
					}));
					if (unreadChannels.length) Internal.LibraryModules.AckUtils.bulkAck(unreadChannels);
				};
				BDFDB.ChannelUtils.rerenderAll = function (instant) {
					BDFDB.TimeUtils.clear(BDFDB.ChannelUtils.rerenderAll.timeout);
					BDFDB.ChannelUtils.rerenderAll.timeout = BDFDB.TimeUtils.timeout(_ => {
						let ChannelsIns = BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.guildchannels), {name: "ChannelsList", unlimited: true});
						if (!ChannelsIns) return;
						else {
							if (ChannelsIns && ChannelsIns.props && ChannelsIns.props.guildChannels.categories && Object.keys(ChannelsIns.props.guildChannels.categories).length) {
								let category = ChannelsIns.props.guildChannels.categories[Object.keys(ChannelsIns.props.guildChannels.categories)[0]];
								category.isCollapsed ? BDFDB.LibraryModules.CategoryCollapseUtils.categoryCollapse(category.id) : BDFDB.LibraryModules.CategoryCollapseUtils.categoryExpand(category.id);
							}
							else {
								let ChannelsPrototype = BDFDB.ObjectUtils.get(ChannelsIns, `${BDFDB.ReactUtils.instanceKey}.type.prototype`);
								if (ChannelsIns && ChannelsPrototype) {
									BDFDB.PatchUtils.patch({name: "BDFDB ChannelUtils"}, ChannelsPrototype, "render", {after: e => {
										e.returnValue.props.children = typeof e.returnValue.props.children == "function" ? (_ => {return null;}) : [];
										BDFDB.ReactUtils.forceUpdate(ChannelsIns);
									}}, {once: true});
									BDFDB.ReactUtils.forceUpdate(ChannelsIns);
								}
							}
						}
					}, instant ? 0 : 1000);
				};
				
				BDFDB.DMUtils = {};
				BDFDB.DMUtils.isDMChannel = function (id) {
					let channel = Internal.LibraryStores.ChannelStore.getChannel(id);
					return BDFDB.ObjectUtils.is(channel) && (channel.isDM() || channel.isGroupDM());
				};
				BDFDB.DMUtils.getIcon = function (id) {
					let channel = Internal.LibraryStores.ChannelStore.getChannel(id);
					if (!channel) return "";
					if (!channel.icon) return channel.isDM() ? BDFDB.UserUtils.getAvatar(channel.recipients[0]) : (channel.isGroupDM() ? window.location.origin + Internal.LibraryModules.IconUtils.getChannelIconURL(channel).split("?")[0] : null);
					return Internal.LibraryModules.IconUtils.getChannelIconURL(channel).split("?")[0];
				};
				BDFDB.DMUtils.markAsRead = function (dmIds) {
					let unreadDMs = [dmIds].flat(10).filter(id => id && typeof id == "string" && BDFDB.DMUtils.isDMChannel(id) && (Internal.LibraryStores.ReadStateStore.hasUnread(id) || Internal.LibraryStores.ReadStateStore.getMentionCount(id) > 0));
					if (unreadDMs.length) for (let i in unreadDMs) BDFDB.TimeUtils.timeout(_ => Internal.LibraryModules.AckUtils.ack(unreadDMs[i]), i * 1000);
				};
				
				BDFDB.ColorUtils = {};
				BDFDB.ColorUtils.convert = function (color, conv, type) {
					if (typeof color == "string" && color.indexOf("var(--") == 0) return color;
					if (BDFDB.ObjectUtils.is(color)) {
						let newColor = {};
						for (let pos in color) newColor[pos] = BDFDB.ColorUtils.convert(color[pos], conv, type);
						return newColor;
					}
					else {
						if (typeof color == "string") color = color.replace(/calc\(.+\s*\*\s*([0-9\.\%]+)\)/g, "$1");
						conv = conv === undefined || !conv ? conv = "RGBCOMP" : conv.toUpperCase();
						type = type === undefined || !type || !["RGB", "RGBA", "RGBCOMP", "HSL", "HSLA", "HSLCOMP", "HSV", "HSVA", "HSVCOMP", "HEX", "HEXA", "INT"].includes(type.toUpperCase()) ? BDFDB.ColorUtils.getType(color) : type.toUpperCase();
						if (conv == "RGBCOMP") {
							switch (type) {
								case "RGBCOMP":
									var rgbComp = [].concat(color);
									if (rgbComp.length == 3) return processRGB(rgbComp);
									else if (rgbComp.length == 4) {
										let a = processA(rgbComp.pop());
										return processRGB(rgbComp).concat(a);
									}
									break;
								case "RGB":
									return processRGB(color.replace(/\s/g, "").slice(4, -1).split(","));
								case "RGBA":
									var rgbComp = color.replace(/\s/g, "").slice(5, -1).split(",");
									var a = processA(rgbComp.pop());
									return processRGB(rgbComp).concat(a);
								case "HSLCOMP":
									var hslComp = [].concat(color);
									if (hslComp.length == 3) return BDFDB.ColorUtils.convert(`hsl(${processHSX(hslComp).join(",")})`, "RGBCOMP");
									else if (hslComp.length == 4) {
										let a = processA(hslComp.pop());
										return BDFDB.ColorUtils.convert(`hsl(${processHSX(hslComp).join(",")})`, "RGBCOMP").concat(a);
									}
									break;
								case "HSL":
									var hslComp = processHSX(color.replace(/\s/g, "").slice(4, -1).split(","));
									var r, g, b, m, c, x, p, q;
									var h = hslComp[0], s = processPercentage(hslComp[1]), l = processPercentage(hslComp[2]);
									var a = s * Math.min(l, 1-l);
									var f = (n, k = (n+h / 30) % 12) => parseInt((l - a * Math.max(Math.min(k-3, 9-k, 1), -1)) * 255);
									return [f(0), f(8), f(4)];
								case "HSLA":
									var hslComp = color.replace(/\s/g, "").slice(5, -1).split(",");
									return BDFDB.ColorUtils.convert(`hsl(${hslComp.slice(0, 3).join(",")})`, "RGBCOMP").concat(processA(hslComp.pop()));
								case "HSVCOMP":
									var hsvComp = [].concat(color);
									if (hsvComp.length == 3) return BDFDB.ColorUtils.convert(`hsv(${processHSX(hsvComp).join(",")})`, "RGBCOMP");
									else if (hsvComp.length == 4) {
										let a = processA(hsvComp.pop());
										return BDFDB.ColorUtils.convert(`hsv(${processHSX(hsvComp).join(",")})`, "RGBCOMP").concat(a);
									}
									break;
								case "HSV":
									var hsvComp = processHSX(color.replace(/\s/g, "").slice(4, -1).split(","));
									var r, g, b, i, f, p, q, t;
									var h = hsvComp[0] / 360, s = processPercentage(hsvComp[1]), v = processPercentage(hsvComp[2]);
									i = Math.floor(h * 6), f = h * 6 - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s);

									switch (i % 6) {
										case 0: r = v, g = t, b = p; break;
										case 1: r = q, g = v, b = p; break;
										case 2: r = p, g = v, b = t; break;
										case 3: r = p, g = q, b = v; break;
										case 4: r = t, g = p, b = v; break;
										case 5: r = v, g = p, b = q; break;
									}
									return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
								case "HSVA":
									var hsvComp = color.replace(/\s/g, "").slice(5, -1).split(",");
									return BDFDB.ColorUtils.convert(`hsv(${hsvComp.slice(0, 3).join(",")})`, "RGBCOMP").concat(processA(hsvComp.pop()));
								case "HEX":
									var hex = /^#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$|^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
									return [parseInt(hex[1] + hex[1] || hex[4], 16), parseInt(hex[2] + hex[2] || hex[5], 16), parseInt(hex[3] + hex[3] || hex[6], 16)];
								case "HEXA":
									var hex = /^#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$|^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
									return [parseInt(hex[1] + hex[1] || hex[5], 16), parseInt(hex[2] + hex[2] || hex[6], 16), parseInt(hex[3] + hex[3] || hex[7], 16), Math.floor(BDFDB.NumberUtils.mapRange([0, 255], [0, 100], parseInt(hex[4] + hex[4] || hex[8], 16)))/100];
								case "INT":
									color = processINT(color);
									return [parseInt(color >> 16 & 255), parseInt(color >> 8 & 255), parseInt(color & 255)];
								default:
									return null;
							}
						}
						else {
							if (conv && type && (conv.indexOf("HSL") == 0 && type.indexOf("HSL") == 0 || conv.indexOf("HSV") == 0 && type.indexOf("HSV") == 0)) {
								let name = type.indexOf("HSL") == 0 ? "HSL" : "HSV";
								if (type == `${name}COMP`) {
									let comp = [].concat(color);
									switch (conv) {
										case `${name}COMP`:
											if (comp.length == 3) return processHSX(comp);
											else if (comp.length == 4) {
												var a = processA(comp.pop());
												return processHSX(comp).concat(a);
											}
											break;
										case name:
											return `${name.toLowerCase()}(${processHSX(comp.slice(0, 3)).join(",")})`;
										case `${name}A`:
											comp = comp.slice(0, 4);
											var a = comp.length == 4 ? processA(comp.pop()) : 1;
											return `${name.toLowerCase()}a(${processHSX(comp).concat(a).join(",")})`;
									}
								}
								return BDFDB.ColorUtils.convert(color.replace(/\s/g, "").slice(color.toUpperCase().indexOf("A") == 3 ? 5 : 4, -1).split(","), conv, `${name}COMP`);
							}
							else {
								let rgbComp = type == "RGBCOMP" ? [].concat(color) : BDFDB.ColorUtils.convert(color, "RGBCOMP", type);
								if (rgbComp) switch (conv) {
									case "RGB":
										return `rgb(${processRGB(rgbComp.slice(0, 3)).join(",")})`;
									case "RGBA":
										rgbComp = rgbComp.slice(0, 4);
										var a = rgbComp.length == 4 ? processA(rgbComp.pop()) : 1;
										return `rgba(${processRGB(rgbComp).concat(a).join(",")})`;
									case "HSLCOMP":
										var a = rgbComp.length == 4 ? processA(rgbComp.pop()) : null;
										var hslComp = processHSX(BDFDB.ColorUtils.convert(rgbComp, "HSL").replace(/\s/g, "").split(","));
										return a != null ? hslComp.concat(a) : hslComp;
									case "HSL":
										var r = processC(rgbComp[0]) / 255, g = processC(rgbComp[1]) / 255, b = processC(rgbComp[2]) / 255;
										var max = Math.max(r, g, b), min = Math.min(r, g, b);

										var h, s, l;
										h = s = l = (max + min) / 2;

										if (max === min) return `hsl(${processHSX([0, 0, l * 100]).join(",")})`;

										var dif = max - min;
										s = l >= 0.5 ? dif / (2 - (max + min)) : dif / (max + min);
										switch (max) {
											case r: h = ((g - b) / dif + 0) * 60; break;
											case g: h = ((b - r) / dif + 2) * 60; break;
											case b: h = ((r - g) / dif + 4) * 60; break;
										}
										return `hsl(${processHSX([Math.round(h * 360), s * 100, l * 100]).join(",")})`;
									case "HSLA":
										var a = rgbComp.length == 4 ? processA(rgbComp.pop()) : 1;
										return `hsla(${BDFDB.ColorUtils.convert(rgbComp, "HSL").slice(4, -1).split(",").concat(a).join(",")})`;
									case "HSVCOMP":
										var a = rgbComp.length == 4 ? processA(rgbComp.pop()) : null;
										var hsvComp = processHSX(BDFDB.ColorUtils.convert(rgbComp, "HSV").replace(/\s/g, "").split(","));
										return a != null ? hsvComp.concat(a) : hsvComp;
									case "HSV":
										var r = processC(rgbComp[0]), g = processC(rgbComp[1]), b = processC(rgbComp[2]);
										var max = Math.max(r, g, b), min = Math.min(r, g, b), dif = max - min, h, s = max === 0 ? 0 : dif / max, v = max / 255;
										switch (max) {
											case min: h = 0; break;
											case r: h = g - b + dif * (g < b ? 6 : 0); h /= 6 * dif; break;
											case g: h = b - r + dif * 2; h /= 6 * dif; break;
											case b: h = r - g + dif * 4; h /= 6 * dif; break;
										}
										return `hsv(${processHSX([Math.round(h * 360), s * 100, v * 100]).join(",")})`;
									case "HSVA":
										var a = rgbComp.length == 4 ? processA(rgbComp.pop()) : 1;
										return `hsva(${BDFDB.ColorUtils.convert(rgbComp, "HSV").slice(4, -1).split(",").concat(a).join(",")})`;
									case "HEX":
										return ("#" + (0x1000000 + (rgbComp[2] | rgbComp[1] << 8 | rgbComp[0] << 16)).toString(16).slice(1)).toUpperCase();
									case "HEXA":
										return ("#" + (0x1000000 + (rgbComp[2] | rgbComp[1] << 8 | rgbComp[0] << 16)).toString(16).slice(1) + (0x100 + Math.round(BDFDB.NumberUtils.mapRange([0, 100], [0, 255], processA(rgbComp[3]) * 100))).toString(16).slice(1)).toUpperCase();
									case "INT":
										return processINT(rgbComp[2] | rgbComp[1] << 8 | rgbComp[0] << 16);
									default:
										return null;
								}
							}
						}
					}
					return null;
					function processC (c) {
						if (c == null) return 255;
						else {
							c = parseInt(c.toString().replace(/[^0-9\-]/g, ""));
							return isNaN(c) || c > 255 ? 255 : c < 0 ? 0 : c;
						}
					};
					function processRGB (comp) {
						return [].concat(comp).map(processC);
					};
					function processA (a) {
						if (a == null) return 1;
						else {
							a = a.toString();
							a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, ""));
							return isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a;
						}
					};
					function processPercentage (p) {
						if (p == null) return 1;
						else return p.indexOf("%") > -1 ? parseFloat(p)/100 : p;
					};
					function processSL (sl) {
						if (sl == null) return "100%";
						else {
							sl = parseFloat(sl.toString().replace(/[^0-9\.\-]/g, ""));
							return (isNaN(sl) || sl > 100 ? 100 : sl < 0 ? 0 : sl) + "%";
						}
					};
					function processHSX (comp) {
						comp = [].concat(comp);
						let h = parseFloat(comp.shift().toString().replace(/[^0-9\.\-]/g, ""));
						h = isNaN(h) || h > 360 ? 360 : h < 0 ? 0 : h;
						return [h].concat(comp.map(processSL));
					};
					function processINT (c) {
						if (c == null) return 16777215;
						else {
							c = parseInt(c.toString().replace(/[^0-9]/g, ""));
							return isNaN(c) || c > 16777215 ? 16777215 : c < 0 ? 0 : c;
						}
					};
				};
				BDFDB.ColorUtils.setAlpha = function (color, a, conv) {
					if (typeof color == "string" && color.indexOf("var(--") == 0) return color;
					if (BDFDB.ObjectUtils.is(color)) {
						let newcolor = {};
						for (let pos in color) newcolor[pos] = BDFDB.ColorUtils.setAlpha(color[pos], a, conv);
						return newcolor;
					}
					else {
						let rgbComp = BDFDB.ColorUtils.convert(color, "RGBCOMP");
						if (rgbComp) {
							a = a.toString();
							a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, ""));
							a = isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a;
							rgbComp[3] = a;
							conv = (conv || BDFDB.ColorUtils.getType(color)).toUpperCase();
							conv = conv == "RGB" || conv == "HSL" || conv == "HEX" ? conv + "A" : conv;
							return BDFDB.ColorUtils.convert(rgbComp, conv);
						}
					}
					return null;
				};
				BDFDB.ColorUtils.getAlpha = function (color) {
					let rgbComp = BDFDB.ColorUtils.convert(color, "RGBCOMP");
					if (rgbComp) {
						if (rgbComp.length == 3) return 1;
						else if (rgbComp.length == 4) {
							let a = rgbComp[3].toString();
							a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, ""));
							return isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a;
						}
					}
					return null;
				};
				BDFDB.ColorUtils.change = function (color, value, conv) {
					if (typeof color == "string" && color.indexOf("var(--") == 0) return color;
					value = parseFloat(value);
					if (color != null && typeof value == "number" && !isNaN(value)) {
						if (BDFDB.ObjectUtils.is(color)) {
							let newColor = {};
							for (let pos in color) newColor[pos] = BDFDB.ColorUtils.change(color[pos], value, conv);
							return newColor;
						}
						else {
							let rgbComp = BDFDB.ColorUtils.convert(color, "RGBCOMP");
							if (rgbComp) {
								let a = BDFDB.ColorUtils.getAlpha(rgbComp);
								if (parseInt(value) !== value) {
									value = value.toString();
									value = (value.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(value.replace(/[^0-9\.\-]/g, ""));
									value = isNaN(value) ? 0 : value;
									return BDFDB.ColorUtils.convert([].concat(rgbComp).slice(0, 3).map(c => {
										c = Math.round(c * (1 + value));
										return c > 255 ? 255 : c < 0 ? 0 : c;
									}).concat(a), conv || BDFDB.ColorUtils.getType(color));
								}
								else return BDFDB.ColorUtils.convert([].concat(rgbComp).slice(0, 3).map(c => {
									c = Math.round(c + value);
									return c > 255 ? 255 : c < 0 ? 0 : c;
								}).concat(a), conv || BDFDB.ColorUtils.getType(color));
							}
						}
					}
					return null;
				};
				BDFDB.ColorUtils.invert = function (color, conv) {
					if (typeof color == "string" && color.indexOf("var(--") == 0) return color;
					if (BDFDB.ObjectUtils.is(color)) {
						let newColor = {};
						for (let pos in color) newColor[pos] = BDFDB.ColorUtils.invert(color[pos], conv);
						return newColor;
					}
					else {
						let comp = BDFDB.ColorUtils.convert(color, "RGBCOMP");
						if (comp) return BDFDB.ColorUtils.convert([255 - comp[0], 255 - comp[1], 255 - comp[2]], conv || BDFDB.ColorUtils.getType(color));
					}
					return null;
				};
				BDFDB.ColorUtils.compare = function (color1, color2) {
					if (color1 && color2) {
						color1 = BDFDB.ColorUtils.convert(color1, "RGBA");
						color2 = BDFDB.ColorUtils.convert(color2, "RGBA");
						if (color1 && color2) return BDFDB.equals(color1, color2);
					}
					return null;
				};
				BDFDB.ColorUtils.isBright = function (color, compare = 160) {
					if (!BDFDB.ColorUtils.getType(color)) return false;
					color = BDFDB.ColorUtils.convert(color, "RGBCOMP");
					if (!color) return false;
					return parseInt(compare) < Math.sqrt(0.299 * color[0]**2 + 0.587 * color[1]**2 + 0.144 * color[2]**2);
				};
				BDFDB.ColorUtils.getType = function (color) {
					if (color !== null) {
						if (typeof color === "object" && (color.length == 3 || color.length == 4)) {
							if (isRGB(color)) return "RGBCOMP";
							else if (isHSL(color)) return "HSLCOMP";
						}
						else if (typeof color === "string") {
							color = color.replace(/calc\(.+\s*\*\s*([0-9\.\%]+)\)/g, "$1");
							if (/^#[a-f\d]{3}$|^#[a-f\d]{6}$/i.test(color)) return "HEX";
							else if (/^#[a-f\d]{4}$|^#[a-f\d]{8}$/i.test(color)) return "HEXA";
							else {
								color = color.toUpperCase();
								let comp = color.replace(/[^0-9\.\-\,\%]/g, "").split(",");
								if (color.indexOf("RGB(") == 0 && comp.length == 3 && isRGB(comp)) return "RGB";
								else if (color.indexOf("RGBA(") == 0 && comp.length == 4 && isRGB(comp)) return "RGBA";
								else if (color.indexOf("HSL(") == 0 && comp.length == 3 && isHSL(comp)) return "HSL";
								else if (color.indexOf("HSLA(") == 0 && comp.length == 4 && isHSL(comp)) return "HSLA";
								else if (color.indexOf("HSV(") == 0 && comp.length == 3 && isHSL(comp)) return "HSV";
								else if (color.indexOf("HSVA(") == 0 && comp.length == 4 && isHSL(comp)) return "HSVA";
							}
						}
						else if (typeof color === "number" && parseInt(color) == color && color > -1 && color < 16777216) return "INT";
					}
					return null;
					function isRGB(comp) {return comp.slice(0, 3).every(rgb => rgb.toString().indexOf("%") == -1 && parseFloat(rgb) == parseInt(rgb));};
					function isHSL(comp) {return comp.slice(1, 3).every(hsl => hsl.toString().indexOf("%") == hsl.length - 1);};
				};
				BDFDB.ColorUtils.createGradient = function (colorObj, direction = "to right") {
					let gradientString = "linear-gradient(" + direction;
					for (let pos of Object.keys(colorObj).sort()) {
						let color = BDFDB.ColorUtils.convert(colorObj[pos], "RGBA");
						gradientString += color ? `, ${color} ${pos*100}%` : ''
					}
					return gradientString += ")";
				};

				BDFDB.DOMUtils = {};
				BDFDB.DOMUtils.getSelection = function () {
					let selection = document.getSelection();
					return selection && selection.anchorNode ? selection.getRangeAt(0).toString() : "";
				};
				BDFDB.DOMUtils.addClass = function (eles, ...classes) {
					if (!eles || !classes) return;
					for (let ele of [eles].map(n => NodeList.prototype.isPrototypeOf(n) ? Array.from(n) : n).flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) add(ele);
						else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) add(e);
						else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) add(n);
					}
					function add(node) {
						if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.add(c);
					}
				};
				BDFDB.DOMUtils.removeClass = function (eles, ...classes) {
					if (!eles || !classes) return;
					for (let ele of [eles].map(n => NodeList.prototype.isPrototypeOf(n) ? Array.from(n) : n).flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) remove(ele);
						else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) remove(e);
						else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) remove(n);
					}
					function remove(node) {
						if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.remove(c);
					}
				};
				BDFDB.DOMUtils.toggleClass = function (eles, ...classes) {
					if (!eles || !classes) return;
					var force = classes.pop();
					if (typeof force != "boolean") {
						classes.push(force);
						force = undefined;
					}
					if (!classes.length) return;
					for (let ele of [eles].map(n => NodeList.prototype.isPrototypeOf(n) ? Array.from(n) : n).flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) toggle(ele);
						else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) toggle(e);
						else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) toggle(n);
					}
					function toggle(node) {
						if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.toggle(c, force);
					}
				};
				BDFDB.DOMUtils.containsClass = function (eles, ...classes) {
					if (!eles || !classes) return;
					let all = classes.pop();
					if (typeof all != "boolean") {
						classes.push(all);
						all = true;
					}
					if (!classes.length) return;
					let contained = undefined;
					for (let ele of [eles].map(n => NodeList.prototype.isPrototypeOf(n) ? Array.from(n) : n).flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) contains(ele);
						else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) contains(e);
						else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) for (let n of document.querySelectorAll(c)) contains(n);
					}
					return contained;
					function contains(node) {
						if (node && node.classList) for (let cla of classes) if (typeof cla == "string") for (let c of cla.split(" ")) if (c) {
							if (contained === undefined) contained = all;
							if (all && !node.classList.contains(c)) contained = false;
							if (!all && node.classList.contains(c)) contained = true;
						}
					}
				};
				BDFDB.DOMUtils.formatClassName = function (...classes) {
					return BDFDB.ArrayUtils.removeCopies(classes.flat(10).filter(n => n).join(" ").split(" ")).join(" ").trim();
				};
				BDFDB.DOMUtils.removeClassFromDOM = function (...classes) {
					for (let c of classes.flat(10).filter(n => n)) if (typeof c == "string") for (let a of c.split(",")) if (a && (a = a.replace(/\.|\s/g, ""))) BDFDB.DOMUtils.removeClass(document.querySelectorAll("." + a), a);
				};
				BDFDB.DOMUtils.show = function (...eles) {
					BDFDB.DOMUtils.toggle(...eles, true);
				};
				BDFDB.DOMUtils.hide = function (...eles) {
					BDFDB.DOMUtils.toggle(...eles, false);
				};
				BDFDB.DOMUtils.toggle = function (...eles) {
					if (!eles) return;
					let force = eles.pop();
					if (typeof force != "boolean") {
						eles.push(force);
						force = undefined;
					}
					if (!eles.length) return;
					for (let ele of eles.flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) toggle(ele);
						else if (NodeList.prototype.isPrototypeOf(ele)) for (let node of ele) toggle(node);
						else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) for (let node of document.querySelectorAll(c)) toggle(node);
					}
					function toggle(node) {
						if (!node || !Node.prototype.isPrototypeOf(node)) return;
						let hide = force === undefined ? !BDFDB.DOMUtils.isHidden(node) : !force;
						if (hide) {
							let display = node.style.getPropertyValue("display");
							if (display && display != "none") node.BDFDBhideDisplayState = {
								display: display,
								important: (` ${node.style.cssText} `.split(` display: ${display}`)[1] || "").trim().indexOf("!important") == 0
							};
							node.style.setProperty("display", "none", "important");
						}
						else {
							if (node.BDFDBhideDisplayState) {
								node.style.setProperty("display", node.BDFDBhideDisplayState.display, node.BDFDBhideDisplayState.important ? "important" : "");
								delete node.BDFDBhideDisplayState;
							}
							else node.style.removeProperty("display");
						}
					}
				};
				BDFDB.DOMUtils.isHidden = function (node) {
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) return getComputedStyle(node, null).getPropertyValue("display") == "none";
				};
				BDFDB.DOMUtils.remove = function (...eles) {
					for (let ele of eles.flat(10).filter(n => n)) {
						if (Node.prototype.isPrototypeOf(ele)) ele.remove();
						else if (NodeList.prototype.isPrototypeOf(ele)) {
							let nodes = Array.from(ele);
							while (nodes.length) nodes.shift().remove();
						}
						else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) {
							let nodes = Array.from(document.querySelectorAll(c));
							while (nodes.length) nodes.shift().remove();
						}
					}
				};
				BDFDB.DOMUtils.create = function (html) {
					if (typeof html != "string" || !html.trim()) return null;
					let template = document.createElement("template");
					try {template.innerHTML = html.replace(/(?<!pre)>[\t\r\n]+<(?!pre)/g, "><");}
					catch (err) {template.innerHTML = html.replace(/>[\t\r\n]+<(?!pre)/g, "><");}
					if (template.content.childNodes.length == 1) return template.content.firstElementChild || template.content.firstChild;
					else {
						let wrapper = document.createElement("span");
						let nodes = Array.from(template.content.childNodes);
						while (nodes.length) wrapper.appendChild(nodes.shift());
						return wrapper;
					}
				};
				BDFDB.DOMUtils.getParent = function (listOrSelector, node) {
					let parent = null;
					if (Node.prototype.isPrototypeOf(node) && listOrSelector) {
						let list = NodeList.prototype.isPrototypeOf(listOrSelector) ? listOrSelector : typeof listOrSelector == "string" ? document.querySelectorAll(listOrSelector) : null;
						if (list) for (let listNode of list) if (listNode.contains(node)) {
							parent = listNode;
							break;
						}
					}
					return parent;
				};
				BDFDB.DOMUtils.setText = function (node, stringOrNode) {
					if (!node || !Node.prototype.isPrototypeOf(node)) return;
					let textnode = node.nodeType == Node.TEXT_NODE ? node : null;
					if (!textnode) for (let child of node.childNodes) if (child.nodeType == Node.TEXT_NODE || BDFDB.DOMUtils.containsClass(child, "BDFDB-textnode")) {
						textnode = child;
						break;
					}
					if (textnode) {
						if (Node.prototype.isPrototypeOf(stringOrNode) && stringOrNode.nodeType != Node.TEXT_NODE) {
							BDFDB.DOMUtils.addClass(stringOrNode, "BDFDB-textnode");
							node.replaceChild(stringOrNode, textnode);
						}
						else if (Node.prototype.isPrototypeOf(textnode) && textnode.nodeType != Node.TEXT_NODE) node.replaceChild(document.createTextNode(stringOrNode), textnode);
						else textnode.textContent = stringOrNode;
					}
					else node.appendChild(Node.prototype.isPrototypeOf(stringOrNode) ? stringOrNode : document.createTextNode(stringOrNode));
				};
				BDFDB.DOMUtils.getText = function (node) {
					if (!node || !Node.prototype.isPrototypeOf(node)) return;
					for (let child of node.childNodes) if (child.nodeType == Node.TEXT_NODE) return child.textContent;
				};
				BDFDB.DOMUtils.getRects = function (node) {
					let rects = {};
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) {
						let hideNode = node;
						while (hideNode) {
							let hidden = BDFDB.DOMUtils.isHidden(hideNode);
							if (hidden) {
								BDFDB.DOMUtils.toggle(hideNode, true);
								hideNode.BDFDBgetRectsHidden = true;
							}
							hideNode = hideNode.parentElement;
						}
						rects = node.getBoundingClientRect();
						hideNode = node;
						while (hideNode) {
							if (hideNode.BDFDBgetRectsHidden) {
								BDFDB.DOMUtils.toggle(hideNode, false);
								delete hideNode.BDFDBgetRectsHidden;
							}
							hideNode = hideNode.parentElement;
						}
					}
					return rects;
				};
				BDFDB.DOMUtils.getHeight = function (node) {
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) {
						let rects = BDFDB.DOMUtils.getRects(node);
						let style = getComputedStyle(node);
						return rects.height + parseInt(style.marginTop) + parseInt(style.marginBottom);
					}
					return 0;
				};
				BDFDB.DOMUtils.getInnerHeight = function (node) {
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) {
						let rects = BDFDB.DOMUtils.getRects(node);
						let style = getComputedStyle(node);
						return rects.height - parseInt(style.paddingTop) - parseInt(style.paddingBottom);
					}
					return 0;
				};
				BDFDB.DOMUtils.getWidth = function (node) {
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) {
						let rects = BDFDB.DOMUtils.getRects(node);
						let style = getComputedStyle(node);
						return rects.width + parseInt(style.marginLeft) + parseInt(style.marginRight);
					}
					return 0;
				};
				BDFDB.DOMUtils.getInnerWidth = function (node) {
					if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) {
						let rects = BDFDB.DOMUtils.getRects(node);
						let style = getComputedStyle(node);
						return rects.width - parseInt(style.paddingLeft) - parseInt(style.paddingRight);
					}
					return 0;
				};
				BDFDB.DOMUtils.appendWebScript = function (url, container) {
					if (typeof url != "string") return;
					if (!container && !document.body.querySelector("bd-head bd-scripts")) document.body.appendChild(BDFDB.DOMUtils.create(`<bd-head><bd-scripts></bd-scripts></bd-head>`));
					container = container || document.body.querySelector("bd-head bd-scripts") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.removeWebScript(url, container);
					let script = document.createElement("script");
					script.src = url;
					container.appendChild(script);
				};
				BDFDB.DOMUtils.removeWebScript = function (url, container) {
					if (typeof url != "string") return;
					container = container || document.body.querySelector("bd-head bd-scripts") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.remove(container.querySelectorAll(`script[src="${url}"]`));
				};
				BDFDB.DOMUtils.appendWebStyle = function (url, container) {
					if (typeof url != "string") return;
					if (!container && !document.body.querySelector("bd-head bd-styles")) document.body.appendChild(BDFDB.DOMUtils.create(`<bd-head><bd-styles></bd-styles></bd-head>`));
					container = container || document.body.querySelector("bd-head bd-styles") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.removeWebStyle(url, container);
					container.appendChild(BDFDB.DOMUtils.create(`<link type="text/css" rel="stylesheet" href="${url}"></link>`));
				};
				BDFDB.DOMUtils.removeWebStyle = function (url, container) {
					if (typeof url != "string") return;
					container = container || document.body.querySelector("bd-head bd-styles") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.remove(container.querySelectorAll(`link[href="${url}"]`));
				};
				BDFDB.DOMUtils.appendLocalStyle = function (id, css, container) {
					if (typeof id != "string" || typeof css != "string") return;
					if (!container && !document.body.querySelector("bd-head bd-styles")) document.body.appendChild(BDFDB.DOMUtils.create(`<bd-head><bd-styles></bd-styles></bd-head>`));
					container = container || document.body.querySelector("bd-head bd-styles") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.removeLocalStyle(id, container);
					container.appendChild(BDFDB.DOMUtils.create(`<style id="${id}CSS">${css.replace(/\t|\r|\n/g,"")}</style>`));
				};
				BDFDB.DOMUtils.removeLocalStyle = function (id, container) {
					if (typeof id != "string") return;
					container = container || document.body.querySelector("bd-head bd-styles") || document.body;
					container = Node.prototype.isPrototypeOf(container) ? container : document.body;
					BDFDB.DOMUtils.remove(container.querySelectorAll(`style[id="${id}CSS"]`));
				};
				
				BDFDB.ModalUtils = {};
				BDFDB.ModalUtils.open = function (plugin, config) {
					if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(config)) return;
					let modalInstance, modalProps, cancels = [], closeModal = _ => {
						if (BDFDB.ObjectUtils.is(modalProps) && typeof modalProps.onClose == "function") modalProps.onClose();
					};
					
					let titleChildren = [], headerChildren = [], contentChildren = [], footerChildren = [];
					
					if (typeof config.text == "string") {
						config.contentClassName = BDFDB.DOMUtils.formatClassName(config.contentClassName, BDFDB.disCN.modaltextcontent);
						contentChildren.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
							children: config.text
						}));
					}
					
					if (config.children) {
						let tabBarItems = [], tabIns = {};
						for (let child of [config.children].flat(10).filter(n => n)) if (Internal.LibraryModules.React.isValidElement(child)) {
							if (child.type == Internal.LibraryComponents.ModalComponents.ModalTabContent) {
								if (!tabBarItems.length) child.props.open = true;
								else delete child.props.open;
								let ref = typeof child.props.ref == "function" ? child.props.ref : (_ => {});
								child.props.ref = instance => {
									ref(instance);
									if (instance) tabIns[child.props.tab] = instance;
								};
								tabBarItems.push({value: child.props.tab});
							}
							contentChildren.push(child);
						}
						if (tabBarItems.length) headerChildren.push(BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.tabbarcontainer,
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TabBar, {
									className: BDFDB.disCN.tabbar,
									itemClassName: BDFDB.disCN.tabbaritem,
									type: Internal.LibraryComponents.TabBar.Types.TOP,
									items: tabBarItems,
									onItemSelect: value => {for (let key in tabIns) tabIns[key].setState({open: key == value});}
								}),
								config.tabBarChildren
							].flat(10).filter(n => n)
						}));
					}
					
					if (BDFDB.ArrayUtils.is(config.buttons)) for (let button of config.buttons) {
						let contents = typeof button.contents == "string" && button.contents;
						if (contents) {
							let color = typeof button.color == "string" && Internal.LibraryComponents.Button.Colors[button.color.toUpperCase()];
							let look = typeof button.look == "string" && Internal.LibraryComponents.Button.Looks[button.look.toUpperCase()];
							let click = typeof button.click == "function" ? button.click : (typeof button.onClick == "function" ? button.onClick : _ => {});
							
							if (button.cancel) cancels.push(click);
							
							footerChildren.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Button, BDFDB.ObjectUtils.exclude(Object.assign({}, button, {
								look: look || (color ? Internal.LibraryComponents.Button.Looks.FILLED : Internal.LibraryComponents.Button.Looks.LINK),
								color: color || Internal.LibraryComponents.Button.Colors.PRIMARY,
								onClick: _ => {
									if (button.close) closeModal();
									if (!(button.close && button.cancel)) click(modalInstance);
								},
								children: contents
							}), "click", "close", "cancel", "contents")));
						}
					}
					
					contentChildren = contentChildren.concat(config.contentChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n)));
					titleChildren = titleChildren.concat(config.titleChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n)));
					headerChildren = headerChildren.concat(config.headerChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n)));
					footerChildren = footerChildren.concat(config.footerChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n)));
					
					if (contentChildren.length) {
						if (typeof config.onOpen != "function") config.onOpen = _ => {};
						if (typeof config.onClose != "function") config.onClose = _ => {};
						
						let name = plugin.name || (typeof plugin.getName == "function" ? plugin.getName() : null);
						name = typeof name == "string" ? name : null;
						let oldTransitionState = 0;
						!Internal.LibraryModules.ModalUtils ? BdApi.UI.alert(BDFDB.ReactUtils.createElement("div", {
								style: {"display": "flex", "flex-direction": "column"},
								children: [
									config.header,
									typeof config.subHeader == "string" || BDFDB.ReactUtils.isValidElement(config.subHeader) ? config.subHeader : (name || "")
								].filter(n => n).map(n => BDFDB.ReactUtils.createElement("span", {children: n}))
							}), config.content || config.children) : Internal.LibraryModules.ModalUtils.openModal(props => {
							modalProps = props;
							return BDFDB.ReactUtils.createElement(class BDFDB_Modal extends Internal.LibraryModules.React.Component {
								render() {
									return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ModalComponents.ModalRoot, {
										className: BDFDB.DOMUtils.formatClassName(name && `${name}-modal`, BDFDB.disCN.modalwrapper, config.className),
										size: typeof config.size == "string" && Internal.LibraryComponents.ModalComponents.ModalSize[config.size.toUpperCase()] || Internal.LibraryComponents.ModalComponents.ModalSize.SMALL,
										transitionState: props.transitionState,
										children: [
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ModalComponents.ModalHeader, {
												className: BDFDB.DOMUtils.formatClassName(config.headerClassName, config.shade && BDFDB.disCN.modalheadershade, headerChildren.length && BDFDB.disCN.modalheaderhassibling),
												separator: config.headerSeparator || false,
												children: [
													BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
														style: {flex: 1},
														children: [
															BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormTitle.Title, {
																tag: Internal.LibraryComponents.FormTitle.Tags && Internal.LibraryComponents.FormTitle.Tags.H4,
																children: config.header
															}),
															BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
																size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
																children: typeof config.subHeader == "string" || BDFDB.ReactUtils.isValidElement(config.subHeader) ? config.subHeader : (name || "")
															})
														]
													}),
													titleChildren,
													BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ModalComponents.ModalCloseButton, {
														onClick: closeModal
													})
												].flat(10).filter(n => n)
											}),
											headerChildren.length ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
												grow: 0,
												shrink: 0,
												children: headerChildren
											}) : null,
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ModalComponents.ModalContent, {
												className: config.contentClassName,
												scroller: config.scroller,
												direction: config.direction,
												content: config.content,
												children: contentChildren
											}),
											footerChildren.length ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ModalComponents.ModalFooter, {
												className: config.footerClassName,
												direction: config.footerDirection,
												children: footerChildren
											}) : null
										]
									});
								}
								componentDidMount() {
									modalInstance = this;
									if (props.transitionState == 1 && props.transitionState > oldTransitionState) config.onOpen(modalInstance);
									oldTransitionState = props.transitionState;
								}
								componentWillUnmount() {
									if (props.transitionState == 2) {
										for (let cancel of cancels) cancel(modalInstance);
										config.onClose(modalInstance);
									}
								}
							}, props, true);
						}, {
							onCloseRequest: closeModal
						});
					}
				};
				BDFDB.ModalUtils.confirm = function (plugin, text, callback) {
					if (!BDFDB.ObjectUtils.is(plugin) || typeof text != "string") return;
					BDFDB.ModalUtils.open(plugin, {
						text: text,
						header: BDFDB.LanguageUtils.LibraryStrings.confirm,
						className: BDFDB.disCN.modalconfirmmodal,
						scroller: false,
						buttons: [
							{contents: BDFDB.LanguageUtils.LanguageStrings.OKAY, close: true, color: "RED", onClick: callback},
							{contents: BDFDB.LanguageUtils.LanguageStrings.CANCEL, close: true}
						]
					});
				};
				
				var MappedMenuItems = {}, RealMenuItems = BDFDB.ModuleUtils.find(m => {
					if (!m || typeof m != "function") return false;
					let string = m.toString();
					return string.indexOf("(){return null}") > -1 && string.indexOf("catch(") == -1 && string.split("){return null}").length > 4;
				});
				if (!RealMenuItems) {
					RealMenuItems = {};
					BDFDB.LogUtils.error(["could not find Module for MenuItems"]);
				}
				BDFDB.ContextMenuUtils = {};
				BDFDB.ContextMenuUtils.open = function (plugin, e, children) {
					Internal.LibraryModules.ContextMenuUtils.openContextMenu(e || mousePosition, _ => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Menu, {
						navId: "bdfdb-context",
						onClose: Internal.LibraryModules.ContextMenuUtils.closeContextMenu,
						children: children
					}, true));
				};
				BDFDB.ContextMenuUtils.close = function (nodeOrInstance) {
					if (!BDFDB.ObjectUtils.is(nodeOrInstance)) return;
					let instance = BDFDB.ReactUtils.findOwner(nodeOrInstance, {props: "closeContextMenu", up: true});
					if (BDFDB.ObjectUtils.is(instance) && instance.props && typeof instance.props.closeContextMenu == "function") instance.props.closeContextMenu();
					else Internal.LibraryModules.ContextMenuUtils.closeContextMenu();
				};
				BDFDB.ContextMenuUtils.createItem = function (component, props = {}) {
					if (!component) return null;
					else {
						if (props.render || props.persisting || BDFDB.ObjectUtils.is(props.popoutProps) || (typeof props.color == "string" && !InternalData.DiscordClasses[`menu${props.color.toLowerCase()}`])) component = Internal.MenuItem;
						if (BDFDB.ObjectUtils.toArray(RealMenuItems).some(c => c == component)) return BDFDB.ReactUtils.createElement(component, props);
						else return BDFDB.ReactUtils.createElement(LibraryComponents.MenuItems.MenuItem, {
							id: props.id,
							disabled: props.disabled,
							customItem: true,
							render: menuItemProps => {
								if (!props.state) props.state = BDFDB.ObjectUtils.extract(props, "checked", "value");
								return BDFDB.ReactUtils.createElement(Internal.CustomMenuItemWrapper, {
									disabled: props.disabled,
									childProps: Object.assign({}, props, menuItemProps, {color: props.color}),
									children: component
								}, true);
							}
						});
					}
				};
				BDFDB.ContextMenuUtils.createItemId = function (...strings) {
					return strings.map(s => typeof s == "number" ? s.toString() : s).filter(s => typeof s == "string").map(s => s.toLowerCase().replace(/\s/, "-")).join("-");
				};
				BDFDB.ContextMenuUtils.findItem = function (returnvalue, config) {
					if (!returnvalue || !BDFDB.ObjectUtils.is(config) || !config.label && !config.id) return [null, -1];
					config.label = config.label && [config.label].flat().filter(n => n);
					config.id = config.id && [config.id].flat().filter(n => n);
					let contextMenu = BDFDB.ArrayUtils.is(returnvalue) ? {props: {children: returnvalue}} : BDFDB.ReactUtils.findChild(returnvalue, {props: "navId"});
					if (contextMenu) {
						let children = BDFDB.ArrayUtils.is(contextMenu.props.children) ? contextMenu.props.children : [contextMenu.props.children];
						for (let i in children) if (children[i]) {
							if (check(children[i])) return [children, parseInt(i)];
							else if (BDFDB.ArrayUtils.is(children[i])) {
								for (let j in children[i]) if (check(children[i][j])) return [children[i], parseInt(j)];
							}
							else if (children[i].props && children[i].props.children) {
								if (BDFDB.ArrayUtils.is(children[i].props.children) && children[i].props.children.length) {
									let [possibleChildren, possibleIndex] = BDFDB.ContextMenuUtils.findItem(children[i].props.children, config);
									if (possibleIndex > -1) return [possibleChildren, possibleIndex];
								}
								else if (check(children[i].props.children)) {
									if (config.group) return [children, parseInt(i)];
									else {
										children[i].props.children = [children[i].props.children];
										return [children[i].props.children, 0];
									}
								}
								else if (children[i].props.children.props && children[i].props.children.props.children) {
									if (BDFDB.ArrayUtils.is(children[i].props.children.props.children) && children[i].props.children.props.children.length) {
										let [possibleChildren, possibleIndex] = BDFDB.ContextMenuUtils.findItem(children[i].props.children.props.children, config);
										if (possibleIndex > -1) return [possibleChildren, possibleIndex];
									}
									else if (check(children[i].props.children.props.children)) {
										if (config.group) return [children, parseInt(i)];
										else {
											children[i].props.children.props.children = [children[i].props.children.props.children];
											return [children[i].props.children.props.children, 0];
										}
									}
								}
							}
						}
						return [children, -1];
					}
					return [null, -1];
					
					function check (child) {
						if (!child) return false;
						let props = child.stateNode ? child.stateNode.props : child.props;
						if (!props) return false;
						return config.id && config.id.some(key => key == "devmode-copy-id" ? typeof props.id == "string" && props.id.startsWith(key) : props.id == key) || config.label && config.label.some(key => props.label == key);
					}
				};

				BDFDB.StringUtils = {};
				BDFDB.StringUtils.upperCaseFirstChar = function (string) {
					if (typeof string != "string") return "";
					else return "".concat(string.charAt(0).toUpperCase()).concat(string.slice(1));
				};
				BDFDB.StringUtils.charIsUpperCase = function (string) {
					if (typeof string != "string") return false;
					else string[0].toUpperCase() === string[0] && string[0].toLowerCase() !== string[0];
				};
				BDFDB.StringUtils.getAcronym = function (string) {
					if (typeof string != "string") return "";
					return string.replace(/'s /g," ").replace(/\w+/g, n => n[0]).replace(/\s/g, "");
				};
				BDFDB.StringUtils.cssValueToNumber = function (string) {
					if (typeof string != "string") return 0;
					const value = parseInt(string, 10);
					return isNaN(value) ? 0 : value;
				};
				BDFDB.StringUtils.htmlEscape = function (string) {
					let ele = document.createElement("div");
					ele.innerText = string;
					return ele.innerHTML;
				};
				BDFDB.StringUtils.regEscape = function (string) {
					return typeof string == "string" && string.replace(/([\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}])/g, "\\$1");
				};
				BDFDB.StringUtils.insertNRST = function (string) {
					return typeof string == "string" && string.replace(/\\r/g, "\r").replace(/\\n/g, "\n").replace(/\\t/g, "\t").replace(/\\s/g, " ");
				};
				BDFDB.StringUtils.equalCase = function (match, string) {
					if (typeof match != "string" || typeof string != "string") return "";
					let first = match.charAt(0);
					return first != first.toUpperCase() ? (string.charAt(0).toLowerCase() + string.slice(1)) : first != first.toLowerCase() ? (string.charAt(0).toUpperCase() + string.slice(1)) : string;
				};
				BDFDB.StringUtils.extractSelection = function (original, selection) {
					if (typeof original != "string") return "";
					if (typeof selection != "string") return original;
					let s = [], f = [], wrong = 0, canceled = false, done = false;
					for (let i of BDFDB.ArrayUtils.getAllIndexes(original, selection[0])) if (!done) {
						while (i <= original.length && !done) {
							let subSelection = selection.slice(s.filter(n => n != undefined).length);
							if (!subSelection && s.length - 20 <= selection.length) done = true;
							else for (let j in subSelection) if (!done && !canceled) {
								if (original[i] == subSelection[j]) {
									s[i] = subSelection[j];
									f[i] = subSelection[j];
									wrong = 0;
									if (i == original.length) done = true;
								}
								else {
									s[i] = null;
									f[i] = original[i];
									wrong++;
									if (wrong > 4) {
										s = [], f = [], wrong = 0, canceled = true;
										break;
									}
								}
								break;
							}
							canceled = false;
							i++;
						}
					}
					if (s.filter(n => n).length) {
						let reverseS = [].concat(s).reverse(), i = 0, j = 0;
						for (let k in s) {
							if (s[k] == null) i = parseInt(k) + 1;
							else break;
						}
						for (let k in reverseS) {
							if (reverseS[k] == null) j = parseInt(k) + 1;
							else break;
						}
						return f.slice(i, f.length - j).join("");
					}
					else return original;
				};
				
				BDFDB.SlateUtils = {};
				BDFDB.SlateUtils.isRichValue = function (richValue) {
					return richValue && typeof richValue == "object" && BDFDB.SlateUtils.toRichValue("").constructor.prototype.isPrototypeOf(richValue);
				};
				BDFDB.SlateUtils.toTextValue = function (richValue) {
					return BDFDB.SlateUtils.isRichValue(richValue) ? Internal.LibraryModules.SlateTextUtils.toTextValue(richValue) : "";
				};
				BDFDB.SlateUtils.toRichValue = function (string) {
					return typeof string == "string" ? Internal.LibraryModules.SlateRichUtils.toRichValue(string) : null;
				};
				
				BDFDB.NumberUtils = {};
				BDFDB.NumberUtils.formatBytes = function (bytes, sigDigits) {
					bytes = parseInt(bytes);
					if (isNaN(bytes) || bytes < 0) return "0 Bytes";
					if (bytes == 1) return "1 Byte";
					let size = Math.floor(Math.log(bytes) / Math.log(1024));
					return parseFloat((bytes / Math.pow(1024, size)).toFixed(sigDigits < 1 ? 0 : sigDigits > 20 ? 20 : sigDigits || 2)) + " " + ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][size];
				};
				BDFDB.NumberUtils.mapRange = function (from, to, value) {
					if (parseFloat(value) < parseFloat(from[0])) return parseFloat(to[0]);
					else if (parseFloat(value) > parseFloat(from[1])) return parseFloat(to[1]);
					else return parseFloat(to[0]) + (parseFloat(value) - parseFloat(from[0])) * (parseFloat(to[1]) - parseFloat(to[0])) / (parseFloat(from[1]) - parseFloat(from[0]));
				};
				BDFDB.NumberUtils.generateId = function (array) {
					array = BDFDB.ArrayUtils.is(array) ? array : [];
					let id = Math.floor(Math.random() * 1000000000);
					if (array.includes(id)) return BDFDB.NumberUtils.generateId(array);
					else {
						array.push(id);
						return id;
					}
				};
				BDFDB.NumberUtils.compareVersions = function (newV, oldV) {
					if (!newV || !oldV) return true;
					newV = newV.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n));
					oldV = oldV.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n));
					let length = Math.max(newV.length, oldV.length);
					if (!length) return true;
					if (newV.length > oldV.length) {
						let tempArray = new Array(newV.length - oldV.length);
						for (let i = 0; i < tempArray.length; i++) tempArray[i] = 0;
						oldV = tempArray.concat(oldV);
					}
					else if (newV.length < oldV.length) {
						let tempArray = new Array(oldV.length - newV.length);
						for (let i = 0; i < tempArray.length; i++) tempArray[i] = 0;
						newV = tempArray.concat(newV);
					}
					for (let i = 0; i < length; i++) for (let iOutdated = false, j = 0; j <= i; j++) {
						if (j == i && newV[j] < oldV[j]) return false;
						if (j < i) iOutdated = newV[j] == oldV[j];
						if ((j == 0 || iOutdated) && j == i && newV[j] > oldV[j]) return true;
					}
					return false;
				};
				BDFDB.NumberUtils.getVersionDifference = function (newV, oldV) {
					if (!newV || !oldV) return false;
					newV = newV.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n));
					oldV = oldV.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n));
					let length = Math.max(newV.length, oldV.length);
					if (!length) return false;
					if (newV.length > oldV.length) {
						let tempArray = new Array(newV.length - oldV.length);
						for (let i = 0; i < tempArray.length; i++) tempArray[i] = 0;
						oldV = tempArray.concat(oldV);
					}
					else if (newV.length < oldV.length) {
						let tempArray = new Array(oldV.length - newV.length);
						for (let i = 0; i < tempArray.length; i++) tempArray[i] = 0;
						newV = tempArray.concat(newV);
					}
					let oldValue = 0, newValue = 0;
					for (let i in oldV.reverse()) oldValue += (oldV[i] * (10 ** i));
					for (let i in newV.reverse()) newValue += (newV[i] * (10 ** i));
					return (newValue - oldValue) / (10 ** (length-1));
				};
				
				BDFDB.DiscordUtils = {};
				BDFDB.DiscordUtils.getSetting = function (category, key) {
					if (!category || !key) return;
					return BDFDB.LibraryStores.UserSettingsProtoStore && BDFDB.LibraryStores.UserSettingsProtoStore.settings[category] && BDFDB.LibraryStores.UserSettingsProtoStore.settings[category][key] && BDFDB.LibraryStores.UserSettingsProtoStore.settings[category][key].value;
				};
				BDFDB.DiscordUtils.setSetting = function (category, key, value) {
					if (!category || !key) return;
					let store = BDFDB.DiscordUtils.getSettingsStore();
					if (store) store.updateAsync(category, settings => {
						if (!settings) return;
						if (!settings[key]) settings[key] = {};
						if (BDFDB.ObjectUtils.is(value)) for (let k in value) settings[key][k] = value[k];
						else settings[key].value = value;
					}, Internal.DiscordConstants.UserSettingsActionTypes.INFREQUENT_USER_ACTION);
				};
				BDFDB.DiscordUtils.getSettingsStore = function () {
					return BDFDB.LibraryModules.UserSettingsProtoUtils && (Object.entries(BDFDB.LibraryModules.UserSettingsProtoUtils).find(n => n && n[1] && n[1].updateAsync && n[1].ProtoClass && n[1].ProtoClass.typeName && n[1].ProtoClass.typeName.endsWith(".PreloadedUserSettings")) || [])[1];
				};
				BDFDB.DiscordUtils.openLink = function (url, config = {}) {
					if ((config.inBuilt || config.inBuilt === undefined && Internal.settings.general.useChromium) && Internal.LibraryRequires.electron && Internal.LibraryRequires.electron.remote) {
						let browserWindow = new Internal.LibraryRequires.electron.remote.BrowserWindow({
							frame: true,
							resizeable: true,
							show: true,
							darkTheme: BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themedark,
							webPreferences: {
								nodeIntegration: false,
								nodeIntegrationInWorker: false
							}
						});
						browserWindow.setMenu(null);
						browserWindow.loadURL(url);
						if (config.minimized) browserWindow.minimize(null);
					}
					else window.open(url, "_blank");
				};
				window.DiscordNative && window.DiscordNative.app && window.DiscordNative.app.getPath("appData").then(path => {BDFDB.DiscordUtils.getFolder.base = path;});
				BDFDB.DiscordUtils.isPlaformEmbedded = function () {
					return Internal.LibraryModules.PlatformUtils && (Object.entries(Internal.LibraryModules.PlatformUtils).find(n => typeof n[1] == "boolean") || [])[1] || false;
				};
				BDFDB.DiscordUtils.getFolder = function () {
					if (!BDFDB.DiscordUtils.getFolder.base) return "";
					else if (BDFDB.DiscordUtils.getFolder.folder) return BDFDB.DiscordUtils.getFolder.folder;
					else {
						let folder;
						try {
							let build = BDFDB.DiscordUtils.getBuild();
							build = "discord" + (build == "stable" ? "" : build);
							folder = Internal.LibraryRequires.path.resolve(BDFDB.DiscordUtils.getFolder.base, build, BDFDB.DiscordUtils.getVersion());
						} 
						catch (err) {folder = BDFDB.DiscordUtils.getFolder.base;}
						return BDFDB.DiscordUtils.getFolder.folder = folder;
					}
				};
				BDFDB.DiscordUtils.getLanguage = function () {
					return Internal.LibraryModules.LanguageUtils && (Internal.LibraryModules.LanguageUtils.chosenLocale || Internal.LibraryModules.LanguageUtils._chosenLocale) || Internal.LibraryModules.LanguageIntlUtils && Internal.LibraryModules.LanguageIntlUtils.getSystemLocale && (Internal.LibraryModules.LanguageIntlUtils.getSystemLocale && Internal.LibraryModules.LanguageIntlUtils.getSystemLocale()) || document.querySelector("html[lang]").getAttribute("lang");
				};
				BDFDB.DiscordUtils.getBuild = function () {
					if (BDFDB.DiscordUtils.getBuild.build) return BDFDB.DiscordUtils.getBuild.build;
					else {
						let build;
						try {build = window.DiscordNative.app.getReleaseChannel();}
						catch (err) {
							let version = BDFDB.DiscordUtils.getVersion();
							if (version) {
								version = version.split(".");
								if (version.length == 3 && !isNaN(version = parseInt(version[2]))) build = version > 300 ? "stable" : version > 200 ? "canary" : "ptb";
								else build = "stable";
							}
							else build = "stable";
						}
						return BDFDB.DiscordUtils.getBuild.build = build;
					}
				};
				BDFDB.DiscordUtils.getVersion = function () {
					if (BDFDB.DiscordUtils.getVersion.version) return BDFDB.DiscordUtils.getVersion.version;
					else {
						let version;
						try {version = window.DiscordNative.app.getVersion();}
						catch (err) {version = "999.999.9999";}
						return BDFDB.DiscordUtils.getVersion.version = version;
					}
				};
				BDFDB.DiscordUtils.getTheme = function () {
					return BDFDB.LibraryStores.ThemeStore.theme == "light" ? BDFDB.disCN.themelight : BDFDB.disCN.themedark;
				};
				BDFDB.DiscordUtils.getZoomFactor = function () {
					let aRects = BDFDB.DOMUtils.getRects(document.querySelector(BDFDB.dotCN.appmount));
					let widthZoom = Math.round(100 * window.outerWidth / aRects.width);
					let heightZoom = Math.round(100 * window.outerHeight / aRects.height);
					return widthZoom < heightZoom ? widthZoom : heightZoom;
				};
				BDFDB.DiscordUtils.getFontScale = function () {
					return parseInt(document.firstElementChild.style.fontSize.replace("%", ""));
				};
				BDFDB.DiscordUtils.shake = function () {
					BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.appcontainer), {name: "Shakeable", unlimited: true, up: true}).shake();
				};
				BDFDB.DiscordUtils.rerenderAll = function (instant) {
					BDFDB.TimeUtils.clear(BDFDB.DiscordUtils.rerenderAll.timeout);
					BDFDB.DiscordUtils.rerenderAll.timeout = BDFDB.TimeUtils.timeout(_ => {
						let LayersProviderIns = BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.layers), {name: "LayersProvider", unlimited: true, up: true});
						let LayersProviderType = LayersProviderIns && BDFDB.ObjectUtils.get(LayersProviderIns, `${BDFDB.ReactUtils.instanceKey}.type`);
						if (!LayersProviderType) return;
						let parentSelector = "", notices = document.querySelector("#bd-notices");
						if (notices) {
							let parentClasses = []
							for (let i = 0, parent = notices.parentElement; i < 3; i++, parent = parent.parentElement) parentClasses.push(parent.className);
							parentSelector = parentClasses.reverse().map(n => !n ? "*" : `.${n.split(" ").join(".")}`).join(" > ");
						}
						BDFDB.PatchUtils.patch({name: "BDFDB DiscordUtils"}, LayersProviderType.prototype, "render", {after: e => {
							e.returnValue = BDFDB.ReactUtils.createElement(LayersProviderType, LayersProviderIns.props);
							BDFDB.ReactUtils.forceUpdate(LayersProviderIns);
							if (parentSelector) BDFDB.TimeUtils.timeout(_ => {
								if (!document.contains(notices)) {
									let parent = document.querySelector(parentSelector) || document.querySelector(BDFDB.dotCN.app).parentElement;
									if (parent) {
										parent.insertBefore(notices, parent.firstElementChild);
										let ZeresPluginLibrary = notices.querySelector("#outdated-plugins") && BDFDB.BDUtils.getPlugin("ZeresPluginLibrary");
										let updateChecker = ZeresPluginLibrary && ZeresPluginLibrary?.Library?.PluginUpdater?.checkAllPlugins;
										if (typeof updateChecker == "function") updateChecker.apply(ZeresPluginLibrary.Library.PluginUpdater);
									}
								}
							}, 1000);
						}}, {once: true});
						BDFDB.ReactUtils.forceUpdate(LayersProviderIns);
					}, instant ? 0 : 1000);
				};
				
				const DiscordClassModules = Object.assign({}, InternalData.CustomClassModules);
				Internal.DiscordClassModules = new Proxy(DiscordClassModules, {
					get: function (_, item) {
						if (DiscordClassModules[item]) return DiscordClassModules[item];
						if (!InternalData.DiscordClassModules[item]) return;
						DiscordClassModules[item] = BDFDB.ModuleUtils.findStringObject(InternalData.DiscordClassModules[item].props, Object.assign({}, InternalData.DiscordClassModules[item]));
						return DiscordClassModules[item] ? DiscordClassModules[item] : undefined;
					}
				});
				BDFDB.DiscordClassModules = Internal.DiscordClassModules;
				for (let item in InternalData.DiscordClassModules) if (!DiscordClassModules[item]) DiscordClassModules[item] = undefined;
				
				const DiscordClasses = Object.assign({}, InternalData.DiscordClasses);
				BDFDB.DiscordClasses = Object.assign({}, DiscordClasses);
				Internal.getDiscordClass = function (item, selector) {
					let className, fallbackClassName, notFoundAndLazyloaded = false;
					className = fallbackClassName = `${Internal.DiscordClassModules.BDFDB.BDFDBundefined}_${Internal.generateClassId()}`;
					if (DiscordClasses[item] === undefined) {
						BDFDB.LogUtils.warn([item, "not found in DiscordClasses"]);
						return className;
					} 
					else if (!BDFDB.ArrayUtils.is(DiscordClasses[item]) || DiscordClasses[item].length != 2) {
						BDFDB.LogUtils.warn([item, "is not an Array of Length 2 in DiscordClasses"]);
						return className;
					}
					else if (Internal.DiscordClassModules[DiscordClasses[item][0]] === undefined) {
						if (!InternalData.LazyloadedClassModules || !InternalData.LazyloadedClassModules[DiscordClasses[item][0]]) {
							BDFDB.LogUtils.warn([DiscordClasses[item][0], "not found in DiscordClassModules"]);
							return className;
						}
						else notFoundAndLazyloaded = true;
					}
					else if ([DiscordClasses[item][1]].flat().every(prop => Internal.DiscordClassModules[DiscordClasses[item][0]][prop] === undefined && !(JSON.stringify(Internal.DiscordClassModules[DiscordClasses[item][0]]).split(" ").find(n => n.startsWith(`${prop}_`) || n.endsWith(`-${prop}`)) || "").split("\"")[0])) {
						if (!InternalData.LazyloadedClassModules || !InternalData.LazyloadedClassModules[DiscordClasses[item][0]]) {
							BDFDB.LogUtils.warn([DiscordClasses[item][1], "not found in", DiscordClasses[item][0], "in DiscordClassModules"]);
							return className;
						}
						else notFoundAndLazyloaded = true;
					}
					if (notFoundAndLazyloaded) {
						className = `${DiscordClasses[item][1]}_${InternalData.LazyloadedClassModules[DiscordClasses[item][0]]}`;
						DiscordClassModules[DiscordClasses[item][0]] = Object.assign({}, DiscordClassModules[item], {[DiscordClasses[item][1]]: className});
					}
					else for (let prop of [DiscordClasses[item][1]].flat()) {
						className = Internal.DiscordClassModules[DiscordClasses[item][0]][prop] || (JSON.stringify(Internal.DiscordClassModules[DiscordClasses[item][0]]).split(" ").find(n => n.startsWith(`${prop}_`) || n.endsWith(`-${prop}`)) || "").split("\"")[0];
						if (className) break;
						else className = fallbackClassName;
					}
					if (selector) {
						className = className.split(" ").filter(n => n.indexOf("da-") != 0).join(selector ? "." : " ");
						className = className || fallbackClassName;
					}
					return BDFDB.ArrayUtils.removeCopies(className.split(" ")).join(" ") || fallbackClassName;
				};
				const generationChars = "0123456789abcdef".split("");
				Internal.generateClassId = function () {
					let id = "";
					while (id.length < 6) id += generationChars[Math.floor(Math.random() * generationChars.length)];
					return id;
				};
				BDFDB.disCN = new Proxy({}, {
					get: function (list, item) {
						return Internal.getDiscordClass(item, false).replace("#", "");
					}
				});
				BDFDB.disCNS = new Proxy({}, {
					get: function (list, item) {
						return Internal.getDiscordClass(item, false).replace("#", "") + " ";
					}
				});
				BDFDB.disCNC = new Proxy({}, {
					get: function (list, item) {
						return Internal.getDiscordClass(item, false).replace("#", "") + ",";
					}
				});
				BDFDB.dotCN = new Proxy({}, {
					get: function (list, item) {
						let className = Internal.getDiscordClass(item, true);
						return (className.indexOf("#") == 0 ? "" : ".") + className;
					}
				});
				BDFDB.dotCNS = new Proxy({}, {
					get: function (list, item) {
						let className = Internal.getDiscordClass(item, true);
						return (className.indexOf("#") == 0 ? "" : ".") + className + " ";
					}
				});
				BDFDB.dotCNC = new Proxy({}, {
					get: function (list, item) {
						let className = Internal.getDiscordClass(item, true);
						return (className.indexOf("#") == 0 ? "" : ".") + className + ",";
					}
				});
				BDFDB.notCN = new Proxy({}, {
					get: function (list, item) {
						return `:not(.${Internal.getDiscordClass(item, true).split(".")[0]})`;
					}
				});
				BDFDB.notCNS = new Proxy({}, {
					get: function (list, item) {
						return `:not(.${Internal.getDiscordClass(item, true).split(".")[0]}) `;
					}
				});
				BDFDB.notCNC = new Proxy({}, {
					get: function (list, item) {
						return `:not(.${Internal.getDiscordClass(item, true).split(".")[0]}),`;
					}
				});
				
				const LanguageStringsObj = Internal.LibraryModules.LanguageStore && Internal.LibraryModules.LanguageStore.Messages || Internal.LibraryModules.LanguageStore || {};
				const EngLanguageStringsObj = Internal.LibraryModules.EngLanguageStore && Internal.LibraryModules.EngLanguageStore.Messages || Internal.LibraryModules.EngLanguageStore || {};
				const LanguageStringFormatter = Internal.LibraryModules.LanguageIntlUtils && Internal.LibraryModules.LanguageIntlUtils.formatToPlainString;
				var LanguageStringFormattersObj = (BDFDB.ModuleUtils.findByString("use strict", "createLoader:", {exportsFilter: m => !m.messagesLoader, all: true}).find(n => n && (n.A || n.Z) && [InternalData.LanguageStringHashes.DISCORD].flat(10).some(hash => LanguageStringFormatter(n.A && n.A[hash] || n.Z && n.Z[hash]))) || {});
				LanguageStringFormattersObj = LanguageStringFormattersObj.A || LanguageStringFormattersObj.Z;
				
				const LanguageHashes = {};
				for (let hash of Object.keys(EngLanguageStringsObj)) LanguageHashes[(typeof EngLanguageStringsObj[hash] == "string" ? [EngLanguageStringsObj[hash]] : EngLanguageStringsObj[hash]).map(n => typeof n == "string" ? n : "PLACEHOLDER").join(" ").toUpperCase().replace(/[^a-zA-Z0-9 ]/g, "").split(" ").filter(n => n).join(" ").trim().replace(/ /g, "_")] = hash;
				
				const LibraryStrings = Object.assign({}, InternalData.LibraryStrings);
				BDFDB.LanguageUtils = {};
				BDFDB.LanguageUtils.languages = Object.assign({}, InternalData.Languages);
				BDFDB.LanguageUtils.getLanguage = function () {
					let lang = BDFDB.DiscordUtils.getLanguage() || "en";
					if (lang == "en-GB" || lang == "en-US") lang = "en";
					let langIds = lang.split("-");
					let langId = langIds[0];
					let langId2 = langIds[1] || "";
					lang = langId2 && langId.toUpperCase() !== langId2.toUpperCase() ? langId + "-" + langId2 : langId;
					return BDFDB.LanguageUtils.languages[lang] || BDFDB.LanguageUtils.languages[langId] || BDFDB.LanguageUtils.languages.en;
				};
				BDFDB.LanguageUtils.getName = function (language) {
					if (!language || typeof language.name != "string") return "";
					if (language.name.startsWith("Discord")) return language.name.slice(0, -1) + (language.ownlang && (BDFDB.LanguageUtils.languages[language.id] || {}).name != language.ownlang ? ` / ${language.ownlang}` : "") + ")";
					else return language.name + (language.ownlang && language.name != language.ownlang ? ` / ${language.ownlang}` : "");
				};
				BDFDB.LanguageUtils.LanguageStrings = new Proxy(LanguageHashes, {
					get: function (list, item) {
						let stringObj = LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]];
						if (!stringObj) BDFDB.LogUtils.warn([item, "not found in BDFDB.LanguageUtils.LanguageStrings"]);
						else {
							if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function" || BDFDB.ArrayUtils.is(stringObj)) return BDFDB.LanguageUtils.LanguageStringsFormat(item);
							else return (stringObj || "").replace(/[?!:\.]$/, "");
						}
						return "";
					}
				});
				BDFDB.LanguageUtils.LanguageStringsCheck = new Proxy(LanguageHashes, {
					get: function (list, item) {
						return !!(LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]]);
					}
				});
				let parseLanguageStringObj = obj => {
					let string = "";
					if (typeof obj == "string") string += obj;
					else if (BDFDB.ObjectUtils.is(obj)) {
						if (obj.content) string += parseLanguageStringObj(obj.content);
						else if (obj.children) string += parseLanguageStringObj(obj.children);
						else if (obj.props) string += parseLanguageStringObj(obj.props);
					}
					else if (BDFDB.ArrayUtils.is(obj)) for (let ele of obj) string += parseLanguageStringObj(ele);
					return (string || "").replace(/[?!:\.]$/, "");
				};
				BDFDB.LanguageUtils.LanguageStringsFormat = function (item, ...values) {
					if (item) {
						let stringObj = LanguageStringsObj[item] || LanguageStringsObj[LanguageHashes[item]];
						if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function" || BDFDB.ArrayUtils.is(stringObj)) {
							let i = 0, returnvalue, formatVars = {};
							let error = "\n";
							while (!returnvalue && i < 10) {
								i++;
								try {returnvalue = BDFDB.ArrayUtils.is(stringObj) ? LanguageStringFormatter(LanguageStringFormattersObj[LanguageHashes[item]], formatVars) : stringObj.format(formatVars, false);}
								catch (err) {
									error += "Error 1 " + err + "\n";
									returnvalue = null;
									let value = values.shift();
									value = value != null ? (value === 0 ? "0" : value) : "undefined";
									let valueName = (err.toString().split("for variable '")[1] || "").split("'")[0];
									formatVars[valueName] = valueName.endsWith("Hook") ? (_ => value) : value;
									if (stringObj.intMessage) {
										try {for (let hook of stringObj.intMessage.format(formatVars).match(/\([^\(\)]+\)/gi)) formatVars[hook.replace(/[\(\)]/g, "")] = n => n;}
										catch (err2) {error += "Error 2 " + err2 + "\n";}
									}
									if (stringObj.intlMessage) {
										try {for (let hook of stringObj.intlMessage.format(formatVars).match(/\([^\(\)]+\)/gi)) formatVars[hook.replace(/[\(\)]/g, "")] = n => n;}
										catch (err3) {error += "Error 3 " + err3 + "\n";}
									}
								}
							}
							if (returnvalue) return parseLanguageStringObj(returnvalue);
							else {
								BDFDB.LogUtils.warn([item, "failed to format string in BDFDB.LanguageUtils.LanguageStrings", error]);
								return "";
							}
						}
						else return BDFDB.LanguageUtils.LanguageStrings[item];
					}
					else BDFDB.LogUtils.warn([item, "enter a valid key to format the string in BDFDB.LanguageUtils.LanguageStrings"]);
					return "";
				};
				BDFDB.LanguageUtils.LibraryStrings = new Proxy(LibraryStrings.default || {}, {
					get: function (list, item) {
						let languageId = BDFDB.LanguageUtils.getLanguage().id;
						if (LibraryStrings[languageId] && LibraryStrings[languageId][item]) return LibraryStrings[languageId][item];
						else if (LibraryStrings.default[item]) return LibraryStrings.default[item];
						else BDFDB.LogUtils.warn([item, "not found in BDFDB.LanguageUtils.LibraryStrings"]);
						return "";
					}
				});
				BDFDB.LanguageUtils.LibraryStringsCheck = new Proxy(LibraryStrings.default || {}, {
					get: function (list, item) {
						return !!LibraryStrings.default[item];
					}
				});
				BDFDB.LanguageUtils.LibraryStringsFormat = function (item, ...values) {
					if (item) {
						let languageId = BDFDB.LanguageUtils.getLanguage().id, string = null;
						if (LibraryStrings[languageId] && LibraryStrings[languageId][item]) string = LibraryStrings[languageId][item];
						else if (LibraryStrings.default[item]) string = LibraryStrings.default[item];
						if (string) {
							for (let i = 0; i < values.length; i++) if (typeof values[i] == "string" || typeof values[i] == "number") string = string.replace(new RegExp(`{{var${i}}}`, "g"), values[i]);
							return string;
						}
						else BDFDB.LogUtils.warn([item, "not found in BDFDB.LanguageUtils.LibraryStrings"]);
					}
					else BDFDB.LogUtils.warn([item, "enter a valid key to format the string in BDFDB.LanguageUtils.LibraryStrings"]);
					return "";
				};
				BDFDB.TimeUtils.interval(interval => {
					if (BDFDB.DiscordUtils.getLanguage()) {
						BDFDB.TimeUtils.clear(interval);
						let language = BDFDB.LanguageUtils.getLanguage();
						if (language) BDFDB.LanguageUtils.languages.$discord = Object.assign({}, language, {name: `Discord (${language.name})`});
					}
				}, 100);
				for (let key in BDFDB.LanguageUtils.languages) try {
					if (new Date(0).toLocaleString(key, {second: 'numeric'}) != "0") {
						BDFDB.LanguageUtils.languages[key].numberMap = {};
						for (let i = 0; i < 10; i++) BDFDB.LanguageUtils.languages[key].numberMap[i] = new Date(i*1000).toLocaleString(key, {second: 'numeric'});
					}
				}
				catch (err) {}
				
				const reactInitialized = Internal.LibraryModules.React && Internal.LibraryModules.React.Component;
				Internal.setDefaultProps = function (component, defaultProps) {
					if (BDFDB.ObjectUtils.is(component)) component.defaultProps = Object.assign({}, component.defaultProps, defaultProps);
				};
				let openedItem;
				Internal.MenuItem = reactInitialized && class BDFDB_MenuItem extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {hovered: false};
					}
					componentWillUnmount() {
						if (openedItem == this.props.id) openedItem = null;
					}
					render() {
						let color = (typeof this.props.color == "string" ? this.props.color : Internal.DiscordConstants.MenuItemColors.DEFAULT).toLowerCase();
						let isCustomColor = false;
						if (color) {
							if (InternalData.DiscordClasses[`menucolor${color}`]) color = color;
							else if (BDFDB.ColorUtils.getType(color)) {
								isCustomColor = true;
								color = BDFDB.ColorUtils.convert(color, "RGBA");
							}
							else color = (Internal.DiscordConstants.MenuItemColors.DEFAULT || "").toLowerCase();
						}
						let renderPopout, onClose, hasPopout = BDFDB.ObjectUtils.is(this.props.popoutProps);
						if (hasPopout) {
							renderPopout = instance => {
								openedItem = this.props.id;
								return typeof this.props.popoutProps.renderPopout == "function" && this.props.popoutProps.renderPopout(instance);
							};
							onClose = instance => {
								openedItem = null;
								typeof this.props.popoutProps.onClose == "function" && this.props.popoutProps.onClose(instance);
							};
						}
						let focused = !openedItem ? this.props.isFocused : openedItem == this.props.id;
						let themeDark = BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themedark;
						let item = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, Object.assign({
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.menuitem, (this.props.label || this.props.subtext) && BDFDB.disCN.menulabelcontainer, color && (isCustomColor ? BDFDB.disCN.menucolorcustom : BDFDB.disCN[`menucolor${color}`]), this.props.disabled && BDFDB.disCN.menudisabled, focused && BDFDB.disCN.menufocused),
							style: {
								color: isCustomColor ? ((focused || this.state.hovered) ? (BDFDB.ColorUtils.isBright(color) ? "#000000" : "#ffffff") : color) : (this.state.hovered ? "#ffffff" : null),
								background: isCustomColor && (focused || this.state.hovered) && color
							},
							onClick: this.props.disabled ? null : e => {
								if (!this.props.action) return false;
								!this.props.persisting && !hasPopout && this.props.onClose && this.props.onClose();
								this.props.action(e, this);
							},
							onMouseEnter: this.props.disabled ? null : e => {
								if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);
								this.setState({hovered: true});
							},
							onMouseLeave: this.props.disabled ? null : e => {
								if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);
								this.setState({hovered: false});
							},
							"aria-disabled": this.props.disabled,
							children: [
								this.props.icon && this.props.showIconFirst && BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menuiconcontainerleft,
									children: BDFDB.ReactUtils.createElement(this.props.icon, {
										className: BDFDB.disCN.menuicon
									})
								}),
								typeof this.props.render == "function" ? this.props.render(this) : this.props.render,
								(this.props.label || this.props.subtext) && BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menulabel,
									children: [
										typeof this.props.label == "function" ? this.props.label(this) : this.props.label,
										this.props.subtext && BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.menusubtext,
											children: typeof this.props.subtext == "function" ? this.props.subtext(this) : this.props.subtext
										})
									].filter(n => n)
								}),
								this.props.hint && !this.props.showIconFirst && BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menuiconcontainer,
									children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.MenuHint, {
										children: typeof this.props.hint == "function" ? this.props.hint(this) : this.props.hint
									})
								}),
								this.props.icon && !this.props.showIconFirst && BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menuiconcontainer,
									children: BDFDB.ReactUtils.createElement(this.props.icon, {
										className: BDFDB.disCN.menuicon
									})
								}),
								this.props.input && BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menuiconcontainer,
									children: this.props.input
								})
							].filter(n => n)
						}, this.props.menuItemProps, {isFocused: focused}));
						return hasPopout ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutContainer, Object.assign({}, this.props.popoutProps, {
							children: item,
							renderPopout: renderPopout,
							onClose: onClose
						})) : item;
					}
				};
				Internal.CustomMenuItemWrapper = reactInitialized && class BDFDB_CustomMenuItemWrapper extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {hovered: false};
					}
					render() {
						let isItem = this.props.children == Internal.MenuItem;
						let item = BDFDB.ReactUtils.createElement(this.props.children, Object.assign({}, this.props.childProps, {
							onMouseEnter: isItem ? e => {
								if (this.props.childProps && typeof this.props.childProps.onMouseEnter == "function") this.props.childProps.onMouseEnter(e, this);
								this.setState({hovered: true});
							} : this.props.childProps && this.props.childProps.onMouseEnter,
							onMouseLeave: isItem ? e => {
								if (this.props.childProps && typeof this.props.childProps.onMouseLeave == "function") this.props.childProps.onMouseLeave(e, this);
								this.setState({hovered: false});
							} : this.props.childProps && this.props.childProps.onMouseLeave,
							isFocused: this.state.hovered && !this.props.disabled
						}));
						return isItem ? item : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							onMouseEnter: e => this.setState({hovered: true}),
							onMouseLeave: e => this.setState({hovered: false}),
							children: item
						});
					}
				};
				Internal.ErrorBoundary = reactInitialized && class BDFDB_ErrorBoundary extends Internal.LibraryModules.React.PureComponent {
					constructor(props) {
						super(props);
						this.state = {hasError: false};
					}
					static getDerivedStateFromError(err) {
						return {hasError: true};
					}
					componentDidCatch(err, info) {
						BDFDB.LogUtils.error(["Could not create React Element!", err]);
					}
					render() {
						if (this.state.hasError) return Internal.LibraryModules.React.createElement("span", {
							style: {
								background: Internal.DiscordConstants.Colors.PRIMARY,
								borderRadius: 5,
								color: BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER,
								fontSize: 12,
								fontWeight: 600,
								padding: 6,
								textAlign: "center",
								verticalAlign: "center"
							},
							children: "React Component Error"
						});
						return this.props.children;
					}
				};
				
				Internal.NativeSubComponents = new Proxy(NativeSubComponents, {
					get: function (_, item) {
						if (NativeSubComponents[item]) return NativeSubComponents[item];
						if (!InternalData.NativeSubComponents[item]) return "div";
						
						Internal.findModuleViaData(NativeSubComponents, InternalData.NativeSubComponents, item);
						
						return NativeSubComponents[item] ? NativeSubComponents[item] : "div";
					}
				});
				
				CustomComponents.AutoFocusCatcher = reactInitialized && class BDFDB_AutoFocusCatcher extends Internal.LibraryModules.React.Component {
					render() {
						const style = {padding: 0, margin: 0, border: "none", width: 0, maxWidth: 0, height: 0, maxHeight: 0, visibility: "hidden"};
						return BDFDB.ReactUtils.forceStyle(BDFDB.ReactUtils.createElement("input", {style}), Object.keys(style));
					}
				};
				
				CustomComponents.BadgeAnimationContainer = reactInitialized && class BDFDB_BadgeAnimationContainer extends Internal.LibraryModules.React.Component {
					componentDidMount() {BDFDB.ReactUtils.forceUpdate(this);}
					componentWillAppear(e) {if (typeof e == "function") e();}
					componentWillEnter(e) {if (typeof e == "function") e();}
					componentWillLeave(e) {if (typeof e == "function") this.timeoutId = setTimeout(e, 300);}
					componentWillUnmount() {BDFDB.TimeUtils.clear(this.timeoutId)}
					render() {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.div, {
							className: this.props.className,
							style: this.props.animatedStyle,
							children: this.props.children
						});
					}
				};
				
				CustomComponents.Badges = {};
				CustomComponents.Badges.getBadgePaddingForValue = function (count) {
					switch (count) {
						case 1:
						case 4:
						case 6:
							return 1;
						default:
							return 0;
					}
				};
				CustomComponents.Badges.IconBadge = reactInitialized && class BDFDB_IconBadge extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgeiconbadge, this.props.shape && Internal.LibraryComponents.Badges.BadgeShapes[this.props.shape] || Internal.LibraryComponents.Badges.BadgeShapes.ROUND),
							style: Object.assign({
								backgroundColor: this.props.disableColor ? null : (this.props.color || BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER)
							}, this.props.style),
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								className: BDFDB.disCN.badgeicon,
								name: this.props.icon
							})
						});
					}
				};
				CustomComponents.Badges.NumberBadge = reactInitialized && class BDFDB_NumberBadge extends Internal.LibraryModules.React.Component {
					handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}
					handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}
					handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
					handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
					getBadgeWidthForValue(e) {return e < 10 ? 16 : e < 100 ? 22 : 30}
					getBadgeCountString(e) {return e < 1e3 ? "" + e : Math.min(Math.floor(e/1e3), 9) + "k+"}
					render() {
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgenumberbadge, Internal.LibraryComponents.Badges && Internal.LibraryComponents.Badges.BadgeShapes && (this.props.shape && Internal.LibraryComponents.Badges.BadgeShapes[this.props.shape] || Internal.LibraryComponents.Badges.BadgeShapes.ROUND)),
							style: Object.assign({
								backgroundColor: !this.props.disableColor && (this.props.color || BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER),
								width: this.getBadgeWidthForValue(this.props.count)
							}, this.props.style),
							onClick: this.handleClick.bind(this),
							onContextMenu: this.handleContextMenu.bind(this),
							onMouseEnter: this.handleMouseEnter.bind(this),
							onMouseLeave: this.handleMouseLeave.bind(this),
							children: this.getBadgeCountString(this.props.count)
						});
					}
				};
				
				CustomComponents.BotTag = reactInitialized && class BDFDB_BotTag extends Internal.LibraryModules.React.Component {
					handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}
					handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}
					handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
					handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
					render() {
						return BDFDB.ReactUtils.createElement("span", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, this.props.invertColor ? BDFDB.disCN.bottaginvert : BDFDB.disCN.bottagregular, this.props.useRemSizes ? BDFDB.disCN.bottagrem : BDFDB.disCN.bottagpx),
							style: this.props.style,
							onClick: this.handleClick.bind(this),
							onContextMenu: this.handleContextMenu.bind(this),
							onMouseEnter: this.handleMouseEnter.bind(this),
							onMouseLeave: this.handleMouseLeave.bind(this),
							children: BDFDB.ReactUtils.createElement("span", {
								className: BDFDB.disCN.bottagtext,
								children: this.props.tag || BDFDB.LanguageUtils.LanguageStrings.BOT
							})
						});
					}
				};
				
				CustomComponents.Button = reactInitialized && class BDFDB_Button extends Internal.LibraryModules.React.Component {
					handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}
					handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}
					handleMouseDown(e) {if (typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this);}
					handleMouseUp(e) {if (typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this);}
					handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
					handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
					render() {
						if (!this.state) this.state = {disabled: this.props.disabled};
						let processingAndListening = (this.state.disabled || this.props.submitting) && (null != this.props.onMouseEnter || null != this.props.onMouseLeave);
						let props = BDFDB.ObjectUtils.exclude(this.props, "look", "color", "hover", "size", "fullWidth", "grow", "disabled", "submitting", "type", "style", "wrapperClassName", "className", "innerClassName", "onClick", "onContextMenu", "onMouseDown", "onMouseUp", "onMouseEnter", "onMouseLeave", "children", "rel");
						let button = BDFDB.ReactUtils.createElement("button", Object.assign({}, !this.state.disabled && !this.props.submitting && props, {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.button, this.props.look != null ? this.props.look : Internal.LibraryComponents.Button.Looks.FILLED, this.props.color != null ? this.props.color : Internal.LibraryComponents.Button.Colors.BRAND, this.props.hover, this.props.size != null ? this.props.size : Internal.LibraryComponents.Button.Sizes.MEDIUM, processingAndListening && this.props.wrapperClassName, this.props.fullWidth && BDFDB.disCN.buttonfullwidth, (this.props.grow === undefined || this.props.grow) && BDFDB.disCN.buttongrow, this.props.submitting && BDFDB.disCN.buttonsubmitting),
							onClick: (this.state.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleClick.bind(this),
							onContextMenu: (this.state.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleContextMenu.bind(this),
							onMouseUp: !this.state.disabled && this.handleMouseDown.bind(this),
							onMouseDown: !this.state.disabled && this.handleMouseUp.bind(this),
							onMouseEnter: this.handleMouseEnter.bind(this),
							onMouseLeave: this.handleMouseLeave.bind(this),
							type: !this.props.type ? "button" : this.props.type,
							disabled: this.state.disabled,
							style: this.props.style,
							rel: this.props.rel,
							children: [
								this.props.submitting && !this.state.disabled ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SpinnerComponents.Spinner, {
									type: Internal.LibraryComponents.SpinnerComponents.Types.PULSING_ELLIPSIS,
									className: BDFDB.disCN.buttonspinner,
									itemClassName: BDFDB.disCN.buttonspinneritem
								}) : null,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.buttoncontents, this.props.innerClassName),
									children: this.props.children
								})
							]
						}));
						return !processingAndListening ? button : BDFDB.ReactUtils.createElement("span", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.buttondisabledwrapper, this.props.wrapperClassName, this.props.size != null ? this.props.size : Internal.LibraryComponents.Button.Sizes.MEDIUM, this.props.fullWidth && BDFDB.disCN.buttonfullwidth, (this.props.grow === undefined || this.props.grow) && BDFDB.disCN.buttongrow),
							children: [
								button,
								BDFDB.ReactUtils.createElement("span", {
									onMouseEnter: this.handleMouseEnter.bind(this),
									onMouseLeave: this.handleMouseLeave.bind(this),
									className: BDFDB.disCN.buttondisabledoverlay
								})
							]
						});
					}
				};
				
				CustomComponents.Card = reactInitialized && class BDFDB_Card extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.hovercardwrapper, this.props.horizontal && BDFDB.disCN.hovercardhorizontal, this.props.backdrop && BDFDB.disCN.hovercard, this.props.className),
							onMouseEnter: e => {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);},
							onMouseLeave: e => {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);},
							onClick: e => {if (typeof this.props.onClick == "function") this.props.onClick(e, this);},
							onContextMenu: e => {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);},
							children: [
								!this.props.noRemove ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
									"aria-label": BDFDB.LanguageUtils.LanguageStrings.REMOVE,
									className: BDFDB.disCNS.hovercardbutton + BDFDB.disCNS.hovercardremovebutton + BDFDB.disCN.hovercardremovebuttondefault,
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
										nativeClass: true,
										name: Internal.LibraryComponents.SvgIcon.Names.REMOVE
									}),
									onClick: e => {
										if (typeof this.props.onRemove == "function") this.props.onRemove(e, this);
										BDFDB.ListenerUtils.stopEvent(e);
									}
								}) : null,
								typeof this.props.children == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
									className: BDFDB.disCN.hovercardinner,
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {children: this.props.children})
								}) : this.props.children
							].flat(10).filter(n => n)
						}), "backdrop", "horizontal", "noRemove"));
					}
				};
				Internal.setDefaultProps(CustomComponents.Card, {backdrop: true, noRemove: false});
				
				CustomComponents.ChannelTextAreaButton = reactInitialized && class BDFDB_ChannelTextAreaButton extends Internal.LibraryModules.React.Component {
					render() {
						const inner = BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.textareabuttonwrapper,
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								name: this.props.iconName,
								iconSVG: this.props.iconSVG,
								className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textareaicon, this.props.iconClassName, this.props.pulse && BDFDB.disCN.textareaiconpulse),
								nativeClass: this.props.nativeClass
							})
						});
						const button = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Button, {
							look: Internal.LibraryComponents.Button.Looks.BLANK,
							size: Internal.LibraryComponents.Button.Sizes.NONE,
							"aria-label": this.props.label,
							tabIndex: this.props.tabIndex,
							className: BDFDB.DOMUtils.formatClassName(this.props.isActive && BDFDB.disCN.textareabuttonactive),
							innerClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textareabutton, this.props.className, this.props.pulse && BDFDB.disCN.textareaattachbuttonplus),
							onClick: this.props.onClick,
							onContextMenu: this.props.onContextMenu,
							onMouseEnter: this.props.onMouseEnter,
							onMouseLeave: this.props.onMouseLeave,
							children: this.props.tooltip && this.props.tooltip.text ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, Object.assign({}, this.props.tooltip, {children: inner})) : inner
						});
						return (this.props.className || "").indexOf(BDFDB.disCN.textareapickerbutton) > -1 ? BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.textareapickerbuttoncontainer,
							children: button
						}) : button;
					}
				};
				Internal.setDefaultProps(CustomComponents.ChannelTextAreaButton, {tabIndex: 0});
				
				CustomComponents.CharCounter = reactInitialized && class BDFDB_CharCounter extends Internal.LibraryModules.React.Component {
					getCounterString() {
						let input = this.refElement || {}, string = "";
						if (BDFDB.DOMUtils.containsClass(this.refElement, BDFDB.disCN.textarea)) {
							let instance = BDFDB.ReactUtils.findOwner(input, {name: "ChannelTextAreaEditor", up: true});
							if (instance) string = instance.props.textValue;
							else string = input.value || input.textContent || "";
						}
						else string = input.value || input.textContent || "";
						if (this.props.max && this.props.showPercentage && (string.length/this.props.max) * 100 < this.props.showPercentage) return "";
						let start = input.selectionStart || 0, end = input.selectionEnd || 0, selectlength = end - start, selection = BDFDB.DOMUtils.getSelection();
						let select = !selectlength && !selection ? 0 : (selectlength || selection.length);
						select = !select ? 0 : (select > string.length ? (end || start ? string.length - (string.length - end - start) : string.length) : select);
						let children = [
							typeof this.props.renderPrefix == "function" && this.props.renderPrefix(string.length),
							`${string.length}${!this.props.max ? "" : "/" + this.props.max}${!select ? "" : " (" + select + ")"}`,
							typeof this.props.renderSuffix == "function" && this.props.renderSuffix(string.length)
						].filter(n => n);
						if (typeof this.props.onChange == "function") this.props.onChange(this);
						return children.length == 1 ? children[0] : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
							align: Internal.LibraryComponents.Flex.Align.CENTER,
							children: children
						});
					}
					updateCounter() {
						if (!this.refElement) return;
						BDFDB.TimeUtils.clear(this.updateTimeout);
						this.updateTimeout = BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 100);
					}
					forceUpdateCounter() {
						if (!this.refElement) return;
						this.props.children = this.getCounterString();
						BDFDB.ReactUtils.forceUpdate(this);
					}
					handleSelection() {
						if (!this.refElement) return;
						let mouseMove = _ => {
							BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 10);
						};
						let mouseUp = _ => {
							document.removeEventListener("mousemove", mouseMove);
							document.removeEventListener("mouseup", mouseUp);
							if (this.refElement.selectionEnd - this.refElement.selectionStart) BDFDB.TimeUtils.timeout(_ => {
								document.addEventListener("click", click);
							});
						};
						let click = _ => {
							BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 100);
							document.removeEventListener("mousemove", mouseMove);
							document.removeEventListener("mouseup", mouseUp);
							document.removeEventListener("click", click);
						};
						document.addEventListener("mousemove", mouseMove);
						document.addEventListener("mouseup", mouseUp);
					}
					componentDidMount() {
						if (this.props.refClass) {
							let node = BDFDB.ReactUtils.findDOMNode(this);
							if (node && node.parentElement) {
								let parent = node.parentElement, loop = 0;
								while (!this.refElement && parent && loop < 5) {
									this.refElement = parent.querySelector(this.props.refClass);
									parent = parent.parentElement;
									loop++;
								}
								if (this.refElement) {
									if (!this._updateCounter) this._updateCounter = _ => {
										if (!document.contains(node)) BDFDB.ListenerUtils.multiRemove(this.refElement, "keydown click change", this._updateCounter);
										else this.updateCounter();
									};
									if (!this._handleSelection) this._handleSelection = _ => {
										if (!document.contains(node)) BDFDB.ListenerUtils.multiRemove(this.refElement, "mousedown", this._handleSelection);
										else this.handleSelection();
									};
									BDFDB.ListenerUtils.multiRemove(this.refElement, "mousedown", this._handleSelection);
									BDFDB.ListenerUtils.multiAdd(this.refElement, "mousedown", this._handleSelection);
									if (this.refElement.tagName == "INPUT" || this.refElement.tagName == "TEXTAREA") {
										BDFDB.ListenerUtils.multiRemove(this.refElement, "keydown click change", this._updateCounter);
										BDFDB.ListenerUtils.multiAdd(this.refElement, "keydown click change", this._updateCounter);
									}
									else {
										if (!this._mutationObserver) this._mutationObserver = new MutationObserver(changes => {
											if (!document.contains(node)) this._mutationObserver.disconnect();
											else this.updateCounter();
										});
										else this._mutationObserver.disconnect();
										this._mutationObserver.observe(this.refElement, {childList: true, subtree: true});
									}
									this.updateCounter();
								}
								else BDFDB.LogUtils.warn(["could not find referenceElement for BDFDB_CharCounter"]);
							}
						}
						else BDFDB.LogUtils.warn(["refClass can not be undefined for BDFDB_CharCounter"]);
					}
					render() {
						let string = this.getCounterString();
						BDFDB.TimeUtils.timeout(_ => string != this.getCounterString() && BDFDB.ReactUtils.forceUpdate(this));
						return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.charcounter, this.props.className),
							children: string
						}), "parsing", "max", "refClass", "renderPrefix", "renderSuffix", "showPercentage"));
					}
				};
				
				CustomComponents.Checkbox = reactInitialized && class BDFDB_Checkbox extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleMouseDown(e) {if (typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this);}
							handleMouseUp(e) {if (typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this);}
							handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
							handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
							getInputMode() {
								return this.props.disabled ? "disabled" : this.props.readOnly ? "readonly" : "default";
							}
							getStyle() {
								let style = this.props.style || {};
								if (!this.props.value) return style;
								style = Object.assign({}, style);
								this.props.color = typeof this.props.getColor == "function" ? this.props.getColor(this.props.value) : this.props.color;
								if (Internal.LibraryComponents.Checkbox.Types) switch (this.props.type) {
									case Internal.LibraryComponents.Checkbox.Types.DEFAULT:
										style.borderColor = this.props.color;
										break;
									case Internal.LibraryComponents.Checkbox.Types.GHOST:
										let color = BDFDB.ColorUtils.setAlpha(this.props.color, 0.15, "RGB");
										style.backgroundColor = color;
										style.borderColor = color;
										break;
									case Internal.LibraryComponents.Checkbox.Types.INVERTED:
										style.backgroundColor = this.props.color;
										style.borderColor = this.props.color;
								}
								return style;
							}
							getColor() {
								return this.props.value ? (Internal.LibraryComponents.Checkbox.Types && this.props.type === Internal.LibraryComponents.Checkbox.Types.INVERTED ? Internal.DiscordConstants.Colors.WHITE : this.props.color) : "transparent";
							}
							handleChange(e) {
								this.props.value = typeof this.props.getValue == "function" ? this.props.getValue(this.props.value, e, this) : !this.props.value;
								if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							render() {
								let label = this.props.children ? BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkboxlabel, this.props.disabled ? BDFDB.disCN.checkboxlabeldisabled : BDFDB.disCN.checkboxlabelclickable, this.props.reverse ? BDFDB.disCN.checkboxlabelreversed : BDFDB.disCN.checkboxlabelforward),
									style: {
										lineHeight: this.props.size + "px"
									},
									children: this.props.children
								}) : null;
								return BDFDB.ReactUtils.createElement("label", {
									className: BDFDB.DOMUtils.formatClassName(this.props.disabled ? BDFDB.disCN.checkboxwrapperdisabled : BDFDB.disCN.checkboxwrapper, this.props.align, this.props.className),
									children: [
										this.props.reverse && label,
										!this.props.displayOnly && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FocusRingScope, {
											children: BDFDB.ReactUtils.createElement("input", {
												className: BDFDB.disCN["checkboxinput" + this.getInputMode()],
												type: "checkbox",
												onClick: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this),
												onContextMenu: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this),
												onMouseUp: !this.props.disabled && this.handleMouseDown.bind(this),
												onMouseDown: !this.props.disabled && this.handleMouseUp.bind(this),
												onMouseEnter: !this.props.disabled && this.handleMouseEnter.bind(this),
												onMouseLeave: !this.props.disabled && this.handleMouseLeave.bind(this),
												checked: this.props.value,
												style: {
													width: this.props.size,
													height: this.props.size
												}
											})
										}),
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkbox, BDFDB.disCN["checkbox" + this.props.shape], this.props.value && BDFDB.disCN.checkboxchecked),
											style: Object.assign({
												width: this.props.size,
												height: this.props.size,
												borderColor: this.props.checkboxColor
											}, this.getStyle()),
											children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Checkmark, {
												size: "null",
												width: 18,
												height: 18,
												color: this.getColor(),
												"aria-hidden": true
											})
										}),
										!this.props.reverse && label
									].filter(n => n)
								});
							}
						}, this.props);
					}
				};
				if (CustomComponents.Checkbox) {
					CustomComponents.Checkbox.Types = {
						DEFAULT: "DEFAULT",
						GHOST: "GHOST",
						INVERTED: "INVERTED"
					};
					CustomComponents.Checkbox.Shapes = {
						BOX: "box",
						ROUND: "round"
					};
					Internal.setDefaultProps(CustomComponents.Checkbox, {type: CustomComponents.Checkbox.Types.INVERTED, shape: CustomComponents.Checkbox.Shapes.ROUND});
				}
				
				CustomComponents.Clickable = reactInitialized && class BDFDB_Clickable extends Internal.LibraryModules.React.Component {
					handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}
					handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}
					handleMouseDown(e) {if (typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this);}
					handleMouseUp(e) {if (typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this);}
					handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
					handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
					render() {
						return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.Clickable, Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, (this.props.className || "").toLowerCase().indexOf("disabled") == -1 && BDFDB.disCN.cursorpointer),
							onClick: this.handleClick.bind(this),
							onContextMenu: this.handleContextMenu.bind(this),
							onMouseUp: this.handleMouseDown.bind(this),
							onMouseDown: !this.props.disabled && this.handleMouseUp.bind(this),
							onMouseEnter: this.handleMouseEnter.bind(this),
							onMouseLeave: this.handleMouseLeave.bind(this)
						}));
					}
				};
				
				CustomComponents.CollapseContainer = reactInitialized && class BDFDB_CollapseContainer extends Internal.LibraryModules.React.Component {
					render() {
						if (!BDFDB.ObjectUtils.is(this.props.collapseStates)) this.props.collapseStates = {};
						this.props.collapsed = this.props.collapsed && (this.props.collapseStates[this.props.title] || this.props.collapseStates[this.props.title] === undefined);
						this.props.collapseStates[this.props.title] = this.props.collapsed;
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.collapsed && BDFDB.disCN.collapsecontainercollapsed, this.props.mini ? BDFDB.disCN.collapsecontainermini : BDFDB.disCN.collapsecontainer, this.props.className),
							id: this.props.id,
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
									className: BDFDB.disCN.collapsecontainerheader,
									align: Internal.LibraryComponents.Flex.Align.CENTER,
									onClick: e => {
										this.props.collapsed = !this.props.collapsed;
										this.props.collapseStates[this.props.title] = this.props.collapsed;
										if (typeof this.props.onClick == "function") this.props.onClick(this.props.collapsed, this);
										BDFDB.ReactUtils.forceUpdate(this);
									},
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormTitle.Title, {
										tag: Internal.LibraryComponents.FormTitle.Tags && Internal.LibraryComponents.FormTitle.Tags.H5,
										className: BDFDB.disCN.collapsecontainertitle,
										children: this.props.title
									})
								}),
								!this.props.collapsed ? BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.collapsecontainerinner,
									children: this.props.children
								}) : null
							]
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.CollapseContainer, {collapsed: true, mini: true});
				
				CustomComponents.ColorPicker = reactInitialized && class BDFDB_ColorPicker extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						if (!this.state) this.state = {};
						this.state.isGradient = props.gradient && props.color && BDFDB.ObjectUtils.is(props.color);
						this.state.gradientBarEnabled = this.state.isGradient;
						this.state.draggingAlphaCursor = false;
						this.state.draggingGradientCursor = false;
						this.state.selectedGradientCursor = 0;
					}
					handleColorChange(color) {
						let changed = false;
						if (color != null) {
							changed = !BDFDB.equals(this.state.isGradient ? this.props.color[this.state.selectedGradientCursor] : this.props.color, color);
							if (this.state.isGradient) this.props.color[this.state.selectedGradientCursor] = color;
							else this.props.color = color;
						}
						else changed = true;
						if (changed) {
							if (typeof this.props.onColorChange == "function") this.props.onColorChange(BDFDB.ColorUtils.convert(this.props.color, "RGBCOMP"));
							BDFDB.ReactUtils.forceUpdate(this);
						}
					}
					render() {
						if (this.state.isGradient) this.props.color = Object.assign({}, this.props.color);
						
						let colorFormat = this.props.alpha ? "HSVA" : "HSV";
						let hexRegex = this.props.alpha ? /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i : /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
						
						let selectedColor = BDFDB.ColorUtils.convert(this.state.isGradient ? this.props.color[this.state.selectedGradientCursor] : this.props.color, colorFormat) || BDFDB.ColorUtils.convert("#000000FF", colorFormat);
						let currentGradient = (this.state.isGradient ? Object.entries(this.props.color, colorFormat) : [[0, selectedColor], [1, selectedColor]]);
						
						let [h, s, v] = BDFDB.ColorUtils.convert(selectedColor, "HSVCOMP");
						let a = BDFDB.ColorUtils.getAlpha(selectedColor);
						a = a == null ? 1 : a;
						
						let hexColor = BDFDB.ColorUtils.convert(selectedColor, this.props.alpha ? "HEXA" : "HEX");
						let hexLength = hexColor.length;
						
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutFocusLock, {
							className: BDFDB.disCNS.colorpickerwrapper + BDFDB.disCN.colorpicker,
							children: [
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.colorpickerinner,
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.colorpickersaturation,
											children: BDFDB.ReactUtils.createElement("div", {
												className: BDFDB.disCN.colorpickersaturationcolor,
												style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0, cursor: "crosshair", backgroundColor: BDFDB.ColorUtils.convert([h, "100%", "50%"], "RGB")},
												onClick: event => {
													let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickersaturationcolor, event.target));
													this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event.clientY) + "%", a], colorFormat, "HSVCOMP"));
												},
												onMouseDown: event => {
													let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickersaturationcolor, event.target));
													let mouseUp = _ => {
														document.removeEventListener("mouseup", mouseUp);
														document.removeEventListener("mousemove", mouseMove);
													};
													let mouseMove = event2 => {
														this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event2.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event2.clientY) + "%", a], colorFormat, "HSVCOMP"));
													};
													document.addEventListener("mouseup", mouseUp);
													document.addEventListener("mousemove", mouseMove);
												},
												children: [
													BDFDB.ReactUtils.createElement("style", {
														children: `${BDFDB.dotCN.colorpickersaturationwhite} {background: -webkit-linear-gradient(to right, #fff, rgba(255,255,255,0));background: linear-gradient(to right, #fff, rgba(255,255,255,0));}${BDFDB.dotCN.colorpickersaturationblack} {background: -webkit-linear-gradient(to top, #000, rgba(0,0,0,0));background: linear-gradient(to top, #000, rgba(0,0,0,0));}`
													}),
													BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.colorpickersaturationwhite,
														style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
														children: [
															BDFDB.ReactUtils.createElement("div", {
																className: BDFDB.disCN.colorpickersaturationblack,
																style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}
															}),
															BDFDB.ReactUtils.createElement("div", {
																className: BDFDB.disCN.colorpickersaturationcursor,
																style: {position: "absolute", cursor: "crosshair", left: s, top: `${BDFDB.NumberUtils.mapRange([0, 100], [100, 0], parseFloat(v))}%`},
																children: BDFDB.ReactUtils.createElement("div", {
																	style: {width: 4, height: 4, boxShadow: "rgb(255, 255, 255) 0px 0px 0px 1.5px, rgba(0, 0, 0, 0.3) 0px 0px 1px 1px inset, rgba(0, 0, 0, 0.4) 0px 0px 1px 2px", borderRadius: "50%", transform: "translate(-2px, -2px)"}
																})
															})
														]
													})
												]
											})
										}),
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.colorpickerhue,
											children: BDFDB.ReactUtils.createElement("div", {
												style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
												children: BDFDB.ReactUtils.createElement("div", {
													className: BDFDB.disCN.colorpickerhuehorizontal,
													style: {padding: "0px 2px", position: "relative", height: "100%"},
													onClick: event => {
														let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target));
														this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event.clientX), s, v, a], colorFormat, "HSVCOMP"));
													},
													onMouseDown: event => {
														let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target));
														let mouseUp = _ => {
															document.removeEventListener("mouseup", mouseUp);
															document.removeEventListener("mousemove", mouseMove);
														};
														let mouseMove = event2 => {
															this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event2.clientX), s, v, a], colorFormat, "HSVCOMP"));
														};
														document.addEventListener("mouseup", mouseUp);
														document.addEventListener("mousemove", mouseMove);
													},
													children: [
														BDFDB.ReactUtils.createElement("style", {
															children: `${BDFDB.dotCN.colorpickerhuehorizontal} {background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}${BDFDB.dotCN.colorpickerhuevertical} {background: linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}`
														}),
														BDFDB.ReactUtils.createElement("div", {
															className: BDFDB.disCN.colorpickerhuecursor,
															style: {position: "absolute", cursor: "ew-resize", left: `${BDFDB.NumberUtils.mapRange([0, 360], [0, 100], h)}%`},
															children: BDFDB.ReactUtils.createElement("div", {
																style: {marginTop: 1, width: 4, borderRadius: 1, height: 8, boxShadow: "rgba(0, 0, 0, 0.6) 0px 0px 2px", background: "rgb(255, 255, 255)", transform: "translateX(-2px)"}
															})
														})
													]
												})
											})
										}),
										this.props.alpha && BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.colorpickeralpha,
											children: [
												BDFDB.ReactUtils.createElement("div", {
													style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
													children: BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.colorpickeralphacheckered,
														style: {padding: "0px 2px", position: "relative", height: "100%"}
													})
												}),
												BDFDB.ReactUtils.createElement("div", {
													style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
													children: BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.colorpickeralphahorizontal,
														style: {padding: "0px 2px", position: "relative", height: "100%", background: `linear-gradient(to right, ${BDFDB.ColorUtils.setAlpha([h, s, v], 0, "RGBA")}, ${BDFDB.ColorUtils.setAlpha([h, s, v], 1, "RGBA")}`},
														onClick: event => {
															let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target));
															this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, v], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event.clientX), colorFormat));
														},
														onMouseDown: event => {
															let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target));
															let mouseUp = _ => {
																document.removeEventListener("mouseup", mouseUp);
																document.removeEventListener("mousemove", mouseMove);
																this.state.draggingAlphaCursor = false;
																BDFDB.ReactUtils.forceUpdate(this);
															};
															let mouseMove = event2 => {
																this.state.draggingAlphaCursor = true;
																this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, v], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event2.clientX), colorFormat));
															};
															document.addEventListener("mouseup", mouseUp);
															document.addEventListener("mousemove", mouseMove);
														},
														children: BDFDB.ReactUtils.createElement("div", {
															className: BDFDB.disCN.colorpickeralphacursor,
															style: {position: "absolute", cursor: "ew-resize", left: `${a * 100}%`},
															children: [
																BDFDB.ReactUtils.createElement("div", {
																	style: {marginTop: 1, width: 4, borderRadius: 1, height: 8, boxShadow: "rgba(0, 0, 0, 0.6) 0px 0px 2px", background: "rgb(255, 255, 255)", transform: "translateX(-2px)"}
																}),
																this.state.draggingAlphaCursor && BDFDB.ReactUtils.createElement("span", {
																	className: BDFDB.disCN.sliderbubble,
																	style: {opacity: 1, visibility: "visible", left: 2},
																	children: `${Math.floor(a * 100)}%`
																})
															].filter(n => n)
														})
													})
												})
											]
										}),
										this.state.gradientBarEnabled && BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.colorpickergradient,
											children: [
												BDFDB.ReactUtils.createElement("div", {
													style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
													children: BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.colorpickergradientcheckered,
														style: {padding: "0px 2px", position: "relative", height: "100%"}
													})
												}),
												BDFDB.ReactUtils.createElement("div", {
													style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0},
													children: BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.colorpickergradienthorizontal,
														style: {padding: "0px 2px", position: "relative", cursor: "copy", height: "100%", background: BDFDB.ColorUtils.createGradient(currentGradient.reduce((colorObj, posAndColor) => (colorObj[posAndColor[0]] = posAndColor[1], colorObj), {}))},
														onClick: event => {
															let rects = BDFDB.DOMUtils.getRects(event.target);
															let pos = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0.01, 0.99], event.clientX);
															if (Object.keys(this.props.color).indexOf(pos) == -1) {
																this.props.color[pos] = BDFDB.ColorUtils.convert("#000000FF", colorFormat);
																this.state.selectedGradientCursor = pos;
																this.handleColorChange();
															}
														},
														children: currentGradient.map(posAndColor => BDFDB.ReactUtils.createElement("div", {
															className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickergradientcursor, (posAndColor[0] == 0 || posAndColor[0] == 1) && BDFDB.disCN.colorpickergradientcursoredge, this.state.selectedGradientCursor == posAndColor[0] && BDFDB.disCN.colorpickergradientcursorselected),
															style: {position: "absolute", cursor: "pointer", left: `${posAndColor[0] * 100}%`},
															onMouseDown: posAndColor[0] == 0 || posAndColor[0] == 1 ? _ => {} : event => {
																event = event.nativeEvent || event;
																let mouseMove = event2 => {
																	if (Math.sqrt((event.pageX - event2.pageX)**2) > 10) {
																		document.removeEventListener("mousemove", mouseMove);
																		document.removeEventListener("mouseup", mouseUp);
																		
																		this.state.draggingGradientCursor = true;
																		let cursor = BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickergradientcursor, event.target);
																		let rects = BDFDB.DOMUtils.getRects(cursor.parentElement);
																		
																		let releasing = _ => {
																			document.removeEventListener("mousemove", dragging);
																			document.removeEventListener("mouseup", releasing);
																			BDFDB.TimeUtils.timeout(_ => {this.state.draggingGradientCursor = false;});
																		};
																		let dragging = event3 => {
																			let pos = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0.01, 0.99], event3.clientX);
																			if (Object.keys(this.props.color).indexOf(pos) == -1) {
																				delete this.props.color[posAndColor[0]];
																				posAndColor[0] = pos;
																				this.props.color[pos] = posAndColor[1];
																				this.state.selectedGradientCursor = pos;
																				this.handleColorChange();
																			}
																		};
																		document.addEventListener("mousemove", dragging);
																		document.addEventListener("mouseup", releasing);
																	}
																};
																let mouseUp = _ => {
																	document.removeEventListener("mousemove", mouseMove);
																	document.removeEventListener("mouseup", mouseUp);
																};
																document.addEventListener("mousemove", mouseMove);
																document.addEventListener("mouseup", mouseUp);
															},
															onClick: event => {
																BDFDB.ListenerUtils.stopEvent(event);
																if (!this.state.draggingGradientCursor) {
																	this.state.selectedGradientCursor = posAndColor[0];
																	BDFDB.ReactUtils.forceUpdate(this);
																}
															},
															onContextMenu: posAndColor[0] == 0 || posAndColor[0] == 1 ? _ => {} : event => {
																BDFDB.ListenerUtils.stopEvent(event);
																delete this.props.color[posAndColor[0]];
																this.state.selectedGradientCursor = 0;
																this.handleColorChange();
															},
															children: BDFDB.ReactUtils.createElement("div", {
																style: {background: BDFDB.ColorUtils.convert(posAndColor[1], "RGBA")}
															})
														}))
													})
												})
											]
										})
									].filter(n => n)
								}),
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextInput, {
									className: BDFDB.disCN.margintop8,
									maxLength: this.props.alpha ? 9 : 7,
									valuePrefix: "#",
									value: hexColor,
									autoFocus: true,
									onChange: value => {
										const oldLength = hexLength;
										hexLength = (value || "").length;
										if (this.props.alpha && (oldLength > 8 || oldLength < 6) && hexLength == 7) value += "FF";
										if (hexRegex.test(value)) this.handleColorChange(value);
									},
									inputChildren: this.props.gradient && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
										text: BDFDB.LanguageUtils.LibraryStrings.gradient,
										children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
											className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickergradientbutton, this.state.gradientBarEnabled && BDFDB.disCN.colorpickergradientbuttonenabled),
											children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
												nativeClass: true,
												width: 28,
												height: 28,
												name: Internal.LibraryComponents.SvgIcon.Names.GRADIENT
											}),
											onClick: _ => {
												this.state.gradientBarEnabled = !this.state.gradientBarEnabled;
												if (this.state.gradientBarEnabled && !this.state.isGradient) this.props.color = {0: selectedColor, 1: selectedColor};
												else if (!this.state.gradientBarEnabled && this.state.isGradient) this.props.color = selectedColor;
												this.state.isGradient = this.props.color && BDFDB.ObjectUtils.is(this.props.color);
												this.handleColorChange();
											}
										})
									})
								}),
								BDFDB.ReactUtils.createElement("div", {
									className: "move-corners",
									children: [{top: 0, left: 0}, {top: 0, right: 0}, {bottom: 0, right: 0}, {bottom: 0, left: 0}].map(pos => BDFDB.ReactUtils.createElement("div", {
										className: "move-corner",
										onMouseDown: e => {
											if (!this.domElementRef.current) return;
											let rects = BDFDB.DOMUtils.getRects(this.domElementRef.current);
											let left = rects.left, top = rects.top;
											let oldX = e.pageX, oldY = e.pageY;
											let mouseUp = _ => {
												document.removeEventListener("mouseup", mouseUp);
												document.removeEventListener("mousemove", mouseMove);
											};
											let mouseMove = e2 => {
												left = left - (oldX - e2.pageX), top = top - (oldY - e2.pageY);
												oldX = e2.pageX, oldY = e2.pageY;
												this.domElementRef.current.style.setProperty("left", `${left}px`, "important");
												this.domElementRef.current.style.setProperty("top", `${top}px`, "important");
											};
											document.addEventListener("mouseup", mouseUp);
											document.addEventListener("mousemove", mouseMove);
										},
										style: Object.assign({}, pos, {width: 10, height: 10, cursor: "move", position: "absolute"})
									}))
								})
							]
						});
					}
				};
				
				CustomComponents.ColorSwatches = reactInitialized && class BDFDB_ColorSwatches extends Internal.LibraryModules.React.Component {
					ColorSwatch(props) {
						const swatches = props.swatches;
						let useWhite = !BDFDB.ColorUtils.isBright(props.color);
						let swatch = BDFDB.ReactUtils.createElement("button", {
							type: "button",
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatch, props.isSingle && BDFDB.disCN.colorpickerswatchsingle, props.isDisabled && BDFDB.disCN.colorpickerswatchdisabled, props.isSelected && BDFDB.disCN.colorpickerswatchselected, props.isCustom && BDFDB.disCN.colorpickerswatchcustom, props.color == null && BDFDB.disCN.colorpickerswatchnocolor),
							number: props.number,
							disabled: props.isDisabled,
							onClick: _ => {
								if (!props.isSelected) {
									let color = props.isCustom && props.color == null ? (swatches.props.color || swatches.props.defaultCustomColor || "rgba(0, 0, 0, 1)") : props.color;
									if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(BDFDB.ColorUtils.convert(color, "RGBCOMP"));
									swatches.props.color = color;
									swatches.props.customColor = props.isCustom ? color : swatches.props.customColor;
									swatches.props.customSelected = props.isCustom;
									BDFDB.ReactUtils.forceUpdate(swatches);
								}
							},
							style: Object.assign({}, props.style, {
								background: BDFDB.ObjectUtils.is(props.color) ? BDFDB.ColorUtils.createGradient(props.color) : BDFDB.ColorUtils.convert(props.color, "RGBA")
							}),
							children: [
								props.isCustom || props.isSingle ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
									className: BDFDB.disCN.colorpickerswatchdropper,
									name: Internal.LibraryComponents.SvgIcon.Names.DROPPER,
									width: props.isCustom ? 14 : 10,
									height: props.isCustom ? 14 : 10,
									color: useWhite ? Internal.DiscordConstants.Colors.WHITE : Internal.DiscordConstants.Colors.BLACK
								}) : null,
								props.isSelected && !props.isSingle ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
									name: Internal.LibraryComponents.SvgIcon.Names.CHECKMARK,
									width: props.isCustom ? 32 : 16,
									height: props.isCustom ? 24 : 16,
									color: useWhite ? Internal.DiscordConstants.Colors.WHITE : Internal.DiscordConstants.Colors.BLACK
								}) : null
							]
						});
						if (props.isCustom || props.isSingle || props.color == null) swatch = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
							text: props.isCustom || props.isSingle ? BDFDB.LanguageUtils.LanguageStrings.CUSTOM_COLOR : BDFDB.LanguageUtils.LanguageStrings.DEFAULT,
							tooltipConfig: {type: props.isSingle ? "top" : "bottom"},
							children: swatch
						});
						if (props.isCustom || props.isSingle) swatch = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutContainer, {
							children: swatch,
							wrap: false,
							popoutClassName: BDFDB.disCNS.colorpickerwrapper + BDFDB.disCN.colorpicker,
							animation: Internal.LibraryComponents.PopoutContainer.Animation.TRANSLATE,
							position: Internal.LibraryComponents.PopoutContainer.Positions.BOTTOM,
							align: Internal.LibraryComponents.PopoutContainer.Align.CENTER,
							open: swatches.props.pickerOpen,
							onClick: _ => swatches.props.pickerOpen = true,
							onOpen: _ => {
								swatches.props.pickerOpen = true;
								if (typeof swatches.props.onPickerOpen == "function") swatches.props.onPickerOpen(this);
							},
							onClose: _ => {
								delete swatches.props.pickerOpen;
								if (typeof swatches.props.onPickerClose == "function") swatches.props.onPickerClose(this);
							},
							renderPopout: _ => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ColorPicker, Object.assign({}, swatches.props.pickerConfig, {
								color: swatches.props.color,
								onColorChange: color => {
									if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(color);
									props.color = color;
									swatches.props.color = color;
									swatches.props.customColor = color;
									swatches.props.customSelected = true;
									BDFDB.ReactUtils.forceUpdate(swatches);
								}
							}), true)
						});
						if (props.isCustom) swatch = BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.colorpickerswatchcustomcontainer,
							children: swatch
						});
						return swatch;
					}
					render() {
						this.props.color = BDFDB.ObjectUtils.is(this.props.color) ? this.props.color : BDFDB.ColorUtils.convert(this.props.color, "RGBA");
						this.props.colors = (BDFDB.ArrayUtils.is(this.props.colors) ? this.props.colors : [null, 5433630, 3066993, 1752220, 3447003, 3429595, 8789737, 10181046, 15277667, 15286558, 15158332, 15105570, 15844367, 13094093, 7372936, 6513507, 16777215, 3910932, 2067276, 1146986, 2123412, 2111892, 7148717, 7419530, 11342935, 11345940, 10038562, 11027200, 12745742, 9936031, 6121581, 2894892]).map(c => BDFDB.ColorUtils.convert(c, "RGBA"));
						this.props.colorRows = this.props.colors.length ? [this.props.colors.slice(0, parseInt(this.props.colors.length/2)), this.props.colors.slice(parseInt(this.props.colors.length/2))] : [];
						this.props.customColor = !this.props.color || !this.props.customSelected && this.props.colors.indexOf(this.props.color) > -1 ? null : this.props.color;
						this.props.defaultCustomColor = BDFDB.ObjectUtils.is(this.props.defaultCustomColor) ? this.props.defaultCustomColor : BDFDB.ColorUtils.convert(this.props.defaultCustomColor, "RGBA");
						this.props.customSelected = !!this.props.customColor;
						this.props.pickerConfig = BDFDB.ObjectUtils.is(this.props.pickerConfig) ? this.props.pickerConfig : {gradient: true, alpha: true};
						
						const isSingle = !this.props.colors.length;
						return BDFDB.ReactUtils.createElement("div", {
							className: isSingle ? BDFDB.disCN.colorpickerswatchsinglewrapper : BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatches, BDFDB.disCN.colorpickerswatchescontainer, this.props.disabled && BDFDB.disCN.colorpickerswatchesdisabled),
							children: [
								BDFDB.ReactUtils.createElement(this.ColorSwatch, {
									swatches: this,
									color: this.props.customColor,
									isSingle: isSingle,
									isCustom: !isSingle,
									isSelected: this.props.customSelected,
									isDisabled: this.props.disabled,
									pickerOpen: this.props.pickerOpen,
									style: {margin: 0}
								}),
								!isSingle && BDFDB.ReactUtils.createElement("div", {
									children: this.props.colorRows.map(row => BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.disCN.colorpickerrow,
										children: row.map(color => BDFDB.ReactUtils.createElement(this.ColorSwatch, {
											swatches: this,
											color: color,
											isCustom: false,
											isSelected: !this.props.customSelected && color == this.props.color,
											isDisabled: this.props.disabled
										}))
									}))
								}) 
							]
						});
					}
				};

				CustomComponents.DateInput = reactInitialized && class BDFDB_DateInput extends Internal.LibraryModules.React.Component {
					renderFormatButton(props) {
						const button = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							className: BDFDB.disCN.dateinputbutton,
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								name: props.svgName,
								width: 20,
								height: 20
							})
						});
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutContainer, {
							width: props.popoutWidth || 350,
							padding: 10,
							animation: Internal.LibraryComponents.PopoutContainer.Animation.SCALE,
							position: Internal.LibraryComponents.PopoutContainer.Positions.TOP,
							align: Internal.LibraryComponents.PopoutContainer.Align.RIGHT,
							onClose: instance => BDFDB.DOMUtils.removeClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected),
							renderPopout: instance => {
								BDFDB.DOMUtils.addClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected);
								return props.children || BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
									align: Internal.LibraryComponents.Flex.Align.CENTER,
									children: [
										props.name && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
											label: props.name
										}),
										BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextInput, {
											className: BDFDB.disCN.dateinputfield,
											placeholder: props.placeholder,
											value: props.getValue(),
											onChange: typeof props.onChange == "function" ? props.onChange : null
										}),
										props.tooltipText && this.renderInfoButton(props.tooltipText)
									].filter(n => n)
								})
							},
							children: props.name ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
								text: props.name,
								children: button
							}) : button
						});
					}
					renderInfoButton(text, style) {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
							text: [text].flat(10).filter(n => n).map(n => BDFDB.ReactUtils.createElement("div", {children: n})),
							tooltipConfig: {
								type: "bottom",
								zIndex: 1009,
								maxWidth: 560
							},
							children: BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.disCN.dateinputbutton,
								style: Object.assign({}, style),
								children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
									name: Internal.LibraryComponents.SvgIcon.Names.QUESTIONMARK,
									width: 24,
									height: 24
								})
							})
						});
					}
					handleChange() {
						if (typeof this.props.onChange == "function") this.props.onChange(BDFDB.ObjectUtils.extract(this.props, "formatString", "dateString", "timeString", "timeOffset", "language"));
					}
					render() {
						let input = this, formatter, preview;
						const defaultOffset = ((new Date()).getTimezoneOffset() * (-1/60));
						return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.dateinputwrapper, this.props.className),
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
									label: this.props.label
								}),
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.dateinputinner,
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.dateinputcontrols,
											children: [
												BDFDB.ReactUtils.createElement(class DateInputPreview extends Internal.LibraryModules.React.Component {
													componentDidMount() {formatter = this;}
													render() {
														return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextInput, {
															className: BDFDB.disCN.dateinputfield,
															placeholder: Internal.LibraryComponents.DateInput.getDefaultString(input.props.language),
															value: input.props.formatString,
															onChange: value => {
																input.props.formatString = value;
																input.handleChange.apply(input, []);
																BDFDB.ReactUtils.forceUpdate(formatter, preview);
															}
														});
													}
												}),
												this.renderInfoButton([
													"$date will be replaced with the Date",
													"$time will be replaced with the Time",
													"$time12 will be replaced with the Time (12h Form)",
													"$month will be replaced with the Month Name",
													"$monthS will be replaced with the Month Name (Short Form)",
													"$day will be replaced with the Weekday Name",
													"$dayS will be replaced with the Weekday Name (Short Form)",
													"$agoAmount will be replaced with ('Today', 'Yesterday', 'x days/weeks/months ago')",
													"$agoWeekday will be replaced with ('Today', 'Yesterday', $day)",
													"$agoWeekdayS will be replaced with ('Today', 'Yesterday', $dayS)",
													"$agoDays will be replaced with ('Today', 'Yesterday', 'x days ago')",
													"$agoDate will be replaced with ('Today', 'Yesterday', $date)"
												], {marginRight: 6}),
												this.renderFormatButton({
													name: BDFDB.LanguageUtils.LanguageStrings.DATE,
													svgName: Internal.LibraryComponents.SvgIcon.Names.CALENDAR,
													placeholder: this.props.dateString,
													getValue: _ => this.props.dateString,
													tooltipText: [
														"$d will be replaced with the Day",
														"$dd will be replaced with the Day (Forced Zeros)",
														"$m will be replaced with the Month",
														"$mm will be replaced with the Month (Forced Zeros)",
														"$yy will be replaced with the Year (2-Digit)",
														"$yyyy will be replaced with the Year (4-Digit)",
														"$month will be replaced with the Month Name",
														"$monthS will be replaced with the Month Name (Short Form)",
													],
													onChange: value => {
														this.props.dateString = value;
														this.handleChange.apply(this, []);
														BDFDB.ReactUtils.forceUpdate(formatter, preview);
													}
												}),
												this.renderFormatButton({
													name: BDFDB.LanguageUtils.LibraryStrings.time,
													svgName: Internal.LibraryComponents.SvgIcon.Names.CLOCK,
													placeholder: this.props.timeString,
													getValue: _ => this.props.timeString,
													tooltipText: [
														"$h will be replaced with the Hours",
														"$hh will be replaced with the Hours (Forced Zeros)",
														"$m will be replaced with the Minutes",
														"$mm will be replaced with the Minutes (Forced Zeros)",
														"$s will be replaced with the Seconds",
														"$ss will be replaced with the Seconds (Forced Zeros)",
														"$u will be replaced with the Milliseconds",
														"$uu will be replaced with the Milliseconds (Forced Zeros)"
													],
													onChange: value => {
														this.props.timeString = value;
														this.handleChange.apply(this, []);
														BDFDB.ReactUtils.forceUpdate(formatter, preview);
													}
												}),
												this.renderFormatButton({
													name: BDFDB.LanguageUtils.LibraryStrings.location,
													svgName: Internal.LibraryComponents.SvgIcon.Names.GLOBE,
													popoutWidth: 550,
													children: [
														BDFDB.ReactUtils.createElement(Internal.LibraryComponents.AutoFocusCatcher, {}),
														BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
															className: BDFDB.disCN.marginbottom4,
															align: Internal.LibraryComponents.Flex.Align.CENTER,
															children: [
																BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
																	label: BDFDB.LanguageUtils.LanguageStrings.LANGUAGE
																}),
																BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Select, {
																	className: BDFDB.disCN.dateinputfield,
																	value: this.props.language != null ? this.props.language : "$discord",
																	options: Object.keys(BDFDB.LanguageUtils.languages).map(id => ({
																		value: id,
																		label: BDFDB.LanguageUtils.getName(BDFDB.LanguageUtils.languages[id])
																	})),
																	searchable: true,
																	optionRenderer: lang => lang.label,
																	onChange: value => {
																		this.props.language = value == "$discord" ? undefined : value;
																		this.handleChange.apply(this, []);
																		BDFDB.ReactUtils.forceUpdate(formatter, preview);
																	}
																})
															]
														}),
														BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
															align: Internal.LibraryComponents.Flex.Align.CENTER,
															children: [
																BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
																	label: BDFDB.LanguageUtils.LibraryStrings.timezone
																}),
																BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Select, {
																	className: BDFDB.disCN.dateinputfield,
																	value: this.props.timeOffset != null ? this.props.timeOffset : defaultOffset,
																	options: [-12.0, -11.0, -10.0, -9.5, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.5, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 5.75, 6.0, 6.5, 7.0, 8.0, 8.75, 9.0, 9.5, 10.0, 10.5, 11.0, 12.0, 12.75, 13.0, 14.0].map(offset => ({label: offset< 0 ? offset : `+${offset}`, value: offset})),
																	searchable: true,
																	onChange: value => {
																		this.props.timeOffset = value == defaultOffset ? undefined : value;
																		this.handleChange.apply(this, []);
																		BDFDB.ReactUtils.forceUpdate(formatter, preview);
																	}
																})
															]
														})
													]
												})
											]
										}),
										BDFDB.ReactUtils.createElement(class DateInputPreview extends Internal.LibraryModules.React.Component {
											componentDidMount() {preview = this;}
											render() {
												return !input.props.noPreview && BDFDB.ReactUtils.createElement("div", {
													className: BDFDB.disCN.dateinputpreview,
													children: [
														input.props.prefix && BDFDB.ReactUtils.createElement("div", {
															className: BDFDB.disCN.dateinputpreviewprefix,
															children: typeof input.props.prefix == "function" ? input.props.prefix(input) : input.props.prefix,
														}),
														BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
															children: Internal.LibraryComponents.DateInput.format(input.props, new Date((new Date()) - (1000*60*60*24*2)))
														}),
														input.props.suffix && BDFDB.ReactUtils.createElement("div", {
															className: BDFDB.disCN.dateinputpreviewsuffix,
															children: typeof input.props.suffix == "function" ? input.props.suffix(input) : input.props.suffix,
														})
													].filter(n => n)
												});
											}
										})
									]
								})
							]
						}), "onChange", "label", "formatString", "dateString", "timeString", "timeOffset", "language", "noPreview", "prefix", "suffix"));
					}
				};
				if (CustomComponents.DateInput) {
					CustomComponents.DateInput.getDefaultString = function (language) {
						language = language || BDFDB.LanguageUtils.getLanguage().id;
						const date = new Date();
						return date.toLocaleString(language).replace(date.toLocaleDateString(language), "$date").replace(date.toLocaleTimeString(language, {hourCycle: "h12"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h11"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h24"}), "$time").replace(date.toLocaleTimeString(language, {hourCycle: "h23"}), "$time");
					};
					CustomComponents.DateInput.parseDate = function (date, offset) {
						let timeObj = date;
						if (typeof timeObj == "string") {
							const language = BDFDB.LanguageUtils.getLanguage().id;
							for (let i = 0; i < 12; i++) {
								const tempDate = new Date();
								tempDate.setMonth(i);
								timeObj = timeObj.replace(tempDate.toLocaleDateString(language, {month:"long"}), tempDate.toLocaleDateString("en", {month:"short"}));
							}
							timeObj = new Date(timeObj);
						}
						else if (typeof timeObj == "number") timeObj = new Date(timeObj);
						
						if (timeObj.toString() == "Invalid Date") timeObj = new Date(parseInt(date));
						if (timeObj.toString() == "Invalid Date" || typeof timeObj.toLocaleDateString != "function") timeObj = new Date();
						offset = offset != null && parseFloat(offset);
						if ((offset || offset === 0) && !isNaN(offset)) timeObj = new Date(timeObj.getTime() + ((offset - timeObj.getTimezoneOffset() * (-1/60)) * 60*60*1000));
						return timeObj;
					};
					CustomComponents.DateInput.format = function (data, time) {
						if (typeof data == "string") data = {formatString: data};
						if (data && typeof data.formatString != "string") data.formatString = "";
						if (!data || typeof data.formatString != "string" || !time) return "";
						
						const language = data.language || BDFDB.LanguageUtils.getLanguage().id;
						const timeObj = Internal.LibraryComponents.DateInput.parseDate(time, data.timeOffset);
						const now = new Date();
						const daysAgo = Math.round((Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) - Date.UTC(timeObj.getFullYear(), timeObj.getMonth(), timeObj.getDate()))/(1000*60*60*24));
						const date = data.dateString && typeof data.dateString == "string" ? Internal.LibraryComponents.DateInput.formatDate({dateString: data.dateString, language: language}, timeObj) : timeObj.toLocaleDateString(language);
						
						return (data.formatString || Internal.LibraryComponents.DateInput.getDefaultString(language))
							.replace(/\$date/g, date)
							.replace(/\$time12/g, data.timeString && typeof data.timeString == "string" ? Internal.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj, true) : timeObj.toLocaleTimeString(language, {hourCycle: "h12"}))
							.replace(/\$time/g, data.timeString && typeof data.timeString == "string" ? Internal.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj) : timeObj.toLocaleTimeString(language, {hourCycle: "h23"}))
							.replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"}))
							.replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"}))
							.replace(/\$dayS/g, timeObj.toLocaleDateString(language, {weekday: "short"}))
							.replace(/\$day/g, timeObj.toLocaleDateString(language, {weekday: "long"}))
							.replace(/\$agoAmount/g, daysAgo < 0 || daysAgo > 1 ? Internal.DiscordObjects.Timestamp(timeObj.getTime()).fromNow() : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
							.replace(/\$agoWeekdayS/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "short"}) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
							.replace(/\$agoWeekday/g, daysAgo < 0 || daysAgo > 1 ? timeObj.toLocaleDateString(language, {weekday: "long"}) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
							.replace(/\$agoDays/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.LanguageUtils.LanguageStringsFormat(`LAST_PLAYED_PLACEHOLDER`, daysAgo) : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
							.replace(/\$agoDate/g, daysAgo < 0 || daysAgo > 1 ? date : BDFDB.LanguageUtils.LanguageStrings[daysAgo == 1 ? "YESTERDAY" : "TODAY"])
							.replace(/\(\)|\[\]/g, "").replace(/,\s*$|^\s*,/g, "").replace(/ +/g, " ").trim();
					};
					CustomComponents.DateInput.formatDate = function (data, time) {
						if (typeof data == "string") data = {dateString: data};
						if (data && typeof data.dateString != "string") return "";
						if (!data || typeof data.dateString != "string" || !data.dateString || !time) return "";
						
						const language = data.language || BDFDB.LanguageUtils.getLanguage().id;
						const timeObj = Internal.LibraryComponents.DateInput.parseDate(time, data.timeOffset);
						
						return data.dateString
							.replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"}))
							.replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"}))
							.replace(/\$dd/g, timeObj.toLocaleDateString(language, {day: "2-digit"}))
							.replace(/\$d/g, timeObj.toLocaleDateString(language, {day: "numeric"}))
							.replace(/\$mm/g, timeObj.toLocaleDateString(language, {month: "2-digit"}))
							.replace(/\$m/g, timeObj.toLocaleDateString(language, {month: "numeric"}))
							.replace(/\$yyyy/g, timeObj.toLocaleDateString(language, {year: "numeric"}))
							.replace(/\$yy/g, timeObj.toLocaleDateString(language, {year: "2-digit"}))
							.trim();
					};
					CustomComponents.DateInput.formatTime = function (data, time, hour12) {
						if (typeof data == "string") data = {timeString: data};
						if (data && typeof data.timeString != "string") return "";
						if (!data || typeof data.timeString != "string" || !data.timeString || !time) return "";
						
						const language = data.language || BDFDB.LanguageUtils.getLanguage().id;
						const timeObj = Internal.LibraryComponents.DateInput.parseDate(time, data.timeOffset);
						
						let hours = timeObj.getHours();
						if (hour12) {
							hours = hours == 0 ? 12 : hours;
							if (hours > 12) hours -= 12;
						}
						const minutes = timeObj.getMinutes();
						const seconds = timeObj.getSeconds();
						const milli = timeObj.getMilliseconds();
						
						let string = data.timeString
							.replace(/\$hh/g, hours < 10 ? `0${hours}` : hours)
							.replace(/\$h/g, hours)
							.replace(/\$mm/g, minutes < 10 ? `0${minutes}` : minutes)
							.replace(/\$m/g, minutes)
							.replace(/\$ss/g, seconds < 10 ? `0${seconds}` : seconds)
							.replace(/\$s/g, seconds)
							.replace(/\$uu/g, milli < 10 ? `00${milli}` : milli < 100 ? `0${milli}` : milli)
							.replace(/\$u/g, milli)
							.trim();

						let digits = "\\d";
						if (BDFDB.LanguageUtils.languages[language] && BDFDB.LanguageUtils.languages[language].numberMap) {
							digits = Object.entries(BDFDB.LanguageUtils.languages[language].numberMap).map(n => n[1]).join("");
							for (let number in BDFDB.LanguageUtils.languages[language].numberMap) string = string.replace(new RegExp(number, "g"), BDFDB.LanguageUtils.languages[language].numberMap[number]);
						}
						return hour12 ? timeObj.toLocaleTimeString(language, {hourCycle: "h12"}).replace(new RegExp(`[${digits}]{1,2}[^${digits}][${digits}]{1,2}[^${digits}][${digits}]{1,2}`, "g"), string) : string;
					};
				}
				
				CustomComponents.EmojiPickerButton = reactInitialized && class BDFDB_EmojiPickerButton extends Internal.LibraryModules.React.Component {
					handleEmojiChange(emoji) {
						if (emoji != null) {
							this.props.emoji = emoji.id ? {
								id: emoji.id,
								name: emoji.name,
								animated: emoji.animated
							} : {
								id: null,
								name: emoji.optionallyDiverseSequence,
								animated: false
							};
							if (typeof this.props.onSelect == "function") this.props.onSelect(this.props.emoji, this);
							if (typeof this.close == "function" && !BDFDB.ListenerUtils.isPressed(16)) this.close();
							BDFDB.ReactUtils.forceUpdate(this);
						}
					}
					render() {
						let button = this;
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutContainer, {
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.EmojiButton, {
								className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.emojiinputbutton),
								renderButtonContents: this.props.emoji ? _ => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Emoji, {
									className: BDFDB.disCN.emojiinputbuttonemoji,
									emojiId: this.props.emoji.id,
									emojiName: this.props.emoji.name
								}) : null
							}),
							wrap: false,
							animation: Internal.LibraryComponents.PopoutContainer.Animation.NONE,
							position: this.props.position || Internal.LibraryComponents.PopoutContainer.Positions.TOP,
							align: Internal.LibraryComponents.PopoutContainer.Align.LEFT,
							renderPopout: instance => {
								this.close = instance.close;
								return [
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.EmojiPicker, {
										closePopout: this.close,
										onSelectEmoji: this.handleEmojiChange.bind(this),
										allowManagedEmojis: this.props.allowManagedEmojis,
										allowManagedEmojisUsage: this.props.allowManagedEmojisUsage
									}),
									BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
										componentDidMount() {Internal.LibraryComponents.EmojiPickerButton.current = button;}
										componentWillUnmount() {delete Internal.LibraryComponents.EmojiPickerButton.current;}
										render() {return null;}
									})
								];
							}
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.EmojiPickerButton, {allowManagedEmojis: false, allowManagedEmojisUsage: false});
				
				CustomComponents.EmptyStateImage = reactInitialized && class BDFDB_EmptyStateImage extends Internal.LibraryModules.React.Component {
					render() {
						let isLightTheme = BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themelight;
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.pageimagewrapper, this.props.className),
							direction: Internal.LibraryComponents.Flex.Direction.VERTICAL,
							align: Internal.LibraryComponents.Flex.Align.CENTER,
							children: [
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.pageimage, BDFDB.disCN.margintop20, BDFDB.disCN.marginbottom20, this.props.imageClassName),
									style: {
										flex: "0 1 auto",
										background: `url("${this.props.src || (isLightTheme ? this.props.lightSrc : this.props.darkSrc) || this.props.lightSrc || this.props.darkSrc || (isLightTheme ? "/assets/a72746e7108167af95c8.svg" : "/assets/01864c39871ce619d855.svg")}") center/contain no-repeat`,
										width: this.props.width || "415px",
										height: this.props.height || "200px"
									}
								}),
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.pageimagetext,
									children: this.props.text || BDFDB.LanguageUtils.LanguageStrings.NO_RESULTS
								})
							]
						});
					}
				};
				
				CustomComponents.FavButton = reactInitialized && class BDFDB_FavButton extends Internal.LibraryModules.React.Component {
					handleClick() {
						this.props.isFavorite = !this.props.isFavorite;
						if (typeof this.props.onClick == "function") this.props.onClick(this.props.isFavorite, this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					render() {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.favbuttoncontainer, BDFDB.disCN.favbutton, this.props.isFavorite && BDFDB.disCN.favbuttonselected, this.props.className),
							onClick: this.handleClick.bind(this),
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								name: Internal.LibraryComponents.SvgIcon.Names[this.props.isFavorite ? "FAVORITE_FILLED" : "FAVORITE"],
								width: this.props.width || 24,
								height: this.props.height || 24,
								className: BDFDB.disCN.favbuttonicon
							})
						});
					}
				};
				
				CustomComponents.FileButton = reactInitialized && class BDFDB_FileButton extends Internal.LibraryModules.React.Component {
					render() {
						let filter = this.props.filter && [this.props.filter].flat(10).filter(n => typeof n == "string") || [];
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Button, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							onClick: e => {(e.currentTarget || e.target).querySelector("input").click();},
							children: [
								BDFDB.LanguageUtils.LibraryStrings.file_navigator_text,
								BDFDB.ReactUtils.createElement("input", {
									type: "file",
									accept: filter.length && (filter.join("/*,") + "/*"),
									style: {display: "none"},
									onChange: e => {
										let file = (e.currentTarget || e.target).files[0];
										if (this.refInput && file && (!filter.length || filter.some(n => file.type.indexOf(n) == 0))) {
											let reader = new FileReader();
											reader.onload = _ => {
												if (file.size > (!isNaN(this.props.maxSize) && this.props.maxSize > 0 ? this.props.maxSize : 5.1*1024*1024)) BDFDB.NotificationUtils.toast("File too large to upload (Max 5MB)", {type: "danger", position: "center"});
												else {
													function Uint8ToString(u8a) {
														const CHUNK_SZ = 0x8000;
														let c = [];
														for (let i = 0; i < u8a.length; i += CHUNK_SZ) c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
														return c.join("");
													}
													this.refInput.handleChange(file.name, `${this.props.mode == "url" ? "url('" : ""}${`data:${file.type};base64,${btoa(Uint8ToString(new Uint8Array(reader.result)))}`}${this.props.mode ? "')" : ""}`);
												}
											}
											reader.readAsArrayBuffer(file);
										}
									}
								})
							]
						}), "filter", "mode"));
					}
				};
				
				CustomComponents.FormItem = reactInitialized && class BDFDB_FormItem extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement("div", {
							className: this.props.className,
							style: this.props.style,
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
									children: [
										this.props.title != null || this.props.error != null ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
											wrap: true,
											children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormTitle.Title, {
												tag: this.props.tag || Internal.LibraryComponents.FormTitle.Tags && Internal.LibraryComponents.FormTitle.Tags.H5,
												disabled: this.props.disabled,
												required: this.props.required,
												error: this.props.error,
												className: this.props.titleClassName,
												children: this.props.title
											})
										}) : null
									].concat([this.props.titleChildren].flat(10)).filter(n => n)
								}),
							].concat(this.props.children)
						});
					}
				};
				
				CustomComponents.FormTitle = reactInitialized && class BDFDB_FormTitle extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.FormTitle, this.props);
					}
				};
				CustomComponents.FormTitle.Title = CustomComponents.FormTitle;
				CustomComponents.FormTitle.Tags = new Proxy({}, {
					get: function (_, item) {
						let tag = item && item.toLowerCase();
						return tag.startsWith("h") && tag.length == 2 ? tag : "h5";
					}
				});
				
				CustomComponents.GuildSummaryItem = reactInitialized && class BDFDB_GuildSummaryItem extends Internal.LibraryModules.React.Component {
					defaultRenderGuild(guild, isLast) {
						if (!guild) return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.guildsummaryemptyguild
						});
						let icon = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildIcon, {
							className: BDFDB.disCN.guildsummaryicon,
							guild: guild,
							showTooltip: this.props.showTooltip,
							tooltipPosition: "top",
							size: Internal.LibraryComponents.GuildIcon.Sizes.SMALLER
						});
						return this.props.switchOnClick ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							className: BDFDB.disCN.guildsummaryclickableicon,
							onClick: _ => Internal.LibraryModules.HistoryUtils.transitionTo(Internal.DiscordConstants.Routes.CHANNEL(guild.id, Internal.LibraryStores.SelectedChannelStore.getChannelId(guild.id))),
							key: guild.id,
							tabIndex: -1,
							children: icon
						}) : icon;
					}
					renderGuilds() {
						let elements = [];
						let renderGuild = typeof this.props.renderGuild != "function" ? this.defaultRenderGuild : this.props.renderGuild;
						let loaded = 0, max = this.props.guilds.length === this.props.max ? this.props.guilds.length : this.props.max - 1;
						while (loaded < max && loaded < this.props.guilds.length) {
							let isLast = loaded === this.props.guilds.length - 1;
							let guild = renderGuild.apply(this, [this.props.guilds[loaded], isLast]);
							elements.push(BDFDB.ReactUtils.createElement("div", {
								className: isLast ? BDFDB.disCN.guildsummaryiconcontainer : BDFDB.disCN.guildsummaryiconcontainermasked,
								children: guild
							}));
							loaded++;
						}
						if (loaded < this.props.guilds.length) {
							let rest = Math.min(this.props.guilds.length - loaded, 99);
							elements.push(BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
								key: "more-guilds",
								children: this.props.renderMoreGuilds("+" + rest, rest, this.props.guilds.slice(loaded), this.props)
							}));
						}
						return elements;
					}
					renderIcon() {
						return this.props.renderIcon ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
							name: Internal.LibraryComponents.SvgIcon.Names.WHATISTHIS,
							className: BDFDB.disCN.guildsummarysvgicon
						}) : null;
					}
					render() {
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.guildsummarycontainer),
							ref: this.props._ref,
							children: [
								this.renderIcon.apply(this),
								this.renderGuilds.apply(this)
							].flat(10).filter(n => n)
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.GuildSummaryItem, {max: 10, renderMoreGuilds: (count, amount, restGuilds, props) => {
					let icon = BDFDB.ReactUtils.createElement("div", {className: BDFDB.disCN.guildsummarymoreguilds, children: count});
					return props.showTooltip ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
						text: restGuilds.map(guild => guild.name).join(", "),
						children: icon
					}) : icon;
				}, renderIcon: false});
				
				CustomComponents.GuildVoiceList = reactInitialized && class BDFDB_GuildVoiceList extends Internal.LibraryModules.React.Component {
					render() {
						let channels = Internal.LibraryStores.GuildChannelStore.getChannels(this.props.guild.id);
						let voiceChannels = (channels.VOCAL || []).filter(c => c.channel.type == Internal.DiscordConstants.ChannelTypes.GUILD_VOICE).map(c => c.channel.id);
						let stageChannels = (channels.VOCAL || []).filter(c => c.channel.type == Internal.DiscordConstants.ChannelTypes.GUILD_STAGE_VOICE && Internal.LibraryStores.StageInstanceStore.getStageInstanceByChannel(c.channel.id)).map(c => c.channel.id);
						let streamOwnerIds = Internal.LibraryStores.ApplicationStreamingStore.getAllApplicationStreams().filter(app => app.guildId === this.props.guild.id).map(app => app.ownerId) || [];
						let streamOwners = streamOwnerIds.map(ownerId => Internal.LibraryStores.UserStore.getUser(ownerId)).filter(n => n);
						let voiceStates = BDFDB.ObjectUtils.toArray(Internal.LibraryStores.SortedVoiceStateStore.getVoiceStates(this.props.guild.id)).flat(10);
						let connectedVoiceUsers = voiceStates.map(n => voiceChannels.includes(n.voiceState.channelId) && n.voiceState.channelId != this.props.guild.afkChannelId && !streamOwnerIds.includes(n.voiceState.userId) && Internal.LibraryStores.UserStore.getUser(n.voiceState.userId)).filter(n => n);
						let connectedStageUsers = voiceStates.map(n => stageChannels.includes(n.voiceState.channelId) && n.voiceState.channelId != this.props.guild.afkChannelId && !streamOwnerIds.includes(n.voiceState.userId) && Internal.LibraryStores.UserStore.getUser(n.voiceState.userId)).filter(n => n);
						let children = [
							!connectedStageUsers.length ? null : BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.disCN.tooltiprow,
								children: [
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
										name: Internal.LibraryComponents.SvgIcon.Names.PODIUM,
										className: BDFDB.disCN.tooltipactivityicon
									}),
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.UserSummaryItem, {
										users: connectedStageUsers,
										max: 6
									})
								]
							}),
							!connectedVoiceUsers.length ? null : BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.disCN.tooltiprow,
								children: [
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
										name: Internal.LibraryComponents.SvgIcon.Names.SPEAKER,
										className: BDFDB.disCN.tooltipactivityicon
									}),
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.UserSummaryItem, {
										users: connectedVoiceUsers,
										max: 6
									})
								]
							}),
							!streamOwners.length ? null : BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.disCN.tooltiprow,
								children: [
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
										name: Internal.LibraryComponents.SvgIcon.Names.STREAM,
										className: BDFDB.disCN.tooltipactivityicon
									}),
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.UserSummaryItem, {
										users: streamOwners,
										max: 6
									})
								]
							})
						].filter(n => n);
						return !children.length ? null : BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.guildvoicelist,
							children: children
						});
					}
				};
				
				CustomComponents.KeybindRecorder = reactInitialized && class BDFDB_KeybindRecorder extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange(arrays) {
								this.props.value = arrays.map(platformKey => Internal.LibraryModules.KeyEvents.codes[Internal.LibraryModules.KeyCodeUtils.codeToKey(platformKey)] || platformKey[1]);
								if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this);
							}
							handleReset() {
								this.props.value = [];
								if (this.recorder) this.recorder.setState({codes: []});
								if (typeof this.props.onChange == "function") this.props.onChange([], this);
								if (typeof this.props.onReset == "function") this.props.onReset(this);
							}
							componentDidMount() {
								if (!this.recorder) this.recorder = BDFDB.ReactUtils.findOwner(this, {name: "KeybindRecorder"});
							}
							render() {
								return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
									className: BDFDB.disCN.hotkeywrapper,
									direction: Internal.LibraryComponents.Flex.Direction.HORIZONTAL,
									align: Internal.LibraryComponents.Flex.Align.CENTER,
									children: [
										BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.KeybindRecorder, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
											defaultValue: [this.props.defaultValue || this.props.value].flat(10).filter(n => n).map(keyCode => [Internal.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, Internal.LibraryModules.KeyCodeUtils.keyToCode((Object.entries(Internal.LibraryModules.KeyEvents.codes).find(n => n[1] == keyCode && Internal.LibraryModules.KeyCodeUtils.keyToCode(n[0], null)) || [])[0], null) || keyCode]),
											onChange: this.handleChange.bind(this)
										}), "reset", "onReset")),
										this.props.reset || this.props.onReset ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
											text: BDFDB.LanguageUtils.LanguageStrings.REMOVE_KEYBIND,
											tooltipConfig: {type: "top"},
											children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
												className: BDFDB.disCN.hotkeyresetbutton,
												onClick: this.handleReset.bind(this),
												children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
													iconSVG: `<svg height="20" width="20" viewBox="0 0 20 20"><path fill="currentColor" d="M 14.348 14.849 c -0.469 0.469 -1.229 0.469 -1.697 0 l -2.651 -3.030 -2.651 3.029 c -0.469 0.469 -1.229 0.469 -1.697 0 -0.469 -0.469 -0.469 -1.229 0 -1.697l2.758 -3.15 -2.759 -3.152 c -0.469 -0.469 -0.469 -1.228 0 -1.697 s 1.228 -0.469 1.697 0 l 2.652 3.031 2.651 -3.031 c 0.469 -0.469 1.228 -0.469 1.697 0 s 0.469 1.229 0 1.697l -2.758 3.152 2.758 3.15 c 0.469 0.469 0.469 1.229 0 1.698 z"></path></svg>`,
												})
											})
										}) : null
									].filter(n => n)
								});
							}
						}, this.props);
					}
				};
				
				CustomComponents.ListRow = reactInitialized && class BDFDB_ListRow extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.listrowwrapper, this.props.className, BDFDB.disCN.listrow),
							children: [
								this.props.prefix,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.listrowcontent,
									style: {flex: "1 1 auto"},
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.listname, this.props.labelClassName),
											style: {flex: "1 1 auto"},
											children: this.props.label
										}),
										typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormText.Text, {
											type: Internal.LibraryComponents.FormText.Types.DESCRIPTION,
											children: this.props.note
										}) : null
									].filter(n => n)
								}),
								this.props.suffix
							].filter(n => n)
						}), "label", "note", "suffix", "prefix", "labelClassName"));
					}
				};
				
				CustomComponents.MemberRole = reactInitialized && class BDFDB_MemberRole extends Internal.LibraryModules.React.Component {
					handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}
					handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}
					render() {
						let color = BDFDB.ColorUtils.convert(this.props.role.colorString, "RGB") || Internal.DiscordConstants.Colors.PRIMARY_300;
						return BDFDB.ReactUtils.createElement("li", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.userrole, this.props.className),
							style: {borderColor: BDFDB.ColorUtils.setAlpha(color, 0.6)},
							onClick: this.handleClick.bind(this),
							onContextMenu: this.handleContextMenu.bind(this),
							children: [
								!this.props.noCircle ? BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.userroleremovebutton,
									children: BDFDB.ReactUtils.createElement("span", {
										className: BDFDB.disCN.userrolecircle,
										style: {backgroundColor: color}
									})
								}) : null,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.userrolename,
									children: this.props.role.name
								})
							].filter(n => n)
						});
					}
				};
				
				CustomComponents.MenuItems = {};
				CustomComponents.MenuItems.MenuCheckboxItem = reactInitialized && class BDFDB_MenuCheckboxItem extends Internal.LibraryModules.React.Component {
					handleClick() {
						if (this.props.state) {
							this.props.state.checked = !this.props.state.checked;
							if (typeof this.props.action == "function") this.props.action(this.props.state.checked, this);
						}
						BDFDB.ReactUtils.forceUpdate(this);
					}
					render() {
						return BDFDB.ReactUtils.createElement(Internal.MenuItem, Object.assign({}, this.props, {
							input: this.props.state && this.props.state.checked ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								className: BDFDB.disCN.menuicon,
								background: BDFDB.disCN.menucheckbox,
								foreground: BDFDB.disCN.menucheck,
								name: Internal.LibraryComponents.SvgIcon.Names.CHECKBOX
							}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								className: BDFDB.disCN.menuicon,
								name: Internal.LibraryComponents.SvgIcon.Names.CHECKBOX_EMPTY
							}),
							action: this.handleClick.bind(this)
						}));
					}
				};
				
				CustomComponents.MenuItems.MenuHint = reactInitialized && class BDFDB_MenuHint extends Internal.LibraryModules.React.Component {
					render() {
						return !this.props.hint ? null : BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.menuhint,
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
								children: this.props.hint
							})
						});
					}
				};
				
				CustomComponents.MenuItems.MenuIcon = reactInitialized && class BDFDB_MenuIcon extends Internal.LibraryModules.React.Component {
					render() {
						let isString = typeof this.props.icon == "string";
						return !this.props.icon ? null : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
							className: BDFDB.disCN.menuicon,
							nativeClass: true,
							iconSVG: isString ? this.props.icon : null,
							name: !isString ? this.props.icon : null
						});
					}
				};
				
				CustomComponents.MenuItems.MenuControlItem = function (props) {
					let effectRef = BDFDB.ReactUtils.useRef(null);
					let controlRef = BDFDB.ReactUtils.useRef(null);
					
					BDFDB.ReactUtils.useLayoutEffect((_ => {
						if (props.isFocused) {
							BDFDB.LibraryStores.AccessibilityStore.keyboardModeEnabled && controlRef.current && controlRef.current.scrollIntoView({
								block: "nearest"
							});
							controlRef.current && controlRef.current.focus();
						}
						else controlRef.current && controlRef.current.blur && controlRef.current.blur(controlRef.current);
					}), [props.isFocused]);
					
					return BDFDB.ReactUtils.createElement("div", Object.assign({
						className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.menuitem, BDFDB.disCN[`menucolor${(props.color && InternalData.DiscordClasses[`menucolor${props.color.toLowerCase()}`] || Internal.DiscordConstants.MenuItemColors.DEFAULT || "").toLowerCase()}`], props.disabled && BDFDB.disCN.menudisabled, props.showDefaultFocus && props.isFocused && BDFDB.disCN.menufocused, !props.showDefaultFocus && BDFDB.disCN.menuhideinteraction),
						onClick: BDFDB.ReactUtils.useCallback((_ => {
							if (!controlRef.current || !controlRef.current.activate || !controlRef.current.activate.call(controlRef.current)) typeof props.onClose == "function" && props.onClose();
						}), [props.onClose]),
						"aria-disabled": props.disabled,
						children: [
							props.label && BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.disCN.menulabelcontainer,
								children: BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menulabel,
									children: props.label
								})
							}),
							typeof props.control == "function" && props.control({
								onClose: props.onClose,
								disabled: props.disabled,
								isFocused: props.isFocused
							}, controlRef)
						]
					}, props.menuItemProps));
				};
				
				CustomComponents.MenuItems.MenuSliderItem = reactInitialized && class BDFDB_MenuSliderItem extends Internal.LibraryModules.React.Component {
					handleValueChange(value) {
						if (this.props.state) {
							this.props.state.value = Math.round(BDFDB.NumberUtils.mapRange([0, 100], [this.props.minValue, this.props.maxValue], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
							if (typeof this.props.onValueChange == "function") this.props.onValueChange(this.props.state.value, this);
						}
						BDFDB.ReactUtils.forceUpdate(this);
					}
					handleValueRender(value) {
						let newValue = Math.round(BDFDB.NumberUtils.mapRange([0, 100], [this.props.minValue, this.props.maxValue], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
						if (typeof this.props.onValueRender == "function") {
							let tempReturn = this.props.onValueRender(newValue, this);
							if (tempReturn != undefined) newValue = tempReturn;
						}
						return newValue;
					}
					render() {
						let value = this.props.state && this.props.state.value || 0;
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.MenuItems.MenuControlItem, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							label: typeof this.props.renderLabel == "function" ? this.props.renderLabel(Math.round(value * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits), this) : this.props.label,
							control: (menuItemProps, ref) => {
								return BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.menuslidercontainer,
									children: BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.Slider, Object.assign({}, menuItemProps, {
										ref: ref,
										className: BDFDB.disCN.menuslider,
										mini: true,
										initialValue: Math.round(BDFDB.NumberUtils.mapRange([this.props.minValue, this.props.maxValue], [0, 100], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits),
										onValueChange: this.handleValueChange.bind(this),
										onValueRender: this.handleValueRender.bind(this)
									}))
								});
							}
						}), "digits", "renderLabel"));
					}
				};
				Internal.setDefaultProps(CustomComponents.MenuItems.MenuSliderItem, {minValue: 0, maxValue: 100, digits: 0});
				
				CustomComponents.ModalComponents = {};
				CustomComponents.ModalComponents.ModalContent = reactInitialized && class BDFDB_ModalContent extends Internal.LibraryModules.React.Component {
					render() {
						return this.props.scroller ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Scrollers.Thin, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modalcontent, this.props.className),
							ref: this.props.scrollerRef,
							children: this.props.children
						}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
							className: BDFDB.DOMUtils.formatClassName(this.props.content && BDFDB.disCN.modalcontent, BDFDB.disCN.modalnoscroller, this.props.className),
							direction: this.props.direction || Internal.LibraryComponents.Flex.Direction.VERTICAL,
							align: Internal.LibraryComponents.Flex.Align.STRETCH,
							children: this.props.children
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.ModalComponents.ModalContent, {scroller: true, content: true});
				
				CustomComponents.ModalComponents.ModalTabContent = reactInitialized && class BDFDB_ModalTabContent extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {open: props.open};
					}
					render() {
						return !this.state.open ? null : BDFDB.ReactUtils.createElement(this.props.scroller ? Internal.LibraryComponents.Scrollers.Thin : "div", Object.assign(BDFDB.ObjectUtils.exclude(this.props, "scroller", "open"), {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modaltabcontent, this.state.open && BDFDB.disCN.modaltabcontentopen, this.props.className),
							children: this.props.children
						}));
					}
				};
				Internal.setDefaultProps(CustomComponents.ModalComponents.ModalTabContent, {tab: "unnamed"});
				
				CustomComponents.ModalComponents.ModalFooter = reactInitialized && class BDFDB_ModalFooter extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modalfooter, this.props.className),
							direction: this.props.direction || Internal.LibraryComponents.Flex.Direction.HORIZONTAL_REVERSE,
							align: Internal.LibraryComponents.Flex.Align.STRETCH,
							grow: 0,
							shrink: 0,
							children: this.props.children
						});
					}
				};
				
				CustomComponents.MultiInput = reactInitialized && class BDFDB_MultiInput extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {focused: false};
					}
					render() {
						if (this.props.children && this.props.children.props) this.props.children.props.className = BDFDB.DOMUtils.formatClassName(this.props.children.props.className, BDFDB.disCN.inputmultifield);
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultiwrapper),
							children: BDFDB.ReactUtils.createElement("div", {
								className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.input, BDFDB.disCN.inputmulti, this.state.focused && BDFDB.disCN.inputfocused),
								children: [
									BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.DOMUtils.formatClassName(this.props.innerClassName, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultifirst),
										children: this.props.children
									}),
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
										className: BDFDB.disCN.inputmultilast,
										inputClassName: BDFDB.disCN.inputmultifield,
										onFocus: e => this.setState({focused: true}),
										onBlur: e => this.setState({focused: false})
									}), "children", "innerClassName"))
								]
							})
						});
					}
				};
				
				CustomComponents.ListInput = reactInitialized && class BDFDB_ListInput extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange() {
								if (typeof this.props.onChange) this.props.onChange(this.props.items, this);
							}
							render() {
								if (!BDFDB.ArrayUtils.is(this.props.items)) this.props.items = [];
								return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.MultiInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
									className: BDFDB.disCN.inputlist,
									innerClassName: BDFDB.disCN.inputlistitems,
									onKeyDown: e => {
										if (e.which == 13 && e.target.value && e.target.value.trim()) {
											let value = e.target.value.trim();
											this.props.value = "";
											if (!this.props.items.includes(value)) {
												this.props.items.push(value);
												BDFDB.ReactUtils.forceUpdate(this);
												this.handleChange.apply(this, []);
											}
										}
									},
									children: this.props.items.map(item => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Badges.TextBadge, {
										className: BDFDB.disCN.inputlistitem,
										color: "var(--bdfdb-blurple)",
										style: {borderRadius: "3px"},
										text: [
											item,
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
												className: BDFDB.disCN.inputlistdelete,
												name: Internal.LibraryComponents.SvgIcon.Names.CLOSE,
												onClick: _ => {
													BDFDB.ArrayUtils.remove(this.props.items, item);
													BDFDB.ReactUtils.forceUpdate(this);
													this.handleChange.apply(this, []);
												}
											})
										]
									}))
								}), "items"));
							}
						}, this.props);
					}
				};
				
				CustomComponents.PaginatedList = reactInitialized && class BDFDB_PaginatedList extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {
							offset: props.offset
						};
					}
					handleJump(offset) {
						if (offset > -1 && offset < Math.ceil(this.props.items.length/this.props.amount) && this.state.offset != offset) {
							this.state.offset = offset;
							if (typeof this.props.onJump == "function") this.props.onJump(offset, this);
							BDFDB.ReactUtils.forceUpdate(this);
						}
					}
					renderPagination(bottom) {
						let maxOffset = Math.ceil(this.props.items.length/this.props.amount) - 1;
						return this.props.items.length > this.props.amount && BDFDB.ReactUtils.createElement("nav", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.pagination, bottom ? BDFDB.disCN.paginationbottom : BDFDB.disCN.paginationtop, this.props.mini && BDFDB.disCN.paginationmini),
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Paginator, {
									totalCount: this.props.items.length,
									currentPage: this.state.offset + 1,
									pageSize: this.props.amount,
									maxVisiblePages: this.props.maxVisiblePages,
									onPageChange: page => {this.handleJump(isNaN(parseInt(page)) ? -1 : page - 1);}
								}),
								this.props.jump && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextInput, {
									type: "number",
									size: Internal.LibraryComponents.TextInput.Sizes.MINI,
									value: this.state.offset + 1,
									min: 1,
									max: maxOffset + 1,
									onKeyDown: (event, instance) => {if (event.which == 13) this.handleJump(isNaN(parseInt(instance.props.value)) ? -1 : instance.props.value - 1);}
								}),
							].filter(n => n)
						});
					}
					render() {
						let items = [], alphabet = {};
						if (BDFDB.ArrayUtils.is(this.props.items) && this.props.items.length) {
							if (!this.props.alphabetKey) items = this.props.items;
							else {
								let unsortedItems = [].concat(this.props.items);
								for (let key of ["0-9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]) {
									let numbers = key == "0-9", alphaItems = [];
									for (let item of unsortedItems) if (item && item[this.props.alphabetKey] && (numbers && !isNaN(parseInt(item[this.props.alphabetKey][0])) || item[this.props.alphabetKey].toUpperCase().indexOf(key) == 0)) alphaItems.push(item);
									for (let sortedItem of alphaItems) BDFDB.ArrayUtils.remove(unsortedItems, sortedItem);
									alphabet[key] = {items: BDFDB.ArrayUtils.keySort(alphaItems, this.props.alphabetKey), disabled: !alphaItems.length};
								}
								alphabet["?!"] = {items: BDFDB.ArrayUtils.keySort(unsortedItems, this.props.alphabetKey), disabled: !unsortedItems.length};
								for (let key in alphabet) items.push(alphabet[key].items);
								items = items.flat(10);
							}
						}
						return typeof this.props.renderItem != "function" || !items.length ? null : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Scrollers.Thin, {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.paginationlist, this.props.mini && BDFDB.disCN.paginationlistmini),
							fade: this.props.fade,
							children: [
								this.renderPagination(),
								items.length > this.props.amount && this.props.alphabetKey && BDFDB.ReactUtils.createElement("nav", {
									className: BDFDB.disCN.paginationlistalphabet,
									children: Object.keys(alphabet).map(key => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.paginationlistalphabetchar, alphabet[key].disabled &&BDFDB.disCN.paginationlistalphabetchardisabled),
										onClick: _ => {if (!alphabet[key].disabled) this.handleJump(Math.floor(items.indexOf(alphabet[key].items[0])/this.props.amount));},
										children: key
									}))
								}),
								this.props.header,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.paginationlistcontent,
									children: items.slice(this.state.offset * this.props.amount, (this.state.offset + 1) * this.props.amount).map((data, i) => {return this.props.renderItem(data, i);}).flat(10).filter(n => n)
								}),
								this.props.copyToBottom && this.renderPagination(true)
							].flat(10).filter(n => n)
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.PaginatedList, {amount: 50, offset: 0, mini: true, jump: true, maxVisiblePages: 7, copyToBottom: false, fade: true});
				
				CustomComponents.Popout = reactInitialized && class BDFDB_Popout extends Internal.LibraryModules.React.Component {
					componentDidMount() {
						this.props.containerInstance.popout = this;
						if (typeof this.props.onOpen == "function") this.props.onOpen(this.props.containerInstance, this);
					}
					componentWillUnmount() {
						delete this.props.containerInstance.popout;
						if (typeof this.props.onClose == "function") this.props.onClose(this.props.containerInstance, this);
					}
					render() {
						if (!this.props.wrap) return this.props.children;
						let pos = typeof this.props.position == "string" ? this.props.position.toLowerCase() : null;
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutFocusLock, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.popoutwrapper, this.props.className, this.props.themed && BDFDB.disCN.popoutthemedpopout, this.props.arrow  && BDFDB.disCN.popoutarrow, this.props.arrow && (pos == "top" ? BDFDB.disCN.popoutarrowtop : BDFDB.disCN.popoutarrowbottom)),
							id: this.props.id,
							onClick: e => e.stopPropagation(),
							style: BDFDB.ObjectUtils.extract(this.props, "padding", "height", "maxHeight", "minHeight", "width", "maxWidth", "minWidth"),
							children: this.props.children
						});
					}
				};
				Internal.setDefaultProps(CustomComponents.Popout, {themed: true, wrap: true});
				
				CustomComponents.PopoutContainer = reactInitialized && class BDFDB_PopoutContainer extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						this.state = {open: props.open};
					}
					componentDidMount() {
						this.toggle = this.toggle.bind(this);
						this.onDocumentClicked = this.onDocumentClicked.bind(this);
						this.domElementRef = BDFDB.ReactUtils.createRef();
						this.domElementRef.current = BDFDB.ReactUtils.findDOMNode(this, true) || BDFDB.ReactUtils.findValue(this[BDFDB.ReactUtils.instanceKey], "ref", {notNull: true});
					}
					onDocumentClicked() {
						const node = BDFDB.ReactUtils.findDOMNode(this.popout);
						if (!node || !document.contains(node) || node != event.target && document.contains(event.target) && !node.contains(event.target)) this.toggle(false);
					}
					toggle(forceState) {
						this.setState({open: forceState != undefined ? forceState : !this.state.open});
					}
					render() {
						if (!this.props._rendered) {
							this.props._rendered = true;
							const child = (BDFDB.ArrayUtils.is(this.props.children) ? this.props.children[0] : this.props.children) || BDFDB.ReactUtils.createElement("div", {style: {height: "100%", width: "100%"}});
							child.props.className = BDFDB.DOMUtils.formatClassName(child.props.className, this.props.className);
							const childProps = Object.assign({}, child.props);
							child.props.onClick = (e, childThis) => {
								if ((this.props.openOnClick || this.props.openOnClick === undefined)) this.toggle();
								if (typeof this.props.onClick == "function") this.props.onClick(e, this);
								if (typeof childProps.onClick == "function") childProps.onClick(e, childThis);
								if (this.props.killEvent || childProps.killEvent) BDFDB.ListenerUtils.stopEvent(e);
							};
							child.props.onContextMenu = (e, childThis) => {
								if (this.props.openOnContextMenu) this.toggle();
								if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);
								if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis);
								if (this.props.killEvent || childProps.killEvent) BDFDB.ListenerUtils.stopEvent(e);
							};
							this.props.children = child;
						}
						return BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
							children: [
								this.props.children,
								this.state.open && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.AppReferencePositionLayer, {
									onMount: _ => BDFDB.TimeUtils.timeout(_ => document.addEventListener("click", this.onDocumentClicked)),
									onUnmount: _ => document.removeEventListener("click", this.onDocumentClicked),
									position: this.props.position,
									align: this.props.align,
									targetRef: this.domElementRef,
									children: _ => {
										const popout = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Popout, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
											className: this.props.popoutClassName,
											containerInstance: this,
											position: this.props.position,
											style: this.props.popoutStyle,
											onOpen: typeof this.props.onOpen == "function" ? this.props.onOpen.bind(this) : _ => {},
											onClose: typeof this.props.onClose == "function" ? this.props.onClose.bind(this) : _ => {},
											children: typeof this.props.renderPopout == "function" ? this.props.renderPopout(this) : null
										}), "popoutStyle", "popoutClassName", "shouldShow", "changing", "renderPopout", "openOnClick", "onClick", "openOnContextMenu", "onContextMenu"));
										const animation = Object.entries(Internal.LibraryComponents.PopoutContainer.Animation).find(n => n[1] == this.props.animation);
										return !animation || animation[0] == Internal.LibraryComponents.PopoutContainer.Animation.NONE ? popout : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutCSSAnimator, {
											position: this.props.position,
											type: Internal.LibraryComponents.PopoutCSSAnimator.Types[animation[0]],
											children: popout
										});
									}
								})
							]
						});
					}
				};
				if (CustomComponents.PopoutContainer) {
					CustomComponents.PopoutContainer.Align = {
						BOTTOM: "bottom",
						CENTER: "center",
						LEFT: "left",
						RIGHT: "right",
						TOP: "top"
					};
					CustomComponents.PopoutContainer.Positions = {
						BOTTOM: "bottom",
						CENTER: "center",
						LEFT: "left",
						RIGHT: "right",
						TOP: "top",
						WINDOW_CENTER: "window_center"
					};
					CustomComponents.PopoutContainer.ObjectProperties = ["Animation"];
					Internal.setDefaultProps(CustomComponents.PopoutContainer, {wrap: true});
				}
				
				CustomComponents.PopoutCSSAnimator = function (props) {
					let positionState = BDFDB.ReactUtils.useState(props.position != null);
					let animationState = BDFDB.ReactUtils.useState((_ => new Internal.LibraryComponents.Timeout));
					BDFDB.ReactUtils.useEffect((_ => (_ => animationState[0].stop())), [animationState[0]]);
					BDFDB.ReactUtils.useEffect(_ => (props.position && animationState[0].start(10, (_ => positionState[1](true)))), [props.position, animationState[0]]);
					const position = typeof props.position == "string" && props.position.replace("window_", "");
					const animation = (Object.entries(Internal.LibraryComponents.PopoutContainer.Animation).find(n => n[1] == props.animation) || ["NONE"])[0].toLowerCase();
					return BDFDB.ReactUtils.createElement("div", {
						className: BDFDB.DOMUtils.formatClassName(InternalData.DiscordClasses[`animationcontainer${position}`] && BDFDB.disCN[`animationcontainer${position}`], InternalData.DiscordClasses[`animationcontainer${animation}`] && BDFDB.disCN[`animationcontainer${animation}`], positionState[0] && BDFDB.disCN.animationcontainerrender),
						children: props.children
					})
				};
				if (CustomComponents.PopoutCSSAnimator) CustomComponents.PopoutCSSAnimator.Types = {
					"1": "TRANSLATE",
					"2": "SCALE",
					"3": "FADE",
					"TRANSLATE": "1",
					"SCALE": "2",
					"FADE": "3"
				};
				
				CustomComponents.QuickSelect = reactInitialized && class BDFDB_QuickSelect extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange(option) {
								this.props.value = option;
								if (typeof this.props.onChange == "function") this.props.onChange(option.value || option.key, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							render() {
								let options = (BDFDB.ArrayUtils.is(this.props.options) ? this.props.options : [{}]).filter(n => n);
								let selectedOption = BDFDB.ObjectUtils.is(this.props.value) ? this.props.value : (options[0] || {});
								return BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.quickselectwrapper),
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
										className: BDFDB.disCN.quickselect,
										align: Internal.LibraryComponents.Flex.Align.CENTER,
										children: [
											BDFDB.ReactUtils.createElement("div", {
												className: BDFDB.disCN.quickselectlabel,
												children: this.props.label
											}),
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
												align: Internal.LibraryComponents.Flex.Align.CENTER,
												className: BDFDB.disCN.quickselectclick,
												onClick: event => {
													Internal.LibraryModules.ContextMenuUtils.openContextMenu(event, _ => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Menu, {
														navId: "bdfdb-quickselect",
														onClose: Internal.LibraryModules.ContextMenuUtils.closeContextMenu,
														className: this.props.popoutClassName,
														children: BDFDB.ContextMenuUtils.createItem(Internal.LibraryComponents.MenuItems.MenuGroup, {
															children: options.map((option, i) => {
																let selected = option.value && option.value === selectedOption.value || option.key && option.key === selectedOption.key;
																return BDFDB.ContextMenuUtils.createItem(Internal.LibraryComponents.MenuItems.MenuItem, {
																	label: option.label,
																	id: BDFDB.ContextMenuUtils.createItemId("option", option.key || option.value || i),
																	action: selected ? null : event2 => this.handleChange.bind(this)(option)
																});
															})
														})
													}));
												},
												children: [
													BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.quickselectvalue,
														children: typeof this.props.renderValue == "function" ? this.props.renderValue(this.props.value) : this.props.value.label
													}),
													BDFDB.ReactUtils.createElement("div", {
														className: BDFDB.disCN.quickselectarrow
													})
												]
											})
										]
									})
								});
							}
						}, this.props);
					}
				};
				
				CustomComponents.RadioGroup = reactInitialized && class BDFDB_RadioGroup extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange(value) {
								this.props.value = value.value;
								if (typeof this.props.onChange == "function") this.props.onChange(value, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							render() {
								return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.RadioGroup, Object.assign({}, this.props, {
									onChange: this.handleChange.bind(this)
								}));
							}
						}, this.props);
					}
				};
				
				CustomComponents.Scrollers = new Proxy({}, {
					get: function (_, item) {
						if (item == "AUTO") return Internal.LibraryComponents.ScrollerBase(BDFDB.disCN.scrollerauto, BDFDB.disCN.scrollerfade, BDFDB.disCN.scrollercustomtheme);
						else if (item == "Thin") return Internal.LibraryComponents.ScrollerBase(BDFDB.disCN.scrollerthin, BDFDB.disCN.scrollerfade, BDFDB.disCN.scrollercustomtheme);
						else if (item == "None") return Internal.LibraryComponents.ScrollerBase(BDFDB.disCN.scrollernone, BDFDB.disCN.scrollerfade, BDFDB.disCN.scrollercustomtheme);
						else return "div";
					}
				});
				
				CustomComponents.SearchBar = reactInitialized && class BDFDB_SearchBar extends Internal.LibraryModules.React.Component {
					handleChange(query) {
						this.props.query = query;
						if (typeof this.props.onChange == "function") this.props.onChange(query, this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					handleClear() {
						this.props.query = "";
						if (this.props.changeOnClear && typeof this.props.onChange == "function") this.props.onChange("", this);
						if (typeof this.props.onClear == "function") this.props.onClear(this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					render() {
						let props = Object.assign({}, this.props, {
							onChange: this.handleChange.bind(this),
							onClear: this.handleClear.bind(this)
						});
						if (typeof props.query != "string") props.query = "";
						return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.SearchBar, props);
					}
				};
				
				CustomComponents.Select = reactInitialized && class BDFDB_Select extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange(value) {
								this.props.value = value.value || value;
								if (typeof this.props.onChange == "function") this.props.onChange(value, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							render() {
								return BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.selectwrapper),
									children: BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.SearchableSelect, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
										className: this.props.inputClassName,
										autoFocus: this.props.autoFocus ? this.props.autoFocus : false,
										maxVisibleItems: this.props.maxVisibleItems || 7,
										renderOptionLabel: this.props.optionRenderer,
										select: this.handleChange.bind(this),
										serialize: typeof this.props.serialize == "function" ? this.props.serialize : _ => {},
										isSelected: typeof this.props.isSelected == "function" ? this.props.isSelected : (value => this.props.value == value)
									}), "inputClassName", "optionRenderer"))
								});
							}
						}, this.props);
					}
				};
				
				CustomComponents.SettingsGuildList = reactInitialized && class BDFDB_SettingsGuildList extends Internal.LibraryModules.React.Component {
					render() {
						this.props.disabled = BDFDB.ArrayUtils.is(this.props.disabled) ? this.props.disabled : [];
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
							className: this.props.className,
							wrap: Internal.LibraryComponents.Flex.Wrap.WRAP,
							children: [this.props.includeDMs && {name: BDFDB.LanguageUtils.LanguageStrings.DIRECT_MESSAGES, acronym: "DMs", id: Internal.DiscordConstants.ME, getIconURL: _ => {}}].concat(Internal.LibraryStores.SortedGuildStore.getFlattenedGuildIds().map(Internal.LibraryStores.GuildStore.getGuild)).filter(n => n).map(guild => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
								text: guild.name,
								children: BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(this.props.guildClassName, BDFDB.disCN.settingsguild, this.props.disabled.includes(guild.id) && BDFDB.disCN.settingsguilddisabled),
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.GuildIcon, {
										guild: guild,
										size: this.props.size || Internal.LibraryComponents.GuildIcon.Sizes.MEDIUM
									}),
									onClick: e => {
										let isDisabled = this.props.disabled.includes(guild.id);
										if (isDisabled) BDFDB.ArrayUtils.remove(this.props.disabled, guild.id, true);
										else this.props.disabled.push(guild.id);
										if (typeof this.props.onClick == "function") this.props.onClick(this.props.disabled, this);
										BDFDB.ReactUtils.forceUpdate(this);
									}
								})
							}))
						});
					}
				};
				
				CustomComponents.SettingsPanel = reactInitialized && class BDFDB_SettingsPanel extends Internal.LibraryModules.React.Component {
					componentDidMount() {
						this.props._instance = this;
						let node = BDFDB.ReactUtils.findDOMNode(this);
						if (node) this.props._node = node;
					}
					componentWillUnmount() {
						if (BDFDB.ObjectUtils.is(this.props.addon) && typeof this.props.addon.onSettingsClosed == "function") this.props.addon.onSettingsClosed();
					}
					render() {						
						let panelItems = [
							BDFDB.ReactUtils.createElement(Internal.LibraryComponents.AutoFocusCatcher, {}),
							typeof this.props.children == "function" ? (_ => {
								return this.props.children(this.props.collapseStates);
							})() : this.props.children
						].flat(10).filter(n => n);
						return BDFDB.ReactUtils.createElement("div", {
							key: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settingsPanel`,
							id: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settings`,
							className: BDFDB.disCN.settingspanel,
							children: [
								this.props.addon.changeLog && !BDFDB.ObjectUtils.isEmpty(this.props.addon.changeLog) && BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
									text: BDFDB.LanguageUtils.LanguageStrings.CHANGE_LOG,
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
										className: BDFDB.disCN._repochangelogbutton,
										children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
											name: Internal.LibraryComponents.SvgIcon.Names.CHANGELOG,
											onClick: _ => BDFDB.PluginUtils.openChangeLog(this.props.addon),
											width: 24,
											height: 24
										})
									})
								}),
								panelItems
							]
						});
					}
				};
				
				CustomComponents.SettingsPanelList = reactInitialized && class BDFDB_SettingsPanelInner extends Internal.LibraryModules.React.Component {
					render() {
						return this.props.children ? BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingspanellistwrapper, this.props.mini && BDFDB.disCN.settingspanellistwrappermini),
							children: [
								this.props.dividerTop ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
									className: this.props.mini ? BDFDB.disCN.marginbottom4 : BDFDB.disCN.marginbottom8
								}) : null,
								typeof this.props.title == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormTitle.Title, {
									className: BDFDB.disCN.marginbottom4,
									tag: Internal.LibraryComponents.FormTitle.Tags && Internal.LibraryComponents.FormTitle.Tags.H3,
									children: this.props.title
								}) : null,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.settingspanellist,
									children: this.props.children
								}),
								this.props.dividerBottom ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
									className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8
								}) : null
							]
						}) : null;
					}
				};
				
				CustomComponents.SettingsItem = reactInitialized && class BDFDB_SettingsItem extends Internal.LibraryModules.React.Component {
					constructor(props) {
						super(props);
						if (!this.state) this.state = {};
						this.state.disabled = props.disabled;
					}
					handleChange(value) {
						if (typeof this.props.onChange == "function") this.props.onChange(value, this);
					}
					render() {
						if (typeof this.props.type != "string" || !["BUTTON", "SELECT", "SLIDER", "SWITCH", "TEXTINPUT"].includes(this.props.type.toUpperCase())) return null;
						let childComponent = Internal.LibraryComponents[this.props.type];
						if (!childComponent) return null;
						if (this.props.mini && childComponent.Sizes) this.props.size = childComponent.Sizes.MINI || childComponent.Sizes.MIN;
						let label = this.props.label ? (this.props.tag ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormTitle.Title, {
							className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName, BDFDB.disCN.marginreset),
							tag: this.props.tag,
							children: this.props.label
						}) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
							size: Internal.LibraryComponents.TextElement.Sizes.SIZE_16,
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsLabel, {
								className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName),
								mini: this.props.mini,
								label: this.props.label
							})
						})) : null;
						let margin = this.props.margin != null ? this.props.margin : (this.props.mini ? 0 : 8);
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrowcontainer, margin != null && (InternalData.DiscordClasses[`marginbottom${margin}`] && BDFDB.disCN[`marginbottom${margin}`] || margin == 0 && BDFDB.disCN.marginreset)),
							id: this.props.id,
							children: [
								this.props.dividerTop ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
									className: this.props.mini ? BDFDB.disCN.marginbottom4 : BDFDB.disCN.marginbottom8
								}) : null,
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingsrow, this.state.disabled && BDFDB.disCN.settingsrowdisabled),
									"data-layout": "horizontal",
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.settingsrowlabel,
											children: [
												label && !this.props.basis ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
													grow: 1,
													shrink: 1,
													wrap: true,
													children: label
												}) : label,
												typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
													className: BDFDB.disCN.settingsrownote,
													children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
														size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
														children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
															speed: 2,
															children: this.props.note
														})
													})
												}) : null
											].flat(10).filter(n => n)
										}),
										BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
											className: BDFDB.disCNS.settingsrowcontrol + BDFDB.disCN.flexchild,
											grow: 0,
											shrink: this.props.basis ? 0 : 1,
											basis: this.props.basis,
											wrap: true,
											style: {"flex-direction": "row", "align-items": "center"},
											children: [
												this.props.labelChildren,
												BDFDB.ReactUtils.createElement(childComponent, BDFDB.ObjectUtils.exclude(Object.assign(BDFDB.ObjectUtils.exclude(this.props, "className", "id", "type"), this.props.childProps, {
													disabled: this.state.disabled,
													onChange: this.handleChange.bind(this),
													onValueChange: this.handleChange.bind(this)
												}), "basis", "margin", "dividerBottom", "dividerTop", "label", "labelClassName", "labelChildren", "tag", "mini", "note", "childProps"))
											].flat(10).filter(n => n)
										})
									]
								}),
								this.props.dividerBottom ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FormDivider, {
									className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8
								}) : null
							]
						});
					}
				};
				
				CustomComponents.SettingsLabel = reactInitialized && class BDFDB_SettingsLabel extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextScroller, {
								className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrowtitle, this.props.mini && BDFDB.disCN.settingsrowtitlemini, BDFDB.disCN.cursordefault),
								speed: 2,
								children: this.props.label
							})
					}	
				};
				
				CustomComponents.SettingsList = reactInitialized && class BDFDB_SettingsList extends Internal.LibraryModules.React.Component {
					componentDidMount() {
						this.checkList();
					}
					componentDidUpdate() {
						this.checkList();
					}
					checkList() {
						let list = BDFDB.ReactUtils.findDOMNode(this);
						if (list && !this.props.configWidth) {
							let headers = Array.from(list.querySelectorAll(BDFDB.dotCN.settingstableheader));
							headers.shift();
							if (BDFDB.DOMUtils.getRects(headers[0]).width == 0) BDFDB.TimeUtils.timeout(_ => this.resizeList(headers));
							else this.resizeList(headers);
						}
					}
					resizeList(headers) {
						let configWidth = 0, biggestWidth = 0;
						if (!configWidth) {
							for (let header of headers) {
								header.style = "";
								let width = BDFDB.DOMUtils.getRects(header).width;
								configWidth = width > configWidth ? width : configWidth;
							}
							configWidth += 4;
							biggestWidth = configWidth;
						}
						if (headers.length * configWidth > 300) {
							this.props.vertical = true;
							configWidth = parseInt(290 / headers.length);
						}
						else if (configWidth < 36) {
							configWidth = 36;
							biggestWidth = configWidth;
						}
						this.props.configWidth = configWidth;
						this.props.biggestWidth = biggestWidth;
						BDFDB.ReactUtils.forceUpdate(this);
					}
					renderHeaderOption(props) {
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.eyebrow, props.clickable && BDFDB.disCN.cursorpointer),
							onClick: _ => {if (typeof this.props.onHeaderClick == "function") this.props.onHeaderClick(props.label, this);},
							onContextMenu: _ => {if (typeof this.props.onHeaderContextMenu == "function") this.props.onHeaderContextMenu(props.label, this);},
							children: BDFDB.ReactUtils.createElement("span", {
								children: props.label
							})
						});
					}
					renderItem(props) {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Card, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName([this.props.cardClassName, props.className].filter(n => n).join(" ").indexOf(BDFDB.disCN.card) == -1 && BDFDB.disCN.cardprimary, BDFDB.disCN.settingstablecard, this.props.cardClassName, props.className),
							cardId: props.key,
							backdrop: false,
							horizontal: true,
							style: Object.assign({}, this.props.cardStyle, props.style),
							children: [
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.settingstablecardlabel,
									children: this.props.renderLabel(props, this)
								}),
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.settingstablecardconfigs,
									style: {
										width: props.wrapperWidth || null,
										minWidth: props.wrapperWidth || null,
										maxWidth: props.wrapperWidth || null
									},
									children: this.props.settings.map(setting => BDFDB.ReactUtils.createElement("div", {
										className: BDFDB.disCN.checkboxcontainer,
										children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
											text: setting.toUpperCase(),
											children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Checkbox, {
												disabled: props.disabled,
												cardId: props.key,
												settingId: setting,
												shape: Internal.LibraryComponents.Checkbox.Shapes && Internal.LibraryComponents.Checkbox.Shapes.ROUND,
												type: Internal.LibraryComponents.Checkbox.Types && Internal.LibraryComponents.Checkbox.Types.INVERTED,
												color: this.props.checkboxColor,
												getColor: this.props.getCheckboxColor,
												value: props[setting],
												getValue: this.props.getCheckboxValue,
												onChange: this.props.onCheckboxChange
											})
										})
									})).flat(10).filter(n => n)
								})
							]
						}), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "checkboxColor", "getCheckboxColor", "getCheckboxValue", "onCheckboxChange", "configWidth", "biggestWidth", "pagination"));
					}
					render() {
						this.props.settings = BDFDB.ArrayUtils.is(this.props.settings) ? this.props.settings : [];
						this.props.renderLabel = typeof this.props.renderLabel == "function" ? this.props.renderLabel : data => data.label;
						this.props.data = (BDFDB.ArrayUtils.is(this.props.data) ? this.props.data : [{}]).filter(n => n);
						
						let wrapperWidth = this.props.configWidth && this.props.configWidth * this.props.settings.length;
						let isHeaderClickable = typeof this.props.onHeaderClick == "function" || typeof this.props.onHeaderContextMenu == "function";
						let usePagination = BDFDB.ObjectUtils.is(this.props.pagination);
						
						let header = BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.disCN.settingstableheaders,
							style: this.props.vertical && this.props.biggestWidth ? {
								marginTop: this.props.biggestWidth - 15 || 0
							} : {},
							children: [
								this.renderHeaderOption({
									className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstableheadername, BDFDB.disCN.settingstableheader),
									clickable: this.props.title && isHeaderClickable,
									label: this.props.title || ""
								}),
								BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.settingstableheaderoptions,
									style: {
										width: wrapperWidth || null,
										minWidth: wrapperWidth || null,
										maxWidth: wrapperWidth || null
									},
									children: this.props.settings.map(setting => this.renderHeaderOption({
										className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstableheaderoption, BDFDB.disCN.settingstableheader, this.props.vertical && BDFDB.disCN.settingstableheadervertical),
										clickable: isHeaderClickable,
										label: setting
									}))
								})
							]
						});
						return !this.props.data.length ? null : BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstablelist, this.props.className),
							children: [
								!usePagination && header,
								!usePagination ? this.props.data.map(data => this.renderItem(Object.assign({}, data, {wrapperWidth}))) : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PaginatedList, Object.assign({}, this.props.pagination, {
									header: header,
									items: this.props.data,
									renderItem: data => this.renderItem(Object.assign({}, data, {wrapperWidth})),
									onJump: (offset, instance) => {
										this.props.pagination.offset = offset;
										if (typeof this.props.pagination.onJump == "function") this.props.pagination.onJump(offset, this, instance);
									}
								}))
							].filter(n => n)
						});
					}
				};
				
				CustomComponents.SettingsSaveItem = reactInitialized && class BDFDB_SettingsSaveItem extends Internal.LibraryModules.React.Component {
					saveSettings(value) {
						if (!BDFDB.ArrayUtils.is(this.props.keys) || !BDFDB.ObjectUtils.is(this.props.plugin)) return;
						let keys = this.props.keys.filter(n => n);
						let option = keys.shift();
						if (BDFDB.ObjectUtils.is(this.props.plugin) && option) {
							let data = BDFDB.DataUtils.load(this.props.plugin, option);
							let newC = "";
							for (let key of keys) newC += `{"${key}":`;
							value = value != null && value.value != null ? value.value : value;
							let isString = typeof value == "string";
							let marker = isString ? `"` : ``;
							newC += (marker + (isString ? value.replace(/\\/g, "\\\\") : value) + marker) + "}".repeat(keys.length);
							newC = JSON.parse(newC);
							newC = BDFDB.ObjectUtils.is(newC) ? BDFDB.ObjectUtils.deepAssign({}, data, newC) : newC;
							BDFDB.DataUtils.save(newC, this.props.plugin, option);
							if (!this.props.plugin.settings) this.props.plugin.settings = {};
							this.props.plugin.settings[option] = newC;
							this.props.plugin.SettingsUpdated = true;
						}
						if (typeof this.props.onChange == "function") this.props.onChange(value, this);
					}
					render() {
						if (typeof this.props.type != "string" || !["SELECT", "SLIDER", "SWITCH", "TEXTINPUT"].includes(this.props.type.toUpperCase())) return null;
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsItem, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							onChange: this.saveSettings.bind(this)
						}), "keys", "key", "plugin"));
					}
				};
				
				CustomComponents.SidebarList = reactInitialized && class BDFDB_SidebarList extends Internal.LibraryModules.React.Component {
					handleItemSelect(item) {
						this.props.selectedItem = item;
						if (typeof this.props.onItemSelect == "function") this.props.onItemSelect(item, this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					render() {
						let items = (BDFDB.ArrayUtils.is(this.props.items) ? this.props.items : [{}]).filter(n => n);
						let selectedItem = this.props.selectedItem || (items[0] || {}).value;
						let selectedElements = (items.find(n => n.value == selectedItem) || {}).elements;
						let renderElement = typeof this.props.renderElement == "function" ? this.props.renderElement : (_ => {});
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.sidebarlist),
							children: [
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Scrollers.Thin, {
									className: BDFDB.DOMUtils.formatClassName(this.props.sidebarClassName, BDFDB.disCN.sidebar),
									fade: true,
									children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TabBar, {
										itemClassName: this.props.itemClassName,
										type: Internal.LibraryComponents.TabBar.Types.SIDE,
										items: items,
										selectedItem: selectedItem,
										renderItem: this.props.renderItem,
										onItemSelect: this.handleItemSelect.bind(this)
									})
								}),
								BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Scrollers.Thin, {
									className: BDFDB.DOMUtils.formatClassName(this.props.contentClassName, BDFDB.disCN.sidebarcontent),
									fade: true,
									children: [selectedElements].flat(10).filter(n => n).map(data => renderElement(data))
								})
							]
						});
					}
				};
				
				CustomComponents.Slider = reactInitialized && class BDFDB_Slider extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleMarkerRender(marker) {
								let newMarker = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, marker);
								if (typeof this.props.digits == "number") newMarker = Math.round(newMarker * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
								return newMarker;
							}
							handleValueChange(value) {
								let newValue = value;
								if (typeof this.props.digits == "number") newValue = Math.round(newValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
								if (newValue < this.props.minValue) newValue = this.props.minValue;
								else if (newValue > this.props.maxValue) newValue = this.props.maxValue;
								this.props.defaultValue = this.props.value = newValue;
								if (typeof this.props.onValueChange == "function") this.props.onValueChange(BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, newValue), this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							handleValueRender(value) {
								let newValue = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, value);
								if (typeof this.props.digits == "number") newValue = Math.round(newValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
								if (typeof this.props.onValueRender == "function") {
									let tempReturn = this.props.onValueRender(newValue, this);
									if (tempReturn != undefined) newValue = tempReturn;
								}
								return newValue;
							}
							render() {
								let value = this.props.value || this.props.defaultValue || 0;
								this.props.minValue = 0;
								this.props.maxValue = 100;
								if (!BDFDB.ArrayUtils.is(this.props.edges) || this.props.edges.length != 2) this.props.edges = [this.props.min || this.props.minValue, this.props.max || this.props.maxValue];
								let defaultValue = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, value);
								if (typeof this.props.digits == "number") defaultValue = Math.round(defaultValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits);
								return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.Slider, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
									initialValue: defaultValue,
									markers: typeof this.props.markerAmount == "number" ? Array.from(Array(this.props.markerAmount).keys()).map((_, i) => i * (this.props.maxValue - this.props.minValue)/10) : undefined,
									onMarkerRender: this.handleMarkerRender.bind(this),
									onValueChange: this.handleValueChange.bind(this),
									onValueRender: this.handleValueRender.bind(this)
								}), "digits", "edges", "max", "min", "markerAmount"));
							}
						}, this.props);
					}
				};
				Internal.setDefaultProps(CustomComponents.Slider, {hideBubble: false, digits: 3});
				
				CustomComponents.SvgIcon = reactInitialized && class BDFDB_Icon extends Internal.LibraryModules.React.Component {
					render() {
						if (BDFDB.ObjectUtils.is(this.props.name)) {
							if (this.props.className) this.props.nativeClass = true;
							this.props.iconSVG = this.props.name.icon;
							let props = Object.assign({
								width: 24,
								height: 24,
								color: "currentColor"
							}, this.props.name.defaultProps, this.props);
							for (let key in props) this.props.iconSVG = this.props.iconSVG.replace(new RegExp(`%%${key}`, "g"), props[key]);
						}
						if (this.props.iconSVG) {
							let icon = BDFDB.ReactUtils.elementToReact(BDFDB.DOMUtils.create(this.props.iconSVG));
							if (BDFDB.ReactUtils.isValidElement(icon)) {
								icon.props.className = BDFDB.DOMUtils.formatClassName(!this.props.nativeClass && BDFDB.disCN.svgicon, icon.props.className, this.props.className);
								icon.props.style = Object.assign({}, icon.props.style, this.props.style);
								icon.props = Object.assign({}, BDFDB.ObjectUtils.extract(this.props, "onClick", "onContextMenu", "onMouseDown", "onMouseUp", "onMouseEnter", "onMouseLeave"), icon.props);
								return icon;
							}
						}
						return null;
					}
				};
				if (CustomComponents.SvgIcon) CustomComponents.SvgIcon.Names = InternalData.SvgIcons || {};
				
				const SwitchIconPaths = {
					a: {
						TOP: "M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z",
						BOTTOM: "M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z"
					},
					b: {
						TOP: "M6.56666 11.0013L6.56666 8.96683L13.5667 8.96683L13.5667 11.0013L6.56666 11.0013Z",
						BOTTOM: "M13.5582 8.96683L13.5582 11.0013L6.56192 11.0013L6.56192 8.96683L13.5582 8.96683Z"
					},
					c: {
						TOP: "M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z",
						BOTTOM: "M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z"
					}
				};
				const SwitchInner = function (props) {
					let reducedMotion = BDFDB.ReactUtils.useContext(Internal.LibraryModules.PreferencesContext.AccessibilityPreferencesContext).reducedMotion;
					let ref = BDFDB.ReactUtils.useRef(null);
					let state = BDFDB.ReactUtils.useState(false);
					let animation = Internal.LibraryComponents.Animations.useSpring({
						config: {
							mass: 1,
							tension: 250
						},
						opacity: props.disabled ? .3 : 1,
						state: state[0] ? (props.value ? .7 : .3) : (props.value ? 1 : 0)
					});
					let fill = animation.state.to({
						output: [props.uncheckedColor, props.checkedColor]
					});
					let mini = props.size == Internal.LibraryComponents.Switch.Sizes.MINI;
					
					return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.div, {
						className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.switch, props.value && BDFDB.disCN.switchchecked, mini && BDFDB.disCN.switchmini),
						onMouseDown: _ => {
							return !props.disabled && state[1](true);
						},
						onMouseUp: _ => {
							return state[1](false);
						},
						onMouseLeave: _ => {
							return state[1](false);
						},
						style: {
							opacity: animation.opacity,
							backgroundColor: animation.state.to({
								output: [props.uncheckedColor, props.checkedColor]
							})
						},
						tabIndex: -1,
						children: [
							BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.svg, {
								className: BDFDB.disCN.switchslider,
								viewBox: "0 0 28 20",
								preserveAspectRatio: "xMinYMid meet",
								style: {
									left: animation.state.to({
										range: [0, .3, .7, 1],
										output: mini ? [-1, 2, 6, 9] : [-3, 1, 8, 12]
									})
								},
								children: [
									BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.rect, {
										fill: "white",
										x: animation.state.to({
											range: [0, .3, .7, 1],
											output: [4, 0, 0, 4]
										}),
										y: animation.state.to({
											range: [0, .3, .7, 1],
											output: [0, 1, 1, 0]
										}),
										height: animation.state.to({
											range: [0, .3, .7, 1],
											output: [20, 18, 18, 20]
										}),
										width: animation.state.to({
											range: [0, .3, .7, 1],
											output: [20, 28, 28, 20]
										}),
										rx: "10"
									}),
									BDFDB.ReactUtils.createElement("svg", {
										viewBox: "0 0 20 20",
										fill: "none",
										children: [
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.path, {
												fill: fill,
												d: animation.state.to({
													range: [0, .3, .7, 1],
													output: reducedMotion.enabled ? [SwitchIconPaths.a.TOP, SwitchIconPaths.a.TOP, SwitchIconPaths.c.TOP, SwitchIconPaths.c.TOP] : [SwitchIconPaths.a.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.c.TOP]
												})
											}),
											BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Animations.animated.path, {
												fill: fill,
												d: animation.state.to({
													range: [0, .3, .7, 1],
													output: reducedMotion.enabled ? [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.a.BOTTOM, SwitchIconPaths.c.BOTTOM, SwitchIconPaths.c.BOTTOM] : [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.c.BOTTOM]
												})
											})
										]
									})
								]
							}),
							BDFDB.ReactUtils.createElement("input", BDFDB.ObjectUtils.exclude(Object.assign({}, props, {
								id: props.id,
								type: "checkbox",
								ref: ref,
								className: BDFDB.DOMUtils.formatClassName(props.inputClassName, BDFDB.disCN.switchinner),
								tabIndex: props.disabled ? -1 : 0,
								onKeyDown: e => {
									if (!props.disabled && !e.repeat && (e.key == " " || e.key == "Enter")) state[1](true);
								},
								onKeyUp: e => {
									if (!props.disabled && !e.repeat) {
										state[1](false);
										if (e.key == "Enter" && ref.current) ref.current.click();
									}
								},
								onChange: e => {
									state[1](false);
									if (typeof props.onChange == "function") props.onChange((e.currentTarget || e.target).checked, e);
								},
								checked: props.value,
								disabled: props.disabled
							}), "uncheckedColor", "checkedColor", "size", "value"))
						]
					});
				};
				CustomComponents.Switch = reactInitialized && class BDFDB_Switch extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange() {
								this.props.value = !this.props.value;
								if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							render() {
								return BDFDB.ReactUtils.createElement(SwitchInner, Object.assign({}, this.props, {
									onChange: this.handleChange.bind(this)
								}));
							}
						}, this.props);
					}
				};
				if (CustomComponents.Switch) {
					CustomComponents.Switch.Sizes = {
						DEFAULT: "default",
						MINI: "mini",
					};
					Internal.setDefaultProps(CustomComponents.Switch, {
						size: CustomComponents.Switch.Sizes.DEFAULT,
						uncheckedColor: Internal.DiscordConstants.Colors.PRIMARY_400,
						checkedColor: Internal.DiscordConstants.Colors.BRAND
					});
				}
				
				CustomComponents.TabBar = reactInitialized && class BDFDB_TabBar extends Internal.LibraryModules.React.Component {
					handleItemSelect(item) {
						this.props.selectedItem = item;
						if (typeof this.props.onItemSelect == "function") this.props.onItemSelect(item, this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					render() {
						let items = (BDFDB.ArrayUtils.is(this.props.items) ? this.props.items : [{}]).filter(n => n);
						let selectedItem = this.props.selectedItem || (items[0] || {}).value;
						let renderItem = typeof this.props.renderItem == "function" ? this.props.renderItem : (data => data.label || data.value);
						return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.TabBar, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							selectedItem: selectedItem,
							onItemSelect: this.handleItemSelect.bind(this),
							children: items.map(data => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TabBar.Item, {
								className: BDFDB.DOMUtils.formatClassName(this.props.itemClassName, selectedItem == data.value && this.props.itemSelectedClassName),
								color: this.props.color,
								look: this.props.look,
								itemType: this.props.type,
								id: data.value,
								children: renderItem(data),
								"aria-label": data.label || data.value
							}))
						}), "itemClassName", "items", "renderItem"));
					}
				};
				if (CustomComponents.TabBar) {
					CustomComponents.TabBar.Types = {
						SIDE: "side",
						TOP: "top",
						TOP_PILL: "top-pill"
					};
					CustomComponents.TabBar.Looks = {
						GREY: "grey",
						BRAND: "brand",
						CUSTOM: "custom"
					};
				}
				
				CustomComponents.Table = reactInitialized && class BDFDB_Table extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.Table, Object.assign({}, this.props, {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.table, this.props.className),
							headerCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tableheadercell, this.props.headerCellClassName),
							sortedHeaderCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tableheadercellsorted, this.props.sortedHeaderCellClassName),
							bodyCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tablebodycell, this.props.bodyCellClassName),
							onSort: (sortKey, sortDirection) => {
								this.props.sortDirection = this.props.sortKey != sortKey && sortDirection == Internal.LibraryComponents.Table.SortDirection.ASCENDING && this.props.columns.filter(n => n.key == sortKey)[0].reverse ? Internal.LibraryComponents.Table.SortDirection.DESCENDING : sortDirection;
								this.props.sortKey = sortKey;
								this.props.data = BDFDB.ArrayUtils.keySort(this.props.data, this.props.sortKey);
								if (this.props.sortDirection == Internal.LibraryComponents.Table.SortDirection.DESCENDING) this.props.data.reverse();
								if (typeof this.props.onSort == "function") this.props.onSort(this.props.sortKey, this.props.sortDirection);
								BDFDB.ReactUtils.forceUpdate(this);
							}
						}));
					}
				};
				
				CustomComponents.TextArea = reactInitialized && class BDFDB_TextArea extends Internal.LibraryModules.React.Component {
					render () {
						return BDFDB.ReactUtils.createElement(class extends Internal.LibraryModules.React.Component {
							handleChange(e) {
								this.props.value = e;
								if (typeof this.props.onChange == "function") this.props.onChange(e, this);
								BDFDB.ReactUtils.forceUpdate(this);
							}
							handleBlur(e) {if (typeof this.props.onBlur == "function") this.props.onBlur(e, this);}
							handleFocus(e) {if (typeof this.props.onFocus == "function") this.props.onFocus(e, this);}
							render() {
								return BDFDB.ReactUtils.createElement(Internal.NativeSubComponents.TextArea, Object.assign({}, this.props, {
									onChange: this.handleChange.bind(this),
									onBlur: this.handleBlur.bind(this),
									onFocus: this.handleFocus.bind(this)
								}));
							}
						}, this.props);
					}
				};
				
				CustomComponents.TextElement = reactInitialized && class BDFDB_TextElement extends Internal.LibraryModules.React.Component {
					render() {
						let color = this.props.color != undefined ? this.props.color && Internal.DiscordConstants.ColorsCSS[this.props.color] : Internal.DiscordConstants.ColorsCSS[CustomComponents.TextElement.Colors.STANDARD];
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Text, {
							className: this.props.className,
							variant: `${this.props.size || CustomComponents.TextElement.Sizes.SIZE_14}/${this.props.weight || "normal"}`,
							style: color ? {color: color} : {},
							color: "",
							children: this.props.children
						});
					}
				};
				CustomComponents.TextElement.Colors = {
					"CUSTOM": "",
					"MUTED": "TEXT_MUTED",
					"PRIMARY": "TEXT_PRIMARY",
					"STANDARD": "TEXT_DEFAULT",
					"STATUS_RED": "STATUS_DANGER"
				};
				CustomComponents.TextElement.Sizes = {
					"SIZE_10": "text-xxs",
					"SIZE_12": "text-xs",
					"SIZE_14": "text-sm",
					"SIZE_16": "text-md",
					"SIZE_20": "text-lg"
				};
				
				CustomComponents.TextGradientElement = reactInitialized && class BDFDB_TextGradientElement extends Internal.LibraryModules.React.Component {
					render() {
						if (this.props.gradient && this.props.children) return BDFDB.ReactUtils.createElement("span", {
							children: this.props.children,
							ref: instance => {
								let ele = BDFDB.ReactUtils.findDOMNode(instance);
								if (ele) {
									ele.style.setProperty("background-image", this.props.gradient, "important");
									ele.style.setProperty("color", "transparent", "important");
									ele.style.setProperty("text-decoration-color", BDFDB.ColorUtils.convert(this.props.gradient[0], "RGBA"), "important");
									ele.style.setProperty("-webkit-background-clip", "text", "important");
								}
							}
						});
						return this.props.children || null;
					}
				};
				
				CustomComponents.TextInput = reactInitialized && class BDFDB_TextInputInner extends Internal.LibraryModules.React.Component {
					handleChange(e, e2) {
						let value = e = BDFDB.ObjectUtils.is(e) ? (e.currentTarget || e.target).value : e;
						if (this.props.type == "number") value = parseInt(value);
						this.props.value = this.props.valuePrefix && !value.startsWith(this.props.valuePrefix) ? (this.props.valuePrefix + value) : value;
						this.props.file = e2 = BDFDB.ObjectUtils.is(e2) ? (e2.currentTarget || e2.target).value : e2;
						if (typeof this.props.onChange == "function") this.props.onChange(this.props.type == "file" ? this.props.file : this.props.value, this);
						BDFDB.ReactUtils.forceUpdate(this);
					}
					handleInput(e) {if (typeof this.props.onInput == "function") this.props.onInput(BDFDB.ObjectUtils.is(e) ? (e.currentTarget || e.target).value : e, this);}
					handleKeyDown(e) {if (typeof this.props.onKeyDown == "function") this.props.onKeyDown(e, this);}
					handleBlur(e) {if (typeof this.props.onBlur == "function") this.props.onBlur(e, this);}
					handleFocus(e) {if (typeof this.props.onFocus == "function") this.props.onFocus(e, this);}
					handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}
					handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}
					handleNumberButton(ins, value) {
						BDFDB.TimeUtils.clear(this.pressedTimeout);
						this.pressedTimeout = BDFDB.TimeUtils.timeout(_ => {
							delete this.props.focused;
							BDFDB.ReactUtils.forceUpdate(this);
						}, 1000);
						this.props.focused = true;
						this.handleChange.apply(this, [value]);
						this.handleInput.apply(this, [value]);
					}
					componentDidMount() {
						if (this.props.type == "file") {
							let navigatorInstance = BDFDB.ReactUtils.findOwner(this, {name: "BDFDB_FileButton"});
							if (navigatorInstance) navigatorInstance.refInput = this;
						}
						let input = BDFDB.ReactUtils.findDOMNode(this);
						if (!input) return;
						input = input.querySelector("input") || input;
						if (input && !input.patched) {
							input.addEventListener("keydown", e => {
								this.handleKeyDown.apply(this, [e]);
								e.stopImmediatePropagation();
							});
							input.patched = true;
						}
					}
					render() {
						let inputChildren = [
							BDFDB.ReactUtils.createElement("input", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
								className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.input, this.props.size, this.props.inputClassName, this.props.focused && BDFDB.disCN.inputfocused, this.props.error || this.props.errorMessage ? BDFDB.disCN.inputerror : (this.props.success && BDFDB.disCN.inputsuccess), this.props.disabled && BDFDB.disCN.inputdisabled, this.props.editable && BDFDB.disCN.inputeditable),
								type: this.props.type == "color" || this.props.type == "file" ? "text" : this.props.type,
								onChange: this.handleChange.bind(this),
								onInput: this.handleInput.bind(this),
								onKeyDown: this.handleKeyDown.bind(this),
								onBlur: this.handleBlur.bind(this),
								onFocus: this.handleFocus.bind(this),
								onMouseEnter: this.handleMouseEnter.bind(this),
								onMouseLeave: this.handleMouseLeave.bind(this),
								maxLength: this.props.type == "file" ? false : this.props.maxLength,
								style: this.props.width ? {width: `${this.props.width}px`} : {},
								ref: this.props.inputRef
							}), "errorMessage", "focused", "error", "success", "inputClassName", "inputChildren", "valuePrefix", "size", "editable", "inputRef", "style", "mode", "colorPickerOpen", "noAlpha", "filter")),
							this.props.inputChildren,
							this.props.type == "color" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
								wrap: true,
								children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.ColorSwatches, {
									colors: [],
									color: this.props.value && this.props.mode == "comp" ? BDFDB.ColorUtils.convert(this.props.value.split(","), "RGB") : this.props.value,
									onColorChange: color => this.handleChange.apply(this, [!color ? "" : (this.props.mode == "comp" ? BDFDB.ColorUtils.convert(color, "RGBCOMP").slice(0, 3).join(",") : BDFDB.ColorUtils.convert(color, this.props.noAlpha ? "RGB" : "RGBA"))]),
									pickerOpen: this.props.colorPickerOpen,
									onPickerOpen: _ => this.props.colorPickerOpen = true,
									onPickerClose: _ => delete this.props.colorPickerOpen,
									ref: this.props.controlsRef,
									pickerConfig: {gradient: false, alpha: this.props.mode != "comp" && !this.props.noAlpha}
								})
							}) : null,
							this.props.type == "file" ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.FileButton, {
								filter: this.props.filter,
								mode: this.props.mode,
								ref: this.props.controlsRef
							}) : null
						].flat(10).filter(n => n);
						
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.inputwrapper, this.props.type == "number" && (this.props.size && Internal.LibraryComponents.TextInput.Sizes[this.props.size.toUpperCase()] && BDFDB.disCN["inputnumberwrapper" + this.props.size.toLowerCase()] || BDFDB.disCN.inputnumberwrapperdefault), this.props.className),
							style: this.props.style,
							children: [
								this.props.type == "number" ? BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.inputnumberbuttons,
									children: [
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.inputnumberbuttonup,
											onClick: e => {
												let min = parseInt(this.props.min);
												let max = parseInt(this.props.max);
												let newV = parseInt(this.props.value) + 1 || min || 0;
												if (isNaN(max) || !isNaN(max) && newV <= max) this.handleNumberButton.bind(this)(e._targetInst, isNaN(min) || !isNaN(min) && newV >= min ? newV : min);
											}
										}),
										BDFDB.ReactUtils.createElement("div", {
											className: BDFDB.disCN.inputnumberbuttondown,
											onClick: e => {
												let min = parseInt(this.props.min);
												let max = parseInt(this.props.max);
												let newV = parseInt(this.props.value) - 1 || min || 0;
												if (isNaN(min) || !isNaN(min) && newV >= min) this.handleNumberButton.bind(this)(e._targetInst, isNaN(max) || !isNaN(max) && newV <= max ? newV : max);
											}
										})
									]
								}) : null,
								inputChildren.length == 1 ? inputChildren[0] : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex, {
									wrap: Internal.LibraryComponents.Flex.Wrap.NO_WRAP,
									align: Internal.LibraryComponents.Flex.Align.CENTER,
									children: inputChildren.map((child, i) => i != 0 ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Flex.Child, {
										shrink: 0,
										children: child
									}) : child)
								}),
								this.props.errorMessage ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TextElement, {
									className: BDFDB.disCN.margintop8,
									size: Internal.LibraryComponents.TextElement.Sizes.SIZE_12,
									color: Internal.LibraryComponents.TextElement.Colors.STATUS_RED,
									children: this.props.errorMessage
								}) : null
							].filter(n => n)
						});
					}
				};
				CustomComponents.TextInput.Sizes = {
					MINI: BDFDB.disCN.inputmini
				};
				
				CustomComponents.TextScroller = reactInitialized && class BDFDB_TextScroller extends Internal.LibraryModules.React.Component {
					render() {
						let scrolling, scroll = _ => {};
						return BDFDB.ReactUtils.createElement("div", {
							className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textscroller, this.props.className),
							style: Object.assign({}, this.props.style, {
								position: "relative",
								display: "block",
								overflow: "hidden"
							}),
							ref: instance => {
								const ele = BDFDB.ReactUtils.findDOMNode(instance);
								if (ele && ele.parentElement) {
									BDFDB.DOMUtils.hide(ele);
									const maxWidth = BDFDB.DOMUtils.getInnerWidth(ele.parentElement);
									if (maxWidth > 50) ele.style.setProperty("max-width", `${maxWidth}px`);
									BDFDB.DOMUtils.show(ele);
									if (!this.props.initiated) BDFDB.TimeUtils.timeout(_ => {
										this.props.initiated = true;
										if (document.contains(ele.parentElement)) BDFDB.ReactUtils.forceUpdate(this);
									}, 3000);
									const Animation = new Internal.LibraryModules.AnimationUtils.Value(0);
									Animation.interpolate({inputRange: [0, 1], outputRange: [0, (BDFDB.DOMUtils.getRects(ele.firstElementChild).width - BDFDB.DOMUtils.getRects(ele).width) * -1]}).addListener(v => {
										ele.firstElementChild.style.setProperty("display", v.value == 0 ? "inline" : "block", "important");
										ele.firstElementChild.style.setProperty("left", `${v.value}px`, "important");
									});
									scroll = p => {
										const display = ele.firstElementChild.style.getPropertyValue("display");
										ele.firstElementChild.style.setProperty("display", "inline", "important");
										const innerWidth = BDFDB.DOMUtils.getRects(ele.firstElementChild).width;
										const outerWidth = BDFDB.DOMUtils.getRects(ele).width;
										ele.firstElementChild.style.setProperty("display", display, "important");
										
										let w = p + parseFloat(ele.firstElementChild.style.getPropertyValue("left")) / (innerWidth - outerWidth);
										w = isNaN(w) || !isFinite(w) ? p : w;
										w *= innerWidth / (outerWidth * 2);
										Internal.LibraryModules.AnimationUtils.parallel([Internal.LibraryModules.AnimationUtils.timing(Animation, {toValue: p, duration: Math.sqrt(w**2) * 4000 / (parseInt(this.props.speed) || 1)})]).start();
									};
								}
							},
							onClick: e => {
								if (typeof this.props.onClick == "function") this.props.onClick(e, this);
							},
							onMouseEnter: e => {
								let target = e.currentTarget || e.target;
								if (BDFDB.DOMUtils.getRects(target).width < BDFDB.DOMUtils.getRects(target.firstElementChild).width || target.firstElementChild.style.getPropertyValue("display") != "inline") {
									scrolling = true;
									scroll(1);
								}
							},
							onMouseLeave: e => {
								if (scrolling) {
									scrolling = false;
									scroll(0);
								}
							},
							children: BDFDB.ReactUtils.createElement("div", {
								style: {
									left: "0",
									position: "relative",
									display: "inline",
									whiteSpace: "nowrap"
								},
								children: this.props.children
							})
						});
					}
				};
				CustomComponents.TooltipContainer = reactInitialized && class BDFDB_TooltipContainer extends Internal.LibraryModules.React.Component {
					updateTooltip(text) {
						if (this.tooltip) this.tooltip.update(text);
					}
					render() {
						let child = (typeof this.props.children == "function" ? this.props.children() : (BDFDB.ArrayUtils.is(this.props.children) ? this.props.children[0] : this.props.children)) || BDFDB.ReactUtils.createElement("div", {});
						if (!child || !child.props) return null;
						child.props.className = BDFDB.DOMUtils.formatClassName(child.props.className, this.props.className);
						let childProps = Object.assign({}, child.props);
						let shown = false;
						child.props.onMouseEnter = (e, childThis) => {
							let target = e.currentTarget || e.target;
							if (!shown && !target.__BDFDBtooltipShown && !(this.props.onlyShowOnShift && !e.shiftKey) && !(this.props.onlyShowOnCtrl && !e.ctrlKey)) {
								target.__BDFDBtooltipShown = shown = true;
								this.tooltip = BDFDB.TooltipUtils.create(target, typeof this.props.text == "function" ? this.props.text(this, e) : this.props.text, Object.assign({
									note: this.props.note,
									delay: this.props.delay
								}, this.props.tooltipConfig, {
									onHide: (tooltip, anker) => {
										delete anker.__BDFDBtooltipShown;
										shown = false;
										if (this.props.tooltipConfig && typeof this.props.tooltipConfig.onHide == "function") this.props.tooltipConfig.onHide(tooltip, anker);
									}
								}));
								if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);
								if (typeof childProps.onMouseEnter == "function") childProps.onMouseEnter(e, childThis);
							}
						};
						child.props.onMouseLeave = (e, childThis) => {
							if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);
							if (typeof childProps.onMouseLeave == "function") childProps.onMouseLeave(e, childThis);
						};
						child.props.onClick = (e, childThis) => {
							if (typeof this.props.onClick == "function") this.props.onClick(e, this);
							if (typeof childProps.onClick == "function") childProps.onClick(e, childThis);
							if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e));
						};
						child.props.onContextMenu = (e, childThis) => {
							if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);
							if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis);
							if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e));
						};
						return BDFDB.ReactUtils.createElement(Internal.LibraryModules.React.Fragment, {
							children: child
						});
					}
				};
				if (CustomComponents.TooltipContainer) CustomComponents.TooltipContainer.Positions = {
					BOTTOM: "bottom",
					CENTER: "center",
					LEFT: "left",
					RIGHT: "right",
					TOP: "top",
					WINDOW_CENTER: "window_center"
				};
				
				CustomComponents.UserPopoutContainer = reactInitialized && class BDFDB_UserPopoutContainer extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(Internal.LibraryComponents.PopoutContainer, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
							wrap: false,
							renderPopout: instance => BDFDB.ReactUtils.createElement(Internal.LibraryComponents.UserPopout, {
								user: Internal.LibraryStores.UserStore.getUser(this.props.userId),
								currentUser: Internal.LibraryStores.UserStore.getUser(BDFDB.UserUtils.me.id),
								userId: this.props.userId,
								channelId: this.props.channelId,
								guildId: this.props.guildId
							}),
						}), "userId", "channelId", "guildId"));
					}
				};
				
				CustomComponents.UserMention = reactInitialized && class BDFDB_UserMention extends Internal.LibraryModules.React.Component {
					render() {
						let user = this.props.user || Internal.LibraryStores.UserStore.getUser(this.props.userId);
						let channel = Internal.LibraryStores.ChannelStore.getChannel(this.props.channelId);
						let guildId = this.props.guildId || channel && channel.guild_id;
						let mention = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							className: this.props.className,
							onContextMenu: event => BDFDB.UserUtils.openMenu(user, guildId, channel.id, event),
							children: "@" + BDFDB.LibraryModules.UserNameUtils.getName(guildId, this.props.channelId, user)
						});
						return this.props.inlinePreview ? mention : BDFDB.ReactUtils.createElement(Internal.LibraryComponents.UserPopoutContainer, Object.assign({}, this.props, {
							position: Internal.LibraryComponents.PopoutContainer.Positions.RIGHT,
							align: Internal.LibraryComponents.PopoutContainer.Align.BOTTOM,
							children: mention
						}));
					}
				};
				
				const VideoInner = function (props) {
					let ref = BDFDB.ReactUtils.useRef(null);
					BDFDB.ReactUtils.useEffect(_ => {
						if (ref.current) props.play ? ref.current.play() : ref.current.pause();
					}, [props.play]);
					return props.ignoreMaxSize || props.naturalWidth <= Internal.DiscordConstants.MAX_VIDEO_WIDTH && props.naturalHeight <= Internal.DiscordConstants.MAX_VIDEO_HEIGHT || props.naturalWidth <= Internal.DiscordConstants.MAX_VIDEO_HEIGHT && props.naturalHeight <= Internal.DiscordConstants.MAX_VIDEO_WIDTH ? BDFDB.ReactUtils.createElement(Internal.LibraryComponents.VideoForwardRef, {
						ref: ref,
						className: props.className,
						poster: props.poster,
						src: props.src,
						width: props.width,
						height: props.height,
						muted: true,
						loop: true,
						autoPlay: props.play,
						playOnHover: props.playOnHover,
						preload: "none"
					}) : BDFDB.ReactUtils.createElement("img", {
						alt: "",
						src: props.poster,
						width: props.width,
						height: props.height
					});
				};
				CustomComponents.Video = reactInitialized && class BDFDB_Video extends Internal.LibraryModules.React.Component {
					render() {
						return BDFDB.ReactUtils.createElement(VideoInner, this.props);
					}
				};
				
				Internal.LibraryComponents = new Proxy(LibraryComponents, {
					get: function (_, item) {
						if (LibraryComponents[item]) return LibraryComponents[item];
						if (!InternalData.LibraryComponents[item] && !CustomComponents[item]) return "div";
						
						Internal.findModuleViaData(LibraryComponents, InternalData.LibraryComponents, item);
						
						if (CustomComponents[item]) LibraryComponents[item] = LibraryComponents[item] ? Object.assign({}, LibraryComponents[item], CustomComponents[item]) : CustomComponents[item];
						
						if (LibraryComponents[item] && typeof LibraryComponents[item] == "object" && LibraryComponents[item].Z && LibraryComponents[item].Z["$$typeof"]) LibraryComponents[item] = LibraryComponents[item].Z;
						else if (LibraryComponents[item] && typeof LibraryComponents[item] == "object" && LibraryComponents[item].A && LibraryComponents[item].A["$$typeof"]) LibraryComponents[item] = LibraryComponents[item].A;
						
						const NativeComponent = LibraryComponents[item] && Internal.NativeSubComponents[item];
						if (NativeComponent && typeof NativeComponent != "string") {
							for (let key in NativeComponent) if (key != "displayName" && key != "name" && (typeof NativeComponent[key] != "function" || key.charAt(0) == key.charAt(0).toUpperCase())) {
								if (key == "defaultProps") LibraryComponents[item][key] = Object.assign({}, LibraryComponents[item][key], NativeComponent[key]);
								else if (!LibraryComponents[item][key]) LibraryComponents[item][key] = NativeComponent[key];
							}
							if (LibraryComponents[item].ObjectProperties) for (let key of LibraryComponents[item].ObjectProperties) if (!LibraryComponents[item][key]) LibraryComponents[item][key] = {};
						}
						return LibraryComponents[item] ? LibraryComponents[item] : "div";
					}
				});
				
				const RealFilteredMenuItems = Object.keys(RealMenuItems).filter(type => typeof RealMenuItems[type] == "function" && RealMenuItems[type].toString().replace(/[\n\t\r]/g, "").endsWith("{return null}"));
				for (let type of RealFilteredMenuItems) {
					let children = BDFDB.ObjectUtils.get(BDFDB.ReactUtils.hookCall(Internal.LibraryComponents.Menu, {hideScroller: true, children: BDFDB.ReactUtils.createElement(RealMenuItems[type], {})}, true), "props.children.props.children.props.children");
					let menuItem = (BDFDB.ArrayUtils.is(children) ? children : []).flat(10).filter(n => n)[0];
					if (menuItem) {
						let menuItemsProps = BDFDB.ReactUtils.findValue(menuItem, "menuItemProps");
						if (menuItemsProps && menuItemsProps.id == "undefined-empty") MappedMenuItems.MenuGroup = type;
						else if (menuItemsProps && menuItemsProps.role) {
							switch (menuItemsProps.role) {
								case "menuitemcheckbox": MappedMenuItems.MenuCheckboxItem = type; break;
								case "menuitemradio": MappedMenuItems.MenuRadioItem = type; break;
								case "menuitem": {
									if (Object.keys(menuItem.props).includes("children")) MappedMenuItems.MenuControlItem = type;
									else if (Object.keys(menuItem.props).includes("hasSubmenu")) MappedMenuItems.MenuItem = type;
									break;
								}
							}
						}
						else {
							let key = BDFDB.ReactUtils.findValue(menuItem, "key");
							if (typeof key == "string" && key.startsWith("separator")) MappedMenuItems.MenuSeparator = type;
						}
					}
				}
				LibraryComponents.MenuItems = new Proxy(RealFilteredMenuItems.reduce((a, v) => ({ ...a, [v]: v}), {}) , {
					get: function (_, item) {
						if (CustomComponents.MenuItems[item]) return CustomComponents.MenuItems[item];
						if (RealMenuItems[item]) return RealMenuItems[item];
						if (MappedMenuItems[item] && RealMenuItems[MappedMenuItems[item]]) return RealMenuItems[MappedMenuItems[item]];
						return null;
					}
				});
				
				BDFDB.LibraryComponents = Internal.LibraryComponents;

				const keyDownTimeouts = {};
				let unfocusedWindow = false;
				BDFDB.ListenerUtils.add(BDFDB, document, "keydown.BDFDBPressedKeys", e => {
					if (!pressedKeys.includes(e.which)) {
						BDFDB.TimeUtils.clear(keyDownTimeouts[e.which]);
						pressedKeys.push(e.which);
						keyDownTimeouts[e.which] = BDFDB.TimeUtils.timeout(_ => {
							BDFDB.ArrayUtils.remove(pressedKeys, e.which, true);
						}, 60000);
					}
				});
				BDFDB.ListenerUtils.add(BDFDB, document, "keyup.BDFDBPressedKeys", e => {
					BDFDB.TimeUtils.clear(keyDownTimeouts[e.which]);
					BDFDB.ArrayUtils.remove(pressedKeys, e.which, true);
				});
				BDFDB.ListenerUtils.add(BDFDB, window, "focus.BDFDBPressedKeysReset", e => {
					if (unfocusedWindow) {
						pressedKeys = [];
						unfocusedWindow = false;
					}
				});
				BDFDB.ListenerUtils.add(BDFDB, window, "blur.BDFDBPressedKeysReset", e => {
					if (!document.querySelector(":hover")) unfocusedWindow = true;
				});
				BDFDB.ListenerUtils.add(BDFDB, document, "mousedown.BDFDBMousePosition", e => {
					mousePosition = e;
				});
				
				Internal.modulePatches = {
					before: [
						"EmojiPickerListRow",
						"Menu",
						"MessageHeader",
						"SearchBar"
					],
					after: [
						"DiscordTag",
						"NameContainerAvatar",
						"UserPanelHeader",
						"UserProfileHeader"
					],
					componentDidMount: [
						"Account",
						"AnalyticsContext"
					],
					componentDidUpdate: [
						"Account",
						"AnalyticsContext"
					]
				};

				const BDFDB_Patrons = Object.assign({}, InternalData.BDFDB_Patrons), BDFDB_Patron_Tiers = Object.assign({}, InternalData.BDFDB_Patron_Tiers);
				Internal._processAvatarMount = function (user, avatar, wrapper) {
					if (!user) return;
					if (Node.prototype.isPrototypeOf(avatar) && (avatar.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) {
						let role = "", note = "", color, link, addBadge = Internal.settings.general.showSupportBadges;
						if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) {
							link = "https://www.patreon.com/MircoWittrien";
							role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text;
							note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text;
							color = BDFDB_Patrons[user.id].color;
							avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]);
						}
						else if (user.id == InternalData.myId) {
							addBadge = true;
							role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`;
							avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev);
						}
						if (addBadge && role && !avatar.querySelector(BDFDB.dotCN.bdfdbbadge)) {
							let badge = document.createElement("div");
							badge.className = BDFDB.disCN.bdfdbbadge;
							badge.setAttribute("user-id", user.id);
							if (link) badge.addEventListener("click", _ => BDFDB.DiscordUtils.openLink(link));
							badge.addEventListener("mouseenter", _ => BDFDB.TooltipUtils.create(badge, role, {position: "top", note: note, backgroundColor: color || ""}));
							avatar.appendChild(badge);
						}
					}
				};
				Internal._processAvatarRender = function (user, avatar, className = "") {
					if (BDFDB.ReactUtils.isValidElement(avatar) && BDFDB.ObjectUtils.is(user) && (avatar.props.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) {
						let role = "", note = "", color, link, addBadge = Internal.settings.general.showSupportBadges;
						if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) {
							link = "https://www.patreon.com/MircoWittrien";
							role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text;
							note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text;
							color = BDFDB_Patrons[user.id].color;
							className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]);
						}
						else if (user.id == InternalData.myId) {
							addBadge = true;
							role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`;
							className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev);
						}
						if (role) {
							if (avatar.type == "img") avatar = BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Avatars.Avatar, Object.assign({}, avatar.props, {
								size: Internal.LibraryComponents.AvatarConstants.AvatarSizes.SIZE_40
							}));
							delete avatar.props.className;
							let newProps = {
								className: className,
								children: [avatar]
							};
							avatar = BDFDB.ReactUtils.createElement("div", newProps);
							if (addBadge) avatar.props.children.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.TooltipContainer, {
								text: role,
								note: note,
								tooltipConfig: {backgroundColor: color || ""},
								onClick: link ? (_ => BDFDB.DiscordUtils.openLink(link)) : (_ => {}),
								children: BDFDB.ReactUtils.createElement("div", {
									className: BDFDB.disCN.bdfdbbadge,
									"user-id": user.id
								})
							}));
							return avatar;
						}
					}
				};
				
				Internal.processAccount = function (e) {
					Internal._processAvatarMount(e.instance.props.currentUser, e.node.querySelector(BDFDB.dotCN.avatarwrapper), e.node);
				};
				Internal.processAnalyticsContext = function (e) {
					if (e.instance.props.section != Internal.DiscordConstants.AnalyticsSections.PROFILE_MODAL && e.instance.props.section != Internal.DiscordConstants.AnalyticsSections.PROFILE_POPOUT) return;
					const user = BDFDB.ReactUtils.findValue(e.instance, "user");
					if (!user) return;
					const avatar = e.instance.props.section != Internal.DiscordConstants.AnalyticsSections.PROFILE_POPOUT && e.node.querySelector(BDFDB.dotCN.avatarwrapper);
					const wrapper = e.node.querySelector(BDFDB.dotCNC.userpopoutouter + BDFDB.dotCN.userprofilemodal) || e.node;
					if (avatar) Internal._processAvatarMount(user, avatar, wrapper);
				};
				Internal.processDiscordTag = function (e) {
					if (e.instance && e.instance.props && e.returnvalue && e.instance.props.user) e.returnvalue.props.user = e.instance.props.user;
				};
				Internal.processEmojiPickerListRow = function (e) {
					if (e.instance.props.emojiDescriptors && Internal.LibraryComponents.EmojiPickerButton.current && Internal.LibraryComponents.EmojiPickerButton.current.props && Internal.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) for (let i in e.instance.props.emojiDescriptors) e.instance.props.emojiDescriptors[i] = Object.assign({}, e.instance.props.emojiDescriptors[i], {isDisabled: false});
				};
				Internal.processNameContainerAvatar = function (e) {
					if (e.returnvalue && Array.isArray(e.returnvalue.props.children) && e.returnvalue.props.children[0]) e.returnvalue.props.children[0] = Internal._processAvatarRender(e.instance.props.user, e.returnvalue.props.children[0]) || e.returnvalue.props.children[0];
				};
				Internal.processMenu = function (e) {
					if (e.instance.props && (e.instance.props.children || BDFDB.ArrayUtils.is(e.instance.props.children) && e.instance.props.children.length)) {
						let patchCancel = BDFDB.PatchUtils.patch(BDFDB, Internal.LibraryModules.ContextMenuUtils, "closeContextMenu", {instead: e => {}});
						BDFDB.TimeUtils.timeout(_ => patchCancel());
					}
					if (e.instance.props && e.instance.props.navId == "message-actions" && !e.instance.props.BDFDBpatched) {
						e.instance.props.BDFDBpatched = true;
						let copyChild = BDFDB.ReactUtils.findChild(e.instance, {filter: n => n && n.props && n.props.id == "copy-link"});
						if (!copyChild) return;
						let link = "";
						BDFDB.PatchUtils.patch(BDFDB, BDFDB.LibraryModules.ClipboardUtils, "copy", {instead: e => {link = e.methodArguments[0];}}, {once: true});
						copyChild.props.action();
						if (!link) return;
						let guildId = link.split("/channels/")[1].split("/")[0];
						let channelId = link.split(`/channels/${guildId}/`)[1].split("/")[0];
						let messageId = link.split(`/channels/${guildId}/${channelId}/`)[1].split("/")[0];
						if (!guildId || !channelId || !messageId) return;
						LibraryModules.MessageToolbarUtils.useMessageMenu({
							guild: Internal.LibraryStores.GuildStore.getGuild(guildId),
							channel: Internal.LibraryStores.ChannelStore.getChannel(channelId),
							message: Internal.LibraryStores.MessageStore.getMessage(channelId, messageId)
						}, e.instance);
					}
				};
				Internal.processMessageHeader = function (e) {
					if (e.instance.props.message && e.instance.props.message.author) {
						if (e.instance.props.avatar && e.instance.props.avatar.props) {
							let child = BDFDB.ReactUtils.findChild(e.instance.props.avatar, {filter: n => n && n.props && typeof n.props.children == "function"});
							let renderChildren = child.props.children;
							if (renderChildren) child.props.children = BDFDB.TimeUtils.suppress((...args) => {
								let renderedChildren = renderChildren(...args);
								return Internal._processAvatarRender(e.instance.props.message.author, renderedChildren, BDFDB.disCN.messageavatar) || renderedChildren;
							}, "Error in Avatar Render of MessageHeader!");
						}
					}
				};
				Internal.processSearchBar = function (e) {
					if (typeof e.instance.props.query != "string") e.instance.props.query = "";
				};
				Internal.processUserPanelHeader = function (e) {
					if (!e.instance.props.user) return;
					let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {filter: n => n && n.props && n.props.src && n.props.size});
					if (index > -1) children[index] = Internal._processAvatarRender(e.instance.props.user, children[index]) || children[index];
				};
				Internal.processUserProfileHeader = function (e) {
					if (!e.instance.props.user) return;
					let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {filter: n => n && n.props && n.props.src && n.props.size});
					if (index > -1) children[index] = Internal._processAvatarRender(e.instance.props.user, children[index]) || children[index];
				};
				
				MyReact.instanceKey = Object.keys(document.querySelector(BDFDB.dotCN.app) || {}).some(n => n.startsWith("__reactInternalInstance")) ? "_reactInternalFiber" : "_reactInternals";

				BDFDB.PluginUtils.load(BDFDB);
				Internal.settings = BDFDB.DataUtils.get(Internal);
				changeLogs = BDFDB.DataUtils.load(BDFDB, "changeLogs");
				BDFDB.PluginUtils.checkChangeLog(BDFDB);
				
				BDFDB.PatchUtils.unpatch(BDFDB);
				Internal.addModulePatches(BDFDB);
				Internal.addContextPatches(BDFDB);
				
				const possibleRenderPaths = ["render", "type", "type.render"];
				const createElementPatches = {
					before: e => {
						if (!e.methodArguments[0] || typeof e.methodArguments[0] == "string") return;
						let renderFunction = null;
						if (typeof e.methodArguments[0] == "function") renderFunction = e.methodArguments[0];
						else for (const path of possibleRenderPaths) {
							const possibleRenderFuncion = BDFDB.ObjectUtils.get(e.methodArguments[0], path);
							if (typeof possibleRenderFuncion == "function") {
								renderFunction = possibleRenderFuncion;
								break;
							}
						}
						if (!renderFunction || typeof renderFunction != "function") return;
						if (PluginStores.modulePatches.before) for (const type in PluginStores.modulePatches.before) if (Internal.isCorrectModule(renderFunction, type, true)) {
							let hasArgumentChildren = false, children = [...e.methodArguments].slice(2);
							if (children.length && e.methodArguments[1].children === undefined) {
								hasArgumentChildren = true;
								e.methodArguments[1].children = children;
							}
							for (let plugin of PluginStores.modulePatches.before[type].flat(10)) Internal.initiatePatch(plugin, type, {
								arguments: e.methodArguments,
								instance: {props: e.methodArguments[1]},
								returnvalue: e.returnValue,
								component: e.methodArguments[0],
								name: type,
								methodname: "render",
								patchtypes: ["before"]
							});
							if (hasArgumentChildren) {
								[].splice.call(e.methodArguments, 2);
								for (let child of e.methodArguments[1].children) [].push.call(e.methodArguments, child);
								delete e.methodArguments[1].children;
							}
							break;
						}
						if (PluginStores.modulePatches.after) {
							let patchFunction = "", parentModule = e.methodArguments[0];
							if (parentModule.prototype && typeof parentModule.prototype.render == "function") parentModule = parentModule.prototype, patchFunction = "render";
							else if (typeof parentModule.render == "function") patchFunction = "render";
							else if (typeof parentModule.type == "function") patchFunction = "type";
							else if (parentModule.type && typeof parentModule.type.render == "function") parentModule = parentModule.type, patchFunction = "render";
							if (patchFunction) for (const type in PluginStores.modulePatches.after) if (Internal.isCorrectModule(renderFunction, type, true)) {
								for (let plugin of PluginStores.modulePatches.after[type].flat(10)) if (!BDFDB.PatchUtils.isPatched(plugin, parentModule, patchFunction)) {
									BDFDB.PatchUtils.patch(plugin, parentModule, patchFunction, {after: e2 => {
										Internal.initiatePatch(plugin, type, {
											arguments: e2.methodArguments,
											instance: e2.instance,
											returnvalue: e2.returnValue,
											component: e.methodArguments[0],
											name: type,
											methodname: patchFunction,
											patchtypes: ["after"]
										});
									}}, {name: type});
								}
								break;
							}
						}
						if (e.methodArguments[0].prototype) for (let patchType of ["componentDidMount", "componentDidUpdate", "componentWillUnmount"]) {
							if (PluginStores.modulePatches[patchType]) for (const type in PluginStores.modulePatches[patchType]) if (Internal.isCorrectModule(renderFunction, type, true)) {
								for (let plugin of PluginStores.modulePatches[patchType][type].flat(10)) if (!BDFDB.PatchUtils.isPatched(plugin, e.methodArguments[0].prototype, patchType)) {
									BDFDB.PatchUtils.patch(plugin, e.methodArguments[0].prototype, patchType, {after: e2 => Internal.initiatePatch(plugin, type, {
										arguments: e2.methodArguments,
										instance: e2.instance,
										returnvalue: e2.returnValue,
										component: e.methodArguments[0],
										name: type,
										methodname: patchType,
										patchtypes: ["after"]
									})}, {name: type});
								}
								break;
							}
						}
					},
					after: e => {
						if (!e.methodArguments[0] || typeof e.methodArguments[0] != "function" || (e.methodArguments[0].prototype && typeof e.methodArguments[0].prototype.render == "function") || !PluginStores.modulePatches.after) return;
						else for (const type in PluginStores.modulePatches.after) if (Internal.isCorrectModule(e.methodArguments[0], type, true) && !Internal.isCorrectModuleButDontPatch(type)) {
							for (let plugin of PluginStores.modulePatches.after[type].flat(10)) BDFDB.PatchUtils.patch(plugin, e.returnValue, "type", {after: e2 => Internal.initiatePatch(plugin, type, {
								arguments: e2.methodArguments,
								instance: e2.instance,
								returnvalue: e2.returnValue,
								component: e.methodArguments[0],
								name: type,
								methodname: "type",
								patchtypes: ["after"]
							})}, {name: type, noCache: true});
							break;
						}
					}
				};
				BDFDB.PatchUtils.patch(BDFDB, LibraryModules.React, "createElement", createElementPatches);
				if (Internal.LibraryModules.InternalReactUtils) for (let key in Internal.LibraryModules.InternalReactUtils) if (typeof Internal.LibraryModules.InternalReactUtils[key] == "function" && Internal.LibraryModules.InternalReactUtils[key].toString().indexOf("return{$$typeof:") > -1) BDFDB.PatchUtils.patch(BDFDB, Internal.LibraryModules.InternalReactUtils, key, createElementPatches, {ignoreErrors: true});
				
				let languageChangeTimeout;
				BDFDB.PatchUtils.patch(BDFDB, Internal.LibraryModules.AppearanceSettingsUtils, "updateLocale", {after: e => {
					BDFDB.TimeUtils.clear(languageChangeTimeout);
					languageChangeTimeout = BDFDB.TimeUtils.timeout(_ => {
						for (let pluginName in PluginStores.loaded) if (PluginStores.loaded[pluginName].started) BDFDB.PluginUtils.translate(PluginStores.loaded[pluginName]);
					}, 10000);
				}});
				
				Internal.onSettingsClosed = function () {
					if (Internal.SettingsUpdated) {
						delete Internal.SettingsUpdated;
						Internal.forceUpdateAll();
					}
				};
				
				Internal.forceUpdateAll = function () {					
					BDFDB.MessageUtils.rerenderAll();
					BDFDB.PatchUtils.forceAllUpdates(BDFDB);
				};
				
				BDFDB.PatchUtils.patch(BDFDB, Internal.LibraryModules.EmojiStateUtils, "getEmojiUnavailableReason", {after: e => {
					if (Internal.LibraryComponents.EmojiPickerButton.current && Internal.LibraryComponents.EmojiPickerButton.current.props && Internal.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) return null;
				}});
				
				Internal.forceUpdateAll();
			
				const pluginQueue = window.BDFDB_Global && BDFDB.ArrayUtils.is(window.BDFDB_Global.pluginQueue) ? window.BDFDB_Global.pluginQueue : [];

				if (BDFDB.UserUtils.me.id == InternalData.myId || BDFDB.UserUtils.me.id == "350635509275557888") {
					BDFDB.DevUtils = {};
					BDFDB.DevUtils.generateClassId = Internal.generateClassId;
					BDFDB.DevUtils.findByIndex = function (index) {
						return BDFDB.DevUtils.req.c[index];
					};
					BDFDB.DevUtils.findPropAny = function (...strings) {
						window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j)) window.t[j + "_" + i] = m;
							if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j)) window.t[j + "_default_" + i] = m.default;
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.findPropFunc = function (...strings) {
						window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j) && typeof m[j] != "string") window.t[j + "_" + i] = m;
							if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j) && typeof m.default[j] != "string") window.t[j + "_default_" + i] = m.default;
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.findPropStringLib = function (...strings) {
						window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j) && typeof m[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m[j])) window.t[j + "_" + i] = m;
							if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j) && typeof m.default[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m.default[j])) window.t[j + "_default_" + i] = m.default;
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.findNameAny = function (...strings) {
						window.t = {"$filter":(m => [...strings].flat(10).filter(n => typeof n == "string").some(string => typeof m.displayName == "string" && m.displayName.toLowerCase().indexOf(string.toLowerCase()) > -1 || m.name == "string" && m.name.toLowerCase().indexOf(string.toLowerCase()) > -1))};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && (typeof m == "object" || typeof m == "function") && window.t.$filter(m)) window.t[(m.displayName || m.name) + "_" + i] = m;
							if (m && (typeof m == "object" || typeof m == "function") && m.default && (typeof m.default == "object" || typeof m.default == "function") && window.t.$filter(m.default)) window.t[(m.default.displayName || m.default.name) + "_" + i] = m.default;
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.findCodeAny = function (...strings) {
						window.t = {"$filter":(m => Internal.checkModuleStrings(m, strings, {ignoreCase: true}))};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "function" && window.t.$filter(m)) window.t["module_" + i] = {string: m.toString(), func: m};
							if (m && m.__esModule) {
								for (let j in m) if (m[j] && typeof m[j] == "function" && window.t.$filter(m[j])) window.t[j + "_module_" + i] = {string: m[j].toString(), func: m[j], module: m};
								if (m.default && (typeof m.default == "object" || typeof m.default == "function")) for (let j in m.default) if (m.default[j] && typeof m.default[j] == "function" && window.t.$filter(m.default[j])) window.t[j + "_module_" + i + "_default"] = {string: m.default[j].toString(), func: m.default[j], module: m};
							}
						}
						for (let i in BDFDB.DevUtils.req.m) if (typeof BDFDB.DevUtils.req.m[i] == "function" && window.t.$filter(BDFDB.DevUtils.req.m[i])) window.t["function_" + i] = {string: BDFDB.DevUtils.req.m[i].toString(), func: BDFDB.DevUtils.req.m[i]};
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.getAllModules = function () {
						window.t = {};
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "object") window.t[i] = m;
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.getAllStringLibs = function () {
						window.t = [];
						for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) {
							let m = BDFDB.DevUtils.req.c[i].exports;
							if (m && typeof m == "object" && !BDFDB.ArrayUtils.is(m) && Object.keys(m).length) {
								var string = true, stringlib = false;
								for (let j in m) {
									if (typeof m[j] != "string") string = false;
									if (typeof m[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m[j])) stringlib = true;
								}
								if (string && stringlib) window.t.push(m);
							}
							if (m && typeof m == "object" && m.default && typeof m.default == "object" && !BDFDB.ArrayUtils.is(m.default) && Object.keys(m.default).length) {
								var string = true, stringlib = false;
								for (let j in m.default) {
									if (typeof m.default[j] != "string") string = false;
									if (typeof m.default[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m.default[j])) stringlib = true;
								}
								if (string && stringlib) window.t.push(m.default);
							}
						}
						console.clear();
						console.log(window.t);
					};
					BDFDB.DevUtils.listen = function (strings) {
						strings = BDFDB.ArrayUtils.is(strings) ? strings : Array.from(arguments);
						BDFDB.DevUtils.listenStop();
						BDFDB.DevUtils.listen.p = BDFDB.PatchUtils.patch("WebpackSearch", BDFDB.ModuleUtils.findByProperties(strings), strings[0], {after: e => {
							console.log(e);
						}});
					};
					BDFDB.DevUtils.listenStop = function () {
						if (typeof BDFDB.DevUtils.listen.p == "function") BDFDB.DevUtils.listen.p();
					};
					BDFDB.DevUtils.generateLanguageStrings = function (strings, config = {}) {
						const language = config.language || "en";
						const languages = BDFDB.ArrayUtils.removeCopies(BDFDB.ArrayUtils.is(config.languages) ? config.languages : ["en"].concat((BDFDB.ModuleUtils.findByProperties("getLanguages").getLanguages()).filter(n => n.enabled).map(n => {
							if (BDFDB.LanguageUtils.languages[n.code]) return n.code;
							else {
								const code = n.code.split("-")[0];
								if (BDFDB.LanguageUtils.languages[code]) return code;
							}
						})).filter(n => n && !n.startsWith("en-") && !n.startsWith("$") && n != language)).sort();
						let translations = {};
						strings = BDFDB.ObjectUtils.sort(strings);
						const stringKeys = Object.keys(strings);
						translations[language] = BDFDB.ObjectUtils.toArray(strings);
						let text = Object.keys(translations[language]).map(k => translations[language][k]).join("\n\n");
						
						let fails = 0, next = lang => {
							if (!lang) {
								let formatTranslation = (l, s, i) => {
									l = l == "en" ? "default" : l;
									return config.cached && config.cached[l] && config.cached[l][stringKeys[i]] || (translations[language][i][0] == translations[language][i][0].toUpperCase() ? BDFDB.StringUtils.upperCaseFirstChar(s) : s);
								};
								let format = config.asObject ? ((l, isNotFirst) => {
									return `${isNotFirst ? "," : ""}\n\t\t"${l == "en" ? "default" : l}": {${translations[l].map((s, i) => `\n\t\t\t"${stringKeys[i]}": "${formatTranslation(l, s, i)}"`).join(",")}\n\t\t}`;
								}) : ((l, isNotFirst) => {
									return `\n\t\t\t\t\t${l == "en" ? "default" : `case "${l}"`}:"\t\t"// ${BDFDB.LanguageUtils.languages[l].name}\n\t\t\t\t\t\treturn {${translations[l].map((s, i) => `\n\t\t\t\t\t\t\t${stringKeys[i]}:${"\t".repeat(10 - ((stringKeys[i].length + 2) / 4))}"${formatTranslation(l, s, i)}"`).join(",")}\n\t\t\t\t\t\t};`;
								});
								let result = Object.keys(translations).filter(n => n != "en").sort().map((l, i) => format(l, i)).join("");
								if (translations.en) result += format("en", result ? 1 : 0);
								BDFDB.NotificationUtils.toast("Translation copied to clipboard", {
									type: "success"
								});
								BDFDB.LibraryModules.WindowUtils.copy(result);
							}
							else {
								const callback = translation => {
									BDFDB.LogUtils.log(lang);
									if (!translation) {
										console.warn("No Translation");
										fails++;
										if (fails > 10) console.error("Skipped Language");
										else languages.unshift(lang);
									}
									else {
										fails = 0;
										translations[lang] = translation.split("\n\n");
									}
									next(languages.shift());
								};
								requestFunction(`https://translate.googleapis.com/translate_a/single?client=gtx&sl=${language}&tl=${lang}&dt=t&dj=1&source=input&q=${encodeURIComponent(text)}`, (error, response, result) => {
									if (!error && result && response.statusCode == 200) {
										try {callback(JSON.parse(result).sentences.map(n => n && n.trans).filter(n => n).join(""));}
										catch (err) {callback("");}
									}
									else {
										if (response.statusCode == 429) {
											BDFDB.NotificationUtils.toast("Too many Requests", {
												type: "danger"
											});
										}
										else {
											BDFDB.NotificationUtils.toast("Failed to translate Text", {
												type: "danger"
											});
											callback("");
										}
									}
								});
							}
						};
						if (stringKeys.length) next(languages.shift());
					};
					BDFDB.DevUtils.req = Internal.getWebModuleReq();
				}
				
				if (libraryCSS) BDFDB.DOMUtils.appendLocalStyle("BDFDB", libraryCSS.replace(/[\n\t\r]/g, "").replace(/\[REPLACE_CLASS_([A-z0-9_]+?)\]/g, (a, b) => BDFDB.dotCN[b]));
			
				BDFDB.LogUtils.log("Finished loading Library");
				
				window.BDFDB_Global = Object.assign({
					started: true,
					loaded: true,
					PluginUtils: {
						buildPlugin: BDFDB.PluginUtils.buildPlugin,
						cleanUp: BDFDB.PluginUtils.cleanUp
					}
				});
				
				while (PluginStores.delayed.loads.length) PluginStores.delayed.loads.shift().load();
				while (PluginStores.delayed.starts.length) PluginStores.delayed.starts.shift().start();
				while (pluginQueue.length) {
					let pluginName = pluginQueue.shift();
					if (pluginName) BDFDB.TimeUtils.timeout(_ => BDFDB.BDUtils.reloadPlugin(pluginName));
				}
			};
			requestLibraryHashes(true);
			
			this.loaded = true;
		}
		start () {
			if (!this.loaded) this.load();
		}
		stop () {
			
		}
		
		getSettingsPanel (collapseStates = {}) {
			let settingsPanel;
			let getString = (type, key, property) => {
				return BDFDB.LanguageUtils.LibraryStringsCheck[`settings_${key}_${property}`] ? BDFDB.LanguageUtils.LibraryStringsFormat(`settings_${key}_${property}`, BDFDB.BDUtils.getSettingsProperty("name", BDFDB.BDUtils.settingsIds[key]) || BDFDB.StringUtils.upperCaseFirstChar(key.replace(/([A-Z])/g, " $1"))) : Internal.defaults[type][key][property];
			};
			return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(BDFDB, {
				collapseStates: collapseStates,
				children: _ => {
					let settingsItems = [];
					
					for (let key in Internal.settings.choices) settingsItems.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsSaveItem, {
						type: "Select",
						plugin: Internal,
						keys: ["choices", key],
						label: getString("choices", key, "description"),
						note: getString("choices", key, "note"),
						basis: "50%",
						value: Internal.settings.choices[key],
						options: Object.keys(Internal.DiscordConstants[Internal.defaults.choices[key].items] || {}).map(p => ({
							value: p,
							label: BDFDB.LanguageUtils.LibraryStrings[p] || p
						})),
						searchable: true
					}));
					for (let key in Internal.settings.general) {
						let nativeSetting = BDFDB.BDUtils.settingsIds[key] && BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds[key]);
						let disabled = typeof Internal.defaults.general[key].isDisabled == "function" && Internal.defaults.general[key].isDisabled({
							value: Internal.settings.general[key],
							nativeValue: nativeSetting
						});
						let hidden = typeof Internal.defaults.general[key].isHidden == "function" && Internal.defaults.general[key].isHidden({
							value: Internal.settings.general[key],
							nativeValue: nativeSetting
						});
						if (!hidden) settingsItems.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsSaveItem, {
							type: "Switch",
							plugin: Internal,
							disabled: disabled,
							keys: ["general", key],
							label: getString("general", key, "description"),
							note: (typeof Internal.defaults.general[key].hasNote == "function" ? Internal.defaults.general[key].hasNote({
								value: Internal.settings.general[key],
								nativeValue: nativeSetting,
								disabled: disabled
							}) : Internal.defaults.general[key].hasNote) && getString("general", key, "note"),
							value: (typeof Internal.defaults.general[key].getValue == "function" ? Internal.defaults.general[key].getValue({
								value: Internal.settings.general[key],
								nativeValue: nativeSetting,
								disabled: disabled
							}) : true) && (Internal.settings.general[key] || nativeSetting),
							onChange: typeof Internal.defaults.general[key].onChange == "function" ? Internal.defaults.general[key].onChange : (_ => {})
						}));
					}
					settingsItems.push(BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SettingsItem, {
						type: "Button",
						label: BDFDB.LanguageUtils.LibraryStrings.update_check_info,
						dividerTop: true,
						basis: "20%",
						children: BDFDB.LanguageUtils.LibraryStrings.check_for_updates,
						labelChildren: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.Clickable, {
							children: BDFDB.ReactUtils.createElement(Internal.LibraryComponents.SvgIcon, {
								name: Internal.LibraryComponents.SvgIcon.Names.QUESTIONMARK,
								width: 20,
								height: 20,
								onClick: _ => BDFDB.ModalUtils.open(Internal, {
									header: "Plugins",
									subHeader: "",
									contentClassName: BDFDB.disCN.marginbottom20,
									text: BDFDB.ObjectUtils.toArray(Object.assign({}, window.PluginUpdates && window.PluginUpdates.plugins, PluginStores.updateData.plugins)).map(p => p.name).filter(n => n).sort().join(", ")
								})
							})
						}),
						onClick: _ => {
							let toast = BDFDB.NotificationUtils.toast(`${BDFDB.LanguageUtils.LanguageStrings.CHECKING_FOR_UPDATES} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {
								type: "info",
								timeout: 0,
								ellipsis: true
							});
							BDFDB.PluginUtils.checkAllUpdates().then(outdated => {
								toast.close();
								if (outdated > 0) BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStringsFormat("update_check_complete_outdated", outdated), {
									type: "danger"
								});
								else BDFDB.NotificationUtils.toast(BDFDB.LanguageUtils.LibraryStrings.update_check_complete, {
									type: "success"
								});
							});
						}
					}));
					
					return settingsItems;
				}
			});
		}
	}
})();