Liking cljdoc? Tell your friends :D

dk.simongray.podcast.app.library

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.
raw docstring

add-episodeclj/s

(add-episode library url fetched item-guid)
(add-episode library url fetched item-guid opts)

The library with the episode item-guid of the feed at url, with what was fetched and the :at of opts, though it isn't subscribed to the feed.

The fetched is the result of dk.simongray.podcast/fetch! or a parsed feed. The profile notes the episode as a remote item, so that every device fetches its feed, and the library lists it among its episodes. It throws when fetched has no feed, with the diagnostic of the fetch as the ex-data, and when the feed has no such episode.

The `library` with the episode `item-guid` of the feed at `url`, with
what was `fetched` and the :at of `opts`, though it isn't subscribed to
the feed.

The `fetched` is the result of dk.simongray.podcast/fetch! or a parsed
feed. The profile notes the episode as a remote item, so that every
device fetches its feed, and the library lists it among its episodes.
It throws when `fetched` has no feed, with the diagnostic of the fetch
as the ex-data, and when the feed has no such episode.
sourceraw docstring

backendclj/s

(backend store)
(backend store {:keys [opml?] :as opts})

A backend that syncs the profiles of libraries through store, a document store of dk.simongray.like-minded, with opts.

It's like-minded/backend with profile/sync-options under the opts, which can also have :opml?, true to write subscriptions.opml beside the documents.

A backend that syncs the profiles of libraries through `store`, a
document store of dk.simongray.like-minded, with `opts`.

It's like-minded/backend with profile/sync-options under the `opts`,
which can also have :opml?, true to write subscriptions.opml beside
the documents.
sourceraw docstring

default-configclj/s

The config of a library when none is given. The :list-seconds is how long a fetched OPML list stays current, and the :offline-seconds how long next-refresh waits after a refresh that found the device offline.

The config of a library when none is given. The :list-seconds is how
long a fetched OPML list stays current, and the :offline-seconds how
long next-refresh waits after a refresh that found the device offline.
sourceraw docstring

documentclj/s

(document library)
(document library opts)

This device's sync document in library, with the :app and :at of opts, as a map of the file's :name and :body.

A backend writes the same document to its store. Where an app can't write to the store, e.g. a sync folder in a browser without a folder picker, the listener can save this file into it by hand.

This device's sync document in `library`, with the :app and :at of
`opts`, as a map of the file's :name and :body.

A backend writes the same document to its store. Where an app can't
write to the store, e.g. a sync folder in a browser without a folder
picker, the listener can save this file into it by hand.
sourceraw docstring

episodeclj/s

(episode library id)
(episode library id opts)

The view of the episode id, [feed-guid item-guid], of library, with the opts of app.episode/view over the config, e.g. its :languages, or nil when the library has no such episode, or doesn't hold its feed in memory, as loaded? tells. Unless the opts say, the :video? of the view is whether the listener watches the show. The view has the :retained fact of an episode that the feed no longer brings back.

The view of the episode `id`, [feed-guid item-guid], of `library`, with
the `opts` of app.episode/view over the config, e.g. its :languages, or
nil when the library has no such episode, or doesn't hold its feed in
memory, as loaded? tells. Unless the `opts` say, the
:video? of the view is whether the listener watches the show. The view
has the :retained fact of an episode that the feed no longer brings
back.
sourceraw docstring

episode-idclj/s

(episode-id library feed item)

The id of the episode item of feed in library, [feed-guid item-guid].

The id of the episode `item` of `feed` in `library`, [feed-guid
item-guid].
sourceraw docstring

episodesclj/s

(episodes library)
(episodes library {:keys [feed-guids] :as opts})

The episodes of the shows of library that the criteria opts select, as [feed item] pairs, e.g.

(episodes library {:where {:status :unplayed} :order :listening})

The criteria are those of criteria/episodes. They read the profile and the downloaded files of the library, and the time of its clock unless the opts give :at. The hidden episodes are left out unless the criteria name :hidden?. With :feed-guids, only the episodes of those shows are read, e.g. for the page of a show.

The episodes of the shows of `library` that the criteria `opts` select,
as [feed item] pairs, e.g.

    (episodes library {:where {:status :unplayed} :order :listening})

The criteria are those of criteria/episodes. They read the profile and
the downloaded files of the library, and the time of its clock unless
the `opts` give :at. The hidden episodes are left out unless the
criteria name :hidden?. With :feed-guids, only the episodes of those
shows are read, e.g. for the page of a show.
sourceraw docstring

episodes-from-opmlclj/s

(episodes-from-opml library list)
(episodes-from-opml library list opts)

The library with the progress, the played marks and the deleted episodes of the OPML subscription list, as Overcast's extended export writes them, at the :at of opts, as profile.opml/episodes-from-opml applies them.

An episode is found by the URL of its media among the feeds that the library has, so subscribe to the list and refresh first. Its feed is found by the URL in the list.

The `library` with the progress, the played marks and the deleted
episodes of the OPML subscription `list`, as Overcast's extended export
writes them, at the :at of `opts`, as profile.opml/episodes-from-opml
applies them.

An episode is found by the URL of its media among the feeds that the
library has, so subscribe to the list and refresh first. Its feed is
found by the URL in the list.
sourceraw docstring

fail-downloadclj/s

(fail-download library id details)
(fail-download library id details opts)

The library with the download of the episode id failed at the time of the call, with opts, and the details of downloads/fail-download: the bytes on the device and the headers that came with them, and the error.

The `library` with the download of the episode `id` failed at the time
of the call, with `opts`, and the `details` of downloads/fail-download:
the bytes on the device and the headers that came with them, and the
error.
sourceraw docstring

fetch-linked-shows!clj/s

