|
@ -2872,180 +2872,182 @@ def parseOpts(): |
|
|
|
|
|
|
|
|
return parser, opts, args |
|
|
return parser, opts, args |
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
|
|
parser, opts, args = parseOpts() |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
try: |
|
|
|
|
|
parser, opts, args = parseOpts() |
|
|
|
|
|
|
|
|
|
|
|
# Open appropriate CookieJar |
|
|
|
|
|
if opts.cookiefile is None: |
|
|
|
|
|
jar = cookielib.CookieJar() |
|
|
|
|
|
else: |
|
|
|
|
|
try: |
|
|
|
|
|
jar = cookielib.MozillaCookieJar(opts.cookiefile) |
|
|
|
|
|
if os.path.isfile(opts.cookiefile) and os.access(opts.cookiefile, os.R_OK): |
|
|
|
|
|
jar.load() |
|
|
|
|
|
except (IOError, OSError), err: |
|
|
|
|
|
sys.exit(u'ERROR: unable to open cookie file') |
|
|
|
|
|
|
|
|
# Open appropriate CookieJar |
|
|
|
|
|
if opts.cookiefile is None: |
|
|
|
|
|
jar = cookielib.CookieJar() |
|
|
|
|
|
else: |
|
|
|
|
|
try: |
|
|
|
|
|
jar = cookielib.MozillaCookieJar(opts.cookiefile) |
|
|
|
|
|
if os.path.isfile(opts.cookiefile) and os.access(opts.cookiefile, os.R_OK): |
|
|
|
|
|
jar.load() |
|
|
|
|
|
except (IOError, OSError), err: |
|
|
|
|
|
sys.exit(u'ERROR: unable to open cookie file') |
|
|
|
|
|
|
|
|
# Dump user agent |
|
|
|
|
|
if opts.dump_user_agent: |
|
|
|
|
|
print std_headers['User-Agent'] |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
# Dump user agent |
|
|
|
|
|
if opts.dump_user_agent: |
|
|
|
|
|
print std_headers['User-Agent'] |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
# General configuration |
|
|
|
|
|
cookie_processor = urllib2.HTTPCookieProcessor(jar) |
|
|
|
|
|
urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler(), cookie_processor, YoutubeDLHandler())) |
|
|
|
|
|
socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words) |
|
|
|
|
|
|
|
|
# General configuration |
|
|
|
|
|
cookie_processor = urllib2.HTTPCookieProcessor(jar) |
|
|
|
|
|
urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler(), cookie_processor, YoutubeDLHandler())) |
|
|
|
|
|
socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words) |
|
|
|
|
|
|
|
|
# Batch file verification |
|
|
|
|
|
batchurls = [] |
|
|
|
|
|
if opts.batchfile is not None: |
|
|
|
|
|
try: |
|
|
|
|
|
if opts.batchfile == '-': |
|
|
|
|
|
batchfd = sys.stdin |
|
|
|
|
|
else: |
|
|
|
|
|
batchfd = open(opts.batchfile, 'r') |
|
|
|
|
|
batchurls = batchfd.readlines() |
|
|
|
|
|
batchurls = [x.strip() for x in batchurls] |
|
|
|
|
|
batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)] |
|
|
|
|
|
except IOError: |
|
|
|
|
|
sys.exit(u'ERROR: batch file could not be read') |
|
|
|
|
|
all_urls = batchurls + args |
|
|
|
|
|
|
|
|
|
|
|
# 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: |
|
|
|
|
|
parser.error(u'account username missing') |
|
|
|
|
|
if opts.outtmpl is not None and (opts.useliteral or opts.usetitle or opts.autonumber): |
|
|
|
|
|
parser.error(u'using output template conflicts with using title, literal title or auto number') |
|
|
|
|
|
if opts.usetitle and opts.useliteral: |
|
|
|
|
|
parser.error(u'using title conflicts with using literal title') |
|
|
|
|
|
if opts.username is not None and opts.password is None: |
|
|
|
|
|
opts.password = getpass.getpass(u'Type account password and press return:') |
|
|
|
|
|
if opts.ratelimit is not None: |
|
|
|
|
|
numeric_limit = FileDownloader.parse_bytes(opts.ratelimit) |
|
|
|
|
|
if numeric_limit is None: |
|
|
|
|
|
parser.error(u'invalid rate limit specified') |
|
|
|
|
|
opts.ratelimit = numeric_limit |
|
|
|
|
|
if opts.retries is not None: |
|
|
|
|
|
try: |
|
|
|
|
|
opts.retries = long(opts.retries) |
|
|
|
|
|
except (TypeError, ValueError), err: |
|
|
|
|
|
parser.error(u'invalid retry count specified') |
|
|
|
|
|
|
|
|
# Batch file verification |
|
|
|
|
|
batchurls = [] |
|
|
|
|
|
if opts.batchfile is not None: |
|
|
try: |
|
|
try: |
|
|
opts.playliststart = long(opts.playliststart) |
|
|
|
|
|
if opts.playliststart <= 0: |
|
|
|
|
|
raise ValueError |
|
|
|
|
|
except (TypeError, ValueError), err: |
|
|
|
|
|
parser.error(u'invalid playlist start number specified') |
|
|
|
|
|
|
|
|
if opts.batchfile == '-': |
|
|
|
|
|
batchfd = sys.stdin |
|
|
|
|
|
else: |
|
|
|
|
|
batchfd = open(opts.batchfile, 'r') |
|
|
|
|
|
batchurls = batchfd.readlines() |
|
|
|
|
|
batchurls = [x.strip() for x in batchurls] |
|
|
|
|
|
batchurls = [x for x in batchurls if len(x) > 0 and not re.search(r'^[#/;]', x)] |
|
|
|
|
|
except IOError: |
|
|
|
|
|
sys.exit(u'ERROR: batch file could not be read') |
|
|
|
|
|
all_urls = batchurls + args |
|
|
|
|
|
|
|
|
|
|
|
# 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: |
|
|
|
|
|
parser.error(u'account username missing') |
|
|
|
|
|
if opts.outtmpl is not None and (opts.useliteral or opts.usetitle or opts.autonumber): |
|
|
|
|
|
parser.error(u'using output template conflicts with using title, literal title or auto number') |
|
|
|
|
|
if opts.usetitle and opts.useliteral: |
|
|
|
|
|
parser.error(u'using title conflicts with using literal title') |
|
|
|
|
|
if opts.username is not None and opts.password is None: |
|
|
|
|
|
opts.password = getpass.getpass(u'Type account password and press return:') |
|
|
|
|
|
if opts.ratelimit is not None: |
|
|
|
|
|
numeric_limit = FileDownloader.parse_bytes(opts.ratelimit) |
|
|
|
|
|
if numeric_limit is None: |
|
|
|
|
|
parser.error(u'invalid rate limit specified') |
|
|
|
|
|
opts.ratelimit = numeric_limit |
|
|
|
|
|
if opts.retries is not None: |
|
|
try: |
|
|
try: |
|
|
opts.playlistend = long(opts.playlistend) |
|
|
|
|
|
if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart): |
|
|
|
|
|
raise ValueError |
|
|
|
|
|
|
|
|
opts.retries = long(opts.retries) |
|
|
except (TypeError, ValueError), err: |
|
|
except (TypeError, ValueError), err: |
|
|
parser.error(u'invalid playlist end number specified') |
|
|
|
|
|
if opts.extractaudio: |
|
|
|
|
|
if opts.audioformat not in ['best', 'aac', 'mp3']: |
|
|
|
|
|
parser.error(u'invalid audio format specified') |
|
|
|
|
|
|
|
|
|
|
|
# Information extractors |
|
|
|
|
|
youtube_ie = YoutubeIE() |
|
|
|
|
|
metacafe_ie = MetacafeIE(youtube_ie) |
|
|
|
|
|
dailymotion_ie = DailymotionIE() |
|
|
|
|
|
youtube_pl_ie = YoutubePlaylistIE(youtube_ie) |
|
|
|
|
|
youtube_user_ie = YoutubeUserIE(youtube_ie) |
|
|
|
|
|
youtube_search_ie = YoutubeSearchIE(youtube_ie) |
|
|
|
|
|
google_ie = GoogleIE() |
|
|
|
|
|
google_search_ie = GoogleSearchIE(google_ie) |
|
|
|
|
|
photobucket_ie = PhotobucketIE() |
|
|
|
|
|
yahoo_ie = YahooIE() |
|
|
|
|
|
yahoo_search_ie = YahooSearchIE(yahoo_ie) |
|
|
|
|
|
deposit_files_ie = DepositFilesIE() |
|
|
|
|
|
facebook_ie = FacebookIE() |
|
|
|
|
|
generic_ie = GenericIE() |
|
|
|
|
|
|
|
|
|
|
|
# File downloader |
|
|
|
|
|
fd = FileDownloader({ |
|
|
|
|
|
'usenetrc': opts.usenetrc, |
|
|
|
|
|
'username': opts.username, |
|
|
|
|
|
'password': opts.password, |
|
|
|
|
|
'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename), |
|
|
|
|
|
'forceurl': opts.geturl, |
|
|
|
|
|
'forcetitle': opts.gettitle, |
|
|
|
|
|
'forcethumbnail': opts.getthumbnail, |
|
|
|
|
|
'forcedescription': opts.getdescription, |
|
|
|
|
|
'forcefilename': opts.getfilename, |
|
|
|
|
|
'simulate': (opts.simulate or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename), |
|
|
|
|
|
'format': opts.format, |
|
|
|
|
|
'format_limit': opts.format_limit, |
|
|
|
|
|
'outtmpl': ((opts.outtmpl is not None and opts.outtmpl.decode(preferredencoding())) |
|
|
|
|
|
or (opts.format == '-1' and opts.usetitle and u'%(stitle)s-%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.format == '-1' and opts.useliteral and u'%(title)s-%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(stitle)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.useliteral and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.usetitle and u'%(stitle)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.useliteral and u'%(title)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s') |
|
|
|
|
|
or u'%(id)s.%(ext)s'), |
|
|
|
|
|
'ignoreerrors': opts.ignoreerrors, |
|
|
|
|
|
'ratelimit': opts.ratelimit, |
|
|
|
|
|
'nooverwrites': opts.nooverwrites, |
|
|
|
|
|
'retries': opts.retries, |
|
|
|
|
|
'continuedl': opts.continue_dl, |
|
|
|
|
|
'noprogress': opts.noprogress, |
|
|
|
|
|
'playliststart': opts.playliststart, |
|
|
|
|
|
'playlistend': opts.playlistend, |
|
|
|
|
|
'logtostderr': opts.outtmpl == '-', |
|
|
|
|
|
'consoletitle': opts.consoletitle, |
|
|
|
|
|
'nopart': opts.nopart, |
|
|
|
|
|
'updatetime': opts.updatetime, |
|
|
|
|
|
}) |
|
|
|
|
|
fd.add_info_extractor(youtube_search_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_pl_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_user_ie) |
|
|
|
|
|
fd.add_info_extractor(metacafe_ie) |
|
|
|
|
|
fd.add_info_extractor(dailymotion_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_ie) |
|
|
|
|
|
fd.add_info_extractor(google_ie) |
|
|
|
|
|
fd.add_info_extractor(google_search_ie) |
|
|
|
|
|
fd.add_info_extractor(photobucket_ie) |
|
|
|
|
|
fd.add_info_extractor(yahoo_ie) |
|
|
|
|
|
fd.add_info_extractor(yahoo_search_ie) |
|
|
|
|
|
fd.add_info_extractor(deposit_files_ie) |
|
|
|
|
|
fd.add_info_extractor(facebook_ie) |
|
|
|
|
|
|
|
|
|
|
|
# This must come last since it's the |
|
|
|
|
|
# fallback if none of the others work |
|
|
|
|
|
fd.add_info_extractor(generic_ie) |
|
|
|
|
|
|
|
|
|
|
|
# PostProcessors |
|
|
|
|
|
if opts.extractaudio: |
|
|
|
|
|
fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat)) |
|
|
|
|
|
|
|
|
|
|
|
# Update version |
|
|
|
|
|
if opts.update_self: |
|
|
|
|
|
updateSelf(fd, sys.argv[0]) |
|
|
|
|
|
|
|
|
|
|
|
# Maybe do nothing |
|
|
|
|
|
if len(all_urls) < 1: |
|
|
|
|
|
if not opts.update_self: |
|
|
|
|
|
parser.error(u'you must provide at least one URL') |
|
|
|
|
|
else: |
|
|
|
|
|
sys.exit() |
|
|
|
|
|
retcode = fd.download(all_urls) |
|
|
|
|
|
|
|
|
parser.error(u'invalid retry count specified') |
|
|
|
|
|
try: |
|
|
|
|
|
opts.playliststart = long(opts.playliststart) |
|
|
|
|
|
if opts.playliststart <= 0: |
|
|
|
|
|
raise ValueError |
|
|
|
|
|
except (TypeError, ValueError), err: |
|
|
|
|
|
parser.error(u'invalid playlist start number specified') |
|
|
|
|
|
try: |
|
|
|
|
|
opts.playlistend = long(opts.playlistend) |
|
|
|
|
|
if opts.playlistend != -1 and (opts.playlistend <= 0 or opts.playlistend < opts.playliststart): |
|
|
|
|
|
raise ValueError |
|
|
|
|
|
except (TypeError, ValueError), err: |
|
|
|
|
|
parser.error(u'invalid playlist end number specified') |
|
|
|
|
|
if opts.extractaudio: |
|
|
|
|
|
if opts.audioformat not in ['best', 'aac', 'mp3']: |
|
|
|
|
|
parser.error(u'invalid audio format specified') |
|
|
|
|
|
|
|
|
|
|
|
# Information extractors |
|
|
|
|
|
youtube_ie = YoutubeIE() |
|
|
|
|
|
metacafe_ie = MetacafeIE(youtube_ie) |
|
|
|
|
|
dailymotion_ie = DailymotionIE() |
|
|
|
|
|
youtube_pl_ie = YoutubePlaylistIE(youtube_ie) |
|
|
|
|
|
youtube_user_ie = YoutubeUserIE(youtube_ie) |
|
|
|
|
|
youtube_search_ie = YoutubeSearchIE(youtube_ie) |
|
|
|
|
|
google_ie = GoogleIE() |
|
|
|
|
|
google_search_ie = GoogleSearchIE(google_ie) |
|
|
|
|
|
photobucket_ie = PhotobucketIE() |
|
|
|
|
|
yahoo_ie = YahooIE() |
|
|
|
|
|
yahoo_search_ie = YahooSearchIE(yahoo_ie) |
|
|
|
|
|
deposit_files_ie = DepositFilesIE() |
|
|
|
|
|
facebook_ie = FacebookIE() |
|
|
|
|
|
generic_ie = GenericIE() |
|
|
|
|
|
|
|
|
|
|
|
# File downloader |
|
|
|
|
|
fd = FileDownloader({ |
|
|
|
|
|
'usenetrc': opts.usenetrc, |
|
|
|
|
|
'username': opts.username, |
|
|
|
|
|
'password': opts.password, |
|
|
|
|
|
'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename), |
|
|
|
|
|
'forceurl': opts.geturl, |
|
|
|
|
|
'forcetitle': opts.gettitle, |
|
|
|
|
|
'forcethumbnail': opts.getthumbnail, |
|
|
|
|
|
'forcedescription': opts.getdescription, |
|
|
|
|
|
'forcefilename': opts.getfilename, |
|
|
|
|
|
'simulate': (opts.simulate or opts.geturl or opts.gettitle or opts.getthumbnail or opts.getdescription or opts.getfilename), |
|
|
|
|
|
'format': opts.format, |
|
|
|
|
|
'format_limit': opts.format_limit, |
|
|
|
|
|
'outtmpl': ((opts.outtmpl is not None and opts.outtmpl.decode(preferredencoding())) |
|
|
|
|
|
or (opts.format == '-1' and opts.usetitle and u'%(stitle)s-%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.format == '-1' and opts.useliteral and u'%(title)s-%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.format == '-1' and u'%(id)s-%(format)s.%(ext)s') |
|
|
|
|
|
or (opts.usetitle and opts.autonumber and u'%(autonumber)s-%(stitle)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.useliteral and opts.autonumber and u'%(autonumber)s-%(title)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.usetitle and u'%(stitle)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.useliteral and u'%(title)s-%(id)s.%(ext)s') |
|
|
|
|
|
or (opts.autonumber and u'%(autonumber)s-%(id)s.%(ext)s') |
|
|
|
|
|
or u'%(id)s.%(ext)s'), |
|
|
|
|
|
'ignoreerrors': opts.ignoreerrors, |
|
|
|
|
|
'ratelimit': opts.ratelimit, |
|
|
|
|
|
'nooverwrites': opts.nooverwrites, |
|
|
|
|
|
'retries': opts.retries, |
|
|
|
|
|
'continuedl': opts.continue_dl, |
|
|
|
|
|
'noprogress': opts.noprogress, |
|
|
|
|
|
'playliststart': opts.playliststart, |
|
|
|
|
|
'playlistend': opts.playlistend, |
|
|
|
|
|
'logtostderr': opts.outtmpl == '-', |
|
|
|
|
|
'consoletitle': opts.consoletitle, |
|
|
|
|
|
'nopart': opts.nopart, |
|
|
|
|
|
'updatetime': opts.updatetime, |
|
|
|
|
|
}) |
|
|
|
|
|
fd.add_info_extractor(youtube_search_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_pl_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_user_ie) |
|
|
|
|
|
fd.add_info_extractor(metacafe_ie) |
|
|
|
|
|
fd.add_info_extractor(dailymotion_ie) |
|
|
|
|
|
fd.add_info_extractor(youtube_ie) |
|
|
|
|
|
fd.add_info_extractor(google_ie) |
|
|
|
|
|
fd.add_info_extractor(google_search_ie) |
|
|
|
|
|
fd.add_info_extractor(photobucket_ie) |
|
|
|
|
|
fd.add_info_extractor(yahoo_ie) |
|
|
|
|
|
fd.add_info_extractor(yahoo_search_ie) |
|
|
|
|
|
fd.add_info_extractor(deposit_files_ie) |
|
|
|
|
|
fd.add_info_extractor(facebook_ie) |
|
|
|
|
|
|
|
|
|
|
|
# This must come last since it's the |
|
|
|
|
|
# fallback if none of the others work |
|
|
|
|
|
fd.add_info_extractor(generic_ie) |
|
|
|
|
|
|
|
|
|
|
|
# PostProcessors |
|
|
|
|
|
if opts.extractaudio: |
|
|
|
|
|
fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat)) |
|
|
|
|
|
|
|
|
|
|
|
# Update version |
|
|
|
|
|
if opts.update_self: |
|
|
|
|
|
updateSelf(fd, sys.argv[0]) |
|
|
|
|
|
|
|
|
|
|
|
# Maybe do nothing |
|
|
|
|
|
if len(all_urls) < 1: |
|
|
|
|
|
if not opts.update_self: |
|
|
|
|
|
parser.error(u'you must provide at least one URL') |
|
|
|
|
|
else: |
|
|
|
|
|
sys.exit() |
|
|
|
|
|
retcode = fd.download(all_urls) |
|
|
|
|
|
|
|
|
# Dump cookie jar if requested |
|
|
|
|
|
if opts.cookiefile is not None: |
|
|
|
|
|
try: |
|
|
|
|
|
jar.save() |
|
|
|
|
|
except (IOError, OSError), err: |
|
|
|
|
|
sys.exit(u'ERROR: unable to save cookie jar') |
|
|
|
|
|
|
|
|
# Dump cookie jar if requested |
|
|
|
|
|
if opts.cookiefile is not None: |
|
|
|
|
|
try: |
|
|
|
|
|
jar.save() |
|
|
|
|
|
except (IOError, OSError), err: |
|
|
|
|
|
sys.exit(u'ERROR: unable to save cookie jar') |
|
|
|
|
|
|
|
|
sys.exit(retcode) |
|
|
|
|
|
|
|
|
sys.exit(retcode) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
try: |
|
|
|
|
|
main() |
|
|
except DownloadError: |
|
|
except DownloadError: |
|
|
sys.exit(1) |
|
|
sys.exit(1) |
|
|
except SameFileError: |
|
|
except SameFileError: |
|
|