mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-22 02:15:12 +00:00
parent
a4894d3e25
commit
6368e2e639
75 changed files with 194 additions and 156 deletions
|
@ -10,7 +10,7 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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 @@
|
||||||
|
|
||||||
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 @@ def check_filter():
|
||||||
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 @@ def process_info(self, info_dict):
|
||||||
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 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def is_logged(webpage):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 ..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 ..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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def extract_formats(self, play_info):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 ..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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
'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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@
|
||||||
# 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 @@ def _apply_first_set_cookie_header(self, url_handle, cookie):
|
||||||
|
|
||||||
@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 @@ def get_testcases(cls, include_onlymatching=False):
|
||||||
|
|
||||||
@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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 .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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def get_flashvar(x, *args, **kwargs):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 .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 @@ def _real_extract(self, url):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 .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 @@ def _get_feed_query(self, uri):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _extract_embed(self, webpage, display_id, url=None):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _fetch_description(self, page):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _get_feed_url(self, uri, url=None):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _get_subtitles(self, video_id, sub_file):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _get_feed_query(self, uri):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _get_feed_query(self, uri):
|
||||||
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 @@ def _get_feed_query(self, uri):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 .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 @@ def _real_extract(self, url):
|
||||||
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 @@ def extract_subtitles(track_list):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 @@ def is_rented():
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
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 @@ def metadata_from_url(r_url):
|
||||||
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 @@ def _real_extract(self, url):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 wrapper(self, *args, **kwargs):
|
||||||
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]
|
||||||
|
|
Loading…
Reference in a new issue