From 63c4a16b52ebead700570998be197be0930317ac Mon Sep 17 00:00:00 2001 From: Zack Williamson Date: Mon, 30 Dec 2024 17:27:00 -0500 Subject: [PATCH] chore: move all currency data ops to backend --- .../electron/events/when-ready.js | 2 +- src/backend/currency/currency-access.ts | 133 ++++++++++++++++-- .../currency/currency-command-manager.ts | 31 ++-- src/backend/currency/currency-manager.ts | 37 ++--- src/backend/database/currencyDatabase.js | 2 +- src/backend/effects/builtin/currency.js | 2 +- src/backend/import/setups/setup-importer.js | 7 +- .../app/controllers/currency.controller.js | 11 +- .../addOrEditCurrency/addOrEditCurrency.js | 12 +- src/gui/app/services/currency.service.js | 116 ++------------- src/gui/app/templates/_currency.html | 4 +- 11 files changed, 183 insertions(+), 174 deletions(-) diff --git a/src/backend/app-management/electron/events/when-ready.js b/src/backend/app-management/electron/events/when-ready.js index 4bd3d4a80..113f80cc9 100644 --- a/src/backend/app-management/electron/events/when-ready.js +++ b/src/backend/app-management/electron/events/when-ready.js @@ -69,7 +69,7 @@ exports.whenReady = async () => { windowManagement.updateSplashScreenStatus("Loading currencies..."); const currencyAccess = require("../../../currency/currency-access").default; - currencyAccess.refreshCurrencyCache(); + currencyAccess.loadCurrencies(); windowManagement.updateSplashScreenStatus("Loading ranks..."); const viewerRanksManager = require("../../../ranks/rank-manager"); diff --git a/src/backend/currency/currency-access.ts b/src/backend/currency/currency-access.ts index feecee257..c4d24af13 100644 --- a/src/backend/currency/currency-access.ts +++ b/src/backend/currency/currency-access.ts @@ -1,5 +1,7 @@ -import { FirebotViewer } from "../../types/viewers"; +import EventEmitter from "events"; +import { JsonDB } from "node-json-db"; +import { FirebotViewer } from "../../types/viewers"; import logger from "../logwrapper"; import frontendCommunicator from "../common/frontend-communicator"; import { SettingsManager } from "../common/settings-manager"; @@ -15,7 +17,7 @@ export type Currency = { payout: number; /** Offline payout */ - offline: number; + offline?: number | string; /** Maps user role IDs to the amount of bonus payout they receive. */ bonus: Record; @@ -25,15 +27,34 @@ type CurrencyCache = { [currencyName: string]: Currency }; -class CurrencyAccess { +class CurrencyAccess extends EventEmitter { private _currencyCache: CurrencyCache = {}; constructor() { - // Refresh Currency Cache - // This gets a message from front end when a currency needs to be created. - // This is also triggered in the currencyManager. - frontendCommunicator.on("refresh-currency-cache", () => { - this.refreshCurrencyCache(); + super(); + + frontendCommunicator.on("currencies:get-currencies", () => { + return this.getCurrencies(); + }); + + frontendCommunicator.on("currencies:get-currency-by-id", (currencyId: string) => { + return this.getCurrencyById(currencyId); + }); + + frontendCommunicator.on("currencies:get-currency-by-name", (currencyName: string) => { + return this.getCurrencyByName(currencyName); + }); + + frontendCommunicator.on("currencies:create-currency", (currency: Currency) => { + this.createCurrency(currency); + }); + + frontendCommunicator.on("currencies:update-currency", (currency: Currency) => { + this.updateCurrency(currency); + }); + + frontendCommunicator.on("currencies:delete-currency", (currency: Currency) => { + this.deleteCurrency(currency); }); } @@ -41,26 +62,34 @@ class CurrencyAccess { return SettingsManager.getSetting("ViewerDB"); } - refreshCurrencyCache(): void { + getCurrencyDb(): JsonDB { + return profileManager.getJsonDbInProfile("/currency/currency"); + } + + loadCurrencies(): void { if (this.isViewerDBOn() !== true) { return; } logger.debug("Refreshing currency cache"); - const db = profileManager.getJsonDbInProfile("/currency/currency"); + const db = this.getCurrencyDb(); + + let resaveCurrencies = false; + const cache: CurrencyCache = db.getData("/"); - let issue2801 = false; - const cache = db.getData("/"); Object.keys(cache).forEach((currencyId) => { if (cache[currencyId].offline === null || cache[currencyId].offline === "") { - issue2801 = true; + resaveCurrencies = true; cache[currencyId].offline = undefined; } }); - if (issue2801) { + + if (resaveCurrencies) { db.push("/", cache); } + this._currencyCache = cache; + frontendCommunicator.send("currencies:currencies-updated", this.getCurrencies()); } getCurrencies(): CurrencyCache { @@ -94,6 +123,82 @@ class CurrencyAccess { return viewer; } + + importCurrency(currency: Currency) { + if (this.isViewerDBOn() !== true) { + return; + } + + if (currency == null || currency.id == null) { + return; + } + + if (!currency.offline) { + currency.offline = undefined; + } + + if (this.getCurrencyById(currency.id)) { + this.updateCurrency(currency); + } else { + let hasDuplicate = false; + let counter = 1; + let name = currency.name; + do { + hasDuplicate = Object.values(this.getCurrencies()) + .some(c => c.name === name); + if (hasDuplicate) { + name = currency.name + counter; + counter++; + } + } while (hasDuplicate); + currency.name = name; + + this.createCurrency(currency); + } + } + + createCurrency(currency: Currency) { + if (this.isViewerDBOn() !== true) { + return false; + } + + if (Object.values(this._currencyCache).some(c => c.name === currency.name)) { + logger.error(`User tried to create currency with the same name as another currency: ${currency.name}.`); + return false; + } + + this._currencyCache[currency.id] = currency; + this.saveAllCurrencies(); + this.emit("currencies:currency-created", currency); + + logger.debug(`Currency created with name: ${currency.name}`); + return true; + } + + updateCurrency(currency: Currency) { + if (this.isViewerDBOn() !== true) { + return; + } + + this._currencyCache[currency.id] = currency; + this.saveAllCurrencies(); + this.emit("currencies:currency-updated", currency); + } + + deleteCurrency(currency: Currency) { + if (this.isViewerDBOn() !== true) { + return; + } + + delete this._currencyCache[currency.id]; + this.saveAllCurrencies(); + this.emit("currencies:currency-deleted", currency); + } + + private saveAllCurrencies() { + this.getCurrencyDb().push("/", this._currencyCache); + frontendCommunicator.send("currencies:currencies-updated", this.getCurrencies()); + } } const currencyAccess = new CurrencyAccess(); diff --git a/src/backend/currency/currency-command-manager.ts b/src/backend/currency/currency-command-manager.ts index fd1e2bee3..f6556b1da 100644 --- a/src/backend/currency/currency-command-manager.ts +++ b/src/backend/currency/currency-command-manager.ts @@ -1,36 +1,31 @@ import { SystemCommand } from "../../types/commands"; - -import currencyAccess from "./currency-access"; +import currencyAccess, { Currency } from "./currency-access"; import currencyManager from "./currency-manager"; import commandManager from "../chat/commands/command-manager"; import logger from "../logwrapper"; -import frontendCommunicator from "../common/frontend-communicator"; import util from "../utility"; -interface BasicCurrency { - id: string; - name: string; -} - type CurrencyCommandRefreshRequestAction = "create" | "update" | "delete"; -interface CurrencyCommandRefreshRequest { - action: CurrencyCommandRefreshRequestAction; - currency: BasicCurrency; -} - class CurrencyCommandManager { constructor() { - // Refresh our currency commands. - frontendCommunicator.on("refreshCurrencyCommands", (request: CurrencyCommandRefreshRequest) => { - this.refreshCurrencyCommands(request.action, request.currency); + currencyAccess.on("currencies:currency-created", (currency: Currency) => { + this.refreshCurrencyCommands("create", currency); + }); + + currencyAccess.on("currencies:currency-updated", (currency: Currency) => { + this.refreshCurrencyCommands("update", currency); + }); + + currencyAccess.on("currencies:currency-deleted", (currency: Currency) => { + this.refreshCurrencyCommands("delete", currency); }); } /** * Creates a command definition when given a currency name. */ - createCurrencyCommandDefinition(currency: BasicCurrency): SystemCommand<{ + createCurrencyCommandDefinition(currency: Partial): SystemCommand<{ currencyBalanceMessageTemplate: string; whisperCurrencyBalanceMessage: boolean; addMessageTemplate: string; @@ -438,7 +433,7 @@ class CurrencyCommandManager { */ refreshCurrencyCommands( action: CurrencyCommandRefreshRequestAction = null, - currency: BasicCurrency = null + currency: Partial = null ): void { // If we don't get currency stop here. if (currency == null) { diff --git a/src/backend/currency/currency-manager.ts b/src/backend/currency/currency-manager.ts index 1e4458b53..bc614a806 100644 --- a/src/backend/currency/currency-manager.ts +++ b/src/backend/currency/currency-manager.ts @@ -29,14 +29,20 @@ class CurrencyManager { private _currencyInterval: NodeJS.Timeout; constructor() { - // Create Currency Event - // This gets a message from front end when a currency needs to be created. - frontendCommunicator.onAsync("create-currency", async (currencyId: string) => { + currencyAccess.on("currencies:currency-created", async (currency: Currency) => { if (currencyAccess.isViewerDBOn() !== true) { return; } - logger.info(`Creating a new currency with id ${currencyId}`); - await this.addCurrencyToAllViewers(currencyId, 0); + logger.info(`Creating a new currency with id ${currency.id}`); + await this.addCurrencyToAllViewers(currency.id, 0); + }); + + currencyAccess.on("currencies:currency-deleted", async (currency: Currency) => { + if (currencyAccess.isViewerDBOn() !== true) { + return; + } + logger.info(`Deleting currency with id ${currency.id}`); + await this.deleteCurrencyById(currency.id); }); frontendCommunicator.onAsync("give-currency", async ({ @@ -81,30 +87,13 @@ class CurrencyManager { // Purge Currency Event // This gets a message from front end when a currency needs to be purged. - frontendCommunicator.onAsync("purge-currency", async (currencyId: string) => { + frontendCommunicator.onAsync("currencies:purge-currency", async (currencyId: string) => { if (currencyAccess.isViewerDBOn() !== true) { return; } logger.info(`Purging currency with id ${currencyId}`); await this.purgeCurrencyById(currencyId); }); - - // Delete Currency Event - // This gets a message from front end when a currency needs to be deleted - frontendCommunicator.onAsync("delete-currency", async (currencyId: string) => { - if (currencyAccess.isViewerDBOn() !== true) { - return; - } - logger.info(`Deleting currency with id ${currencyId}`); - await this.deleteCurrencyById(currencyId); - }); - - - // Start up our currency timers. - // Also fired in currency-access. - frontendCommunicator.on("refresh-currency-cache", () => { - this.startTimer(); - }); } /** @@ -267,7 +256,7 @@ class CurrencyManager { continue; } - basePayout = currency.offline; + basePayout = currency.offline as number; } const currentMinutes = DateTime.utc().minute; diff --git a/src/backend/database/currencyDatabase.js b/src/backend/database/currencyDatabase.js index 049825176..e421fa14b 100644 --- a/src/backend/database/currencyDatabase.js +++ b/src/backend/database/currencyDatabase.js @@ -4,7 +4,7 @@ const currencyAccess = require("../currency/currency-access").default; const currencyManager = require("../currency/currency-manager"); exports.isViewerDBOn = () => currencyAccess.isViewerDBOn(); -exports.refreshCurrencyCache = () => currencyAccess.refreshCurrencyCache(); +exports.refreshCurrencyCache = () => currencyAccess.loadCurrencies(); exports.addCurrencyToNewUser = viewer => currencyAccess.addCurrencyToNewViewer(viewer); exports.getCurrencies = () => currencyAccess.getCurrencies(); exports.getCurrencyById = id => currencyAccess.getCurrencyById(id); diff --git a/src/backend/effects/builtin/currency.js b/src/backend/effects/builtin/currency.js index b70b4410c..7c26d747f 100644 --- a/src/backend/effects/builtin/currency.js +++ b/src/backend/effects/builtin/currency.js @@ -188,7 +188,7 @@ const currency = { $scope.currencies = currencyService.getCurrencies(); $scope.getCurrencyName = function(currencyId) { - const currency = currencyService.getCurrencies(currencyId); + const currency = currencyService.getCurrency(currencyId); return currency.name; }; diff --git a/src/backend/import/setups/setup-importer.js b/src/backend/import/setups/setup-importer.js index e6636f760..4d19bf280 100644 --- a/src/backend/import/setups/setup-importer.js +++ b/src/backend/import/setups/setup-importer.js @@ -16,6 +16,7 @@ const quickActionManager = require("../../quick-actions/quick-action-manager"); const variableMacroManager = require("../../variables/macro-manager"); const rankManager = require("../../ranks/rank-manager"); const { escapeRegExp } = require("../../utility"); +const currencyAccess = require("../../currency/currency-access").default; function findAndReplaceCurrency(data, currency) { const entries = Object.entries(data); @@ -105,7 +106,7 @@ async function importSetup(setup, selectedCurrency) { // currencies const currencies = setup.components.currencies || []; for (const currency of currencies) { - frontendCommunicator.send("import-currency", currency); + currencyAccess.importCurrency(currency); } // effect queues @@ -209,7 +210,7 @@ async function importSetup(setup, selectedCurrency) { function removeSetupComponents(components) { Object.entries(components) .forEach(([componentType, componentList]) => { - componentList.forEach(({id, name}) => { + componentList.forEach((id) => { switch (componentType) { case "commands": commandManager.deleteCustomCommand(id); @@ -218,7 +219,7 @@ function removeSetupComponents(components) { countersManager.deleteItem(id); break; case "currencies": - frontendCommunicator.send("remove-currency", { id, name }); + currencyAccess.deleteCurrency(id); break; case "effectQueues": effectQueueManager.deleteItem(id); diff --git a/src/gui/app/controllers/currency.controller.js b/src/gui/app/controllers/currency.controller.js index ca9973a75..74855b76a 100644 --- a/src/gui/app/controllers/currency.controller.js +++ b/src/gui/app/controllers/currency.controller.js @@ -9,10 +9,7 @@ utilityService, currencyService ) { - // Returns an array of all currencies. - $scope.getCurrencies = function() { - return currencyService.getCurrencies(); - }; + $scope.currencyService = currencyService; // Open currency modal. $scope.openAddOrEditCurrencyModal = function(currency) { @@ -21,13 +18,13 @@ resolveObj: { currency: () => currency }, - closeCallback: resp => { + closeCallback: (resp) => { const action = resp.action, currency = resp.currency; switch (action) { case "add": - currencyService.saveCurrency(currency); + currencyService.createCurrency(currency); break; case "update": currencyService.updateCurrency(currency); @@ -44,4 +41,4 @@ }); }; }); -}()); +}()); \ No newline at end of file diff --git a/src/gui/app/directives/modals/currency/addOrEditCurrency/addOrEditCurrency.js b/src/gui/app/directives/modals/currency/addOrEditCurrency/addOrEditCurrency.js index dfc88fdc6..6efe2bb7f 100644 --- a/src/gui/app/directives/modals/currency/addOrEditCurrency/addOrEditCurrency.js +++ b/src/gui/app/directives/modals/currency/addOrEditCurrency/addOrEditCurrency.js @@ -12,7 +12,7 @@ dismiss: "&", modalInstance: "<" }, - controller: function($scope, utilityService, currencyService, viewerRolesService, logger) { + controller: function(utilityService, currencyService, viewerRolesService, logger) { const { v4: uuid } = require("uuid"); const $ctrl = this; @@ -56,6 +56,14 @@ return; } + if ($ctrl.isNewCurrency && currencyService.currencies.some(c => c.name === $ctrl.currency.name)) { + utilityService.showErrorModal( + "You cannot create a currency with the same name as another currency!" + ); + logger.error(`User tried to create currency with the same name as another currency: ${currency.name}.`); + return; + } + if (!$ctrl.currency.offline) { $ctrl.currency.offline = undefined; } @@ -117,4 +125,4 @@ }; } }); -}()); +}()); \ No newline at end of file diff --git a/src/gui/app/services/currency.service.js b/src/gui/app/services/currency.service.js index 9d137f794..753466888 100644 --- a/src/gui/app/services/currency.service.js +++ b/src/gui/app/services/currency.service.js @@ -1,132 +1,46 @@ "use strict"; (function() { - //This handles events - const profileManager = require("../../backend/common/profile-manager.js"); - const { ipcRenderer } = require("electron"); - - angular.module("firebotApp").factory("currencyService", function(logger, utilityService, - backendCommunicator) { + angular.module("firebotApp").factory("currencyService", function(backendCommunicator) { const service = {}; // The currency settings. - const currencyDb = profileManager.getJsonDbInProfile("/currency/currency"); + service.currencies = Object.values(backendCommunicator.fireEventSync("currencies:get-currencies")); // This will get currency information. // Can pass option param to just get one currency, otherwise it gets all of them. - service.getCurrencies = function(currencyId) { - - // If we have an optional param return settings for that currency. - if (currencyId != null) { - try { - return currencyDb.getData(`/${currencyId}`); - } catch (err) { - logger.error(err); - return []; - } - } - - let currencyData; - try { - currencyData = currencyDb.getData("/"); - } catch (err) { - logger.error(err); - return []; - } - - return Object.values(currencyData); + service.getCurrencies = () => { + return service.currencies; }; service.getCurrency = (currencyId) => { - return service.getCurrencies().find(c => c.id === currencyId); + return service.currencies.find(c => c.id === currencyId); }; // Saved the currency modal. - service.saveCurrency = function(currency, updateName = false) { - const currencyId = currency.id, - allCurrencies = service.getCurrencies(); - - // Check to make sure we don't have a currency with the same name. - if (updateName) { - let hasDuplicate; - let counter = 1; - let name = currency.name; - do { - hasDuplicate = Object.values(allCurrencies) - .some(c => c.name === name); - if (hasDuplicate) { - name = currency.name + counter; - counter++; - } - } while (hasDuplicate); - currency.name = name; - } else { - const dupe = Object.values(allCurrencies) - .some(c => c.name === name); - // Uh Oh! We have a currency with this name already. - if (dupe) { - utilityService.showErrorModal( - "You cannot create a currency with the same name as another currency!" - ); - logger.error(`User tried to create currency with the same name as another currency: ${currency.name}.`); - return; - } - } - - // Push Currency to DB. - currencyDb.push(`/${currencyId}`, currency); - - // Log currency name. - logger.debug(`Currency created with name: ${currency.name}`); - - // Send success message. - ipcRenderer.send("create-currency", currencyId); - ipcRenderer.send("refresh-currency-cache"); - ipcRenderer.send("refreshCurrencyCommands", {"action": "create", "currency": currency}); + service.createCurrency = function(currency) { + backendCommunicator.send("currencies:create-currency", currency); }; // Updated a pre-existing currency through the modal. service.updateCurrency = function(currency) { - const currencyId = currency.id; - currencyDb.push(`/${currencyId}`, currency); - ipcRenderer.send("refresh-currency-cache"); - ipcRenderer.send("refreshCurrencyCommands", {"action": "update", "currency": currency}); + backendCommunicator.send("currencies:update-currency", currency); }; // Purged a currency through the modal. - service.purgeCurrency = function(currencyId) { - ipcRenderer.send("purge-currency", currencyId); + service.purgeCurrency = function(currency) { + backendCommunicator.send("currencies:purge-currency", currency.id); }; // Deleted a currency through the modal. - service.deleteCurrency = function(currency) { - const currencyId = currency.id; - currencyDb.delete(`/${currencyId}`); - ipcRenderer.send("delete-currency", currencyId); - ipcRenderer.send("refresh-currency-cache"); - ipcRenderer.send("refreshCurrencyCommands", {"action": "delete", "currency": currency}); + service.deleteCurrency = (currency) => { + backendCommunicator.send("currencies:delete-currency", currency); }; - backendCommunicator.on("import-currency", (currency) => { - if (currency == null || currency.id == null) { - return; - } - - if (!currency.offline) { - currency.offline = undefined; - } - - if (service.getCurrency(currency.id)) { - service.updateCurrency(currency); - } else { - service.saveCurrency(currency, true); - } - }); - - backendCommunicator.on("remove-currency", (currency) => { - service.deleteCurrency(currency); + backendCommunicator.on("currencies:currencies-updated", (currencies) => { + service.currencies = Object.values(currencies); }); return service; }); -}()); +}()); \ No newline at end of file diff --git a/src/gui/app/templates/_currency.html b/src/gui/app/templates/_currency.html index 2edfee713..8803dc07d 100644 --- a/src/gui/app/templates/_currency.html +++ b/src/gui/app/templates/_currency.html @@ -3,12 +3,12 @@
-
+
No currencies saved. You should make one! :)
-
+