diff --git a/src/core/orchestrator.ts b/src/core/orchestrator.ts index a940285..5396c64 100644 --- a/src/core/orchestrator.ts +++ b/src/core/orchestrator.ts @@ -1037,30 +1037,48 @@ export class Orchestrator { id: string; cronExpr: string; taskType: string; + payload: string; enabled: boolean; }>; ConsoleLogger.info("core", `Found ${schedules.length} total schedules`); - // Filter reminders for this chatId - we need to check the payload of each schedule - // Since we can't easily query by chatId, we'll need to get schedule details - // For now, filter by taskType === "reminder" - const reminderSchedules = schedules.filter((s) => s.taskType === "reminder" && s.enabled); + // Filter reminders for this chatId + const filteredSchedules = schedules.filter((s) => { + if (!s.enabled) return false; + if (s.taskType !== "reminder" && s.taskType !== "ai_query") return false; + + try { + const payload = JSON.parse(s.payload); + return payload.chatId === chatId; + } catch (err) { + return false; + } + }); - ConsoleLogger.info("core", `Found ${reminderSchedules.length} reminder schedules`); + ConsoleLogger.info("core", `Found ${filteredSchedules.length} filtered schedules for chatId ${chatId}`); - if (reminderSchedules.length === 0) { + if (filteredSchedules.length === 0) { ConsoleLogger.info("core", "No reminders found, sending 'No active reminders' message"); this.sendToTelegram(chatId, "👌🏻 No active reminders."); return; } - // Format reminders - we'll show ID and cronExpr, but reminderMessage is in the payload - // For a better implementation, we'd need to query each schedule's payload - const formatted = reminderSchedules - .map((rem) => `ID: ${rem.id}\nTime: ${rem.cronExpr}`) + // Format reminders - include message/query and task type + const formatted = filteredSchedules + .map((s) => { + let message = "N/A"; + try { + const p = JSON.parse(s.payload); + message = p.reminderMessage || p.query || "N/A"; + } catch (e) {} + + const typeLabel = s.taskType === "ai_query" ? "🤖 Task" : "🔔 Reminder"; + return `${typeLabel}\nID: ${s.id}\nTime: ${s.cronExpr}\nMessage: ${message}`; + }) .join("\n\n---\n\n"); - const message = `Active reminders:\n\n${formatted}`; + + const message = `⏰ Active schedules:\n\n${formatted}`; ConsoleLogger.info("core", `Sending reminder list to chatId ${chatId}: ${message.substring(0, 100)}...`); this.sendToTelegram(chatId, message, false, "HTML"); } catch (err) { @@ -1078,12 +1096,37 @@ export class Orchestrator { } try { + // Security: verify that this reminder belongs to this chatId + const listResponse = await this.sendAndWait(cronManager, "cron.schedule.list", {}); + const listPayload = listResponse.payload as { result?: { schedules?: Array<{ id: string; payload: string }> } }; + const schedules = listPayload.result?.schedules ?? []; + const targetSchedule = schedules.find(s => s.id === reminderId); + + if (!targetSchedule) { + this.sendToTelegram(chatId, `😨 Reminder ${reminderId} not found.`); + return; + } + + try { + const payload = JSON.parse(targetSchedule.payload); + if (payload.chatId !== chatId) { + this.sendToTelegram(chatId, `❌ You are not authorized to cancel this reminder.`); + return; + } + } catch (e) { + // If payload is malformed or missing chatId, we might want to prevent deletion or allow it? + // Let's be conservative: if we can't confirm ownership, we reject. + // UNLESS we are superuser (could add later). + this.sendToTelegram(chatId, `❌ Security check failed for reminder ${reminderId}.`); + return; + } + const response = await this.sendAndWait(cronManager, "cron.schedule.remove", { id: reminderId }); const responsePayload = response.payload as { status?: string; result?: { removed?: string } }; if (responsePayload.result?.removed === reminderId) { - this.sendToTelegram(chatId, `🟢 Reminder ${reminderId} has been canceled.`); + this.sendToTelegram(chatId, `🟢 Reminder ${reminderId} has been canceled.`); } else { - this.sendToTelegram(chatId, `😨 Reminder ${reminderId} not found.`); + this.sendToTelegram(chatId, `😨 Reminder ${reminderId} not found.`); } } catch (err) { const message = err instanceof Error ? err.message : String(err); diff --git a/src/services/cron-manager.ts b/src/services/cron-manager.ts index 98e6272..de6dc17 100644 --- a/src/services/cron-manager.ts +++ b/src/services/cron-manager.ts @@ -148,17 +148,19 @@ export class CronManager extends BaseProcess { return id; } - private listSchedules(): Array<{ id: string; cronExpr: string; taskType: string; enabled: boolean }> { - const rows = this.db.prepare("SELECT id, cron_expr, task_type, enabled FROM cron_schedules").all() as Array<{ + private listSchedules(): Array<{ id: string; cronExpr: string; taskType: string; payload: string; enabled: boolean }> { + const rows = this.db.prepare("SELECT id, cron_expr, task_type, payload, enabled FROM cron_schedules").all() as Array<{ id: string; cron_expr: string; task_type: string; + payload: string; enabled: number; }>; return rows.map((r) => ({ id: r.id, cronExpr: r.cron_expr, taskType: r.task_type, + payload: r.payload, enabled: r.enabled === 1, })); }