# rssdy — the RSS podcast provider Mounts the podcast feeds you subscribe to at **`/rss`** in the crabidy library. Works with plain public feeds and with **premium per-subscriber URLs**, and always shows the newest episodes. ## Logging in There is no login. A feed is either public or its URL *is* the credential — a paid podcast gives you a URL with a token in it: ```text https://feeds.economist.com/v1/rss/the-economist-podcasts/f74365b0-… ``` Anyone holding that URL has your subscription, so the provider treats it as a secret: it is redacted from `Debug`, never logged, and **never put in a library path**. Paths carry a slug of the subscription name and a hash of the episode id instead — paths are displayed, logged, and persisted into saved queues and bookmarks, so a URL in one would leak everywhere. Keep `rss.toml` private; it holds the URLs in cleartext, like every other provider credential. ## Subscribing Either edit the config (below), or from a client: press `%` on `/rss`, paste the feed URL, and the provider fetches it once, names the subscription from the feed's own title, and writes it into `rss.toml`. `e` renames a subscription (its path changes with the name), `d` unsubscribes — that only removes the config entry, never audio you captured from it. ## How it works ```text /rss ├── one node per feed, newest episodes first │ └── a track; audio is the feed's enclosure URL └── … ``` A subscription is queueable and downloadable, so you can queue or `W`-capture a whole feed. Episodes stream directly from the enclosure URL — no sidecar, no helper binary. **Nothing is cached.** Every visit to a subscription fetches the feed, so an episode published a minute ago is there. One memo exists purely so that listing a feed and then queueing its 40 episodes costs one fetch rather than 41: it is written by listings and read only when resolving a track, so it can never make a listing stale. Episode paths are `blake3(guid)[..16]`, which is stable as long as the publisher keeps its guids stable. Two consequences worth knowing: - A bookmark (`w`) to an episode that has since aged out of the feed cannot resolve — there is nothing left to look up. Capture (`W`) what you want to keep. - A publisher that regenerates guids on every fetch invalidates bookmarks. Nothing can be done about that from this side. ## Configuration — `~/.config/crabidy/rss.toml` ```toml # One table per subscription. `name` is yours and decides the path slug; # duplicates get a numeric suffix. [[feeds]] name = "The Economist Podcasts" url = "https://feeds.economist.com/v1/rss/…" [[feeds]] name = "Cautionary Tales" url = "https://feeds.example.org/cautionary-tales" # Optional, defaults shown. # episodes_per_feed = 200 # episodes listed per feed # call_timeout_secs = 30 # per-request timeout # max_feed_bytes = 33554432 # 32 MiB cap on a feed body ``` A feed entry with no url is skipped with a warning. No feeds at all is fine: `/rss` mounts empty and you can `%` into it. ## Notes - Feeds are read as RSS 2.0/1.0/0.x, Atom, or JSON Feed via [`feed-rs`](https://crates.io/crates/feed-rs). - `itunes:duration` is parsed here rather than taken from `feed-rs`, which reads it as NPT — a format with no `MM:SS` form, so `53:25` came back as 53 *seconds*. `S`, `MM:SS` and `HH:MM:SS` all work now. - Build the server without the `rss` cargo feature to leave this provider out of the binary entirely.