diff --git a/services/AMZN/__init__.py b/services/AMZN/__init__.py index cfffcba..6c1cfd4 100644 --- a/services/AMZN/__init__.py +++ b/services/AMZN/__init__.py @@ -13,6 +13,7 @@ from devine.core.credential import Credential from devine.core.tracks import Chapters, Tracks, Subtitle, Chapter from devine.core.search_result import SearchResult from devine.core.manifests import DASH +from pip._internal.utils import urls class AMZN(Service): @@ -35,14 +36,16 @@ class AMZN(Service): @staticmethod @click.command(name="AMZN", short_help="https://amazon.com", help=__doc__) @click.argument("title", type=str) + @click.option("--sd-only", is_flag=True, help="Get only the SD manifests") @click.pass_context def cli(ctx, **kwargs): return AMZN(ctx, **kwargs) - def __init__(self, ctx, title): + def __init__(self, ctx, title, sd_only=False): self.title = title self.cookies = None + self.sd_only = sd_only # Overriding the constructor super().__init__(ctx) @@ -103,59 +106,76 @@ class AMZN(Service): def get_tracks(self, title: Title_T) -> Tracks: tracks = Tracks() + params = { + 'deviceID': 'eff7bd3a-730d-41d2-8ad8-bf4dfa55bee3', + 'deviceTypeID': 'AOAGZA014O5RE', + 'gascEnabled': 'false', + 'marketplaceID': 'ATVPDKIKX0DER', + 'uxLocale': 'en_US', + 'firmware': '1', + 'playerType': 'xp', + 'operatingSystemName': 'Windows' if not self.sd_only else 'Linux', + 'operatingSystemVersion': '10.0', + 'deviceApplicationName': 'Firefox64', + 'asin': title.id, + 'consumptionType': 'Streaming', + 'desiredResources': 'PlaybackUrls,SubtitleUrls', + 'resourceUsage': 'CacheResources', + 'videoMaterialType': 'Feature', + 'displayWidth': '1920', + 'displayHeight': '1080', + 'supportsVariableAspectRatio': 'true', + 'deviceStreamingTechnologyOverride': 'DASH', + 'deviceDrmOverride': 'CENC', + 'deviceBitrateAdaptationsOverride': 'CVBR,CBR', + 'supportsEmbeddedTrickplayForVod': 'false', + 'audioTrackId': 'all', + 'languageFeature': 'MLFv2', + 'liveManifestType': 'patternTemplate,accumulating,live', + 'supportedDRMKeyScheme': 'DUAL_KEY', + 'supportsEmbeddedTrickplay': 'true', + 'daiSupportsEmbeddedTrickplay': 'true', + 'daiLiveManifestType': 'patternTemplate,accumulating,live', + 'ssaiSegmentInfoSupport': 'Base', + 'ssaiStitchType': 'MultiPeriod', + 'gdprEnabled': 'false', + 'subtitleFormat': 'TTMLv2', + 'playbackSettingsFormatVersion': '1.0.0', + 'titleDecorationScheme': 'primary-content', + 'xrayToken': 'XRAY_WEB_2023_V2', + 'xrayPlaybackMode': 'playback', + 'xrayDeviceClass': 'normal', + 'playerAttributes': '{"middlewareName":"Firefox64","middlewareVersion":"130.0","nativeApplicationName":"Firefox64","nativeApplicationVersion":"130.0","supportedAudioCodecs":"AAC","frameRate":"HFR","H264.codecLevel":"4.2","H265.codecLevel":"0.0","AV1.codecLevel":"0.0"}', + } + if not self.sd_only: + response = self.session.get( + url=self.config['endpoints']['playback'], + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0', + }, + params=params + ).json() + hd_urls = [] + for set in response['playbackUrls']['urlSets']: + url = response['playbackUrls']['urlSets'][set]['urls']['manifest']['url'] + hd_urls.append(url) + tracks.add(DASH.from_url(url=hd_urls[random.randint(0, len(hd_urls) - 1)], session=self.session).to_tracks(language='en')) + + sd_urls = [] + params['operatingSystemName'] = 'Linux' + del params['operatingSystemVersion'] response = self.session.get( url=self.config['endpoints']['playback'], headers={ - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0' }, - params={ - 'deviceID': 'eff7bd3a-730d-41d2-8ad8-bf4dfa55bee3', - 'deviceTypeID': 'AOAGZA014O5RE', - 'gascEnabled': 'false', - 'marketplaceID': 'ATVPDKIKX0DER', - 'uxLocale': 'en_US', - 'firmware': '1', - 'playerType': 'xp', - 'operatingSystemName': 'Windows', - 'operatingSystemVersion': '10.0', - 'deviceApplicationName': 'Firefox64', - 'asin': title.id, - 'consumptionType': 'Streaming', - 'desiredResources': 'PlaybackUrls,SubtitleUrls', - 'resourceUsage': 'CacheResources', - 'videoMaterialType': 'Feature', - 'displayWidth': '1920', - 'displayHeight': '1080', - 'supportsVariableAspectRatio': 'true', - 'deviceStreamingTechnologyOverride': 'DASH', - 'deviceDrmOverride': 'CENC', - 'deviceBitrateAdaptationsOverride': 'CVBR,CBR', - 'supportsEmbeddedTrickplayForVod': 'false', - 'audioTrackId': 'all', - 'languageFeature': 'MLFv2', - 'liveManifestType': 'patternTemplate,accumulating,live', - 'supportedDRMKeyScheme': 'DUAL_KEY', - 'supportsEmbeddedTrickplay': 'true', - 'daiSupportsEmbeddedTrickplay': 'true', - 'daiLiveManifestType': 'patternTemplate,accumulating,live', - 'ssaiSegmentInfoSupport': 'Base', - 'ssaiStitchType': 'MultiPeriod', - 'gdprEnabled': 'false', - 'subtitleFormat': 'TTMLv2', - 'playbackSettingsFormatVersion': '1.0.0', - 'titleDecorationScheme': 'primary-content', - 'xrayToken': 'XRAY_WEB_2023_V2', - 'xrayPlaybackMode': 'playback', - 'xrayDeviceClass': 'normal', - 'playerAttributes': '{"middlewareName":"Firefox64","middlewareVersion":"130.0","nativeApplicationName":"Firefox64","nativeApplicationVersion":"130.0","supportedAudioCodecs":"AAC","frameRate":"HFR","H264.codecLevel":"4.2","H265.codecLevel":"0.0","AV1.codecLevel":"0.0"}', - } + params=params ).json() - urls = [] for set in response['playbackUrls']['urlSets']: url = response['playbackUrls']['urlSets'][set]['urls']['manifest']['url'] - urls.append(url) - tracks.add(DASH.from_url(url=urls[random.randint(0, len(urls) - 1)], session=self.session).to_tracks(language='en')) + sd_urls.append(url) + tracks.add(DASH.from_url(url=sd_urls[random.randint(0, len(sd_urls) - 1)], session=self.session).to_tracks(language='en')) return tracks def get_chapters(self, title: Title_T) -> Chapters: @@ -177,7 +197,7 @@ class AMZN(Service): 'uxLocale': 'en_US', 'firmware': '1', 'playerType': 'xp', - 'operatingSystemName': 'Windows', + 'operatingSystemName': 'Windows' if not self.sd_only else 'Linux', 'operatingSystemVersion': '10.0', 'deviceApplicationName': 'Firefox64', 'asin': title.id, @@ -234,7 +254,7 @@ class AMZN(Service): 'uxLocale': 'en_US', 'firmware': '1', 'playerType': 'xp', - 'operatingSystemName': 'Windows', + 'operatingSystemName': 'Windows' if not self.sd_only else 'Linux', 'operatingSystemVersion': '10.0', 'deviceApplicationName': 'Firefox64', 'asin': title.id, @@ -271,6 +291,6 @@ class AMZN(Service): 'widevine2Challenge': f"{base64.b64encode(challenge).decode()}", 'includeHdcpTestKeyInLicense': 'true', } - ).json()['widevine2License']['license'] + ).json() - return response \ No newline at end of file + return response['widevine2License']['license'] \ No newline at end of file