Push-Erinnerungen: Widget, Backend-Scheduler, Pushover-Versand jede Minute

This commit is contained in:
2026-05-28 19:11:05 +02:00
parent 7ec2879f73
commit ee2b625ed5
3 changed files with 15 additions and 8 deletions

View File

@@ -84,17 +84,20 @@ async function sendPushoverMsg(userKey, appToken, message) {
setInterval(async () => { setInterval(async () => {
try { try {
const now = db.prepare("SELECT datetime('now','localtime') as t").get().t;
const due = db.prepare(` const due = db.prepare(`
SELECT s.*, p.user_key, p.app_token SELECT s.*, p.user_key, p.app_token
FROM push_schedules s FROM push_schedules s
JOIN pushover_settings p ON p.user_id = s.user_id JOIN pushover_settings p ON p.user_id = s.user_id
WHERE s.sent = 0 AND s.scheduled_at <= datetime('now','localtime') WHERE s.sent = 0 AND s.scheduled_at <= ?
`).all(); `).all(now);
for (const row of due) { for (const row of due) {
await sendPushoverMsg(row.user_key, row.app_token, row.message); await sendPushoverMsg(row.user_key, row.app_token, row.message);
db.prepare('UPDATE push_schedules SET sent=1 WHERE id=?').run(row.id); db.prepare('UPDATE push_schedules SET sent=1 WHERE id=?').run(row.id);
console.log(`✓ Push gesendet an user ${row.user_id}: ${row.message}`); console.log(`✓ Push gesendet an user ${row.user_id}: "${row.message}" (fällig: ${row.scheduled_at})`);
} }
} catch(e) { console.error('Push-Job Fehler:', e.message); } } catch(e) { console.error('Push-Job Fehler:', e.message); }
}, 60 * 1000); // jede Minute }, 60 * 1000);
console.log('⏰ Push-Scheduler aktiv (jede Minute)');

View File

@@ -219,10 +219,12 @@ router.get('/push-schedules', authenticate, (req, res) => {
router.post('/push-schedules', authenticate, (req, res) => { router.post('/push-schedules', authenticate, (req, res) => {
const { message, scheduled_at } = req.body; const { message, scheduled_at } = req.body;
if (!message?.trim() || !scheduled_at) return res.status(400).json({ error: 'Nachricht und Zeitpunkt erforderlich' }); if (!message?.trim() || !scheduled_at) return res.status(400).json({ error: 'Nachricht und Zeitpunkt erforderlich' });
// Normalisieren: T→Leerzeichen, Sekunden ergänzen
const normalized = scheduled_at.replace('T',' ') + (scheduled_at.length <= 16 ? ':00' : '');
const r = db.prepare(` const r = db.prepare(`
INSERT INTO push_schedules (user_id, message, scheduled_at, created_at) INSERT INTO push_schedules (user_id, message, scheduled_at, created_at)
VALUES (?, ?, ?, datetime('now','localtime')) VALUES (?, ?, ?, datetime('now','localtime'))
`).run(uid(req), message.trim(), scheduled_at); `).run(uid(req), message.trim(), normalized);
res.json(db.prepare('SELECT * FROM push_schedules WHERE id=?').get(r.lastInsertRowid)); res.json(db.prepare('SELECT * FROM push_schedules WHERE id=?').get(r.lastInsertRowid));
}); });
@@ -230,8 +232,9 @@ router.put('/push-schedules/:id', authenticate, (req, res) => {
const row = db.prepare('SELECT * FROM push_schedules WHERE id=? AND user_id=?').get(req.params.id, uid(req)); const row = db.prepare('SELECT * FROM push_schedules WHERE id=? AND user_id=?').get(req.params.id, uid(req));
if (!row) return res.status(404).json({ error: 'Nicht gefunden' }); if (!row) return res.status(404).json({ error: 'Nicht gefunden' });
const { message, scheduled_at } = req.body; const { message, scheduled_at } = req.body;
const normalized = scheduled_at ? scheduled_at.replace('T',' ') + (scheduled_at.length <= 16 ? ':00' : '') : row.scheduled_at;
db.prepare('UPDATE push_schedules SET message=?, scheduled_at=?, sent=0 WHERE id=?') db.prepare('UPDATE push_schedules SET message=?, scheduled_at=?, sent=0 WHERE id=?')
.run(message ?? row.message, scheduled_at ?? row.scheduled_at, row.id); .run(message ?? row.message, normalized, row.id);
res.json(db.prepare('SELECT * FROM push_schedules WHERE id=?').get(row.id)); res.json(db.prepare('SELECT * FROM push_schedules WHERE id=?').get(row.id));
}); });

View File

@@ -1008,10 +1008,11 @@ function PushScheduler({ toast }) {
api('/tools/nachrichten/pushover').then(d=>setHasPushover(!!(d.user_key&&d.app_token))).catch(()=>{}); api('/tools/nachrichten/pushover').then(d=>setHasPushover(!!(d.user_key&&d.app_token))).catch(()=>{});
}, [isOpen]); }, [isOpen]);
// Vorauswahl: jetzt + 1 Stunde // Vorauswahl: jetzt + 1 Stunde in Lokalzeit
const defaultDt = () => { const defaultDt = () => {
const d = new Date(Date.now() + 60*60*1000); const d = new Date(Date.now() + 60*60*1000);
return d.toISOString().slice(0,16); const p = n => String(n).padStart(2,'0');
return `${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}`;
}; };
const fmtDt = s => { if (!s) return ''; const d = new Date(s.replace(' ','T')); return isNaN(d)?s:d.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}); }; const fmtDt = s => { if (!s) return ''; const d = new Date(s.replace(' ','T')); return isNaN(d)?s:d.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}); };