From 6b733bc9cf76a17caef9ac5d86323869fdd2bf8d Mon Sep 17 00:00:00 2001 From: Dicken Date: Fri, 10 Jul 2026 13:58:30 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20K=C3=B6Pi=20Tages-Cron=20um=2006:00=20U?= =?UTF-8?q?hr=20mit=20Pushover,=20Admin-Testbutton=20zum=20manuellen=20Aus?= =?UTF-8?q?l=C3=B6sen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/tools/koepi/routes.js | 24 +++++++++++++++++++----- frontend/src/tools/koepi.jsx | 17 ++++++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/backend/src/tools/koepi/routes.js b/backend/src/tools/koepi/routes.js index d2a0b53..72845b3 100644 --- a/backend/src/tools/koepi/routes.js +++ b/backend/src/tools/koepi/routes.js @@ -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; diff --git a/frontend/src/tools/koepi.jsx b/frontend/src/tools/koepi.jsx index d95891c..43f15aa 100644 --- a/frontend/src/tools/koepi.jsx +++ b/frontend/src/tools/koepi.jsx @@ -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 (
{/* Header */} @@ -179,7 +189,12 @@ export default function Koepi({ toast }) {
{isAdmin && ( - + <> + + + )}