# Alpinbet Signals Platform Платформа для сбора, обработки и доставки сигналов Alpinbet. ## Состав проекта - `backend/` — Express + Prisma API, авторизация, сигналы, push, админские маршруты. - `frontend/` — Nuxt-клиент, лента сигналов, настройки, PWA/mobile shell. - `parser/` — парсер Alpinbet, который читает HTML, извлекает сигналы и синхронизирует их в PostgreSQL. - `forecast-ocr-service/` — OCR-сервис для распознавания прогноза с изображения. - `traefik/` — reverse proxy, TLS и роутинг доменов. - `docker-compose.yml` — основной способ запуска. ## Как это работает 1. `parser` получает страницы Alpinbet через сохраненную сессию. 2. Из HTML извлекаются сигналы, коэффициенты, команды и изображения прогноза. 3. Если у сигнала есть картинка прогноза, `parser` скачивает ее и отправляет multipart-запросом в `forecast-ocr-service`. 4. OCR-сервис возвращает `rawForecast` и нормализованный `forecast`. 5. `parser` сохраняет сигнал в PostgreSQL. 6. `backend` отдает API и отправляет push-уведомления. 7. `frontend` показывает сигналы, доступы и настройки пользователя. ## Безопасность в текущем состоянии - JWT для веба хранится в `HttpOnly` cookie. - Веб-клиент больше не хранит токен в `localStorage`. - OCR больше не принимает произвольный `imageUrl`, только файл. - Наружу должны смотреть только `80` и `443`. - `adminer` и `dockmon` сейчас закомментированы в `docker-compose.yml`. - Traefik dashboard использует `usersFile`, а не пароль, зашитый в репозиторий. ## Быстрый старт 1. Скопируйте `.env.example` в `.env`. 2. Заполните `.env` реальными значениями. 3. Проверьте `parser/.env`. 4. Поднимите стек: ```bash docker compose up -d --build ``` 5. Примените схему БД: ```bash docker compose exec backend npx prisma db push ``` ## Полезные команды Сборка: ```bash npm run build cd backend && npm run build cd frontend && npm run build ``` Проверка итогового compose-конфига: ```bash docker compose config ``` Проверка OCR локально: ```bash curl http://localhost:4010/health curl -X POST http://localhost:4010/ocr/forecast -F "image=@./forecast-ocr-service/tmp-forecast-test.png" ``` ## Переменные окружения Корневой `.env`: - `POSTGRES_DB` - `POSTGRES_USER` - `POSTGRES_PASSWORD` - `JWT_SECRET` - `PARSER_INTERNAL_SECRET` - `NUXT_PUBLIC_API_BASE` - `APP_PUBLIC_URL` - `CORS_ORIGIN` - `TRAEFIK_ACME_EMAIL` - `SMTP_*` - `VAPID_*` - `FIREBASE_*` `parser/.env`: - `DATABASE_URL` - `ALPINBET_BASE_URL` - `ALPINBET_TARGET_URL` - `ALPINBET_BOTS` - `AUTH_ENABLED` - `AUTH_LOGIN_URL` - `AUTH_USERNAME` - `AUTH_PASSWORD` - `SESSION_FILE` - `STATE_FILE` - `POLL_INTERVAL_MS` - `FORECAST_OCR_URL` - `FORECAST_OCR_TIMEOUT_MS` - `FORECAST_OCR_ENABLED` - `BACKEND_INTERNAL_URL` - `PARSER_INTERNAL_SECRET` ## Чеклист Перед Деплоем - Заполните `.env` реальными секретами и не оставляйте `change_me_*`. - Смените `JWT_SECRET`, `PARSER_INTERNAL_SECRET`, `POSTGRES_PASSWORD`, SMTP и Firebase credentials, если они уже где-то светились. - Создайте `traefik/secrets/dashboard-users` на сервере. - Проверьте, что наружу открыты только `80` и `443`. - Убедитесь, что `adminer` и `dockmon` остаются закомментированными. - Выполните `docker compose config` перед запуском. - Поднимите стек через `docker compose up -d --build`. - После старта выполните `docker compose exec backend npx prisma db push`. - Проверьте `https://antigol.ru`, `https://api.antigol.ru/health` и обычный логин. - Автобэкап PostgreSQL включён сервисом `postgres-backup`, архивы складываются в `./backups`. - Сделайте контрольный backup PostgreSQL перед следующими продовыми изменениями. ## Полезные файлы - [docker-compose.yml](/C:/Users/vlad/Documents/Projects/alpinbet-parser/docker-compose.yml) - [traefik/dynamic/routes.yml](/C:/Users/vlad/Documents/Projects/alpinbet-parser/traefik/dynamic/routes.yml) - [backend/prisma/schema.prisma](/C:/Users/vlad/Documents/Projects/alpinbet-parser/backend/prisma/schema.prisma) - [parser/src/forecast-ocr.js](/C:/Users/vlad/Documents/Projects/alpinbet-parser/parser/src/forecast-ocr.js) - [forecast-ocr-service/src/index.js](/C:/Users/vlad/Documents/Projects/alpinbet-parser/forecast-ocr-service/src/index.js)