BetterDiscordApp-rauenzi/renderer/src/modules/datastore.js

185 lines
8.8 KiB
JavaScript
Raw Normal View History

2019-05-29 05:48:41 +02:00
import {Config} from "data";
2019-06-27 04:31:18 +02:00
import Utilities from "./utilities";
import Logger from "common/logger";
2019-05-28 20:19:48 +02:00
const fs = require("fs");
const path = require("path");
2021-03-01 01:19:25 +01:00
const releaseChannel = window?.DiscordNative?.app?.getReleaseChannel?.() ?? "stable";
const discordVersion = window?.DiscordNative?.remoteApp?.getVersion?.() ?? "0.0.309";
2019-05-28 20:19:48 +02:00
2019-06-27 04:31:18 +02:00
// Schema
2019-06-06 21:57:25 +02:00
// =======================
// %appdata%\BetterDiscord
// -> data
// -> [releaseChannel]\ (stable/canary/ptb)
// -> settings.json
// -> plugins.json
// -> themes.json
2019-05-29 05:48:41 +02:00
export default new class DataStore {
2019-05-28 20:19:48 +02:00
constructor() {
2019-06-07 05:52:08 +02:00
this.data = {misc: {}};
2019-05-28 20:19:48 +02:00
this.pluginData = {};
2019-06-28 07:36:05 +02:00
this.cacheData = {};
2019-05-28 20:19:48 +02:00
}
initialize() {
2021-03-25 17:19:55 +01:00
const bdFolderExists = fs.existsSync(Config.dataPath);
if (!bdFolderExists) fs.mkdirSync(Config.dataPath);
const pluginFolderExists = fs.existsSync(this.pluginFolder);
if (!pluginFolderExists) fs.mkdirSync(this.pluginFolder);
const themeFolderExists = fs.existsSync(this.themeFolder);
if (!themeFolderExists) fs.mkdirSync(this.themeFolder);
2020-07-29 21:06:54 +02:00
const newStorageExists = fs.existsSync(this.baseFolder);
if (!newStorageExists) fs.mkdirSync(this.baseFolder);
2019-06-07 05:52:08 +02:00
if (!fs.existsSync(this.dataFolder)) fs.mkdirSync(this.dataFolder);
2019-06-10 22:37:50 +02:00
if (!fs.existsSync(this.customCSS)) fs.writeFileSync(this.customCSS, "");
2019-06-07 05:52:08 +02:00
const dataFiles = fs.readdirSync(this.dataFolder).filter(f => !fs.statSync(path.resolve(this.dataFolder, f)).isDirectory() && f.endsWith(".json"));
for (const file of dataFiles) {
let data = {};
try {data = __non_webpack_require__(path.resolve(this.dataFolder, file));}
catch (e) {Logger.stacktrace("DataStore", `Could not load file ${file}`, e);}
this.data[file.split(".")[0]] = data;
2019-06-07 05:52:08 +02:00
}
if (newStorageExists) return;
try {this.convertOldData();} // Convert old data if it exists (routine checks existence and removes existence)
catch (e) {Logger.stacktrace("DataStore", `Could not convert old data.`, e);}
}
convertOldData() {
const oldFile = path.join(Config.dataPath, "bdstorage.json");
if (!fs.existsSync(oldFile)) return;
const oldData = __non_webpack_require__(oldFile); // got the data
fs.renameSync(oldFile, `${oldFile}.bak`); // rename file after grabbing data to prevent loop
const setChannelData = (channel, key, value, ext = "json") => fs.writeFileSync(path.resolve(this.baseFolder, channel, `${key}.${ext}`), JSON.stringify(value, null, 4));
const channels = ["stable", "canary", "ptb"];
2020-07-27 01:34:06 +02:00
let customcss = "";
let favoriteEmotes = {};
try {customcss = oldData.bdcustomcss ? atob(oldData.bdcustomcss) : "";}
2020-10-20 05:45:32 +02:00
catch (e) {Logger.stacktrace("DataStore:convertOldData", "Error decoding custom css", e);}
2020-07-27 01:34:06 +02:00
try {favoriteEmotes = oldData.bdfavemotes ? JSON.parse(atob(oldData.bdfavemotes)) : {};}
2020-10-20 05:45:32 +02:00
catch (e) {Logger.stacktrace("DataStore:convertOldData", "Error decoding favorite emotes", e);}
for (const channel of channels) {
if (!fs.existsSync(path.resolve(this.baseFolder, channel))) fs.mkdirSync(path.resolve(this.baseFolder, channel));
const channelData = oldData.settings[channel];
2020-10-08 20:13:19 +02:00
if (!channelData || !channelData.settings) continue;
const oldSettings = channelData.settings;
const newSettings = {
2021-04-03 05:36:55 +02:00
general: {publicServers: oldSettings["bda-gs-1"], voiceDisconnect: oldSettings["bda-dc-0"], showToasts: oldSettings["fork-ps-2"]},
appearance: {twentyFourHour: oldSettings["bda-gs-6"], minimalMode: oldSettings["bda-gs-2"], coloredText: oldSettings["bda-gs-7"]},
addons: {addonErrors: oldSettings["fork-ps-1"], autoReload: oldSettings["fork-ps-5"]},
developer: {debuggerHotkey: oldSettings["bda-gs-8"], reactDevTools: oldSettings.reactDevTools}
};
const newEmotes = {
general: {download: oldSettings["fork-es-3"], emoteMenu: oldSettings["bda-es-0"], hideEmojiMenu: !oldSettings["bda-es-9"], modifiers: oldSettings["bda-es-8"], animateOnHover: oldSettings["fork-es-2"]},
categories: {twitchglobal: oldSettings["bda-es-7"], twitchsubscriber: oldSettings["bda-es-7"], frankerfacez: oldSettings["bda-es-1"], bttv: oldSettings["bda-es-2"]}
};
setChannelData(channel, "settings", newSettings); // settingsCookie
setChannelData(channel, "emotes", newEmotes); // emotes (from settingsCookie)
2020-10-20 05:45:32 +02:00
setChannelData(channel, "plugins", channelData.plugins || {}); // pluginCookie
setChannelData(channel, "themes", channelData.themes || {}); // themeCookie
setChannelData(channel, "misc", {favoriteEmotes}); // favorite emotes
fs.writeFileSync(path.resolve(this.baseFolder, channel, "custom.css"), customcss); // customcss
}
2021-04-03 05:36:55 +02:00
this.initialize(); // Reinitialize data store with the converted data
2019-05-28 20:19:48 +02:00
}
2020-07-16 07:42:56 +02:00
get injectionPath() {
if (this._injectionPath) return this._injectionPath;
2021-03-01 01:19:25 +01:00
const base = Config.appPath;
const roamingBase = Config.userData;
const roamingLocation = path.resolve(roamingBase, discordVersion, "modules", "discord_desktop_core", "injector");
2020-07-16 07:42:56 +02:00
const location = path.resolve(base, "..", "app");
const realLocation = fs.existsSync(location) ? location : fs.existsSync(roamingLocation) ? roamingLocation : null;
if (!realLocation) return this._injectionPath = null;
return this._injectionPath = realLocation;
}
get pluginFolder() {return this._pluginFolder || (this._pluginFolder = path.resolve(Config.dataPath, "plugins"));}
get themeFolder() {return this._themeFolder || (this._themeFolder = path.resolve(Config.dataPath, "themes"));}
2019-06-10 22:37:50 +02:00
get customCSS() {return this._customCSS || (this._customCSS = path.resolve(this.dataFolder, "custom.css"));}
2019-06-07 05:52:08 +02:00
get baseFolder() {return this._baseFolder || (this._baseFolder = path.resolve(Config.dataPath, "data"));}
get dataFolder() {return this._dataFolder || (this._dataFolder = path.resolve(this.baseFolder, `${releaseChannel}`));}
2019-05-28 20:19:48 +02:00
getPluginFile(pluginName) {return path.resolve(Config.dataPath, "plugins", pluginName + ".config.json");}
2019-06-06 21:57:25 +02:00
2019-06-07 05:52:08 +02:00
_getFile(key) {
2020-07-16 07:42:56 +02:00
if (key == "settings" || key == "plugins" || key == "themes" || key == "window") return path.resolve(this.dataFolder, `${key}.json`);
2019-06-07 05:52:08 +02:00
return path.resolve(this.dataFolder, `misc.json`);
}
2019-06-06 21:57:25 +02:00
getBDData(key) {
2019-06-07 05:52:08 +02:00
return this.data.misc[key] || "";
2019-05-28 20:19:48 +02:00
}
2019-06-06 21:57:25 +02:00
setBDData(key, value) {
2019-06-07 05:52:08 +02:00
this.data.misc[key] = value;
fs.writeFileSync(path.resolve(this.dataFolder, `misc.json`), JSON.stringify(this.data.misc, null, 4));
2019-05-28 20:19:48 +02:00
}
2019-06-27 04:31:18 +02:00
getLocale(locale) {
const file = path.resolve(this.localeFolder, `${locale}.json`);
if (!fs.existsSync(file)) return null;
return Utilities.testJSON(fs.readFileSync(file).toString());
}
saveLocale(locale, strings) {
fs.writeFileSync(path.resolve(this.localeFolder, `${locale}.json`), JSON.stringify(strings, null, 4));
}
2019-06-06 21:57:25 +02:00
getData(key) {
2019-05-28 20:19:48 +02:00
return this.data[key] || "";
}
2019-06-06 21:57:25 +02:00
setData(key, value) {
2019-05-28 20:19:48 +02:00
this.data[key] = value;
2019-06-07 05:52:08 +02:00
fs.writeFileSync(path.resolve(this.dataFolder, `${key}.json`), JSON.stringify(value, null, 4));
2019-05-28 20:19:48 +02:00
}
2019-06-10 22:37:50 +02:00
loadCustomCSS() {
return fs.readFileSync(this.customCSS).toString();
}
saveCustomCSS(css) {
return fs.writeFileSync(this.customCSS, css);
}
ensurePluginData(pluginName) {
if (typeof(this.pluginData[pluginName]) !== "undefined") return; // Already have data cached
// Setup blank data if config doesn't exist
if (!fs.existsSync(this.getPluginFile(pluginName))) return this.pluginData[pluginName] = {};
// Getting here means not cached, read from disk
2019-05-28 20:19:48 +02:00
this.pluginData[pluginName] = JSON.parse(fs.readFileSync(this.getPluginFile(pluginName)));
}
getPluginData(pluginName, key) {
this.ensurePluginData(pluginName); // Ensure plugin data, if any, is cached
return this.pluginData[pluginName][key]; // Return blindly to allow falsey values
2019-05-28 20:19:48 +02:00
}
setPluginData(pluginName, key, value) {
if (value === undefined) return; // Can't set undefined, use deletePluginData
this.ensurePluginData(pluginName); // Ensure plugin data, if any, is cached
this.pluginData[pluginName][key] = value; // Set the value blindly to allow falsey values
fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4)); // Save to disk
2019-05-28 20:19:48 +02:00
}
deletePluginData(pluginName, key) {
this.ensurePluginData(pluginName); // Ensure plugin data, if any, is cached
2019-05-28 20:19:48 +02:00
delete this.pluginData[pluginName][key];
fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4));
}
2019-05-29 05:48:41 +02:00
};