# 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.