7.3 KiB
RF4 Spotter
RF4 Spotter — неофициальный сервис свежих точек и статистики клёва для Russian Fishing 4. Этап 1 содержит контейнерный каркас, демоданные, read-only API, главную страницу и страницу точки. Реальный импорт официальных рекордов пока остаётся отдельным исследовательским адаптером этапа 0.
Запуск через Docker
Требуются Docker Engine и Docker Compose. Это основной и рекомендуемый сценарий:
docker compose up --build
После успешного запуска:
- сайт: http://localhost:4321;
- OpenAPI: http://localhost:8000/docs;
- проверка API: http://localhost:8000/health;
- консоль MinIO: http://localhost:9001.
Контейнер API сам выполняет alembic upgrade head, затем идемпотентный seed. PostgreSQL хранит данные в именованном volume postgres_data, а MinIO — в minio_data.
Остановка:
docker compose down
Удаление volume и повторное создание чистой базы — только когда данные больше не нужны:
docker compose down --volumes
docker compose up --build
Переменные и локальные значения по умолчанию перечислены в .env.example. Секретов в репозитории нет.
Что реализовано
- FastAPI и SQLAlchemy 2;
- PostgreSQL 17 и начальная миграция Alembic;
- идемпотентный seed с двумя точками и свежими демо-уловами;
GET /api/v1/activityс фильтрами периода, водоёма, рыбы, способа и сортировки;GET /api/v1/spots/{id}и/catches;- справочники рыб, водоёмов и приманок;
- Astro SSR-интерфейс с адаптивным дизайном из
design-referenceбез переноса React/Vinext-стека; - объяснимые индексы активности и уверенности по формуле спецификации;
- состояния «нет данных» и «источник недоступен»;
- идемпотентный импорт официальных записей с журналом запусков;
- публичная страница
/recordsс источником и временем последнего импорта; - форма
/report, защищённые admin API и журнал модерации; - honeypot и базовый лимит отправок;
- скриншоты уловов в MinIO/S3 с декодированием изображения, ограничением размера и очисткой метаданных.
Все пользовательские ники и уловы в seed демонстрационные.
Проверка проекта
Backend и исследовательский парсер:
python3 -m venv .venv
.venv/bin/pip install -r apps/api/requirements.txt
.venv/bin/pip install -e .
.venv/bin/pytest apps/api/tests tests -q
Frontend:
cd apps/web
npm install
npm run build
npm audit --omit=dev
E2E после запуска Compose:
cd apps/web
npx playwright install chromium
npm run test:e2e
Импорт официальных рекордов
Однократный контейнерный запуск после старта базы:
docker compose --profile tools run --rm importer
Импорт делает до трёх ограниченных попыток, проверяет DOM-контракт и не удаляет ранее сохранённые данные при сбое. Повторный запуск обновляет совпавшие записи по SHA-256 ключу и не создаёт дубликаты. Автоматическое расписание намеренно ещё не включено: сначала требуется согласовать допустимость регулярного опроса официального сайта.
Ручной административный запуск также доступен через POST /api/v1/admin/imports/official-records, журнал — через GET /api/v1/admin/imports. Импорт сохраняет HTTP-метаданные и использует ETag/Last-Modified, когда источник их предоставляет.
Планировщик реализован отдельным opt-in профилем и по умолчанию опрашивает источник не чаще одного раза в час:
docker compose --profile scheduler up -d scheduler
Обычный docker compose up его не запускает. Не включайте профиль во внешнем окружении, пока условия автоматического сбора не согласованы с владельцем источника; отсутствие robots.txt не является разрешением.
Пользовательские уловы и модерация
Новая запись из /report получает статус pending и не участвует в активности до одобрения. Административные методы требуют заголовок Authorization: Bearer $ADMIN_TOKEN:
curl -H "Authorization: Bearer change-me-in-production" \
"http://localhost:8000/api/v1/admin/catch-reports?status=pending"
Перед внешним развёртыванием обязательно замените демонстрационный ADMIN_TOKEN, а также значения S3_ACCESS_KEY и S3_SECRET_KEY. Форма принимает JPEG, PNG и WebP до 8 МБ; API повторно кодирует изображение и удаляет EXIF перед сохранением в MinIO. Модератор получает временную подписанную ссылку через admin API.
Очередь модерации доступна по адресу http://localhost:4321/admin/moderation. Администратор вводит ADMIN_TOKEN; интерфейс держит его только в памяти открытой страницы и не сохраняет в URL или браузерном хранилище.
Исследовательский парсер официальных рекордов
python -m rf4_research.records \
--url https://rf4game.de/records/region/RU/ \
--region RU \
--category records
Команда делает один HTTP-запрос и печатает типизированные записи в JSON. Это ещё не продуктивный импортёр: в нём нет повторов, кэша, транзакций и дедупликации. Подтверждённая структура источника и риски описаны в docs/data-sources.md.