diff --git a/yt_dlp/extractor/extractors.py b/yt_dlp/extractor/extractors.py index 424406177..7510e698a 100644 --- a/yt_dlp/extractor/extractors.py +++ b/yt_dlp/extractor/extractors.py @@ -1340,7 +1340,10 @@ from .trovo import ( from .trunews import TruNewsIE from .trutv import TruTVIE from .tube8 import Tube8IE -from .tubitv import TubiTvIE +from .tubitv import ( + TubiTvIE, + TubiTvShowIE, +) from .tumblr import TumblrIE from .tunein import ( TuneInClipIE, diff --git a/yt_dlp/extractor/tubitv.py b/yt_dlp/extractor/tubitv.py index ebfb05c63..6bc3234c6 100644 --- a/yt_dlp/extractor/tubitv.py +++ b/yt_dlp/extractor/tubitv.py @@ -7,13 +7,19 @@ from .common import InfoExtractor from ..utils import ( ExtractorError, int_or_none, + js_to_json, sanitized_Request, urlencode_postdata, ) class TubiTvIE(InfoExtractor): - _VALID_URL = r'https?://(?:www\.)?tubitv\.com/(?:video|movies|tv-shows)/(?P[0-9]+)' + _VALID_URL = r'''(?x) + (?: + tubitv:| + https?://(?:www\.)?tubitv\.com/(?:video|movies|tv-shows)/ + ) + (?P[0-9]+)''' _LOGIN_URL = 'http://tubitv.com/login' _NETRC_MACHINE = 'tubitv' _GEO_COUNTRIES = ['US'] @@ -108,3 +114,28 @@ class TubiTvIE(InfoExtractor): 'uploader_id': video_data.get('publisher_id'), 'release_year': int_or_none(video_data.get('year')), } + + +class TubiTvShowIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?tubitv\.com/series/[0-9]+/(?P[^/?#]+)' + _TESTS = [{ + 'url': 'https://tubitv.com/series/3936/the-joy-of-painting-with-bob-ross?start=true', + 'playlist_mincount': 390, + 'info_dict': { + 'id': 'the-joy-of-painting-with-bob-ross', + } + }] + + def _entries(self, show_url, show_name): + show_webpage = self._download_webpage(show_url, show_name) + show_json = self._parse_json(self._search_regex( + r"window\.__data\s*=\s*({.+?});\s*", + show_webpage, 'data',), show_name, transform_source=js_to_json)['video'] + for episode_id in show_json['fullContentById'].keys(): + yield self.url_result( + 'tubitv:%s' % episode_id, + ie=TubiTvIE.ie_key(), video_id=episode_id) + + def _real_extract(self, url): + show_name = re.match(self._VALID_URL, url).group('show_name') + return self.playlist_result(self._entries(url, show_name), playlist_id=show_name)