131 lines
5.5 KiB
Markdown
131 lines
5.5 KiB
Markdown
# willhaben-tracker
|
||
|
||
Telegram bot that monitors classified ads on [willhaben.at](https://www.willhaben.at) and notifies you about new listings matching your keywords, plus price drops on tracked ads. Notifications include photos when available.
|
||
|
||
## Prerequisites
|
||
|
||
- Docker
|
||
- Docker Compose (v2.x)
|
||
|
||
## Quick Start
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
# Edit .env with your bot token and database credentials
|
||
docker compose up -d --build
|
||
```
|
||
|
||
## Deploy on Tizona (NAS)
|
||
|
||
Copy-paste these commands from your local machine:
|
||
|
||
```bash
|
||
# 1. Clone repo on tizona (run as root via SSH)
|
||
ssh tizona "mkdir -p /mnt/user/appdata && rm -rf /mnt/user/appdata/willhaben-tracker"
|
||
ssh tizona "git clone https://git.lago.dev/Lago/willhaben-tracker.git /mnt/user/appdata/willhaben-tracker"
|
||
|
||
# 2. Copy .env (must exist locally)
|
||
scp .env tizona:/mnt/user/appdata/willhaben-tracker/.env
|
||
|
||
# 3. Start stack on tizona
|
||
ssh tizona "cd /mnt/user/appdata/willhaben-tracker && docker compose up -d --build"
|
||
|
||
# 4. Verify everything is running
|
||
ssh tizona "cd /mnt/user/appdata/willhaben-tracker && docker compose ps"
|
||
```
|
||
|
||
### Update (pull + rebuild)
|
||
|
||
```bash
|
||
ssh tizona "cd /mnt/user/appdata/willhaben-tracker && \
|
||
git pull origin main && \
|
||
docker compose build worker --no-cache && \
|
||
docker compose up -d"
|
||
```
|
||
|
||
### Full reset (wipe data, keep schema)
|
||
|
||
```bash
|
||
ssh tizona "cd /mnt/user/appdata/willhaben-tracker && \
|
||
docker compose down && \
|
||
rm -rf data/db && mkdir -p data/db && \
|
||
docker compose up -d --build"
|
||
```
|
||
|
||
### Backup & Restore
|
||
|
||
```bash
|
||
# Dump database
|
||
ssh tizona "docker compose exec db pg_dump -U postgres postgres" > backup_$(date +%F).sql
|
||
|
||
# Restore
|
||
cat backup_2024-01-01.sql | ssh tizona "cd /mnt/user/appdata/willhaben-tracker && docker compose exec -T db psql -U postgres postgres"
|
||
```
|
||
|
||
### Troubleshooting
|
||
|
||
| Problem | Fix |
|
||
|---------|-----|
|
||
| `role "supabase_admin" does not exist` in Studio | Full reset (wipes data, re-runs init scripts) |
|
||
| Migrations didn't run on new tables | `data/db/` had stale data — delete it and restart |
|
||
| Worker crashes with `UndefinedTableError` | Docker image was built before migration commit — force rebuild: `docker compose build worker --no-cache && docker compose up -d` |
|
||
| Studio shows "unhealthy" but APIs work | Cosmetic health check issue — ignore unless you can't browse tables |
|
||
|
||
## Configuration
|
||
|
||
Edit `.env` before first startup. All values are read by the worker and database services.
|
||
|
||
| Variable | Description | Default |
|
||
|---------------------------|----------------------------------------------------|--------------------------------|
|
||
| `TELEGRAM_BOT_TOKEN` | Token from @BotFather | (required) |
|
||
| `POSTGRES_USER` | PostgreSQL username | `postgres` |
|
||
| `POSTGRES_PASSWORD` | PostgreSQL password | (required) |
|
||
| `POSTGRES_DB` | Database name | `postgres` |
|
||
| `JWT_SECRET` | PostgREST JWT signing key | auto-generated default |
|
||
| `DEFAULT_INTERVAL_MINUTES`| Default scrape interval per keyword | `5` |
|
||
|
||
## Architecture
|
||
|
||
| Service | Image | Port | Purpose |
|
||
|----------|------------------------------------|-------|----------------------------------|
|
||
| db | postgres:15-alpine | 55632 | PostgreSQL database |
|
||
| rest | postgrest/postgrest:v12.2.0 | — | REST API over the database |
|
||
| kong | kong:2.8.1 | 55621 | Reverse proxy / gateway |
|
||
| studio | supabase/studio | 55630 | Supabase Studio admin UI |
|
||
| meta | supabase/postgres-meta:v0.84.2 | — | Database metadata service |
|
||
| worker | (built from ./worker) | — | Scraper + Telegram bot |
|
||
|
||
## Telegram Bot UI
|
||
|
||
All users must be whitelisted before use. The bot uses **inline keyboards** (buttons) instead of text commands for a clean experience. Times are shown in **Vienna timezone**.
|
||
|
||
### Commands (global menu, appears when you type `/`)
|
||
|
||
| Command | Access | Description |
|
||
|---------|--------|-------------|
|
||
| `/start` | Anyone | Open main menu |
|
||
| `/admin` | Admin only | Open admin panel |
|
||
|
||
### Main Menu (`/start`)
|
||
|
||
Tap one of the buttons:
|
||
|
||
- **➕ Add Keyword** → Bot asks for keyword text → Shows confirmation with Yes/No
|
||
- **📋 My Keywords** → Sends a formatted card per keyword with status, interval (Vienna tz), last scrape, subscriber count. Each card has action buttons:
|
||
- `⏸ Stop` / `▶ Start` — Toggle active state
|
||
- `✏️ Edit` — Submenu to change name or interval
|
||
- Change Name: type new name → confirm Yes/No → in-place update
|
||
- Change Interval: preset buttons (1m, 3m, 5m, 10m, 30m, 60m) or ⌨️ Custom
|
||
- `🗑 Remove` — Confirm Yes/No → deletes subscription
|
||
- **📊 Stats** — Keywords count, ads indexed, notifications sent
|
||
|
||
### Admin Panel (`/admin`)
|
||
|
||
- **➕ Add User** — Enter Telegram ID → adds user
|
||
- **👥 List Users** — Shows all users with status icons and admin badges
|
||
- **🗑 Remove User** — Enter Telegram ID → removes user
|
||
|
||
## Default Admin
|
||
|
||
On first boot, Telegram ID `298181113` is seeded as an admin user. Add additional admins via the `/admin` panel.
|