]> jfr.im git - yt-dlp.git/blame - youtube_dl/downloader/external.py
[downloader/external] add _bool_option to pass value to bool option
[yt-dlp.git] / youtube_dl / downloader / external.py
CommitLineData
222516d9
PH
1from __future__ import unicode_literals
2
3import os.path
4import subprocess
222516d9
PH
5
6from .common import FileDownloader
7from ..utils import (
8 encodeFilename,
74f8654a 9 encodeArgument,
222516d9
PH
10)
11
12
13class ExternalFD(FileDownloader):
14 def real_download(self, filename, info_dict):
15 self.report_destination(filename)
16 tmpfilename = self.temp_name(filename)
17
18 retval = self._call_downloader(tmpfilename, info_dict)
19 if retval == 0:
20 fsize = os.path.getsize(encodeFilename(tmpfilename))
21 self.to_screen('\r[%s] Downloaded %s bytes' % (self.get_basename(), fsize))
22 self.try_rename(tmpfilename, filename)
23 self._hook_progress({
24 'downloaded_bytes': fsize,
25 'total_bytes': fsize,
26 'filename': filename,
27 'status': 'finished',
28 })
29 return True
30 else:
31 self.to_stderr('\n')
32 self.report_error('%s exited with code %d' % (
33 self.get_basename(), retval))
34 return False
35
36 @classmethod
37 def get_basename(cls):
38 return cls.__name__[:-2].lower()
39
40 @property
41 def exe(self):
42 return self.params.get('external_downloader')
43
44 @classmethod
45 def supports(cls, info_dict):
46 return info_dict['protocol'] in ('http', 'https', 'ftp', 'ftps')
47
bf812ef7
S
48 def _option(self, command_option, param):
49 param = self.params.get(param)
e7a8c303 50 if param is None or param is False:
bf812ef7
S
51 return []
52 if isinstance(param, bool):
53 return [command_option]
54 return [command_option, param]
55
266b0ad6 56 def _bool_option(self, command_option, param, true_value='true', false_value='false', separator=None):
57 param = self.params.get(param)
58 if not isinstance(param, bool):
59 return []
60 if separator:
61 return [command_option + separator + (true_value if param else false_value)]
62 return [command_option, true_value if param else false_value]
63
c75f0b36
PH
64 def _configuration_args(self, default=[]):
65 ex_args = self.params.get('external_downloader_args')
66 if ex_args is None:
67 return default
68 assert isinstance(ex_args, list)
69 return ex_args
70
222516d9
PH
71 def _call_downloader(self, tmpfilename, info_dict):
72 """ Either overwrite this or implement _make_cmd """
74f8654a 73 cmd = [encodeArgument(a) for a in self._make_cmd(tmpfilename, info_dict)]
222516d9 74
74f8654a 75 self._debug_cmd(cmd)
222516d9
PH
76
77 p = subprocess.Popen(
384b6202
PH
78 cmd, stderr=subprocess.PIPE)
79 _, stderr = p.communicate()
222516d9
PH
80 if p.returncode != 0:
81 self.to_stderr(stderr)
82 return p.returncode
83
84
384b6202
PH
85class CurlFD(ExternalFD):
86 def _make_cmd(self, tmpfilename, info_dict):
163d9667 87 cmd = [self.exe, '--location', '-o', tmpfilename]
e5660ee6 88 for key, val in info_dict['http_headers'].items():
384b6202 89 cmd += ['--header', '%s: %s' % (key, val)]
9f3da138 90 cmd += self._option('--interface', 'source_address')
e7a8c303 91 cmd += self._option('--proxy', 'proxy')
92 cmd += self._option('--insecure', 'nocheckcertificate')
c75f0b36 93 cmd += self._configuration_args()
384b6202
PH
94 cmd += ['--', info_dict['url']]
95 return cmd
96
97
e0ac5214 98class AxelFD(ExternalFD):
99 def _make_cmd(self, tmpfilename, info_dict):
100 cmd = [self.exe, '-o', tmpfilename]
101 for key, val in info_dict['http_headers'].items():
102 cmd += ['-H', '%s: %s' % (key, val)]
103 cmd += self._configuration_args()
104 cmd += ['--', info_dict['url']]
105 return cmd
106
107
222516d9
PH
108class WgetFD(ExternalFD):
109 def _make_cmd(self, tmpfilename, info_dict):
110 cmd = [self.exe, '-O', tmpfilename, '-nv', '--no-cookies']
e5660ee6 111 for key, val in info_dict['http_headers'].items():
222516d9 112 cmd += ['--header', '%s: %s' % (key, val)]
9f3da138 113 cmd += self._option('--bind-address', 'source_address')
bf812ef7 114 cmd += self._option('--proxy', 'proxy')
9f3da138 115 cmd += self._option('--no-check-certificate', 'nocheckcertificate')
c75f0b36 116 cmd += self._configuration_args()
222516d9
PH
117 cmd += ['--', info_dict['url']]
118 return cmd
119
120
384b6202
PH
121class Aria2cFD(ExternalFD):
122 def _make_cmd(self, tmpfilename, info_dict):
c75f0b36
PH
123 cmd = [self.exe, '-c']
124 cmd += self._configuration_args([
125 '--min-split-size', '1M', '--max-connection-per-server', '4'])
384b6202
PH
126 dn = os.path.dirname(tmpfilename)
127 if dn:
128 cmd += ['--dir', dn]
129 cmd += ['--out', os.path.basename(tmpfilename)]
e5660ee6 130 for key, val in info_dict['http_headers'].items():
384b6202 131 cmd += ['--header', '%s: %s' % (key, val)]
9f3da138 132 cmd += self._option('--interface', 'source_address')
bf812ef7 133 cmd += self._option('--all-proxy', 'proxy')
266b0ad6 134 cmd += self._bool_option('--check-certificate', 'nocheckcertificate', 'false', 'true', '=')
384b6202
PH
135 cmd += ['--', info_dict['url']]
136 return cmd
137
906e2f0e
JMF
138
139class HttpieFD(ExternalFD):
140 def _make_cmd(self, tmpfilename, info_dict):
141 cmd = ['http', '--download', '--output', tmpfilename, info_dict['url']]
142 for key, val in info_dict['http_headers'].items():
143 cmd += ['%s:%s' % (key, val)]
144 return cmd
145
222516d9
PH
146_BY_NAME = dict(
147 (klass.get_basename(), klass)
148 for name, klass in globals().items()
149 if name.endswith('FD') and name != 'ExternalFD'
150)
151
152
153def list_external_downloaders():
154 return sorted(_BY_NAME.keys())
155
156
157def get_external_downloader(external_downloader):
158 """ Given the name of the executable, see whether we support the given
159 downloader . """
6c4d20cd
S
160 # Drop .exe extension on Windows
161 bn = os.path.splitext(os.path.basename(external_downloader))[0]
222516d9 162 return _BY_NAME[bn]