crabidy/plan/rss-provider.md

3.1 KiB
Raw Permalink Blame History

Plan — RSS provider

Executes architecture/rss-provider.md against quality/rss-provider.md. Two commits: (A) the rssdy crate, (B) wiring (server feature, clients, docs).

A — The rssdy crate

  • A1 — api::Episode::key_forblake3(guid) truncated to 16 hex chars. Verifies: G7.
  • A2 — api::FeedFetcherreqwest client with the timeout, streaming the body while counting bytes so max_feed_bytes rejects before buffering it whole; parse with feed-rs; map entries to Episode (guid → key, title, author, published, itunes:duration where present, first audio enclosure); skip entries with no enclosure; sort newest first; truncate to limit. Errors carry no URL. Verifies: G1, G15, G16, G17.
  • A3 — slugify + de-duplication at load and on rename/subscribe. Verifies: G8.
  • A4 — parse_path for root/feed/episode, rejecting anything else. Verifies: G10.
  • A5 — Client::with_api / init — resolve subscriptions with slugs, drop entries without a url (warning), keep the settings for write-back. No feeds still mounts. Verifies: G18.
  • A6 — Listingsget_lib_root lists subscriptions and is creatable; get_lib_node("/rss/<slug>") fetches, replaces the memo, and returns episodes as tracks (queueable, downloadable). Verifies: G3, G9.
  • A7 — Memo — bounded push/replace, listing-written, read by get_urls_for_track / get_metadata_for_track / resolve_tracks_into. Verifies: G4, G5.
  • A8 — Subscription CRUDcreate_lib_node (URL → fetch → name from feed title → add), rename_lib_node, delete_lib_node, and settings() reserializing the live list. Verifies: G11G14.
  • A9 — rssdy/src/tests.rs over a FakeFeeds fixture backend covering every gate above.
  • A10 — Commit A: crate tests, clippy, fmt clean.

B — Wiring

  • B1 — Server feature rss — optional dep:rssdy, all-providers membership, ALL_PROVIDERS + BUILT_IN_PROVIDERS entries, ProviderToggles.rss, ProviderToggles::all, and the mount registration through mount_from_config. Verifies: G19.
  • B2 — check-features gains an rss-alone row. Verifies: G19.
  • B3 — Clients/rss into MUTABLE_ROOTS in cbd-tui/src/rpc.rs and cbd-web/src/state.rs, with their cacheability tests extended. Verifies: G6.
  • B4 — Docsdocs/src/providers/rss.md, rssdy/README.md, links from docs/src/providers.md, SUMMARY.md, config.md, and the root README (tree + config table). Say plainly that a premium URL is a credential, that listings are never cached, and that bookmarks depend on publisher guids. Verifies: G20.
  • B5 — plan/summary.md entry, then commit B.

Deferred (recorded, not dropped)

  • OPML import/export, per-episode played state, background polling, and artwork (itunes:image) — the library model has no field for it.
  • Sharing the episode→Track mapping with fyyd; worth extracting only if a third podcast source lands.