summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-05 11:16:25 +0300
committerPaul Buetow <paul@buetow.org>2026-05-05 11:16:25 +0300
commited208d7120b6e6a7c2ce234504228b5a1ba48f11 (patch)
treeba3b79bca8cfaaba5d77697446a6f26f57c037eb
parenta7a346ef6018ec675c2256380f3f7758a24fc5ed (diff)
Update AGENTS.md with podcast support documentation
-rw-r--r--AGENTS.md44
1 files changed, 44 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 855d7e8..a50ba5f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -201,6 +201,50 @@ This triggers `FSScanner.Scan()`, which:
---
+## Podcast Support
+
+Podcasts are **special sets** (`sets.is_podcast = 1`). They reuse set permissions, browsing, and cover images, while adding feed management and episode tracking.
+
+### Subscribing
+
+Admin opens the **Podcasts** button in the admin panel (or calls `POST /api/podcasts`):
+- Submit an RSS/Atom feed URL and optional folder name.
+- Server creates a set folder, parses the feed, downloads the cover image, and inserts episodes into `podcast_episodes`.
+
+### Episode Management
+
+Episodes are stored in `podcast_episodes` and rendered in the browse grid for podcast sets:
+- **Undownloaded** episodes show a **Download to server** button (calls `POST /api/podcasts/episodes/{id}/download`).
+- **Downloaded** episodes become regular `media` rows and appear as normal media cards.
+- Users can mark episodes as listened/unlistened via the checkmark button.
+
+### Background Feed Checker
+
+A background goroutine (`CheckFeeds`) refreshes feeds every hour (configurable via `PODCAST_CHECK_INTERVAL_MINUTES`). It uses conditional GET (`If-None-Match`, `If-Modified-Since`) to avoid re-downloading unchanged feeds.
+
+### New Endpoints
+
+| Method | Path | Description |
+|--------|------|-------------|
+| `GET` | `/api/podcasts` | List podcast sets |
+| `POST` | `/api/podcasts` | Subscribe to a new feed (admin) |
+| `GET` | `/api/podcasts/{id}/episodes` | List episodes with status |
+| `POST` | `/api/podcasts/episodes/{id}/download` | Server-side download |
+| `POST` | `/api/podcasts/episodes/{id}/complete` | Toggle completion |
+
+### New Files
+
+- `internal/model/podcast.go` — PodcastFeed, PodcastEpisode, PodcastStatus
+- `internal/repository/podcast.go` — CRUD and queries
+- `internal/podcast/feed.go` — RSS/Atom parser using `gofeed`
+- `internal/podcast/cover.go` — Cover image downloader
+- `internal/service/podcast.go` — Business logic and background checker
+- `internal/api/handlers_podcast.go` — REST handlers
+- `internal/service/import.go` — Shared `ImportMediaFile` helper (used by uploads + downloader)
+- `web/js/podcasts.js` — Feed manager modal and episode renderer
+
+---
+
## Notes for Agents
- When modifying tests, always run `go test ./... -race -cover` before committing.