From b8f00f6b95cb6b132c3a448e904bf190afaae6ff Mon Sep 17 00:00:00 2001 From: imSp4rky Date: Sun, 20 Sep 2026 01:19:48 -0600 Subject: [PATCH] fix(remote): keep the server's own CDM when the tier licenses with server_cdm --- tests/remote/unit/test_server_accounts.py | 14 ++++++++++++++ unshackle/core/api/handlers.py | 4 +++- unshackle/core/remote_service.py | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/remote/unit/test_server_accounts.py b/tests/remote/unit/test_server_accounts.py index c229a309..d3247d4a 100644 --- a/tests/remote/unit/test_server_accounts.py +++ b/tests/remote/unit/test_server_accounts.py @@ -119,3 +119,17 @@ def test_validate_rejects_bad_region_values(accounts): handlers.config.serve["server_accounts"]["EX"]["ca_main"] = "canada" with pytest.raises(ValueError): handlers.validate_server_accounts() + + +def test_server_cdm_ignores_client_cdm_type(monkeypatch): + """A server_cdm tier licenses with the server's own device, so the client's CDM type must + not swap it for a stub of the other DRM system.""" + seen = [] + monkeypatch.setattr(handlers, "load_service_yaml", lambda s: {}) + monkeypatch.setattr(handlers, "load_full_cdm", lambda s, p, t=None: seen.append(t)) + monkeypatch.setattr(handlers.Services, "load", staticmethod(lambda s: object())) + monkeypatch.setattr(handlers, "instantiate_service", lambda *a: "svc") + data = {"cdm_type": "playready"} + handlers.create_service_instance("OTHER", "t", data, None, [], None, server_cdm=True) + handlers.create_service_instance("OTHER", "t", data, None, [], None) + assert seen == [None, "playready"] diff --git a/unshackle/core/api/handlers.py b/unshackle/core/api/handlers.py index f78821db..8bb096f0 100644 --- a/unshackle/core/api/handlers.py +++ b/unshackle/core/api/handlers.py @@ -2855,6 +2855,7 @@ def create_service_instance( proxy_providers: list, profile: Optional[str], server_account: bool = False, + server_cdm: bool = False, ) -> Any: """Make a service instance and resolve its credentials and cookies. @@ -2868,7 +2869,7 @@ def create_service_instance( from unshackle.core.tracks import Video service_config = load_service_yaml(normalized_service) - cdm = load_full_cdm(normalized_service, profile, data.get("cdm_type")) + cdm = load_full_cdm(normalized_service, profile, None if server_cdm else data.get("cdm_type")) # Reconstruct enum track-selection params from client data so service code that reads # ctx.parent.params (Service.__init__ proxy/range/vcodec/best_available block) sees enums. @@ -2987,6 +2988,7 @@ async def session_create_handler(data: Dict[str, Any], request: Optional[web.Req proxy_providers, profile, server_account=server_account, + server_cdm=server_cdm_allowed(request, normalized_service), ) service_instance, cookies, credential = await asyncio.to_thread(build_service) diff --git a/unshackle/core/remote_service.py b/unshackle/core/remote_service.py index c148c237..3c5a8f94 100644 --- a/unshackle/core/remote_service.py +++ b/unshackle/core/remote_service.py @@ -938,7 +938,7 @@ class RemoteService: create_data.update(self._service_params) create_data["service_params"] = self._service_params - cdm = self.ctx.obj.cdm if self.ctx.obj else None + cdm = self.ctx.obj.cdm if self.ctx.obj and not self._server_cdm else None if cdm is not None: from unshackle.core.cdm.detect import is_playready_cdm