diff --git a/vinetrimmer/commands/dl.py b/vinetrimmer/commands/dl.py index 5c17925..effe7bd 100644 --- a/vinetrimmer/commands/dl.py +++ b/vinetrimmer/commands/dl.py @@ -395,7 +395,7 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla # Modified video track selection to choose closest resolution if exact match not found if quality and closest_resolution: available_resolutions = [int(track.height) for track in title.tracks.videos] - if not available_resolutions: + if available_resolutions == []: log.error(" - No video tracks available") continue if quality not in available_resolutions: @@ -405,11 +405,13 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla # Modified video track selection to choose lowest bitrate if vbitrate == min if vbitrate and vbitrate.lower() == "min": - available_bitrate = [int(track.bitrate) for track in title.tracks.videos] - if not available_resolutions: + if not quality: + quality = 1080 + available_bitrate = [int(track.bitrate) for track in title.tracks.videos if track.height == quality] + if available_bitrate == []: log.error(" - No video tracks available") continue - vbitrate = min(available_bitrate) + vbitrate = min(available_bitrate) / 1000 log.warning(f" - Choosing minimum bitrate: {vbitrate}") elif vbitrate: vbitrate = int(vbitrate) @@ -528,9 +530,6 @@ def result(ctx, service, quality, closest_resolution, range_, wanted, alang, sla session_id=session_id ) assert license - # Convert bytes to string if necessary - if isinstance(license, bytes): - license = license.decode('utf-8') ctx.obj.cdm.parse_license( session_id, license diff --git a/vinetrimmer/devices/hisense_smarttv_he55a7000euwts_sl3000.prd b/vinetrimmer/devices/hisense_smarttv_he55a7000euwts_sl3000.prd index 0c1b3a2..5140dad 100644 Binary files a/vinetrimmer/devices/hisense_smarttv_he55a7000euwts_sl3000.prd and b/vinetrimmer/devices/hisense_smarttv_he55a7000euwts_sl3000.prd differ diff --git a/vinetrimmer/key_store.db b/vinetrimmer/key_store.db index dec5608..b46f4fc 100644 Binary files a/vinetrimmer/key_store.db and b/vinetrimmer/key_store.db differ diff --git a/vinetrimmer/services/amazon.py b/vinetrimmer/services/amazon.py index 9f86e9e..b7cee19 100644 --- a/vinetrimmer/services/amazon.py +++ b/vinetrimmer/services/amazon.py @@ -636,10 +636,10 @@ class Amazon(BaseService): "marketplaceID": self.region["marketplace_id"], "resourceUsage": "ImmediateConsumption", "videoMaterialType": "Feature", - "operatingSystemName": "Linux" if self.vquality == "SD" else "Windows", - "operatingSystemVersion": "unknown" if self.vquality == "SD" else "10.0", + "operatingSystemName": "Windows", + "operatingSystemVersion": "10.0", "customerID": self.customer_id, - "deviceDrmOverride": "Playready", #CENC or Playready both work + "deviceDrmOverride": "CENC", #CENC or Playready both work "deviceStreamingTechnologyOverride": "DASH", # or SmoothStreaming "deviceVideoQualityOverride": self.vquality, "deviceHdrFormatsOverride": self.VIDEO_RANGE_MAP.get(self.range, "None"), @@ -661,6 +661,7 @@ class Amazon(BaseService): ).json() lic_list.append(lic) params["deviceStreamingTechnologyOverride"] = "SmoothStreaming" + params["deviceDrmOverride"] = "Playready" lic = self.session.post( url=self.endpoints["licence"], params=params, @@ -1161,76 +1162,66 @@ class Amazon(BaseService): return bearer["access_token"] def refresh(self, device: dict, refresh_token: str, access_token: str) -> dict: - # https://gitlab.com/keatontaylor/alexapy/-/commit/540b6333d973177bbc98e6ef39b00134f80ef0bb - - cookies = { - 'at-main': access_token, - } - headers = { - 'User-Agent': 'AmazonWebView/Amazon Alexa/2.2.223830.0/iOS/11.4.1/iPhone', - 'Accept-Language': 'en-US', - 'Accept-Charset': 'utf-8', - 'Connection': 'keep-alive', - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': '*/*' - } - data2 = { - **device, - 'domain': '.' + self.endpoints["token"].split("/")[-3], - 'source_token': refresh_token, - 'requested_token_type': 'auth_cookies', - 'source_token_type': 'refresh_token', - } - - # using the refresh token get the cookies needed for making calls to alexa.amazon.com - response = requests.post(url=self.endpoints["token"], headers=headers, cookies=cookies, data=data2) + # using the refresh token get the cookies needed for making calls to *.amazon.com + response = requests.post( + url=self.endpoints["token"], + headers={ + 'User-Agent': 'AmazonWebView/Amazon Alexa/2.2.223830.0/iOS/11.4.1/iPhone', # https://gitlab.com/keatontaylor/alexapy/-/commit/540b6333d973177bbc98e6ef39b00134f80ef0bb + 'Accept-Language': 'en-US', + 'Accept-Charset': 'utf-8', + 'Connection': 'keep-alive', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': '*/*' + }, + cookies={ + 'at-main': access_token, + }, + data={ + **device, + 'domain': '.' + self.endpoints["token"].split("/")[-3], + 'source_token': str(refresh_token), + 'requested_token_type': 'auth_cookies', + 'source_token_type': 'refresh_token', + } + ) + response_json = response.json() cookies = {} + self.log.debug(response_json) if response.status_code == 200: # Extract the cookies from the response - raw_cookies = response.json()['response']['tokens']['cookies']['.amazon.com'] + raw_cookies = response_json['response']['tokens']['cookies']['.amazon.com'] for cookie in raw_cookies: cookies[cookie['Name']] = cookie['Value'] else: - error = response.json()['response']["error"] + error = response_json['response']["error"] self.cache_path.unlink(missing_ok=True) raise self.log.exit(f"Error when refreshing cookies: {error['message']} [{error['code']}]") - - # Create a new cookies object to be used with requsts. - - headers = { - 'Content-Type': 'application/json; charset=utf-8', - 'Accept-Encoding': 'gzip, deflate, br', - 'Connection': 'keep-alive', - 'Accept': 'application/json; charset=utf-8', - 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36", - 'Accept-Language': 'en-US,en-US;q=1.0', - 'x-amzn-identity-auth-domain': self.endpoints["token"].split("/")[-3], - 'x-amzn-requestid': str(uuid4()).replace('-', '') - } - json_data = { - **device, - 'requested_token_type': 'access_token', - 'source_token_type': 'refresh_token', - 'source_token': str(refresh_token), - } # https://github.com/Sandmann79/xbmc/blob/dab17d913ee877d96115e6f799623bca158f3f24/plugin.video.amazon-test/resources/lib/login.py#L593 - - # Add cookies to session - #if cookies != {}: - # for k,v in cookies.iteritems(): - # if not isinstance(v, str): - # v = str(v) - # self.session.cookies.set(k,v) - # make the call and print the response. - - response = requests.post(url=self.endpoints["token"], headers=headers, json=json_data, cookies=cookies) + response = requests.post( + url=self.endpoints["token"], + headers={ + 'Content-Type': 'application/json; charset=utf-8', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive', + 'Accept': 'application/json; charset=utf-8', + 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36", + 'Accept-Language': 'en-US,en-US;q=1.0', + 'x-amzn-identity-auth-domain': self.endpoints["token"].split("/")[-3], + 'x-amzn-requestid': str(uuid4()).replace('-', '') + }, + json={ + **device, + 'requested_token_type': 'access_token', + 'source_token_type': 'refresh_token', + 'source_token': str(refresh_token), + }, # https://github.com/Sandmann79/xbmc/blob/dab17d913ee877d96115e6f799623bca158f3f24/plugin.video.amazon-test/resources/lib/login.py#L593 + cookies=cookies + ) response_json = response.json() if response.status_code != 200 or "error" in response_json: self.cache_path.unlink(missing_ok=True) # Remove the cached device as its tokens have expired - raise self.log.exit( - f"Failed to refresh device token -> {response_json['error_description']} [{response_json['error']}]" - ) + raise self.log.exit(f"Failed to refresh device token -> {response_json['error_description']} [{response_json['error']}]") self.log.debug(response_json) if response_json["token_type"] != "bearer": raise self.log.exit("Unexpected returned refreshed token type")