[tvnow] Add support for shows
authorAndroKev <AndroKev@users.noreply.github.com>
Mon, 12 Mar 2018 07:57:41 +0000 (08:57 +0100)
committerSergey M․ <dstftw@gmail.com>
Mon, 2 Apr 2018 17:06:47 +0000 (00:06 +0700)
youtube_dl/extractor/extractors.py
youtube_dl/extractor/tvnow.py

index de48a37ad910fa9c4466aa9f78a85f634192593d..e3a67cc5bd0b3ffa6888e0e08eb851412898db1f 100644 (file)
@@ -1136,6 +1136,7 @@ from .tvnoe import TVNoeIE
 from .tvnow import (
     TVNowIE,
     TVNowListIE,
+    TVNowListChannelIE,
 )
 from .tvp import (
     TVPEmbedIE,
index 1bf47244440809f154d01b5664f1ffa085e4fb29..8e0ac6be59d5ec0b81d092d2b37aa5bdee51ddf7 100644 (file)
@@ -19,7 +19,7 @@ class TVNowBaseIE(InfoExtractor):
         'id', 'title', 'free', 'geoblocked', 'articleLong', 'articleShort',
         'broadcastStartDate', 'isDrm', 'duration', 'season', 'episode',
         'manifest.dashclear', 'format.title', 'format.defaultImage169Format',
-        'format.defaultImage169Logo')
+        'format.defaultImage169Logo', 'replaceMovieInformation')
 
     def _call_api(self, path, video_id, query):
         return self._download_json(
@@ -58,7 +58,7 @@ class TVNowBaseIE(InfoExtractor):
         duration = parse_duration(info.get('duration'))
 
         f = info.get('format', {})
-        thumbnail = f.get('defaultImage169Format') or f.get('defaultImage169Logo')
+        thumbnail = ('https://aistvnow-a.akamaihd.net/tvnow/movie/%s' % info.get('replaceMovieInformation')) or f.get('defaultImage169Format') or f.get('defaultImage169Logo')
 
         return {
             'id': video_id,
@@ -133,7 +133,27 @@ class TVNowIE(TVNowBaseIE):
         return self._extract_video(info, display_id)
 
 
-class TVNowListIE(TVNowBaseIE):
+class TVNowListBaseIE(TVNowBaseIE):
+    def _extend_query(self, show, season, video=None):
+        fields = []
+        fields.extend(show)
+        fields.extend('formatTabs.%s' % field for field in season)
+        if video:
+            fields.extend(
+                'formatTabs.formatTabPages.container.movies.%s' % field
+                for field in video)
+
+        return fields
+
+    def _tvnow_list_info(self, list_id, show_id, fields):
+        return self._call_api(
+            'formats/seo', list_id, query={
+                'fields': ','.join(fields),
+                'name': show_id + '.php'
+            })
+
+
+class TVNowListIE(TVNowListBaseIE):
     _VALID_URL = r'(?P<base_url>https?://(?:www\.)?tvnow\.(?:de|at|ch)/(?:rtl(?:2|plus)?|nitro|superrtl|ntv|vox)/(?P<show_id>[^/]+)/)list/(?P<id>[^?/#&]+)$'
 
     _SHOW_FIELDS = ('title', )
@@ -152,18 +172,7 @@ class TVNowListIE(TVNowBaseIE):
     def _real_extract(self, url):
         base_url, show_id, season_id = re.match(self._VALID_URL, url).groups()
 
-        fields = []
-        fields.extend(self._SHOW_FIELDS)
-        fields.extend('formatTabs.%s' % field for field in self._SEASON_FIELDS)
-        fields.extend(
-            'formatTabs.formatTabPages.container.movies.%s' % field
-            for field in self._VIDEO_FIELDS)
-
-        list_info = self._call_api(
-            'formats/seo', season_id, query={
-                'fields': ','.join(fields),
-                'name': show_id + '.php'
-            })
+        list_info = self._tvnow_list_info(season_id, show_id, self._extend_query(self._SHOW_FIELDS, self._SEASON_FIELDS, self._VIDEO_FIELDS))
 
         season = next(
             season for season in list_info['formatTabs']['items']
@@ -177,8 +186,40 @@ class TVNowListIE(TVNowBaseIE):
                 seo_url = info.get('seoUrl')
                 if not seo_url:
                     continue
+
                 entries.append(self.url_result(
-                    base_url + seo_url + '/player', 'TVNow', info.get('id')))
+                    base_url + seo_url + '/player', 'TVNow', str(info.get('id', seo_url))))
 
         return self.playlist_result(
             entries, compat_str(season.get('id') or season_id), title)
+
+
+class TVNowListChannelIE(TVNowListBaseIE):
+    _VALID_URL = r'(?P<base_url>https?://(?:www\.)?tvnow\.(?:de|at|ch)/(?:rtl(?:2|plus)?|nitro|superrtl|ntv|vox)/(?P<show_id>[^/]+))'
+
+    _SHOW_FIELDS = ('id', 'title', )
+    _SEASON_FIELDS = ('id', 'headline', 'seoheadline', )
+
+    _TESTS = [{
+        'url': 'https://www.tvnow.at/vox/ab-ins-beet',
+        'only_matching': 'True',
+    }]
+
+    @classmethod
+    def suitable(cls, url):
+        return False if TVNowIE.suitable(url) or TVNowListIE.suitable(url) else super(TVNowListChannelIE, cls).suitable(url)
+
+    def _real_extract(self, url):
+        base_url, show_id = re.match(self._VALID_URL, url).groups()
+
+        list_info = self._tvnow_list_info(show_id, show_id, self._extend_query(self._SHOW_FIELDS, self._SEASON_FIELDS))
+
+        entries = []
+        for season_info in list_info['formatTabs']['items']:
+            season_url = season_info.get('seoheadline')
+            if not season_url:
+                continue
+            entries.append(self.url_result(
+                base_url + "/list/" + season_url, 'TVNowList', compat_str(season_info.get('id')), season_info.get('headline')))
+
+        return self.playlist_result(entries)