tg-bot-ts/src/systems/pollPersistence.ts

90 lines
No EOL
3.1 KiB
TypeScript

import fs from "fs";
import path from "path";
import { PollState, VoteEntry } from "@src/types";
import { Store } from "@systems/store";
import { Paths } from "@helpers/paths";
const PERSIST_PATH = Paths.data("poll-state.json");
// ─── Serialized shape ─────────────────────────────────────────────────────────
// Maps → arrays of [key, value] tuples, Sets → arrays of values
interface SerializedPollState {
messageId?: string | null;
slot: number;
yes: [string, VoteEntry][];
no: [string, VoteEntry][];
locked: boolean;
confirmed?: "yes" | "no" | null;
lockMessage?: string;
confirmMessage?: string;
lockedYesKeys?: string[];
}
// ─── Serialize / deserialize ──────────────────────────────────────────────────
function serialize(polls: Map<number, PollState>): SerializedPollState[] {
return [...polls.values()].map((s) => ({
messageId: s.messageId,
slot: s.slot,
yes: [...s.yes.entries()],
no: [...s.no.entries()],
locked: s.locked,
confirmed: s.confirmed,
lockMessage: s.lockMessage,
confirmMessage: s.confirmMessage,
lockedYesKeys: s.lockedYesKeys ? [...s.lockedYesKeys] : undefined,
}));
}
function deserialize(data: SerializedPollState[]): Map<number, PollState> {
const polls = new Map<number, PollState>();
for (const s of data) {
polls.set(s.slot, {
messageId: s.messageId,
slot: s.slot,
yes: new Map(s.yes),
no: new Map(s.no),
locked: s.locked,
confirmed: s.confirmed,
lockMessage: s.lockMessage,
confirmMessage: s.confirmMessage,
lockedYesKeys: s.lockedYesKeys ? new Set(s.lockedYesKeys) : undefined,
});
}
return polls;
}
// ─── Public API ───────────────────────────────────────────────────────────────
export namespace persist {
export function save(polls: Map<number, PollState>): void {
try {
Store.write(PERSIST_PATH, serialize(polls));
} catch (err) {
console.error("[pollPersistence] Failed to save poll state:", err);
}
}
export function load(): Map<number, PollState> | null {
try {
const data = Store.read<SerializedPollState[]>(PERSIST_PATH);
if (!data) return null;
const polls = deserialize(data);
console.log(`[pollPersistence] Restored ${polls.size} poll(s) from disk.`);
return polls;
} catch (err) {
console.error("[pollPersistence] Failed to load poll state:", err);
return null;
}
}
export function clear(): void {
try {
Store.delete(PERSIST_PATH);
} catch (err) {
console.error("[pollPersistence] Failed to clear poll state:", err);
}
}
}