Files
TeleWave/CLAUDE.md
T
Leonid Pershin 2b03e43a83
ci / build-backend (push) Successful in 2m38s
ci / build-frontend (push) Successful in 1m16s
ci / tests (push) Successful in 2m33s
ci / sonar (push) Successful in 3m48s
Add Telegram bot integration and related features
Implemented Telegram bot functionality, including settings management, subscriber tracking, and link generation for user interaction. Updated the backend to support new Telegram-related services and database entities. Enhanced the frontend to display Telegram options and allow users to open a chat with the bot. Localization strings were added for both English and Russian to support the new features. This integration aims to improve user engagement through Telegram notifications and interactions.
2026-07-31 07:58:18 +03:00

129 lines
11 KiB
Markdown

# CLAUDE.md
Инструкции для Claude Code при работе в этом репозитории.
## Что это
**TeleWave** — сервис онлайн-каналов: зритель смотрит сетку каналов, видео отдаётся из хранилища
на сервере. Админ ведёт библиотеку, каналы и эфир.
Работает: аутентификация, роли, пользователи; библиотека шоу/серий, коллекции, жанры, метаданные
(TMDb/OMDb), обработка медиа (ffmpeg → HLS), изображения; группы, шаблон сетки, стыки и заставки,
автосборка по профилям, обмен конфигурацией файлом и запросом к ИИ; генерация ленты, live-раздача,
публичный просмотр, статистика хранилища. Telegram-бот расписания (подписки на оповещения по каналам, прокси, опрос или вебхук). Конвенции — зеркало
[`PnvPanel`](../PnvPanel) (тот же автор).
**Спеки в `docs/` — источник правды по домену**, читай до правок в подсистеме:
[`tv-scheduler-architecture.md`](docs/tv-scheduler-architecture.md) (группы, сетка, слоты, стыки,
заставки, планировщик, автосборка, обмен конфигурацией — главный документ),
[`media-storage-and-streaming.md`](docs/media-storage-and-streaming.md) и
[`server-storage-setup.md`](docs/server-storage-setup.md) (медиа и хранилище).
## Стек
- **Backend**: C# / .NET 10, ASP.NET Core Minimal API, Clean Architecture, CQRS через
[`LiteCqrs.Net`](https://github.com/mrleo1nid/LiteCqrs.Net) (лёгкая альтернатива MediatR с явным
разделением Command/Query — см. README). EF Core 10 + Npgsql, Identity + JWT, FluentValidation,
Serilog, маппинг DTO вручную, OpenAPI + Scalar UI, тесты на xUnit + NSubstitute.
- **Frontend**: React 19 + Vite + TS, TanStack Query/Router (файловые роуты, `routeTree.gen.ts`
генерируется сборкой), shadcn поверх Radix + Tailwind v4, Zustand (только auth+тема),
react-hook-form + zod, i18n (ru/en), pnpm + oxlint + prettier.
## Архитектура — жёсткие правила
Зависимости строго внутрь: **Api → Infrastructure → Application → Domain**.
- **Domain** — без внешних зависимостей: `Auth`, `Library` (шоу, серии, коллекции, жанры), `Media`,
`Images`, `Programming` (группы, сетка, слоты, стыки + **чистый планировщик** `Planning`),
`Broadcast` (каналы, заставки, лента, live), `Settings`. Модель rich: приватные сеттеры,
фабрики `Create`, поведенческие методы.
- **Application** — CQRS-хендлеры, DTO, валидаторы и **порты** (`Common/Interfaces/I*.cs`:
`IAppDbContext`, `ICurrentUser`, `IMediaProcessor`, `IMediaStorage`, `IBumperRenderer`,
`IMetadataProvider`, `IImageStore`, `IStorageInspector`, …). Зависит только от Domain: никаких
`Npgsql`/`AspNetCore.Identity`, лишь их абстракции.
- **Infrastructure** — реализации портов: EF Core (`AppDbContext : IdentityDbContext<AppUser,
AppRole, Guid>`, конфигурации в `Persistence/Configurations`), ffmpeg, хранилище, метаданные,
идемпотентный `DbInitializer` (роли + админ из env `AdminSeed__*`).
- **Api** — Minimal API (`Endpoints/*Endpoints.cs`), middleware, DI composition root (`Program.cs`).
Обязательно:
- Команды меняют состояние в транзакции (`UnitOfWorkBehavior`); запросы только читают. Диспетчер —
`ISender`/`ICommandHandler`/`IQueryHandler`, регистрация в `Application/DependencyInjection.cs`.
- Управляемые ошибки — через `Result<T>` (`Common/Models/Result.cs`), не исключениями. Валидация —
FluentValidation через `ValidationBehavior`; хендлер не перепроверяет формат ввода.
- Всё I/O асинхронно, `CancellationToken` пробрасывается до EF/HTTP; никаких `.Result`/`.Wait()`.
Nullable включён, `TreatWarningsAsErrors=true` — предупреждения анализаторов не игнорировать.
- Планировщик (`Domain/Programming/Planning`) — **чистая функция**: вход `PlanningInput`, никаких
запросов и часов внутри. Данные под него собирает `Application/Programming/Planning`.
## Инварианты, которые легко нарушить
- **Роли** динамические, у пользователя ровно одна; системные `admin`/`user` (`IsSystem=true`) не
переименовать и не удалить, последнего админа не разжаловать, себя не заблокировать и не удалить.
- **Регистрация открытая** (создаётся `user`, токены сразу); понадобится модерация — заводи отдельный
флаг, не переиспользуй `IsBlocked`. Вход по `UserName`, email и SMTP не используются; JWT access +
refresh в httpOnly `tw_refresh_token` с обнаружением повторного использования отозванного.
- **Правка сетки эфир не двигает**: команда поднимает ревизию шаблона, ленту пересобирает применение.
- **Вещательные сутки** начинаются с `Channel.DayStartTime` (06:00), сетка задаётся во времени
канала (`UtcOffsetMinutes`), в базе всё в UTC.
## Единый контейнер
- Один образ: Api раздаёт REST (`/api`) и статику SPA из `wwwroot` (fallback на `index.html`), один
origin, база API — относительный `/api`. Multi-stage Dockerfile: node → dotnet sdk → aspnet.
Отдельный nginx для статики не вводить — ломает требование единого контейнера.
- Работает под непривилегированным `USER $APP_UID` (uid/gid 1654) **статически**, без
gosu/entrypoint: права на bind-mount выставляет оператор (`docs/server-storage-setup.md` § 5).
Data Protection не заводим — шифруемых секретов на диске нет. **TLS внешний**: `app` отдаёт HTTP
и доверяет `X-Forwarded-*`.
- docker-compose: только `app`. PostgreSQL внешний (`ConnectionStrings__Default` из `.env`), база
и пользователь создаются заранее вручную; миграции применяются на старте (`ApplyMigrationsAsync`),
прав `CREATEDB` не нужно.
## Соглашения по коду
- `<Verb><Noun>Command`/`<Get|List><Noun>Query` + `Handler`/`Validator` (где есть что проверить),
папки по фичам (`Auth/Login/`, `Programming/Templates/Generate/`, …). Один публичный тип на файл =
имя файла, кроме `Body` — тела Api-эндпоинтов, не совпадающие с командой 1:1 (`sealed record`
внизу файла эндпоинта). DTO — суффикс `Dto`.
- Ошибки — каталоги `XErrors` (`Error.Validation/NotFound/Conflict/…`), наружу единым
`application/problem+json` (`Api/Common/ResultExtensions.cs`). Секреты не логировать.
- **Изображения — только через реестр `Image`** (`Domain/Images`, галерея `features/admin/images`):
картинка хранится как `ImageId` и выбирается контролом `ImageGallery`/`GalleryBrowser`, своих
файловых полей не заводить. Файлы — `images/{id}{ext}`, отдаются по `/api/images/{id}`.
- Фронт: фича = папка в `src/features/admin/<фича>`; тексты только через i18n, ключи в `ru.ts` и `en.ts`.
- Комментарии объясняют **почему**, а не что; по-русски, как в существующем коде.
## Команды
Backend (из `backend/`):
```bash
dotnet build
dotnet csharpier format . # только через dotnet (версия из .config/); в CI — csharpier check
dotnet test tests/TeleWave.Domain.Tests # по одному проекту: MSBuild не берёт несколько
dotnet test tests/TeleWave.Application.Tests
dotnet test tests/TeleWave.Integration.Tests # Testcontainers; без Docker пропускаются
dotnet run --project src/TeleWave.Api
dotnet ef migrations add <Name> --project src/TeleWave.Infrastructure --startup-project src/TeleWave.Api
```
Frontend (из `frontend/`):
```bash
pnpm install && pnpm dev
pnpm lint && pnpm typecheck && pnpm build
pnpm format && pnpm format:check # CI падает на неотформатированном — прогоняй после правок
```
Инфраструктура: `docker compose up -d --build` (только api; postgres внешний). Окружение — Windows,
оболочка **PowerShell**; для POSIX-скриптов есть Bash-инструмент.
## Рабочие принципы
- Базовый срез реализован — правь по месту. Новые крупные направления с непринятыми решениями
(многоэкземплярность, транскод-профили, подсистемы) — после сверки; неоднозначность — вопрос.
- Меняешь поведение подсистемы — обнови её спеку в `docs/` тем же заходом.
- Соблюдай границы слоёв — главный инвариант проекта.
- Правь файлы через Edit/Write: пользователь видит дифф, а harness не даст перезаписать файл вслепую.
Скриптом на python — только при крайней необходимости (массовая механическая замена), и сказать явно.
- Не коммить и не пуши без явной просьбы; отвечай пользователю на русском.