Files
vixtix/scripts/send-reminders.ts
Victor 4b8d75617b feat: add reminder system with cron scheduler and fix timezone formatting
- Add reminders to Prisma schema (Reminder model, TaskReminder relation)
- Add /api/reminders endpoint and cron send-reminders.ts script
- Add reminder fields to NewTaskModal and EditTaskModal components
- Fix reminder datetime serialization: use toISOString().slice(0,16) for
  UTC-safe YYYY-MM-DDTHH:mm format compatible with datetime-local inputs
- Update Dockerfile to install tsx for cron container
- Add AGENTS.md with project conventions
- Update docker-compose.yml with cron service and build context
2026-05-09 01:57:49 +00:00

91 lines
2.2 KiB
TypeScript

// @ts-nocheck
import { PrismaClient } from '../src/generated/prisma/client';
const prisma = new PrismaClient();
const MATTERMOST_WEBHOOK_URL = process.env.MATTERMOST_WEBHOOK_URL;
if (!MATTERMOST_WEBHOOK_URL) {
console.error('MATTERMOST_WEBHOOK_URL is not set');
process.exit(1);
}
async function sendToMattermost(message: string): Promise<boolean> {
try {
const payload = {
text: `⏰ Reminder: ${message}`,
};
const response = await fetch(MATTERMOST_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) {
console.error(`Mattermost webhook failed: ${response.status} ${response.statusText}`);
return false;
}
console.log(`Sent reminder to Mattermost: ${message}`);
return true;
} catch (error) {
console.error('Error sending to Mattermost:', error);
return false;
}
}
async function main() {
const now = new Date();
console.log(`Checking for due reminders at ${now.toISOString()}...`);
// 1. Find unsent standalone reminders that are due
const dueReminders = await prisma.reminder.findMany({
where: {
sent: false,
dueDate: { lte: now },
},
orderBy: { dueDate: 'asc' },
});
for (const reminder of dueReminders) {
const sent = await sendToMattermost(reminder.message);
if (sent) {
await prisma.reminder.update({
where: { id: reminder.id },
data: { sent: true },
});
}
}
// 2. Find unsent task reminders that are due
const dueTaskReminders = await prisma.taskReminder.findMany({
where: {
sent: false,
reminder: { lte: now },
},
orderBy: { reminder: 'asc' },
include: { task: true },
});
for (const tr of dueTaskReminders) {
const message = `[${tr.task.title}]${tr.task.description ? ` - ${tr.task.description}` : ''}`;
const sent = await sendToMattermost(message);
if (sent) {
await prisma.taskReminder.update({
where: { id: tr.id },
data: { sent: true },
});
}
}
await prisma.$disconnect();
console.log('Done.');
}
main().catch((error) => {
console.error('Cron worker error:', error);
prisma.$disconnect();
process.exit(1);
});