(fetch-linked-shows! library feed-guid)
(fetch-linked-shows! library feed-guid opts)

Fetch the shows that the show feed-guid of library links to, with the opts of app.show/fetch-linked-shows! over the config. It gives a map of the :podroll and the :publisher, in ClojureScript as a promise, or nil when the library has no such feed.

Fetch the shows that the show `feed-guid` of `library` links to, with
the `opts` of app.show/fetch-linked-shows! over the config. It gives a
map of the :podroll and the :publisher, in ClojureScript as a promise,
or nil when the library has no such feed.
sourceraw docstring

fetch-remote-values!clj/s

(fetch-remote-values! library id)
(fetch-remote-values! library id opts)

Fetch the value blocks that the time splits of the episode id of library point at, with the opts of app.episode/fetch-remote-values! over the config. It gives a map of the :remote-values and the :remote-report, in ClojureScript as a promise, or nil when the library has no such episode.

Fetch the value blocks that the time splits of the episode `id` of
`library` point at, with the `opts` of app.episode/fetch-remote-values!
over the config. It gives a map of the :remote-values and the
:remote-report, in ClojureScript as a promise, or nil when the library
has no such episode.
sourceraw docstring

finish-downloadclj/s

(finish-download library id details)
(finish-download library id details opts)

The library with the download of the episode id finished at the time of the call, with opts, and the :path and :bytes of the file in details, as downloads/finish-download records it.

The `library` with the download of the episode `id` finished at the
time of the call, with `opts`, and the :path and :bytes of the file in
`details`, as downloads/finish-download records it.
sourceraw docstring

follow-listclj/s

(follow-list library url list)
(follow-list library url list opts)

The library following the OPML list at url, whose parse is list, with the opts below.

The opts give the :etag and :last-modified of the fetch, the :title of the list and the :folder for its shows. The shows of the list become subscriptions.

The `library` following the OPML list at `url`, whose parse is `list`,
with the `opts` below.

The `opts` give the :etag and :last-modified of the fetch, the :title of
the list and the :folder for its shows. The shows of the list become
subscriptions.
sourceraw docstring

hub-requestsclj/s

(hub-requests library subscriptions callback-fn)
(hub-requests library subscriptions callback-fn opts)

The requests to send the WebSub hubs of the feeds in library, by feed guid, given the subscriptions that websub-clj keeps by feed guid, with callback URLs from callback-fn and opts:

  • a subscription at the first hub of each show's feed, when the show has no subscription, or one that ended or is at another hub or topic
  • an unsubscription for each show that the listener left, or whose feed names no hub or is gone
  • the renewals and retries that websub/due returns

The callback-fn takes a feed guid and its subscription, which is nil for a new one, and returns a new callback URL, as in websub/due. A new subscription gets a secret from websub/token. Give each request to websub/asked before websub/call! sends it. The opts are those of websub/due, :at, and :allow-pred, which url/public? is by default, since the feeds choose the hubs.

The requests to send the WebSub hubs of the feeds in `library`, by feed
guid, given the `subscriptions` that websub-clj keeps by feed guid, with
callback URLs from `callback-fn` and `opts`:

- a subscription at the first hub of each show's feed, when the show has
  no subscription, or one that ended or is at another hub or topic
- an unsubscription for each show that the listener left, or whose feed
  names no hub or is gone
- the renewals and retries that websub/due returns

The `callback-fn` takes a feed guid and its subscription, which is nil
for a new one, and returns a new callback URL, as in websub/due. A new
subscription gets a secret from websub/token. Give each request to
websub/asked before websub/call! sends it. The `opts` are those of
websub/due, :at, and :allow-pred, which url/public? is by default, since
the feeds choose the hubs.
sourceraw docstring

identify!clj/s

(identify! library)
(identify! library opts)

Ask the directories for the ids of the shows of library that have none yet, with opts, as directory/identify! does, and keep them in the entries of their feeds. The views of a show and its episodes then link to it in the apps that know it by those ids. It gives the library with the :report of the directories that failed under :identify, in ClojureScript as a promise.

The Podcast Index is asked with the credentials of the :index of the config. The shows are asked about two at a time, since Apple limits how often it answers, and a show whose directory failed is asked again next time. A show of local files is never asked about, since no directory lists it. The opts are the config for this call, and :feed-guids, the shows to ask about, ids or not.

Ask the directories for the ids of the shows of `library` that have
none yet, with `opts`, as directory/identify! does, and keep them in
the entries of their feeds. The views of a show and its episodes then
link to it in the apps that know it by those ids. It gives the library
with the :report of the directories that failed under :identify, in
ClojureScript as a promise.

The Podcast Index is asked with the credentials of the :index of the
config. The shows are asked about two at a time, since Apple limits how
often it answers, and a show whose directory failed is asked again
next time. A show of local files is never asked about, since no
directory lists it. The `opts` are the config for this call, and
:feed-guids, the shows to ask about, ids or not.
sourceraw docstring

indexclj/s

(index library)

A search index of the feeds of library, e.g. for a library read back without its :index.

A search index of the feeds of `library`, e.g. for a library read back
without its :index.
sourceraw docstring

keep-fileclj/s

(keep-file library id keep?)

The library with the file of the episode id kept whatever the rules say, or no longer kept when keep? is false.

The `library` with the file of the episode `id` kept whatever the rules
say, or no longer kept when `keep?` is false.
sourceraw docstring

leave!clj/s

(leave! library backends)
(leave! library backends opts)

Retire this device of library from the listener's sync through backends, with the opts of like-minded/leave! except :cursors and :failures, e.g. when the listener turns sync off.

