OLX Price Tracker - A Rust CLI tool for tracking OLX.pt listings and alerting on deals.
- Language: Rust (edition 2024, MSRV 1.85)
- Async Runtime: Tokio
- HTTP Client: Reqwest with socks proxy support
- Database: SQLite via rusqlite
- CLI: Clap with derive macros
- Logging: Tracing
src/
βββ main.rs # CLI entry point (~335 lines)
βββ lib.rs # Library exports
βββ config.rs # TOML config parsing
βββ commands/ # CLI command handlers
β βββ mod.rs # Exports
β βββ add.rs # Add search command
β βββ list.rs # List searches command
β βββ run.rs # Run & daemon commands
β βββ deals.rs # Show deals command
β βββ stats.rs # Show stats command
β βββ remove.rs # Remove search command
β βββ toggle.rs # Toggle search command
β βββ search.rs # Quick search command
βββ db/ # SQLite database layer
β βββ mod.rs # Database struct
β βββ schema.rs # Migrations
β βββ queries.rs # CRUD operations
βββ api/ # OLX API client
β βββ mod.rs # Exports
β βββ client.rs # HTTP client (88.9% test coverage)
β βββ models.rs # Response types
βββ tracker/ # Core business logic
β βββ mod.rs # Tracker exports
β βββ search.rs # Search execution
β βββ price.rs # Deal detection (100% test coverage)
βββ filters/ # Extensible filter system
β βββ mod.rs # Filter trait (100% test coverage)
β βββ keyword.rs # Keyword matching
β βββ price.rs # Price filtering
β βββ radius.rs # Location filtering (100% test coverage)
βββ format/ # Output formatting
β βββ mod.rs # Table/JSON/Markdown formatters
βββ notify/ # Notifications
β βββ mod.rs # Multi-notifier (100% test coverage)
β βββ discord.rs # Discord webhooks
β βββ webhook.rs # Generic webhooks
βββ server/ # HTTP API server
βββ mod.rs # Server setup
βββ auth.rs # API key authentication (100% test coverage)
βββ daemon.rs # Background daemon
βββ error.rs # Error responses (100% test coverage)
βββ handlers.rs # HTTP handlers
βββ models.rs # Request/response models
βββ routes.rs # Route definitions
βββ state.rs # Application state
unsafe_code = "forbid"- No unsafe code allowed- Clippy pedantic + nursery enabled
- Run
cargo clippy --all-targetsbefore committing
- Use
cargo fmtbefore committing - Max line width: 100 chars
- Edition 2024 style
- Use
anyhow::Resultfor application errors - Use
thiserrorfor library error types - Always provide context with
.context()or.with_context()
- Single-threaded runtime (rusqlite is not thread-safe)
- Futures don't need to be
Send - Use
tokio::time::sleepfor delays
- Unit tests in same file with
#[cfg(test)]module - Run
cargo testbefore committing - HTTP mocking with
wiremockfor API client tests - All tests use mocks - NO real OLX API calls
- Current coverage: 65.4% overall, 201 tests passing
- High-coverage modules: api/client (88.9%), db/queries (100%), filters (100%)
- Integration tests would go in
tests/directory
Run coverage report:
cargo install cargo-tarpaulin # One-time install
cargo tarpaulin --out Stdout --engine llvm# Development
cargo build # Debug build
cargo build --release # Release build
# Quality Checks (run these before committing)
cargo fmt # Format code
cargo clippy --all-targets # Run linter (catch common mistakes and enforce style)
cargo test # Run all tests
cargo test --lib # Run only library tests (faster)
# Running
./target/release/olx-tracker --help
./target/release/olx-tracker list
./target/release/olx-tracker runALWAYS run these three commands at the end of ANY significant task:
# 1. Format code (fixes style automatically)
cargo fmt
# 2. Check lints (must have 0 warnings for CI)
cargo clippy --all-targets
# 3. Run tests (must all pass)
cargo testWhy this matters:
- CI runs with
RUSTFLAGS="-Dwarnings"which treats warnings as errors - Formatting issues will fail the CI format check
- Broken tests block merging to main
- Running these locally catches issues before pushing
When to run:
- After writing new code
- After refactoring
- Before committing
- After resolving merge conflicts
- At the end of any development session
CRITICAL: Always run format, clippy, and tests before committing!
Before committing changes, always run:
# 1. Format code (auto-fixes style issues)
cargo fmt
# 2. Check lints (MUST have 0 warnings - CI treats warnings as errors)
cargo clippy --all-targets
# 3. Run tests (MUST all pass)
cargo test
# 4. Build release (optional, ensures release build works)
cargo build --releaseVerification: All three must succeed with no errors or warnings. CI will fail if any of these fail locally.
- Create
src/filters/my_filter.rs - Implement the
Filtertrait - Export in
src/filters/mod.rs - Add to
FilterChain::with_defaults()if needed
- Create
src/notify/my_notifier.rs - Implement the
Notifiertrait (async_trait) - Export in
src/notify/mod.rs
- Add variant to
Commandsenum inmain.rs - Create
src/commands/my_command.rswithcmd_my_command()function - Export in
src/commands/mod.rs - Add match arm in
main.rscallingcommands::cmd_my_command()
- SQLite file: configurable via
--dbflag orOLX_TRACKER_DBenv - Default:
olx_tracker.dbin current directory - Migrations run automatically on startup
- Schema version tracked in
schema_versiontable
Required: config.toml with bearer token from OLX (get from browser DevTools).
See config.example.toml for all options.
- Axum-based HTTP API exposing all CLI functionality
- API key authentication via headers
- Background daemon support (starts/stops within server process)
- Request timeout configuration
- JSON request/response format
- See README.md for endpoint documentation
- Quick search (no database, instant results)
- Tracked searches (saved to SQLite)
- Multi-country support (pt, pl, ua, ro, bg, kz, uz)
- City + radius filtering with auto-lookup
- Price range filtering (min/max)
- Search TTL (auto-expire after N days)
- Sort orders: newest, cheapest, expensive, relevance
- Table (CLI default, pretty-printed)
- JSON (includes images array, for APIs/scripts)
- Markdown (includes images, optimized for LLMs)
- Threshold-based: X% below average price
- Target price: Any listing at/below specified price
- Per-search max price override
- Smart filtering with FilterChain
- Discord webhooks (rich embeds)
- Generic webhooks (JSON payload)
- Configurable per event type (new listings, price drops, deals)
- SOCKS5 and HTTP proxies
- Credential masking in logs for security
- Per-request configuration
- Prefer well-maintained crates with minimal transitive deps
- Use
default-features = falsewhen possible - Keep deps up to date:
cargo upgrade - Check for security issues:
cargo audit(install withcargo install cargo-audit)
wiremock- HTTP mock server for API client teststokio-test- Async test utilitiestempfile- Temporary file/directory creation for teststower- Testing utilities for HTTP serviceshttp-body-util- HTTP body utilities for testing