import * as fs from 'fs' import * as path from 'path' const DATA_DIR = fs.existsSync('/data') ? '/data' : '/tmp' const TIMERS_PATH = path.join(DATA_DIR, 'tablet-timers.json') export interface Timer { id: string label: string startedAt: string endsAt: string agent?: 'cosmo' | 'lusya' } function load(): Timer[] { try { if (fs.existsSync(TIMERS_PATH)) { return JSON.parse(fs.readFileSync(TIMERS_PATH, 'utf-8')) } } catch {} return [] } function save(list: Timer[]) { try { fs.writeFileSync(TIMERS_PATH, JSON.stringify(list, null, 2)) } catch {} } function cleanup(list: Timer[]): Timer[] { // Drop items expired more than 30 min ago const cutoff = Date.now() - 30 * 60 * 1000 return list.filter(t => new Date(t.endsAt).getTime() > cutoff) } export function listActive(): Timer[] { const list = cleanup(load()) save(list) return list } export function addTimer(t: Omit): Timer { const full: Timer = { id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6), startedAt: new Date().toISOString(), ...t, } const list = cleanup(load()) list.push(full) save(list) return full } export function removeTimer(id: string): Timer | null { const list = load() const found = list.find(t => t.id === id) if (!found) return null save(list.filter(t => t.id !== id)) return found } /** * Fuzzy lookup by label (case-insensitive substring match). * Returns most-recently-started matching active timer, or null. */ export function findByLabel(label: string): Timer | null { const q = label.trim().toLowerCase() if (!q) return null const list = listActive() const matches = list.filter(t => t.label.toLowerCase().includes(q) || q.includes(t.label.toLowerCase()) ) if (matches.length === 0) return null // Sort by startedAt desc — most recent wins matches.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime()) return matches[0] } /** * Shift endsAt by deltaSeconds. Returns updated timer or null if not found. * Clamps endsAt to no earlier than "now + 1s" (не даём в прошлое). */ export function adjustTimer(id: string, deltaSeconds: number): Timer | null { const list = load() const idx = list.findIndex(t => t.id === id) if (idx === -1) return null const current = new Date(list[idx].endsAt).getTime() const proposed = current + deltaSeconds * 1000 const minimum = Date.now() + 1000 list[idx] = { ...list[idx], endsAt: new Date(Math.max(proposed, minimum)).toISOString() } save(list) return list[idx] }