mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-30 22:25:19 +00:00 
			
		
		
		
	| @@ -10,7 +10,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # These bloat the lazy_extractors, so allow them to passthrough silently | # These bloat the lazy_extractors, so allow them to passthrough silently | ||||||
| ALLOWED_CLASSMETHODS = {'get_testcases', 'extract_from_webpage'} | ALLOWED_CLASSMETHODS = {'extract_from_webpage', 'get_testcases', 'get_webpage_testcases'} | ||||||
| _WARNED = False | _WARNED = False | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -14,10 +14,17 @@ from devscripts.utils import get_filename_args, read_file, write_file | |||||||
| 
 | 
 | ||||||
| NO_ATTR = object() | NO_ATTR = object() | ||||||
| STATIC_CLASS_PROPERTIES = [ | STATIC_CLASS_PROPERTIES = [ | ||||||
|     'IE_NAME', 'IE_DESC', 'SEARCH_KEY', '_VALID_URL', '_WORKING', '_ENABLED', '_NETRC_MACHINE', 'age_limit' |     'IE_NAME', '_ENABLED', '_VALID_URL',  # Used for URL matching | ||||||
|  |     '_WORKING', 'IE_DESC', '_NETRC_MACHINE', 'SEARCH_KEY',  # Used for --extractor-descriptions | ||||||
|  |     'age_limit',  # Used for --age-limit (evaluated) | ||||||
|  |     '_RETURN_TYPE',  # Accessed in CLI only with instance (evaluated) | ||||||
| ] | ] | ||||||
| CLASS_METHODS = [ | CLASS_METHODS = [ | ||||||
|     'ie_key', 'working', 'description', 'suitable', '_match_valid_url', '_match_id', 'get_temp_id', 'is_suitable' |     'ie_key', 'suitable', '_match_valid_url',  # Used for URL matching | ||||||
|  |     'working', 'get_temp_id', '_match_id',  # Accessed just before instance creation | ||||||
|  |     'description',  # Used for --extractor-descriptions | ||||||
|  |     'is_suitable',  # Used for --age-limit | ||||||
|  |     'supports_login', 'is_single_video',  # Accessed in CLI only with instance | ||||||
| ] | ] | ||||||
| IE_TEMPLATE = ''' | IE_TEMPLATE = ''' | ||||||
| class {name}({bases}): | class {name}({bases}): | ||||||
|   | |||||||
| @@ -44,5 +44,6 @@ | |||||||
|     "writesubtitles": false, |     "writesubtitles": false, | ||||||
|     "allsubtitles": false, |     "allsubtitles": false, | ||||||
|     "listsubtitles": false, |     "listsubtitles": false, | ||||||
|     "fixup": "never" |     "fixup": "never", | ||||||
|  |     "allow_playlist_files": false | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1381,6 +1381,7 @@ class YoutubeDL: | |||||||
|                 if rejecttitle: |                 if rejecttitle: | ||||||
|                     if re.search(rejecttitle, title, re.IGNORECASE): |                     if re.search(rejecttitle, title, re.IGNORECASE): | ||||||
|                         return '"' + title + '" title matched reject pattern "' + rejecttitle + '"' |                         return '"' + title + '" title matched reject pattern "' + rejecttitle + '"' | ||||||
|  | 
 | ||||||
|             date = info_dict.get('upload_date') |             date = info_dict.get('upload_date') | ||||||
|             if date is not None: |             if date is not None: | ||||||
|                 dateRange = self.params.get('daterange', DateRange()) |                 dateRange = self.params.get('daterange', DateRange()) | ||||||
| @@ -2953,8 +2954,6 @@ class YoutubeDL: | |||||||
|         if 'format' not in info_dict and 'ext' in info_dict: |         if 'format' not in info_dict and 'ext' in info_dict: | ||||||
|             info_dict['format'] = info_dict['ext'] |             info_dict['format'] = info_dict['ext'] | ||||||
| 
 | 
 | ||||||
