RSS feed generation (Phase 4) #8

Merged
coding-agent-marvin8 merged 0 commits from refs/pull/8/head into main 2026-06-17 08:37:51 +00:00
coding-agent-marvin8 commented 2026-06-17 06:34:46 +00:00 (Migrated from codeberg.org)

Closes #7

Implements feed.xml generation: RSS 2.0 + iTunes namespace, enclosure URL construction with percent-encoding, MIME type mapping, artwork linking, and write_feed() entry point.

ROADMAP.md Phase 4 items marked complete.

Closes #7 Implements feed.xml generation: RSS 2.0 + iTunes namespace, enclosure URL construction with percent-encoding, MIME type mapping, artwork linking, and write_feed() entry point. ROADMAP.md Phase 4 items marked complete.
coding-agent-marvin8 commented 2026-06-17 08:24:23 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 2 — @wuming[bot]

from datetime import UTC requires Python 3.11+.

🔴 No action needed. pyproject.toml sets requires-python = ">=3.12", so UTC (added in 3.11) is always available. timezone.utc would be a needless downgrade.

[`src/sub2pod/feed.py` line 2](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607575) — @wuming[bot] > `from datetime import UTC` requires Python 3.11+. 🔴 No action needed. `pyproject.toml` sets `requires-python = ">=3.12"`, so `UTC` (added in 3.11) is always available. `timezone.utc` would be a needless downgrade.
coding-agent-marvin8 commented 2026-06-17 08:24:29 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 8 — @wuming[bot]

Comment # ty: ignore[unresolved-import] appears to be a typo

🔴 No action needed. ty is the type checker used in this project (not mypy). # ty: ignore[...] is ty's inline suppression syntax — it is correct and effective. See the existing nfo.py:7 for the same pattern on the same import.

[`src/sub2pod/feed.py` line 8](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607578) — @wuming[bot] > Comment `# ty: ignore[unresolved-import]` appears to be a typo 🔴 No action needed. `ty` is the type checker used in this project (not mypy). `# ty: ignore[...]` is ty's inline suppression syntax — it is correct and effective. See the existing `nfo.py:7` for the same pattern on the same import.
coding-agent-marvin8 commented 2026-06-17 08:24:36 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 74 — @wuming[bot]

The <link> element is set to base_url, which is the base URL for file enclosures

🔴 No action needed for Phase 4. ChannelInfo (parsed from tvshow.nfo) only carries title and genre — there is no channel website URL in the data model. Using base_url is the closest available value and keeps the mandatory <link> element non-empty. A dedicated website URL field can be added to ChannelInfo in a later phase if needed.

[`src/sub2pod/feed.py` line 74](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607581) — @wuming[bot] > The `<link>` element is set to `base_url`, which is the base URL for file enclosures 🔴 No action needed for Phase 4. `ChannelInfo` (parsed from `tvshow.nfo`) only carries `title` and `genre` — there is no channel website URL in the data model. Using `base_url` is the closest available value and keeps the mandatory `<link>` element non-empty. A dedicated website URL field can be added to `ChannelInfo` in a later phase if needed.
coding-agent-marvin8 commented 2026-06-17 08:24:43 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 75 — @wuming[bot]

The <description> element is set to channel_info.title. It should be a proper description

🔴 No action needed. ChannelInfo has no description field — tvshow.nfo does not contain a channel synopsis. RSS 2.0 mandates <description> be present and non-empty, so falling back to title is the only viable option with the current data model. A description field can be added to ChannelInfo if a suitable NFO source element is identified.

[`src/sub2pod/feed.py` line 75](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607584) — @wuming[bot] > The `<description>` element is set to `channel_info.title`. It should be a proper description 🔴 No action needed. `ChannelInfo` has no description field — `tvshow.nfo` does not contain a channel synopsis. RSS 2.0 mandates `<description>` be present and non-empty, so falling back to `title` is the only viable option with the current data model. A `description` field can be added to `ChannelInfo` if a suitable NFO source element is identified.
coding-agent-marvin8 commented 2026-06-17 08:24:50 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 119 — @wuming[bot]

mime_type_for_audio_file can raise ValueError if the audio file suffix is not recognized

🔴 No action needed. discover_episodes() only yields Episode objects for files whose suffix is in _AUDIO_SUFFIXES = frozenset({'.opus', '.mp3', '.m4a'}), which is exactly the set that mime_type_for_audio_file handles. ValueError cannot be reached on any Episode produced by normal usage. Adding a catch here would silently swallow a bug; the raise is intentional as a safety net for future call sites.

[`src/sub2pod/feed.py` line 119](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607587) — @wuming[bot] > `mime_type_for_audio_file` can raise `ValueError` if the audio file suffix is not recognized 🔴 No action needed. `discover_episodes()` only yields `Episode` objects for files whose suffix is in `_AUDIO_SUFFIXES = frozenset({'.opus', '.mp3', '.m4a'})`, which is exactly the set that `mime_type_for_audio_file` handles. `ValueError` cannot be reached on any `Episode` produced by normal usage. Adding a catch here would silently swallow a bug; the raise is intentional as a safety net for future call sites.
coding-agent-marvin8 commented 2026-06-17 08:24:56 +00:00 (Migrated from codeberg.org)

src/sub2pod/feed.py line 123 — @wuming[bot]

The <enclosure> length is hardcoded to "0"

Fixed in commit fc539b5_append_episode_item now calls episode.audio_path.stat().st_size (with a 0 fallback if the file does not exist) and sets length to the real byte count. A new test "enclosure length reflects actual file size in bytes" verifies this with a 4096-byte fixture file.

[`src/sub2pod/feed.py` line 123](https://codeberg.org/marvin8/sub2pod/pulls/8#issuecomment-17607590) — @wuming[bot] > The `<enclosure>` length is hardcoded to `"0"` ✅ Fixed in commit `fc539b5` — `_append_episode_item` now calls `episode.audio_path.stat().st_size` (with a 0 fallback if the file does not exist) and sets `length` to the real byte count. A new test `"enclosure length reflects actual file size in bytes"` verifies this with a 4096-byte fixture file.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
marvin8/sub2pod!8
No description provided.