- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability. - Updated the `.gitignore` to exclude Next.js build artifacts and node modules. - Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack. - Enhanced Dockerfile to support the new build process for the Next.js application. - Updated CI workflow to build and test the Next.js application. - Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking. - Refactored frontend testing setup to accommodate the new structure and testing framework. - Removed legacy webapp files and dependencies to streamline the project.
3.9 KiB
Architecture
High-level architecture of Duty Teller: components, data flow, and package relationships.
Components
- Bot — python-telegram-bot v22 (Application API). Handles commands and group messages; runs in polling mode.
- FastAPI — HTTP server: REST API (
/api/duties,/api/calendar-events,/api/calendar/ical/{token}.ics) and static miniapp at/app(built fromwebapp-next/, Next.js static export). Runs in a separate thread alongside the bot. - Database — SQLAlchemy ORM with Alembic migrations. Default backend: SQLite (
data/duty_teller.db). Stores users, duties (with event types: duty, unavailable, vacation), group duty pins, calendar subscription tokens. - Duty-schedule import — Two-step admin flow: handover time (timezone → UTC), then JSON file. Parser produces per-person date lists; import service deletes existing duties in range and inserts new ones.
- Group duty pin — In groups, the bot can pin the current duty message; time/timezone for the pinned text come from
DUTY_DISPLAY_TZ. Pin state is restored on startup from the database. When the duty changes on schedule, the bot sends a new message, unpins the previous one and pins the new one; ifDUTY_PIN_NOTIFYis enabled (default), pinning the new message triggers a Telegram notification for members. The first pin (bot added to group or/pin_duty) is always silent.
Data flow
-
Telegram → bot
User/group messages → handlers → services or DB. Handlers useduty_teller.services(e.g. import, group duty pin) andduty_teller.db(repository, session). Messages useduty_teller.i18nfor Russian/English. -
Miniapp → API
Browser opens/app; frontend callsGET /api/dutiesandGET /api/calendar-eventswith date range. FastAPI dependencies: DB session, Telegram initData validation (require_miniapp_username), date validation. Data is read viaduty_teller.db.repository. -
Import
Admin sends JSON file via/import_duty_schedule. Handler reads file →duty_teller.importers.duty_schedule.parse_duty_schedule()→DutyScheduleResult→duty_teller.services.import_service.run_import()→ repository (get_or_create_user_by_full_name,delete_duties_in_range,insert_duty). -
Personal calendar ICS
GET /api/calendar/ical/{token}.icsuses the secret token only (no Telegram auth); repository resolves user by token and returns duties;personal_calendar_ics.build_personal_ics()produces ICS bytes.
Package layout
flowchart LR
subgraph entry
main[main.py / duty-teller]
end
subgraph duty_teller
run[run.py]
config[config.py]
handlers[handlers]
api[api]
db[db]
services[services]
importers[importers]
i18n[i18n]
utils[utils]
end
main --> run
run --> config
run --> handlers
run --> api
handlers --> services
handlers --> db
handlers --> i18n
api --> db
api --> config
services --> db
services --> importers
importers --> .
- handlers — Telegram command and message handlers; call
servicesanddb, usei18nfor user-facing text. - api — FastAPI app, dependencies (auth, DB session, date validation), calendar ICS builders; uses
db.repositoryandconfig. - db — Models, session (
session_scope), repository (CRUD for users, duties, pins, calendar tokens), schemas for API. - services — Business logic (import, group duty pin); receive DB session from caller, use
importersfor parsing. - importers — Duty-schedule JSON parser; no DB access, returns structured result.
- i18n — Translations and language detection (ru/en) for bot and API.
- utils — Shared helpers (dates, user, handover).
See Project layout in README for file-level details.