A local bot that monitors the Israeli flight carrier Air Haifa for available flight dates and sends instant Telegram alerts when new flights appear.
| Feature | Detail |
|---|---|
| Strategy pattern | Each carrier is an isolated module — easily add more carriers in the future |
| Playwright scraping | Headless Chromium with stealth mode to bypass basic anti-bot measures |
| Smart deduplication | SHA-256 state hashing → only alerts for genuinely new dates (stores to state.json) |
| Exponential back-off | Survives transient network/Wi-Fi drops without crashing |
| APScheduler | Configurable polling interval; runs immediately on startup |
| Telegram alerts | MarkdownV2 messages with direct booking links to multiple recipients |
| Structured logging | structlog formatted output |
exodus/
├── src/exodus/
│ ├── schemas.py ← Single source of truth for all data contracts
│ ├── config_loader.py ← Parses config.yaml & loads .env tokens
│ ├── main.py ← Entry point + scheduler + back-off
│ ├── core/
│ │ ├── engine.py ← Playwright lifecycle & orchestration
│ │ ├── notifier.py ← Telegram notifications
│ │ └── state_manager.py← Deduplication via state.json
│ └── carriers/
│ ├── base_carrier.py ← Abstract interface (Strategy contract)
│ └── air_haifa.py ← Air Haifa implementation
├── tests/ ← Full test suite (no real browser / Telegram calls)
├── config.yaml ← Main configuration — edit schedule & browser settings here
├── .env ← Telegram secrets (Not in version control)
├── state.json ← Auto-managed deduplication store (created at runtime)
└── pyproject.toml
- Python 3.11+
- uv package manager
uv venv .venv
.venv\Scripts\activate
uv pip sync requirements.txt
uv pip install -e .
playwright install chromiumCopy the example environment file and add your actual Telegram credentials:
cp .env.example .envInside .env, set:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_IDS=1234567,9876543Get your bot token: Message @BotFather on Telegram →
/newbot
Get your chat ID: Message @userinfobot
Edit config.yaml to change scheduler polling frequency and browser settings (like headless mode, timeouts):
scheduler:
poll_interval_minutes: 30
max_retries: 5
backoff_base_seconds: 60
browser:
headless: true
slow_mo_ms: 0
timeout_ms: 30000
state:
file_path: "state.json"
carriers:
- id: "air_haifa"
enabled: true
name: "Air Haifa"
extra:
base_url: "https://airhaifa.com"Make sure your virtual environment is activated, then start the main module:
python -m exodus.mainThe bot will scrape immediately on startup, log its findings to the terminal, notify the Telegram chat IDs of any available flights, and then repeat every poll_interval_minutes.
Note: Tests were currently skipped per project state but can be run with:
pytest -vNo real browser or Telegram token needed — all external interactions are mocked.
| Key | Default | Description |
|---|---|---|
scheduler.poll_interval_minutes |
30 |
How often to scrape |
scheduler.max_retries |
5 |
Retries on network/connection failure |
scheduler.backoff_base_seconds |
60 |
Exponential back-off base logic |
browser.headless |
true |
Set false to watch the browser |
browser.slow_mo_ms |
0 |
Slow down operations for debugging |
browser.timeout_ms |
30000 |
Element visibility wait timeout (ms) |