Skip to content
@deckyard/jellyfin

@deckyard/jellyfin

Jellyfin is a self-hosted media server for films, shows, music and photos. This deck is a client for its REST API: sign in, browse and search what a user sees, keep track of what was played, fetch posters, and look after the server (users, library scans, scheduled tasks, the clients playing right now).

  • Signing in: passwords, API keys, users, devices.
  • The library: libraries, items, paging, search, resume, next up, played and favourite marks, images.
  • Administration: the server, users, scans, tasks, sessions.
  • Cheatsheet: every export.

Conventions

Snippets assume this import:

jennifer
import "@deckyard/jellyfin/" as jellyfin;

A request the server refused throws jellyfin.HttpError, kind jellyfin.http, with the HTTP status and the validation errors as fields; any other failure is Error{kind: "jellyfin"} (a cancelled task stays "task cancelled"):

jennifer
try {
    def it as jellyfin.Item init jellyfin.item($c, $id);
} catch (e) {
    if ($e.kind == "jellyfin.http" and $e.status == 404) {
        io.printf("no such item\n");
    } else {
        throw $e;
    }
}

Every request has a deadline (30 s) and a response cap (16 MiB). Plain http is refused except to this machine, because the password and token would cross the network in clear; a server on the LAN without TLS needs withPlainHttp. Ids, query parameter names and paths are checked before they go into a URL.

The deck follows the Jellyfin 10.9-and-later API (user ids as query parameters, /UserViews, /UserItems/Resume, /UserPlayedItems). It needs the net capability and does not run on jennifer-tiny.