+ _DISCO_API_PARAMS = {
+ 'disco_host': 'us1-prod-direct.animalplanet.com',
+ 'realm': 'go',
+ 'country': 'us',
+ }
+
+
+class TLCIE(DiscoveryPlusBaseIE):
+ _VALID_URL = r'https?://(?:go\.)?tlc\.com/video' + DPlayBaseIE._PATH_REGEX
+ _TESTS = [{
+ 'url': 'https://go.tlc.com/video/my-600-lb-life-tlc/melissas-story-part-1',
+ 'info_dict': {
+ 'id': '2206540',
+ 'display_id': 'my-600-lb-life-tlc/melissas-story-part-1',
+ 'ext': 'mp4',
+ 'title': 'Melissas Story (Part 1)',
+ 'description': 'At 650 lbs, Melissa is ready to begin her seven-year weight loss journey.',
+ 'season_number': 1,
+ 'episode_number': 1,
+ },
+ 'skip': 'Available for Premium users',
+ }, {
+ 'url': 'https://go.tlc.com/video/my-600-lb-life-tlc/melissas-story-part-1',
+ 'only_matching': True,
+ }]
+
+ _PRODUCT = 'tlc'
+ _DISCO_API_PARAMS = {
+ 'disco_host': 'us1-prod-direct.tlc.com',
+ 'realm': 'go',
+ 'country': 'us',
+ }
+
+
+class DiscoveryPlusIE(DiscoveryPlusBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?discoveryplus\.com/(?!it/)(?:\w{2}/)?video' + DPlayBaseIE._PATH_REGEX
+ _TESTS = [{
+ 'url': 'https://www.discoveryplus.com/video/property-brothers-forever-home/food-and-family',
+ 'info_dict': {
+ 'id': '1140794',
+ 'display_id': 'property-brothers-forever-home/food-and-family',
+ 'ext': 'mp4',
+ 'title': 'Food and Family',
+ 'description': 'The brothers help a Richmond family expand their single-level home.',
+ 'duration': 2583.113,
+ 'timestamp': 1609304400,
+ 'upload_date': '20201230',
+ 'creator': 'HGTV',
+ 'series': 'Property Brothers: Forever Home',
+ 'season_number': 1,
+ 'episode_number': 1,
+ },
+ 'skip': 'Available for Premium users',
+ }, {
+ 'url': 'https://discoveryplus.com/ca/video/bering-sea-gold-discovery-ca/goldslingers',
+ 'only_matching': True,
+ }]
+
+ _PRODUCT = 'dplus_us'
+ _DISCO_API_PARAMS = {
+ 'disco_host': 'us1-prod-direct.discoveryplus.com',
+ 'realm': 'go',
+ 'country': 'us',
+ }
+
+
+class DiscoveryPlusIndiaIE(DiscoveryPlusBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?discoveryplus\.in/videos?' + DPlayBaseIE._PATH_REGEX
+ _TESTS = [{
+ 'url': 'https://www.discoveryplus.in/videos/how-do-they-do-it/fugu-and-more?seasonId=8&type=EPISODE',
+ 'info_dict': {
+ 'id': '27104',
+ 'ext': 'mp4',
+ 'display_id': 'how-do-they-do-it/fugu-and-more',
+ 'title': 'Fugu and More',
+ 'description': 'The Japanese catch, prepare and eat the deadliest fish on the planet.',
+ 'duration': 1319.32,
+ 'timestamp': 1582309800,
+ 'upload_date': '20200221',
+ 'series': 'How Do They Do It?',
+ 'season_number': 8,
+ 'episode_number': 2,
+ 'creator': 'Discovery Channel',
+ 'thumbnail': r're:https://.+\.jpeg',
+ 'episode': 'Episode 2',
+ 'season': 'Season 8',
+ 'tags': [],
+ },
+ 'params': {
+ 'skip_download': True,
+ }
+ }]
+
+ _PRODUCT = 'dplus-india'
+ _DISCO_API_PARAMS = {
+ 'disco_host': 'ap2-prod-direct.discoveryplus.in',
+ 'realm': 'dplusindia',
+ 'country': 'in',
+ 'domain': 'https://www.discoveryplus.in/',
+ }
+
+ def _update_disco_api_headers(self, headers, disco_base, display_id, realm):
+ headers.update({
+ 'x-disco-params': 'realm=%s' % realm,
+ 'x-disco-client': f'WEB:UNKNOWN:{self._PRODUCT}:17.0.0',
+ 'Authorization': self._get_auth(disco_base, display_id, realm),
+ })
+
+
+class DiscoveryNetworksDeIE(DPlayBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?(?P<domain>(?:tlc|dmax)\.de|dplay\.co\.uk)/(?:programme|show|sendungen)/(?P<programme>[^/]+)/(?:video/)?(?P<alternate_id>[^/]+)'
+
+ _TESTS = [{
+ 'url': 'https://www.tlc.de/programme/breaking-amish/video/die-welt-da-drauen/DCB331270001100',
+ 'info_dict': {
+ 'id': '78867',
+ 'ext': 'mp4',
+ 'title': 'Die Welt da draußen',
+ 'description': 'md5:61033c12b73286e409d99a41742ef608',
+ 'timestamp': 1554069600,
+ 'upload_date': '20190331',
+ 'creator': 'TLC',
+ 'season': 'Season 1',
+ 'series': 'Breaking Amish',
+ 'episode_number': 1,
+ 'tags': ['new york', 'großstadt', 'amische', 'landleben', 'modern', 'infos', 'tradition', 'herausforderung'],
+ 'display_id': 'breaking-amish/die-welt-da-drauen',
+ 'episode': 'Episode 1',
+ 'duration': 2625.024,
+ 'season_number': 1,
+ 'thumbnail': r're:https://.+\.jpg',
+ },
+ 'params': {
+ 'skip_download': True,
+ },
+ }, {
+ 'url': 'https://www.dmax.de/programme/dmax-highlights/video/tuning-star-sidney-hoffmann-exklusiv-bei-dmax/191023082312316',
+ 'only_matching': True,
+ }, {
+ 'url': 'https://www.dplay.co.uk/show/ghost-adventures/video/hotel-leger-103620/EHD_280313B',
+ 'only_matching': True,
+ }, {
+ 'url': 'https://tlc.de/sendungen/breaking-amish/die-welt-da-drauen/',
+ 'only_matching': True,
+ }]
+
+ def _real_extract(self, url):
+ domain, programme, alternate_id = self._match_valid_url(url).groups()
+ country = 'GB' if domain == 'dplay.co.uk' else 'DE'
+ realm = 'questuk' if country == 'GB' else domain.replace('.', '')
+ return self._get_disco_api_info(
+ url, '%s/%s' % (programme, alternate_id),
+ 'sonic-eu1-prod.disco-api.com', realm, country)
+
+
+class DiscoveryPlusShowBaseIE(DPlayBaseIE):
+
+ def _entries(self, show_name):
+ headers = {
+ 'x-disco-client': self._X_CLIENT,
+ 'x-disco-params': f'realm={self._REALM}',
+ 'referer': self._DOMAIN,
+ 'Authentication': self._get_auth(self._BASE_API, None, self._REALM),
+ }
+ show_json = self._download_json(
+ f'{self._BASE_API}cms/routes/{self._SHOW_STR}/{show_name}?include=default',
+ video_id=show_name, headers=headers)['included'][self._INDEX]['attributes']['component']
+ show_id = show_json['mandatoryParams'].split('=')[-1]
+ season_url = self._BASE_API + 'content/videos?sort=episodeNumber&filter[seasonNumber]={}&filter[show.id]={}&page[size]=100&page[number]={}'
+ for season in show_json['filters'][0]['options']:
+ season_id = season['id']
+ total_pages, page_num = 1, 0
+ while page_num < total_pages:
+ season_json = self._download_json(
+ season_url.format(season_id, show_id, str(page_num + 1)), show_name, headers=headers,
+ note='Downloading season %s JSON metadata%s' % (season_id, ' page %d' % page_num if page_num else ''))
+ if page_num == 0:
+ total_pages = try_get(season_json, lambda x: x['meta']['totalPages'], int) or 1
+ episodes_json = season_json['data']
+ for episode in episodes_json:
+ video_path = episode['attributes']['path']
+ yield self.url_result(
+ '%svideos/%s' % (self._DOMAIN, video_path),
+ ie=self._VIDEO_IE.ie_key(), video_id=episode.get('id') or video_path)
+ page_num += 1
+
+ def _real_extract(self, url):
+ show_name = self._match_valid_url(url).group('show_name')
+ return self.playlist_result(self._entries(show_name), playlist_id=show_name)
+
+
+class DiscoveryPlusItalyIE(DiscoveryPlusBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?discoveryplus\.com/it/video' + DPlayBaseIE._PATH_REGEX
+ _TESTS = [{
+ 'url': 'https://www.discoveryplus.com/it/video/i-signori-della-neve/stagione-2-episodio-1-i-preparativi',
+ 'only_matching': True,
+ }]
+
+ _PRODUCT = 'dplus_us'
+ _DISCO_API_PARAMS = {
+ 'disco_host': 'eu1-prod-direct.discoveryplus.com',
+ 'realm': 'dplay',
+ 'country': 'it',
+ }
+
+
+class DiscoveryPlusItalyShowIE(DiscoveryPlusShowBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?discoveryplus\.it/programmi/(?P<show_name>[^/]+)/?(?:[?#]|$)'
+ _TESTS = [{
+ 'url': 'https://www.discoveryplus.it/programmi/deal-with-it-stai-al-gioco',
+ 'playlist_mincount': 168,
+ 'info_dict': {
+ 'id': 'deal-with-it-stai-al-gioco',
+ },
+ }]
+
+ _BASE_API = 'https://disco-api.discoveryplus.it/'
+ _DOMAIN = 'https://www.discoveryplus.it/'
+ _X_CLIENT = 'WEB:UNKNOWN:dplay-client:2.6.0'
+ _REALM = 'dplayit'
+ _SHOW_STR = 'programmi'
+ _INDEX = 1
+ _VIDEO_IE = DPlayIE
+
+
+class DiscoveryPlusIndiaShowIE(DiscoveryPlusShowBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?discoveryplus\.in/show/(?P<show_name>[^/]+)/?(?:[?#]|$)'
+ _TESTS = [{
+ 'url': 'https://www.discoveryplus.in/show/how-do-they-do-it',
+ 'playlist_mincount': 140,
+ 'info_dict': {
+ 'id': 'how-do-they-do-it',
+ },
+ }]
+
+ _BASE_API = 'https://ap2-prod-direct.discoveryplus.in/'
+ _DOMAIN = 'https://www.discoveryplus.in/'
+ _X_CLIENT = 'WEB:UNKNOWN:dplus-india:prod'
+ _REALM = 'dplusindia'
+ _SHOW_STR = 'show'
+ _INDEX = 4
+ _VIDEO_IE = DiscoveryPlusIndiaIE