Files
duty-teller/.cursor/rules/project.mdc
Nikolay Tatarinov 37d4226beb chore: update project documentation and configuration files
- Added AGENTS.md for AI agent documentation and maintainers, outlining project structure and conventions.
- Updated CONTRIBUTING.md to specify that all project documentation must be in English, including README and docstrings.
- Enhanced README.md to reference documentation guidelines and the new AGENTS.md file.
- Cleaned up .gitignore by removing unnecessary entries for cursor-related files.
- Introduced new .cursor rules for backend, frontend, project architecture, and testing to standardize development practices.
2026-03-02 20:02:20 +03:00

114 lines
4.9 KiB
Plaintext

---
description: Overall project architecture and context for duty-teller
globs:
- "**"
---
# Project — duty-teller
A Telegram bot for team duty shift calendar management and group reminders,
with a Telegram Mini App (webapp) for calendar visualization.
## Architecture
```
┌──────────────┐ polling ┌──────────────────────┐
│ Telegram │◄────────────►│ python-telegram-bot │
│ Bot API │ │ (handlers/) │
└──────────────┘ └──────────┬───────────┘
┌──────────────┐ HTTP ┌──────────▼───────────┐
│ Telegram │◄────────────►│ FastAPI (api/) │
│ Mini App │ initData │ + static webapp │
│ (webapp/) │ auth └──────────┬───────────┘
└──────────────┘ │
┌──────────▼───────────┐
│ SQLite + SQLAlchemy │
│ (db/) │
└──────────────────────┘
```
- **Bot:** python-telegram-bot v22, async polling mode.
- **API:** FastAPI served by uvicorn in a daemon thread alongside the bot.
- **Database:** SQLite via SQLAlchemy 2.x ORM; Alembic for migrations.
- **Frontend:** Vanilla JS Telegram Mini App at `/app`, no framework.
## Key packages
| Package | Role |
|---------|------|
| `duty_teller/handlers/` | Telegram bot command and message handlers |
| `duty_teller/api/` | FastAPI app, REST endpoints, Telegram initData auth, ICS feeds |
| `duty_teller/db/` | ORM models, repository (CRUD), session management, Pydantic schemas |
| `duty_teller/services/` | Business logic (import, duty pin) — receives Session |
| `duty_teller/importers/` | Duty schedule file parsers |
| `duty_teller/i18n/` | Bilingual translations (ru/en), `t()` function |
| `duty_teller/utils/` | Date helpers, user utilities, HTTP client |
| `duty_teller/cache.py` | TTL caches with pattern-based invalidation |
| `duty_teller/config.py` | Environment-based configuration |
| `webapp/` | Telegram Mini App (HTML + JS + CSS) |
## API endpoints
| Method | Path | Auth | Purpose |
|--------|------|------|---------|
| GET | `/health` | None | Health check |
| GET | `/api/duties` | initData | Duties for date range |
| GET | `/api/calendar-events` | initData | External calendar events |
| GET | `/api/calendar/ical/team/{token}.ics` | Token | Team ICS feed |
| GET | `/api/calendar/ical/{token}.ics` | Token | Personal ICS feed |
| GET | `/app` | None | Static Mini App (HTML/JS/CSS) |
## Deployment
- **Docker:** Multi-stage build (`Dockerfile`), `docker-compose.prod.yml` for production.
- **Entrypoint:** `entrypoint.sh` runs `alembic -c pyproject.toml upgrade head`, then
starts `python main.py` as `botuser`.
- **Data:** SQLite DB persisted via Docker volume at `/app/data`.
- **Health:** `curl -f http://localhost:8080/health` every 30 s.
## CI/CD (Gitea Actions)
### Lint & test (`.gitea/workflows/ci.yml`)
Triggered on push/PR to `main` and `develop`:
1. **Ruff:** `ruff check duty_teller tests`
2. **Pytest:** `pytest tests/ -v` (80% coverage gate)
3. **Bandit:** `bandit -r duty_teller -ll` (security scan)
### Docker build & release (`.gitea/workflows/docker-build.yml`)
Triggered on `v*` tags:
1. Build and push image to Gitea registry.
2. Create release with auto-generated notes.
## Key environment variables
| Variable | Default | Required | Purpose |
|----------|---------|----------|---------|
| `BOT_TOKEN` | — | Yes | Telegram bot API token |
| `DATABASE_URL` | `sqlite:///data/duty_teller.db` | No | SQLAlchemy database URL |
| `MINI_APP_BASE_URL` | — | Yes (prod) | Public URL for the Mini App |
| `HTTP_HOST` | `127.0.0.1` | No | FastAPI bind host |
| `HTTP_PORT` | `8080` | No | FastAPI bind port |
| `ADMIN_USERNAMES` | — | No | Comma-separated admin Telegram usernames |
| `ALLOWED_USERNAMES` | — | No | Comma-separated allowed usernames |
| `DUTY_DISPLAY_TZ` | `Europe/Moscow` | No | Timezone for duty display |
| `DEFAULT_LANGUAGE` | `en` | No | Default UI language (`en` or `ru`) |
| `EXTERNAL_CALENDAR_ICS_URL` | — | No | External ICS URL for holidays |
| `CORS_ORIGINS` | `*` | No | Comma-separated CORS origins |
## Languages
- **Backend:** Python 3.12+
- **Frontend:** Vanilla JavaScript (ES modules, no bundler)
- **i18n:** Russian (default) and English
## Version control
- Git with Gitea Flow branching strategy.
- Conventional Commits for commit messages.
- PRs reviewed via Gitea Pull Requests.