import * as fs from "fs"; import {Environment} from "../common/environment.js"; import {logError} from "../util/utils.js"; import {Answers} from "../model/answers.js"; import path from "node:path"; import {KeyedAsyncLock} from "../util/async-lock.js"; type DataJsonFile = { admins: number[] muted: number[] } export let jsonFile: DataJsonFile; const DEFAULT_DATA: DataJsonFile = { admins: [], muted: [], }; const DEFAULT_ANSWERS: Answers = { test: ["a"], prefix: ["?"], better: ["Better"], who: [], kick: [], invite: [], day: [], }; const dataFileLock = new KeyedAsyncLock(); function ensureDataPath(): void { fs.mkdirSync(Environment.DATA_PATH, {recursive: true}); } function readJsonFile(fileName: string, defaultValue: T): T { ensureDataPath(); const filePath = `${Environment.DATA_PATH}/${fileName}`; if (!fs.existsSync(filePath)) { fs.writeFileSync(filePath, JSON.stringify(defaultValue, null, 2)); return structuredClone(defaultValue); } return JSON.parse(fs.readFileSync(filePath).toString()) as T; } export async function readData(): Promise { try { jsonFile = readJsonFile("data.json", DEFAULT_DATA); const admins = jsonFile.admins || []; admins.unshift(Environment.CREATOR_ID); Environment.setAdmins(new Set(admins)); Environment.setMuted(new Set(jsonFile.muted || [])); return Promise.resolve(); } catch (e) { logError(e instanceof Error ? e : String(e)); return Promise.reject(e); } } export async function saveData(): Promise { return dataFileLock.runExclusive("data.json", async () => { ensureDataPath(); jsonFile ??= structuredClone(DEFAULT_DATA); const adminIds: number[] = []; Environment.ADMIN_IDS.forEach(id => adminIds.push(id)); jsonFile.admins = adminIds; const mutedList: number[] = []; Environment.MUTED_IDS.forEach(id => mutedList.push(id)); jsonFile.muted = mutedList; try { const filePath = path.join(Environment.DATA_PATH, "data.json"); const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`; fs.writeFileSync(tmpPath, JSON.stringify(jsonFile)); fs.renameSync(tmpPath, filePath); return readData(); } catch (e) { return Promise.reject(e); } }); } export async function retrieveAnswers(): Promise { try { const json = readJsonFile("answers.json", DEFAULT_ANSWERS); Environment.setAnswers(json); return Promise.resolve(); } catch (e) { logError(e instanceof Error ? e : String(e)); return Promise.reject(e); } }