- Go 96.9%
- Shell 2%
- Just 0.6%
- Dockerfile 0.5%
|
|
||
|---|---|---|
| .gitea/workflows | ||
| .githooks | ||
| .github | ||
| cmd/bot | ||
| internal | ||
| scripts | ||
| .air.toml | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .golangci.yml | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| Justfile | ||
| LICENSE | ||
| README.en.md | ||
| README.md | ||
ktk-schedule
English
Telegram bot for the KTK workspace. Authenticates users, stores credentials in encrypted SQLite, renders schedules directly in Telegram, and sends morning notifications.
Built for daily production use: HTTP timeouts, retry wrappers, rate limiting, circuit breaker, persistent cache, Docker health checks, graceful shutdown.
Features
| Area | What it does |
|---|---|
| Schedule | Week view, specific dates, today, week switching, day selection |
| Groups | Personal group, other group, subgroup selection, both subgroups mode |
| Teachers | Teacher sign-in and schedule retrieval |
| Academic data | Lesson time, room, type, current status, grades, attendance |
| Files | Homework attachments, uploaded files, day-based download |
| Notifications | Morning schedule delivery via NOTIFY_TIME and TIMEZONE |
| Reliability | Bounded HTTP reads, retries, rate limiting, circuit breaker, cache |
| Operations | /health, /health/extended, optional /debug/pprof, Docker, Forgejo CI/CD |
| Security | AES-GCM password storage, private /login, .env secrets, SQLite WAL |
Quick Start
cp .env.example .env
Minimum required variables:
BOT_TOKEN=123456:your-token-from-botfather
CREDENTIALS_SECRET=random-string-at-least-32-characters
Generate a secret:
openssl rand -base64 32
Run locally:
go run ./cmd/bot
Run with Docker:
docker compose up --build -d
docker compose logs -f
Bot Commands
| Command | Purpose |
|---|---|
/start |
Show available commands |
/my_id |
Show your Telegram ID |
/login username password |
Sign in to the workspace |
/schedule |
Open the current week schedule |
/schedule 01.09 |
Schedule for a date in the current academic year |
/schedule 2026-09-01 |
Schedule for an exact date |
/notify_on / /notify_off |
Enable or disable morning notifications |
/announce text |
Send an owner announcement to all users |
reply /announce |
Broadcast the replied-to message |
/stats |
Show bot statistics (owner only) |
/login deletes the user message immediately after receipt — credentials never stay in the chat.
Schedule Output
📅 01.06.2026
1 пара [70 мин] — ОП.12 ИКГ
⏰ 08:00-09:10
🔬 Практическое занятие
👤 Бухтоярова Елена Леонидовна
🏫 Кабинет: 301
2 пара [70 мин] — ОП.02 ДМЭМЛ
⏰ 09:20-10:30
📚 Лекция
👤 Сапожникова Елена Владимировна
🏫 Кабинет: 41
After /schedule, inline navigation is available for days, weeks, files, groups, and subgroups.
Architecture
flowchart LR
T[Telegram] --> A[internal/app]
A --> K[internal/ktk]
A --> S[internal/storage]
A --> TG[internal/tg]
S --> C[internal/credentials]
K --> W[Workspace API]
S --> DB[(SQLite)]
A --> H[/health/]
| Path | Responsibility |
|---|---|
cmd/bot |
Entry point, config loading, logging, graceful shutdown |
internal/app |
Telegram handlers, sessions, notifications, cache, rate limit, health server |
internal/ktk |
Workspace client, parsing, formatting, files, endpoint discovery |
internal/storage |
SQLite, migrations, users, encrypted credentials, schedule cache |
internal/credentials |
AES-GCM encryption and legacy plaintext migration |
internal/config |
.env loading and validation |
internal/tg |
Inline keyboards and compact callback payloads |
.gitea/workflows |
CI/CD, image build, deploy, backup, rollback |
Package boundaries are intentional: Telegram orchestration in internal/app, workspace logic in internal/ktk, persistence in internal/storage.
Configuration
All variables are documented in .env.example. Required:
| Variable | Description |
|---|---|
BOT_TOKEN |
Telegram bot token from @BotFather |
CREDENTIALS_SECRET |
AES-GCM secret, at least 32 characters |
OWNER_TELEGRAM_ID |
Owner Telegram ID for /announce and /stats |
KTK_BASE_URL |
Workspace base URL (default https://workspace.ktk-45.ru) |
KTK_DEVICE_NAME |
Device name sent with sign-in requests |
DEFAULT_GROUP_ID |
Default group after first sign-in |
DEFAULT_SUBGROUP |
Default subgroup: 1 or 2 |
NOTIFY_TIME |
Morning notification time, HH:MM format |
TIMEZONE |
Time zone, e.g. Asia/Yekaterinburg |
DATABASE_PATH |
Path to the SQLite file |
HEALTH_ADDR |
Health server address, default 127.0.0.1:8080 |
PPROF_ENABLED |
Enable /debug/pprof on the health server |
Development
Required: Go 1.26.4+, just, golangci-lint, govulncheck. Hot reload uses air.
just setup # configure .githooks
just setup-air # install air
just setup-lint # install golangci-lint
just setup-vuln # install govulncheck
Common commands:
just dev # hot reload (air)
just run # run normally
just test # go test -count=1 ./...
just race # tests with -race
just lint # golangci-lint run
just vuln # govulncheck ./...
just build # build ./ktk-schedule
just check # full local verification before handoff
just ci-check # CI-level verification
just backup # backup SQLite from Docker volume
just clean # remove binary, database, and logs
Operations
Docker Compose starts the service with a persistent SQLite volume:
docker compose up --build -d
docker compose logs -f
Health endpoints:
| Endpoint | Purpose |
|---|---|
/health |
Basic process health check |
/health/extended |
Extended diagnostics |
/debug/pprof |
Profiling, only when PPROF_ENABLED=true |
Do not expose the health server or pprof publicly without access control.
Forgejo CI/CD runs quality checks, builds the Docker image, publishes it to the registry, and deploys to the VDS. A compressed SQLite backup is created before deployment; if the new container fails health checks, the pipeline attempts a rollback to the previous image.