feat: KöPi Tages-Cron um 06:00 Uhr mit Pushover, Admin-Testbutton zum manuellen Auslösen

This commit is contained in:
2026-07-10 13:58:30 +02:00
parent 1900d73490
commit 6b733bc9cf
2 changed files with 35 additions and 6 deletions

View File

@@ -301,24 +301,28 @@ async function sendKoepiPushover(offers) {
}
}
// Wird täglich um 06:00 vom Scheduler in index.js aufgerufen
async function runDailyCheck() {
// Wird täglich um 06:00 vom Scheduler in index.js aufgerufen.
// forceNotify=true (manueller Admin-Test): Pushover wird auch ohne Änderung verschickt.
async function runDailyCheck(forceNotify = false) {
try {
const { offers } = await scrapeMarktguru(true);
const currentSig = offerSignature(offers);
const lastSig = db.prepare('SELECT value FROM admin_settings WHERE key=?').get(KOEPI_SETTINGS_KEY)?.value || '';
const changed = currentSig !== lastSig;
if (currentSig === lastSig) {
if (!changed && !forceNotify) {
console.log('🍺 KöPi-Check: keine Änderungen an den Angeboten.');
return;
return { changed: false, sent: false, offerCount: offers.length };
}
await sendKoepiPushover(offers);
db.prepare('INSERT OR REPLACE INTO admin_settings (key, value) VALUES (?, ?)')
.run(KOEPI_SETTINGS_KEY, currentSig);
console.log(`🍺 KöPi-Check: ${offers.length} Angebot(e) geändert Pushover versendet.`);
console.log(`🍺 KöPi-Check: ${offers.length} Angebot(e)${changed ? ' geändert' : ' (Test, unverändert)'} Pushover versendet.`);
return { changed, sent: true, offerCount: offers.length };
} catch (e) {
console.error('KöPi Tages-Check Fehler:', e.message);
return { error: e.message };
}
}
@@ -339,5 +343,15 @@ router.post('/clear-cache', authenticate, (req, res) => {
res.json({ ok: true });
});
// Manueller Test des Tages-Checks (Admin) — sendet Pushover auch ohne echte Änderung
router.post('/run-daily-check', authenticate, async (req, res) => {
if (req.user?.role !== 'admin') return res.status(403).json({ error: 'Kein Zugriff' });
try {
const result = await runDailyCheck(true);
if (result.error) return res.status(500).json({ error: result.error });
res.json(result);
} catch(e) { res.status(500).json({ error: e.message }); }
});
module.exports = router;
module.exports.runDailyCheck = runDailyCheck;

View File

@@ -170,6 +170,16 @@ export default function Koepi({ toast }) {
} catch(e) { toast?.(e.message,'error'); }
};
const [cronRunning, setCronRunning] = useState(false);
const testDailyCheck = async () => {
setCronRunning(true);
try {
const r = await api('/tools/koepi/run-daily-check', { method:'POST', body:{} });
toast(`🔔 Test: ${r.offerCount} Angebot(e) gefunden, Pushover ${r.sent ? 'versendet' : 'nicht versendet'}${r.changed ? ' (Änderung erkannt)' : ' (unverändert)'}`);
} catch(e) { toast?.(e.message||'Fehler','error'); }
finally { setCronRunning(false); }
};
return (
<div style={{ maxWidth:700, margin:'0 auto' }}>
{/* Header */}
@@ -179,7 +189,12 @@ export default function Koepi({ toast }) {
</h2>
<div style={{ flex:1 }}/>
{isAdmin && (
<>
<button onClick={testDailyCheck} disabled={cronRunning} style={{ ...S.btn('#f59e0b',true), fontSize:10, opacity:cronRunning?0.5:1 }}>
{cronRunning ? '⏳ läuft…' : '🔔 Cron testen'}
</button>
<button onClick={clearCache} style={{ ...S.btn('#666666',true), fontSize:10 }}>🗑 Cache leeren</button>
</>
)}
</div>