feat: KöPi Tages-Cron um 06:00 Uhr mit Pushover, Admin-Testbutton zum manuellen Auslösen
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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={clearCache} style={{ ...S.btn('#666666',true), fontSize:10 }}>🗑 Cache leeren</button>
|
||||
<>
|
||||
<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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user