1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
# 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 <user_id>
```
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
|