From 5290850dc6f2ef72d829a7990aa21838298a2f93 Mon Sep 17 00:00:00 2001 From: chu23465 <130033130+chu23465@users.noreply.github.com> Date: Fri, 11 Apr 2025 06:26:41 +0530 Subject: [PATCH] Fix vbitrate == "min" --- vinetrimmer/commands/dl.py | 13 +- .../hisense_smarttv_he55a7000euwts_sl3000.prd | Bin 2108 -> 2108 bytes vinetrimmer/key_store.db | Bin 331776 -> 331776 bytes vinetrimmer/services/amazon.py | 111 ++++++++---------- 4 files changed, 57 insertions(+), 67 deletions(-) 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 0c1b3a23b23438cb323a3410956dfe2cb525426c..5140dad15321a2c89ea496070b577348d730ba52 100644 GIT binary patch delta 516 zcmdlZut#7*O8t*D>9(KVI0fB37*rte$YG${*{F}_0_r0n9c^=diV!Z delta 516 zcmdlZut#7*O1*bPBC$2H3W$=7bII)JIh*cKQLk0ial4B&ps_4 zDarSA%d|;s`X0*-e>uebDR(tjTCqQFRB zzEx@9s<87%mfV%Knk9i6Dea%uEnc%p@9N(t6D;}q71MGmdekFo53@X)J|knl(IWZh zLP|oHCaW+S1V}CMRo%W+%f&mXC+@#{S`7mO_YMXKV2b#oC+X7ir%+ztyuX*{&Mk4O zxl__F8hKAO$v&xee({|DKrrF#OZ|=a4i%am%Gi>=FyYbUC5#UBl)4OPKO-13GJ%~! zVo*wAgeBBKrpX2@E)MJePb|E6dW-$k2a{h`G8c#J5vts!_(Jc`&MvHBhx$#BwmTh9TVFdsNj^PIY diff --git a/vinetrimmer/key_store.db b/vinetrimmer/key_store.db index dec5608388c755c942bea66ed09f8bcea7017415..b46f4fc2bed93f5ea403acac7c0029b41697cad1 100644 GIT binary patch delta 1763 zcmbtUO>1367(R37CO5swO+u_zNzzKIP?W@T=HtvvH8vk@BB8gT3qOOBnKNfJMU6p8 zi;LXby2zpujaiJSVC_Z=f{95un=T3>wBRBX@@-0>E`)3%ick=A?n&_nB(pg0FmvX8 zp7)*Snex?x<*NrjZ3dH5Ej?gzcIetOk38fxG3>1<%jbK3kiq z?mwL^7QysLQ)gAHLu;|k^Pn&5W`}J570^HTcgF?r!r@-`Q-(yG=zws{14NWIJPHLS zK0}I=z#xi@QA|h_7@}iLA|oOnbB&ntg;cSI%X14SX(QP9XnP>p9srLuLhfC%xgqdg z{!*pXbWDHW(U;sB0w<1C_j}AMc{X1L$1}B47L~!NjOQg6%ivDFLb1=Dy#jj9q~uUc zjN~eyVax+fj1VY@NfZSLbA>q#U8@Lo`-b|yVm@aAQ5;DhNsMTq;Yymu{>!qRN$bbp zw_^timmU5%@WyS;B2-Zu6LwYj_uADt&~0yR!ajR%7Mw{2@4`YRdFv+lqM^Fkqh8sw zO*7z$47g{*8PHvm-KpUAW|NCEU=(x_8DWaG(lR2Uh$Lc~V?;FK+W4Y!S%$hLL>LtY zX&y6$49ARzP8Jfu)#Rxk!5^SPWyv0y2R*wpGY>wQe*a{5!WICkofzH%$?#U@%Tf&m z=e&le!MP+q1W$v$w0vzsEg6nN*I^PyMCgcf-?blyOcBbFP=Sz`Tmj6p}b}#*Bs00!bPnmr@AIWE^TtLn>k? zSh$|t-UMGeVQjH;_E$L2ag$L!Q3D2+`FR(ZwZ$bPRuzVqR`LAxGnfAfRkb{;BX zOhDUAprSVJw9=-0Cfi7CB6pV@YedH;UUR^u;>doh+XM2eX~~#KTH4P;xCi7{Qe-EN z2gVEc<~;jD6F_|vFQ?h|`*J-<_R=o3eZJAQ{7=R)dofM6Uqjf^!vG~mY4+~=e-LT& AaR2}S delta 606 zcmXAkQAkr^6vw~wec$!2dpEbtT%uNDMG&MeZM8D5GdCRQ0;8vpJGHQg%BQ4iRgpXi6?%MK35L=xdpF)RA(&oox(-l@Ys*qkH#fRq`F1WWa$zWUF)vv_)r70q zYjIyJ;T8)f_;%T1#7l;V9zvT1`_W^;N$TkngBC1l@#jq;8l?Cx2Zjn=0f|8Iua_I5 z>JEIb*(!aH5R33NKFNFF8?QiH7WUx5EcnG>76t&f&q6@dF2PTTN1B4Tk%11JT803= zc`0|iE8x+^g*kZOWKT#vDp|JIrl!=3jzzTw4`KvP-saTQWc}3AU3kFV%flZux1!bVvH}Yi9MkN{jgD)}=%qI$B^C+}q%M7&e yVkZgUr;p&rg&7Dc(ncP1>Rd({7H4LmgvuCfBFx-MHL3>GreZlRsvG&&&;I}{wY&BJ 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")