# Silmataivas (Rust Version) Silmataivas is a weather monitoring service that sends personalized alerts based on user-defined thresholds and notification preferences. This is the Rust version, providing a RESTful API for managing users, locations, weather thresholds, and notification settings. ## Features - **Weather monitoring using OpenWeatherMap API**: Automatic hourly weather data fetching for all users with locations - **Location-based weather tracking**: Each user can set their location for personalized weather monitoring - **Custom weather thresholds per user**: Define temperature, rain, and wind speed thresholds with custom operators - **Automatic threshold checking**: After fetching weather data, the system automatically checks if any thresholds are exceeded - **Flexible notifications**: NTFY (push) and SMTP (email) notifications when thresholds are exceeded - **User-specific configuration**: Each user has their own settings and thresholds - **RESTful API for all resources**: Complete API for managing users, locations, thresholds, and notifications - **Background task scheduling**: Weather polling runs automatically every hour in the background ## Project Structure - **src/main.rs**: All application logic and API endpoints (no lib.rs, not a library) - **src/**: Modules for users, locations, notifications, weather thresholds, etc. - **migrations/**: SQL migrations for SQLite - **Dockerfile**: For containerized deployment ## Quick Start ### Prerequisites - Rust (see [rustup.rs](https://rustup.rs/)) - SQLite (default, or set `DATABASE_URL` for PostgreSQL) ### Running Locally ```bash # Clone the repository git clone https://codeberg.org/silmataivas/silmataivas.git cd silmataivas # Set required environment variables export OPENWEATHERMAP_API_KEY="your_api_key_here" # Build and run cargo build --release ./target/release/silmataivas ``` The server will: - Listen on port 4000 by default (configurable via `PORT` environment variable) - Use `~/.local/share/silmataivas/silmataivas.db` as the default database location - Create the database directory automatically if it doesn't exist - Generate an admin token automatically if none is provided ### Using Docker ```bash docker build -t silmataivas . docker run -p 4000:4000 \ -e OPENWEATHERMAP_API_KEY="your_api_key_here" \ -e DATABASE_URL="sqlite:///data/silmataivas.db" \ silmataivas ``` ## Weather Polling The application automatically fetches weather data from OpenWeatherMap API every hour for all users who have set their locations. Here's how it works: ### Automatic Weather Data Collection 1. **Hourly Scheduling**: The weather poller runs every hour in the background 2. **Location Rounding**: Coordinates are rounded to 2 decimal places (~1km precision) to reduce API calls for nearby locations 3. **Async Processing**: Each user-location combination is processed in parallel for efficiency 4. **Data Storage**: Weather data is stored in the `weather_api_data` table for future reference ### Threshold Checking After fetching weather data, the system automatically: 1. Checks all enabled thresholds for the user 2. Compares current weather conditions against threshold values 3. Sends notifications (NTFY/SMTP) if thresholds are exceeded 4. Only sends one notification per check to avoid spam ### Manual Weather Check You can manually trigger a weather check for testing: ```bash cargo run -- check-weather ``` ### Environment Variables The application uses the following environment variables for configuration: #### Required - `OPENWEATHERMAP_API_KEY`: Your OpenWeatherMap API key for weather data access #### Optional - `DATABASE_URL`: Database connection string (defaults to XDG_DATA_HOME or ~/.local/share) - `XDG_DATA_HOME`: Custom data directory (defaults to ~/.local/share) - `ADMIN_TOKEN`: Initial admin user token (auto-generated if not set) - `PORT`: Server port (default: 4000) - `HOST`: Server host (default: 0.0.0.0) - `LOG_LEVEL`: Logging level (default: info) #### Database URL Fallback Logic If `DATABASE_URL` is not set, the application will use the following fallback path: 1. `$XDG_DATA_HOME/silmataivas/silmataivas.db` (if XDG_DATA_HOME is set) 2. `~/.local/share/silmataivas/silmataivas.db` (default fallback) The directory will be created automatically if it doesn't exist. #### Example Configuration ```bash # Required export OPENWEATHERMAP_API_KEY="your_api_key_here" # Optional - custom database location export DATABASE_URL="sqlite:///path/to/custom/database.db" # Optional - custom data directory export XDG_DATA_HOME="/custom/data/path" # Optional - server configuration export PORT="8080" export HOST="127.0.0.1" export LOG_LEVEL="debug" ``` ## API Usage All API endpoints (except `/health`) require authentication using a Bearer token: ``` Authorization: Bearer ``` See the source code for endpoint details. (OpenAPI docs are not yet auto-generated in this Rust version.) ## Migration Note This project was previously implemented in Elixir/Phoenix. All Elixir/Phoenix code, references, and setup instructions have been removed. The project is now a Rust binary only (no library, no Elixir code). ## Development - Format: `cargo fmt` - Lint: `cargo clippy` - Test: `cargo test` ## Contributing - Use conventional commits for PRs - See the code for module structure and API details --- For any issues or questions, please open an issue on Codeberg. ## TODO ### โœ… Project Completion Checklist for Weather Monitoring App #### ๐Ÿงฑ Architecture & Code Quality - [ ] Centralized error handling (e.g., `thiserror`, `anyhow`, `IntoResponse`) - [ ] Organize code into service/domain/modules to improve separation of concerns - [ ] Add rate limiting/backoff for OpenWeather API usage - [ ] Write unit tests for core logic (e.g., user CRUD, weather checks) - [ ] Add integration tests for full API endpoints - [ ] Benchmark endpoint latency and cold-start performance #### ๐Ÿ”’ Security - [ ] Ensure proper SQL injection protection (`sqlx` should cover this, but verify inputs) - [ ] Review CORS and CSRF protection for web endpoints - [ ] Validate and sanitize all environment variables at startup - [ ] Secure storage for SMTP/Ntfy credentials (env vars or secret store) #### ๐Ÿ”ญ Observability & Monitoring - [ ] Add `/healthz` and `/metrics` endpoints (e.g., Prometheus) - [ ] Use structured logging (`tracing` spans for request lifecycle) - [ ] Consider log rotation or persistent log storage - [ ] Alerting or notifications if cron job fails #### โš™๏ธ CLI & Deployment - [ ] Build CLI for DB/settings management (with help output and scripting support) - [ ] Implement DB backup or export functionality (even for SQLite) - [ ] Enable SQLite WAL mode and regular vacuuming - [ ] Add install/setup instructions to CLI or README #### ๐Ÿง‘โ€๐Ÿ’ป Web Interface (MVP) - [ ] Add a minimal web UI (htmx, Yew, or static + API) - [ ] Ensure UI is responsive/mobile friendly - [ ] Add form to configure thresholds, ntfy/smtp, location, etc. - [ ] Web UI: Add table or list of current weather rules #### โ˜€๏ธ Weather & Notifications Logic - [ ] Only send notification on threshold **crossing**, not on every cron run - [ ] Allow multiple thresholds per user (e.g., temp < 0ยฐC and wind > 30km/h) - [ ] Store basic history of weather checks (for debugging/trends) - [ ] Abstract weather provider to allow future plug-ins (e.g., Tomorrow.io, Meteomatics) #### ๐Ÿงช Testing & QA - [ ] Add CI test for API correctness (user + notification config CRUD) - [ ] Add e2e test for full flow: create user โ†’ set threshold โ†’ trigger alert - [ ] Add test for OpenAPI schema consistency #### ๐Ÿ“ฆ Open Source Readiness - [ ] Add detailed README with setup, architecture overview, and usage - [ ] Add LICENSE file - [ ] Add `CONTRIBUTING.md` with basic guide - [ ] Add `.env.example` with defaults - [ ] Add changelog or release notes for future versions #### ๐Ÿš€ Final Steps - [ ] Deploy to production server - [ ] Verify Docker Compose deployment with CLI and web UI - [ ] Publish initial release/tag on Codeberg