72 lines
2.8 KiB
Markdown
72 lines
2.8 KiB
Markdown
# Dyżur-bot
|
||
|
||
A telegram bot for managing the cleaning rota in hackerspace.
|
||
Bot offers weekly reminders about cleaning duties as well as on demand informations.
|
||
Backend read the schedule from a Google sheet, store it in local JSON file.
|
||
|
||
## Running
|
||
|
||
Requires `GOOGLE_CREDENTIALS_FILE` (path to a Google service-account key,
|
||
shared as an editor on the sheet), `GOOGLE_SHEETS_ID`, and `BOT_TOKEN` in the
|
||
environment or a `.env` file (see `service.go`/`sheet.go` for optional
|
||
`SHEET_RANGE`, `ROTA_CACHE_PATH`, `SYNC_INTERVAL`). Then:
|
||
|
||
```sh
|
||
go run ./cmd/dyzur-bot
|
||
```
|
||
|
||
The service loads the cached rota, syncs from Google Sheets in the background on
|
||
`SYNC_INTERVAL` (default 30m), and runs the Telegram bot via long polling until
|
||
interrupted (Ctrl-C / SIGTERM).
|
||
|
||
When `SHEET_RANGE` is unset, the bot reads the current year's tab (e.g.
|
||
`2026!A1:G100`), resolved on every sync — so it follows the New Year rollover
|
||
automatically without a restart. A sync that fails, or that returns no duty
|
||
weeks (e.g. a next-year tab that exists but hasn't been filled in yet), keeps
|
||
the last-good cache instead of clearing it; if no sync succeeds for 6h the bot
|
||
logs a loud stale-cache error.
|
||
|
||
> **Run exactly one instance per bot token.** The bot uses long polling
|
||
> (`getUpdates`); two concurrent pollers on the same token make Telegram return
|
||
> HTTP 409 Conflict and updates get dropped. Do not scale this to multiple
|
||
> replicas.
|
||
|
||
### Docker
|
||
|
||
```sh
|
||
docker build -t dyzur-bot .
|
||
docker run --rm --env-file .env -v dyzur-data:/data dyzur-bot
|
||
```
|
||
|
||
The image is a static binary on `distroless` (timezone data is embedded, so
|
||
reminders work without system `tzdata`). The rota cache lives at
|
||
`/data/rota.json` (`ROTA_CACHE_PATH`); mount a volume at `/data` to persist it
|
||
across restarts.
|
||
|
||
### Commands
|
||
|
||
- `/kto_sprzata` — who is on cleaning duty this week.
|
||
- `/sync` — refresh the rota from Google Sheets now (throttled to once per
|
||
minute across the chat to avoid spamming the Sheets API).
|
||
|
||
Any other command is ignored — the bot stays silent instead of replying
|
||
"unknown command".
|
||
|
||
### Reminders
|
||
|
||
If `GROUP_CHAT_ID` is set, the bot posts a weekly duty reminder to that chat.
|
||
Schedule (all optional, with defaults): `REMINDER_WEEKDAY` (default `Monday`),
|
||
`REMINDER_HOUR` (default `9`, 0–23), interpreted in Europe/Warsaw time.
|
||
|
||
On each fire the bot handles three weeks relative to the fire time:
|
||
|
||
- **This week** — announces who is on duty. It never auto-assigns at this point;
|
||
a still-empty week is announced as unstaffed.
|
||
- **One week ahead** — if both slots are empty, it picks the two people with the
|
||
fewest duties (random tie-break), writes their names into the sheet, and
|
||
announces the assignment.
|
||
- **Two weeks ahead** — if both slots are empty, it asks people to volunteer
|
||
before the week is auto-assigned the following week.
|
||
|
||
Leave `GROUP_CHAT_ID` unset to disable reminders.
|