5.6 KiB
5.6 KiB
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/inpytv/urls.py.
Architecture and data flow to understand first
- Schedule generation:
api/routers/schedule.py->core/services/scheduler.py(ScheduleGenerator.generate_for_date) -> createsAiringrows. - Playback signaling:
api/routers/channel.py(/channel/{id}/now,/airings) computesexact_playback_offset_secondsfor 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.
- metadata sync only:
- Local media serving in dev uses range-aware endpoint
api/views.py::serve_video_with_rangemounted at/media/*whenDEBUG=True.
Backend conventions (project-specific)
- API style: Django Ninja
Schema/Pydantic payloads in routers underapi/routers/. - Auth pattern: session auth + CSRF cookie (
api/routers/auth.py); frontend sendswithCredentialsandX-CSRFToken(frontend/src/api.js). - Session persistence is settings-driven; use
SESSION_COOKIE_AGE/SESSION_EXPIRE_AT_BROWSER_CLOSEinpytv/settings.py(do not hardcode lifetimes in routers/frontend). Channel.requires_authis actively enforced in channel endpoints (/now,/airings,/status).- Source-rule behavior is business-critical:
allow/prefer/avoid/blockweighting incore/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.jsfor both/apiand/mediatohttp://localhost:8000. - Channel playback UX depends on
frontend/src/components/ChannelTuner.jsxtriple-buffer behavior and backend-provided offset.
Developer workflows (discovered commands)
# 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.pyin a way that changes URL matching behavior. - Treat
cached_file_pathand/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 makemigrationsdocker compose exec web python manage.py migrate
- Prefer running validation commands inside
webfor 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_dateclears/rebuilds block window airings). - Keep
MediaItem.cached_file_pathsemantics intact: frontend playback and cache status depend on it. - Validate cross-layer changes by exercising both API endpoints and frontend assumptions around
/media/...URLs.