feat(DSCP): Add option to get UHD tracks
This commit is contained in:
parent
6f31335d6a
commit
79ad7516d1
@ -26,13 +26,14 @@ class DSCP(Service):
|
|||||||
Author: stabbedbybrick
|
Author: stabbedbybrick
|
||||||
Authorization: Cookies
|
Authorization: Cookies
|
||||||
Robustness:
|
Robustness:
|
||||||
L3: 1080p, AAC2.0
|
L3: 2160p, AAC2.0
|
||||||
|
|
||||||
\b
|
\b
|
||||||
Tips:
|
Tips:
|
||||||
- Input can be either complete title URL or just the path: '/show/richard-hammonds-workshop'
|
- Input can be either complete title URL or just the path: '/show/richard-hammonds-workshop'
|
||||||
- Use the --lang LANG_RANGE option to request non-english tracks
|
- Use the --lang LANG_RANGE option to request non-english tracks
|
||||||
- Single video URLs are currently not supported
|
- Single video URLs are currently not supported
|
||||||
|
- use -v H.265 to request H.265 tracks
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ class DSCP(Service):
|
|||||||
|
|
||||||
def __init__(self, ctx: Context, title: str):
|
def __init__(self, ctx: Context, title: str):
|
||||||
self.title = title
|
self.title = title
|
||||||
|
self.vcodec = ctx.parent.params.get("vcodec")
|
||||||
super().__init__(ctx)
|
super().__init__(ctx)
|
||||||
|
|
||||||
self.license = None
|
self.license = None
|
||||||
@ -65,7 +67,7 @@ class DSCP(Service):
|
|||||||
self.configure()
|
self.configure()
|
||||||
|
|
||||||
def search(self) -> Generator[SearchResult, None, None]:
|
def search(self) -> Generator[SearchResult, None, None]:
|
||||||
r = self.session.get(self.config["endpoints"]["search"].format(region=self.region, query=self.title))
|
r = self.session.get(self.config["endpoints"]["search"].format(base_api=self.base_api, query=self.title))
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
data = r.json()
|
data = r.json()
|
||||||
|
|
||||||
@ -91,9 +93,15 @@ class DSCP(Service):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if kind == "show":
|
if kind == "show":
|
||||||
r = self.session.get(self.config["endpoints"]["show"].format(region=self.region, title_id=content_id))
|
data = self.session.get(
|
||||||
r.raise_for_status()
|
self.config["endpoints"]["show"].format(base_api=self.base_api, title_id=content_id)
|
||||||
data = r.json()
|
).json()
|
||||||
|
if "errors" in data:
|
||||||
|
if "invalid.token" in data["errors"][0]["code"]:
|
||||||
|
self.log.error("- Invalid Token. Cookies are invalid or may have expired.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
raise ConnectionError(data["errors"])
|
||||||
|
|
||||||
content = next(x for x in data["included"] if x["attributes"].get("alias") == "generic-show-episodes")
|
content = next(x for x in data["included"] if x["attributes"].get("alias") == "generic-show-episodes")
|
||||||
content_id = content["id"]
|
content_id = content["id"]
|
||||||
@ -104,7 +112,7 @@ class DSCP(Service):
|
|||||||
seasons = [
|
seasons = [
|
||||||
self.session.get(
|
self.session.get(
|
||||||
self.config["endpoints"]["seasons"].format(
|
self.config["endpoints"]["seasons"].format(
|
||||||
region=self.region, content_id=content_id, season=season, show_id=show_id
|
base_api=self.base_api, content_id=content_id, season=season, show_id=show_id
|
||||||
)
|
)
|
||||||
).json()
|
).json()
|
||||||
for season in season_params
|
for season in season_params
|
||||||
@ -134,138 +142,32 @@ class DSCP(Service):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_tracks(self, title: Union[Movie, Episode]) -> Tracks:
|
def get_tracks(self, title: Union[Movie, Episode]) -> Tracks:
|
||||||
|
platform = "firetv" if self.vcodec == "H.265" else "desktop"
|
||||||
res = self.session.post(
|
res = self.session.post(
|
||||||
self.config["endpoints"]["playback"].format(region=self.region),
|
self.config["endpoints"]["playback"].format(base_api=self.base_api),
|
||||||
json={
|
json={
|
||||||
"videoId": title.id,
|
"videoId": title.id,
|
||||||
"wisteriaProperties": {
|
|
||||||
"advertiser": {
|
|
||||||
"adId": "|84958235701907329361495486486652228049||17163182474853637414c74993b0cb4f9a42062d41449",
|
|
||||||
"firstPlay": 0,
|
|
||||||
"fwDid": "",
|
|
||||||
"fwIsLat": 0,
|
|
||||||
"interactiveCapabilities": [
|
|
||||||
"brightline",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"appBundle": "undefined",
|
|
||||||
"device": {
|
|
||||||
"browser": {
|
|
||||||
"name": "chrome",
|
|
||||||
"version": "125.0.0.0",
|
|
||||||
},
|
|
||||||
"id": "",
|
|
||||||
"language": "en",
|
|
||||||
"make": "",
|
|
||||||
"model": "",
|
|
||||||
"name": "chrome",
|
|
||||||
"os": "Windows",
|
|
||||||
"osVersion": "NT 10.0",
|
|
||||||
"player": {
|
|
||||||
"name": "Discovery Player Web",
|
|
||||||
"version": "",
|
|
||||||
},
|
|
||||||
"type": "desktop",
|
|
||||||
},
|
|
||||||
"gdpr": 0,
|
|
||||||
"platform": "desktop",
|
|
||||||
"playbackId": str(uuid.uuid4()),
|
|
||||||
"product": "dplus_se" if self.site_id != "dplus_se" else "dplus_us",
|
|
||||||
"sessionId": str(uuid.uuid4()),
|
|
||||||
"siteId": "dplus_se" if self.site_id != "dplus_se" else "dplus_us",
|
|
||||||
"streamProvider": {
|
|
||||||
"hlsVersion": 6,
|
|
||||||
"pingConfig": 0,
|
|
||||||
"suspendBeaconing": 0,
|
|
||||||
"version": "1.0.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"deviceCapabilities": {
|
|
||||||
"manifests": {
|
|
||||||
"formats": {
|
|
||||||
"dash": {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"segments": {
|
|
||||||
"formats": {
|
|
||||||
"fmp4": {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"codecs": {
|
|
||||||
"audio": {
|
|
||||||
"decoders": [
|
|
||||||
{
|
|
||||||
"codec": "aac",
|
|
||||||
"profiles": [
|
|
||||||
"lc",
|
|
||||||
"hev",
|
|
||||||
"hev2",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"video": {
|
|
||||||
"decoders": [
|
|
||||||
{
|
|
||||||
"codec": "h264",
|
|
||||||
"profiles": [
|
|
||||||
"high",
|
|
||||||
"main",
|
|
||||||
"baseline",
|
|
||||||
],
|
|
||||||
"maxLevel": "5.2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codec": "h265",
|
|
||||||
"profiles": [
|
|
||||||
"main10",
|
|
||||||
"main",
|
|
||||||
],
|
|
||||||
"maxLevel": "5.2",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"hdrFormats": [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"contentProtection": {
|
|
||||||
"contentDecryptionModules": [
|
|
||||||
{
|
|
||||||
"drmKeySystem": "clearkey",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"drmKeySystem": "widevine",
|
|
||||||
"maxSecurityLevel": "l3",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"deviceInfo": {
|
"deviceInfo": {
|
||||||
"adBlocker": False,
|
"adBlocker": "false",
|
||||||
"deviceId": "",
|
"drmSupported": "true",
|
||||||
"drmTypes": {
|
"hwDecodingCapabilities": ["H264", "H265"],
|
||||||
"widevine": True,
|
"screen": {"width": 3840, "height": 2160},
|
||||||
"playready": False,
|
"player": {"width": 3840, "height": 2160},
|
||||||
"fairplay": False,
|
},
|
||||||
"clearkey": True,
|
"wisteriaProperties": {
|
||||||
},
|
"advertiser": {"firstPlay": 0, "fwIsLat": 0},
|
||||||
"drmSupported": True,
|
"device": {"browser": {"name": "chrome", "version": "96.0.4664.55"}, "type": platform},
|
||||||
"hdrCapabilities": [
|
"platform": platform,
|
||||||
"SDR",
|
"product": "dplus_emea",
|
||||||
],
|
"sessionId": str(uuid.uuid1()),
|
||||||
"hwDecodingCapabilities": [
|
"streamProvider": {"suspendBeaconing": 0, "hlsVersion": 7, "pingConfig": 1},
|
||||||
"H264",
|
|
||||||
"H265",
|
|
||||||
],
|
|
||||||
"soundCapabilities": [
|
|
||||||
"STEREO",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
).json()
|
).json()
|
||||||
|
|
||||||
if "errors" in res:
|
if "errors" in res:
|
||||||
if "missingpackage" in res["errors"][0]["code"]:
|
if "missingpackage" in res["errors"][0]["code"]:
|
||||||
self.log.error("- Access Denied. Please check your subscription.")
|
self.log.error("- Access Denied. Title is not available for this account.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if "invalid.token" in res["errors"][0]["code"]:
|
if "invalid.token" in res["errors"][0]["code"]:
|
||||||
@ -306,18 +208,21 @@ class DSCP(Service):
|
|||||||
def configure(self):
|
def configure(self):
|
||||||
self.session.headers.update(
|
self.session.headers.update(
|
||||||
{
|
{
|
||||||
"origin": "https://www.discoveryplus.com",
|
"user-agent": "Chrome/96.0.4664.55",
|
||||||
"referer": "https://www.discoveryplus.com/",
|
|
||||||
"x-disco-client": "WEB:UNKNOWN:dplus_us:2.44.4",
|
"x-disco-client": "WEB:UNKNOWN:dplus_us:2.44.4",
|
||||||
"x-disco-params": "realm=go,siteLookupKey=dplus_us,bid=dplus,hn=www.discoveryplus.com,hth=,uat=false",
|
"x-disco-params": "realm=go,siteLookupKey=dplus_us,bid=dplus,hn=www.discoveryplus.com,hth=,uat=false",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
info = self.session.get(self.config["endpoints"]["info"]).json()
|
info = self.session.get(self.config["endpoints"]["info"]).json()
|
||||||
self.region = info["data"]["attributes"]["baseApiUrl"].split("-")[0].split("//")[1]
|
self.base_api = info["data"]["attributes"]["baseApiUrl"]
|
||||||
|
|
||||||
user = self.session.get(self.config["endpoints"]["user"].format(region=self.region)).json()
|
user = self.session.get(self.config["endpoints"]["user"].format(base_api=self.base_api)).json()
|
||||||
if "errors" in user:
|
if "errors" in user:
|
||||||
|
if "invalid.token" in user["errors"][0]["code"]:
|
||||||
|
self.log.error("- Invalid Token. Cookies are invalid or may have expired.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
raise ConnectionError(user["errors"])
|
raise ConnectionError(user["errors"])
|
||||||
|
|
||||||
self.territory = user["data"]["attributes"]["currentLocationTerritory"]
|
self.territory = user["data"]["attributes"]["currentLocationTerritory"]
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
endpoints:
|
endpoints:
|
||||||
info: https://global-prod.disco-api.com/bootstrapInfo
|
info: https://global-prod.disco-api.com/bootstrapInfo
|
||||||
user: https://{region}-prod-direct.discoveryplus.com/users/me
|
user: "{base_api}/users/me"
|
||||||
prod: "https://{region}-prod-direct.discoveryplus.com/cms/configs/web-prod"
|
prod: "{base_api}/cms/configs/web-prod"
|
||||||
show: "https://{region}-prod-direct.discoveryplus.com/cms/routes/show/{title_id}?include=default&decorators=viewingHistory,isFavorite,playbackAllowed"
|
show: "{base_api}/cms/routes/show/{title_id}?include=default&decorators=viewingHistory,isFavorite,playbackAllowed"
|
||||||
seasons: "https://{region}-prod-direct.discoveryplus.com/cms/collections/{content_id}?include=default&decorators=viewingHistory,isFavorite,playbackAllowed,contentAction,badges&{season}&{show_id}"
|
seasons: "{base_api}/cms/collections/{content_id}?include=default&decorators=viewingHistory,isFavorite,playbackAllowed,contentAction,badges&{season}&{show_id}"
|
||||||
playback: "https://{region}-prod-direct.discoveryplus.com/playback/v3/videoPlaybackInfo"
|
playback: "{base_api}/playback/v3/videoPlaybackInfo"
|
||||||
search: "https://{region}-prod-direct.discoveryplus.com/cms/routes/search/result?include=default&decorators=viewingHistory,isFavorite,playbackAllowed,contentAction,badges&contentFilter[query]={query}&page[items.number]=1&page[items.size]=8"
|
search: "{base_api}/cms/routes/search/result?include=default&decorators=viewingHistory,isFavorite,playbackAllowed,contentAction,badges&contentFilter[query]={query}&page[items.number]=1&page[items.size]=8"
|
Loading…
Reference in New Issue
Block a user