From df5478464cde9ccd55331acb878209984dbd568b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rog=C3=A9rio=20Brito?= Date: Wed, 26 Jun 2013 00:26:03 -0300 Subject: [PATCH] Imported Upstream version 2013.06.33 --- README.md | 1 + README.txt | 1 + devscripts/release.sh | 4 +- test/test_download.py | 20 +- test/test_write_info_json.py | 12 +- test/test_youtube_lists.py | 22 +- test/test_youtube_subtitles.py | 22 +- test/tests.json | 46 ++ youtube-dl | Bin 112794 -> 117178 bytes youtube-dl.1 | 1 + youtube-dl.bash-completion | 2 +- youtube_dl/FileDownloader.py | 542 +-------------------- youtube_dl/YoutubeDL.py | 596 ++++++++++++++++++++++++ youtube_dl/__init__.py | 45 +- youtube_dl/extractor/__init__.py | 13 +- youtube_dl/extractor/common.py | 2 +- youtube_dl/extractor/googleplus.py | 10 +- youtube_dl/extractor/jukebox.py | 56 +++ youtube_dl/extractor/mtv.py | 8 + youtube_dl/extractor/tudou.py | 32 ++ youtube_dl/extractor/vevo.py | 44 ++ youtube_dl/extractor/vimeo.py | 4 +- youtube_dl/extractor/worldstarhiphop.py | 4 + youtube_dl/extractor/youtube.py | 19 +- youtube_dl/utils.py | 2 +- youtube_dl/version.py | 2 +- 26 files changed, 905 insertions(+), 605 deletions(-) create mode 100644 youtube_dl/YoutubeDL.py create mode 100644 youtube_dl/extractor/jukebox.py create mode 100644 youtube_dl/extractor/tudou.py create mode 100644 youtube_dl/extractor/vevo.py diff --git a/README.md b/README.md index 929f2b5..7d19024 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ which means you can modify it, redistribute it or use it however you like. -u, --username USERNAME account username -p, --password PASSWORD account password -n, --netrc use .netrc authentication data + --video-password PASSWORD video password (vimeo only) ## Post-processing Options: -x, --extract-audio convert video files to audio-only files (requires diff --git a/README.txt b/README.txt index b58f682..56e2512 100644 --- a/README.txt +++ b/README.txt @@ -147,6 +147,7 @@ Authentication Options: -u, --username USERNAME account username -p, --password PASSWORD account password -n, --netrc use .netrc authentication data + --video-password PASSWORD video password (vimeo only) Post-processing Options: ------------------------ diff --git a/devscripts/release.sh b/devscripts/release.sh index d32ae47..46c31e4 100755 --- a/devscripts/release.sh +++ b/devscripts/release.sh @@ -69,7 +69,9 @@ git checkout HEAD -- youtube-dl youtube-dl.exe /bin/echo -e "\n### Signing and uploading the new binaries to youtube-dl.org..." for f in $RELEASE_FILES; do gpg --detach-sig "build/$version/$f"; done -scp -r "build/$version" ytdl@youtube-dl.org:html/downloads/ +scp -r "build/$version" ytdl@yt-dl.org:html/tmp/ +ssh ytdl@yt-dl.org "mv html/tmp/$version html/downloads/" +ssh ytdl@yt-dl.org "sh html/update_latest.sh $version" /bin/echo -e "\n### Now switching to gh-pages..." git clone --branch gh-pages --single-branch . build/gh-pages diff --git a/test/test_download.py b/test/test_download.py index 8d86984..067bde4 100644 --- a/test/test_download.py +++ b/test/test_download.py @@ -13,7 +13,7 @@ import binascii # Allow direct execution sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import youtube_dl.FileDownloader +import youtube_dl.YoutubeDL import youtube_dl.extractor from youtube_dl.utils import * @@ -40,17 +40,17 @@ def _try_rm(filename): md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest() -class FileDownloader(youtube_dl.FileDownloader): +class YoutubeDL(youtube_dl.YoutubeDL): def __init__(self, *args, **kwargs): self.to_stderr = self.to_screen self.processed_info_dicts = [] - return youtube_dl.FileDownloader.__init__(self, *args, **kwargs) + super(YoutubeDL, self).__init__(*args, **kwargs) def report_warning(self, message): # Don't accept warnings during tests raise ExtractorError(message) def process_info(self, info_dict): self.processed_info_dicts.append(info_dict) - return youtube_dl.FileDownloader.process_info(self, info_dict) + return super(YoutubeDL, self).process_info(info_dict) def _file_md5(fn): with open(fn, 'rb') as f: @@ -86,14 +86,14 @@ def generator(test_case): params = self.parameters.copy() params.update(test_case.get('params', {})) - fd = FileDownloader(params) + ydl = YoutubeDL(params) for ie in youtube_dl.extractor.gen_extractors(): - fd.add_info_extractor(ie) + ydl.add_info_extractor(ie) finished_hook_called = set() def _hook(status): if status['status'] == 'finished': finished_hook_called.add(status['filename']) - fd.add_progress_hook(_hook) + ydl.fd.add_progress_hook(_hook) test_cases = test_case.get('playlist', [test_case]) for tc in test_cases: @@ -103,7 +103,7 @@ def generator(test_case): try: for retry in range(1, RETRIES + 1): try: - fd.download([test_case['url']]) + ydl.download([test_case['url']]) except (DownloadError, ExtractorError) as err: if retry == RETRIES: raise @@ -153,9 +153,11 @@ def generator(test_case): return test_template ### And add them to TestDownload -for test_case in defs: +for n, test_case in enumerate(defs): test_method = generator(test_case) test_method.__name__ = "test_{0}".format(test_case["name"]) + if getattr(TestDownload, test_method.__name__, False): + test_method.__name__ = "test_{0}_{1}".format(test_case["name"], n) setattr(TestDownload, test_method.__name__, test_method) del test_method diff --git a/test/test_write_info_json.py b/test/test_write_info_json.py index b5eca76..de6d518 100644 --- a/test/test_write_info_json.py +++ b/test/test_write_info_json.py @@ -9,7 +9,7 @@ import unittest # Allow direct execution sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import youtube_dl.FileDownloader +import youtube_dl.YoutubeDL import youtube_dl.extractor from youtube_dl.utils import * @@ -22,9 +22,9 @@ proxy_handler = compat_urllib_request.ProxyHandler() opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler()) compat_urllib_request.install_opener(opener) -class FileDownloader(youtube_dl.FileDownloader): +class YoutubeDL(youtube_dl.YoutubeDL): def __init__(self, *args, **kwargs): - youtube_dl.FileDownloader.__init__(self, *args, **kwargs) + super(YoutubeDL, self).__init__(*args, **kwargs) self.to_stderr = self.to_screen with io.open(PARAMETERS_FILE, encoding='utf-8') as pf: @@ -49,9 +49,9 @@ class TestInfoJSON(unittest.TestCase): def test_info_json(self): ie = youtube_dl.extractor.YoutubeIE() - fd = FileDownloader(params) - fd.add_info_extractor(ie) - fd.download([TEST_ID]) + ydl = YoutubeDL(params) + ydl.add_info_extractor(ie) + ydl.download([TEST_ID]) self.assertTrue(os.path.exists(INFO_JSON_FILE)) with io.open(INFO_JSON_FILE, 'r', encoding='utf-8') as jsonf: jd = json.load(jsonf) diff --git a/test/test_youtube_lists.py b/test/test_youtube_lists.py index 2c46edf..320b440 100644 --- a/test/test_youtube_lists.py +++ b/test/test_youtube_lists.py @@ -10,7 +10,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from youtube_dl.extractor import YoutubeUserIE, YoutubePlaylistIE, YoutubeIE, YoutubeChannelIE from youtube_dl.utils import * -from youtube_dl.FileDownloader import FileDownloader +from youtube_dl import YoutubeDL PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json") with io.open(PARAMETERS_FILE, encoding='utf-8') as pf: @@ -23,7 +23,7 @@ proxy_handler = compat_urllib_request.ProxyHandler() opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler()) compat_urllib_request.install_opener(opener) -class FakeDownloader(FileDownloader): +class FakeYDL(YoutubeDL): def __init__(self): self.result = [] self.params = parameters @@ -41,7 +41,7 @@ class TestYoutubeLists(unittest.TestCase): self.assertEqual(info['_type'], 'playlist') def test_youtube_playlist(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re')[0] self.assertIsPlaylist(result) @@ -50,13 +50,13 @@ class TestYoutubeLists(unittest.TestCase): self.assertEqual(ytie_results, [ 'bV9L5Ht9LgY', 'FXxLjLQi3Fg', 'tU3Bgo5qJZE']) def test_issue_673(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('PLBB231211A4F62143')[0] self.assertTrue(len(result['entries']) > 25) def test_youtube_playlist_long(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('https://www.youtube.com/playlist?list=UUBABnxM4Ar9ten8Mdjj1j0Q')[0] self.assertIsPlaylist(result) @@ -64,7 +64,7 @@ class TestYoutubeLists(unittest.TestCase): def test_youtube_playlist_with_deleted(self): #651 - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('https://www.youtube.com/playlist?list=PLwP_SiAcdui0KVebT0mU9Apz359a4ubsC')[0] ytie_results = [YoutubeIE()._extract_id(url['url']) for url in result['entries']] @@ -72,14 +72,14 @@ class TestYoutubeLists(unittest.TestCase): self.assertFalse('KdPEApIVdWM' in ytie_results) def test_youtube_playlist_empty(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('https://www.youtube.com/playlist?list=PLtPgu7CB4gbZDA7i_euNxn75ISqxwZPYx')[0] self.assertIsPlaylist(result) self.assertEqual(len(result['entries']), 0) def test_youtube_course(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) # TODO find a > 100 (paginating?) videos course result = ie.extract('https://www.youtube.com/course?list=ECUl4u3cNGP61MdtwGTqZA0MreSaDybji8')[0] @@ -89,7 +89,7 @@ class TestYoutubeLists(unittest.TestCase): self.assertEqual(YoutubeIE()._extract_id(entries[-1]['url']), 'rYefUsYuEp0') def test_youtube_channel(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubeChannelIE(dl) #test paginated channel result = ie.extract('https://www.youtube.com/channel/UCKfVa3S1e4PHvxWcwyMMg8w')[0] @@ -99,13 +99,13 @@ class TestYoutubeLists(unittest.TestCase): self.assertTrue(len(result['entries']) >= 18) def test_youtube_user(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubeUserIE(dl) result = ie.extract('https://www.youtube.com/user/TheLinuxFoundation')[0] self.assertTrue(len(result['entries']) >= 320) def test_youtube_safe_search(self): - dl = FakeDownloader() + dl = FakeYDL() ie = YoutubePlaylistIE(dl) result = ie.extract('PLtPgu7CB4gbY9oDN3drwC3cMbJggS7dKl')[0] self.assertEqual(len(result['entries']), 2) diff --git a/test/test_youtube_subtitles.py b/test/test_youtube_subtitles.py index 129e239..e8f5e4a 100644 --- a/test/test_youtube_subtitles.py +++ b/test/test_youtube_subtitles.py @@ -12,7 +12,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from youtube_dl.extractor import YoutubeIE from youtube_dl.utils import * -from youtube_dl import FileDownloader +from youtube_dl import YoutubeDL PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json") with io.open(PARAMETERS_FILE, encoding='utf-8') as pf: @@ -25,7 +25,7 @@ proxy_handler = compat_urllib_request.ProxyHandler() opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler()) compat_urllib_request.install_opener(opener) -class FakeDownloader(FileDownloader): +class FakeYDL(YoutubeDL): def __init__(self): self.result = [] # Different instances of the downloader can't share the same dictionary @@ -42,27 +42,27 @@ md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest() class TestYoutubeSubtitles(unittest.TestCase): def setUp(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['allsubtitles'] = False DL.params['writesubtitles'] = False DL.params['subtitlesformat'] = 'srt' DL.params['listsubtitles'] = False def test_youtube_no_subtitles(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = False IE = YoutubeIE(DL) info_dict = IE.extract('QRS8MkLhQmM') subtitles = info_dict[0]['subtitles'] self.assertEqual(subtitles, None) def test_youtube_subtitles(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = True IE = YoutubeIE(DL) info_dict = IE.extract('QRS8MkLhQmM') sub = info_dict[0]['subtitles'][0] self.assertEqual(md5(sub[2]), '4cd9278a35ba2305f47354ee13472260') def test_youtube_subtitles_it(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = True DL.params['subtitleslang'] = 'it' IE = YoutubeIE(DL) @@ -70,7 +70,7 @@ class TestYoutubeSubtitles(unittest.TestCase): sub = info_dict[0]['subtitles'][0] self.assertEqual(md5(sub[2]), '164a51f16f260476a05b50fe4c2f161d') def test_youtube_onlysubtitles(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = True DL.params['onlysubtitles'] = True IE = YoutubeIE(DL) @@ -78,14 +78,14 @@ class TestYoutubeSubtitles(unittest.TestCase): sub = info_dict[0]['subtitles'][0] self.assertEqual(md5(sub[2]), '4cd9278a35ba2305f47354ee13472260') def test_youtube_allsubtitles(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['allsubtitles'] = True IE = YoutubeIE(DL) info_dict = IE.extract('QRS8MkLhQmM') subtitles = info_dict[0]['subtitles'] self.assertEqual(len(subtitles), 13) def test_youtube_subtitles_format(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = True DL.params['subtitlesformat'] = 'sbv' IE = YoutubeIE(DL) @@ -93,13 +93,13 @@ class TestYoutubeSubtitles(unittest.TestCase): sub = info_dict[0]['subtitles'][0] self.assertEqual(md5(sub[2]), '13aeaa0c245a8bed9a451cb643e3ad8b') def test_youtube_list_subtitles(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['listsubtitles'] = True IE = YoutubeIE(DL) info_dict = IE.extract('QRS8MkLhQmM') self.assertEqual(info_dict, None) def test_youtube_automatic_captions(self): - DL = FakeDownloader() + DL = FakeYDL() DL.params['writesubtitles'] = True DL.params['subtitleslang'] = 'it' IE = YoutubeIE(DL) diff --git a/test/tests.json b/test/tests.json index 01367b0..5f4f642 100644 --- a/test/tests.json +++ b/test/tests.json @@ -11,6 +11,32 @@ "description": "test chars: \"'/\\ä↭𝕐\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de ." } }, + { + "name": "Youtube", + "url": "http://www.youtube.com/watch?v=1ltcDfZMA3U", + "file": "1ltcDfZMA3U.flv", + "note": "Test VEVO video (#897)", + "info_dict": { + "upload_date": "20070518", + "title": "Maps - It Will Find You", + "description": "Music video by Maps performing It Will Find You.", + "uploader": "MuteUSA", + "uploader_id": "MuteUSA" + } + }, + { + "name": "Youtube", + "url": "http://www.youtube.com/watch?v=UxxajLWwzqY", + "file": "UxxajLWwzqY.mp4", + "note": "Test generic use_cipher_signature video (#897)", + "info_dict": { + "upload_date": "20120506", + "title": "Icona Pop - I Love It (feat. Charli XCX) [OFFICIAL VIDEO]", + "description": "md5:b085c9804f5ab69f4adea963a2dceb3c", + "uploader": "IconaPop", + "uploader_id": "IconaPop" + } + }, { "name": "Dailymotion", "md5": "392c4b85a60a90dc4792da41ce3144eb", @@ -649,5 +675,25 @@ "info_dict": { "title": "When Girls Act Like D-Bags" } + }, + { + "name": "Vevo", + "url": "http://www.vevo.com/watch/hurts/somebody-to-die-for/GB1101300280", + "file": "GB1101300280.mp4", + "md5": "06bea460acb744eab74a9d7dcb4bfd61", + "info_dict": { + "title": "Somebody To Die For", + "upload_date": "20130624", + "uploader": "Hurts" + } + }, + { + "name": "Tudou", + "url": "http://www.tudou.com/listplay/zzdE77v6Mmo/2xN2duXMxmw.html", + "file": "159447792.f4v", + "md5": "ad7c358a01541e926a1e413612c6b10a", + "info_dict": { + "title": "卡马乔国足开大脚长传冲吊集锦" + } } ] diff --git a/youtube-dl b/youtube-dl index ffe9a4a46910617eb12fc85c4df4d238a11a397f..20ef4314130f781ffb810b483139b2f6f65e6420 100755 GIT binary patch delta 52559 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�P`GRH3h)%KF!ur?G`D{RHT*WB2qo!7ofm$wZyMcJH}Tifn3s zB`~rJiD+^>f9!451dnYi^7HErJ}xZB@^UK8t;_8$rIkcb?uzuw{;vB5aC_S8@8w56 zu)>)epkZ*}3h`XXiuKL`sk`+OHm}#r@u~217oh)p2lVj1)MCH%B#{SR*3}|lvU{Wt z{B#H^P9bGgqnD5f-9&`MRX$jwWG-{*QKBL8;@iUy_R&;%ObsIKHEXj2VF`O9H}{iy zeD~z=5KLZsMP!V`g>hyIK!b|Z=Pp5-hA>gn{9b*9+eV>ERqK46rkT9k2yUxslrObh z7&QI%yc%MSJ3A@wknM6@lU?hLiD({P81cG>{O-L_k2MrtCF1KINr*@zEH=) z=~SkN!RBwu|zi3Ju^>HrlR@7TxF zoBhSy;J_h4WzE%(#FgMz4lk+G9Vu|~AD`vt2aAcm9ek2TmS0v+a6`_S5(3F&4sqY~ z*|}cV61E~+Sy@vRm^n1BrNpY|k_E&e1bf}pL5J7T<~NnJG(DZ6eqrY57+7pEZf2>4 zf%1R+<^b=m9uH@uhnW9!aQ)-29Q?1pa$3F>Fj^BJTVgLpTO>llK^jEARu4R{|Zcl zF9L@DUxbt<<*a1je?~pa=KeRBCTH+JJ>KN={M*P}kN^$;UmO=>;f}7q>2jd?q}j@U zDKLpuXn+m&`z`?Z3^rngsPX2gt9HxvQcTXsZ(iQk-}gyJbE zC2*h^(Wy-dnhdZ#PlzfaQ3_>U`Am2p%_!HHcgIFDJhsRj;2_Z}uGPb8Z>k5HanB;= zcbjVa%4A%%7${W@t?lF4Ma&NYR}y94t}aeE*Aj-B-&ez3NRpcWT5~;AH!L(vrG}t1ma^6 z)xVXu#?3Mpd4JdMau5i^M-`??4LD_`p#(b(h>XZ+YfC`O4BS!`Z&PJ&Fo7zZd$F6+b*`gM>xXD^LrJ2yRx~T{005K}A>Jy) zm0MSRMam*%M;Qnuvji?bsD)Ua5Q2&9&jzXx6e$M(y}e=?H}6SPV@*a*Q{m`1783}O z!F@t`1O4n@+&6`Np8$)eD1zg_61G^A3WUKugtm442C1u_}i&W|n@sX+u2 z9(0U)&dG)7*GdkaHg2|k5MjhP6v$eas46-Y|4?|c}t>q&J46AZarBWVU-e&px!=$bj&-M`&HwEK@pQaoGtp6lM%c&!TfvXtN|~N&-1WWa;B{hwG9e z`=MFj113|SomX2|>z$3pd}>(owb`lzJRKN1s!rCQ$aHOf4#_-4N)k|$h|UWxT#hqF z`7gW%E+sM|ln5SPX{DFow%FXfA3={|G?u_c@?qa-$gyVJe^fN6vU5cuDYMrP{lS#haYUbUjDuA_38vYfb11jvT z&Auk(Gnl|rm`z>Dj9`@(^J_0llLgt1B2H>FO9D%6VIDy(1U&FfdPuPbS#bqFLGLZ6 znKQHQ;rV=CJF?b`{h$n$PlFkckyx{JWh;V!bCErk34-rj<BS8`QjvnpHOU#bNv);(JeMK3ws` zU1fG+AL|RX`xk*wcfd0jsFtD%1eOS+p~C6&EdZf#>Zdm1aN#eDyu?_q(=!(ovuyPs z(NbYBlaP?2-?@nA8=>~lhrE{<9W4wmq{YX)QeO3Hq`?r7A(!3;Kfe)caZfW*H^!BJ zQexe4H?K)XoYI=7dwp4|?hx>#S=VXP>l17652f`-51KW%L*xic0fqEK9->4xLl!L4 zwFA(zYp=Qt4Tujr7OxVzo2=4-_T+_a>!XTQvhW+!}epn=1IPe-)Gct$T76ko_V+=tyX&xan z&mTP!lS{BeV9I8?GCRwF5Vem-75SQ{{Q*Gfe{0Vx;(NP%ap?hwObe`_ZZuot;LE)_Wp8WucC#btf2HZ_13-$gK;m;>Yx+o^m2JNM_|S4w^y9$9Kg_podCpo z@}&AD2rU@IEV{JcXYyhZiZJ(ZQSP}52@VH&ftX(I00f;l^M~wbRtOID@g`*7?GiHR z)@$bI?CbpLPumOpD(Elm=iwEAYljucY5loDDrazxhyn7Q)T^uvy^xm4G8;R9D2d3Sdv|^H=+a z8)QYd*}DlLa0YCxtz-q_>j@R=^bh9X)=rt=x4U*(StXLKgh&=(sA`WZGy(SB%bdZa z*339dNUPeCJZaE8Phl@OC%scKe1mcjPew}g{>v@R%P#F^a*fNq-k43Ie>o0ZoqAaI zsB0113CIf5YakN`@1S+up$O76?SHZ)C5bxbO-$9t!wEpXAR^jS17;z%>K2cBc)kvk zHVzmCUYj`+-+Thn@UL%>7XZ1GOm$j<419AETaQLzSusxwtkrxdb z4JYZfC7ba;RZQkwScu6XjK>|dnE-FDMdn%rYSZUug?ceerd_G6QzK8!x0xRy5Po-NGL+ zgD47nJhCGBIb^#IRC@5oFAB+`YiDg&_Y!zTQ?Nh$rUh|E0~FFihXfh9w|YnRK|xsTF|0HLsD^07)z*4%p^TaFN=gqJsbldKdfB6C-0X0gmeNe=QM&dOY``h7N&Z+ zjYc=pJ`p})ivZvD&DyQM0y*MOsPp}Nf=gOn4Uxo1?Vq1oi8g#czDit7ZG@pQA0gez z(v>h_In->zl;bU8hl}$lISbed6~}6muB=NhS(-rKDD5;lUC0Orp&5d4dohgzWYJ4^ zbJnZ=`n@Jjm~&rkQJRjfq;yj4&d~4P?`5zb6MrdCzB7PGAs)?fM-sq%hXvSTc6d#4 zW#fH7{vX&SjDd!*jsEw(h#xi$2@e=It-2T(>3`#)#WqH;fAA1Q_y6D_iSA6$f4~$$ z$ZQzgUlbMy`JZS&$^VTe>!KG5ON}3&l`I zd;f#=kf0!+tpAQ;51lkuiJSB~h461*2-Cs;86ahj^WVnBIRub@ruUaXNA2)8umd^? zxf?g_XBjZ^|6Uu#?}-0Qhlzi=o6!uVZwP5Sb&1XUp zF6N{$)jhS%#vUod9-Dx^H9eWsXccS8cz26ji*1Q+>tdGpA3>oSSdQPdOi(c7w30ux z)EYytUfuM@sw|2$&5PHiivcxz!X7A2K#vz@waJOrIAlUdrh!)QHzm5TA9UJ&e&}(# zi5)8NLvsXGk=XLXt9qb0LL%O0>q457$|wlg%jdIEh%0GT4hH=FAgXA2f1TlR`0}O` zU8AN8VsV7`=3>S)t`7`9bH|sorR}pM-xwI;&I*WlZMC{qq(D z4ZON#dJ&{hm{)v&2nt{T&+f<_!f1&$D&g9E8;l6ALyEO#h8d}zfr5UkckGic?+eT? z-{D&sV)|r+G>IDe!by<*e9UM>fT2Jh<_4r6!Z{z`Vv!H5Rl2B1y9H@2Rf`@Gn#xSUJ&T6N*6zp*D_yq8BW;bytI-{!7(WxON z*tio@p-MM0zJo-?ksxQOH`FDr+s&yaOwj(#sci--Twt*)0^fNQ$_M2NukIMYR^aII#^36-YwdmZTDt`JA>eK=MzWst0!pHJ7-e*oGCcuHrK0F7Or?)| zzhV3E(!7F=aOpT(m4zlt;yU%N>`5QaE=Q2;%#>fBE^qW<;<={#eXK$|h$dbDIujcexpJ`h_nACnDLZ zG4S74Lb7*TlwTV*`jBm6jwlnpyfMWt=v0x--rSp5A@aN2IhUDLS|-k10iv!6Pa8t* z9f0rYVA<{%z=>I$6fAm)b|YjPr&!`@)r3!{zAm|4|2hx84$`N6{egY$hBnm1%klKP z+qkJw%t~lGG_6@BsS01@-P<3&Y4)J#R}$2naNo zhq)6x)xpNGZT>U!if;x%J}eBw-?{$GyzpCCj~_{Qp8xr%xfAd>N3ZPvIpV9uIaqx> zXS+K52b1Hd84~4p$;B#R#4-l(#JvRnFd+jiU93zD?cD!=o>Hq<)3!@x!}HmCl208O56CM^Xr5Jnv-g$ z9LbTyMVNp}Q>72k9fHoD0zsQ4{Ypgc zTv;Q$7NY#*a(;e_TPp;;hi<4d`WFf7&W5pd8=75n_@;krI5@Kz}bHsPRsN6qbRIL%!ZBjB@RHgkdtKrW0eggE3UK zh?18FwX+AUoB?eNKjOxeT=qKl$Ff#^sT`*v^Y#Y)W@K#%n1ll|eJ$3!R8C+4-5HO2 zvqa+@Mu}_wjQ+GMM})>VNuKy}F)JRb3HMn4OwL{x#Z$vDWB0u@4ZdID6Y-9UdC*wP z^!uF!6>sAc(9}~3KU>0!G2B>Xy#pR{;c>?G4rals$o3VwgL9Z7q7&gknuu z$>X;CbIG*$H>pl8)XND>XMRAbh{S4mGMF6HWISt+&-0T-=M|c6*j(L?>IspO=9X=3 zGt+pyBqMuL7v~Bt5SL*j*uGve#Zry@uXQ7#e2dBn*uH3U#IYk*!E6bccdsNCgh#0e zBjNQGA3K)M2fsseBC;p4t;YM#C&Q&_O&KDV*uP}CZ;dHPSHE^~B8*}55{BQpgJ8D5 z9(uc%eNn}jYwo@~LUA=P#Od63z(u48|9a9sEC-!6hpA*!NR(Y;*;BREQU=1LX89w3 z3)w=Pw$={BT=3U7%txPw(pp?%bSdvxB7jdK!MMYde?m0I(>gfx-)Gy{JnXgG;L~za zaL_{(w?2#)2Y-$HXJivzLp~07vS0tu>ipt<{Fr$6=VKg0I$`bM9U08;83Tk44fq3T zl!pfRJcfDX7`0#Bz;axXKruo9LZFSa>wgFQf6_(&9bhG>YuhbyWBFcIlBK!C;)H6E zZcVWxavnq!SbU(Khu}ds-?CPD@B!o)bS%d)m`_sNmu~M zrGi$$YUln6iIYed9fT(fS?H&wHK$4*;2REF&IAt@B;{iH@Mb|EXL!Cu$?L!hWL(ce z^b7dA@e*SiO#&5~;F|pP8Kr6V@?!S@E$QlgKv(J#6TQ_B+#RFg> zxGQGEvXi1kltY>Uo6~&i$Njz!=gAa`5>Dy1&3t#V>*Q*VhvBr{S75I&h|agimJR2^ z6r|j?k<#7qYxVqE`=Re=J`(jC6CfUMNI=mZNhF%NzK7@xq@%Th<+FZ;fY}KC42Fe( zqBmBy`sy_>Svk>MajCDQ5~&lNz^^oEYZevvyJW7sglgq8LPXvn12g-jYpN@l1% zlO-=_SXFLuRff28qo3sFsT}xRrIdTuXo$*cvfmpE_Qq!l zwGh>3|AVjhOwLJ>=n_NKB`*-J%WpW@z;Khl5T+N`Z(X7l8Hw=@b%+GZO*|F)OnD9Z zD{J!%e(Ukq^!ZvW)fMk`cRDXR`(vF6#;%4ex>3TA!3Mhks|`f{vc73w@kT{e5SsPG zy=*Te)7%AoXRZ=;3^1;&2d1nb@wtfj0-Yt_t|XL0V$Xy7P#Z`B ztK5cVmPYCr@<8CXubQAM2ATbXU7=TLOh|-<$4Rf=?VWXofYP(_@$(ioJ`hwPCYKRa5YR5QuDNT z!u09}(JgC!qHwl}tGdO}^Yps?(mNndgrhUSGF8!(Eoq*UZ4m<);HAZ3l17I7HA^6E zOL;v?(r6E|^tuPj*A4Y& z1+t?B{Mk1*R?q@g9ya@+Xr{lghnN7;k4$h`|H4*h1?)jTY_mgqGoikK7l}A%5E&VG z`)tVxK>wpz04HGYQIcLb z&|mIp7XqNepwoeGyj0m3C|rT1LxE2ch<`6pKxY?YJD2}19lx)?{2y0ff>mUq!LefN z4@M?EYsRUaLv$BhwOta5a;;)ZF9dqWPO3wKhzNx8l)FoU9~jUFjwc(b$#&ML6s!r{ zFP+AQ>OKSHR5MB;!)$?XjCXe$zc8`C_R0WBsjIC4wbM&HFN4g~Fx)$RPoks8S`0}n#CS!7cO2C;c?6=(ubA)97&r?UYW6L}P3n-J!@LJ|Ppj2V5wh#|JK-5i&2?1ntdMZ;sA17NT>X z3t?Q$w=b#ST7b5huy&x9R3$bRLw%o<1zyKvkan_Cvx+&?j5b*b4|GcNV#2ft35Juj zI03^NG|#TIBK9+liruHO)#!t}=){cg?_P#b*AKb5g~k*#7rOv1fM#RjlIC;en}Bdf!cXF!SKPuS#gX9tM*;i$bP06z z3h-x>)A$S=@jrIHM)AK!#1C-*%;V=9$-nwEmlR+J@*!+`Rqk{Te%2Af3idx?6VTPf z)$YGt^8Y28@ln;WTVTWT8LO=Y#AP!g}Iga#`zT0CQpLdcgI3w2_@&zJjUK)CV;(P_Oz zeN9E{Y9w{@_6OB41Y>o-*ToE$Xs!h(&lz>Awqje=5rfvXRjue08^l+SzSml~uaT$g zt&ZAG+~_r$2Vl_{n+$uVQOQmAqysDSvT5|FPktuchXCKXVTWw)Zc#I~_ie3v5xF-* zzK&)$z7VSW$!Z$lN8zz1l+8ldLWYW< zI*!ONj|3bSV_6HEe@%#e9{EMHa)HrUwL2!D0x$Y!2yn;c*g*9oW!jGMVJ{H;Qq|AK z`GYCXYEo7yh_xH`#FJtTnlIOFfbmY}r%jL-lyQrBbU~9N^Aa^)caLZ0c zQ2Kf%W_uXdMUtMMXuA>Ey+@sIV_r4dP}gT!1q}<+bHTtwWQBQDK>M z<_$!-at8pDu${YSRBlkLE212j{0XEBXOW;FVM|u7AQ1CreeSl3^WG>Zw|nZ+O2_qD zHkVY{Z;=@#pstZTMRvTGt@V)ZGbfP^ckxME7CxLY)dKa(_wCnpvjJ|~;0I5|u*q!R z8^4*fbEQn+j!O0SxhtkOGxgE{Gy+}}ghprLNV-^$+@b-^W0q@(B=mEEdwKkRZ3}ie zkSdJ+8A1+%O<^dX*P_g#(l-%Om%p5_30EG3;G;nGaNilYHSz}QPOH(-ZAc=kGb?=E ztIxE!eB<4-R)_O*w+|o3R-JFee+^m^FVqgvpI^CIy)P=a?|ta|Uf@?>gulzh{NBk! zvO!SZ!9l=6Fyj4ZdIm|#0G`49=QVVYwhTZXIs<=H08}mmFaYF&P-Owc%%8#c(bqjl zSV|-C0sWij-2PmrVG-v3Xai|cl~QLv3-#H0^7lB9MnU&{dTl7}pFFQXrJVtH7cbDm`)OW_-`T$#*Wa+T0PWtC z@?wiq#RgBWDN()MEe%(p0uAxhc0f_p_ct|1*#fV(xYDxo)SrX4WC1UL%o1|4g`4W% z18y=Sz%aLI4`!TwDuh1Q zVYM*P57x(w43^|sH^Me{=vst_oM8P}l$=M&PbUb;YSr0TN&)q~b=u1_tF+m(R!pt! zfHf-ff!L2#S7&C)gmluiEuvliaWy$o;?{fpKSB6;XUKblWhZZ60rilXNP~jwzSQzg z#;5Tq)WhEfy(`H&4ed;a{-qlhe^x7J8e`|RQoy?Qt1-57+8#O`F`HK=wp!_j4r+WStfs!dn(bd~&@L7g)?mmHx4Bak6$(5=VpOoTlMnpXTcVr!s=+DO z;bg>;2tjfXO{fs)(>O!FuV<*6)DDYwU~?37ha4_?-bpWOyGA6}vf@9>*3$45o#0R; zF>j3lQwzz=C!;(&8cFmRdmba1JtoxI8r~w{aw@(Pfw4>YbGRCs>+3l_z_X#RN!`W> z9NOmv=3289F+HgxSgZEE3A0hiV?;NmqIFa-!<|_uo1BI~b$QjKTe$?EJ6;y2zW!Rw z!1-$FCVDkpk@H>m$^k7mlJgxi>uayk8H>sieH{NZck>K+Jfyf&5rhV-h6R0VW}%kd z^2ChgV|625lXY0x)Ub0T^{yArqTB%})9`5sdX9QaT$?= zkL)#M7QgZVUHL(zrf*F5(%w0nS9g{<^Ip2ri;F9QX5p$L8ZIciOK4K=j&{zOY%ViowjXCm~~LEoe zX@py+O-vlOf!DWRy;)c$>0sEv+1o?S#r;DG%y(aL!QRtU0W_U9ybFkB!q0mEL}2@Y z{*uqHV_-}f48bc5+Mu~1YtaqAHFue&i`Lr{V)<*$lPFjfNVny$c317vq zFWuNhEh}1fk{!bFg3jXG!EjI~U#fD?xVn4Zp9Iv3>2hG*pfAb2SJ>SKmF6lGJ)dC} zz(_;VquZq3@+W8BHs%TuO+`jC7ihi9X^{H`Eg1vBqq(~Crn&;sQF?`lv?n2x04Q=T zoAvqhU>7=WXqr8dr%+>ojKrvg*R&QhG6ww&0!5NxCpjYyb($Hf647h{5`94DN-KL^ zZv3@fe?ino0|Z@VU$z5M@17$ox*OE7UmqO|4L>GqlEdAWyl#jw$r#UNEN(gUa9<8w z%(xL@w`TQe%LJtAL5!WDDu$f+=VNCkT!2=U0aUiea*G7QY;#3Q0{vyM6W>%6kXKr_ zghY{n2U+^bDS7PEAM#Qbx4qd0(zD)|P30!r#V@$(tF9F>qYfOb?SjvmnxH7)FYgQ% zUbDR{mHbFz*v3nCC@WT8klvg4Ytiyl?@6=?a!>*Mxy{;Gq5^=1ME|`^l7oMn_5}xw z*x-PX_V*?RG^+-{1^#E1{P($+kIEOzMR25e`3C+-#FZT-P$-xtyUH5D*`%z@gsGeE z!Ug=OghXs=qRV}|6}`%SU8HWB)D}s)lQV0jb}_ON8gzavm$Z}SYz_I+0l3l&3u&Zb za|{D~z+1NR!8X;LCN9}>_mCfRQy`qmm#HOa37LE^x|sy6v@;mFekc$cbD)DDYg7k!}M< zeQHO3up*L<)ttz^hopgdQKUdEimYFKz=x8Gv8LM~DDB-A0agpM;CVhl(r3oAs=$6J zrAUjaoF=32+HyZRti-o3lY*2ytHZkGWHA+7b70dIhZM$V6xmr3d}7mg8eSsUMNt$` zGL-fY$ZjEKz2m>`p5_&lumO_sD9Tz0GN|bDPd8a^iqU?=q&Wpq1$FNW&lZ<`ytS9d zc)&dsCTa+;gYj#o6qX9Fv5FP=; zl8P1X2&8~#t2b78_|}$eDVxgl!!f)j`Kp_DuJshIVrkn`&q-y*c(Z_rJxrVDB8E~7 zFyG3KK)h6OKY#k3@Qeq=53{k~^sud-Fh;(O$h`!VvLTnlwPa7e7tQ%-G6F7iq*lLl z=SsO#CKg45UqZ-(Us5IhR-22bhHu9oq_DDqiuucTt-rodqH|1`74LdF`etg(_LLu1 zAR%_A+Gf?SS@-1S*6B0aA|OK0jj)|x^@bOouP)rLTdrfP{vY}RS5JQ|0_kY{b)uW1 z0myzlqImK4ug>oF7Vvm5464%oYcI903m|>mOQ9J2wU?4I0N_9V=5E`k&?N#M8agnK z=O^J70MtLH3*ejL+K<$CR)10RS_6n4&zj#j{3R>S0l)zJaAbk^K1KSN3<84T{Ug(= zMga2v$1nLyf_t8e+==(MSVe8@#bO1Oa+r7#W5*Qb0K@M~}FZFzauaGWT|P`CP-#!LmqxVe9s5K-gb zP)C0H3iKMN?P2z%YQ0L7IK&2nOr`6L6A76?N&}mf+y%g zH9fw=S+EZ;=^y(S8`9R|YT_)~uKi#moLMxYm2SSZD&hPtjdrDyN{i4rDVQbl5f0&= zYpWQMd_*7R3z|JGv}~gPHrrP62vj?C+Wt;D@W3mlId3;FATw0ZB|Qn~b+??F)0_Eo zse4C=7RnlykdV-JEsy?YjBf0dURa17o90=R#oG7pG~Bc@v_Jg&Tiu7VBA4G~H$mVy zW4SL1w|hHXFWjx)5^@_NaNf&~lt&la6-aIvz4dqYZfz03b8}S@)<*76+JS&&e;$sm z2c*S2dqob(Qbxae3(>)1oAFj7usRQs!1dEWWDa8{Y9FrD=3(gJ{90fxOIiL8B&OYT zF9ZMMLlpJ3G-lowR}A6LDh**1OwNgd#5IJ%+MSu5PU$^H7B9|o@;5>)Sh;34PI_mq zktwf`XwM)=)5di=15((CriOoD9-1Qe)B#D?uKgJNTmougiiGdBjE7xb;Xr8|I_x@K zUpIl~;YsgwfNMkamoJXH5Y;L7_jF*zCLm618cBOXZzh_8YcYZ;VJ(lCl1Vve;gd4+ zi`a)qd~rzqJT{CEA@3SD=teiX@JuGdagWQJo3vxiIwff&-m#Mw2^eBZ^q82!-T|@A zS~m8+FnfDW<%IP2UUm1*m~E&ho;i-LK}%9?D)bHvK5BI ztKW|oLgnNoTU!8J^+ zY>BdO=FOntm&W-N$0~fHC6^)kzu$FwIs#7{lZ1_Uh~n8$g)H<#BJ_T2%5TFd3%w5@ z`}jrl4%ONIs@M0&=>bo$*Yg1d|NiFY=IUJ}UR`KP65D=3>02zwaQ(UtAyf%rU|NEl zlQrbZBHL%zB}ThCJ1K}&pwqSbD>?vg1yYe&F;{es2bo{m$>xIF&s6inP{;itJNaEo zt|Y+V-TtWScWQxu{;Nf*OsK-8Z6?VPk6*UG_N*Yj_K>q`9}L|^^bo?khr9pge?Sq-GU z8AH8Tuzs<0^A*C}>#lCZ8u*N;%MSdXBk^d!fgCdQk%Gd0BWs7K%P^x)9xX6?0617H zzNr-0Z-!=kjb9SH1B>Pt5QSO-fo#3%WnX>ArI6e`-u`k9-rq2hwkmH+dh|;x&hzmV zh%!q=I*s7@9@Mj#mPj{$CtN=zKNRY>ko2@BdIBP!hx}{U*U@y0fFGdfw5DGKRuO-l zBvn|sKfkGs1MuU(d(SP>Z4y!kBlM?d5c94t$$GF^VMyJ)q#e5A7}db3jyFRV*wSaj z=C`j(5O>`T7=#~L;@!{;kJjDqMoY!pFAhti1vU@yM6 z{Y2&{7$AgohwU0&3ap|Fkq%`t+w0#|@*LJ3atKT3n9`4CSR>}Wsha+kj^0l%40CgR z{lF&fr5lXg_nRm%4m)GG_$}{Z z8MQS17Zh_i6~}2RKvthIWj0@w@xfsjyyuEk4ue#MBw#c-{%{PV#Kg`rC*^)Y$=>Ue zNRIs3n4izrmCu>R3)H={`SaxN`7huW{QaS@@C$EWKI7wq`ETF!Yuvo++%!kOb~2%y zEeTXCD8~a))0Sf=Ckaq!`uhcL)L8N3l(tgL4N^W%j7`Y85aN9O%z&$<8HgzOllG-b zs%qnk%)Od*phd{_cfLTOcOZYh58CJZEZ-^XdKYJNC7+pTLcs7@Fwqlebih5k!tbqe zKD~sXgK>n#VFMRlv>5*)DMxu#J|q$(H!>dpQ}CJ!_>-$2Yo>8)>qy?54R1VKki6P_ z&5w^h(C(QF#vU9&{2PKi{yj%>#93ux#zDQeicz{E;M4M_B#!>B^E@WVZw!x!e0 zX}?-Me!5rj{ruVc4RiOscjv|XR3uq)8-niG(&guYZNsw9llBAk;mFRR90LKSc&Z?s zSO7?~ArYzZ+kJ?7X>o6Y&o<=M0&YxqgxO&Z!qE7bRs_x%f#b3| zC+!#ovcJxvi=mw03#JD763^Qn&4Feqt05F))GZEX{{zQQs++IrI*!Z+3~9?I_o#jl zMJEC2@6k8%JeWpZV+UYv_ZJq=`b4QgQg+)KpXpAAdj((Z&SpqE^QiBGR@Qcy*FuNs zJhW?G9c_TVoZ+swC^Ha4%$|SK!GRkkUi&JsJ}l`uvRc-^5go`HX(`QMBh{Ih@ASI0 zE&Q~Tk~JVhF%Wva;V0d)m^EU^On&U~i3$dgsoY#%7C{lci$M{yXpwqXL(hQRP6czT z;k$G^c(Ki*9R?J?BrG209DHWY&61E2%cQNrun%!t!xX$4nPFZ$F|65F?<=m7yB8S2 z>5C{DIl*l$JmPu4>w-?xjG?&9M1Mx7H0un3eujoXD@UN=O~g4;?Q9U><6`>4psxYg zmp5d<+(utxUch0t9P1}iYVwA2fqfh)bu?awTc~UGiWvXa3&Gk1^&3qazWeqh#>g7v zMGhX15<>7KG8fHlbzi>gR|S*-U$`6CM2Ip!(tr=aEN^NhMJXKZhZ{zBG|pj%Jqeik zFuA17w}n=by5Iq5HQ!Up5`6Qqc$?aQQ;SJz0*2F2$l{(I%|gCOJjG(H5KM}b+AV(a zyy3WC{glnd4&#@N6%0gu;;JEIVh5YiC5E5nU@h5i!+y@^=ZhOnCy{0UP<9W?cqv5?W yfvRPKmR&)nL)&jQb%<8y{ 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 delta 48260 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 200: - info_dict['title'] = info_dict['title'][:197] + u'...' - - # Keep for backwards compatibility - info_dict['stitle'] = info_dict['title'] - - if not 'format' in info_dict: - info_dict['format'] = info_dict['ext'] - - reason = self._match_entry(info_dict) - if reason is not None: - self.to_screen(u'[download] ' + reason) - return - - max_downloads = self.params.get('max_downloads') - if max_downloads is not None: - if self._num_downloads > int(max_downloads): - raise MaxDownloadsReached() - - filename = self.prepare_filename(info_dict) - - # Forced printings - if self.params.get('forcetitle', False): - compat_print(info_dict['title']) - if self.params.get('forceid', False): - compat_print(info_dict['id']) - if self.params.get('forceurl', False): - compat_print(info_dict['url']) - if self.params.get('forcethumbnail', False) and 'thumbnail' in info_dict: - compat_print(info_dict['thumbnail']) - if self.params.get('forcedescription', False) and 'description' in info_dict: - compat_print(info_dict['description']) - if self.params.get('forcefilename', False) and filename is not None: - compat_print(filename) - if self.params.get('forceformat', False): - compat_print(info_dict['format']) - - # Do nothing else if in simulate mode - if self.params.get('simulate', False): - return - - if filename is None: - return - - try: - dn = os.path.dirname(encodeFilename(filename)) - if dn != '' and not os.path.exists(dn): - os.makedirs(dn) - except (OSError, IOError) as err: - self.report_error(u'unable to create directory ' + compat_str(err)) - return - - if self.params.get('writedescription', False): - try: - descfn = filename + u'.description' - self.report_writedescription(descfn) - with io.open(encodeFilename(descfn), 'w', encoding='utf-8') as descfile: - descfile.write(info_dict['description']) - except (OSError, IOError): - self.report_error(u'Cannot write description file ' + descfn) - return - - if self.params.get('writesubtitles', False) and 'subtitles' in info_dict and info_dict['subtitles']: - # subtitles download errors are already managed as troubles in relevant IE - # that way it will silently go on when used with unsupporting IE - subtitle = info_dict['subtitles'][0] - (sub_error, sub_lang, sub) = subtitle - sub_format = self.params.get('subtitlesformat') - if sub_error: - self.report_warning("Some error while getting the subtitles") - else: - try: - sub_filename = filename.rsplit('.', 1)[0] + u'.' + sub_lang + u'.' + sub_format - self.report_writesubtitles(sub_filename) - with io.open(encodeFilename(sub_filename), 'w', encoding='utf-8') as subfile: - subfile.write(sub) - except (OSError, IOError): - self.report_error(u'Cannot write subtitles file ' + descfn) - return - - if self.params.get('allsubtitles', False) and 'subtitles' in info_dict and info_dict['subtitles']: - subtitles = info_dict['subtitles'] - sub_format = self.params.get('subtitlesformat') - for subtitle in subtitles: - (sub_error, sub_lang, sub) = subtitle - if sub_error: - self.report_warning("Some error while getting the subtitles") - else: - try: - sub_filename = filename.rsplit('.', 1)[0] + u'.' + sub_lang + u'.' + sub_format - self.report_writesubtitles(sub_filename) - with io.open(encodeFilename(sub_filename), 'w', encoding='utf-8') as subfile: - subfile.write(sub) - except (OSError, IOError): - self.report_error(u'Cannot write subtitles file ' + descfn) - return - - if self.params.get('writeinfojson', False): - infofn = filename + u'.info.json' - self.report_writeinfojson(infofn) - try: - json_info_dict = dict((k, v) for k,v in info_dict.items() if not k in ['urlhandle']) - write_json_file(json_info_dict, encodeFilename(infofn)) - except (OSError, IOError): - self.report_error(u'Cannot write metadata to JSON file ' + infofn) - return - - if self.params.get('writethumbnail', False): - if 'thumbnail' in info_dict: - thumb_format = info_dict['thumbnail'].rpartition(u'/')[2].rpartition(u'.')[2] - if not thumb_format: - thumb_format = 'jpg' - thumb_filename = filename.rpartition('.')[0] + u'.' + thumb_format - self.to_screen(u'[%s] %s: Downloading thumbnail ...' % - (info_dict['extractor'], info_dict['id'])) - uf = compat_urllib_request.urlopen(info_dict['thumbnail']) - with open(thumb_filename, 'wb') as thumbf: - shutil.copyfileobj(uf, thumbf) - self.to_screen(u'[%s] %s: Writing thumbnail to: %s' % - (info_dict['extractor'], info_dict['id'], thumb_filename)) - - if not self.params.get('skip_download', False): - if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(filename)): - success = True - else: - try: - success = self._do_download(filename, info_dict) - except (OSError, IOError) as err: - raise UnavailableVideoError() - except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: - self.report_error(u'unable to download video data: %s' % str(err)) - return - except (ContentTooShortError, ) as err: - self.report_error(u'content too short (expected %s bytes and served %s)' % (err.expected, err.downloaded)) - return - - if success: - try: - self.post_process(filename, info_dict) - except (PostProcessingError) as err: - self.report_error(u'postprocessing: %s' % str(err)) - return - - def download(self, url_list): - """Download a given list of URLs.""" - if len(url_list) > 1 and self.fixed_template(): - raise SameFileError(self.params['outtmpl']) - - for url in url_list: - try: - #It also downloads the videos - videos = self.extract_info(url) - except UnavailableVideoError: - self.report_error(u'unable to download video') - except MaxDownloadsReached: - self.to_screen(u'[info] Maximum number of downloaded files reached.') - raise - - return self._download_retcode - - def post_process(self, filename, ie_info): - """Run all the postprocessors on the given file.""" - info = dict(ie_info) - info['filepath'] = filename - keep_video = None - for pp in self._pps: - try: - keep_video_wish,new_info = pp.run(info) - if keep_video_wish is not None: - if keep_video_wish: - keep_video = keep_video_wish - elif keep_video is None: - # No clear decision yet, let IE decide - keep_video = keep_video_wish - except PostProcessingError as e: - self.to_stderr(u'ERROR: ' + e.msg) - if keep_video is False and not self.params.get('keepvideo', False): - try: - self.to_screen(u'Deleting original file %s (pass -k to keep)' % filename) - os.remove(encodeFilename(filename)) - except (IOError, OSError): - self.report_warning(u'Unable to remove downloaded video file') - def _download_with_rtmpdump(self, filename, url, player_url, page_url, play_path, tc_url): self.report_destination(filename) tmpfilename = self.temp_name(filename) diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py new file mode 100644 index 0000000..b4a966b --- /dev/null +++ b/youtube_dl/YoutubeDL.py @@ -0,0 +1,596 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import + +import io +import os +import re +import shutil +import socket +import sys +import time +import traceback + +from .utils import * +from .extractor import get_info_extractor +from .FileDownloader import FileDownloader + + +class YoutubeDL(object): + """YoutubeDL class. + + YoutubeDL objects are the ones responsible of downloading the + actual video file and writing it to disk if the user has requested + it, among some other tasks. In most cases there should be one per + program. As, given a video URL, the downloader doesn't know how to + extract all the needed information, task that InfoExtractors do, it + has to pass the URL to one of them. + + For this, YoutubeDL objects have a method that allows + InfoExtractors to be registered in a given order. When it is passed + a URL, the YoutubeDL object handles it to the first InfoExtractor it + finds that reports being able to handle it. The InfoExtractor extracts + all the information about the video or videos the URL refers to, and + YoutubeDL process the extracted information, possibly using a File + Downloader to download the video. + + YoutubeDL objects accept a lot of parameters. In order not to saturate + the object constructor with arguments, it receives a dictionary of + options instead. These options are available through the params + attribute for the InfoExtractors to use. The YoutubeDL also + registers itself as the downloader in charge for the InfoExtractors + that are added to it, so this is a "mutual registration". + + Available options: + + username: Username for authentication purposes. + password: Password for authentication purposes. + videopassword: Password for acces a video. + usenetrc: Use netrc for authentication instead. + verbose: Print additional info to stdout. + quiet: Do not print messages to stdout. + forceurl: Force printing final URL. + forcetitle: Force printing title. + forceid: Force printing ID. + forcethumbnail: Force printing thumbnail URL. + forcedescription: Force printing description. + forcefilename: Force printing final filename. + simulate: Do not download the video files. + format: Video format code. + format_limit: Highest quality format to try. + outtmpl: Template for output names. + restrictfilenames: Do not allow "&" and spaces in file names + ignoreerrors: Do not stop on download errors. + nooverwrites: Prevent overwriting files. + playliststart: Playlist item to start at. + playlistend: Playlist item to end at. + matchtitle: Download only matching titles. + rejecttitle: Reject downloads for matching titles. + logtostderr: Log messages to stderr instead of stdout. + writedescription: Write the video description to a .description file + writeinfojson: Write the video description to a .info.json file + writethumbnail: Write the thumbnail image to a file + writesubtitles: Write the video subtitles to a file + allsubtitles: Downloads all the subtitles of the video + listsubtitles: Lists all available subtitles for the video + subtitlesformat: Subtitle format [sbv/srt] (default=srt) + subtitleslang: Language of the subtitles to download + keepvideo: Keep the video file after post-processing + daterange: A DateRange object, download only if the upload_date is in the range. + skip_download: Skip the actual download of the video file + + The following parameters are not used by YoutubeDL itself, they are used by + the FileDownloader: + nopart, updatetime, buffersize, ratelimit, min_filesize, max_filesize, test, + noresizebuffer, retries, continuedl, noprogress, consoletitle + """ + + params = None + _ies = [] + _pps = [] + _download_retcode = None + _num_downloads = None + _screen_file = None + + def __init__(self, params): + """Create a FileDownloader object with the given options.""" + self._ies = [] + self._pps = [] + self._progress_hooks = [] + self._download_retcode = 0 + self._num_downloads = 0 + self._screen_file = [sys.stdout, sys.stderr][params.get('logtostderr', False)] + self.params = params + self.fd = FileDownloader(self, self.params) + + if '%(stitle)s' in self.params['outtmpl']: + self.report_warning(u'%(stitle)s is deprecated. Use the %(title)s and the --restrict-filenames flag(which also secures %(uploader)s et al) instead.') + + def add_info_extractor(self, ie): + """Add an InfoExtractor object to the end of the list.""" + self._ies.append(ie) + ie.set_downloader(self) + + def add_post_processor(self, pp): + """Add a PostProcessor object to the end of the chain.""" + self._pps.append(pp) + pp.set_downloader(self) + + def to_screen(self, message, skip_eol=False): + """Print message to stdout if not in quiet mode.""" + assert type(message) == type(u'') + if not self.params.get('quiet', False): + terminator = [u'\n', u''][skip_eol] + output = message + terminator + if 'b' in getattr(self._screen_file, 'mode', '') or sys.version_info[0] < 3: # Python 2 lies about the mode of sys.stdout/sys.stderr + output = output.encode(preferredencoding(), 'ignore') + self._screen_file.write(output) + self._screen_file.flush() + + def to_stderr(self, message): + """Print message to stderr.""" + assert type(message) == type(u'') + output = message + u'\n' + if 'b' in getattr(self._screen_file, 'mode', '') or sys.version_info[0] < 3: # Python 2 lies about the mode of sys.stdout/sys.stderr + output = output.encode(preferredencoding()) + sys.stderr.write(output) + + def fixed_template(self): + """Checks if the output template is fixed.""" + return (re.search(u'(?u)%\\(.+?\\)s', self.params['outtmpl']) is None) + + def trouble(self, message=None, tb=None): + """Determine action to take when a download problem appears. + + Depending on if the downloader has been configured to ignore + download errors or not, this method may throw an exception or + not when errors are found, after printing the message. + + tb, if given, is additional traceback information. + """ + if message is not None: + self.to_stderr(message) + if self.params.get('verbose'): + if tb is None: + if sys.exc_info()[0]: # if .trouble has been called from an except block + tb = u'' + if hasattr(sys.exc_info()[1], 'exc_info') and sys.exc_info()[1].exc_info[0]: + tb += u''.join(traceback.format_exception(*sys.exc_info()[1].exc_info)) + tb += compat_str(traceback.format_exc()) + else: + tb_data = traceback.format_list(traceback.extract_stack()) + tb = u''.join(tb_data) + self.to_stderr(tb) + if not self.params.get('ignoreerrors', False): + if sys.exc_info()[0] and hasattr(sys.exc_info()[1], 'exc_info') and sys.exc_info()[1].exc_info[0]: + exc_info = sys.exc_info()[1].exc_info + else: + exc_info = sys.exc_info() + raise DownloadError(message, exc_info) + self._download_retcode = 1 + + def report_warning(self, message): + ''' + Print the message to stderr, it will be prefixed with 'WARNING:' + If stderr is a tty file the 'WARNING:' will be colored + ''' + if sys.stderr.isatty() and os.name != 'nt': + _msg_header=u'\033[0;33mWARNING:\033[0m' + else: + _msg_header=u'WARNING:' + warning_message=u'%s %s' % (_msg_header,message) + self.to_stderr(warning_message) + + def report_error(self, message, tb=None): + ''' + Do the same as trouble, but prefixes the message with 'ERROR:', colored + in red if stderr is a tty file. + ''' + if sys.stderr.isatty() and os.name != 'nt': + _msg_header = u'\033[0;31mERROR:\033[0m' + else: + _msg_header = u'ERROR:' + error_message = u'%s %s' % (_msg_header, message) + self.trouble(error_message, tb) + + def slow_down(self, start_time, byte_counter): + """Sleep if the download speed is over the rate limit.""" + rate_limit = self.params.get('ratelimit', None) + if rate_limit is None or byte_counter == 0: + return + now = time.time() + elapsed = now - start_time + if elapsed <= 0.0: + return + speed = float(byte_counter) / elapsed + if speed > rate_limit: + time.sleep((byte_counter - rate_limit * (now - start_time)) / rate_limit) + + def report_writedescription(self, descfn): + """ Report that the description file is being written """ + self.to_screen(u'[info] Writing video description to: ' + descfn) + + def report_writesubtitles(self, sub_filename): + """ Report that the subtitles file is being written """ + self.to_screen(u'[info] Writing video subtitles to: ' + sub_filename) + + def report_writeinfojson(self, infofn): + """ Report that the metadata file has been written """ + self.to_screen(u'[info] Video description metadata as JSON to: ' + infofn) + + def report_file_already_downloaded(self, file_name): + """Report file has already been fully downloaded.""" + try: + self.to_screen(u'[download] %s has already been downloaded' % file_name) + except (UnicodeEncodeError) as err: + self.to_screen(u'[download] The file has already been downloaded') + + def increment_downloads(self): + """Increment the ordinal that assigns a number to each file.""" + self._num_downloads += 1 + + def prepare_filename(self, info_dict): + """Generate the output filename.""" + try: + template_dict = dict(info_dict) + + template_dict['epoch'] = int(time.time()) + autonumber_size = self.params.get('autonumber_size') + if autonumber_size is None: + autonumber_size = 5 + autonumber_templ = u'%0' + str(autonumber_size) + u'd' + template_dict['autonumber'] = autonumber_templ % self._num_downloads + if template_dict['playlist_index'] is not None: + template_dict['playlist_index'] = u'%05d' % template_dict['playlist_index'] + + sanitize = lambda k,v: sanitize_filename( + u'NA' if v is None else compat_str(v), + restricted=self.params.get('restrictfilenames'), + is_id=(k==u'id')) + template_dict = dict((k, sanitize(k, v)) for k,v in template_dict.items()) + + filename = self.params['outtmpl'] % template_dict + return filename + except KeyError as err: + self.report_error(u'Erroneous output template') + return None + except ValueError as err: + self.report_error(u'Insufficient system charset ' + repr(preferredencoding())) + return None + + def _match_entry(self, info_dict): + """ Returns None iff the file should be downloaded """ + + title = info_dict['title'] + matchtitle = self.params.get('matchtitle', False) + if matchtitle: + if not re.search(matchtitle, title, re.IGNORECASE): + return u'[download] "' + title + '" title did not match pattern "' + matchtitle + '"' + rejecttitle = self.params.get('rejecttitle', False) + if rejecttitle: + if re.search(rejecttitle, title, re.IGNORECASE): + return u'"' + title + '" title matched reject pattern "' + rejecttitle + '"' + date = info_dict.get('upload_date', None) + if date is not None: + dateRange = self.params.get('daterange', DateRange()) + if date not in dateRange: + return u'[download] %s upload date is not in range %s' % (date_from_str(date).isoformat(), dateRange) + return None + + def extract_info(self, url, download=True, ie_key=None, extra_info={}): + ''' + Returns a list with a dictionary for each video we find. + If 'download', also downloads the videos. + extra_info is a dict containing the extra values to add to each result + ''' + + if ie_key: + ie = get_info_extractor(ie_key)() + ie.set_downloader(self) + ies = [ie] + else: + ies = self._ies + + for ie in ies: + if not ie.suitable(url): + continue + + if not ie.working(): + self.report_warning(u'The program functionality for this site has been marked as broken, ' + u'and will probably not work.') + + try: + ie_result = ie.extract(url) + if ie_result is None: # Finished already (backwards compatibility; listformats and friends should be moved here) + break + if isinstance(ie_result, list): + # Backwards compatibility: old IE result format + for result in ie_result: + result.update(extra_info) + ie_result = { + '_type': 'compat_list', + 'entries': ie_result, + } + else: + ie_result.update(extra_info) + if 'extractor' not in ie_result: + ie_result['extractor'] = ie.IE_NAME + return self.process_ie_result(ie_result, download=download) + except ExtractorError as de: # An error we somewhat expected + self.report_error(compat_str(de), de.format_traceback()) + break + except Exception as e: + if self.params.get('ignoreerrors', False): + self.report_error(compat_str(e), tb=compat_str(traceback.format_exc())) + break + else: + raise + else: + self.report_error(u'no suitable InfoExtractor: %s' % url) + + def process_ie_result(self, ie_result, download=True, extra_info={}): + """ + Take the result of the ie(may be modified) and resolve all unresolved + references (URLs, playlist items). + + It will also download the videos if 'download'. + Returns the resolved ie_result. + """ + + result_type = ie_result.get('_type', 'video') # If not given we suppose it's a video, support the default old system + if result_type == 'video': + if 'playlist' not in ie_result: + # It isn't part of a playlist + ie_result['playlist'] = None + ie_result['playlist_index'] = None + if download: + self.process_info(ie_result) + return ie_result + elif result_type == 'url': + # We have to add extra_info to the results because it may be + # contained in a playlist + return self.extract_info(ie_result['url'], + download, + ie_key=ie_result.get('ie_key'), + extra_info=extra_info) + elif result_type == 'playlist': + # We process each entry in the playlist + playlist = ie_result.get('title', None) or ie_result.get('id', None) + self.to_screen(u'[download] Downloading playlist: %s' % playlist) + + playlist_results = [] + + n_all_entries = len(ie_result['entries']) + playliststart = self.params.get('playliststart', 1) - 1 + playlistend = self.params.get('playlistend', -1) + + if playlistend == -1: + entries = ie_result['entries'][playliststart:] + else: + entries = ie_result['entries'][playliststart:playlistend] + + n_entries = len(entries) + + self.to_screen(u"[%s] playlist '%s': Collected %d video ids (downloading %d of them)" % + (ie_result['extractor'], playlist, n_all_entries, n_entries)) + + for i,entry in enumerate(entries,1): + self.to_screen(u'[download] Downloading video #%s of %s' %(i, n_entries)) + extra = { + 'playlist': playlist, + 'playlist_index': i + playliststart, + } + if not 'extractor' in entry: + # We set the extractor, if it's an url it will be set then to + # the new extractor, but if it's already a video we must make + # sure it's present: see issue #877 + entry['extractor'] = ie_result['extractor'] + entry_result = self.process_ie_result(entry, + download=download, + extra_info=extra) + playlist_results.append(entry_result) + ie_result['entries'] = playlist_results + return ie_result + elif result_type == 'compat_list': + def _fixup(r): + r.setdefault('extractor', ie_result['extractor']) + return r + ie_result['entries'] = [ + self.process_ie_result(_fixup(r), download=download) + for r in ie_result['entries'] + ] + return ie_result + else: + raise Exception('Invalid result type: %s' % result_type) + + def process_info(self, info_dict): + """Process a single resolved IE result.""" + + assert info_dict.get('_type', 'video') == 'video' + #We increment the download the download count here to match the previous behaviour. + self.increment_downloads() + + info_dict['fulltitle'] = info_dict['title'] + if len(info_dict['title']) > 200: + info_dict['title'] = info_dict['title'][:197] + u'...' + + # Keep for backwards compatibility + info_dict['stitle'] = info_dict['title'] + + if not 'format' in info_dict: + info_dict['format'] = info_dict['ext'] + + reason = self._match_entry(info_dict) + if reason is not None: + self.to_screen(u'[download] ' + reason) + return + + max_downloads = self.params.get('max_downloads') + if max_downloads is not None: + if self._num_downloads > int(max_downloads): + raise MaxDownloadsReached() + + filename = self.prepare_filename(info_dict) + + # Forced printings + if self.params.get('forcetitle', False): + compat_print(info_dict['title']) + if self.params.get('forceid', False): + compat_print(info_dict['id']) + if self.params.get('forceurl', False): + compat_print(info_dict['url']) + if self.params.get('forcethumbnail', False) and 'thumbnail' in info_dict: + compat_print(info_dict['thumbnail']) + if self.params.get('forcedescription', False) and 'description' in info_dict: + compat_print(info_dict['description']) + if self.params.get('forcefilename', False) and filename is not None: + compat_print(filename) + if self.params.get('forceformat', False): + compat_print(info_dict['format']) + + # Do nothing else if in simulate mode + if self.params.get('simulate', False): + return + + if filename is None: + return + + try: + dn = os.path.dirname(encodeFilename(filename)) + if dn != '' and not os.path.exists(dn): + os.makedirs(dn) + except (OSError, IOError) as err: + self.report_error(u'unable to create directory ' + compat_str(err)) + return + + if self.params.get('writedescription', False): + try: + descfn = filename + u'.description' + self.report_writedescription(descfn) + with io.open(encodeFilename(descfn), 'w', encoding='utf-8') as descfile: + descfile.write(info_dict['description']) + except (OSError, IOError): + self.report_error(u'Cannot write description file ' + descfn) + return + + if self.params.get('writesubtitles', False) and 'subtitles' in info_dict and info_dict['subtitles']: + # subtitles download errors are already managed as troubles in relevant IE + # that way it will silently go on when used with unsupporting IE + subtitle = info_dict['subtitles'][0] + (sub_error, sub_lang, sub) = subtitle + sub_format = self.params.get('subtitlesformat') + if sub_error: + self.report_warning("Some error while getting the subtitles") + else: + try: + sub_filename = filename.rsplit('.', 1)[0] + u'.' + sub_lang + u'.' + sub_format + self.report_writesubtitles(sub_filename) + with io.open(encodeFilename(sub_filename), 'w', encoding='utf-8') as subfile: + subfile.write(sub) + except (OSError, IOError): + self.report_error(u'Cannot write subtitles file ' + descfn) + return + + if self.params.get('allsubtitles', False) and 'subtitles' in info_dict and info_dict['subtitles']: + subtitles = info_dict['subtitles'] + sub_format = self.params.get('subtitlesformat') + for subtitle in subtitles: + (sub_error, sub_lang, sub) = subtitle + if sub_error: + self.report_warning("Some error while getting the subtitles") + else: + try: + sub_filename = filename.rsplit('.', 1)[0] + u'.' + sub_lang + u'.' + sub_format + self.report_writesubtitles(sub_filename) + with io.open(encodeFilename(sub_filename), 'w', encoding='utf-8') as subfile: + subfile.write(sub) + except (OSError, IOError): + self.report_error(u'Cannot write subtitles file ' + descfn) + return + + if self.params.get('writeinfojson', False): + infofn = filename + u'.info.json' + self.report_writeinfojson(infofn) + try: + json_info_dict = dict((k, v) for k,v in info_dict.items() if not k in ['urlhandle']) + write_json_file(json_info_dict, encodeFilename(infofn)) + except (OSError, IOError): + self.report_error(u'Cannot write metadata to JSON file ' + infofn) + return + + if self.params.get('writethumbnail', False): + if 'thumbnail' in info_dict: + thumb_format = info_dict['thumbnail'].rpartition(u'/')[2].rpartition(u'.')[2] + if not thumb_format: + thumb_format = 'jpg' + thumb_filename = filename.rpartition('.')[0] + u'.' + thumb_format + self.to_screen(u'[%s] %s: Downloading thumbnail ...' % + (info_dict['extractor'], info_dict['id'])) + uf = compat_urllib_request.urlopen(info_dict['thumbnail']) + with open(thumb_filename, 'wb') as thumbf: + shutil.copyfileobj(uf, thumbf) + self.to_screen(u'[%s] %s: Writing thumbnail to: %s' % + (info_dict['extractor'], info_dict['id'], thumb_filename)) + + if not self.params.get('skip_download', False): + if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(filename)): + success = True + else: + try: + success = self.fd._do_download(filename, info_dict) + except (OSError, IOError) as err: + raise UnavailableVideoError() + except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err: + self.report_error(u'unable to download video data: %s' % str(err)) + return + except (ContentTooShortError, ) as err: + self.report_error(u'content too short (expected %s bytes and served %s)' % (err.expected, err.downloaded)) + return + + if success: + try: + self.post_process(filename, info_dict) + except (PostProcessingError) as err: + self.report_error(u'postprocessing: %s' % str(err)) + return + + def download(self, url_list): + """Download a given list of URLs.""" + if len(url_list) > 1 and self.fixed_template(): + raise SameFileError(self.params['outtmpl']) + + for url in url_list: + try: + #It also downloads the videos + videos = self.extract_info(url) + except UnavailableVideoError: + self.report_error(u'unable to download video') + except MaxDownloadsReached: + self.to_screen(u'[info] Maximum number of downloaded files reached.') + raise + + return self._download_retcode + + def post_process(self, filename, ie_info): + """Run all the postprocessors on the given file.""" + info = dict(ie_info) + info['filepath'] = filename + keep_video = None + for pp in self._pps: + try: + keep_video_wish,new_info = pp.run(info) + if keep_video_wish is not None: + if keep_video_wish: + keep_video = keep_video_wish + elif keep_video is None: + # No clear decision yet, let IE decide + keep_video = keep_video_wish + except PostProcessingError as e: + self.to_stderr(u'ERROR: ' + e.msg) + if keep_video is False and not self.params.get('keepvideo', False): + try: + self.to_screen(u'Deleting original file %s (pass -k to keep)' % filename) + os.remove(encodeFilename(filename)) + except (IOError, OSError): + self.report_warning(u'Unable to remove downloaded video file') diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index a8b62a6..2acaab6 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -25,6 +25,7 @@ __authors__ = ( 'M. Yasoob Ullah Khalid', 'Julien Fraichard', 'Johny Mo Swag', + 'Axel Noack', ) __license__ = 'Public Domain' @@ -46,6 +47,7 @@ from .update import update_self from .version import __version__ from .FileDownloader import * from .extractor import gen_extractors +from .YoutubeDL import YoutubeDL from .PostProcessor import * def parseOpts(overrideArguments=None): @@ -171,6 +173,8 @@ def parseOpts(overrideArguments=None): dest='password', metavar='PASSWORD', help='account password') authentication.add_option('-n', '--netrc', action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False) + authentication.add_option('--video-password', + dest='videopassword', metavar='PASSWORD', help='video password (vimeo only)') video_format.add_option('-f', '--format', @@ -318,7 +322,7 @@ def parseOpts(overrideArguments=None): if overrideArguments is not None: opts, args = parser.parse_args(overrideArguments) if opts.verbose: - print(u'[debug] Override config: ' + repr(overrideArguments)) + sys.stderr.write(u'[debug] Override config: ' + repr(overrideArguments) + '\n') else: xdg_config_home = os.environ.get('XDG_CONFIG_HOME') if xdg_config_home: @@ -331,9 +335,9 @@ def parseOpts(overrideArguments=None): argv = systemConf + userConf + commandLineConf opts, args = parser.parse_args(argv) if opts.verbose: - print(u'[debug] System config: ' + repr(systemConf)) - print(u'[debug] User config: ' + repr(userConf)) - print(u'[debug] Command-line args: ' + repr(commandLineConf)) + sys.stderr.write(u'[debug] System config: ' + repr(systemConf) + '\n') + sys.stderr.write(u'[debug] User config: ' + repr(userConf) + '\n') + sys.stderr.write(u'[debug] Command-line args: ' + repr(commandLineConf) + '\n') return parser, opts, args @@ -368,7 +372,7 @@ def _real_main(argv=None): # Dump user agent if opts.dump_user_agent: - print(std_headers['User-Agent']) + compat_print(std_headers['User-Agent']) sys.exit(0) # Batch file verification @@ -409,18 +413,18 @@ def _real_main(argv=None): if opts.list_extractors: for ie in extractors: - print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else '')) + compat_print(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie._WORKING else '')) matchedUrls = [url for url in all_urls if ie.suitable(url)] all_urls = [url for url in all_urls if url not in matchedUrls] for mu in matchedUrls: - print(u' ' + mu) + compat_print(u' ' + mu) sys.exit(0) # Conflicting, missing and erroneous options if opts.usenetrc and (opts.username is not None or opts.password is not None): parser.error(u'using .netrc conflicts with giving username/password') if opts.password is not None and opts.username is None: - print(u'WARNING: account username missing') + parser.error(u' account username missing\n') if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid): parser.error(u'using output template conflicts with using title, video ID or auto number') if opts.usetitle and opts.useid: @@ -492,11 +496,12 @@ def _real_main(argv=None): or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s') or u'%(title)s-%(id)s.%(ext)s') - # File downloader - fd = FileDownloader({ + # YoutubeDL + ydl = YoutubeDL({ 'usenetrc': opts.usenetrc, 'username': opts.username, 'password': opts.password, + 'videopassword': opts.videopassword, 'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat), 'forceurl': opts.geturl, 'forcetitle': opts.gettitle, @@ -550,31 +555,31 @@ def _real_main(argv=None): }) if opts.verbose: - fd.to_screen(u'[debug] youtube-dl version ' + __version__) + ydl.to_screen(u'[debug] youtube-dl version ' + __version__) try: sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.path.dirname(os.path.abspath(__file__))) out, err = sp.communicate() out = out.decode().strip() if re.match('[0-9a-f]+', out): - fd.to_screen(u'[debug] Git HEAD: ' + out) + ydl.to_screen(u'[debug] Git HEAD: ' + out) except: pass - fd.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform())) - fd.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies)) + ydl.to_screen(u'[debug] Python version %s - %s' %(platform.python_version(), platform.platform())) + ydl.to_screen(u'[debug] Proxy map: ' + str(proxy_handler.proxies)) for extractor in extractors: - fd.add_info_extractor(extractor) + ydl.add_info_extractor(extractor) # PostProcessors if opts.extractaudio: - fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites)) + ydl.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, nopostoverwrites=opts.nopostoverwrites)) if opts.recodevideo: - fd.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo)) + ydl.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.recodevideo)) # Update version if opts.update_self: - update_self(fd.to_screen, opts.verbose, sys.argv[0]) + update_self(ydl.to_screen, opts.verbose, sys.argv[0]) # Maybe do nothing if len(all_urls) < 1: @@ -584,9 +589,9 @@ def _real_main(argv=None): sys.exit() try: - retcode = fd.download(all_urls) + retcode = ydl.download(all_urls) except MaxDownloadsReached: - fd.to_screen(u'--max-download limit reached, aborting.') + ydl.to_screen(u'--max-download limit reached, aborting.') retcode = 101 # Dump cookie jar if requested diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index b208f90..0ea9908 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -4,8 +4,8 @@ from .arte import ArteTvIE from .bandcamp import BandcampIE from .bliptv import BlipTVIE, BlipTVUserIE from .breakcom import BreakIE -from .comedycentral import ComedyCentralIE from .collegehumor import CollegeHumorIE +from .comedycentral import ComedyCentralIE from .dailymotion import DailymotionIE from .depositfiles import DepositFilesIE from .eighttracks import EightTracksIE @@ -21,6 +21,7 @@ from .howcast import HowcastIE from .hypem import HypemIE from .ina import InaIE from .infoq import InfoQIE +from .jukebox import JukeboxIE from .justintv import JustinTVIE from .keek import KeekIE from .liveleak import LiveLeakIE @@ -30,7 +31,6 @@ from .mtv import MTVIE from .myspass import MySpassIE from .myvideo import MyVideoIE from .nba import NBAIE -from .statigram import StatigramIE from .photobucket import PhotobucketIE from .pornotube import PornotubeIE from .rbmaradio import RBMARadioIE @@ -38,17 +38,20 @@ from .redtube import RedTubeIE from .soundcloud import SoundcloudIE, SoundcloudSetIE from .spiegel import SpiegelIE from .stanfordoc import StanfordOpenClassroomIE +from .statigram import StatigramIE from .steam import SteamIE from .teamcoco import TeamcocoIE from .ted import TEDIE +from .tudou import TudouIE from .tumblr import TumblrIE from .ustream import UstreamIE from .vbox7 import Vbox7IE +from .vevo import VevoIE from .vimeo import VimeoIE from .vine import VineIE from .worldstarhiphop import WorldStarHipHopIE -from .xnxx import XNXXIE from .xhamster import XHamsterIE +from .xnxx import XNXXIE from .xvideos import XVideosIE from .yahoo import YahooIE, YahooSearchIE from .youjizz import YouJizzIE @@ -57,6 +60,7 @@ from .youporn import YouPornIE from .youtube import YoutubeIE, YoutubePlaylistIE, YoutubeSearchIE, YoutubeUserIE, YoutubeChannelIE from .zdf import ZDFIE + def gen_extractors(): """ Return a list of an instance of every supported extractor. The order does matter; the first extractor matched is the one handling the URL. @@ -125,6 +129,9 @@ def gen_extractors(): GametrailersIE(), StatigramIE(), BreakIE(), + VevoIE(), + JukeboxIE(), + TudouIE(), GenericIE() ] diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 062f4cf..64d63e1 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -211,7 +211,7 @@ class InfoExtractor(object): raise ExtractorError(u'Unable to extract %s' % _name) else: self._downloader.report_warning(u'unable to extract %s; ' - u'please report this issue on GitHub.' % _name) + u'please report this issue on http://yt-dl.org/bug' % _name) return None def _html_search_regex(self, pattern, string, name, default=None, fatal=True, flags=0): diff --git a/youtube_dl/extractor/googleplus.py b/youtube_dl/extractor/googleplus.py index e922bd1..ff2cdee 100644 --- a/youtube_dl/extractor/googleplus.py +++ b/youtube_dl/extractor/googleplus.py @@ -46,14 +46,18 @@ class GooglePlusIE(InfoExtractor): video_title = self._html_search_regex(r'[a-z0-9\-]+).html' + _IFRAME = r'