Files
PYTV/AGENTS.md
2026-03-20 15:00:24 -04:00

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/ 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)

# 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.