mirror of
https://github.com/ytdl-org/youtube-dl
synced 2025-01-01 00:50:09 +09:00
Compare commits
9 Commits
249131afc9
...
a7b6079150
Author | SHA1 | Date | |
---|---|---|---|
|
a7b6079150 | ||
|
c5098961b0 | ||
|
dbc08fba83 | ||
|
71223bff39 | ||
|
44f73880fe | ||
|
81d6b10f48 | ||
|
1cd4bb0d82 | ||
|
2fe0d70b6e | ||
|
76f2b63a26 |
@ -425,6 +425,34 @@ class TestJSInterpreter(unittest.TestCase):
|
||||
self._test(jsi, [''], args=['', '-'])
|
||||
self._test(jsi, [], args=['', ''])
|
||||
|
||||
def test_slice(self):
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice()}', [0, 1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(0)}', [0, 1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(5)}', [5, 6, 7, 8])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(99)}', [])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(-2)}', [7, 8])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(-99)}', [0, 1, 2, 3, 4, 5, 6, 7, 8])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(0, 0)}', [])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(1, 0)}', [])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(0, 1)}', [0])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(3, 6)}', [3, 4, 5])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(1, -1)}', [1, 2, 3, 4, 5, 6, 7])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(-1, 1)}', [])
|
||||
self._test('function f(){return [0, 1, 2, 3, 4, 5, 6, 7, 8].slice(-3, -1)}', [6, 7])
|
||||
self._test('function f(){return "012345678".slice()}', '012345678')
|
||||
self._test('function f(){return "012345678".slice(0)}', '012345678')
|
||||
self._test('function f(){return "012345678".slice(5)}', '5678')
|
||||
self._test('function f(){return "012345678".slice(99)}', '')
|
||||
self._test('function f(){return "012345678".slice(-2)}', '78')
|
||||
self._test('function f(){return "012345678".slice(-99)}', '012345678')
|
||||
self._test('function f(){return "012345678".slice(0, 0)}', '')
|
||||
self._test('function f(){return "012345678".slice(1, 0)}', '')
|
||||
self._test('function f(){return "012345678".slice(0, 1)}', '0')
|
||||
self._test('function f(){return "012345678".slice(3, 6)}', '345')
|
||||
self._test('function f(){return "012345678".slice(1, -1)}', '1234567')
|
||||
self._test('function f(){return "012345678".slice(-1, 1)}', '')
|
||||
self._test('function f(){return "012345678".slice(-3, -1)}', '67')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -174,6 +174,14 @@ _NSIG_TESTS = [
|
||||
'https://www.youtube.com/s/player/5604538d/player_ias.vflset/en_US/base.js',
|
||||
'7X-he4jjvMx7BCX', 'sViSydX8IHtdWA',
|
||||
),
|
||||
(
|
||||
'https://www.youtube.com/s/player/20dfca59/player_ias.vflset/en_US/base.js',
|
||||
'-fLCxedkAk4LUTK2', 'O8kfRq1y1eyHGw',
|
||||
),
|
||||
(
|
||||
'https://www.youtube.com/s/player/b12cc44b/player_ias.vflset/en_US/base.js',
|
||||
'keLa5R2U00sR9SQK', 'N1OGyujjEwMnLw',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -157,7 +157,7 @@ class MTVServicesInfoExtractor(InfoExtractor):
|
||||
|
||||
description = strip_or_none(xpath_text(itemdoc, 'description'))
|
||||
|
||||
timestamp = timeconvert(xpath_text(itemdoc, 'pubDate'))
|
||||
timestamp = timeconvert(xpath_text(itemdoc, 'pubDate') or xpath_text(itemdoc, 'airDate'))
|
||||
|
||||
title_el = None
|
||||
if title_el is None:
|
||||
@ -290,7 +290,17 @@ class MTVServicesInfoExtractor(InfoExtractor):
|
||||
main_container = self._extract_child_with_type(data, 'MainContainer')
|
||||
ab_testing = self._extract_child_with_type(main_container, 'ABTesting')
|
||||
video_player = self._extract_child_with_type(ab_testing or main_container, 'VideoPlayer')
|
||||
mgid = video_player['props']['media']['video']['config']['uri']
|
||||
if video_player:
|
||||
mgid = video_player['props']['media']['video']['config']['uri']
|
||||
else:
|
||||
flex_wrapper = self._extract_child_with_type(ab_testing or main_container, 'FlexWrapper')
|
||||
auth_suite_wrapper = self._extract_child_with_type(flex_wrapper, 'AuthSuiteWrapper')
|
||||
player = self._extract_child_with_type(auth_suite_wrapper or flex_wrapper, 'Player')
|
||||
if player:
|
||||
mgid = player['props']['videoDetail']['mgid']
|
||||
|
||||
if not mgid:
|
||||
raise ExtractorError('Could not extract mgid')
|
||||
|
||||
return mgid
|
||||
|
||||
|
@ -6,19 +6,19 @@ from .mtv import MTVServicesInfoExtractor
|
||||
|
||||
class SouthParkIE(MTVServicesInfoExtractor):
|
||||
IE_NAME = 'southpark.cc.com'
|
||||
_VALID_URL = r'https?://(?:www\.)?(?P<url>southpark(?:\.cc|studios)\.com/(?:clips|(?:full-)?episodes|collections)/(?P<id>.+?)(\?|#|$))'
|
||||
_VALID_URL = r'https?://(?:www\.)?(?P<url>southpark(?:\.cc|studios)\.com/((?:video-)?clips|(?:full-)?episodes|collections)/(?P<id>.+?)(\?|#|$))'
|
||||
|
||||
_FEED_URL = 'http://feeds.mtvnservices.com/od/feed/intl-mrss-player-feed'
|
||||
|
||||
_TESTS = [{
|
||||
'url': 'http://southpark.cc.com/clips/104437/bat-daded#tab=featured',
|
||||
'url': 'https://southpark.cc.com/video-clips/d7wr06/south-park-you-all-agreed-to-counseling',
|
||||
'info_dict': {
|
||||
'id': 'a7bff6c2-ed00-11e0-aca6-0026b9414f30',
|
||||
'id': '31929ad5-8269-11eb-8774-70df2f866ace',
|
||||
'ext': 'mp4',
|
||||
'title': 'South Park|Bat Daded',
|
||||
'description': 'Randy disqualifies South Park by getting into a fight with Bat Dad.',
|
||||
'timestamp': 1112760000,
|
||||
'upload_date': '20050406',
|
||||
'title': 'You All Agreed to Counseling',
|
||||
'description': 'Kenny, Cartman, Stan, and Kyle visit Mr. Mackey and ask for his help getting Mrs. Nelson to come back. Mr. Mackey reveals the only way to get things back to normal is to get the teachers vaccinated.',
|
||||
'timestamp': 1615377600,
|
||||
'upload_date': '20210310',
|
||||
},
|
||||
}, {
|
||||
'url': 'http://southpark.cc.com/collections/7758/fan-favorites/1',
|
||||
@ -40,11 +40,11 @@ class SouthParkIE(MTVServicesInfoExtractor):
|
||||
|
||||
class SouthParkEsIE(SouthParkIE):
|
||||
IE_NAME = 'southpark.cc.com:español'
|
||||
_VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.cc\.com/episodios-en-espanol/(?P<id>.+?)(\?|#|$))'
|
||||
_VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.cc\.com/es/episodios/(?P<id>.+?)(\?|#|$))'
|
||||
_LANG = 'es'
|
||||
|
||||
_TESTS = [{
|
||||
'url': 'http://southpark.cc.com/episodios-en-espanol/s01e01-cartman-consigue-una-sonda-anal#source=351c1323-0b96-402d-a8b9-40d01b2e9bde&position=1&sort=!airdate',
|
||||
'url': 'http://southpark.cc.com/es/episodios/s01e01-cartman-consigue-una-sonda-anal#source=351c1323-0b96-402d-a8b9-40d01b2e9bde&position=1&sort=!airdate',
|
||||
'info_dict': {
|
||||
'title': 'Cartman Consigue Una Sonda Anal',
|
||||
'description': 'Cartman Consigue Una Sonda Anal',
|
||||
@ -69,6 +69,7 @@ class SouthParkDeIE(SouthParkIE):
|
||||
'timestamp': 1380160800,
|
||||
'upload_date': '20130926',
|
||||
},
|
||||
'skip': 'Geo-restricted',
|
||||
}, {
|
||||
# non-ASCII characters in initial URL
|
||||
'url': 'http://www.southpark.de/alle-episoden/s18e09-hashtag-aufwärmen',
|
||||
@ -77,6 +78,7 @@ class SouthParkDeIE(SouthParkIE):
|
||||
'description': 'Kyle will mit seinem kleinen Bruder Ike Videospiele spielen. Als der nicht mehr mit ihm spielen will, hat Kyle Angst, dass er die Kids von heute nicht mehr versteht.',
|
||||
},
|
||||
'playlist_count': 3,
|
||||
'skip': 'Geo-restricted',
|
||||
}, {
|
||||
# non-ASCII characters in redirect URL
|
||||
'url': 'http://www.southpark.de/alle-episoden/s18e09',
|
||||
@ -85,6 +87,7 @@ class SouthParkDeIE(SouthParkIE):
|
||||
'description': 'Kyle will mit seinem kleinen Bruder Ike Videospiele spielen. Als der nicht mehr mit ihm spielen will, hat Kyle Angst, dass er die Kids von heute nicht mehr versteht.',
|
||||
},
|
||||
'playlist_count': 3,
|
||||
'skip': 'Geo-restricted',
|
||||
}, {
|
||||
'url': 'http://www.southpark.de/collections/2476/superhero-showdown/1',
|
||||
'only_matching': True,
|
||||
@ -103,6 +106,7 @@ class SouthParkNlIE(SouthParkIE):
|
||||
'description': 'Stan is addicted to the new Terrance and Phillip mobile game.',
|
||||
},
|
||||
'playlist_mincount': 3,
|
||||
'skip': 'Geo-restricted',
|
||||
}]
|
||||
|
||||
|
||||
@ -118,6 +122,7 @@ class SouthParkDkIE(SouthParkIE):
|
||||
'description': 'Butters is convinced he\'s living in a virtual reality.',
|
||||
},
|
||||
'playlist_mincount': 3,
|
||||
'skip': 'Geo-restricted',
|
||||
}, {
|
||||
'url': 'http://www.southparkstudios.dk/collections/2476/superhero-showdown/1',
|
||||
'only_matching': True,
|
||||
|
@ -1659,17 +1659,46 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
||||
def _extract_n_function_name(self, jscode):
|
||||
func_name, idx = self._search_regex(
|
||||
# new: (b=String.fromCharCode(110),c=a.get(b))&&c=nfunc[idx](c)
|
||||
# or: (b="nn"[+a.D],c=a.get(b))&&(c=nfunc[idx](c)s
|
||||
# old: .get("n"))&&(b=nfunc[idx](b)
|
||||
# older: .get("n"))&&(b=nfunc(b)
|
||||
# or: (b="nn"[+a.D],c=a.get(b))&&(c=nfunc[idx](c)
|
||||
# or: (PL(a),b=a.j.n||null)&&(b=nfunc[idx](b)
|
||||
# or: (b="nn"[+a.D],vL(a),c=a.j[b]||null)&&(c=narray[idx](c),a.set(b,c),narray.length||nfunc("")
|
||||
# old: (b=a.get("n"))&&(b=nfunc[idx](b)(?P<c>[a-z])\s*=\s*[a-z]\s*
|
||||
# older: (b=a.get("n"))&&(b=nfunc(b)
|
||||
r'''(?x)
|
||||
(?:\(\s*(?P<b>[a-z])\s*=\s*(?:
|
||||
String\s*\.\s*fromCharCode\s*\(\s*110\s*\)|
|
||||
"n+"\[\s*\+?s*[\w$.]+\s*]
|
||||
)\s*,(?P<c>[a-z])\s*=\s*[a-z]\s*)?
|
||||
\.\s*get\s*\(\s*(?(b)(?P=b)|"n{1,2}")(?:\s*\)){2}\s*&&\s*\(\s*(?(c)(?P=c)|b)\s*=\s*
|
||||
(?P<nfunc>[a-zA-Z_$][\w$]*)(?:\s*\[(?P<idx>\d+)\])?\s*\(\s*[\w$]+\s*\)
|
||||
''', jscode, 'Initial JS player n function name', group=('nfunc', 'idx'))
|
||||
\((?:[\w$()\s]+,)*?\s* # (
|
||||
(?P<b>[a-z])\s*=\s* # b=
|
||||
(?:
|
||||
(?: # expect ,c=a.get(b) (etc)
|
||||
String\s*\.\s*fromCharCode\s*\(\s*110\s*\)|
|
||||
"n+"\[\s*\+?s*[\w$.]+\s*]
|
||||
)\s*(?:,[\w$()\s]+(?=,))*|
|
||||
(?P<old>[\w$]+) # a (old[er])
|
||||
)\s*
|
||||
(?(old)
|
||||
# b.get("n")
|
||||
(?:\.\s*[\w$]+\s*|\[\s*[\w$]+\s*]\s*)*?
|
||||
(?:\.\s*n|\[\s*"n"\s*]|\.\s*get\s*\(\s*"n"\s*\))
|
||||
| # ,c=a.get(b)
|
||||
,\s*(?P<c>[a-z])\s*=\s*[a-z]\s*
|
||||
(?:\.\s*[\w$]+\s*|\[\s*[\w$]+\s*]\s*)*?
|
||||
(?:\[\s*(?P=b)\s*]|\.\s*get\s*\(\s*(?P=b)\s*\))
|
||||
)
|
||||
# interstitial junk
|
||||
\s*(?:\|\|\s*null\s*)?(?:\)\s*)?&&\s*(?:\(\s*)?
|
||||
(?(c)(?P=c)|(?P=b))\s*=\s* # [c|b]=
|
||||
# nfunc|nfunc[idx]
|
||||
(?P<nfunc>[a-zA-Z_$][\w$]*)(?:\s*\[(?P<idx>\d+)\])?\s*\(\s*[\w$]+\s*\)
|
||||
''', jscode, 'Initial JS player n function name', group=('nfunc', 'idx'),
|
||||
default=(None, None))
|
||||
# thx bashonly: yt-dlp/yt-dlp/pull/10611
|
||||
if not func_name:
|
||||
self.report_warning('Falling back to generic n function search')
|
||||
return self._search_regex(
|
||||
r'''(?xs)
|
||||
(?:(?<=[^\w$])|^) # instead of \b, which ignores $
|
||||
(?P<name>(?!\d)[a-zA-Z\d_$]+)\s*=\s*function\((?!\d)[a-zA-Z\d_$]+\)
|
||||
\s*\{(?:(?!};).)+?["']enhanced_except_
|
||||
''', jscode, 'Initial JS player n function name', group='name')
|
||||
if not idx:
|
||||
return func_name
|
||||
|
||||
|
@ -925,9 +925,16 @@ class JSInterpreter(object):
|
||||
obj.reverse()
|
||||
return obj
|
||||
elif member == 'slice':
|
||||
assertion(isinstance(obj, list), 'must be applied on a list')
|
||||
assertion(len(argvals) == 1, 'takes exactly one argument')
|
||||
return obj[argvals[0]:]
|
||||
assertion(isinstance(obj, (list, compat_str)), 'must be applied on a list or string')
|
||||
# From [1]:
|
||||
# .slice() - like [:]
|
||||
# .slice(n) - like [n:] (not [slice(n)]
|
||||
# .slice(m, n) - like [m:n] or [slice(m, n)]
|
||||
# [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
|
||||
assertion(len(argvals) <= 2, 'takes between 0 and 2 arguments')
|
||||
if len(argvals) < 2:
|
||||
argvals += (None,)
|
||||
return obj[slice(*argvals)]
|
||||
elif member == 'splice':
|
||||
assertion(isinstance(obj, list), 'must be applied on a list')
|
||||
assertion(argvals, 'takes one or more arguments')
|
||||
|
@ -2079,7 +2079,7 @@ def timeconvert(timestr):
|
||||
timetuple = email.utils.parsedate_tz(timestr)
|
||||
if timetuple is not None:
|
||||
timestamp = email.utils.mktime_tz(timetuple)
|
||||
return timestamp
|
||||
return int(timestamp) if timestamp is not None else timestamp
|
||||
|
||||
|
||||
def sanitize_filename(s, restricted=False, is_id=False):
|
||||
|
Loading…
Reference in New Issue
Block a user