It writes the retirement through each backend once more, so that the other devices stop waiting for this one before they compact. It returns the library with the retired profile and the result under :sync, as sync! does, in ClojureScript as a promise. A retired device can't sync again, so to sync later, give the library a new device with with-device.

Retire this device of `library` from the listener's sync through
`backends`, with the `opts` of like-minded/leave! except :cursors and
:failures, e.g. when the listener turns sync off.

It writes the retirement through each backend once more, so that the
other devices stop waiting for this one before they compact. It returns
the library with the retired profile and the result under :sync, as
sync! does, in ClojureScript as a promise. A retired device can't sync
again, so to sync later, give the library a new device with
with-device.
sourceraw docstring

live-itemsclj/s

(live-items library)
(live-items library opts)

The live items of the subscriptions of library, as [feed item] pairs, at the :at of opts or the time of its clock: those on air first, then those to come, the soonest first, then those over, the latest first.

A live item plays by its id, [feed-guid item-guid], as an episode does, e.g. with playback.

The live items of the subscriptions of `library`, as [feed item] pairs,
at the :at of `opts` or the time of its clock: those on air first, then
those to come, the soonest first, then those over, the latest first.

A live item plays by its id, [feed-guid item-guid], as an episode does,
e.g. with playback.
sourceraw docstring

load!clj/s

(load! library store feed-guids)

The library with the feeds feed-guids read back from their documents in store, those that it doesn't hold in memory, in ClojureScript as a promise. With :all for feed-guids, it's every feed.

The result has the :report of what didn't read under :load. A feed whose document is missing or doesn't read keeps only its URL, so that the next refresh fetches it again, with :library/unreadable-document in the report.

The `library` with the feeds `feed-guids` read back from their
documents in `store`, those that it doesn't hold in memory, in
ClojureScript as a promise. With :all for `feed-guids`, it's every feed.

The result has the :report of what didn't read under :load. A feed
whose document is missing or doesn't read keeps only its URL, so that
the next refresh fetches it again, with :library/unreadable-document in
the report.
sourceraw docstring

loaded?clj/s

(loaded? library feed-guid)

Whether library holds the feed feed-guid in memory, rather than only in the document that a save wrote, as after restore! with :load or after unload!.

Whether `library` holds the feed `feed-guid` in memory, rather than only
in the document that a save wrote, as after restore! with :load or after
unload!.
sourceraw docstring

makeclj/s

(make device)
(make device {:keys [config] :as opts})

A library for the device device, made with the opts below.

The device is a stable id that tells the listener's devices apart, made once per installation. The opts describe the device for the other devices, such as its :name and :platform, and give the :config.

A library for the device `device`, made with the `opts` below.

The `device` is a stable id that tells the listener's devices apart,
made once per installation. The `opts` describe the device for the other
devices, such as its :name and :platform, and give the :config.
sourceraw docstring

mark-show-playedclj/s

(mark-show-played library feed-guid)
(mark-show-played library feed-guid opts)

The library with every episode of the show feed-guid marked as played with one stamp, with opts, e.g. for a show that the listener heard elsewhere. The time is that of the clock unless the opts give :at.

The `library` with every episode of the show `feed-guid` marked as
played with one stamp, with `opts`, e.g. for a show that the listener
heard elsewhere. The time is that of the clock unless the `opts` give
:at.
sourceraw docstring

mergeclj/s

(merge library result)

The library with result merged in, a library that came from an earlier value of library, e.g. by a refresh or a sync.

The profiles merge, so nothing that the listener did meanwhile is lost. A feed or a list stays only while the merged profile subscribes to it, has a remote item of it, or follows it, so one that the listener left on another device goes. Of two entries of one feed or list, the later fetch wins. The later :refresh and :sync are kept too, and the rest is that of library.

The `library` with `result` merged in, a library that came from an
earlier value of `library`, e.g. by a refresh or a sync.

The profiles merge, so nothing that the listener did meanwhile is lost.
A feed or a list stays only while the merged profile subscribes to it,
has a remote item of it, or follows it, so one that the listener left
on another device goes. Of two entries of one feed or list, the later
fetch wins. The later :refresh and :sync are kept too, and the rest is
that of `library`.
sourceraw docstring

migrationsclj/s

The migration of a saved library from each version to the next, by the version it takes, each a function of the saved map.

Version 1 holds the feeds inline, and they stay so until the next save writes them out as documents. Version 2 holds an entry for each setting of a subscription. Version 3 has no archive, so it reads as it is.

The migration of a saved library from each version to the next, by the
version it takes, each a function of the saved map.

Version 1 holds the feeds inline, and they stay so until the next save
writes them out as documents. Version 2 holds an entry for each setting
of a subscription. Version 3 has no archive, so it reads as it is.
sourceraw docstring

next-refreshclj/s

(next-refresh library)
(next-refresh library opts)

When library should refresh again, with opts: when the first of its feeds and followed lists is due, or nil when it has none to fetch. The result is never before the time of the call.

The feed of a subscription that was never fetched is due at once, unless the last refresh failed to fetch it. Then it waits the first wait of the :after-failure of the cadence, as a feed that failed once does. A feed that's gone, of local files or held for remote items alone is never due. After a refresh that found the device offline, the next waits the :offline-seconds of the config.

When `library` should refresh again, with `opts`: when the first of its
feeds and followed lists is due, or nil when it has none to fetch. The
result is never before the time of the call.

The feed of a subscription that was never fetched is due at once, unless
the last refresh failed to fetch it. Then it waits the first wait of the
:after-failure of the cadence, as a feed that failed once does. A feed
that's gone, of local files or held for remote items alone is never
due. After a refresh that found the device offline, the next waits the
:offline-seconds of the config.
sourceraw docstring

next-syncclj/s

(next-sync library)
(next-sync library opts)

