Files
duty-teller/docs/architecture.md
Nikolay Tatarinov 16bf1a1043 feat: migrate to Next.js for Mini App and enhance project structure
- 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.
2026-03-03 16:04:08 +03:00

3.9 KiB

Architecture

High-level architecture of Duty Teller: components, data flow, and package relationships.

Components

  • Botpython-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 from webapp-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; if DUTY_PIN_NOTIFY is 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 use duty_teller.services (e.g. import, group duty pin) and duty_teller.db (repository, session). Messages use duty_teller.i18n for Russian/English.

  • Miniapp → API
    Browser opens /app; frontend calls GET /api/duties and GET /api/calendar-events with date range. FastAPI dependencies: DB session, Telegram initData validation (require_miniapp_username), date validation. Data is read via duty_teller.db.repository.

  • Import
    Admin sends JSON file via /import_duty_schedule. Handler reads file → duty_teller.importers.duty_schedule.parse_duty_schedule()DutyScheduleResultduty_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}.ics uses 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 services and db, use i18n for user-facing text.
  • api — FastAPI app, dependencies (auth, DB session, date validation), calendar ICS builders; uses db.repository and config.
  • 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 importers for 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.