| 
					
				 | 
			
			
				@@ -4,7 +4,12 @@ from __future__ import unicode_literals 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import re 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .theplatform import ThePlatformFeedIE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from ..utils import int_or_none 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from ..utils import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    dict_get, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ExtractorError, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    float_or_none, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int_or_none, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class CorusIE(ThePlatformFeedIE): 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -12,24 +17,49 @@ class CorusIE(ThePlatformFeedIE): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     https?:// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         (?:www\.)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         (?P<domain> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            (?:globaltv|etcanada)\.com| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            (?:hgtv|foodnetwork|slice|history|showcase|bigbrothercanada)\.ca 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            (?: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                globaltv| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                etcanada| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                seriesplus| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                wnetwork| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                ytv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            )\.com| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            (?: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                hgtv| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                foodnetwork| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                slice| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                history| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                showcase| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                bigbrothercanada| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                abcspark| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                disney(?:channel|lachaine) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            )\.ca 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        /(?:[^/]+/)* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        (?: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            video\.html\?.*?\bv=| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            videos?/(?:[^/]+/)*(?:[a-z0-9-]+-)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        (?P<id> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            [\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}| 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            (?:[A-Z]{4})?\d{12,20} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        /(?:video/(?:[^/]+/)?|(?:[^/]+/)+(?:videos/[a-z0-9-]+-|video\.html\?.*?\bv=)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        (?P<id>\d+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     ''' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     _TESTS = [{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'url': 'http://www.hgtv.ca/shows/bryan-inc/videos/movie-night-popcorn-with-bryan-870923331648/', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'md5': '05dcbca777bf1e58c2acbb57168ad3a6', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'info_dict': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'id': '870923331648', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'ext': 'mp4', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'title': 'Movie Night Popcorn with Bryan', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'description': 'Bryan whips up homemade popcorn, the old fashion way for Jojo and Lincoln.', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'uploader': 'SHWM-NEW', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'upload_date': '20170206', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             'timestamp': 1486392197, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'params': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'format': 'bestvideo', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'skip_download': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'expected_warnings': ['Failed to parse JSON'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'url': 'http://www.foodnetwork.ca/shows/chopped/video/episode/chocolate-obsession/video.html?v=872683587753', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'only_matching': True, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -48,58 +78,83 @@ class CorusIE(ThePlatformFeedIE): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'url': 'https://www.bigbrothercanada.ca/video/big-brother-canada-704/1457812035894/', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'only_matching': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'url': 'https://www.seriesplus.com/emissions/dre-mary-mort-sur-ordonnance/videos/deux-coeurs-battant/SERP0055626330000200/', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'only_matching': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'url': 'https://www.disneychannel.ca/shows/gabby-duran-the-unsittables/video/crybaby-duran-clip/2f557eec-0588-11ea-ae2b-e2c6776b770e/', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'only_matching': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    _TP_FEEDS = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'globaltv': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'ChQqrem0lNUp', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2269680845, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'etcanada': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'ChQqrem0lNUp', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2269680845, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'hgtv': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'L0BMHXi2no43', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2414428465, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'foodnetwork': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'ukK8o58zbRmJ', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2414429569, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'slice': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': '5tUJLgV2YNJ5', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2414427935, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'history': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'tQFx_TyyEq4J', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2369613659, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'showcase': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': '9H6qyshBZU3E', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2414426607, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        'bigbrothercanada': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'feed_id': 'ChQqrem0lNUp', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'account_id': 2269680845, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    _GEO_BYPASS = False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    _SITE_MAP = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'globaltv': 'series', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'etcanada': 'series', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'foodnetwork': 'food', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'bigbrothercanada': 'series', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'disneychannel': 'disneyen', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'disneylachaine': 'disneyfr', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def _real_extract(self, url): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         domain, video_id = re.match(self._VALID_URL, url).groups() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        feed_info = self._TP_FEEDS[domain.split('.')[0]] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return self._extract_feed_info('dtjsEC', feed_info['feed_id'], 'byId=' + video_id, video_id, lambda e: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'episode_number': int_or_none(e.get('pl1$episode')), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'season_number': int_or_none(e.get('pl1$season')), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'series': e.get('pl1$show'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'HLS': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                'manifest': 'm3u', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'DesktopHLS Default': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                'manifest': 'm3u', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            'MP4 MBR': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                'manifest': 'm3u', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, feed_info['account_id']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        site = domain.split('.')[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        path = self._SITE_MAP.get(site, site) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if path != 'series': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            path = 'migration/' + path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        video = self._download_json( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'https://globalcontent.corusappservices.com/templates/%s/playlist/' % path, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            video_id, query={'byId': video_id}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            headers={'Accept': 'application/json'})[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        title = video['title'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        formats = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for source in video.get('sources', []): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            smil_url = source.get('file') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not smil_url: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            source_type = source.get('type') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            note = 'Downloading%s smil file' % (' ' + source_type if source_type else '') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            resp = self._download_webpage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                smil_url, video_id, note, fatal=False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                headers=self.geo_verification_headers()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not resp: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            error = self._parse_json(resp, video_id, fatal=False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if error.get('exception') == 'GeoLocationBlocked': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self.raise_geo_restricted(countries=['CA']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise ExtractorError(error['description']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            smil = self._parse_xml(resp, video_id, fatal=False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if smil is None: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            namespace = self._parse_smil_namespace(smil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            formats.extend(self._parse_smil_formats( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                smil, smil_url, video_id, namespace)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if not formats and video.get('drm'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise ExtractorError('This video is DRM protected.', expected=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self._sort_formats(formats) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        subtitles = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for track in video.get('tracks', []): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            track_url = track.get('file') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not track_url: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lang = 'fr' if site in ('disneylachaine', 'seriesplus') else 'en' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            subtitles.setdefault(lang, []).append({'url': track_url}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        metadata = video.get('metadata') or {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        get_number = lambda x: int_or_none(video.get('pl1$' + x) or metadata.get(x + 'Number')) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'id': video_id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'title': title, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'formats': formats, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'thumbnail': dict_get(video, ('defaultThumbnailUrl', 'thumbnail', 'image')), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'description': video.get('description'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'timestamp': int_or_none(video.get('availableDate'), 1000), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'subtitles': subtitles, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'duration': float_or_none(metadata.get('duration')), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'series': dict_get(video, ('show', 'pl1$show')), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'season_number': get_number('season'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'episode_number': get_number('episode'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 |