/** * @name PersistSettings * @author Ahlawat * @authorId 1025214794766221384 * @version 1.3.0 * @invite SgKSKyh9gY * @description Backs up your settings and restores them in case Discord clears them after logging out or for other reasons. * @website https://tharki-god.github.io/ * @source https://github.com/Tharki-God/BetterDiscordPlugins * @updateUrl https://tharki-god.github.io/BetterDiscordPlugins/PersistSettings.plugin.js */ /* PersistSettings, a powercord/replugged plugin to make sure you never lose your favourites again! * Copyright (C) 2021 Vendicated * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Ported to BetterDiscord * Copyright 2022 Ahlawat */ /*@cc_on @if (@_jscript) var shell = WScript.CreateObject("WScript.Shell"); var fs = new ActiveXObject("Scripting.FileSystemObject"); var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins"); var pathSelf = WScript.ScriptFullName; shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30); if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) { shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40); } else if (!fs.FolderExists(pathPlugins)) { shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10); } else if (shell.Popup("Should I move myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) { fs.MoveFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf))); shell.Exec("explorer " + pathPlugins); shell.Popup("I'm installed!", 0, "Successfully installed", 0x40); } WScript.Quit(); @else@*/ module.exports = (() => { const config = { info: { name: "PersistSettings", authors: [ { name: "Ahlawat", discord_id: "1025214794766221384", github_username: "Tharki-God", }, ], version: "1.3.0", description: "Backs up your settings and restores them in case Discord clears them after logging out or for other reasons", github: "https://github.com/Tharki-God/BetterDiscordPlugins", github_raw: "https://tharki-god.github.io/BetterDiscordPlugins/PersistSettings.plugin.js", }, changelog: [ { title: "v0.0.1", items: ["Idea in mind"], }, { title: "v0.0.5", items: ["Base Model"], }, { title: "Initial Release v1.0.0", items: [ "This is the initial release of the plugin :)", "Fuck You Discord (>'-'<)", ], }, { title: "v1.0.1", items: ["Bug Fixes", "Library Handler fixed"], }, { title: "v1.2.1", items: [ "Fixed some bugs", "its recommended to delete config file and restart discord.", ], }, ], main: "PersistSettings.plugin.js", }; const RequiredLibs = [{ window: "ZeresPluginLibrary", filename: "0PluginLibrary.plugin.js", external: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js", downloadUrl: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js" }, { window: "BunnyLib", filename: "1BunnyLib.plugin.js", external: "https://github.com/Tharki-God/BetterDiscordPlugins", downloadUrl: "https://tharki-god.github.io/BetterDiscordPlugins/1BunnyLib.plugin.js" }, ]; class handleMissingLibrarys { load() { for (const Lib of RequiredLibs.filter(lib => !window.hasOwnProperty(lib.window))) BdApi.showConfirmationModal( "Library Missing", `The library plugin (${Lib.window}) needed for ${config.info.name} is missing. Please click Download Now to install it.`, { confirmText: "Download Now", cancelText: "Cancel", onConfirm: () => this.downloadLib(Lib), } ); } async downloadLib(Lib) { const fs = require("fs"); const path = require("path"); const { Plugins } = BdApi; const LibFetch = await fetch( Lib.downloadUrl ); if (!LibFetch.ok) return this.errorDownloadLib(Lib); const LibContent = await LibFetch.text(); try { await fs.writeFile( path.join(Plugins.folder, Lib.filename), LibContent, (err) => { if (err) return this.errorDownloadLib(Lib); } ); } catch (err) { return this.errorDownloadLib(Lib); } } errorDownloadZLib(Lib) { const { shell } = require("electron"); BdApi.showConfirmationModal( "Error Downloading", [ `${Lib.window} download failed. Manually install plugin library from the link below.`, ], { confirmText: "Download", cancelText: "Cancel", onConfirm: () => { shell.openExternal( Lib.external ); }, } ); } start() { } stop() { } } return RequiredLibs.some(m => !window.hasOwnProperty(m.window)) ? handleMissingLibrarys : (([Plugin, ZLibrary]) => { const { PluginUpdater, Logger, Utilities } = ZLibrary; const { LibraryModules: { Dispatcher, ExperimentsStore, NotificationStore, AccessibilityStore, KeybindStore, MediaEngineStore } } = BunnyLib.build(config); const AccessiblityEvents = Object.freeze([ "ACCESSIBILITY_SET_MESSAGE_GROUP_SPACING", "ACCESSIBILITY_SET_PREFERS_REDUCED_MOTION", "ACCESSIBILITY_DESATURATE_ROLES_TOGGLE", "ACCESSIBILITY_DARK_SIDEBAR_TOGGLE", "ACCESSIBILITY_SET_SATURATION", "ACCESSIBILITY_SET_FONT_SIZE", "ACCESSIBILITY_SET_ZOOM", ]); const VoiceEvents = Object.freeze([ "AUDIO_SET_DISPLAY_SILENCE_WARNING", "AUDIO_SET_AUTOMATIC_GAIN_CONTROL", "MEDIA_ENGINE_SET_HARDWARE_H264", "MEDIA_ENGINE_SET_VIDEO_DEVICE", "AUDIO_SET_NOISE_SUPPRESSION", "AUDIO_SET_ECHO_CANCELLATION", "MEDIA_ENGINE_SET_OPEN_H264", "MEDIA_ENGINE_SET_AEC_DUMP", "AUDIO_SET_OUTPUT_VOLUME", "AUDIO_SET_OUTPUT_DEVICE", "AUDIO_SET_INPUT_DEVICE", "AUDIO_SET_ATTENUATION", "AUDIO_SET_MODE", "AUDIO_SET_QOS", ]); const NotificationEvents = Object.freeze([ "NOTIFICATIONS_SET_DISABLE_UNREAD_BADGE", "NOTIFICATIONS_SET_PERMISSION_STATE", "NOTIFICATIONS_SET_DISABLED_SOUNDS", "NOTIFICATIONS_SET_TASKBAR_FLASH", "NOTIFICATIONS_SET_DESKTOP_TYPE", "NOTIFICATIONS_SET_TTS_TYPE", ]); const KeybindEvents = Object.freeze([ "KEYBINDS_ADD_KEYBIND", "KEYBINDS_SET_KEYBIND", "KEYBINDS_DELETE_KEYBIND", "KEYBINDS_ENABLE_ALL_KEYBINDS", ]); return class PersistSettings extends Plugin { constructor(...args) { super(...args); this.restore = this.restore.bind(this); this.backupVoice = this.backupVoice.bind(this); this.backupKeybinds = this.backupKeybinds.bind(this); this.backupSettings = this.backupSettings.bind(this); this.backupExperiments = this.backupExperiments.bind(this); this.backupAccessibility = this.backupAccessibility.bind(this); this.backupNotifications = this.backupNotifications.bind(this); } checkForUpdates() { try { PluginUpdater.checkForUpdate( config.info.name, config.info.version, config.info.github_raw ); } catch (err) { Logger.err("Plugin Updater could not be reached.", err); } } start() { this.addListeners(); } addListeners() { Dispatcher.subscribe("CONNECTION_OPEN", this.restore); Dispatcher.subscribe("USER_SETTINGS_UPDATE", this.backupSettings); Dispatcher.subscribe( "EXPERIMENT_OVERRIDE_BUCKET", this.backupExperiments ); for (const event of KeybindEvents) { Dispatcher.subscribe(event, this.backupKeybinds); } for (const event of AccessiblityEvents) { Dispatcher.subscribe(event, this.backupAccessibility); } for (const event of VoiceEvents) { Dispatcher.subscribe(event, this.backupVoice); } for (const event of NotificationEvents) { Dispatcher.subscribe(event, this.backupNotifications); } setTimeout(() => this.didRestore || this.restore(), 1000 * 10); } backupKeybinds() { const keybinds = KeybindStore.__getLocalVars().keybinds; Utilities.saveData(config.info.name, "keybinds", keybinds); } backupAccessibility() { const accessibility = AccessibilityStore.__getLocalVars().state; Utilities.saveData( config.info.name, "accessibility", accessibility ); } backupNotifications() { const notifications = NotificationStore.__getLocalVars().state; Utilities.saveData( config.info.name, "notifications", notifications ); } backupExperiments() { const experiments = ExperimentsStore.__getLocalVars()?.experimentOverrides; Utilities.saveData(config.info.name, "experiments", experiments); } backupVoice() { const voice = MediaEngineStore.__getLocalVars()?.settingsByContext.default; Utilities.saveData(config.info.name, "voice", voice); } backupSettings() { this.backupVoice(); this.backupKeybinds(); this.backupExperiments(); this.backupAccessibility(); this.backupNotifications(); } restore() { this.didRestore = true; this.restoreVoice(); this.restoreKeybinds(); this.restoreExperiments(); this.restoreAccessibility(); this.restoreNotifications(); } restoreKeybinds() { const backup = Utilities.loadData( config.info.name, "keybinds", false ); if (!backup) return void this.backupKeybinds(); const keybinds = KeybindStore.__getLocalVars().keybinds; for (const state in keybinds) { if (!backup[state]) delete keybinds[state] } for (const state in backup) { Object.defineProperty(keybinds, state, { value: backup[state], writable: true, }); } } restoreExperiments() { const backup = Utilities.loadData( config.info.name, "experiments", false ); if (!backup) return void this.backupExperiments(); const experiments = ExperimentsStore.__getLocalVars(); for (const state in experiments) { if (!backup[state]) delete experiments[state] } for (const state in backup) { Object.defineProperty(experiments, state, { value: backup[state], writable: true, }); } } restoreVoice() { const backup = Utilities.loadData(config.info.name, "voice", false); if (!backup) return void this.backupVoice(); const voice = MediaEngineStore.__getLocalVars().settingsByContext.default; for (const state in voice) { Object.defineProperty(voice, state, { value: backup[state], writable: true, }); } } restoreAccessibility() { const backup = Utilities.loadData( config.info.name, "accessibility", false ); if (!backup) return void this.backupAccessibility(); const accessibility = AccessibilityStore.__getLocalVars().state; for (const state in accessibility) { Object.defineProperty(accessibility, state, { value: backup[state], writable: true, }); } } restoreNotifications() { const backup = Utilities.loadData( config.info.name, "notifications", false ); if (!backup) return void this.backupNotifications(); const notifications = NotificationStore.__getLocalVars().state; for (const state in notifications) { Object.defineProperty(notifications, state, { value: backup[state], writable: true, }); } } onStop() { this.removeListeners(); } removeListeners() { Dispatcher.unsubscribe("CONNECTION_OPEN", this.restore); Dispatcher.unsubscribe("USER_SETTINGS_UPDATE", this.backupSettings); Dispatcher.unsubscribe( "EXPERIMENT_OVERRIDE_BUCKET", this.backupExperiments ); for (const event of KeybindEvents) { Dispatcher.unsubscribe(event, this.backupKeybinds); } for (const event of AccessiblityEvents) { Dispatcher.unsubscribe(event, this.backupAccessibility); } for (const event of VoiceEvents) { Dispatcher.unsubscribe(event, this.backupVoice); } for (const event of NotificationEvents) { Dispatcher.unsubscribe(event, this.backupNotifications); } } }; })(ZLibrary.buildPlugin(config)); })(); /*@end@*/