74f487486f
- server.js: catch browser-launch failures inside the injected fetchAndExtractPriceViaBrowser wrapper so they route through checkProduct's normal error classification (recordCheckFailure) instead of escaping as a thrown error that bypasses the DB write. - server.js: add an in-flight guard around runCheck so overlapping callers (cron + check-now) share one run instead of each launching its own Chromium. - Dockerfile: copy only package.json/package-lock.json/node_modules before installing Chromium so the expensive install layer is keyed to dependency changes, not every commit; copy the rest of the app afterward. - Dockerfile: clean up apt package lists after the Playwright install step, matching the build stage's existing cleanup. - README.md: note that exercising the fallback locally (not just running the test suite) needs `npx playwright install chromium`. - README.md: correct the fallback description — domcontentloaded navigation reads the page before most client-side JS finishes, so the fallback mainly helps with HTTP-client blocking, not JS-rendered prices; reworded to drop the inaccurate claim. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013gwc3aCiyQxmCWQke8RvEz
54 lines
2.0 KiB
Markdown
54 lines
2.0 KiB
Markdown
# Korting — prijstracker
|
|
|
|
Houdt een lijst productpagina's dagelijks in de gaten en mailt wanneer
|
|
de prijs verandert.
|
|
|
|
## Lokaal draaien
|
|
|
|
```bash
|
|
npm install
|
|
cp .env.example .env # env vars invullen
|
|
npm test
|
|
npm start
|
|
```
|
|
|
|
De app leest `.env` in via `dotenv`. `BASIC_AUTH_USER`, `BASIC_AUTH_PASS`,
|
|
`SMTP_FROM` en `NOTIFY_EMAIL` zijn verplicht; ontbreken ze, dan stopt de
|
|
app bij het opstarten met een melding.
|
|
|
|
De UI staat achter basic auth (`BASIC_AUTH_USER` / `BASIC_AUTH_PASS`) op
|
|
`http://localhost:3000`.
|
|
|
|
Wil je de headless-browser-fallback ook echt lokaal uitproberen (de
|
|
testsuite gebruikt fakes en heeft hier geen echte browser voor nodig), run
|
|
dan eerst `npx playwright install chromium` om de Chromium-binary te
|
|
downloaden.
|
|
|
|
## Environment variables
|
|
|
|
| Variabele | Omschrijving |
|
|
|---|---|
|
|
| `PORT` | HTTP-poort (default `3000`) |
|
|
| `DB_PATH` | Pad naar het SQLite-bestand (default `./data/korting.db`) |
|
|
| `BASIC_AUTH_USER` / `BASIC_AUTH_PASS` | Login voor de web-UI |
|
|
| `SMTP_HOST` / `SMTP_PORT` / `SMTP_USER` / `SMTP_PASS` | SMTP-server (Postal op `mail.sjoerd.app`) |
|
|
| `SMTP_FROM` | Afzenderadres van de notificatiemails |
|
|
| `NOTIFY_EMAIL` | Ontvangeradres van de notificatiemails |
|
|
|
|
## Hoe het werkt
|
|
|
|
Elke dag om 08:00 (Europe/Amsterdam) doorloopt de app alle producten,
|
|
haalt de huidige prijs op (JSON-LD → meta tags → regex-fallback), en
|
|
stuurt een email als de prijs is veranderd sinds de vorige geslaagde
|
|
check. Een mislukte poging (pagina onbereikbaar, geen prijs gevonden,
|
|
of de mail kon niet verstuurd worden) verandert de opgeslagen prijs
|
|
niet, zodat de volgende dag opnieuw wordt geprobeerd. Via de "Nu
|
|
controleren"-knop in de UI kan dit ook handmatig getriggerd worden.
|
|
|
|
Als het ophalen van de prijs op de gewone manier mislukt (netwerkfout, of
|
|
geen prijs gevonden in de HTML), probeert de app het één keer opnieuw met
|
|
een echte headless-browser (Playwright/Chromium) — nuttig voor pagina's
|
|
die eenvoudige HTTP-clients blokkeren. Geen garantie tegen elke vorm van
|
|
bot-detectie, maar dekt een reëel deel van de gevallen die de gewone
|
|
aanpak mist.
|