# Drivers Bot Telegram bot + Telegram Mini App для учета автомобилей, заправок, сервиса, жидкостей, напоминаний и стоимости владения. ## Состав - `app/` - FastAPI API, статика Mini App, бизнес-логика и Alembic. - `bot/` - aiogram 3 бот, который открывает Mini App и работает с API через внутренний токен. - `web/` - статический frontend Telegram WebApp. - `alembic/` - миграции PostgreSQL. - `tests/` - базовые security/API тесты. ## Production Mini App Для production Mini App должен открываться только по публичному HTTPS-домену. Для текущего проекта: ```text https://drivers.smartsoltech.kr ``` В BotFather нужно выполнить: ```text /setdomain @your_bot_username drivers.smartsoltech.kr ``` Важно: - в BotFather указывается домен без `https://`; - `WEBAPP_URL` или `PUBLIC_WEBAPP_URL` в `.env` должны быть `https://drivers.smartsoltech.kr`; - нельзя использовать `localhost`, `127.0.0.1`, внутренний IP или `http://` для Telegram Mini App в production; - если появляется `Bot domain invalid`, сначала проверь `/setdomain` и значение `WEBAPP_URL` в контейнере бота. ## Production .env ```dotenv POSTGRES_DB=drivers POSTGRES_USER=drivers POSTGRES_PASSWORD=change-this-db-password POSTGRES_PORT=5433 DATABASE_URL=postgresql+asyncpg://drivers:change-this-db-password@db:5432/drivers BOT_TOKEN=123456:telegram-token BOT_USERNAME=your_bot_username WEBAPP_URL=https://drivers.smartsoltech.kr PUBLIC_WEBAPP_URL=https://drivers.smartsoltech.kr API_BASE_URL=http://api:8000 CORS_ORIGINS=https://drivers.smartsoltech.kr,https://t.me INTERNAL_API_TOKEN=change-this-long-random-token APP_ENV=production ALLOW_DEV_AUTH=false VAPID_PUBLIC_KEY= ``` `BOT_TOKEN`, `DATABASE_URL`, `WEBAPP_URL`, `API_BASE_URL`, `CORS_ORIGINS`, `INTERNAL_API_TOKEN` читаются только из env. Секреты не хранятся в коде. ## Nginx Пример reverse proxy: ```nginx server { listen 80; server_name drivers.smartsoltech.kr; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name drivers.smartsoltech.kr; ssl_certificate /etc/letsencrypt/live/drivers.smartsoltech.kr/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/drivers.smartsoltech.kr/privkey.pem; location / { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; } } ``` ## Запуск ```bash cp .env.example .env docker compose up -d --build ``` API локально: `http://localhost:8000`. Локальные проверки: ```bash python3 -m venv .venv .venv/bin/pip install -e ".[dev]" .venv/bin/pytest -q .venv/bin/ruff check app bot tests docker compose build docker compose up -d db api curl http://127.0.0.1:8000/health docker compose down ``` ## Авторизация API Пользовательские endpoint-ы требуют Telegram WebApp `initData` в заголовке: ```http X-Telegram-Init-Data: query_id=...&user=...&auth_date=...&hash=... ``` Backend проверяет подпись Telegram, создает/обновляет пользователя и разрешает операции только с объектами владельца. Бот использует `INTERNAL_API_TOKEN` и `X-Telegram-User-Id`. Публичное `/api/users` закрыто внутренним токеном. Для Mini App создание пользователя выполняется через `/api/users/webapp-auth`. ## Основные endpoint-ы - `GET /api/users/me` - `GET /api/me` - `GET /api/my/vehicles` - `POST /api/my/vehicles` - `PATCH /api/my/vehicles/{vehicle_id}` - `GET /api/my/vehicles/{vehicle_id}/service-history` - `POST /api/my/vehicles/{vehicle_id}/grant-service-access` - `POST /api/cars`, `GET /api/cars`, `GET/PATCH/DELETE /api/cars/{id}` - `POST /api/fuel`, `GET /api/cars/{car_id}/fuel?limit=50&offset=0` - `PATCH /api/fuel/{id}`, `DELETE /api/fuel/{id}` - `POST /api/service`, `GET /api/cars/{car_id}/service?limit=50&offset=0` - `PATCH /api/service/{id}`, `DELETE /api/service/{id}` - `GET /api/cars/{car_id}/stats` - `GET /api/users/{user_id}/reminders?limit=50&offset=0` - `POST /api/service-centers` - `GET /api/service-centers/my` - `POST /api/service-centers/{id}/verification` - `POST /api/service-centers/{id}/employees/invite` - `GET /api/service-centers/{id}/visits` - `POST /api/service-centers/{id}/visits` - `POST /api/service-visits/{id}/work-items` - `POST /api/service-visits/{id}/complete` - `POST /api/service-visits/{id}/confirm` - `POST /api/service-visits/{id}/dispute` - `POST /api/service-visits/{id}/vehicle-change-requests` - `POST /api/vehicle-change-requests/{id}/approve` - `POST /api/vehicle-change-requests/{id}/reject` - `GET /api/admin/service-centers/pending` - `POST /api/admin/service-centers/{id}/verify` - `POST /api/admin/service-centers/{id}/reject` - `POST /api/admin/service-centers/{id}/suspend` - `GET /api/admin/audit-log` - `GET /api/admin/disputes` - `POST /api/ocr/parse-text-receipt` - `POST /api/ocr/license-plate` - `POST /api/ocr/vin` - `POST /api/ocr/service-document` - `GET /api/me/achievements` - `GET /api/my/vehicles/{vehicle_id}/score` - `GET /api/my/vehicles/{vehicle_id}/timeline` - `GET /api/service-centers/{service_center_id}/trust-score` CarPass quality and trust scores are backend-owned. The scoring engine in `app/services/scoring.py` calculates vehicle profile completeness, verified maintenance history, maintenance health, service-center trust, evidence-style achievements, and cooldown-protected engagement events. Frontend only displays the result. Расход топлива считается по интервалам между полными баками (`is_full_tank=true`). Если данных мало, API возвращает `null`, а не выдуманную цифру. ## OCR Настоящий OCR по фото/PDF пока не подключен. Endpoint `POST /api/ocr/parse-text-receipt` честно разбирает только текстовый чек. Старый `/api/ocr/fuel-receipt` оставлен как deprecated-совместимость. Новая OCR-архитектура использует заменяемый provider: - `OCRProvider` - `StubOCRProvider` - будущие `TesseractOCRProvider`, cloud OCR или VLM provider OCR возвращает кандидаты и не меняет данные автомобиля напрямую: ```json { "recognized_text": "VIN KMHCT41BAHU123456", "candidates": [ {"type": "vin", "value": "KMHCT41BAHU123456", "confidence": 0.84} ] } ``` ## Platform Roadmap Проектное расширение в сторону владельцев авто и СТО описано в `PROJECT_PLAN.md`. В код добавлен первый совместимый слой платформы: - расширенный `ServiceCenter`; - верификация СТО; - сотрудники СТО; - `VehicleAccess`; - `ServiceVisit`; - `ServiceWorkItem`; - `VehicleDataChangeRequest`; - `AuditLog`; - нормализация VIN и госномера. СТО не получает персональные данные владельца по VIN/номеру. Поиск возвращает только минимальную маскированную карточку и пишет действие в аудит. Критичные изменения автомобиля проходят через запрос подтверждения владельцем.