99 lines
3.9 KiB
Markdown
99 lines
3.9 KiB
Markdown
# 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
|
|
├── <subscription> one node per feed, newest episodes first
|
|
│ └── <episode> 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.
|
|
|
|
Only **audio** enclosures become episodes: an item is taken when its
|
|
enclosure type says audio, or when the type is missing or generic and the URL
|
|
looks like audio (including extensionless `/feed/mp3`-style URLs). Video and
|
|
image enclosures are skipped, so a show that publishes both plays its audio
|
|
and a blog feed does not list its featured images as tracks. See
|
|
`docs/src/providers/rss.md` for the exact rule.
|
|
|
|
**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.
|