import type { ActivityItem } from './types.js'; import type { ActivityLogRepository } from '../database/repositories.js'; const MAX_ITEMS = 200; /** * Bounded log of bot actions surfaced on the dashboard. * Hydrates from SQLite on construction and persists every push, * so the feed survives restarts. */ export class ActivityLog { private items: ActivityItem[] = []; constructor(private repo: ActivityLogRepository) { const rows = repo.getRecent(MAX_ITEMS); this.items = rows .map((r) => ({ timestamp: r.timestamp, type: r.type as ActivityItem['type'], message: r.message, recipient: r.recipient ?? undefined, imageUrl: r.imageUrl ?? undefined, postTitle: r.postTitle ?? undefined, postUrl: r.postUrl ?? undefined, })) .reverse(); } push( type: ActivityItem['type'], message: string, recipient?: string, imageUrl?: string, origin?: { postTitle: string; postUrl: string }, ): void { const item: ActivityItem = { timestamp: Date.now(), type, message, recipient, imageUrl, ...origin }; this.items.push(item); if (this.items.length > MAX_ITEMS) { this.items = this.items.slice(-MAX_ITEMS); } this.repo.insert(item); this.repo.prune(MAX_ITEMS); } recent(limit: number): ActivityItem[] { return this.items.slice(-limit).reverse(); } totalProcessed(): number { return this.repo.countSentSkipped(); } }