Everything an episode page needs, in one map.
Everything an episode page needs, in one map.
The fetched feeds of an app, and keeping them current.
The feeds are a map by key, the guid that the feed was first fetched under. Each entry has the parsed feed, its URL, the ETag and Last-Modified of the last fetch, the guid that the feed gives itself now, when the feed last changed, and the time of the next check:
{"917393e3-…" {:url "https://feeds.podcastindex.org/pc20.xml"
:feed {…}
:retained {item-guid {:missed-at #inst "…"
:gone? true}}
:etag "…"
:last-modified "…"
:guid "917393e3-…" ; what the feed says now
:changed-at #inst "…"
:fetched-at #inst "…"
:next-check #inst "…"
:failures 0
:status 200}}
The feed keeps the items that a fetch no longer brings back, after the fresh ones, since many hosts serve only the newest items. Each has a fact under :retained: when a fetch first missed it, and :gone? when the host took it out rather than leaving it to age out of a capped feed, as it's later than the oldest fresh item, or has no date.
An entry with only its :url is a feed to fetch for the first time, e.g. of a new subscription, and it's due at once. An entry that's :gone? is never due, as default-cadence says, and nor is one that's :local?, the feed of a show of local files, which has no URL.
The fetched feeds of an app, and keeping them current.
The feeds are a map by key, the guid that the feed was first fetched
under. Each entry has the parsed feed, its URL, the ETag and
Last-Modified of the last fetch, the guid that the feed gives itself
now, when the feed last changed, and the time of the next check:
{"917393e3-…" {:url "https://feeds.podcastindex.org/pc20.xml"
:feed {…}
:retained {item-guid {:missed-at #inst "…"
:gone? true}}
:etag "…"
:last-modified "…"
:guid "917393e3-…" ; what the feed says now
:changed-at #inst "…"
:fetched-at #inst "…"
:next-check #inst "…"
:failures 0
:status 200}}
The feed keeps the items that a fetch no longer brings back, after the
fresh ones, since many hosts serve only the newest items. Each has a fact
under :retained: when a fetch first missed it, and :gone? when the host
took it out rather than leaving it to age out of a capped feed, as it's
later than the oldest fresh item, or has no date.
An entry with only its :url is a feed to fetch for the first time, e.g.
of a new subscription, and it's due at once. An entry that's :gone? is
never due, as default-cadence says, and nor is one that's :local?, the
feed of a show of local files, which has no URL.The subscriptions, feeds, queue and play progress of an app, in one map.
The parts of a library are:
{:device "…" ; the id of this device
:profile {…} ; the profile, a CRDT that syncs
:feeds {feed-guid {…}} ; the feeds, as app.feeds keeps them
:fetched-lists {url {…}} ; the followed OPML lists, as fetched
:index {…} ; the search index, with :search?
:sync {:cursors {…} …} ; the last sync's cursors and report
:refresh {:added […] …} ; the new episodes, moves and report
:effects [[:seek id 784]] ; the effects of the last event, to apply
:sleep {:episodes 1} ; the sleep timer of this device, if set
:files {id {…}} ; the downloaded files of this device
:config {…}} ; the options below
The profile is a CRDT, so never change it with assoc or dissoc. A feed keeps the episodes that a fetch no longer brings back, as app.feeds says, and the views and listings mark each with its :retained fact. With :max-items, the oldest of them go once a feed has more items, but never one that the profile holds anything for, e.g. progress, a played mark that isn't archived, a star or a place in the queue. The config holds the options that the functions take, given once:
{:fetch f ; in place of podcast/fetch!
:send f ; in place of client/send!
:allow-pred url/public? ; which URLs a request may go to
:credentials-of f ; credentials of a private feed by URL
:index {…} ; the credentials of the Podcast Index
:languages ["da" "en"] ; of the listener, for transcripts
:search? true ; whether to keep the search index
:cadence {…} ; as app.feeds takes it
:concurrency 8 ; how many feeds are fetched at once
:max-pages 5 ; of a paged feed, at its first fetch
:max-items 500 ; the most items of a feed, all by default
:archive-after 31536000000 ; when played episodes are archived, in ms
:only-newer? false ; older episodes that appear are new too
:keep-fn app.feeds/slim ; what to keep of a feed, all by default
:local-file-fn f ; the downloaded file of an episode id
:cache store ; for companion files, see read-files!
:now-fn f ; the clock, util.time/now by default
:timeout-seconds 15 :max-bytes … :user-agent …}
Each function also takes the same keys as options, for one call, and :at, an instant to stamp each change with in place of the time of the clock.
The subscriptions, feeds, queue and play progress of an app, in one map.
The parts of a library are:
{:device "…" ; the id of this device
:profile {…} ; the profile, a CRDT that syncs
:feeds {feed-guid {…}} ; the feeds, as app.feeds keeps them
:fetched-lists {url {…}} ; the followed OPML lists, as fetched
:index {…} ; the search index, with :search?
:sync {:cursors {…} …} ; the last sync's cursors and report
:refresh {:added […] …} ; the new episodes, moves and report
:effects [[:seek id 784]] ; the effects of the last event, to apply
:sleep {:episodes 1} ; the sleep timer of this device, if set
:files {id {…}} ; the downloaded files of this device
:config {…}} ; the options below
The profile is a CRDT, so never change it with assoc or dissoc. A feed
keeps the episodes that a fetch no longer brings back, as app.feeds
says, and the views and listings mark each with its :retained fact.
With :max-items, the oldest of them go once a feed has more items, but
never one that the profile holds anything for, e.g. progress, a played
mark that isn't archived, a star or a place in the queue. The config
holds the options that the functions take, given once:
{:fetch f ; in place of podcast/fetch!
:send f ; in place of client/send!
:allow-pred url/public? ; which URLs a request may go to
:credentials-of f ; credentials of a private feed by URL
:index {…} ; the credentials of the Podcast Index
:languages ["da" "en"] ; of the listener, for transcripts
:search? true ; whether to keep the search index
:cadence {…} ; as app.feeds takes it
:concurrency 8 ; how many feeds are fetched at once
:max-pages 5 ; of a paged feed, at its first fetch
:max-items 500 ; the most items of a feed, all by default
:archive-after 31536000000 ; when played episodes are archived, in ms
:only-newer? false ; older episodes that appear are new too
:keep-fn app.feeds/slim ; what to keep of a feed, all by default
:local-file-fn f ; the downloaded file of an episode id
:cache store ; for companion files, see read-files!
:now-fn f ; the clock, util.time/now by default
:timeout-seconds 15 :max-bytes … :user-agent …}
Each function also takes the same keys as options, for one call, and
:at, an instant to stamp each change with in place of the time of the
clock.The Media Session of a browser for the episode that plays: what the lock screen and the notification show, and what their buttons and those of the headphones do, as player events for library/step.
The functions are pure. With the session namespace of the play-nice
library, a player of the episode id in the media element audio wires
them up like this, with a step! that runs an event through library/step
and does its effects:
(session/metadata! (:metadata (library/playback @lib id)))
(session/actions!
(zipmap (media-session/actions @lib id)
(repeat (fn [details]
(run! step! (media-session/events
@lib id (.-currentTime audio)
details))))))
The next and previous buttons go where the listener's preference :track-buttons says, as profile/default-preferences has it.
The Media Session of a browser for the episode that plays: what the lock
screen and the notification show, and what their buttons and those of
the headphones do, as player events for library/step.
The functions are pure. With the session namespace of the play-nice
library, a player of the episode `id` in the media element `audio` wires
them up like this, with a step! that runs an event through library/step
and does its effects:
(session/metadata! (:metadata (library/playback @lib id)))
(session/actions!
(zipmap (media-session/actions @lib id)
(repeat (fn [details]
(run! step! (media-session/events
@lib id (.-currentTime audio)
details))))))
The next and previous buttons go where the listener's preference
:track-buttons says, as profile/default-preferences has it.Everything a show page needs, in one map.
Everything a show page needs, in one map.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |