97 lines
5.6 KiB
Markdown
97 lines
5.6 KiB
Markdown
# AGENTS.md
|
|
|
|
## What this project is
|
|
- PYTV is a Django + Django-Ninja backend (`core/`, `api/`, `pytv/`) with a React/Vite frontend (`frontend/`) for a "cable TV" style experience.
|
|
- Core domain model is in `core/models.py`: `Channel`, `ScheduleTemplate`/`ScheduleBlock`, `Airing`, `MediaSource`, `MediaItem`.
|
|
- API entrypoint is `api/api.py`; all HTTP API routes are mounted under `/api/` in `pytv/urls.py`.
|
|
|
|
## Architecture and data flow to understand first
|
|
- Schedule generation: `api/routers/schedule.py` -> `core/services/scheduler.py` (`ScheduleGenerator.generate_for_date`) -> creates `Airing` rows.
|
|
- Playback signaling: `api/routers/channel.py` (`/channel/{id}/now`, `/airings`) computes `exact_playback_offset_seconds` for frontend sync.
|
|
- Media caching pipeline for YouTube sources:
|
|
- metadata sync only: `core/services/youtube.py::sync_source`
|
|
- just-in-time download: `core/services/cache.py::run_cache` + `youtube.download_for_airing`
|
|
- emergency replacement (<1h before air with no cache): `ScheduleGenerator.replace_undownloaded_airings`.
|
|
- Local media serving in dev uses range-aware endpoint `api/views.py::serve_video_with_range` mounted at `/media/*` when `DEBUG=True`.
|
|
|
|
## Backend conventions (project-specific)
|
|
- API style: Django Ninja `Schema`/Pydantic payloads in routers under `api/routers/`.
|
|
- Auth pattern: session auth + CSRF cookie (`api/routers/auth.py`); frontend sends `withCredentials` and `X-CSRFToken` (`frontend/src/api.js`).
|
|
- Session persistence is settings-driven; use `SESSION_COOKIE_AGE`/`SESSION_EXPIRE_AT_BROWSER_CLOSE` in `pytv/settings.py` (do not hardcode lifetimes in routers/frontend).
|
|
- `Channel.requires_auth` is actively enforced in channel endpoints (`/now`, `/airings`, `/status`).
|
|
- Source-rule behavior is business-critical: `allow/prefer/avoid/block` weighting in `core/services/scheduler.py` (not just CRUD metadata).
|
|
- In `api/routers/sources.py`, literal routes (e.g. `/cache-upcoming`) must stay before parameterized routes (explicitly documented in file).
|
|
|
|
## Frontend/backend integration points
|
|
- Frontend API client is centralized in `frontend/src/api.js` (do not scatter fetch logic).
|
|
- Dev proxy is configured in `frontend/vite.config.js` for both `/api` and `/media` to `http://localhost:8000`.
|
|
- Channel playback UX depends on `frontend/src/components/ChannelTuner.jsx` triple-buffer behavior and backend-provided offset.
|
|
|
|
## Developer workflows (discovered commands)
|
|
```bash
|
|
# Local backend (from repo root)
|
|
python manage.py migrate
|
|
python manage.py runserver 0.0.0.0:8000
|
|
python manage.py seed
|
|
python manage.py cache_upcoming --hours 24
|
|
python manage.py run_cache_worker --interval 600 --hours 24
|
|
python manage.py backup_now
|
|
python manage.py run_backup_worker --interval 60
|
|
python manage.py state --channel <id> --test-generate
|
|
|
|
# Tests (pytest configured via pytest.ini)
|
|
pytest
|
|
|
|
# Frontend (from frontend/)
|
|
npm install
|
|
npm run dev
|
|
npm run build
|
|
npm run lint
|
|
|
|
# Docker stack (repo root)
|
|
docker compose up --build
|
|
|
|
# Docker migrations (ALWAYS run inside the web container)
|
|
docker compose exec web python manage.py migrate
|
|
|
|
# Local DB reset (admin/dev only, destructive)
|
|
docker compose exec web python manage.py flush --no-input
|
|
docker compose exec web python manage.py migrate
|
|
|
|
# Optional: reseed mock data after reset
|
|
docker compose exec web python manage.py seed
|
|
|
|
# Optional: run tests in the same containerized environment
|
|
docker compose exec web pytest
|
|
```
|
|
|
|
## Agent execution safety rails
|
|
- In this repo, assume the user controls long-running processes. Do not start/stop `docker compose up`, Django dev server, or Vite dev server unless explicitly asked.
|
|
- Prefer read-only investigation first (`read_file`, targeted tests) before broad edits.
|
|
- Keep business logic in `core/services/`; routers should remain thin orchestration/API layers.
|
|
- Preserve public API shapes used by frontend (`frontend/src/api.js`) unless the task explicitly includes coordinated frontend updates.
|
|
- Do not reorder literal and parameterized source routes in `api/routers/sources.py` in a way that changes URL matching behavior.
|
|
- Treat `cached_file_path` and `/media/...` URL behavior as compatibility-sensitive; verify signaling paths when changing cache/playback logic.
|
|
- Backups are compatibility-sensitive and stored at fixed path `/Backups`; do not add user-configurable backup destination paths.
|
|
|
|
## Containerized dev/test expectations
|
|
- The user runs Docker and dev servers; agents should not spin them up by default.
|
|
- If a schema change is introduced, run migrations via container exec, not host Python:
|
|
- `docker compose exec web python manage.py makemigrations`
|
|
- `docker compose exec web python manage.py migrate`
|
|
- Prefer running validation commands inside `web` for parity with runtime dependencies (yt-dlp/node/ffprobe path assumptions).
|
|
- When sharing run steps in PR notes, provide container commands first, then local equivalents as secondary options.
|
|
|
|
## Testing map and where to extend
|
|
- API router tests: `api/tests/test_*.py`.
|
|
- End-to-end domain behavior tests: `tests/test_channel_actions.py`, `tests/test_source_rules.py`, `tests/test_playback_sync.py`, `tests/test_channel_auth.py`.
|
|
- If changing scheduler/cache/youtube logic, update both API-level tests and service-behavior tests.
|
|
|
|
## Practical guardrails for AI agents
|
|
- Prefer editing service-layer logic in `core/services/` over embedding business rules in routers.
|
|
- Preserve idempotent schedule generation semantics (`generate_for_date` clears/rebuilds block window airings).
|
|
- Keep `MediaItem.cached_file_path` semantics intact: frontend playback and cache status depend on it.
|
|
- Validate cross-layer changes by exercising both API endpoints and frontend assumptions around `/media/...` URLs.
|
|
|
|
|