mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
feat(dl): add --cdm to pin one CDM device for a run
Overrides the cdm config mapping (and its quality/DRM sub-entries) for the whole run; the REST API cdm field now flows through the same param.
This commit is contained in:
@@ -186,6 +186,7 @@ order the service used, then renumbers the episodes into the order you asked for
|
|||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `--cdm-only` / `--vaults-only` | Use only the CDM, or only Key Vaults, for key acquisition. |
|
| `--cdm-only` / `--vaults-only` | Use only the CDM, or only Key Vaults, for key acquisition. |
|
||||||
|
| `--cdm <name>` | Use the named CDM device from the `cdm` config mapping for this run, ignoring the service/default mapping. |
|
||||||
| `--skip-dl` | Skip the download but still retrieve keys. |
|
| `--skip-dl` | Skip the download but still retrieve keys. |
|
||||||
| `--export` | Export track info and keys to a JSON file in the exports directory. |
|
| `--export` | Export track info and keys to a JSON file in the exports directory. |
|
||||||
|
|
||||||
|
|||||||
@@ -751,6 +751,7 @@ By default, unshackle checks your **key vaults** first and only asks a **CDM** t
|
|||||||
a content key when the vault misses. You can force one side or the other:
|
a content key when the vault misses. You can force one side or the other:
|
||||||
|
|
||||||
- `--cdm-only`: only use the CDM (skip vaults).
|
- `--cdm-only`: only use the CDM (skip vaults).
|
||||||
|
- `--cdm <name>`: use the named CDM device for this run, ignoring the `cdm` config mapping (including its quality and Widevine/PlayReady sub-entries).
|
||||||
- `--vaults-only`: only use key vaults and never license through the CDM. A missing
|
- `--vaults-only`: only use key vaults and never license through the CDM. A missing
|
||||||
content key fails.
|
content key fails.
|
||||||
|
|
||||||
@@ -945,6 +946,7 @@ authoritative list.
|
|||||||
| `--workers` / `--downloads` / `--slow` | | Concurrency and pacing. |
|
| `--workers` / `--downloads` / `--slow` | | Concurrency and pacing. |
|
||||||
| `--list` / `--list-titles` / `--skip-dl` | | Dry runs. |
|
| `--list` / `--list-titles` / `--skip-dl` | | Dry runs. |
|
||||||
| `--cdm-only` / `--vaults-only` | | Content key source control. |
|
| `--cdm-only` / `--vaults-only` | | Content key source control. |
|
||||||
|
| `--cdm <name>` | | Pin one CDM device, bypassing the `cdm` config mapping. |
|
||||||
| `--export` | | Export track info and keys to JSON. |
|
| `--export` | | Export track info and keys to JSON. |
|
||||||
| `--tmdb` / `--imdb` / `--tvdb` / `--anilist` / `--enrich` | | Metadata overrides. |
|
| `--tmdb` / `--imdb` / `--tvdb` / `--anilist` / `--enrich` | | Metadata overrides. |
|
||||||
| `--tvdb-order` | | Renumber episodes to a TVDB season order. |
|
| `--tvdb-order` | | Renumber episodes to a TVDB season order. |
|
||||||
|
|||||||
@@ -498,6 +498,7 @@ control this trade-off on the `dl` command:
|
|||||||
|------|--------|
|
|------|--------|
|
||||||
| `--vaults-only` | Never send a license request; use only cached/vault keys. Fails if a content key is missing. |
|
| `--vaults-only` | Never send a license request; use only cached/vault keys. Fails if a content key is missing. |
|
||||||
| `--cdm-only` | Ignore vaults for sourcing keys and always perform a fresh license request. |
|
| `--cdm-only` | Ignore vaults for sourcing keys and always perform a fresh license request. |
|
||||||
|
| `--cdm <name>` | Use the named CDM device for this run instead of the one the `cdm` config maps for the service. |
|
||||||
|
|
||||||
See [key vaults](vaults.md) for how to configure vault backends.
|
See [key vaults](vaults.md) for how to configure vault backends.
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ the [DRM & CDM guide](../../guide/drm-and-cdm.md). Device files themselves live
|
|||||||
- **Type:** `dict` · **Default:** `{}`
|
- **Type:** `dict` · **Default:** `{}`
|
||||||
|
|
||||||
Maps a service tag to the CDM (Widevine/PlayReady device) to use, with a `default` fallback.
|
Maps a service tag to the CDM (Widevine/PlayReady device) to use, with a `default` fallback.
|
||||||
Resolution is case-insensitive: a per-request API override wins, then the per-service entry,
|
Resolution is case-insensitive: an override (`dl --cdm <name>`, or the `cdm` field of an API
|
||||||
then `default`.
|
job) wins, then the per-service entry, then `default`. An override pins one device for the whole
|
||||||
|
run and skips any quality or Widevine/PlayReady sub-entries.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
cdm:
|
cdm:
|
||||||
|
|||||||
@@ -833,6 +833,13 @@ class dl:
|
|||||||
default=None,
|
default=None,
|
||||||
help="Only use CDM, or only use Key Vaults for retrieval of Decryption Keys.",
|
help="Only use CDM, or only use Key Vaults for retrieval of Decryption Keys.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--cdm",
|
||||||
|
"cdm_name",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Use this CDM device for the run, overriding the cdm config mapping.",
|
||||||
|
)
|
||||||
@click.option("--no-proxy", is_flag=True, default=False, help="Force disable all proxy use.")
|
@click.option("--no-proxy", is_flag=True, default=False, help="Force disable all proxy use.")
|
||||||
@click.option(
|
@click.option(
|
||||||
"--no-proxy-download",
|
"--no-proxy-download",
|
||||||
@@ -1201,6 +1208,7 @@ class dl:
|
|||||||
f"Applied service-specific '{config_key}' overrides for {self.service}: {override_value}"
|
f"Applied service-specific '{config_key}' overrides for {self.service}: {override_value}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.cdm_override = ctx.params.get("cdm_name")
|
||||||
cdm_only = ctx.params.get("cdm_only")
|
cdm_only = ctx.params.get("cdm_only")
|
||||||
|
|
||||||
if cdm_only:
|
if cdm_only:
|
||||||
@@ -1504,6 +1512,8 @@ class dl:
|
|||||||
self.service_anime = bool(getattr(service, "ANIME", False))
|
self.service_anime = bool(getattr(service, "ANIME", False))
|
||||||
self.service_daily = bool(getattr(service, "DAILY", False))
|
self.service_daily = bool(getattr(service, "DAILY", False))
|
||||||
self.server_cdm = getattr(service, "_server_cdm", False)
|
self.server_cdm = getattr(service, "_server_cdm", False)
|
||||||
|
if self.server_cdm and self.cdm_override:
|
||||||
|
self.log.warning("--cdm is ignored: this remote service licenses with the server CDM")
|
||||||
self._remote_service = service if hasattr(service, "_server_cdm") else None
|
self._remote_service = service if hasattr(service, "_server_cdm") else None
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
|
|||||||
@@ -440,6 +440,7 @@ def perform_download(
|
|||||||
"no_proxy": params.get("no_proxy", False),
|
"no_proxy": params.get("no_proxy", False),
|
||||||
"no_proxy_download": params.get("no_proxy_download", False),
|
"no_proxy_download": params.get("no_proxy_download", False),
|
||||||
"profile": params.get("profile"),
|
"profile": params.get("profile"),
|
||||||
|
"cdm_name": params.get("cdm"),
|
||||||
"repack": params.get("repack", False),
|
"repack": params.get("repack", False),
|
||||||
"tag": params.get("tag"),
|
"tag": params.get("tag"),
|
||||||
"tmdb_id": params.get("tmdb_id"),
|
"tmdb_id": params.get("tmdb_id"),
|
||||||
@@ -484,10 +485,6 @@ def perform_download(
|
|||||||
daily=params.get("daily", False),
|
daily=params.get("daily", False),
|
||||||
output_dir=Path(params["output_dir"]) if params.get("output_dir") else None,
|
output_dir=Path(params["output_dir"]) if params.get("output_dir") else None,
|
||||||
)
|
)
|
||||||
# Per-request CDM override (a device name in the WVDs dir); get_cdm() takes it first.
|
|
||||||
if params.get("cdm"):
|
|
||||||
dl_instance.cdm_override = params["cdm"]
|
|
||||||
|
|
||||||
# Per-request credential ("user:pass"); feed it into the map get_credentials() reads so a
|
# Per-request credential ("user:pass"); feed it into the map get_credentials() reads so a
|
||||||
# client can authenticate without anything being persisted to disk. Without a profile,
|
# client can authenticate without anything being persisted to disk. Without a profile,
|
||||||
# get_credentials() falls back to "default", so store it there too rather than dropping it
|
# get_credentials() falls back to "default", so store it there too rather than dropping it
|
||||||
|
|||||||
@@ -757,6 +757,9 @@ async def download(request: web.Request) -> web.Response:
|
|||||||
cdm_only:
|
cdm_only:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Only use CDM for content key retrieval (true) or only vaults (false) (default - None)
|
description: Only use CDM for content key retrieval (true) or only vaults (false) (default - None)
|
||||||
|
cdm:
|
||||||
|
type: string
|
||||||
|
description: CDM device name on the server to license with, overriding the cdm config mapping. Requires serve.cdm_overrides to allow it (default - None)
|
||||||
proxy:
|
proxy:
|
||||||
type: string
|
type: string
|
||||||
description: Proxy URI or country code (default - None)
|
description: Proxy URI or country code (default - None)
|
||||||
|
|||||||
Reference in New Issue
Block a user