|         # This is mostly just for backward compatibility of process_info |  | ||||||
|         # As a side-effect, this allows for format-specific filters |  | ||||||
|         if self._match_entry(info_dict) is not None: |         if self._match_entry(info_dict) is not None: | ||||||
|             info_dict['__write_download_archive'] = 'ignore' |             info_dict['__write_download_archive'] = 'ignore' | ||||||
|             return |             return | ||||||
|   | |||||||
| @@ -1352,7 +1352,7 @@ MSO_INFO = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AdobePassIE(InfoExtractor): | class AdobePassIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     _SERVICE_PROVIDER_TEMPLATE = 'https://sp.auth.adobe.com/adobe-services/%s' |     _SERVICE_PROVIDER_TEMPLATE = 'https://sp.auth.adobe.com/adobe-services/%s' | ||||||
|     _USER_AGENT = 'Mozilla/5.0 (X11; Linux i686; rv:47.0) Gecko/20100101 Firefox/47.0' |     _USER_AGENT = 'Mozilla/5.0 (X11; Linux i686; rv:47.0) Gecko/20100101 Firefox/47.0' | ||||||
|     _MVPD_CACHE = 'ap-mvpd' |     _MVPD_CACHE = 'ap-mvpd' | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AENetworksBaseIE(ThePlatformIE): | class AENetworksBaseIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _BASE_URL_REGEX = r'''(?x)https?:// |     _BASE_URL_REGEX = r'''(?x)https?:// | ||||||
|         (?:(?:www|play|watch)\.)? |         (?:(?:www|play|watch)\.)? | ||||||
|         (?P<domain> |         (?P<domain> | ||||||
| @@ -304,7 +304,6 @@ class HistoryTopicIE(AENetworksBaseIE): | |||||||
| class HistoryPlayerIE(AENetworksBaseIE): | class HistoryPlayerIE(AENetworksBaseIE): | ||||||
|     IE_NAME = 'history:player' |     IE_NAME = 'history:player' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<domain>(?:history|biography)\.com)/player/(?P<id>\d+)' |     _VALID_URL = r'https?://(?:www\.)?(?P<domain>(?:history|biography)\.com)/player/(?P<id>\d+)' | ||||||
|     _TESTS = [] |  | ||||||
| 
 | 
 | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         domain, video_id = self._match_valid_url(url).groups() |         domain, video_id = self._match_valid_url(url).groups() | ||||||
|   | |||||||
| @@ -380,7 +380,7 @@ class AfreecaTVIE(InfoExtractor): | |||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AfreecaTVLiveIE(AfreecaTVIE): | class AfreecaTVLiveIE(AfreecaTVIE):  # XXX: Do not subclass from concrete IE | ||||||
| 
 | 
 | ||||||
|     IE_NAME = 'afreecatv:live' |     IE_NAME = 'afreecatv:live' | ||||||
|     _VALID_URL = r'https?://play\.afreeca(?:tv)?\.com/(?P<id>[^/]+)(?:/(?P<bno>\d+))?' |     _VALID_URL = r'https?://play\.afreeca(?:tv)?\.com/(?P<id>[^/]+)(?:/(?P<bno>\d+))?' | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ class AluraIE(InfoExtractor): | |||||||
|             raise ExtractorError('Unable to log in') |             raise ExtractorError('Unable to log in') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AluraCourseIE(AluraIE): | class AluraCourseIE(AluraIE):  # XXX: Do not subclass from concrete IE | ||||||
| 
 | 
 | ||||||
|     _VALID_URL = r'https?://(?:cursos\.)?alura\.com\.br/course/(?P<id>[^/]+)' |     _VALID_URL = r'https?://(?:cursos\.)?alura\.com\.br/course/(?P<id>[^/]+)' | ||||||
|     _LOGIN_URL = 'https://cursos.alura.com.br/loginForm?urlAfterLogin=/loginForm' |     _LOGIN_URL = 'https://cursos.alura.com.br/loginForm?urlAfterLogin=/loginForm' | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AMCNetworksIE(ThePlatformIE): | class AMCNetworksIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<site>amc|bbcamerica|ifc|(?:we|sundance)tv)\.com/(?P<id>(?:movies|shows(?:/[^/]+)+)/[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)?(?P<site>amc|bbcamerica|ifc|(?:we|sundance)tv)\.com/(?P<id>(?:movies|shows(?:/[^/]+)+)/[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.bbcamerica.com/shows/the-graham-norton-show/videos/tina-feys-adorable-airline-themed-family-dinner--51631', |         'url': 'https://www.bbcamerica.com/shows/the-graham-norton-show/videos/tina-feys-adorable-airline-themed-family-dinner--51631', | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AMPIE(InfoExtractor): | class AMPIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     # parse Akamai Adaptive Media Player feed |     # parse Akamai Adaptive Media Player feed | ||||||
|     def _extract_feed_info(self, url): |     def _extract_feed_info(self, url): | ||||||
|         feed = self._download_json( |         feed = self._download_json( | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AolIE(YahooIE): | class AolIE(YahooIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'aol.com' |     IE_NAME = 'aol.com' | ||||||
|     _VALID_URL = r'(?:aol-video:|https?://(?:www\.)?aol\.(?:com|ca|co\.uk|de|jp)/video/(?:[^/]+/)*)(?P<id>\d{9}|[0-9a-f]{24}|[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})' |     _VALID_URL = r'(?:aol-video:|https?://(?:www\.)?aol\.(?:com|ca|co\.uk|de|jp)/video/(?:[^/]+/)*)(?P<id>\d{9}|[0-9a-f]{24}|[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -168,7 +168,7 @@ class AudiusIE(AudiusBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AudiusTrackIE(AudiusIE): | class AudiusTrackIE(AudiusIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'''(?x)(?:audius:)(?:https?://(?:www\.)?.+/v1/tracks/)?(?P<track_id>\w+)''' |     _VALID_URL = r'''(?x)(?:audius:)(?:https?://(?:www\.)?.+/v1/tracks/)?(?P<track_id>\w+)''' | ||||||
|     IE_NAME = 'audius:track' |     IE_NAME = 'audius:track' | ||||||
|     IE_DESC = 'Audius track ID or API link. Prepend with "audius:"' |     IE_DESC = 'Audius track ID or API link. Prepend with "audius:"' | ||||||
| @@ -243,7 +243,7 @@ class AudiusPlaylistIE(AudiusBaseIE): | |||||||
|                                     playlist_data.get('description')) |                                     playlist_data.get('description')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AudiusProfileIE(AudiusPlaylistIE): | class AudiusProfileIE(AudiusPlaylistIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'audius:artist' |     IE_NAME = 'audius:artist' | ||||||
|     IE_DESC = 'Audius.co profile/artist pages' |     IE_DESC = 'Audius.co profile/artist pages' | ||||||
|     _VALID_URL = r'https?://(?:www)?audius\.co/(?P<id>[^\/]+)/?(?:[?#]|$)' |     _VALID_URL = r'https?://(?:www)?audius\.co/(?P<id>[^\/]+)/?(?:[?#]|$)' | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ from .common import InfoExtractor | |||||||
| from ..compat import compat_urllib_parse_urlencode | from ..compat import compat_urllib_parse_urlencode | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AWSIE(InfoExtractor): | class AWSIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     _AWS_ALGORITHM = 'AWS4-HMAC-SHA256' |     _AWS_ALGORITHM = 'AWS4-HMAC-SHA256' | ||||||
|     _AWS_REGION = 'us-east-1' |     _AWS_REGION = 'us-east-1' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from .brightcove import BrightcoveNewIE | |||||||
| from ..utils import extract_attributes | from ..utils import extract_attributes | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BandaiChannelIE(BrightcoveNewIE): | class BandaiChannelIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'bandaichannel' |     IE_NAME = 'bandaichannel' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?b-ch\.com/titles/(?P<id>\d+/\d+)' |     _VALID_URL = r'https?://(?:www\.)?b-ch\.com/titles/(?P<id>\d+/\d+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -211,7 +211,7 @@ class BandcampIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BandcampAlbumIE(BandcampIE): | class BandcampAlbumIE(BandcampIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'Bandcamp:album' |     IE_NAME = 'Bandcamp:album' | ||||||
|     _VALID_URL = r'https?://(?:(?P<subdomain>[^.]+)\.)?bandcamp\.com/album/(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:(?P<subdomain>[^.]+)\.)?bandcamp\.com/album/(?P<id>[^/?#&]+)' | ||||||
| 
 | 
 | ||||||
| @@ -314,7 +314,7 @@ class BandcampAlbumIE(BandcampIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BandcampWeeklyIE(BandcampIE): | class BandcampWeeklyIE(BandcampIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'Bandcamp:weekly' |     IE_NAME = 'Bandcamp:weekly' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?bandcamp\.com/?\?(?:.*?&)?show=(?P<id>\d+)' |     _VALID_URL = r'https?://(?:www\.)?bandcamp\.com/?\?(?:.*?&)?show=(?P<id>\d+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -588,7 +588,7 @@ class BBCCoUkIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BBCIE(BBCCoUkIE): | class BBCIE(BBCCoUkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'bbc' |     IE_NAME = 'bbc' | ||||||
|     IE_DESC = 'BBC' |     IE_DESC = 'BBC' | ||||||
|     _VALID_URL = r'''(?x) |     _VALID_URL = r'''(?x) | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ class BFMTVIE(BFMTVBaseIE): | |||||||
|         return self._brightcove_url_result(video_block['videoid'], video_block) |         return self._brightcove_url_result(video_block['videoid'], video_block) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BFMTVLiveIE(BFMTVIE): | class BFMTVLiveIE(BFMTVIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'bfmtv:live' |     IE_NAME = 'bfmtv:live' | ||||||
|     _VALID_URL = BFMTVBaseIE._VALID_URL_BASE + '(?P<id>(?:[^/]+/)?en-direct)' |     _VALID_URL = BFMTVBaseIE._VALID_URL_BASE + '(?P<id>(?:[^/]+/)?en-direct)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ class BilibiliBaseIE(InfoExtractor): | |||||||
|         missing_formats = format_names.keys() - set(traverse_obj(formats, (..., 'quality'))) |         missing_formats = format_names.keys() - set(traverse_obj(formats, (..., 'quality'))) | ||||||
|         if missing_formats: |         if missing_formats: | ||||||
|             self.to_screen(f'Format(s) {", ".join(format_names[i] for i in missing_formats)} are missing; ' |             self.to_screen(f'Format(s) {", ".join(format_names[i] for i in missing_formats)} are missing; ' | ||||||
|                            'you have to login or become premium member to download them') |                            f'you have to login or become premium member to download them. {self._login_hint()}') | ||||||
| 
 | 
 | ||||||
|         self._sort_formats(formats) |         self._sort_formats(formats) | ||||||
|         return formats |         return formats | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSBaseIE(ThePlatformFeedIE): | class CBSBaseIE(ThePlatformFeedIE):  # XXX: Do not subclass from concrete IE | ||||||
|     def _parse_smil_subtitles(self, smil, namespace=None, subtitles_lang='en'): |     def _parse_smil_subtitles(self, smil, namespace=None, subtitles_lang='en'): | ||||||
|         subtitles = {} |         subtitles = {} | ||||||
|         for k, ext in [('sMPTE-TTCCURL', 'tt'), ('ClosedCaptionURL', 'ttml'), ('webVTTCaptionURL', 'vtt')]: |         for k, ext in [('sMPTE-TTCCURL', 'tt'), ('ClosedCaptionURL', 'ttml'), ('webVTTCaptionURL', 'vtt')]: | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from .cbs import CBSIE | |||||||
| from ..utils import int_or_none | from ..utils import int_or_none | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSInteractiveIE(CBSIE): | class CBSInteractiveIE(CBSIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<site>cnet|zdnet)\.com/(?:videos|video(?:/share)?)/(?P<id>[^/?]+)' |     _VALID_URL = r'https?://(?:www\.)?(?P<site>cnet|zdnet)\.com/(?:videos|video(?:/share)?)/(?P<id>[^/?]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://www.cnet.com/videos/hands-on-with-microsofts-windows-8-1-update/', |         'url': 'http://www.cnet.com/videos/hands-on-with-microsofts-windows-8-1-update/', | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSLocalIE(AnvatoIE): | class CBSLocalIE(AnvatoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL_BASE = r'https?://[a-z]+\.cbslocal\.com/' |     _VALID_URL_BASE = r'https?://[a-z]+\.cbslocal\.com/' | ||||||
|     _VALID_URL = _VALID_URL_BASE + r'video/(?P<id>\d+)' |     _VALID_URL = _VALID_URL_BASE + r'video/(?P<id>\d+)' | ||||||
| 
 | 
 | ||||||
| @@ -47,7 +47,7 @@ class CBSLocalIE(AnvatoIE): | |||||||
|             'anvato:anvato_cbslocal_app_web_prod_547f3e49241ef0e5d30c79b2efbca5d92c698f67:' + mcp_id, 'Anvato', mcp_id) |             'anvato:anvato_cbslocal_app_web_prod_547f3e49241ef0e5d30c79b2efbca5d92c698f67:' + mcp_id, 'Anvato', mcp_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSLocalArticleIE(AnvatoIE): | class CBSLocalArticleIE(AnvatoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = CBSLocalIE._VALID_URL_BASE + r'\d+/\d+/\d+/(?P<id>[0-9a-z-]+)' |     _VALID_URL = CBSLocalIE._VALID_URL_BASE + r'\d+/\d+/\d+/(?P<id>[0-9a-z-]+)' | ||||||
| 
 | 
 | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSNewsEmbedIE(CBSIE): | class CBSNewsEmbedIE(CBSIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'cbsnews:embed' |     IE_NAME = 'cbsnews:embed' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/embed/video[^#]*#(?P<id>.+)' |     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/embed/video[^#]*#(?P<id>.+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -27,7 +27,7 @@ class CBSNewsEmbedIE(CBSIE): | |||||||
|         return self._extract_video_info(item['mpxRefId'], 'cbsnews') |         return self._extract_video_info(item['mpxRefId'], 'cbsnews') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CBSNewsIE(CBSIE): | class CBSNewsIE(CBSIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'cbsnews' |     IE_NAME = 'cbsnews' | ||||||
|     IE_DESC = 'CBS News' |     IE_DESC = 'CBS News' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/(?:news|video)/(?P<id>[\da-z_-]+)' |     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/(?:news|video)/(?P<id>[\da-z_-]+)' | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ from .mtv import MTVIE | |||||||
| # TODO Remove - Reason: Outdated Site | # TODO Remove - Reason: Outdated Site | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CMTIE(MTVIE): | class CMTIE(MTVIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'cmt.com' |     IE_NAME = 'cmt.com' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?cmt\.com/(?:videos|shows|(?:full-)?episodes|video-clips)/(?P<id>[^/]+)' |     _VALID_URL = r'https?://(?:www\.)?cmt\.com/(?:videos|shows|(?:full-)?episodes|video-clips)/(?P<id>[^/]+)' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -3676,12 +3676,13 @@ class InfoExtractor: | |||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get_testcases(cls, include_onlymatching=False): |     def get_testcases(cls, include_onlymatching=False): | ||||||
|         t = getattr(cls, '_TEST', None) |         # Do not look in super classes | ||||||
|  |         t = vars(cls).get('_TEST') | ||||||
|         if t: |         if t: | ||||||
|             assert not hasattr(cls, '_TESTS'), f'{cls.ie_key()}IE has _TEST and _TESTS' |             assert not hasattr(cls, '_TESTS'), f'{cls.ie_key()}IE has _TEST and _TESTS' | ||||||
|             tests = [t] |             tests = [t] | ||||||
|         else: |         else: | ||||||
|             tests = getattr(cls, '_TESTS', []) |             tests = vars(cls).get('_TESTS', []) | ||||||
|         for t in tests: |         for t in tests: | ||||||
|             if not include_onlymatching and t.get('only_matching', False): |             if not include_onlymatching and t.get('only_matching', False): | ||||||
|                 continue |                 continue | ||||||
| @@ -3690,12 +3691,12 @@ class InfoExtractor: | |||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get_webpage_testcases(cls): |     def get_webpage_testcases(cls): | ||||||
|         tests = getattr(cls, '_WEBPAGE_TESTS', []) |         tests = vars(cls).get('_WEBPAGE_TESTS', []) | ||||||
|         for t in tests: |         for t in tests: | ||||||
|             t['name'] = cls.ie_key() |             t['name'] = cls.ie_key() | ||||||
|         return tests |         return tests | ||||||
| 
 | 
 | ||||||
|     @classproperty |     @classproperty(cache=True) | ||||||
|     def age_limit(cls): |     def age_limit(cls): | ||||||
|         """Get age limit from the testcases""" |         """Get age limit from the testcases""" | ||||||
|         return max(traverse_obj( |         return max(traverse_obj( | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CorusIE(ThePlatformFeedIE): | class CorusIE(ThePlatformFeedIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'''(?x) |     _VALID_URL = r'''(?x) | ||||||
|                     https?:// |                     https?:// | ||||||
|                         (?:www\.)? |                         (?:www\.)? | ||||||
|   | |||||||
| @@ -125,7 +125,7 @@ class DaumClipIE(DaumBaseIE): | |||||||
|             self._KAKAO_EMBED_BASE + video_id, 'Kakao', video_id) |             self._KAKAO_EMBED_BASE + video_id, 'Kakao', video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DaumListIE(InfoExtractor): | class DaumListIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     def _get_entries(self, list_id, list_id_type): |     def _get_entries(self, list_id, list_id_type): | ||||||
|         name = None |         name = None | ||||||
|         entries = [] |         entries = [] | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| from .zdf import ZDFIE | from .zdf import ZDFIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DreiSatIE(ZDFIE): | class DreiSatIE(ZDFIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = '3sat' |     IE_NAME = '3sat' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?3sat\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)\.html' |     _VALID_URL = r'https?://(?:www\.)?3sat\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)\.html' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from ..utils import str_to_int | |||||||
| from .keezmovies import KeezMoviesIE | from .keezmovies import KeezMoviesIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ExtremeTubeIE(KeezMoviesIE): | class ExtremeTubeIE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?extremetube\.com/(?:[^/]+/)?video/(?P<id>[^/#?&]+)' |     _VALID_URL = r'https?://(?:www\.)?extremetube\.com/(?:[^/]+/)?video/(?P<id>[^/#?&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://www.extremetube.com/video/music-video-14-british-euro-brit-european-cumshots-swallow-652431', |         'url': 'http://www.extremetube.com/video/music-video-14-british-euro-brit-european-cumshots-swallow-652431', | ||||||
|   | |||||||
| @@ -125,7 +125,7 @@ class FancodeVodIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class FancodeLiveIE(FancodeVodIE): | class FancodeLiveIE(FancodeVodIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'fancode:live' |     IE_NAME = 'fancode:live' | ||||||
| 
 | 
 | ||||||
|     _VALID_URL = r'https?://(www\.)?fancode\.com/match/(?P<id>[0-9]+).+' |     _VALID_URL = r'https?://(www\.)?fancode\.com/match/(?P<id>[0-9]+).+' | ||||||
|   | |||||||
| @@ -127,7 +127,7 @@ class HitboxIE(InfoExtractor): | |||||||
|         return metadata |         return metadata | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class HitboxLiveIE(HitboxIE): | class HitboxLiveIE(HitboxIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'hitbox:live' |     IE_NAME = 'hitbox:live' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?:hitbox|smashcast)\.tv/(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)?(?:hitbox|smashcast)\.tv/(?P<id>[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -138,7 +138,7 @@ class ImgurGalleryIE(InfoExtractor): | |||||||
|         return self.url_result('http://imgur.com/%s' % gallery_id, ImgurIE.ie_key(), gallery_id) |         return self.url_result('http://imgur.com/%s' % gallery_id, ImgurIE.ie_key(), gallery_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ImgurAlbumIE(ImgurGalleryIE): | class ImgurAlbumIE(ImgurGalleryIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'imgur:album' |     IE_NAME = 'imgur:album' | ||||||
|     _VALID_URL = r'https?://(?:i\.)?imgur\.com/a/(?P<id>[a-zA-Z0-9]+)' |     _VALID_URL = r'https?://(?:i\.)?imgur\.com/a/(?P<id>[a-zA-Z0-9]+)' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -134,7 +134,7 @@ class JamendoIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class JamendoAlbumIE(JamendoIE): | class JamendoAlbumIE(JamendoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?jamendo\.com/album/(?P<id>[0-9]+)' |     _VALID_URL = r'https?://(?:www\.)?jamendo\.com/album/(?P<id>[0-9]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.jamendo.com/album/121486/duck-on-cover', |         'url': 'https://www.jamendo.com/album/121486/duck-on-cover', | ||||||
|   | |||||||
| @@ -194,7 +194,7 @@ class LA7PodcastEpisodeIE(InfoExtractor): | |||||||
|         return self._extract_info(webpage, video_id) |         return self._extract_info(webpage, video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class LA7PodcastIE(LA7PodcastEpisodeIE): | class LA7PodcastIE(LA7PodcastEpisodeIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'la7.it:podcast' |     IE_NAME = 'la7.it:podcast' | ||||||
|     _VALID_URL = r'(https?://)?(www\.)?la7\.it/(?P<id>[^/]+)/podcast/?(?:$|[#?])' |     _VALID_URL = r'(https?://)?(www\.)?la7\.it/(?P<id>[^/]+)/podcast/?(?:$|[#?])' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ class Laola1TvEmbedIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Laola1TvBaseIE(Laola1TvEmbedIE): | class Laola1TvBaseIE(Laola1TvEmbedIE):  # XXX: Do not subclass from concrete IE | ||||||
|     def _extract_video(self, url): |     def _extract_video(self, url): | ||||||
|         display_id = self._match_id(url) |         display_id = self._match_id(url) | ||||||
|         webpage = self._download_webpage(url, display_id) |         webpage = self._download_webpage(url, display_id) | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from .common import InfoExtractor | |||||||
| from .arkena import ArkenaIE | from .arkena import ArkenaIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class LcpPlayIE(ArkenaIE): | class LcpPlayIE(ArkenaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://play\.lcp\.fr/embed/(?P<id>[^/]+)/(?P<account_id>[^/]+)/[^/]+/[^/]+' |     _VALID_URL = r'https?://play\.lcp\.fr/embed/(?P<id>[^/]+)/(?P<account_id>[^/]+)/[^/]+/[^/]+' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://play.lcp.fr/embed/327336/131064/darkmatter/0', |         'url': 'http://play.lcp.fr/embed/327336/131064/darkmatter/0', | ||||||
|   | |||||||
| @@ -286,7 +286,7 @@ class MediasetIE(ThePlatformBaseIE): | |||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MediasetShowIE(MediasetIE): | class MediasetShowIE(MediasetIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'''(?x) |     _VALID_URL = r'''(?x) | ||||||
|                     (?: |                     (?: | ||||||
|                         https?:// |                         https?:// | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MiTeleIE(TelecincoIE): | class MiTeleIE(TelecincoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = 'mitele.es' |     IE_DESC = 'mitele.es' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?mitele\.es/(?:[^/]+/)+(?P<id>[^/]+)/player' |     _VALID_URL = r'https?://(?:www\.)?mitele\.es/(?:[^/]+/)+(?P<id>[^/]+)/player' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ from ..utils import ( | |||||||
| from .keezmovies import KeezMoviesIE | from .keezmovies import KeezMoviesIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MofosexIE(KeezMoviesIE): | class MofosexIE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?mofosex\.com/videos/(?P<id>\d+)/(?P<display_id>[^/?#&.]+)\.html' |     _VALID_URL = r'https?://(?:www\.)?mofosex\.com/videos/(?P<id>\d+)/(?P<display_id>[^/?#&.]+)\.html' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://www.mofosex.com/videos/318131/amateur-teen-playing-and-masturbating-318131.html', |         'url': 'http://www.mofosex.com/videos/318131/amateur-teen-playing-and-masturbating-318131.html', | ||||||
|   | |||||||
| @@ -536,7 +536,7 @@ class MTVItaliaIE(MTVServicesInfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MTVItaliaProgrammaIE(MTVItaliaIE): | class MTVItaliaProgrammaIE(MTVItaliaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'mtv.it:programma' |     IE_NAME = 'mtv.it:programma' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?mtv\.it/(?:programmi|playlist)/(?P<id>[0-9a-z]+)' |     _VALID_URL = r'https?://(?:www\.)?mtv\.it/(?:programmi|playlist)/(?P<id>[0-9a-z]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -99,7 +99,7 @@ query Medium($id: ID!) { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MurrtubeUserIE(MurrtubeIE): | class MurrtubeUserIE(MurrtubeIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = 'Murrtube user profile' |     IE_DESC = 'Murrtube user profile' | ||||||
|     _VALID_URL = r'https?://murrtube\.net/(?P<id>[^/]+)$' |     _VALID_URL = r'https?://murrtube\.net/(?P<id>[^/]+)$' | ||||||
|     _TEST = { |     _TEST = { | ||||||
|   | |||||||
| @@ -97,7 +97,7 @@ class MusicdexAlbumIE(MusicdexBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MusicdexPageIE(MusicdexBaseIE): | class MusicdexPageIE(MusicdexBaseIE):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     def _entries(self, id): |     def _entries(self, id): | ||||||
|         next_page_url = self._API_URL % id |         next_page_url = self._API_URL % id | ||||||
|         while next_page_url: |         while next_page_url: | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ class NationalGeographicVideoIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NationalGeographicTVIE(FOXIE): | class NationalGeographicTVIE(FOXIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?nationalgeographic\.com/tv/watch/(?P<id>[\da-fA-F]+)' |     _VALID_URL = r'https?://(?:www\.)?nationalgeographic\.com/tv/watch/(?P<id>[\da-fA-F]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.nationalgeographic.com/tv/watch/6a875e6e734b479beda26438c9f21138/', |         'url': 'https://www.nationalgeographic.com/tv/watch/6a875e6e734b479beda26438c9f21138/', | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NBCIE(ThePlatformIE): | class NBCIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?nbc\.com/(?:classic-tv/)?[^/]+/video/[^/]+/(?P<id>n?\d+))' |     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?nbc\.com/(?:classic-tv/)?[^/]+/video/[^/]+/(?P<id>n?\d+))' | ||||||
| 
 | 
 | ||||||
|     _TESTS = [ |     _TESTS = [ | ||||||
| @@ -315,7 +315,7 @@ class NBCSportsStreamIE(AdobePassIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NBCNewsIE(ThePlatformIE): | class NBCNewsIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'(?x)https?://(?:www\.)?(?:nbcnews|today|msnbc)\.com/([^/]+/)*(?:.*-)?(?P<id>[^/?]+)' |     _VALID_URL = r'(?x)https?://(?:www\.)?(?:nbcnews|today|msnbc)\.com/([^/]+/)*(?:.*-)?(?P<id>[^/?]+)' | ||||||
|     _EMBED_REGEX = [r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//www\.nbcnews\.com/widget/video-embed/[^"\']+)\1'] |     _EMBED_REGEX = [r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//www\.nbcnews\.com/widget/video-embed/[^"\']+)\1'] | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -218,7 +218,7 @@ class NJoyIE(NDRBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NDREmbedBaseIE(InfoExtractor): | class NDREmbedBaseIE(InfoExtractor):  # XXX: Conventionally, Concrete class names do not end in BaseIE | ||||||
|     IE_NAME = 'ndr:embed:base' |     IE_NAME = 'ndr:embed:base' | ||||||
|     _VALID_URL = r'(?:ndr:(?P<id_s>[\da-z]+)|https?://www\.ndr\.de/(?P<id>[\da-z]+)-ppjson\.json)' |     _VALID_URL = r'(?:ndr:(?P<id_s>[\da-z]+)|https?://www\.ndr\.de/(?P<id>[\da-z]+)-ppjson\.json)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -315,7 +315,7 @@ class NDREmbedBaseIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NDREmbedIE(NDREmbedBaseIE): | class NDREmbedIE(NDREmbedBaseIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'ndr:embed' |     IE_NAME = 'ndr:embed' | ||||||
|     _VALID_URL = r'https?://(?:\w+\.)*ndr\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:(?:ard)?player|externalPlayer)\.html' |     _VALID_URL = r'https?://(?:\w+\.)*ndr\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:(?:ard)?player|externalPlayer)\.html' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -413,7 +413,7 @@ class NDREmbedIE(NDREmbedBaseIE): | |||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NJoyEmbedIE(NDREmbedBaseIE): | class NJoyEmbedIE(NDREmbedBaseIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'njoy:embed' |     IE_NAME = 'njoy:embed' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?n-joy\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:player|externalPlayer)_[^/]+\.html' |     _VALID_URL = r'https?://(?:www\.)?n-joy\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:player|externalPlayer)_[^/]+\.html' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ class NextMediaIE(InfoExtractor): | |||||||
|         return self._og_search_property('description', page) |         return self._og_search_property('description', page) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NextMediaActionNewsIE(NextMediaIE): | class NextMediaActionNewsIE(NextMediaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = '蘋果日報 - 動新聞' |     IE_DESC = '蘋果日報 - 動新聞' | ||||||
|     _VALID_URL = r'https?://hk\.dv\.nextmedia\.com/actionnews/[^/]+/(?P<date>\d+)/(?P<id>\d+)/\d+' |     _VALID_URL = r'https?://hk\.dv\.nextmedia\.com/actionnews/[^/]+/(?P<date>\d+)/(?P<id>\d+)/\d+' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -102,7 +102,7 @@ class NextMediaActionNewsIE(NextMediaIE): | |||||||
|         return self._extract_from_nextmedia_page(news_id, url, article_page) |         return self._extract_from_nextmedia_page(news_id, url, article_page) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AppleDailyIE(NextMediaIE): | class AppleDailyIE(NextMediaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = '臺灣蘋果日報' |     IE_DESC = '臺灣蘋果日報' | ||||||
|     _VALID_URL = r'https?://(www|ent)\.appledaily\.com\.tw/[^/]+/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?' |     _VALID_URL = r'https?://(www|ent)\.appledaily\.com\.tw/[^/]+/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -188,7 +188,7 @@ class NickDeIE(MTVServicesInfoExtractor): | |||||||
|         return self._remove_template_parameter(config['feedWithQueryParams']) |         return self._remove_template_parameter(config['feedWithQueryParams']) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NickNightIE(NickDeIE): | class NickNightIE(NickDeIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'nicknight' |     IE_NAME = 'nicknight' | ||||||
|     _VALID_URL = r'https?://(?:www\.)(?P<host>nicknight\.(?:de|at|tv))/(?:playlist|shows)/(?:[^/]+/)*(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)(?P<host>nicknight\.(?:de|at|tv))/(?:playlist|shows)/(?:[^/]+/)*(?P<id>[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -599,7 +599,7 @@ class NPORadioFragmentIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NPODataMidEmbedIE(InfoExtractor): | class NPODataMidEmbedIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         display_id = self._match_id(url) |         display_id = self._match_id(url) | ||||||
|         webpage = self._download_webpage(url, display_id) |         webpage = self._download_webpage(url, display_id) | ||||||
| @@ -653,7 +653,7 @@ class HetKlokhuisIE(NPODataMidEmbedIE): | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NPOPlaylistBaseIE(NPOIE): | class NPOPlaylistBaseIE(NPOIE):  # XXX: Do not subclass from concrete IE | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         playlist_id = self._match_id(url) |         playlist_id = self._match_id(url) | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -735,7 +735,7 @@ class NRKTVSeriesIE(NRKTVSerieBaseIE): | |||||||
|             entries, series_id, titles.get('title'), titles.get('subtitle')) |             entries, series_id, titles.get('title'), titles.get('subtitle')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NRKTVDirekteIE(NRKTVIE): | class NRKTVDirekteIE(NRKTVIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = 'NRK TV Direkte and NRK Radio Direkte' |     IE_DESC = 'NRK TV Direkte and NRK Radio Direkte' | ||||||
|     _VALID_URL = r'https?://(?:tv|radio)\.nrk\.no/direkte/(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:tv|radio)\.nrk\.no/direkte/(?P<id>[^/?#&]+)' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import re | |||||||
| from .common import InfoExtractor | from .common import InfoExtractor | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class OnceIE(InfoExtractor): | class OnceIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     _VALID_URL = r'https?://.+?\.unicornmedia\.com/now/(?:ads/vmap/)?[^/]+/[^/]+/(?P<domain_id>[^/]+)/(?P<application_id>[^/]+)/(?:[^/]+/)?(?P<media_item_id>[^/]+)/content\.(?:once|m3u8|mp4)' |     _VALID_URL = r'https?://.+?\.unicornmedia\.com/now/(?:ads/vmap/)?[^/]+/[^/]+/(?P<domain_id>[^/]+)/(?P<application_id>[^/]+)/(?:[^/]+/)?(?P<media_item_id>[^/]+)/content\.(?:once|m3u8|mp4)' | ||||||
|     ADAPTIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/master/playlist/%s/%s/%s/content.m3u8' |     ADAPTIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/master/playlist/%s/%s/%s/content.m3u8' | ||||||
|     PROGRESSIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/media/progressive/%s/%s/%s/%s/content.mp4' |     PROGRESSIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/media/progressive/%s/%s/%s/%s/content.mp4' | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ class PeekVidsIE(InfoExtractor): | |||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class PlayVidsIE(PeekVidsIE): | class PlayVidsIE(PeekVidsIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?playvids\.com/(?:embed/|[^/]{2}/)?(?P<id>[^/?#]*)' |     _VALID_URL = r'https?://(?:www\.)?playvids\.com/(?:embed/|[^/]{2}/)?(?P<id>[^/?#]*)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.playvids.com/U3pBrYhsjXM/pc/dane-jones-cute-redhead-with-perfect-tits-with-mini-vamp', |         'url': 'https://www.playvids.com/U3pBrYhsjXM/pc/dane-jones-cute-redhead-with-perfect-tits-with-mini-vamp', | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ class RadLiveIE(InfoExtractor): | |||||||
|         return result |         return result | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RadLiveSeasonIE(RadLiveIE): | class RadLiveSeasonIE(RadLiveIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'radlive:season' |     IE_NAME = 'radlive:season' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/season/(?P<id>[a-f0-9-]+)' |     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/season/(?P<id>[a-f0-9-]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -134,7 +134,7 @@ class RadLiveSeasonIE(RadLiveIE): | |||||||
|         return self.playlist_result(entries, season_id, video_info.get('title')) |         return self.playlist_result(entries, season_id, video_info.get('title')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RadLiveChannelIE(RadLiveIE): | class RadLiveChannelIE(RadLiveIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'radlive:channel' |     IE_NAME = 'radlive:channel' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/channel/(?P<id>[a-f0-9-]+)' |     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/channel/(?P<id>[a-f0-9-]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -356,7 +356,7 @@ class RaiPlayIE(RaiBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RaiPlayLiveIE(RaiPlayIE): | class RaiPlayLiveIE(RaiPlayIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplay\.it/dirette/(?P<id>[^/?#&]+))' |     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplay\.it/dirette/(?P<id>[^/?#&]+))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://www.raiplay.it/dirette/rainews24', |         'url': 'http://www.raiplay.it/dirette/rainews24', | ||||||
| @@ -504,7 +504,7 @@ class RaiPlaySoundIE(RaiBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RaiPlaySoundLiveIE(RaiPlaySoundIE): | class RaiPlaySoundLiveIE(RaiPlaySoundIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplaysound\.it/(?P<id>[^/?#&]+)$)' |     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplaysound\.it/(?P<id>[^/?#&]+)$)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.raiplaysound.it/radio2', |         'url': 'https://www.raiplaysound.it/radio2', | ||||||
| @@ -717,7 +717,7 @@ class RaiIE(RaiBaseIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RaiNewsIE(RaiIE): | class RaiNewsIE(RaiIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = rf'https?://(www\.)?rainews\.it/(?!articoli)[^?#]+-(?P<id>{RaiBaseIE._UUID_RE})(?:-[^/?#]+)?\.html' |     _VALID_URL = rf'https?://(www\.)?rainews\.it/(?!articoli)[^?#]+-(?P<id>{RaiBaseIE._UUID_RE})(?:-[^/?#]+)?\.html' | ||||||
|     _EMBED_REGEX = [rf'<iframe[^>]+data-src="(?P<url>/iframe/[^?#]+?{RaiBaseIE._UUID_RE}\.html)'] |     _EMBED_REGEX = [rf'<iframe[^>]+data-src="(?P<url>/iframe/[^?#]+?{RaiBaseIE._UUID_RE}\.html)'] | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ class RedBullTVIE(InfoExtractor): | |||||||
|         return self.extract_info(video_id) |         return self.extract_info(video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RedBullEmbedIE(RedBullTVIE): | class RedBullEmbedIE(RedBullTVIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?redbull\.com/embed/(?P<id>rrn:content:[^:]+:[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}:[a-z]{2}-[A-Z]{2,3})' |     _VALID_URL = r'https?://(?:www\.)?redbull\.com/embed/(?P<id>rrn:content:[^:]+:[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}:[a-z]{2}-[A-Z]{2,3})' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         # HLS manifest accessible only using assetId |         # HLS manifest accessible only using assetId | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RTSIE(SRGSSRIE): | class RTSIE(SRGSSRIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = 'RTS.ch' |     IE_DESC = 'RTS.ch' | ||||||
|     _VALID_URL = r'rts:(?P<rts_id>\d+)|https?://(?:.+?\.)?rts\.ch/(?:[^/]+/){2,}(?P<id>[0-9]+)-(?P<display_id>.+?)\.html' |     _VALID_URL = r'rts:(?P<rts_id>\d+)|https?://(?:.+?\.)?rts\.ch/(?:[^/]+/){2,}(?P<id>[0-9]+)-(?P<display_id>.+?)\.html' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -170,7 +170,7 @@ class RTVEALaCartaIE(InfoExtractor): | |||||||
|             for s in subs) |             for s in subs) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RTVEAudioIE(RTVEALaCartaIE): | class RTVEAudioIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'rtve.es:audio' |     IE_NAME = 'rtve.es:audio' | ||||||
|     IE_DESC = 'RTVE audio' |     IE_DESC = 'RTVE audio' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?rtve\.es/(alacarta|play)/audios/[^/]+/[^/]+/(?P<id>[0-9]+)' |     _VALID_URL = r'https?://(?:www\.)?rtve\.es/(alacarta|play)/audios/[^/]+/[^/]+/(?P<id>[0-9]+)' | ||||||
| @@ -257,7 +257,7 @@ class RTVEAudioIE(RTVEALaCartaIE): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RTVEInfantilIE(RTVEALaCartaIE): | class RTVEInfantilIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'rtve.es:infantil' |     IE_NAME = 'rtve.es:infantil' | ||||||
|     IE_DESC = 'RTVE infantil' |     IE_DESC = 'RTVE infantil' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?rtve\.es/infantil/serie/[^/]+/video/[^/]+/(?P<id>[0-9]+)/' |     _VALID_URL = r'https?://(?:www\.)?rtve\.es/infantil/serie/[^/]+/video/[^/]+/(?P<id>[0-9]+)/' | ||||||
| @@ -276,7 +276,7 @@ class RTVEInfantilIE(RTVEALaCartaIE): | |||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RTVELiveIE(RTVEALaCartaIE): | class RTVELiveIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'rtve.es:live' |     IE_NAME = 'rtve.es:live' | ||||||
|     IE_DESC = 'RTVE.es live streams' |     IE_DESC = 'RTVE.es live streams' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?rtve\.es/directo/(?P<id>[a-zA-Z0-9-]+)' |     _VALID_URL = r'https?://(?:www\.)?rtve\.es/directo/(?P<id>[a-zA-Z0-9-]+)' | ||||||
|   | |||||||
| @@ -240,7 +240,6 @@ class RutubeMovieIE(RutubePlaylistBaseIE): | |||||||
|     IE_NAME = 'rutube:movie' |     IE_NAME = 'rutube:movie' | ||||||
|     IE_DESC = 'Rutube movies' |     IE_DESC = 'Rutube movies' | ||||||
|     _VALID_URL = r'https?://rutube\.ru/metainfo/tv/(?P<id>\d+)' |     _VALID_URL = r'https?://rutube\.ru/metainfo/tv/(?P<id>\d+)' | ||||||
|     _TESTS = [] |  | ||||||
| 
 | 
 | ||||||
|     _MOVIE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/?format=json' |     _MOVIE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/?format=json' | ||||||
|     _PAGE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/video?page=%s&format=json' |     _PAGE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/video?page=%s&format=json' | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SevenPlusIE(BrightcoveNewIE): | class SevenPlusIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = '7plus' |     IE_NAME = '7plus' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))' |     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ class SkyItPlayerIE(InfoExtractor): | |||||||
|         return self._parse_video(video, video_id) |         return self._parse_video(video, video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SkyItVideoIE(SkyItPlayerIE): | class SkyItVideoIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'video.sky.it' |     IE_NAME = 'video.sky.it' | ||||||
|     _VALID_URL = r'https?://(?:masterchef|video|xfactor)\.sky\.it(?:/[^/]+)*/video/[0-9a-z-]+-(?P<id>\d+)' |     _VALID_URL = r'https?://(?:masterchef|video|xfactor)\.sky\.it(?:/[^/]+)*/video/[0-9a-z-]+-(?P<id>\d+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -99,7 +99,7 @@ class SkyItVideoIE(SkyItPlayerIE): | |||||||
|         return self._player_url_result(video_id) |         return self._player_url_result(video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SkyItVideoLiveIE(SkyItPlayerIE): | class SkyItVideoLiveIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'video.sky.it:live' |     IE_NAME = 'video.sky.it:live' | ||||||
|     _VALID_URL = r'https?://video\.sky\.it/diretta/(?P<id>[^/?&#]+)' |     _VALID_URL = r'https?://video\.sky\.it/diretta/(?P<id>[^/?&#]+)' | ||||||
|     _TEST = { |     _TEST = { | ||||||
| @@ -127,7 +127,7 @@ class SkyItVideoLiveIE(SkyItPlayerIE): | |||||||
|         return self._parse_video(livestream, asset_id) |         return self._parse_video(livestream, asset_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SkyItIE(SkyItPlayerIE): | class SkyItIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'sky.it' |     IE_NAME = 'sky.it' | ||||||
|     _VALID_URL = r'https?://(?:sport|tg24)\.sky\.it(?:/[^/]+)*/\d{4}/\d{2}/\d{2}/(?P<id>[^/?&#]+)' |     _VALID_URL = r'https?://(?:sport|tg24)\.sky\.it(?:/[^/]+)*/\d{4}/\d{2}/\d{2}/(?P<id>[^/?&#]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -166,7 +166,7 @@ class SkyItIE(SkyItPlayerIE): | |||||||
|         return self._player_url_result(video_id) |         return self._player_url_result(video_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SkyItArteIE(SkyItIE): | class SkyItArteIE(SkyItIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'arte.sky.it' |     IE_NAME = 'arte.sky.it' | ||||||
|     _VALID_URL = r'https?://arte\.sky\.it/video/(?P<id>[^/?&#]+)' |     _VALID_URL = r'https?://arte\.sky\.it/video/(?P<id>[^/?&#]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -187,7 +187,7 @@ class SkyItArteIE(SkyItIE): | |||||||
|     _VIDEO_ID_REGEX = r'"embedUrl"\s*:\s*"(?:https:)?//player\.sky\.it/player/external\.html\?[^"]*\bid=(\d+)' |     _VIDEO_ID_REGEX = r'"embedUrl"\s*:\s*"(?:https:)?//player\.sky\.it/player/external\.html\?[^"]*\bid=(\d+)' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CieloTVItIE(SkyItIE): | class CieloTVItIE(SkyItIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'cielotv.it' |     IE_NAME = 'cielotv.it' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?cielotv\.it/video/(?P<id>[^.]+)\.html' |     _VALID_URL = r'https?://(?:www\.)?cielotv\.it/video/(?P<id>[^.]+)\.html' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -208,7 +208,7 @@ class CieloTVItIE(SkyItIE): | |||||||
|     _VIDEO_ID_REGEX = r'videoId\s*=\s*"(\d+)"' |     _VIDEO_ID_REGEX = r'videoId\s*=\s*"(\d+)"' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TV8ItIE(SkyItVideoIE): | class TV8ItIE(SkyItVideoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'tv8.it' |     IE_NAME = 'tv8.it' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?tv8\.it/(?:show)?video/[0-9a-z-]+-(?P<id>\d+)' |     _VALID_URL = r'https?://(?:www\.)?tv8\.it/(?:show)?video/[0-9a-z-]+-(?P<id>\d+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ class SouthParkIE(MTVServicesInfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SouthParkEsIE(SouthParkIE): | class SouthParkEsIE(SouthParkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'southpark.cc.com:español' |     IE_NAME = 'southpark.cc.com:español' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.cc\.com/es/episodios/(?P<id>.+?)(\?|#|$))' |     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.cc\.com/es/episodios/(?P<id>.+?)(\?|#|$))' | ||||||
|     _LANG = 'es' |     _LANG = 'es' | ||||||
| @@ -50,7 +50,7 @@ class SouthParkEsIE(SouthParkIE): | |||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SouthParkDeIE(SouthParkIE): | class SouthParkDeIE(SouthParkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'southpark.de' |     IE_NAME = 'southpark.de' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.de/(?:(en/(videoclip|collections|episodes|video-clips))|(videoclip|collections|folgen))/(?P<id>(?P<unique_id>.+?)/.+?)(?:\?|#|$))' |     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.de/(?:(en/(videoclip|collections|episodes|video-clips))|(videoclip|collections|folgen))/(?P<id>(?P<unique_id>.+?)/.+?)(?:\?|#|$))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -109,7 +109,7 @@ class SouthParkDeIE(SouthParkIE): | |||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SouthParkLatIE(SouthParkIE): | class SouthParkLatIE(SouthParkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'southpark.lat' |     IE_NAME = 'southpark.lat' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?southpark\.lat/(?:en/)?(?:video-?clips?|collections|episod(?:e|io)s)/(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)?southpark\.lat/(?:en/)?(?:video-?clips?|collections|episod(?:e|io)s)/(?P<id>[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -152,7 +152,7 @@ class SouthParkLatIE(SouthParkIE): | |||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SouthParkNlIE(SouthParkIE): | class SouthParkNlIE(SouthParkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'southpark.nl' |     IE_NAME = 'southpark.nl' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.nl/(?:clips|(?:full-)?episodes|collections)/(?P<id>.+?)(\?|#|$))' |     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.nl/(?:clips|(?:full-)?episodes|collections)/(?P<id>.+?)(\?|#|$))' | ||||||
|     _FEED_URL = 'http://www.southpark.nl/feeds/video-player/mrss/' |     _FEED_URL = 'http://www.southpark.nl/feeds/video-player/mrss/' | ||||||
| @@ -167,7 +167,7 @@ class SouthParkNlIE(SouthParkIE): | |||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SouthParkDkIE(SouthParkIE): | class SouthParkDkIE(SouthParkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'southparkstudios.dk' |     IE_NAME = 'southparkstudios.dk' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?(?P<url>southparkstudios\.(?:dk|nu)/(?:clips|full-episodes|collections)/(?P<id>.+?)(\?|#|$))' |     _VALID_URL = r'https?://(?:www\.)?(?P<url>southparkstudios\.(?:dk|nu)/(?:clips|full-episodes|collections)/(?P<id>.+?)(\?|#|$))' | ||||||
|     _FEED_URL = 'http://www.southparkstudios.dk/feeds/video-player/mrss/' |     _FEED_URL = 'http://www.southparkstudios.dk/feeds/video-player/mrss/' | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Tele5IE(DPlayIE): | class Tele5IE(DPlayIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?tele5\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)?tele5\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)' | ||||||
|     _GEO_COUNTRIES = ['DE'] |     _GEO_COUNTRIES = ['DE'] | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TheWeatherChannelIE(ThePlatformIE): | class TheWeatherChannelIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?weather\.com(?P<asset_name>(?:/(?P<locale>[a-z]{2}-[A-Z]{2}))?/(?:[^/]+/)*video/(?P<id>[^/?#]+))' |     _VALID_URL = r'https?://(?:www\.)?weather\.com(?P<asset_name>(?:/(?P<locale>[a-z]{2}-[A-Z]{2}))?/(?:[^/]+/)*video/(?P<id>[^/?#]+))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://weather.com/series/great-outdoors/video/ice-climber-is-in-for-a-shock', |         'url': 'https://weather.com/series/great-outdoors/video/ice-climber-is-in-for-a-shock', | ||||||
|   | |||||||
| @@ -655,7 +655,7 @@ class TikTokUserIE(TikTokBaseIE): | |||||||
|         return self.playlist_result(self._entries_api(user_id, videos), user_id, user_name, thumbnail=thumbnail) |         return self.playlist_result(self._entries_api(user_id, videos), user_id, user_name, thumbnail=thumbnail) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TikTokBaseListIE(TikTokBaseIE): | class TikTokBaseListIE(TikTokBaseIE):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor | ||||||
|     def _entries(self, list_id, display_id): |     def _entries(self, list_id, display_id): | ||||||
|         query = { |         query = { | ||||||
|             self._QUERY_NAME: list_id, |             self._QUERY_NAME: list_id, | ||||||
| @@ -764,7 +764,7 @@ class TikTokTagIE(TikTokBaseListIE): | |||||||
|         return self.playlist_result(self._entries(tag_id, display_id), tag_id, display_id) |         return self.playlist_result(self._entries(tag_id, display_id), tag_id, display_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DouyinIE(TikTokIE): | class DouyinIE(TikTokIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?douyin\.com/video/(?P<id>[0-9]+)' |     _VALID_URL = r'https?://(?:www\.)?douyin\.com/video/(?P<id>[0-9]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.douyin.com/video/6961737553342991651', |         'url': 'https://www.douyin.com/video/6961737553342991651', | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TouTvIE(RadioCanadaIE): | class TouTvIE(RadioCanadaIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _NETRC_MACHINE = 'toutv' |     _NETRC_MACHINE = 'toutv' | ||||||
|     IE_NAME = 'tou.tv' |     IE_NAME = 'tou.tv' | ||||||
|     _VALID_URL = r'https?://ici\.tou\.tv/(?P<id>[a-zA-Z0-9_-]+(?:/S[0-9]+[EC][0-9]+)?)' |     _VALID_URL = r'https?://ici\.tou\.tv/(?P<id>[a-zA-Z0-9_-]+(?:/S[0-9]+[EC][0-9]+)?)' | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ from ..utils import ( | |||||||
| from .keezmovies import KeezMoviesIE | from .keezmovies import KeezMoviesIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Tube8IE(KeezMoviesIE): | class Tube8IE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?tube8\.com/(?:[^/]+/)+(?P<display_id>[^/]+)/(?P<id>\d+)' |     _VALID_URL = r'https?://(?:www\.)?tube8\.com/(?:[^/]+/)+(?P<display_id>[^/]+)/(?P<id>\d+)' | ||||||
|     _EMBED_REGEX = [r'<iframe[^>]+\bsrc=["\'](?P<url>(?:https?:)?//(?:www\.)?tube8\.com/embed/(?:[^/]+/)+\d+)'] |     _EMBED_REGEX = [r'<iframe[^>]+\bsrc=["\'](?P<url>(?:https?:)?//(?:www\.)?tube8\.com/embed/(?:[^/]+/)+\d+)'] | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -426,7 +426,7 @@ class TVNowIE(TVNowNewBaseIE): | |||||||
|         return self._extract_video(info, video_id, display_id) |         return self._extract_video(info, video_id, display_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TVNowFilmIE(TVNowIE): | class TVNowFilmIE(TVNowIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'''(?x) |     _VALID_URL = r'''(?x) | ||||||
|                     (?P<base_url>https?:// |                     (?P<base_url>https?:// | ||||||
|                         (?:www\.)?tvnow\.(?:de|at|ch)/ |                         (?:www\.)?tvnow\.(?:de|at|ch)/ | ||||||
|   | |||||||
| @@ -405,7 +405,7 @@ class UdemyIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class UdemyCourseIE(UdemyIE): | class UdemyCourseIE(UdemyIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'udemy:course' |     IE_NAME = 'udemy:course' | ||||||
|     _VALID_URL = r'https?://(?:[^/]+\.)?udemy\.com/(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:[^/]+\.)?udemy\.com/(?P<id>[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -52,10 +52,9 @@ class UplynkIE(InfoExtractor): | |||||||
|         return self._extract_uplynk_info(url) |         return self._extract_uplynk_info(url) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class UplynkPreplayIE(UplynkIE): | class UplynkPreplayIE(UplynkIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'uplynk:preplay' |     IE_NAME = 'uplynk:preplay' | ||||||
|     _VALID_URL = r'https?://.*?\.uplynk\.com/preplay2?/(?P<path>ext/[0-9a-f]{32}/(?P<external_id>[^/?&]+)|(?P<id>[0-9a-f]{32}))\.json' |     _VALID_URL = r'https?://.*?\.uplynk\.com/preplay2?/(?P<path>ext/[0-9a-f]{32}/(?P<external_id>[^/?&]+)|(?P<id>[0-9a-f]{32}))\.json' | ||||||
|     _TEST = None |  | ||||||
| 
 | 
 | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         path, external_id, video_id = self._match_valid_url(url).groups() |         path, external_id, video_id = self._match_valid_url(url).groups() | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| from .nbc import NBCIE | from .nbc import NBCIE | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class USANetworkIE(NBCIE): | class USANetworkIE(NBCIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?usanetwork\.com/(?:[^/]+/videos?|movies?)/(?:[^/]+/)?(?P<id>\d+))' |     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?usanetwork\.com/(?:[^/]+/videos?|movies?)/(?:[^/]+/)?(?P<id>\d+))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.usanetwork.com/peacock-trailers/video/intelligence-trailer/4185302', |         'url': 'https://www.usanetwork.com/peacock-trailers/video/intelligence-trailer/4185302', | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ class VeohIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VeohUserIE(VeohIE): | class VeohUserIE(VeohIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https?://(?:www\.)?veoh\.com/users/(?P<id>[\w-]+)' |     _VALID_URL = r'https?://(?:www\.)?veoh\.com/users/(?P<id>[\w-]+)' | ||||||
|     IE_NAME = 'veoh:user' |     IE_NAME = 'veoh:user' | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VGTVIE(XstreamIE): | class VGTVIE(XstreamIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_DESC = 'VGTV, BTTV, FTV, Aftenposten and Aftonbladet' |     IE_DESC = 'VGTV, BTTV, FTV, Aftenposten and Aftonbladet' | ||||||
|     _GEO_BYPASS = False |     _GEO_BYPASS = False | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -1004,7 +1004,7 @@ class VimeoIE(VimeoBaseInfoExtractor): | |||||||
|         return merge_dicts(info_dict, info_dict_config, json_ld) |         return merge_dicts(info_dict, info_dict_config, json_ld) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VimeoOndemandIE(VimeoIE): | class VimeoOndemandIE(VimeoIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'vimeo:ondemand' |     IE_NAME = 'vimeo:ondemand' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?vimeo\.com/ondemand/(?:[^/]+/)?(?P<id>[^/?#&]+)' |     _VALID_URL = r'https?://(?:www\.)?vimeo\.com/ondemand/(?:[^/]+/)?(?P<id>[^/?#&]+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -1129,7 +1129,7 @@ class VimeoChannelIE(VimeoBaseInfoExtractor): | |||||||
|         return self._extract_videos(channel_id, self._BASE_URL_TEMPL % channel_id) |         return self._extract_videos(channel_id, self._BASE_URL_TEMPL % channel_id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VimeoUserIE(VimeoChannelIE): | class VimeoUserIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'vimeo:user' |     IE_NAME = 'vimeo:user' | ||||||
|     _VALID_URL = r'https://vimeo\.com/(?!(?:[0-9]+|watchlater)(?:$|[?#/]))(?P<id>[^/]+)(?:/videos)?/?(?:$|[?#])' |     _VALID_URL = r'https://vimeo\.com/(?!(?:[0-9]+|watchlater)(?:$|[?#/]))(?P<id>[^/]+)(?:/videos)?/?(?:$|[?#])' | ||||||
|     _TITLE_RE = r'<a[^>]+?class="user">([^<>]+?)</a>' |     _TITLE_RE = r'<a[^>]+?class="user">([^<>]+?)</a>' | ||||||
| @@ -1239,7 +1239,7 @@ class VimeoAlbumIE(VimeoBaseInfoExtractor): | |||||||
|             entries, album_id, album.get('name'), album.get('description')) |             entries, album_id, album.get('name'), album.get('description')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VimeoGroupsIE(VimeoChannelIE): | class VimeoGroupsIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'vimeo:group' |     IE_NAME = 'vimeo:group' | ||||||
|     _VALID_URL = r'https://vimeo\.com/groups/(?P<id>[^/]+)(?:/(?!videos?/\d+)|$)' |     _VALID_URL = r'https://vimeo\.com/groups/(?P<id>[^/]+)(?:/(?!videos?/\d+)|$)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
| @@ -1331,7 +1331,7 @@ class VimeoReviewIE(VimeoBaseInfoExtractor): | |||||||
|         return info_dict |         return info_dict | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VimeoWatchLaterIE(VimeoChannelIE): | class VimeoWatchLaterIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE | ||||||
|     IE_NAME = 'vimeo:watchlater' |     IE_NAME = 'vimeo:watchlater' | ||||||
|     IE_DESC = 'Vimeo watch later list, ":vimeowatchlater" keyword (requires authentication)' |     IE_DESC = 'Vimeo watch later list, ":vimeowatchlater" keyword (requires authentication)' | ||||||
|     _VALID_URL = r'https://vimeo\.com/(?:home/)?watchlater|:vimeowatchlater' |     _VALID_URL = r'https://vimeo\.com/(?:home/)?watchlater|:vimeowatchlater' | ||||||
| @@ -1354,7 +1354,7 @@ class VimeoWatchLaterIE(VimeoChannelIE): | |||||||
|         return self._extract_videos('watchlater', 'https://vimeo.com/watchlater') |         return self._extract_videos('watchlater', 'https://vimeo.com/watchlater') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VimeoLikesIE(VimeoChannelIE): | class VimeoLikesIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'https://(?:www\.)?vimeo\.com/(?P<id>[^/]+)/likes/?(?:$|[?#]|sort:)' |     _VALID_URL = r'https://(?:www\.)?vimeo\.com/(?P<id>[^/]+)/likes/?(?:$|[?#]|sort:)' | ||||||
|     IE_NAME = 'vimeo:likes' |     IE_NAME = 'vimeo:likes' | ||||||
|     IE_DESC = 'Vimeo user likes' |     IE_DESC = 'Vimeo user likes' | ||||||
|   | |||||||
| @@ -242,7 +242,7 @@ class VVVVIDIE(InfoExtractor): | |||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class VVVVIDShowIE(VVVVIDIE): | class VVVVIDShowIE(VVVVIDIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _VALID_URL = r'(?P<base_url>%s(?P<id>\d+)(?:/(?P<show_title>[^/?&#]+))?)/?(?:[?#&]|$)' % VVVVIDIE._VALID_URL_BASE |     _VALID_URL = r'(?P<base_url>%s(?P<id>\d+)(?:/(?P<show_title>[^/?&#]+))?)/?(?:[?#&]|$)' % VVVVIDIE._VALID_URL_BASE | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'https://www.vvvvid.it/show/156/psyco-pass', |         'url': 'https://www.vvvvid.it/show/156/psyco-pass', | ||||||
|   | |||||||
| @@ -133,7 +133,7 @@ class WDRIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class WDRPageIE(WDRIE): | class WDRPageIE(WDRIE):  # XXX: Do not subclass from concrete IE | ||||||
|     _MAUS_REGEX = r'https?://(?:www\.)wdrmaus.de/(?:[^/]+/)*?(?P<maus_id>[^/?#.]+)(?:/?|/index\.php5|\.php5)$' |     _MAUS_REGEX = r'https?://(?:www\.)wdrmaus.de/(?:[^/]+/)*?(?P<maus_id>[^/?#.]+)(?:/?|/index\.php5|\.php5)$' | ||||||
|     _PAGE_REGEX = r'/(?:mediathek/)?(?:[^/]+/)*(?P<display_id>[^/]+)\.html' |     _PAGE_REGEX = r'/(?:mediathek/)?(?:[^/]+/)*(?P<display_id>[^/]+)\.html' | ||||||
|     _VALID_URL = r'https?://(?:www\d?\.)?(?:(?:kinder\.)?wdr\d?|sportschau)\.de' + _PAGE_REGEX + '|' + _MAUS_REGEX |     _VALID_URL = r'https?://(?:www\d?\.)?(?:(?:kinder\.)?wdr\d?|sportschau)\.de' + _PAGE_REGEX + '|' + _MAUS_REGEX | ||||||
|   | |||||||
| @@ -1051,7 +1051,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|             <a\s[^>]*\bhref="(?P<url>https://www\.youtube\.com/watch\?v=[0-9A-Za-z_-]{11})" |             <a\s[^>]*\bhref="(?P<url>https://www\.youtube\.com/watch\?v=[0-9A-Za-z_-]{11})" | ||||||
|             \s[^>]*\bclass="[^"]*\blazy-load-youtube''', |             \s[^>]*\bclass="[^"]*\blazy-load-youtube''', | ||||||
|     ] |     ] | ||||||
|     _RETURN_TYPE = 'video'  # While there are "multifeed" test cases, they don't seem to actually exist anymore |     _RETURN_TYPE = 'video'  # XXX: How to handle multifeed? | ||||||
| 
 | 
 | ||||||
|     _PLAYER_INFO_RE = ( |     _PLAYER_INFO_RE = ( | ||||||
|         r'/s/player/(?P<id>[a-zA-Z0-9_-]{8,})/player', |         r'/s/player/(?P<id>[a-zA-Z0-9_-]{8,})/player', | ||||||
| @@ -1582,66 +1582,99 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|             'skip': 'This live event has ended.', |             'skip': 'This live event has ended.', | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             # Multifeed videos (multiple cameras), URL is for Main Camera |             # Multifeed videos (multiple cameras), URL can be of any Camera | ||||||
|             'url': 'https://www.youtube.com/watch?v=jvGDaLqkpTg', |             'url': 'https://www.youtube.com/watch?v=zaPI8MvL8pg', | ||||||
|             'info_dict': { |             'info_dict': { | ||||||
|                 'id': 'jvGDaLqkpTg', |                 'id': 'zaPI8MvL8pg', | ||||||
|                 'title': 'Tom Clancy Free Weekend Rainbow Whatever', |                 'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04', | ||||||
|                 'description': 'md5:e03b909557865076822aa169218d6a5d', |                 'description': 'md5:563ccbc698b39298481ca3c571169519', | ||||||
|             }, |             }, | ||||||
|             'playlist': [{ |             'playlist': [{ | ||||||
|                 'info_dict': { |                 'info_dict': { | ||||||
|                     'id': 'jvGDaLqkpTg', |                     'id': 'j5yGuxZ8lLU', | ||||||
|                     'ext': 'mp4', |                     'ext': 'mp4', | ||||||
|                     'title': 'Tom Clancy Free Weekend Rainbow Whatever (Main Camera)', |                     'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Chris)', | ||||||
|                     'description': 'md5:e03b909557865076822aa169218d6a5d', |                     'uploader': 'WiiLikeToPlay', | ||||||
|                     'duration': 10643, |                     'description': 'md5:563ccbc698b39298481ca3c571169519', | ||||||
|                     'upload_date': '20161111', |                     'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray', | ||||||
|                     'uploader': 'Team PGP', |                     'duration': 10120, | ||||||
|                     'uploader_id': 'UChORY56LMMETTuGjXaJXvLg', |                     'channel_follower_count': int, | ||||||
|                     'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg', |                     'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg', | ||||||
|  |                     'availability': 'public', | ||||||
|  |                     'playable_in_embed': True, | ||||||
|  |                     'upload_date': '20131105', | ||||||
|  |                     'uploader_id': 'WiiRikeToPray', | ||||||
|  |                     'categories': ['Gaming'], | ||||||
|  |                     'live_status': 'was_live', | ||||||
|  |                     'tags': 'count:24', | ||||||
|  |                     'release_timestamp': 1383701910, | ||||||
|  |                     'thumbnail': 'https://i.ytimg.com/vi/j5yGuxZ8lLU/maxresdefault.jpg', | ||||||
|  |                     'comment_count': int, | ||||||
|  |                     'age_limit': 0, | ||||||
|  |                     'like_count': int, | ||||||
|  |                     'channel_id': 'UCN2XePorRokPB9TEgRZpddg', | ||||||
|  |                     'channel': 'WiiLikeToPlay', | ||||||
|  |                     'view_count': int, | ||||||
|  |                     'release_date': '20131106', | ||||||
|                 }, |                 }, | ||||||
|             }, { |             }, { | ||||||
|                 'info_dict': { |                 'info_dict': { | ||||||
|                     'id': '3AKt1R1aDnw', |                     'id': 'zaPI8MvL8pg', | ||||||
|                     'ext': 'mp4', |                     'ext': 'mp4', | ||||||
|                     'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 2)', |                     'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Tyson)', | ||||||
|                     'description': 'md5:e03b909557865076822aa169218d6a5d', |                     'uploader_id': 'WiiRikeToPray', | ||||||
|                     'duration': 10991, |                     'availability': 'public', | ||||||
|                     'upload_date': '20161111', |                     'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg', | ||||||
|                     'uploader': 'Team PGP', |                     'channel': 'WiiLikeToPlay', | ||||||
|                     'uploader_id': 'UChORY56LMMETTuGjXaJXvLg', |                     'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray', | ||||||
|                     'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg', |                     'channel_follower_count': int, | ||||||
|  |                     'description': 'md5:563ccbc698b39298481ca3c571169519', | ||||||
|  |                     'duration': 10108, | ||||||
|  |                     'age_limit': 0, | ||||||
|  |                     'like_count': int, | ||||||
|  |                     'tags': 'count:24', | ||||||
|  |                     'channel_id': 'UCN2XePorRokPB9TEgRZpddg', | ||||||
|  |                     'uploader': 'WiiLikeToPlay', | ||||||
|  |                     'release_timestamp': 1383701915, | ||||||
|  |                     'comment_count': int, | ||||||
|  |                     'upload_date': '20131105', | ||||||
|  |                     'thumbnail': 'https://i.ytimg.com/vi/zaPI8MvL8pg/maxresdefault.jpg', | ||||||
|  |                     'release_date': '20131106', | ||||||
|  |                     'playable_in_embed': True, | ||||||
|  |                     'live_status': 'was_live', | ||||||
|  |                     'categories': ['Gaming'], | ||||||
|  |                     'view_count': int, | ||||||
|                 }, |                 }, | ||||||
|             }, { |             }, { | ||||||
|                 'info_dict': { |                 'info_dict': { | ||||||
|                     'id': 'RtAMM00gpVc', |                     'id': 'R7r3vfO7Hao', | ||||||
|                     'ext': 'mp4', |                     'ext': 'mp4', | ||||||
|                     'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 3)', |                     'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Spencer)', | ||||||
|                     'description': 'md5:e03b909557865076822aa169218d6a5d', |                     'thumbnail': 'https://i.ytimg.com/vi/R7r3vfO7Hao/maxresdefault.jpg', | ||||||
|                     'duration': 10995, |                     'channel_id': 'UCN2XePorRokPB9TEgRZpddg', | ||||||
|                     'upload_date': '20161111', |                     'like_count': int, | ||||||
|                     'uploader': 'Team PGP', |                     'availability': 'public', | ||||||
|                     'uploader_id': 'UChORY56LMMETTuGjXaJXvLg', |                     'playable_in_embed': True, | ||||||
|                     'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg', |                     'upload_date': '20131105', | ||||||
|                 }, |                     'description': 'md5:563ccbc698b39298481ca3c571169519', | ||||||
|             }, { |                     'uploader_id': 'WiiRikeToPray', | ||||||
|                 'info_dict': { |                     'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray', | ||||||
|                     'id': '6N2fdlP3C5U', |                     'channel_follower_count': int, | ||||||
|                     'ext': 'mp4', |                     'tags': 'count:24', | ||||||
|                     'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 4)', |                     'release_date': '20131106', | ||||||
|                     'description': 'md5:e03b909557865076822aa169218d6a5d', |                     'uploader': 'WiiLikeToPlay', | ||||||
|                     'duration': 10990, |                     'comment_count': int, | ||||||
|                     'upload_date': '20161111', |                     'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg', | ||||||
|                     'uploader': 'Team PGP', |                     'channel': 'WiiLikeToPlay', | ||||||
|                     'uploader_id': 'UChORY56LMMETTuGjXaJXvLg', |                     'categories': ['Gaming'], | ||||||
|                     'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg', |                     'release_timestamp': 1383701914, | ||||||
|  |                     'live_status': 'was_live', | ||||||
|  |                     'age_limit': 0, | ||||||
|  |                     'duration': 10128, | ||||||
|  |                     'view_count': int, | ||||||
|                 }, |                 }, | ||||||
|             }], |             }], | ||||||
|             'params': { |             'params': {'skip_download': True}, | ||||||
|                 'skip_download': True, |  | ||||||
|             }, |  | ||||||
|             'skip': 'Not multifeed anymore', |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             # Multifeed video with comma in title (see https://github.com/ytdl-org/youtube-dl/issues/8536) |             # Multifeed video with comma in title (see https://github.com/ytdl-org/youtube-dl/issues/8536) | ||||||
|   | |||||||
| @@ -5839,7 +5839,7 @@ def cached_method(f): | |||||||
|         bound_args.apply_defaults() |         bound_args.apply_defaults() | ||||||
|         key = tuple(bound_args.arguments.values())[1:] |         key = tuple(bound_args.arguments.values())[1:] | ||||||
| 
 | 
 | ||||||
|         cache = vars(self).setdefault('__cached_method__cache', {}).setdefault(f.__name__, {}) |         cache = vars(self).setdefault('_cached_method__cache', {}).setdefault(f.__name__, {}) | ||||||
|         if key not in cache: |         if key not in cache: | ||||||
|             cache[key] = f(self, *args, **kwargs) |             cache[key] = f(self, *args, **kwargs) | ||||||
|         return cache[key] |         return cache[key] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 pukkandan
					pukkandan