fix(remote): forward dl track selection and profile to remote sessions

Remote sessions now carry -l/-vl/-al/-a/-fs under a nested dl_params, so services fetch the requested audio versions. Server-account tokens for non-default accounts move from default to the account name, so each account logs in once after upgrade.
This commit is contained in:
imSp4rky
2026-09-22 12:52:05 -06:00
parent b988951e17
commit db771a13c6
10 changed files with 805 additions and 77 deletions
+31 -1
View File
@@ -143,6 +143,7 @@ Find titles in a service by query string. The service must have a `search()` met
| `profile` | string | no | `null` | Credential/cookie profile to use. |
| `proxy` | string | no | `null` | Full proxy URI, or a country code when the API key has `server_proxy`. |
| `no_proxy` | boolean | no | `false` | Force-disable all proxy use. |
| `credentials`, `cookies`, `cache` | - | no | `null` | Your own login material, on a `--remote-only` server only. See [Client cache on a remote-only server](#client-cache-on-a-remote-only-server). |
=== "Request"
@@ -192,9 +193,34 @@ Get the list of titles behind a title ID, for example episodes or a movie, witho
| `proxy` | string | no | Full proxy URI, or a country code when the API key has `server_proxy`. |
| `no_proxy` | boolean | no | Force-disable proxy. |
| `cdm_type` | string | no | Preferred CDM type. |
| `credentials`, `cookies`, `cache` | - | no | Your own login material, on a `--remote-only` server only. See [Client cache on a remote-only server](#client-cache-on-a-remote-only-server). |
You can also pass service-specific CLI options as additional keys.
#### Client cache on a remote-only server
A `--remote-only` server keeps nothing that a client sends. When the request
does not use a server account, the server runs `search`, `list-titles` and
`list-tracks` on a new service cache directory for that request only, and
removes the directory when the request ends, on success and on error. A
`--remote-only` server exposes only `search` of these three endpoints, so the
rule applies to `list-titles` and `list-tracks` only if a later release exposes
them in that mode.
`credentials` (`{username, password, extra?}`) and `cookies` (base64 of a
zlib-compressed Netscape cookie file) are the same as on
[`POST /api/session/create`](#post-apisessioncreate). `cache` is a map of cache
files in the same form: each cache key is the file path relative to the service cache
directory, with `/` separators and no `.json` suffix, and each value is base64
of the zlib-compressed file. The server writes these files into the request
cache directory before the service authenticates.
When you send `credentials`, `cookies` or `cache`, a successful response also
has a `cache` field in the same form, with the updated files (for example a
refreshed token), but no `titles_` files. Save them to send with the next
request. A request that uses a server account, or a request to a full-mode
server, uses the server's own cache and returns no `cache` field.
=== "Request"
```bash
@@ -278,6 +304,8 @@ Show the video, audio, and subtitle tracks for a title. For series, you can scop
| `episode` | int/string | no | Episode number (combined with `season`). |
| `part` | int/string | no | Part index of a split episode (combined with `season` and `episode`). |
| `profile`, `proxy`, `no_proxy`, `cdm_type` | - | no | As on `list-titles`. |
| `credentials`, `cookies`, `cache` | - | no | As on `list-titles`. |
| `dl_params` | object | no | The `dl` track selection that the service reads from `ctx.parent.params`: `lang`, `v_lang`, `a_lang`, `acodec` and `forced_subs`, as on [`POST /api/session/create`](#post-apisessioncreate). Some services select the manifests they fetch from these values. |
When you give both `season` and `episode`, the server combines them into a `"{season}x{episode}"` selector. `part` narrows that to `"{season}x{episode}.{part}"`, one part of a [split episode](../creating-a-service.md#split-episodes). Without `part` you get every part of the episode. The server reads `part` only when you give both `season` and `episode`, and `wanted` takes precedence over all three. To scope a part by range, put it in `wanted` instead (`"S01E01.2"`).
@@ -857,7 +885,9 @@ DELETE /api/session/{id} → tear down, harvest updated cache
### `POST /api/session/create`
Make a remote session for a service and title. Authentication runs asynchronously in the background. This call returns immediately with `status: "authenticating"`, and you then poll the prompt endpoint. The body accepts `service` and `title_id` (both required). It also accepts a broad set of optional keys, because the body allows `additionalProperties`. These are `credentials` (`{username, password, extra?}`), `cookies` (base64 of zlib-compressed Netscape cookie file), `proxy`, `no_proxy`, `profile`, `cache` (map of forwarded cache files, keyed by the file path relative to the service cache directory with `/` separators and no `.json` suffix, so a nested key such as `session_web/<sha1>` lands in a subdirectory), `client_region`, `proxy_region`, `cdm_type`, `range_`, `vcodec`, `quality`, `best_available`, `client`, and any service CLI options. `proxy_region` is the country code the client resolved `proxy` from; the server matches it against its own accounts. `client` is a freeform object the dashboard shows as sent (the CLI puts `version`, `code_hash`, `platform` and a redacted `argv` in it); the server ignores it above 4096 bytes of JSON.
Make a remote session for a service and title. Authentication runs asynchronously in the background. This call returns immediately with `status: "authenticating"`, and you then poll the prompt endpoint. The body accepts `service` and `title_id` (both required). It also accepts a broad set of optional keys, because the body allows `additionalProperties`. These are `credentials` (`{username, password, extra?}`), `cookies` (base64 of zlib-compressed Netscape cookie file), `proxy`, `no_proxy`, `profile`, `cache` (map of forwarded cache files, keyed by the file path relative to the service cache directory with `/` separators and no `.json` suffix, so a nested key such as `session_web/<sha1>` lands in a subdirectory), `client_region`, `proxy_region`, `cdm_type`, `range_`, `vcodec`, `quality`, `best_available`, `dl_params`, `client`, and any service CLI options. `proxy_region` is the country code the client resolved `proxy` from; the server matches it against its own accounts. `client` is a freeform object the dashboard shows as sent (the CLI puts `version`, `code_hash`, `platform` and a redacted `argv` in it); the server ignores it above 4096 bytes of JSON.
`dl_params` is an object with the `dl` track selection: `lang`, `v_lang` and `a_lang` (arrays of language strings), `acodec` (an array of audio codec names or `dl -a` aliases such as `ddp`) and `forced_subs` (boolean). The service reads these values from `ctx.parent.params`. The server uses the `dl` default for each absent or malformed value, and drops an unknown codec name.
Service CLI options also travel in a nested `service_params` object, which wins over a flat key with the same name. `profile` at the top level always means the credentials profile, never a service's own `--profile` option.
+28
View File
@@ -124,6 +124,9 @@ hood the client walks a remote session through its lifecycle.
the client region itself
- Track-selection hints (`range_`, `vcodec`, `quality`, `best_available`) so
the server fetches the right manifests
- Your language and audio codec selection (`-l`, `-vl`, `-al`, `-a`, `-fs`)
in a `dl_params` object. Some services fetch one manifest
for each audio language, and pick the languages from these values
- Your local per-service **cache files** (e.g. refreshed tokens), including
files in subdirectories of the service cache directory, but only the files
for the active profile. The client withholds a file whose path, in any
@@ -207,6 +210,9 @@ hood the client walks a remote session through its lifecycle.
authentication. The login belongs to the client when the client sent
cookies, credentials, or cache files, or answered a login prompt (a device code
or an OTP) that led to a successful login. A server-account login never does.
The client saves only the returned files that pass the same profile check it
applies before it sends them, so a file for another profile cannot overwrite
that profile's local file.
!!! tip "Renaming remote titles locally"
You can rename titles for a remote service you do not have installed locally by
@@ -349,6 +355,28 @@ shows as sent), and the track-selection hints `range_`, `vcodec`,
`quality`, `best_available`, plus arbitrary service CLI options
(`additionalProperties: true`).
`dl_params` holds the `dl` track selection: `lang`, `v_lang` and `a_lang`
(arrays of language strings), `acodec` (an array of audio codec names, such as
`EC3`), and `forced_subs` (boolean). The server gives these values to the
service in `ctx.parent.params`, never as service options, so a service option
with the same name, such as an own `--lang`, does not get them. The server uses
the `dl` default for each absent or malformed value: `lang` is `["orig"]`,
`v_lang`, `a_lang` and `acodec` are `[]`, and `forced_subs` is `false`. The
server drops an unknown codec name. An empty array is a valid value and stays
empty.
The server does not forward the `dl` mode flags: `video_only`, `audio_only`,
`subs_only`, `chapters_only`, `list_`, `skip_dl`, `sub_format` and
`no_attachments`. A service that reads one of them to skip work fetches more on
the server, but the result is the same.
In a client-login session (not a server account), the server gives the service
the client's `profile` in `ctx.parent.params`, the same as a local run with that
profile. The profile name keys the service's token cache, so the cache files
the client sends and gets back belong to that profile. A service can also use
the name to select per-profile entries in the server's service config, such as
a per-profile ESN.
The response returns **before** authentication finishes:
```json