When library should sync again, with opts: right away before the first sync, and sooner when the profile changed since the last one.

When `library` should sync again, with `opts`: right away before the
first sync, and sooner when the profile changed since the last one.
sourceraw docstring

notificationsclj/s

(notifications library)

The new episodes that the last refresh of library found in the shows that announce theirs, by show, the show with the newest episode first:

[{:feed-guid "…" :title "The Daily" :artwork "https://…"
  :episodes  [{:id [feed-guid item-guid] :title "…"
               :published #inst "…"}]}]

A show announces its new episodes when its :notify? setting says so, or else the listener's preference, as profile/notifies? says. An episode that the listener played already is left out.

The new episodes that the last refresh of `library` found in the shows
that announce theirs, by show, the show with the newest episode first:

    [{:feed-guid "…" :title "The Daily" :artwork "https://…"
      :episodes  [{:id [feed-guid item-guid] :title "…"
                   :published #inst "…"}]}]

A show announces its new episodes when its :notify? setting says so,
or else the listener's preference, as profile/notifies? says. An
episode that the listener played already is left out.
sourceraw docstring

opml-nameclj/s

The name of the subscription list that a backend with :opml? writes beside the documents, for any podcast app to import.

The name of the subscription list that a backend with :opml? writes
beside the documents, for any podcast app to import.
sourceraw docstring

planclj/s

(plan library)
(plan library files)
(plan library files opts)

The episodes to download and the files to delete on this device with files, for the profile and feeds of library, with the opts of downloads/plan. Without files, it's the record of the files in the library.

It plans with the feeds that the library holds in memory. The files of the episodes of a feed that it doesn't hold are kept, so load! every feed first for a plan of them all. A show of local files has nothing to download.

The episodes to download and the files to delete on this device with
`files`, for the profile and feeds of `library`, with the `opts` of
downloads/plan. Without `files`, it's the record of the files in the
library.

It plans with the feeds that the library holds in memory. The files of
the episodes of a feed that it doesn't hold are kept, so load! every
feed first for a plan of them all. A show of local files has nothing to
download.
sourceraw docstring

playbackclj/s

(playback library id)
(playback library id {:keys [read] :as opts})

What a player needs for the episode id of library, with the opts of episode over the config, or nil when the library has no such episode:

{:id         [feed-guid item-guid]
 :src        "https://…/7.mp3"   ; the file to play
 :local?     false                ; whether the file is on the device
 :enclosure  {:url "…" :type "audio/mpeg" …}
 :position   754.0                ; where to start, in seconds
 :duration   3612.0               ; when it's known
 :rate       1.5
 :played?    false
 :title      "…" :show "…" :artwork "https://…"
 :poster     "https://…"         ; of a video, before it plays
 :chapters   {:source :embedded :document {…}}  ; in the feed itself
 :chapters-url "https://…"                    ; a file of chapters
 :transcript {:url "…" :type "text/vtt" …}   ; e.g. for captions
 :metadata   {…}}                 ; for the Media Session

The file to play is the downloaded one, which the :local-file-fn of the options gives for the id, e.g. an object URL, or else the record of the files in the library, and otherwise the enclosure, which is on the device for a show of local files. With :read, what read-files! gave for the episode, its chapters and measured duration go over those of the feed. The keys without a value are left out, and app.episode/metadata gives the metadata.

What a player needs for the episode `id` of `library`, with the `opts`
of episode over the config, or nil when the library has no such
episode:

    {:id         [feed-guid item-guid]
     :src        "https://…/7.mp3"   ; the file to play
     :local?     false                ; whether the file is on the device
     :enclosure  {:url "…" :type "audio/mpeg" …}
     :position   754.0                ; where to start, in seconds
     :duration   3612.0               ; when it's known
     :rate       1.5
     :played?    false
     :title      "…" :show "…" :artwork "https://…"
     :poster     "https://…"         ; of a video, before it plays
     :chapters   {:source :embedded :document {…}}  ; in the feed itself
     :chapters-url "https://…"                    ; a file of chapters
     :transcript {:url "…" :type "text/vtt" …}   ; e.g. for captions
     :metadata   {…}}                 ; for the Media Session

The file to play is the downloaded one, which the :local-file-fn of the
options gives for the id, e.g. an object URL, or else the record of the
files in the library, and otherwise the enclosure, which is on the
device for a show of local files. With :read, what read-files! gave for
the episode, its chapters and measured duration go over those of the
feed. The keys without a value are left out, and app.episode/metadata
gives the metadata.
sourceraw docstring

pushedclj/s

(pushed library feed-guid delivery)
(pushed library feed-guid {:keys [body content-type] :as delivery} opts)

The library after a WebSub hub pushed the feed feed-guid in delivery, the map that :deliver! of websub/handler receives, with opts.

The body is parsed as fetch! parses a feed. The new episodes join the queue or the inbox as after a refresh, and :refresh holds the result. Since a hub can push only what changed, a push removes no episode (see app.feeds/pushed). When a push can't be applied, the feed is due at once, so the next refresh fetches it, and the report says why. A push of a feed that the library doesn't have changes nothing.

The `library` after a WebSub hub pushed the feed `feed-guid` in
`delivery`, the map that :deliver! of websub/handler receives, with
`opts`.

The body is parsed as fetch! parses a feed. The new episodes join the
queue or the inbox as after a refresh, and :refresh holds the result.
Since a hub can push only what changed, a push removes no episode (see
app.feeds/pushed). When a push can't be applied, the feed is due at once,
so the next refresh fetches it, and the report says why. A push of a
feed that the library doesn't have changes nothing.
sourceraw docstring

read-files!clj/s

(read-files! library id)
(read-files! library id opts)

Read the files of the episode id of library, with the opts of app.episode/read-files! over the config. It gives a map of the :chapters, the :transcript and the :media, in ClojureScript as a promise, or nil when the library has no such episode. The media file is the one that the episode's view chooses.

Read the files of the episode `id` of `library`, with the `opts` of
app.episode/read-files! over the config. It gives a map of the
:chapters, the :transcript and the :media, in ClojureScript as a
promise, or nil when the library has no such episode. The media file is
the one that the episode's view chooses.
sourceraw docstring

refresh!clj/s

(refresh! library)
(refresh! library opts)

Fetch and apply whatever library is due to fetch, with the opts below.

It fetches the followed lists, the feeds of new subscriptions and remote items, and the feeds of subscriptions whose next check has come. A feed held for remote items alone isn't fetched again, unless :feed-guids names it. It returns the library with the result under :refresh, in ClojureScript as a promise:

{:at         #inst "…"
 :added      [[feed-guid item-guid] …]  ; the new episodes
 :backfilled [[feed-guid item-guid] …]  ; older ones that appeared
 :renamed    [[old-id new-id] …]        ; episodes under a new guid,
                                        ; which took their state along
 :moved      {feed-guid "https://…"}   ; the feeds that moved, and so
                                        ; their subscriptions
 :counts     {:checked 120 :unchanged 104 :changed 14 :failed 2
              :left 0}
 :seconds    4.2                        ; how long it took
 :report     [...]}                     ; the fetches that failed, and why

Only the new episodes join the queue or the inbox. Nothing is thrown for what the network or a server does. The opts are the config for this call, and these:

  • :feed-guids, the feeds to fetch instead of those that are due, e.g. those that a Podping names
  • :online?, false when the device has no network, so that nothing is fetched
  • :max-feeds, :max-seconds, :on-feed-fn and :signal, to fetch fewer feeds or within a deadline, to hear of each fetch as it ends, and to stop, as app.feeds/refresh! takes them. The feeds left out stay due, and the :left of the :counts says how many there are.
  • :store, the store that the library is saved to, from which it loads the feeds that it fetches and doesn't hold, as load! does. Without it, such a feed isn't fetched, and the report has :library/not-loaded.

A refresh in which every fetch of a feed failed before a server answered, at more than one host, counts as offline too. Offline, no feed or list counts it as a failure, each stays due for the next refresh, and the report has :refresh/offline.

Fetch and apply whatever `library` is due to fetch, with the `opts`
below.

It fetches the followed lists, the feeds of new subscriptions and remote
items, and the feeds of subscriptions whose next check has come. A feed
held for remote items alone isn't fetched again, unless :feed-guids
names it. It returns the library with the result under :refresh, in
ClojureScript as a promise:

    {:at         #inst "…"
     :added      [[feed-guid item-guid] …]  ; the new episodes
     :backfilled [[feed-guid item-guid] …]  ; older ones that appeared
     :renamed    [[old-id new-id] …]        ; episodes under a new guid,
                                            ; which took their state along
     :moved      {feed-guid "https://…"}   ; the feeds that moved, and so
                                            ; their subscriptions
     :counts     {:checked 120 :unchanged 104 :changed 14 :failed 2
                  :left 0}
     :seconds    4.2                        ; how long it took
     :report     [...]}                     ; the fetches that failed, and why

Only the new episodes join the queue or the inbox. Nothing is thrown for
what the network or a server does. The `opts` are the config for this
call, and these:

- :feed-guids, the feeds to fetch instead of those that are due, e.g.
  those that a Podping names
- :online?, false when the device has no network, so that nothing is
  fetched
- :max-feeds, :max-seconds, :on-feed-fn and :signal, to fetch fewer
  feeds or within a deadline, to hear of each fetch as it ends, and to
  stop, as app.feeds/refresh! takes them. The feeds left out stay due,
  and the :left of the :counts says how many there are.
- :store, the store that the library is saved to, from which it loads
  the feeds that it fetches and doesn't hold, as load! does. Without
  it, such a feed isn't fetched, and the report has :library/not-loaded.

A refresh in which every fetch of a feed failed before a server
answered, at more than one host, counts as offline too. Offline, no feed
or list counts it as a failure, each stays due for the next refresh,
and the report has :refresh/offline.
sourceraw docstring

remove-episodeclj/s

(remove-episode library id)
(remove-episode library [feed-guid :as id] opts)

The library without the remote item id, with the :at of opts. The feed of the episode goes too, when no subscription or other remote item needs it, and the queue and the progress stay as they are.

The `library` without the remote item `id`, with the :at of `opts`. The
feed of the episode goes too, when no subscription or other remote item
needs it, and the queue and the progress stay as they are.
sourceraw docstring

remove-fileclj/s

(remove-file library id)
(remove-file library id opts)

The library without the file of the episode id, deleted at the time of the call, with opts. The entry stays, so that no plan downloads it again.

The `library` without the file of the episode `id`, deleted at the time
of the call, with `opts`. The entry stays, so that no plan downloads it
again.
sourceraw docstring

remove-played-episodesclj/s

(remove-played-episodes library)
(remove-played-episodes library opts)

The library without the remote items that the listener played, with the :at of opts, e.g. to tidy up the episodes that the listener took from other shows.

They leave the queue and the playlists too, and their feeds go when nothing else needs them. One that the listener starred, bookmarked, clipped or rated stays.

The `library` without the remote items that the listener played, with
the :at of `opts`, e.g. to tidy up the episodes that the listener took
from other shows.

They leave the queue and the playlists too, and their feeds go when
nothing else needs them. One that the listener starred, bookmarked,
clipped or rated stays.
sourceraw docstring

restore!clj/s

(restore! library store)
(restore! library
          store
          {:keys [keys load] :or {keys saved-keys load :all} :as opts})

The library with what was saved to store, read with the opts below, and with the result under :restore, in ClojureScript as a promise.

The parts of library.edn that :keys in opts names, saved-keys by default, replace those of library, so give it a new library, and each feed is read from its document. A library saved by an older version is brought up to this one. When the library keeps a search index, it's read back, or built again from the feeds when its documents are missing or don't read. The result is a map of the :report of what didn't read:

{:report [...]}  ; :library/unreadable-document, :library/index-rebuilt,
                 ; :library/malformed-profile, :library/newer-format

A store without the documents gives the library as it is, and so does a library saved by a newer version, which save! then won't write over.

The :load of opts says which feeds to read: :all by default, :none, or the guids of some. The others stay in their documents until load! reads them, e.g. the feeds of the shows on the screen, and the views mark them as not loaded.

The `library` with what was saved to `store`, read with the `opts`
below, and with the result under :restore, in ClojureScript as a
promise.

The parts of library.edn that :keys in `opts` names, saved-keys by
default, replace those of `library`, so give it a new library, and each
feed is read from its document. A library saved by an older version is
brought up to this one. When the library keeps a search index, it's read
back, or built again from the feeds when its documents are missing or
don't read. The result is a map of the :report of what didn't read:

    {:report [...]}  ; :library/unreadable-document, :library/index-rebuilt,
                     ; :library/malformed-profile, :library/newer-format

A store without the documents gives the library as it is, and so does a
library saved by a newer version, which save! then won't write over.

The :load of `opts` says which feeds to read: :all by default, :none, or
the guids of some. The others stay in their documents until load!
reads them, e.g. the feeds of the shows on the screen, and the views
mark them as not loaded.
sourceraw docstring

save!clj/s

(save! library store)
(save! library store {:keys [keys] :or {keys saved-keys} :as opts})

Write library to store with the opts below, and give the names of the documents it put and deleted, as a map of :put and :delete, or a map of :error, in ClojureScript as a promise.

It writes library.edn, with the parts of library that :keys in opts names, saved-keys by default, and the version of their shape. Each feed goes to a document of its own, which is put when the feed changed since the last save, and the documents of the feeds that changed or went are deleted. When the library keeps a search index, it writes the documents of the index that changed since the last save, and deletes those that the index no longer needs. One that it couldn't delete is left out of :delete for the next save to delete, and a store without :delete keeps them all. Give it a store of its own, e.g. over a folder, IndexedDB or the origin private file system, since it deletes the documents of any other library there.

The :error is :library/save-failed when the store failed, and :library/newer-format when library was restored from a library of a newer version, which it doesn't write over.

Write `library` to `store` with the `opts` below, and give the names of
the documents it put and deleted, as a map of :put and :delete, or a
map of :error, in ClojureScript as a promise.

It writes library.edn, with the parts of `library` that :keys in `opts`
names, saved-keys by default, and the version of their shape. Each feed
goes to a document of its own, which is put when the feed changed since
the last save, and the documents of the feeds that changed or went are
deleted. When the library keeps a search index, it writes the documents
of the index that changed since the last save, and deletes those that
the index no longer needs. One that it couldn't delete is left out of
:delete for the next save to delete, and a store without :delete keeps
them all. Give it a store of its own, e.g. over a folder, IndexedDB or
the origin private file system, since it deletes the documents of any
other library there.

The :error is :library/save-failed when the store failed, and
:library/newer-format when `library` was restored from a library of a
newer version, which it doesn't write over.
sourceraw docstring

saved-keysclj/s

The parts of a library that are saved by default: the profile, the feeds, the followed lists, the last sync, whose cursors fit the profile, and the downloaded files.

The parts of a library that are saved by default: the profile, the
feeds, the followed lists, the last sync, whose cursors fit the profile,
and the downloaded files.
sourceraw docstring

saved-nameclj/s

The name of the document of a saved library.

The name of the document of a saved library.
sourceraw docstring

(search library q)
(search library q opts)

The episodes and shows of library that match the query q, best first, with the opts below, or nil when the library keeps no index.

Each result has its :feed, and an episode its :item. The words that matched with typos are in the metadata. The opts are those of dk.simongray.drop-in-search/query, whose :filter-pred gets the result with them, and :where, the criteria of criteria/where that an episode must meet, which leaves the shows out. The criteria read the profile of the library, and the time of its clock unless the opts give :at.

(search library "value for va" {:where {:status :unplayed}})
The episodes and shows of `library` that match the query `q`, best
first, with the `opts` below, or nil when the library keeps no index.

Each result has its :feed, and an episode its :item. The words that
matched with typos are in the metadata. The `opts` are those of
dk.simongray.drop-in-search/query, whose :filter-pred gets the result
with them, and :where, the criteria of criteria/where that an episode
must meet, which leaves the shows out. The criteria read the profile of
the library, and the time of its clock unless the `opts` give :at.

    (search library "value for va" {:where {:status :unplayed}})
sourceraw docstring

showclj/s

(show library feed-guid)
(show library feed-guid opts)

The view of the show feed-guid of library, with the opts of app.show/view, or nil when the library has no such feed. Its episodes have their :retained facts.

The :title is the listener's :custom-title of the show, and the :episodes are in the :order that the listener chose for it, as profile/default-settings has them.

A feed that the library doesn't hold in memory gives only its :url, its :title and its :artwork, as the profile knows them, and :unloaded? true. Read it back with load!.

The view of the show `feed-guid` of `library`, with the `opts` of
app.show/view, or nil when the library has no such feed. Its episodes
have their :retained facts.

The :title is the listener's :custom-title of the show, and the
:episodes are in the :order that the listener chose for it, as
profile/default-settings has them.

A feed that the library doesn't hold in memory gives only its :url,
its :title and its :artwork, as the profile knows them, and
:unloaded? true. Read it back with load!.
sourceraw docstring

showsclj/s

(shows library)

The subscriptions of library in the listener's order, as profile/shows gives it, each as a map for a screen of shows:

{:feed-guid "…"
 :title     "…"           ; the listener's own title, or the feed's
 :artwork   "https://…"
 :newest    #inst "…"     ; when the newest episode came out
 :counts    {:episodes 40 :unplayed 12 :in-progress 1 :played 27
             :inbox 2 :queued 1}}

The counts are of the episodes that the library keeps of each show, and of those of its episodes in the inbox and the queue. A show whose feed isn't fetched yet counts only the inbox and the queue, and so does one whose feed isn't loaded, which has :unloaded? true.

The subscriptions of `library` in the listener's order, as profile/shows
gives it, each as a map for a screen of shows:

    {:feed-guid "…"
     :title     "…"           ; the listener's own title, or the feed's
     :artwork   "https://…"
     :newest    #inst "…"     ; when the newest episode came out
     :counts    {:episodes 40 :unplayed 12 :in-progress 1 :played 27
                 :inbox 2 :queued 1}}

The counts are of the episodes that the library keeps of each show, and
of those of its episodes in the inbox and the queue. A show whose feed
isn't fetched yet counts only the inbox and the queue, and so does one
whose feed isn't loaded, which has :unloaded? true.
sourceraw docstring

snippetclj/s

(snippet library result q)
(snippet library result q opts)

A window of the text of the result that search gave for the query q in library, around the words that match, with the opts of feed.search/snippet, or nil when no field of the result matches or the library keeps no index.

(snippet library result "value for va")
;; => {:field :description
;;     :parts [{:text "…on "} {:text "value" :match? true} …]}
A window of the text of the `result` that search gave for the query `q`
in `library`, around the words that match, with the `opts` of
feed.search/snippet, or nil when no field of the result matches or the
library keeps no index.

    (snippet library result "value for va")
    ;; => {:field :description
    ;;     :parts [{:text "…on "} {:text "value" :match? true} …]}
sourceraw docstring

start-downloadclj/s

(start-download library entry)
(start-download library entry opts)

The library with the download of entry, one of the :download of its plan, started at the time of the call, with opts, as downloads/start-download records it.

The `library` with the download of `entry`, one of the :download of
its plan, started at the time of the call, with `opts`, as
downloads/start-download records it.
sourceraw docstring

stepclj/s

(step library event)
(step library event opts)

The library after the player event, with opts, both as profile.player/step takes them.

It has the new profile, the :effects to apply, and what's left of the :sleep timer of this device. The opts go over the :sleep of the library. With the listener's :continuous?, an episode that ends with no other queued is followed by the first unplayed episode of its show in the listening order: the next of a serial show, and the newest of an episodic one.

The `library` after the player `event`, with `opts`, both as
profile.player/step takes them.

It has the new profile, the :effects to apply, and what's left of
the :sleep timer of this device. The `opts` go over the :sleep of
the library. With the listener's :continuous?, an episode that ends
with no other queued is followed by the first unplayed episode of its
show in the listening order: the next of a serial show, and the newest
of an episodic one.
sourceraw docstring

subscribeclj/s

(subscribe library url)
(subscribe library url fetched)
(subscribe library url fetched opts)

The library subscribed to the feed at url, with what was fetched and the settings in opts.

The fetched is the result of dk.simongray.podcast/fetch! or a parsed feed, and the opts are as profile/configure takes them, besides :at. Without fetched, or with nil, the feed is fetched at the next refresh, and the subscription has the guid of the URL until then. The start of a feed that discovery/fetch-head! gave counts as no feed, but for the title, the artwork and the guid that it declares. The key of a subscription is the guid that its feed gives itself when it's first fetched, on any device, and stays when the feed gives itself another.

It throws when fetched has no feed, e.g. after a fetch that failed, and when the feed declares the guid of another subscription, at another URL, since the feed would take that subscription over. The ex-data is the diagnostic of the fetch, or :fetch/guid-taken. To replace the other subscription, unsubscribe from it first.

The `library` subscribed to the feed at `url`, with what was `fetched`
and the settings in `opts`.

The `fetched` is the result of dk.simongray.podcast/fetch! or a parsed
feed, and the `opts` are as profile/configure takes them, besides :at.
Without `fetched`, or with nil, the feed is fetched at the next refresh,
and the subscription has the guid of the URL until then. The start of a
feed that discovery/fetch-head! gave counts as no feed, but for the
title, the artwork and the guid that it declares. The key of a
subscription is the guid that its feed gives itself when it's first
fetched, on any device, and stays when the feed gives itself another.

It throws when `fetched` has no feed, e.g. after a fetch that failed,
and when the feed declares the guid of another subscription, at another
URL, since the feed would take that subscription over. The ex-data is
the diagnostic of the fetch, or :fetch/guid-taken. To replace the other
subscription, unsubscribe from it first.
sourceraw docstring

subscribe-localclj/s

(subscribe-local library feed)
(subscribe-local library feed opts)

The library subscribed to the show of local files feed, which feed.local/feed built, with the settings in opts, besides :at.

The feed stays on this device, as its files do, and no refresh fetches it, so subscribe again with the files as they are when they change. The profile syncs the subscription and the progress of the episodes, so a device with the same files, which make the same guids, shares them, and one without them lists the show by its title. An image that's a data URL stays out of the profile.

The `library` subscribed to the show of local files `feed`, which
feed.local/feed built, with the settings in `opts`, besides :at.

The feed stays on this device, as its files do, and no refresh fetches
it, so subscribe again with the files as they are when they change. The
profile syncs the subscription and the progress of the episodes, so a
device with the same files, which make the same guids, shares them, and
one without them lists the show by its title. An image that's a data URL
stays out of the profile.
sourceraw docstring

subscriptionsclj/s

(subscriptions library)

The live subscriptions of library by guid, each with its :settings, defaults included, and its :feed once it's fetched.

The live subscriptions of `library` by guid, each with its :settings,
defaults included, and its :feed once it's fetched.
sourceraw docstring

sync!clj/s

(sync! library backends)
(sync! library backends opts)

Sync library with the listener's other devices through backends, with the opts of like-minded/sync! except :cursors and :failures.

It keeps the cursors for the next sync, and compacts the profile as profile/compact does, with the :archive-after of the config. It returns the library with the result under :sync, in ClojureScript as a promise:

{:cursors  {…}         ; those of the stores, for the next sync
 :at       #inst "…"
 :clock    #inst "…"   ; the clock of the profile after the sync
 :failures 0           ; the syncs in a row in which a backend failed
 :report   [...]}      ; with :sync/backend-failed for each that did
Sync `library` with the listener's other devices through `backends`,
with the `opts` of like-minded/sync! except :cursors and :failures.

It keeps the cursors for the next sync, and compacts the profile as
profile/compact does, with the :archive-after of the config. It returns
the library with the result under :sync, in ClojureScript as a promise:

    {:cursors  {…}         ; those of the stores, for the next sync
     :at       #inst "…"
     :clock    #inst "…"   ; the clock of the profile after the sync
     :failures 0           ; the syncs in a row in which a backend failed
     :report   [...]}      ; with :sync/backend-failed for each that did
sourceraw docstring

to-opmlclj/s

(to-opml library)

The subscriptions of library as an OPML subscription list, as profile.opml/to-opml gives it, with the episodes that the listener played, started or hid, as Overcast's extended export writes them, by the media of the feeds that the library has.

The subscriptions of `library` as an OPML subscription list, as
profile.opml/to-opml gives it, with the episodes that the listener
played, started or hid, as Overcast's extended export writes them, by
the media of the feeds that the library has.
sourceraw docstring

unfollow-listclj/s

(unfollow-list library url)
(unfollow-list library url opts)

The library no longer following the list at url, with opts.

The `library` no longer following the list at `url`, with `opts`.
sourceraw docstring

unload!clj/s

(unload! library store feed-guids)

The library without the feeds feed-guids in memory, each written to its document in store first, in ClojureScript as a promise. With :all for feed-guids, it's every feed.

The entry of each feed keeps the name of its document, and load! or a refresh with the store reads it back. The views show the feed as not loaded meanwhile, e.g. on a server, which needs no feed between its refreshes, or on a phone, which needs only those on the screen.

The result has the :report under :unload. When the store fails, the feeds stay in memory, and the report has :library/save-failed.

The `library` without the feeds `feed-guids` in memory, each written to
its document in `store` first, in ClojureScript as a promise. With :all
for `feed-guids`, it's every feed.

The entry of each feed keeps the name of its document, and load! or a
refresh with the store reads it back. The views show the feed as not
loaded meanwhile, e.g. on a server, which needs no feed between its
refreshes, or on a phone, which needs only those on the screen.

The result has the :report under :unload. When the store fails, the
feeds stay in memory, and the report has :library/save-failed.
sourceraw docstring

unloadedclj/s

(unloaded library)

The guids of the feeds that library keeps in their documents alone, for load! to read back.

The guids of the feeds that `library` keeps in their documents alone,
for load! to read back.
sourceraw docstring

unsubscribeclj/s

(unsubscribe library feed-guid)
(unsubscribe library feed-guid opts)

The library unsubscribed from the feed feed-guid, with opts. The feed and its search documents go, but for the episodes of its remote items, and the profile keeps a record of the subscription.

The `library` unsubscribed from the feed `feed-guid`, with `opts`. The
feed and its search documents go, but for the episodes of its remote
items, and the profile keeps a record of the subscription.
sourceraw docstring

unsynced?clj/s

(unsynced? library)

Whether the profile of library changed since its last sync, by the clock of the profile.

Whether the profile of `library` changed since its last sync, by the
clock of the profile.
sourceraw docstring

update-profileclj/s

(update-profile library f & args)

The library with its profile replaced by what f gives for it, the args and the time of the clock, in that order. For a series of changes at one time, give a function of the profile and the time.

The `library` with its profile replaced by what `f` gives for it, the
`args` and the time of the clock, in that order. For a series of changes
at one time, give a function of the profile and the time.
sourceraw docstring

urlsclj/s

(urls library)

A map from each feed of library, with the episodes that it lists, to its URL.

A map from each feed of `library`, with the episodes that it lists, to
its URL.
sourceraw docstring

versionclj/s

The version of the shape of a saved library: 4 since a played episode can be in the archive alone, 3 since the settings of a subscription are one entry, 2 since each feed went to a document of its own. A saved library without one is version 1.

The version of the shape of a saved library: 4 since a played episode
can be in the archive alone, 3 since the settings of a subscription are
one entry, 2 since each feed went to a document of its own. A saved
library without one is version 1.
sourceraw docstring

with-deviceclj/s

(with-device library device)
(with-device library device opts)

The library as that of the new device, described for the other devices by the opts that make takes, e.g. to sync again after leave!.

The profile keeps what it holds, and the next sync starts afresh, as the first sync of a new device does.

The `library` as that of the new `device`, described for the other
devices by the `opts` that make takes, e.g. to sync again after leave!.

The profile keeps what it holds, and the next sync starts afresh, as the
first sync of a new device does.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close