[ivi] fallback to old extraction method for unknown error codes
[youtube-dl] / youtube_dl / extractor / ivi.py
index efdc3cc984fefe093fa18635c7f334ebbfd8dd55..0db023622dc0ce7287eb49682ee67c60835451c9 100644 (file)
@@ -80,50 +80,70 @@ class IviIE(InfoExtractor):
         'MP4-SHQ', 'MP4-HD720', 'MP4-HD1080')
 
     def _real_extract(self, url):
-        try:
-            from Crypto.Cipher import Blowfish
-            from Crypto.Hash import CMAC
-        except ImportError:
-            raise ExtractorError('pycrypto not found. Please install it.', expected=True)
-
         video_id = self._match_id(url)
 
-        timestamp = self._download_json(
-            self._LIGHT_URL, video_id,
-            'Downloading timestamp JSON', data=json.dumps({
-                'method': 'da.timestamp.get',
-                'params': []
-            }).encode())['result']
-
         data = json.dumps({
             'method': 'da.content.get',
             'params': [
                 video_id, {
-                    'site': 's353',
+                    'site': 's%d',
                     'referrer': 'http://www.ivi.ru/watch/%s' % video_id,
                     'contentid': video_id
                 }
             ]
         }).encode()
 
-        video_json = self._download_json(
-            self._LIGHT_URL, video_id,
-            'Downloading video JSON', data=data, query={
-                'ts': timestamp,
-                'sign': CMAC.new(self._LIGHT_KEY, timestamp.encode() + data, Blowfish).hexdigest(),
-            })
+        for site in (353, 183):
+            content_data = data % site
+            if site == 353:
+                try:
+                    from Cryptodome.Cipher import Blowfish
+                    from Cryptodome.Hash import CMAC
+                    pycryptodomex_found = True
+                except ImportError:
+                    pycryptodomex_found = False
+                    continue
 
-        error = video_json.get('error')
-        if error:
-            origin = error['origin']
-            if origin == 'NotAllowedForLocation':
-                self.raise_geo_restricted(
-                    msg=error['message'], countries=self._GEO_COUNTRIES)
-            elif origin == 'NoRedisValidData':
-                raise ExtractorError('Video %s does not exist' % video_id, expected=True)
-            raise ExtractorError(
-                'Unable to download video %s: %s' % (video_id, error['message']),
-                expected=True)
+                timestamp = (self._download_json(
+                    self._LIGHT_URL, video_id,
+                    'Downloading timestamp JSON', data=json.dumps({
+                        'method': 'da.timestamp.get',
+                        'params': []
+                    }).encode(), fatal=False) or {}).get('result')
+                if not timestamp:
+                    continue
+
+                query = {
+                    'ts': timestamp,
+                    'sign': CMAC.new(self._LIGHT_KEY, timestamp.encode() + content_data, Blowfish).hexdigest(),
+                }
+            else:
+                query = {}
+
+            video_json = self._download_json(
+                self._LIGHT_URL, video_id,
+                'Downloading video JSON', data=content_data, query=query)
+
+            error = video_json.get('error')
+            if error:
+                origin = error.get('origin')
+                message = error.get('message') or error.get('user_message')
+                extractor_msg = 'Unable to download video %s'
+                if origin == 'NotAllowedForLocation':
+                    self.raise_geo_restricted(message, self._GEO_COUNTRIES)
+                elif origin == 'NoRedisValidData':
+                    extractor_msg = 'Video %s does not exist'
+                elif site == 353:
+                    continue
+                elif not pycryptodomex_found:
+                    raise ExtractorError(
+                        'pycryptodome not found. Please install it.',
+                        expected=True)
+                elif message:
+                    extractor_msg += ': ' + message
+                raise ExtractorError(extractor_msg % video_id, expected=True)
+            else:
+                break
 
         result = video_json['result']
         title = result['title']