mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-03-10 08:29:00 +00:00
@@ -1913,8 +1913,7 @@ class dl:
|
|||||||
),
|
),
|
||||||
licence=partial(
|
licence=partial(
|
||||||
service.get_playready_license
|
service.get_playready_license
|
||||||
if (is_playready_cdm(self.cdm))
|
if is_playready_cdm(self.cdm)
|
||||||
and hasattr(service, "get_playready_license")
|
|
||||||
else service.get_widevine_license,
|
else service.get_widevine_license,
|
||||||
title=title,
|
title=title,
|
||||||
track=track,
|
track=track,
|
||||||
|
|||||||
@@ -394,6 +394,27 @@ class Service(metaclass=ABCMeta):
|
|||||||
Decode the data, return as is to reduce unnecessary computations.
|
Decode the data, return as is to reduce unnecessary computations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def get_playready_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> Optional[Union[bytes, str]]:
|
||||||
|
"""
|
||||||
|
Get a PlayReady License message by sending a License Request (challenge).
|
||||||
|
|
||||||
|
This License message contains the encrypted Content Decryption Keys and will be
|
||||||
|
read by the CDM and decrypted.
|
||||||
|
|
||||||
|
This is a very important request to get correct. A bad, unexpected, or missing
|
||||||
|
value in the request can cause your key to be detected and promptly banned,
|
||||||
|
revoked, disabled, or downgraded.
|
||||||
|
|
||||||
|
:param challenge: The license challenge from the PlayReady CDM.
|
||||||
|
:param title: The current `Title` from get_titles that is being executed. This is provided in
|
||||||
|
case it has data needed to be used, e.g. for a HTTP request.
|
||||||
|
:param track: The current `Track` needing decryption. Provided for same reason as `title`.
|
||||||
|
:return: The License response as Bytes or a Base64 string. Don't Base64 Encode or
|
||||||
|
Decode the data, return as is to reduce unnecessary computations.
|
||||||
|
"""
|
||||||
|
# Delegates license handling to the Widevine license method by default if a service-specific PlayReady implementation is not provided.
|
||||||
|
return self.get_widevine_license(challenge=challenge, title=title, track=track)
|
||||||
|
|
||||||
# Required Abstract functions
|
# Required Abstract functions
|
||||||
# The following functions *must* be implemented by the Service.
|
# The following functions *must* be implemented by the Service.
|
||||||
# The functions will be executed in shown order.
|
# The functions will be executed in shown order.
|
||||||
|
|||||||
@@ -303,21 +303,6 @@ class EXAMPLE(Service):
|
|||||||
def get_widevine_service_certificate(self, **_: any) -> str:
|
def get_widevine_service_certificate(self, **_: any) -> str:
|
||||||
return self.config.get("certificate")
|
return self.config.get("certificate")
|
||||||
|
|
||||||
def get_playready_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> Optional[bytes]:
|
|
||||||
license_url = self.config["endpoints"].get("playready_license")
|
|
||||||
if not license_url:
|
|
||||||
raise ValueError("PlayReady license endpoint not configured")
|
|
||||||
|
|
||||||
response = self.session.post(
|
|
||||||
url=license_url,
|
|
||||||
data=challenge,
|
|
||||||
headers={
|
|
||||||
"user-agent": self.config["client"][self.device]["license_user_agent"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.content
|
|
||||||
|
|
||||||
def get_widevine_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> Optional[Union[bytes, str]]:
|
def get_widevine_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> Optional[Union[bytes, str]]:
|
||||||
license_url = self.license_data.get("url") or self.config["endpoints"].get("widevine_license")
|
license_url = self.license_data.get("url") or self.config["endpoints"].get("widevine_license")
|
||||||
if not license_url:
|
if not license_url:
|
||||||
@@ -340,3 +325,18 @@ class EXAMPLE(Service):
|
|||||||
return response.json().get("license")
|
return response.json().get("license")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return response.content
|
return response.content
|
||||||
|
|
||||||
|
def get_playready_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> Optional[Union[bytes, str]]:
|
||||||
|
license_url = self.config["endpoints"].get("playready_license")
|
||||||
|
if not license_url:
|
||||||
|
raise ValueError("PlayReady license endpoint not configured")
|
||||||
|
|
||||||
|
response = self.session.post(
|
||||||
|
url=license_url,
|
||||||
|
data=challenge,
|
||||||
|
headers={
|
||||||
|
"user-agent": self.config["client"][self.device]["license_user_agent"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.content
|
||||||
Reference in New Issue
Block a user