mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
docs: apply simplified technical english across docs and docstrings.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Config API
|
||||
|
||||
Auto-generated reference for the [`Config`][unshackle.core.config.Config] object that models the
|
||||
`unshackle` configuration file. For a human-friendly walkthrough of every key, see the
|
||||
`unshackle` configuration file. For a human-friendly walkthrough of every config key, see the
|
||||
[Configuration Reference](../configuration/index.md).
|
||||
|
||||
::: unshackle.core.config
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Directories { #directories }
|
||||
|
||||
The `directories` key is a **dict** mapping directory names to filesystem paths. Only the
|
||||
names listed below are honoured; a handful are **protected** and cannot be moved (attempts
|
||||
to override them are silently skipped). All defaults are computed relative to the installed
|
||||
package, and every user-settable path is passed through `Path(...).expanduser()`, so `~`
|
||||
works.
|
||||
The `directories` config key is a **dict** mapping directory names to filesystem paths.
|
||||
unshackle honours only the names listed below. A handful are **protected** and you cannot
|
||||
move them, and unshackle silently ignores an override of one. unshackle computes all
|
||||
defaults relative to the installed package, and passes every user-settable path through
|
||||
`Path(...).expanduser()`, so `~` works.
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
directories:
|
||||
@@ -38,9 +38,9 @@ directories:
|
||||
!!! note "The `services` directory is special"
|
||||
`services` may be a **list**, and each entry can be either a local directory or a
|
||||
**repository spec**: a git URL (`https://...`, `ssh://...`, `git@...`, or anything ending in
|
||||
`.git`) or `owner/repo` shorthand. Repo specs are cloned and updated automatically; plain
|
||||
paths are used as-is. **List order is priority**: the first source to define a service
|
||||
tag wins.
|
||||
`.git`) or `owner/repo` shorthand. unshackle clones and updates repo specs automatically,
|
||||
and uses plain paths as they are. **List order is priority**: the first source to define a
|
||||
service tag wins.
|
||||
|
||||
```yaml
|
||||
directories:
|
||||
@@ -51,11 +51,11 @@ directories:
|
||||
```
|
||||
|
||||
!!! info "How git-backed service repos are handled"
|
||||
unshackle's use of git is **read-only on the remote**: it only ever performs a shallow
|
||||
`clone`, `fetch`, `pull`, and a local `reset`; **nothing is ever pushed**. Private repos
|
||||
are authenticated through your existing git credential helper, and unshackle stores no
|
||||
unshackle's use of git is **read-only on the remote**: it only ever does a shallow
|
||||
`clone`, `fetch`, `pull`, and a local `reset`. **unshackle never pushes anything**. Your
|
||||
existing git credential helper authenticates private repos, and unshackle stores no
|
||||
tokens of its own. Clones live under `<first-local-services-dir>/_repos/<host>__<owner>__<repo>/`
|
||||
(or the bundled `unshackle/services`), and **nothing is written to the cache directory**. After
|
||||
(or the bundled `unshackle/services`), and **unshackle writes nothing to the cache directory**. After
|
||||
the first clone unshackle re-pulls **at most once every 24 h**, so it does not touch the
|
||||
network on every run.
|
||||
|
||||
@@ -74,9 +74,9 @@ directories:
|
||||
|
||||
## Filenames { #filenames }
|
||||
|
||||
The `filenames` key is a **dict** of templated file/name patterns. Each value is used
|
||||
verbatim (no path processing). Braced fields like `{time}` and `{service}` are filled in at
|
||||
runtime.
|
||||
The `filenames` config key is a **dict** of templated file/name patterns. unshackle uses
|
||||
each value verbatim (no path processing). It fills in braced fields like `{time}` and
|
||||
`{service}` at runtime.
|
||||
|
||||
| Key | Type | Default | Notes |
|
||||
|-----|------|---------|-------|
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Persistent defaults for the `dl` command. The block is used as Click's `default_map`, so any
|
||||
`dl` flag can be given a default here. See [Downloading](../../guide/downloading.md) and the
|
||||
Persistent defaults for the `dl` command. unshackle uses the block as Click's `default_map`,
|
||||
so you can give any `dl` flag a default here. See [Downloading](../../guide/downloading.md) and the
|
||||
[CLI Reference](../../guide/cli-reference.md) for what each flag does.
|
||||
|
||||
**Key naming.** A key is the flag's long name with dashes replaced by underscores
|
||||
(`--best-available` → `best_available`, `--sub-format` → `sub_format`). A few keys are named
|
||||
after the flag's internal destination rather than its visible name; set these exact keys:
|
||||
**Config key naming.** A config key is the flag's long name with dashes replaced by
|
||||
underscores (`--best-available` → `best_available`, `--sub-format` → `sub_format`). A few
|
||||
config keys use the flag's internal destination and not its visible name. Set these exact
|
||||
config keys:
|
||||
|
||||
| Flag | Config key |
|
||||
|------|-----------|
|
||||
@@ -27,7 +28,7 @@ after the flag's internal destination rather than its visible name; set these ex
|
||||
[`services.<TAG>.dl`](services.md) override → this global `dl:` block → the built-in
|
||||
default. In other words, config only fills in options you did not set on the command line.
|
||||
|
||||
Common keys (a useful subset; every `dl` flag works):
|
||||
Common config keys. This is a useful subset, and every `dl` flag works:
|
||||
|
||||
| Key | Type | Default | Sets |
|
||||
|-----|------|---------|------|
|
||||
@@ -89,28 +90,28 @@ dl:
|
||||
|
||||
!!! note "`serve` uses these same keys"
|
||||
The [`serve`](services.md#serve) block accepts most of the same `dl` option keys at its top level
|
||||
to set server-wide download defaults for every request it handles. Keys the API does not know
|
||||
are ignored there (`speed_limit`, for example; `serve` has its own `global_speed_limit`).
|
||||
to set server-wide download defaults for every request it handles. The API ignores the
|
||||
config keys it does not know there, `speed_limit` for example. `serve` has its own
|
||||
`global_speed_limit`.
|
||||
|
||||
## `continue_downloads`
|
||||
|
||||
- **Type:** `bool` · **Default:** `false`
|
||||
|
||||
Keep a failed download's completed segment files so the next attempt resumes from where it
|
||||
Keep a failed download's completed segment files so the next download resumes from where it
|
||||
stopped instead of restarting from byte zero.
|
||||
|
||||
Only whole, fully downloaded segments are reused; partially written segments are always
|
||||
discarded, and no partial-byte (`Range`) resume across runs takes place. Reuse also
|
||||
requires proof that the remote content is unchanged: the manifest URL, segment count, and
|
||||
byte ranges must all match the previous run, otherwise the download silently restarts
|
||||
clean.
|
||||
unshackle reuses only whole, fully downloaded segments. It always discards partially written
|
||||
segments, and no partial-byte (`Range`) resume across runs takes place. Reuse is possible only
|
||||
with proof that the segmentation did not change. The manifest URL, segment count, and byte
|
||||
ranges must all match the previous download, or the download silently restarts clean.
|
||||
|
||||
!!! note "What can and cannot resume"
|
||||
- Segmented DASH, ISM, and HLS tracks resume.
|
||||
- Single-file (non-segmented) downloads and DASH tracks collapsed to a single ranged
|
||||
download never produce segment files, so this option does not apply to them (the
|
||||
download never make segment files, so this option does not apply to them (the
|
||||
downloader has its own in-flight partial-file handling for those).
|
||||
- HLS resumes Widevine/PlayReady and unencrypted content only; AES-128 content always
|
||||
- HLS resumes Widevine/PlayReady and unencrypted titles only. An AES-128 title always
|
||||
restarts. An HLS failure during the post-download merge step also restarts.
|
||||
|
||||
For a one-off resume without changing config, pass `dl --continue-downloads` on the
|
||||
@@ -124,8 +125,8 @@ continue_downloads: true
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Subtitle handling: SDH stripping, format conversion, and whether subtitles are muxed in or
|
||||
written as sidecar files. See [Subtitles](../../guide/subtitles.md) for the full guide.
|
||||
Subtitle handling: SDH stripping, format conversion, and whether unshackle muxes the subtitles
|
||||
in or writes them as sidecar files. See [Subtitles](../../guide/subtitles.md) for the full guide.
|
||||
|
||||
| Sub-key | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
@@ -168,7 +169,7 @@ subtitle:
|
||||
| Default | English, Arabic, Bulgarian, Spanish, French, Japanese |
|
||||
| With the list above | English, Spanish, French, Arabic, Bulgarian, Japanese |
|
||||
|
||||
Nothing is removed, unlike `-sl`, which drops every subtitle language it does not name.
|
||||
unshackle removes nothing, unlike `-sl`, which drops every subtitle language it does not name.
|
||||
|
||||
Use `orig` in the list for the title's original language. A base tag also covers its
|
||||
regional forms, so `en` sorts `en-US` and `en-GB`, but `zh` does **not** cover
|
||||
@@ -245,8 +246,8 @@ muxing:
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Language-tag remapping and the rule engine behind the `{lang_tag}` filename variable. When a
|
||||
`rules` list is present, each rule is evaluated in order and the first match's `tag` is used.
|
||||
A rule may test:
|
||||
`rules` list is present, unshackle evaluates each rule in order and uses the first match's
|
||||
`tag`. A rule can examine:
|
||||
|
||||
| Condition | Meaning |
|
||||
|-----------|---------|
|
||||
|
||||
@@ -31,13 +31,13 @@ cdm:
|
||||
default: chromecdm_l3
|
||||
```
|
||||
|
||||
Quality keys support `1080`, `>=1080`, `>720`, `<=576`, `<480` style comparisons; DRM keys
|
||||
are `widevine` / `playready`. Quality keys are matched first, but only when a video height is
|
||||
known; if the value is still a dict after that, `widevine`/`playready` are used when present,
|
||||
otherwise the credential profile name, then `default`.
|
||||
Quality keys can hold `1080`, `>=1080`, `>720`, `<=576`, `<480` style comparisons. DRM keys
|
||||
are `widevine` / `playready`. unshackle matches the quality keys first, but only when a video
|
||||
height is known. If the value is still a dict after that, unshackle uses
|
||||
`widevine`/`playready` when present, or else the credential profile name, then `default`.
|
||||
|
||||
The resolved name is looked up in [`remote_cdm`](#remote_cdm) by `name` first. If no entry
|
||||
matches, it is loaded as a local device file, in this order: `<name>.prd` in
|
||||
unshackle finds the resolved name in [`remote_cdm`](#remote_cdm) by `name` first. If no entry
|
||||
matches, unshackle loads it as a local device file, in this order: `<name>.prd` in
|
||||
`directories.prds`, `<name>.prd` in `directories.wvds`, then `<name>.wvd` in
|
||||
`directories.wvds`.
|
||||
|
||||
@@ -45,7 +45,7 @@ matches, it is loaded as a local device file, in this order: `<name>.prd` in
|
||||
|
||||
- **Type:** `list[dict]` · **Default:** `[]`
|
||||
|
||||
A list of remote CDM server definitions. Each entry is matched by its `name` (referenced from
|
||||
A list of remote CDM definitions. unshackle matches each entry by its `name` (referenced from
|
||||
[`cdm`](#cdm)), and its `type` selects the backend:
|
||||
|
||||
| `type` | Backend | Key fields |
|
||||
@@ -89,7 +89,7 @@ styles: `Device Type`/`device_type`, `System ID`/`system_id`, `Security Level`/`
|
||||
| `system_id` | `26830` (Widevine), `0` (PlayReady) | |
|
||||
| `security_level` | Widevine `3`; PlayReady `2000` for `SL2`, else `3000` | |
|
||||
|
||||
PlayReady mode is used when `device_type` is `PLAYREADY` or `device_name` starts with `SL`.
|
||||
unshackle uses PlayReady mode when `device_type` is `PLAYREADY` or `device_name` starts with `SL`.
|
||||
|
||||
### `custom_api` fields { #remote-cdm-custom-api }
|
||||
|
||||
@@ -105,8 +105,8 @@ PlayReady mode is used when `device_type` is `PLAYREADY` or `device_name` starts
|
||||
| `legacy` | dict | Legacy mode options. |
|
||||
| `timeout` | int | Default `30`. Request timeout in seconds. |
|
||||
|
||||
Transforms cover base64/hex/JSON encoding and `kid:key` parsing. PlayReady mode is used when
|
||||
`device.type` is `PLAYREADY` or the device name is `SL2`/`SL3`.
|
||||
Transforms cover base64/hex/JSON encoding and `kid:key` parsing. unshackle uses PlayReady mode
|
||||
when `device.type` is `PLAYREADY` or the device name is `SL2`/`SL3`.
|
||||
|
||||
```yaml
|
||||
remote_cdm:
|
||||
@@ -135,12 +135,12 @@ remote_cdm:
|
||||
|
||||
- **Type:** `str` or `dict` · **Default:** `"shaka"`
|
||||
|
||||
Selects the tool used to physically decrypt CENC content. The value is compared
|
||||
case-insensitively; `"mp4decrypt"` selects Bento4's mp4decrypt, and **anything else**
|
||||
(including `"shaka"`) selects shaka-packager. When the value is a dict, the service key is
|
||||
matched case-insensitively and the `default` entry is the fallback.
|
||||
Selects the tool that physically decrypts CENC-encrypted tracks. unshackle compares the value
|
||||
case-insensitively. `"mp4decrypt"` selects Bento4's mp4decrypt, and **anything else**
|
||||
(including `"shaka"`) selects shaka-packager. When the value is a dict, unshackle compares the
|
||||
service tag case-insensitively and uses the `default` entry as the fallback.
|
||||
|
||||
HLS AES-128 ClearKey is decrypted in-process and ignores this setting.
|
||||
unshackle decrypts HLS AES-128 ClearKey in-process and ignores this setting.
|
||||
|
||||
=== "Global"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# A complete annotated example
|
||||
|
||||
The following config sets a handful of common keys. Every key not shown keeps its default.
|
||||
The following config sets a handful of common config keys. Every config key not shown keeps its default.
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
directories:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# Configuration Reference
|
||||
|
||||
Every key you can set in `unshackle.yaml`, with its name, type, default value, and behaviour,
|
||||
Every config key you can set in `unshackle.yaml`, with its name, type, default value, and behaviour,
|
||||
split into one page per area. A worked config is on the [annotated example](example.md) page.
|
||||
|
||||
Where the file lives, how unshackle discovers it, and how to edit it:
|
||||
[The Configuration File](../../getting-started/configuration-file.md).
|
||||
|
||||
!!! info "How defaults work"
|
||||
Every key is optional except [`output_template`](output.md), which `dl` requires.
|
||||
Without it, `dl` aborts with an error. If you omit any other key, unshackle uses
|
||||
the built-in default listed here. There is **no schema validation**: unknown keys are
|
||||
silently ignored (they never become settings), and the file is parsed with
|
||||
`yaml.safe_load`. An empty or missing file means every other key falls back to its
|
||||
Every config key is optional except [`output_template`](output.md), which `dl` requires.
|
||||
Without it, `dl` aborts with an error. If you do not write any other config key, unshackle
|
||||
uses the built-in default listed here. There is **no schema validation**: unshackle
|
||||
silently ignores unknown config keys (they never become settings), and reads the file with
|
||||
`yaml.safe_load`. An empty or missing file means every other config key falls back to its
|
||||
default.
|
||||
|
||||
!!! warning "Two keys behave specially on load"
|
||||
|
||||
@@ -5,7 +5,7 @@ Smaller configuration areas: external metadata API keys, caching and update chec
|
||||
## External API keys { #external-api-keys }
|
||||
|
||||
All are unset by default and enable optional metadata/geolocation features. For which fields
|
||||
each metadata provider can actually answer with, see
|
||||
each metadata provider can answer with, see
|
||||
[What each metadata provider supplies](../../guide/downloading.md#what-each-metadata-provider-supplies).
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
@@ -23,7 +23,7 @@ each metadata provider can actually answer with, see
|
||||
| `ipinfo_api_key` | str | `""` | ipinfo.io API key for IP/region lookups. |
|
||||
|
||||
!!! note "How `metadata_providers` is applied"
|
||||
A lookup goes to each provider in turn and stops at the first good match, so the order
|
||||
A lookup goes to each metadata provider in turn and stops at the first good match, so the order
|
||||
decides which source wins. `metadata_providers` sets that order:
|
||||
|
||||
```yaml
|
||||
@@ -37,8 +37,8 @@ each metadata provider can actually answer with, see
|
||||
metadata_providers: [imdb, omdb, simkl, tmdb, tvdb, anilist]
|
||||
```
|
||||
|
||||
Whatever the order, unshackle skips a provider that has no API key. `imdb` and
|
||||
`anilist` need no key, so they are always available. Available names are `imdb`, `omdb`,
|
||||
Whatever the order, unshackle skips a metadata provider that has no API key. `imdb` and
|
||||
`anilist` need no API key, so they are always available. Available names are `imdb`, `omdb`,
|
||||
`simkl`, `tmdb`, `tvdb`, and `anilist`. The old name `imdbapi` still works and is read as
|
||||
`imdb`.
|
||||
|
||||
@@ -63,7 +63,7 @@ each metadata provider can actually answer with, see
|
||||
|
||||
!!! note "What `disable_metadata` turns off"
|
||||
With `disable_metadata: true`, unshackle never contacts a metadata provider on its own.
|
||||
The title search is dead, and that includes the keyless `imdb` provider. Titles, years and
|
||||
The title search is dead, and that includes the keyless `imdb` metadata provider. Titles, years and
|
||||
languages then come only from the service.
|
||||
|
||||
```yaml
|
||||
@@ -72,18 +72,18 @@ each metadata provider can actually answer with, see
|
||||
|
||||
An ID you give with `--tmdb`, `--imdb`, `--tvdb`, or `--anilist` is your permission to use
|
||||
that ID. That lookup still works. unshackle looks the ID up directly, cross references the other
|
||||
IDs from it, and `--enrich` still reads that source. Only the lookups you did not ask for
|
||||
are stopped.
|
||||
IDs from it, and `--enrich` still reads that source. unshackle stops only the lookups you
|
||||
did not ask for.
|
||||
|
||||
!!! note "The `imdb` provider needs no key"
|
||||
It replaces the earlier `imdbapi` provider, which read a third-party mirror
|
||||
It replaces the earlier `imdbapi` metadata provider, which read a third-party mirror
|
||||
(api.tiffara.com) and needed the `imdb_api_enabled` switch. That option is gone: delete it
|
||||
from your config, where it is now ignored.
|
||||
|
||||
!!! tip "A different order per title kind"
|
||||
Give a map instead of one list when the best source differs by kind. TVDB is strongest on
|
||||
series, TMDB on films. There are two kinds, `tv` and `movie`, and this example sets both
|
||||
of them and names every provider, so nothing is left to the default:
|
||||
of them and names every metadata provider, so nothing is left to the default:
|
||||
|
||||
```yaml
|
||||
metadata_providers:
|
||||
@@ -91,9 +91,9 @@ each metadata provider can actually answer with, see
|
||||
movie: [tmdb, imdb, omdb, simkl, tvdb]
|
||||
```
|
||||
|
||||
Each list is independent: it both orders and filters that kind on its own, so a provider
|
||||
you leave out of `tv` is still used for `movie`. Here TVDB is tried first for a series and
|
||||
last for a film.
|
||||
Each list is independent: it both orders and filters that kind on its own, so unshackle
|
||||
still uses for `movie` a metadata provider you leave out of `tv`. Here unshackle tries TVDB
|
||||
first for a series and last for a film.
|
||||
|
||||
You do not need to give both keys, or a full list in each. A kind you leave out uses the
|
||||
default order:
|
||||
@@ -104,11 +104,11 @@ each metadata provider can actually answer with, see
|
||||
```
|
||||
|
||||
`tv` covers every episode and `movie` covers every film. unshackle only looks up
|
||||
metadata for those two kinds, so any other key, such as `anime` or `music`, is ignored.
|
||||
metadata for those two kinds, so unshackle ignores any other config key, such as `anime` or `music`.
|
||||
|
||||
!!! note "`ipinfo_api_key` never touches your service sessions"
|
||||
The token is only ever sent to `api.ipinfo.io` as a per-request `Authorization` header; it
|
||||
is **never** attached to your service session, so it cannot leak to a streaming provider.
|
||||
unshackle sends the token only to `api.ipinfo.io`, as a per-request `Authorization` header.
|
||||
It **never** goes on your service HTTP session, so it cannot leak to a streaming service.
|
||||
Lookups degrade gracefully through a fallback chain: the authenticated Lite endpoint (higher
|
||||
rate limits, and ASN/continent data, but no city or region) → anonymous ipinfo →
|
||||
`ip-api.in` as a last resort.
|
||||
@@ -160,19 +160,19 @@ calls.
|
||||
| `set_terminal_bg` | bool | `false` | Append the theme's background colour to output styling. |
|
||||
|
||||
!!! note "Effect of `set_terminal_bg`"
|
||||
When on, the theme's background colour is appended to the foreground styles, which makes
|
||||
When on, unshackle appends the theme's background colour to the foreground styles, which makes
|
||||
the full colour palette render correctly on terminals whose *default* background differs
|
||||
from unshackle's theme. When off, such terminals can render the ASCII-art banner and
|
||||
coloured output incorrectly.
|
||||
|
||||
!!! danger "Key exposure"
|
||||
With `debug_keys` on, decryption content keys are written to the structured debug log at
|
||||
With `debug_keys` on, unshackle writes the content keys to the structured debug log at
|
||||
INFO level during the DRM handshake. Treat `debug`, `debug_keys`, and the `unshackle_debug_*.jsonl` files as
|
||||
sensitive, and keep `redact_paths` enabled when sharing logs.
|
||||
|
||||
`debug_keys` affects **only** content-encryption keys (the `content_key`/`key` fields).
|
||||
Passwords, tokens, cookies, and session tokens are **always** redacted regardless of this
|
||||
setting, and KIDs, key counts, and other metadata are always logged either way.
|
||||
setting, and KIDs, content key counts, and other metadata are always logged either way.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
TLS-fingerprinting and HTTP client settings for the rnet-based session.
|
||||
TLS-fingerprinting and HTTP client settings for the rnet-based HTTP session.
|
||||
|
||||
| Sub-key | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
@@ -43,7 +43,7 @@ network:
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Default HTTP headers merged into every session unshackle creates.
|
||||
Default HTTP headers merged into every HTTP session unshackle makes.
|
||||
|
||||
```yaml
|
||||
headers:
|
||||
@@ -52,17 +52,17 @@ headers:
|
||||
|
||||
!!! warning "Don't set `Accept-Encoding` (and similar) here"
|
||||
Compatibility headers such as `Accept-Encoding` are set by the rnet HTTP backend as part of
|
||||
its browser-impersonation profile; overriding them breaks the impersonation fingerprint.
|
||||
This block is for cross-service defaults only (for example `Accept-Language`,
|
||||
`User-Agent`); per-service headers belong in that service's own config.
|
||||
its browser-impersonation profile. If you override them, you break the impersonation
|
||||
fingerprint. This block is for cross-service defaults only (for example `Accept-Language`,
|
||||
`User-Agent`). Per-service headers belong in that service's own config.
|
||||
|
||||
## `proxy_providers`
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Proxy/VPN provider configuration. Each sub-key names a provider, and its block is passed
|
||||
straight to that provider's constructor. See [Proxies & VPN](../../guide/proxies-and-vpn.md) for
|
||||
the full provider guide. Recognised providers and their exit ports:
|
||||
Proxy/VPN provider configuration. Each sub-key names a proxy provider, and unshackle passes its
|
||||
block straight to that provider's constructor. See [Proxies & VPN](../../guide/proxies-and-vpn.md)
|
||||
for the full proxy provider guide. Recognised proxy providers and their exit ports:
|
||||
|
||||
| Provider | Config key | Credentials | Proxy scheme/port |
|
||||
|----------|-----------|-------------|-------------------|
|
||||
|
||||
@@ -23,7 +23,7 @@ output_template:
|
||||
series: "{title} ({year})"
|
||||
```
|
||||
|
||||
**The nested `folder` sub-key** controls output subfolders and is popped out of
|
||||
**The nested `folder` sub-key** controls output subfolders, and unshackle pops it out of
|
||||
`output_template`:
|
||||
|
||||
- A **dict** sets per-kind folder templates (kinds: `movies`, `series`, `songs`, `albums`).
|
||||
@@ -53,7 +53,7 @@ folder-kind keys.
|
||||
|
||||
!!! tip "`{absolute}` counts episodes across seasons"
|
||||
`absolute` holds the absolute episode number, zero-padded to 3 digits (`007`), and is
|
||||
empty on titles that have none. It is added to the name and never replaces `{season}`
|
||||
empty on titles that have none. You add it to the name yourself, and it never replaces `{season}`
|
||||
or `{episode}`. Any series with a TVDB absolute order can use it, anime most often.
|
||||
Services can supply it, and
|
||||
[`--enrich`](../../guide/downloading.md#metadata-and-tagging) fills it in from TVDB.
|
||||
@@ -74,8 +74,8 @@ folder-kind keys.
|
||||
- **Type:** `list` · **Default:** `[]`
|
||||
|
||||
Conditionally replaces [`tag`](#tagging-naming-keys) for a given download. Each rule pairs a `when`
|
||||
dict of conditions with the `tag` to use when they hold. Rules are evaluated in order and the
|
||||
first match wins; if no rule matches, the global `tag` is kept.
|
||||
dict of conditions with the `tag` to use when they hold. unshackle evaluates the rules in
|
||||
order and the first match wins. If no rule matches, the global `tag` stays.
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
tag_rules:
|
||||
@@ -88,30 +88,31 @@ tag_rules:
|
||||
Rule semantics:
|
||||
|
||||
- Every condition in `when` must hold (they are AND-ed).
|
||||
- A value may be a scalar or a list; a list matches if **any** entry matches.
|
||||
- A value can be a scalar or a list. A list matches if **any** entry matches.
|
||||
- Comparison is case-insensitive string equality.
|
||||
- The keys of `when` are the filename template variables that describe the release itself:
|
||||
- The keys of `when` are the filename template variables for the release itself:
|
||||
`title_type`, `quality`, `resolution`, `source`, `video`, `hdr`, `hfr`, `audio`,
|
||||
`audio_channels`, `audio_full`, `atmos`, `dual`, `multi`, `dubbed`, `edition`, `repack`,
|
||||
and `lang_tag`. Only these are available. The title's own fields (`title`, `year`, `season`,
|
||||
`episode`, and so on) are added after the rules run and cannot be matched.
|
||||
- An unknown key in `when` is a mistake: unshackle logs a warning that names the key and skips
|
||||
that rule. A rule without conditions or without a `tag` is also warned about and skipped.
|
||||
and `lang_tag`. Only these are available. unshackle adds the title's own fields (`title`,
|
||||
`year`, `season`, `episode`, and so on) after it evaluates the rules, so a condition cannot
|
||||
use them.
|
||||
- An unknown key in `when` is a mistake: unshackle logs a warning that names the key
|
||||
and skips that rule. A rule without conditions or without a `tag` is also warned about and skipped.
|
||||
|
||||
Put the more specific rules first, because the first match ends the search.
|
||||
Put the more specific rules first, because unshackle stops at the first match.
|
||||
|
||||
!!! warning "Match `hdr` on the exact value"
|
||||
Matching is exact, and `hdr` is a composite label for Dolby Vision titles: a DV title with
|
||||
an HDR10 base layer gives `DV.HDR`, and with an HDR10+ base layer `DV.HDR10P`. Plain `DV`
|
||||
does **not** match those. List every variant you want, as the example above does. Note
|
||||
does **not** match those. Name every variant you want, as the example above does. Note
|
||||
also that HDR10 gives `HDR`, not `HDR10`. The full set of values is `HDR`, `HDR10P`, `DV`,
|
||||
`DV.HDR`, `DV.HDR10P`, and `HLG`, as listed in the
|
||||
[variable table](../../guide/output-and-naming.md#template-variables).
|
||||
|
||||
### Operators
|
||||
|
||||
A condition value may start with a comparison operator, which is applied to the rest of the
|
||||
value:
|
||||
A condition value can start with a comparison operator, which unshackle applies to the rest of
|
||||
the value:
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
tag_rules:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Post-download scripts { #post-scripts }
|
||||
|
||||
Run your own script when a download finishes, with unshackle's metadata passed in as
|
||||
Operate your own script when a download finishes, with unshackle's metadata passed in as
|
||||
`{variable}` placeholders. Use it to hand a finished file to an uploader, send a
|
||||
notification, or start a library scan.
|
||||
|
||||
## `post_scripts`
|
||||
|
||||
- **Type:** `list[dict]` · **Default:** `[]` (no scripts run)
|
||||
- **Type:** `list[dict]` · **Default:** `[]` (unshackle operates no scripts)
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
post_scripts:
|
||||
@@ -17,7 +17,7 @@ post_scripts:
|
||||
```
|
||||
|
||||
Every entry that matches the event and mode runs, so one download can feed an uploader and
|
||||
a notifier without a wrapper script. An entry may also be written as a plain string, which
|
||||
a notifier without a wrapper script. You can also write an entry as a plain string, which
|
||||
is the same as `{command: "...", event: success, mode: file}`.
|
||||
|
||||
| Key | Default | Meaning |
|
||||
@@ -26,15 +26,15 @@ is the same as `{command: "...", event: success, mode: file}`.
|
||||
| `event` | `success` | `success` when a file was written, `failure` when the download failed |
|
||||
| `mode` | `file` | `file`, `season`, or `run`. See [Modes](#modes) |
|
||||
|
||||
An entry whose `event` or `mode` is not one of the listed values is skipped and logs a
|
||||
warning naming the bad value, once per command. An entry whose `command` cannot be split
|
||||
into arguments, such as one with an unbalanced quote, is skipped with a warning too. Neither
|
||||
stops the download or the other entries.
|
||||
unshackle skips an entry whose `event` or `mode` is not one of the listed values, and logs a
|
||||
warning that names the bad value, once per command. unshackle also skips an entry whose
|
||||
`command` it cannot split into arguments, such as one with an unbalanced quote, and logs a
|
||||
warning. Neither stops the download or the other entries.
|
||||
|
||||
## How the command runs
|
||||
|
||||
The command is split into arguments **first**, and variables are substituted into those
|
||||
arguments afterwards. The process runs without a shell.
|
||||
unshackle splits the command into arguments **first**, and then substitutes the variables
|
||||
into those arguments. The process runs without a shell.
|
||||
|
||||
This is what keeps a title like `Bob"; rm -rf ~` harmless: a value can never turn into an
|
||||
extra argument or a shell operator, and you never have to think about quoting. It also
|
||||
@@ -45,12 +45,12 @@ means a path containing spaces always arrives as a single argument on every OS.
|
||||
first stops a value becoming a *new* argument, but a value on its own can still be a
|
||||
whole argument. A bare `{title}` whose value is `--upload-file=/etc/passwd` would arrive
|
||||
as an option to your script, not as text. Write `--title={title}`, not a bare `{title}`,
|
||||
so a service can never forge a flag. unshackle refuses to run a command when a
|
||||
so a service can never forge a flag. unshackle refuses to operate a command when a
|
||||
substituted value would become an option-like token (one that starts with `-`), and logs
|
||||
a warning instead.
|
||||
|
||||
!!! warning "No shell features, and name your interpreter"
|
||||
Pipes, `&&`, `>` redirection, `~` and globs do not work, because no shell is involved.
|
||||
Pipes, `&&`, `>` redirection, `~` and globs do not work, because unshackle uses no shell.
|
||||
If you want them, make the shell explicit: `bash -c "..."`.
|
||||
|
||||
For the same reason there is no interpreter lookup. Write `python /opt/upload.py`
|
||||
@@ -58,7 +58,7 @@ means a path containing spaces always arrives as a single argument on every OS.
|
||||
Python or the one in its own virtual environment.
|
||||
|
||||
On Windows, when a **fixed** part of an argument contains a space, quote the whole
|
||||
argument (`"--out=C:\My Dir\{filename}"`), not just the value. Substituted values
|
||||
argument (`"--out=C:\My Dir\{filename}"`), not only the value. Substituted values
|
||||
never need quoting on any OS.
|
||||
|
||||
On Windows, do not target a `.bat` or `.cmd` file directly. Windows runs batch files
|
||||
@@ -79,7 +79,7 @@ already started.
|
||||
## Variables
|
||||
|
||||
Metadata comes from the same naming context that produced the file's name, built per output
|
||||
file. So `{quality}` and `{hdr}` always describe the file being passed. Downloading
|
||||
file. So `{quality}` and `{hdr}` always give the values for the file unshackle passes in. Downloading
|
||||
`-q 1080,2160 -r HDR10,SDR` produces four files, each with its own invocation and its own
|
||||
values.
|
||||
|
||||
@@ -104,11 +104,11 @@ Every variable from your `output_template` is available here as well, including
|
||||
|
||||
!!! warning "Empty variables become an empty string"
|
||||
`--tmdb={tmdb}` with no ID resolved hands your script `--tmdb=`, so treat an empty
|
||||
string as absent. Write your script to handle every variable being empty.
|
||||
string as absent. Write your script to accept an empty value for every variable.
|
||||
|
||||
Empty is common, and not only when data is missing:
|
||||
|
||||
- Nothing was resolved. `{tmdb}` is empty when no metadata provider found the title,
|
||||
- No metadata provider found an ID. `{tmdb}` is empty when no metadata provider found the title,
|
||||
the matching API key is missing, or the title is a movie you gave no ID for.
|
||||
- The title has no such field. Movies have no `{season}` or `{episode}`, and music has
|
||||
neither.
|
||||
@@ -153,10 +153,9 @@ track arrived in, such as `.flac`, because a music download is not muxed.
|
||||
|
||||
### Tagging IDs { #tagging-ids }
|
||||
|
||||
`{tmdb}`, `{imdb}` and `{tvdb}` carry the IDs unshackle is tagging the file with, read at
|
||||
the moment the hook is dispatched rather than snapshotted at the start of the run. An
|
||||
episode's TMDB ID is resolved by the title search inside the download loop, so a hook fires
|
||||
with it already filled in.
|
||||
`{tmdb}`, `{imdb}` and `{tvdb}` carry the IDs unshackle tags the file with. unshackle reads
|
||||
them at the moment it sends the hook, and not at the start of the run. The title search inside
|
||||
the download loop finds an episode's TMDB ID, so a hook fires with it already filled in.
|
||||
|
||||
They hold an ID you passed with `--tmdb`, `--imdb` or `--tvdb`, plus a TMDB ID the episode
|
||||
search resolved. No such search runs for a movie, so a movie hook gets them empty unless you
|
||||
@@ -165,14 +164,14 @@ passed one.
|
||||
### Sidecar files
|
||||
|
||||
`{sidecars}` holds the sidecar subtitle files written beside the output, which are the only
|
||||
extra files a download leaves next to it. Attachments such as fonts are muxed into the
|
||||
container and temporary artwork is deleted, so neither appears. Expect `{sidecars}` to be
|
||||
extra files a download leaves next to it. unshackle muxes attachments such as fonts into the
|
||||
container and deletes temporary artwork, so neither appears. Expect `{sidecars}` to be
|
||||
empty unless [`subtitle.output_mode`](download.md#subtitle) is `sidecar` or `both`, which is
|
||||
not the default. A music download writes no sidecars at all.
|
||||
|
||||
Paths are absolute and separated by a newline, because a newline is the only character that
|
||||
cannot appear in a filename on any supported OS. The whole list arrives as a single
|
||||
argument, so no quoting is needed in your template.
|
||||
argument, so your template needs no quoting.
|
||||
|
||||
When one download writes several outputs (`-q 1080,720`), each output's folder gets its own
|
||||
copy of the sidecar files, and each invocation lists the copies sitting beside its own
|
||||
@@ -201,7 +200,7 @@ subs = [p for p in sys.argv[i].removeprefix("--subs=").split("\n") if p]
|
||||
hook fires after that point. This applies to every title type. If one episode of S01
|
||||
fails, the S01 hook does not fire at all.
|
||||
|
||||
The hook is keyed to the folder, not to the season, so one season landing in several
|
||||
unshackle attaches the hook to the folder, not to the season, so one season landing in several
|
||||
folders (`-q 1080,720` with a quality-dependent folder template) fires it once per folder,
|
||||
each with its own `{folder}`. A movie is a group of its own: a `season` hook fires for a
|
||||
movie's folder as soon as the movie finishes.
|
||||
@@ -269,32 +268,33 @@ entries, which have no `--postscript` equivalent.
|
||||
## The REST API
|
||||
|
||||
The API never accepts a post-script command. `postscript`, `post_script` and `post_scripts`
|
||||
in a `POST /api/download` body are rejected with `400 INVALID_PARAMETERS`, because a command
|
||||
arriving from an HTTP caller would be remote code execution.
|
||||
in a `POST /api/download` body get `400 INVALID_PARAMETERS`. A command that arrives from an
|
||||
HTTP caller would be remote code execution.
|
||||
|
||||
Scripts defined in `unshackle.yaml` do run for API jobs, music jobs included. Only the
|
||||
unshackle does operate the scripts defined in `unshackle.yaml` for API jobs, music jobs
|
||||
included. Only the
|
||||
command itself may not cross the network.
|
||||
|
||||
## Logging
|
||||
|
||||
The command that was run is logged twice: at `DEBUG` level on the console, and as a
|
||||
unshackle logs the command it operated twice: at `DEBUG` level on the console, and as a
|
||||
`post_script_dispatch` entry in the
|
||||
[structured JSON debug log](../../guide/troubleshooting.md#the-structured-json-debug-log)
|
||||
when that log is enabled.
|
||||
when that log is on.
|
||||
|
||||
Both are masked the same way, honouring [`redact_paths`](misc.md), which is on by default.
|
||||
unshackle masks both the same way, and honours [`redact_paths`](misc.md), which is on by default.
|
||||
Debug logs get shared in issue reports, and a hook command line is mostly paths. URL
|
||||
credentials and `token=` / `api_key=` query parameters are also masked.
|
||||
|
||||
!!! warning "Do not hardcode secrets in the command"
|
||||
An arbitrary secret in the command line, such as `-H "Authorization: Bearer <key>"`,
|
||||
cannot be recognised and is logged verbatim. Read the secret from a file or an
|
||||
unshackle cannot recognise an arbitrary secret in the command line, such as
|
||||
`-H "Authorization: Bearer <key>"`, and logs it verbatim. Read the secret from a file or an
|
||||
environment variable inside your script rather than putting it in the `command`.
|
||||
|
||||
## Limitations
|
||||
|
||||
- No `success` hooks run under `--no-mux` or `--skip-dl`, because neither writes a muxed
|
||||
- No `success` hook operates under `--no-mux` or `--skip-dl`, because neither writes a muxed
|
||||
output. A `failure` hook still runs under `--no-mux` if the download itself fails.
|
||||
- `failure` hooks only run in `file` mode.
|
||||
- `failure` hooks only operate in `file` mode.
|
||||
- There is no webhook sender. Call `curl` from a script instead.
|
||||
- Script output is not captured. Redirect it inside your own script if you want a log.
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
Per-service configuration, keyed by the canonical service tag (for example `EXAMPLE1`, `EXAMPLE2`,
|
||||
`EXAMPLE3`). unshackle reads several well-known sub-keys out of each service's block:
|
||||
|
||||
- **`proxy_map`**: remaps the region query you passed to `-p/--proxy` for this service. A key is
|
||||
that query, or `"provider:query"` when the flag also named a provider; the value is the query
|
||||
asked of the proxy provider instead. It has no effect when `-p` was given a full proxy URL.
|
||||
- **`proxy_map`**: remaps the region query you passed to `-p/--proxy` for this service.
|
||||
A config key is that query, or `"provider:query"` when the flag also named a proxy provider. The value is
|
||||
the query asked of the proxy provider instead. It has no effect when you give `-p` a full proxy URL.
|
||||
- **`title_map`**: an exact-match rename map applied to fetched titles (source name →
|
||||
desired name), so a service that names a title differently from your library still matches.
|
||||
- **`dl`**: per-service download defaults, using the same keys as the global
|
||||
[`dl`](download.md#dl) block.
|
||||
|
||||
Individual services may read any additional keys they define. The merged result (the service's
|
||||
own `config.yaml` with this block layered on top) is handed to the service as `self.config`.
|
||||
Individual services may read any additional keys they define. unshackle hands the merged result
|
||||
(the service's own `config.yaml` with this block layered on top) to the service as `self.config`.
|
||||
|
||||
User- or device-specific values (API keys, account IDs, device attributes) belong in this block
|
||||
rather than in the service's own `config.yaml`, which holds shared defaults; see
|
||||
rather than in the service's own `config.yaml`, which holds shared defaults. See
|
||||
[creating a service](../../dev/creating-a-service.md).
|
||||
|
||||
```yaml
|
||||
@@ -38,10 +38,10 @@ services:
|
||||
|
||||
Per-service login credentials. Each value is a `username:password[:extra]` string, the same
|
||||
data as a `[username, password]` (or `[username, password, extra]`) list, or a dict of profile
|
||||
name to either of those. With the dict form, `-p/--profile` selects the entry, and the
|
||||
`default` key is used when no profile was given or the named profile is missing. These are
|
||||
parsed into `Credential` objects; the credential's SHA-1 is also used as an account hash for
|
||||
cache keys.
|
||||
name to either of those. With the dict form, `-p/--profile` selects the entry, and unshackle
|
||||
uses the `default` config key when you give no profile, or when the named profile is missing.
|
||||
unshackle parses these into `Credential` objects. It also uses the credential's SHA-1 as an
|
||||
account hash for cache keys.
|
||||
|
||||
```yaml
|
||||
credentials:
|
||||
@@ -52,22 +52,22 @@ credentials:
|
||||
```
|
||||
|
||||
!!! tip "Cookies vs credentials"
|
||||
Cookies are stored as files under [`directories.cookies`](directories.md), not in this key.
|
||||
unshackle stores cookies as files under [`directories.cookies`](directories.md), not in this config key.
|
||||
A service's `authenticate()` accepts cookies, credentials, or both.
|
||||
|
||||
## `firefox_cookies`
|
||||
|
||||
- **Type:** `dict` keyed by service tag · **Default:** `{}`
|
||||
|
||||
Settings for extracting cookies directly from a local Firefox profile. A service block is
|
||||
expected to provide `hosts` (a list of cookie hostnames; entries shorter than 3 characters
|
||||
are ignored to prevent dumping the whole cookie store) and an optional `local_storage`
|
||||
boolean to also pull matching entries from `webappsstore.sqlite`, which only services that
|
||||
keep auth tokens in localStorage rather than in HTTP cookies need. Extraction is read-only.
|
||||
Settings for extracting cookies directly from a local Firefox profile. A service block must give
|
||||
`hosts`, a list of cookie hostnames. unshackle ignores an entry shorter than 3 characters, to
|
||||
prevent dumping the whole cookie store. With an optional `local_storage` boolean, unshackle also
|
||||
pulls matching entries from `webappsstore.sqlite`, which only services that keep auth tokens
|
||||
in localStorage rather than in HTTP cookies need. Extraction is read-only.
|
||||
|
||||
!!! note "Firefox does not need to be closed"
|
||||
The extractor copies **both** `cookies.sqlite` **and** its WAL file into a `0700` temp
|
||||
directory, so writes Firefox has not yet flushed to the main DB are included. Extraction
|
||||
directory, so the copy holds the writes Firefox has not yet flushed to the main DB. Extraction
|
||||
fails only if Firefox holds an exclusive write lock at the instant of the copy. The live
|
||||
profile is not modified.
|
||||
|
||||
@@ -81,21 +81,21 @@ keep auth tokens in localStorage rather than in HTTP cookies need. Extraction is
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Definitions of remote unshackle service servers, used by the `--remote` mode. Each entry is
|
||||
named by you (pick it with `--server`, or omit that flag when only one is configured) and gives
|
||||
named by you (pick it with `--server`, or do not write that flag when you configure only one) and gives
|
||||
the server's `url` (required), an optional `api_key`, an optional `auth_headers` list, an
|
||||
optional `server_cdm` boolean, and an optional `services` sub-dict of per-service local
|
||||
overrides such as `title_map`.
|
||||
|
||||
`auth_headers` lists extra header names to send the API key in, tried before the defaults
|
||||
`X-Secret-Key` and `X-Api-Key`, which are always appended as fallbacks. unshackle sends the
|
||||
first name; if the server answers `401`, it retries the same request with the next name, and
|
||||
keeps the one that works for the rest of the session. Names you list keep your spelling and are
|
||||
not repeated in the fallbacks, so `auth_headers: ["Authorization", "x-secret-key"]` is tried as
|
||||
`Authorization`, `x-secret-key`, `X-Api-Key`.
|
||||
first name. If the server answers `401`, it retries the same request with the next name, and
|
||||
keeps the one that works for the rest of the HTTP session. Names you give keep your spelling and
|
||||
are not repeated in the fallbacks, so unshackle tries
|
||||
`auth_headers: ["Authorization", "x-secret-key"]` as `Authorization`, `x-secret-key`, `X-Api-Key`.
|
||||
|
||||
In `--remote` mode unshackle turns the server's service list into synthetic CLI
|
||||
commands that run against it, falling back to the tags in that `services` sub-dict when the
|
||||
list cannot be fetched. Each synthetic command carries the server-side service's options and
|
||||
commands that operate against it, falling back to the tags in that `services` sub-dict when
|
||||
unshackle cannot fetch the list. Each synthetic command carries the server-side service's options and
|
||||
documentation, so `unshackle dl --remote <TAG> -h` shows the same help text as it does on the
|
||||
server. See [remote sessions](../../dev/rest-api/remote-sessions.md) for the
|
||||
full setup.
|
||||
@@ -105,7 +105,7 @@ full setup.
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
|
||||
Configuration for the `serve` command (the built-in REST API server). The full server guide
|
||||
is the [REST API](../../dev/rest-api/index.md) section; these are the config keys.
|
||||
is the [REST API](../../dev/rest-api/index.md) section. These are the config keys.
|
||||
|
||||
| Sub-key | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
@@ -123,15 +123,16 @@ is the [REST API](../../dev/rest-api/index.md) section; these are the config key
|
||||
| `devices` | list | *(auto)* | Widevine devices offered; auto-filled from `directories.wvds`. |
|
||||
| `playready_devices` | list | *(auto)* | PlayReady devices; auto-filled from `directories.prds`. |
|
||||
|
||||
Each entry under `users` is keyed by that user's API key and may set its own `services`,
|
||||
Each entry under `users` uses that user's API key as its name, and can set its own `services`,
|
||||
`devices`, and `playready_devices` allowlists, narrowing the global ones, plus an optional
|
||||
`username` used as the log label for that key (defaults to a truncated form of the key). A
|
||||
user with no `playready_devices` key gets no PlayReady access at all, not the global list.
|
||||
`username` used as the log label for that API key (defaults to a truncated form of the API key).
|
||||
A user with no `playready_devices` config key gets no PlayReady access at all, not the global
|
||||
list.
|
||||
|
||||
`server_cdm` decides whether the server runs the CDM licensing for that key. It is `false`
|
||||
`server_cdm` decides whether the server runs the CDM licensing for that API key. It is `false`
|
||||
unless the entry sets it, so a remote client configured with `server_cdm: true` is told to
|
||||
license with its own local CDM instead, and a client that asks anyway gets a `FORBIDDEN`
|
||||
error. Because a download job always licenses with the server's CDM, a key without
|
||||
error. Because a download job always licenses with the server's CDM, an API key without
|
||||
`server_cdm` also cannot submit or retry `/api/download` jobs. Keys that have no `users`
|
||||
entry, such as `api_secret`, keep server CDM access.
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ The full guide is at [Vaults](../../guide/vaults.md). Two keys configure them.
|
||||
|
||||
- **Type:** `list[dict]` · **Default:** `[]`
|
||||
|
||||
An ordered list of key-vault backends. unshackle queries them in order and reuses content
|
||||
keys instead of re-licensing. Each entry needs a `type` (the backend module name) and a
|
||||
`name`, plus backend-specific keys.
|
||||
An ordered list of key-vault backends. unshackle queries them in order and reuses the
|
||||
content keys instead of licensing them again. Each entry needs a `type` (the backend module
|
||||
name) and a `name`, plus backend-specific keys.
|
||||
|
||||
| `type` | Purpose | Required keys | Notes |
|
||||
|--------|---------|--------------|-------|
|
||||
@@ -32,12 +32,12 @@ key_vaults:
|
||||
```
|
||||
|
||||
!!! note "Per-entry options"
|
||||
- `no_push: true` makes a vault read-only (keys are fetched but never written to it).
|
||||
- `no_push: true` makes a vault read-only (unshackle fetches content keys from it but never writes to it).
|
||||
- A vault of `type: API` whose `name` contains `decrypt_labs` auto-fills its `token` from
|
||||
[`decrypt_labs_api_key`](misc.md#external-api-keys) when not set inline. Vault `type` values are
|
||||
case-sensitive module names.
|
||||
- An all-zero content key (32 zeros) is treated as "no key" everywhere and is never
|
||||
stored.
|
||||
- unshackle treats an all-zero content key (32 zeros) as "no key" everywhere and never
|
||||
stores it.
|
||||
|
||||
## `vault_timeout`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user