import { SettingString, settingsType } from "../type/settingTypes"; import ms from "ms"; import { CodingHelper } from "./codingHelper"; import SettingCommandHandler from "../command/settingCommandHandler"; import SettingService from "../service/settingService"; import { APPLICATION_SECRET } from "../env.defaults"; export default abstract class SettingHelper { private static settings: { [key in SettingString]?: string } = {}; public static getSetting(key: SettingString): string | number | boolean | ms.StringValue { let settingType = settingsType[key]; let setting = this.settings[key] ?? String(settingType.default ?? ""); if (Array.isArray(settingType.type)) { return setting; } if (settingType.type.includes("/crypt")) { setting = CodingHelper.decrypt(APPLICATION_SECRET, String(setting)); } if (settingType.type.startsWith("string")) { return setting; } if (settingType.type.startsWith("ms")) { return setting as ms.StringValue; } if (settingType.type.startsWith("number")) { return Number(setting); } if (settingType.type.startsWith("boolean")) { return setting == "true"; } return setting; } public static async setSetting(key: SettingString, value: string) { if (value == undefined || value == null) return; let settingType = settingsType[key]; let result = value; this.checkSettings(key, result); if (!Array.isArray(settingType.type) && settingType.type.includes("/crypt")) { result = CodingHelper.encrypt(APPLICATION_SECRET, value); } await SettingCommandHandler.create({ topic: key.split(".")[0], key: key.split(".")[1], value: result, }); } public static async resetSetting(key: SettingString) { let settingType = settingsType[key]; this.settings[key] = String(settingType.default ?? ""); await SettingCommandHandler.delete({ topic: key.split(".")[0], key: key.split(".")[1], }); } public static async configure() { console.log("Configured Settings"); let settings = await SettingService.getSettings(); for (const element of settings) { let ref = `${element.topic}.${element.key}` as SettingString; this.settings[ref] = element.value; this.checkSettings(ref); } } private static checkSettings(key: SettingString, value?: string) { let settingType = settingsType[key]; if (!value) { value = this.getSetting(key).toString(); } if ( !Array.isArray(settingType.type) && settingType.type.startsWith("string") && this.checkIfEmptyOrNotString(value) ) { throw new Error(`set valid value to ${key}`); } if ( !Array.isArray(settingType.type) && settingType.type.startsWith("ms") && this.checkIfNotMS(value as ms.StringValue) ) { throw new Error(`set valid ms value to ${key} -> [0-9]*(y|d|h|m|s)`); } if (!Array.isArray(settingType.type) && settingType.type.startsWith("number") && isNaN(Number(value))) { throw new Error(`set valid numeric value to ${key}`); } if ( !Array.isArray(settingType.type) && settingType.type.startsWith("number") && settingType.min && Number(value) < settingType.min ) { throw new Error(`${key} has to be at least ${settingType.min}`); } if ( !Array.isArray(settingType.type) && settingType.type.startsWith("boolean") && value != "true" && value != "false" ) { throw new Error(`"set 'true' or 'false' to ${key}`); } } private static checkIfEmptyOrNotString(val: any) { return typeof val != "string" || val == ""; } private static checkIfNotMS(input: ms.StringValue): boolean { try { const result = ms(input); if (result === undefined) { return true; } } catch (e) { return true; } return false; } }