aria2rpc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. #!/usr/bin/env ruby
  2. # The MIT License
  3. #
  4. # Copyright (c) 2009 Tatsuhiro Tsujikawa
  5. #
  6. # Permission is hereby granted, free of charge, to any person obtaining a copy
  7. # of this software and associated documentation files (the "Software"), to deal
  8. # in the Software without restriction, including without limitation the rights
  9. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. # copies of the Software, and to permit persons to whom the Software is
  11. # furnished to do so, subject to the following conditions:
  12. #
  13. # The above copyright notice and this permission notice shall be included in
  14. # all copies or substantial portions of the Software.
  15. #
  16. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. # THE SOFTWARE.
  23. require 'xmlrpc/client'
  24. require 'pp'
  25. require 'optparse'
  26. program_name=File.basename($0)
  27. options={}
  28. args=nil
  29. OptionParser.new do |opt|
  30. opt.on("-d","--dir DIR"){|val| options["dir"]=val}
  31. opt.on("-V","--check-integrity [BOOL]", ["true","false"]){|val|
  32. options["check-integrity"]= val||"true"
  33. }
  34. opt.on("-c","--continue [BOOL]",["true","false"]){|val|
  35. options["continue"]=val||"true"
  36. }
  37. opt.on("--all-proxy PROXY"){|val| options["all-proxy"]=val}
  38. opt.on("--all-proxy-user USER"){|val| options["all-proxy-user"]=val}
  39. opt.on("--all-proxy-passwd PASSWD"){|val| options["all-proxy-passwd"]=val}
  40. opt.on("--connect-timeout SEC"){|val| options["connect-timeout"]=val}
  41. opt.on("--dry-run [BOOL]",["true","false"]){|val|
  42. options["dry-run"]=val||"true"
  43. }
  44. opt.on("--lowest-speed-limit SPEED"){|val| options["lowest-speed-limit"]=val}
  45. opt.on("--max-file-not-found NUM"){|val| options["max-file-not-found"]=val}
  46. opt.on("-m","--max-tries N"){|val| options["max-tries"]=val}
  47. opt.on("--no-proxy DOMAINS"){|val| options["no-proxy"]=val}
  48. opt.on("-o","--out FILE"){|val| options["out"]=val}
  49. opt.on("--proxy-method METHOD"){|val| options["proxy-method"]=val}
  50. opt.on("-R","--remote-time [BOOL]",["true","false"]){|val|
  51. options["remote-time"]=val||"true"
  52. }
  53. opt.on("-s","--split N"){|val| options["split"]=val}
  54. opt.on("-t","--timeout SEC"){|val| options["timeout"]=val}
  55. opt.on("--http-auth-challenge [BOOL]",["true","false"]){|val|
  56. options["http-auth-challenge"]=val||"true"
  57. }
  58. opt.on("--http-no-cache [BOOL]",["true","false"]){|val|
  59. options["http-no-cache"]=val||"true"
  60. }
  61. opt.on("--http-user USER"){|val| options["http-user"]=val}
  62. opt.on("--http-passwd PASSWD"){|val| options["http-passwd"]=val}
  63. opt.on("--http-proxy PROXY"){|val| options["http-proxy"]=val}
  64. opt.on("--http-proxy-user USER"){|val| options["http-proxy-user"]=val}
  65. opt.on("--http-proxy-passwd PASSWD"){|val| options["http-proxy-passwd"]=val}
  66. opt.on("--https-proxy PROXY"){|val| options["https-proxy"]=val}
  67. opt.on("--https-proxy-user USER"){|val| options["https-proxy-user"]=val}
  68. opt.on("--https-proxy-passwd PASSWD"){|val| options["https-proxy-passwd"]=val}
  69. opt.on("--referer REFERER"){|val| options["referer"]=val}
  70. opt.on("--enable-http-keep-alive [BOOL]",["true","false"]){|val|
  71. options["enable-http-keep-alive"]=val||"true"
  72. }
  73. opt.on("--enable-http-pipelining [BOOL]",["true","false"]){|val|
  74. options["enable-http-pipelining"]=val||"true"
  75. }
  76. opt.on("--header HEADER"){|val|
  77. options["header"] = [] if options["header"] == nil
  78. options["header"] << val
  79. }
  80. opt.on("--use-head [BOOL]",["true","false"]){|val|
  81. options["use-head"]=val||"true"
  82. }
  83. opt.on("-U","--user-agent USERAGENT"){|val| options["user-agent"]=val}
  84. opt.on("--ftp-user USER"){|val| options["ftp-user"]=val}
  85. opt.on("--ftp-passwd PASSWD"){|val| options["ftp-passwd"]=val}
  86. opt.on("-p","--ftp-pasv [BOOL]",["true","false"]){|val|
  87. options["ftp-pasv"]=val||"true"
  88. }
  89. opt.on("--ftp-proxy PROXY"){|val| options["ftp-proxy"]=val}
  90. opt.on("--ftp-proxy-user USER"){|val| options["ftp-proxy-user"]=val}
  91. opt.on("--ftp-proxy-passwd PASSWD"){|val| options["ftp-proxy-passwd"]=val}
  92. opt.on("--ftp-type TYPE"){|val| options["ftp-type"]=val}
  93. opt.on("--ftp-reuse-connection [BOOL]",["true","false"]){|val|
  94. options["ftp-reuse-connection"]=val||"true"
  95. }
  96. opt.on("-n","--no-netrc [BOOL]",["true","false"]){|val|
  97. options["no-netrc"]=val||"true"
  98. }
  99. opt.on("--reuse-uri [BOOL]",["true","false"]){|val|
  100. options["reuse-uri"]=val||"true"
  101. }
  102. opt.on("--select-file INDEXES"){|val| options["select-file"]=val}
  103. opt.on("--bt-enable-lpd [BOOL]",["true","false"]){|val|
  104. options["bt-enable-lpd"]=val||"true"
  105. }
  106. opt.on("--bt-external-ip IPADDRESS"){|val| options["bt-external-ip"]=val}
  107. opt.on("--bt-hash-check-seed [BOOL]",["true","false"]){|val|
  108. options["bt-hash-check-seed"]=val||"true"
  109. }
  110. opt.on("--bt-max-open-files NUM"){|val| options["bt-max-open-files"]=val}
  111. opt.on("--bt-max-peers NUM"){|val| options["bt-max-peers"]=val}
  112. opt.on("--bt-metadata-only [BOOL]",["true","false"]){|val|
  113. options["bt-metadata-only"]=val||"true"
  114. }
  115. opt.on("--bt-min-crypto-level LEVEL",["plain","arc4"]){|val|
  116. options["bt-min-crypto-level"]=val
  117. }
  118. opt.on("--bt-prioritize-piece RANGE") {|val|
  119. options["bt-prioritize-piece"]=val
  120. }
  121. opt.on("--bt-require-crypto [BOOL]",["true","false"]){|val|
  122. options["bt-require-crypto"]=val||"true"
  123. }
  124. opt.on("--bt-request-peer-speed-limit SPEED"){|val|
  125. options["bt-request-peer-speed-limit"]=val
  126. }
  127. opt.on("--bt-save-metadata [BOOL]",["true","false"]){|val|
  128. options["bt-save-metadata"]=val||"true"
  129. }
  130. opt.on("--bt-seed-unverified [BOOL]",["true","false"]){|val|
  131. options["bt-seed-unverified"]=val||"true"
  132. }
  133. opt.on("--bt-stop-timeout SEC"){|val| options["bt-stop-timeout"]=val}
  134. opt.on("--bt-tracker-interval SEC"){|val| options["bt-tracker-interval"]=val}
  135. opt.on("--bt-tracker-timeout SEC"){|val| options["bt-tracker-timeout"]=val}
  136. opt.on("--bt-tracker-connect-timeout SEC"){|val|
  137. options["bt-tracker-connect-timeout"]=val
  138. }
  139. opt.on("--enable-peer-exchange [BOOL]",["true","false"]){|val|
  140. options["enable-peer-exchange"]=val||"true"
  141. }
  142. opt.on("--follow-torrent VALUE", ["true","false","mem"]){|val|
  143. options["follow-torrent"]=val
  144. }
  145. opt.on("-O","--index-out INDEXPATH"){|val|
  146. options["index-out"]=[] if options["index-out"] == nil
  147. options["index-out"] << val
  148. }
  149. opt.on("-u","--max-upload-limit SPEED"){|val| options["max-upload-limit"]=val}
  150. opt.on("--seed-ratio RATIO"){|val| options["seed-ratio"]=val}
  151. opt.on("--seed-time MINUTES"){|val| options["seed-time"]=val}
  152. opt.on("--follow-metalink VALUE", ["true","false","mem"]){|val|
  153. options["follow-metalink"]=val
  154. }
  155. opt.on("-C","--metalink-servers NUM"){|val| options["metalink-servers"]=val}
  156. opt.on("--metalink-language LANG"){|val| options["metalink-language"]=val}
  157. opt.on("--metalink-location LOCS"){|val| options["metalink-location"]=val}
  158. opt.on("--metalink-os OS"){|val| options["metalink-os"]=val}
  159. opt.on("--metalink-version VERSION"){|val| options["metalink-version"]=val}
  160. opt.on("--metalink-preferred-protocol PROTO"){|val|
  161. options["metalink-preferred-protocol"]=val
  162. }
  163. opt.on("--metalink-enable-unique-protocol [BOOL]",["true","false"]){|val|
  164. options["metalink-enable-unique-protocol"]=val||"true"
  165. }
  166. opt.on("--allow-overwrite [BOOL]",["true","false"]){|val|
  167. options["allow-overwrite"]=val||"true"
  168. }
  169. opt.on("--allow-piece-length-change [BOOL]",["true","false"]){|val|
  170. options["allow-piece-length-change"]=val||"true"
  171. }
  172. opt.on("--async-dns [BOOL]",["true","false"]){|val|
  173. options["async-dns"]=val||"true"
  174. }
  175. opt.on("--auto-file-renaming [BOOL]",["true","false"]){|val|
  176. options["auto-file-renaming"]=val||"true"
  177. }
  178. opt.on("--file-allocation METHOD",["none","prealloc","falloc"]){|val|
  179. options["file-allocation"]=val
  180. }
  181. opt.on("--max-download-limit LIMIT"){|val| options["max-download-limit"]=val}
  182. opt.on("--no-file-allocation-limit SIZE"){|val|
  183. options["no-file-allocation-limit"]=val
  184. }
  185. opt.on("-P","--parameterized-uri [BOOL]",["true","false"]){|val|
  186. options["parameterized-uri"]=val||"true"
  187. }
  188. opt.on("--realtime-chunk-checksum [BOOL]",["true","false"]){|val|
  189. options["realtime-chunk-checksum"]=val||"true"
  190. }
  191. opt.on("--remove-control-file [BOOL]",["true","false"]){|val|
  192. options["remove-control-file"]=val||"true"
  193. }
  194. opt.on("--always-resume [BOOL]",["true","false"]){|val|
  195. options["always-resume"]=val||"true"
  196. }
  197. opt.on("--max-resume-failure-tries N"){|val|
  198. options["max-resume-failure-tries"]=val
  199. }
  200. opt.on("--http-accept-gzip [BOOL]",["true","false"]){|val|
  201. options["http-accept-gzip"]=val||"true"
  202. }
  203. opt.on("-x","--max-connection-per-server NUM"){|val| options["max-connection-per-server"]=val}
  204. opt.on("-k","--min-split-size SIZE"){|val| options["min-split-size"]=val}
  205. opt.on("--conditional-get [BOOL]",["true","false"]){|val|
  206. options["conditional-get"]=val||"true"
  207. }
  208. opt.on("--enable-async-dns6 [BOOL]",["true","false"]){|val|
  209. options["enable-async-dns6"]=val||"true"
  210. }
  211. opt.on("--bt-tracker URIS"){|val| options["bt-tracker"]=val}
  212. opt.on("--bt-exclude-tracker URIS"){|val| options["bt-exclude-tracker"]=val}
  213. opt.on("--retry-wait SEC"){|val| options["retry-wait"]=val}
  214. opt.on("--metalink-base-uri URI"){|val| options["metalink-base-uri"]=val}
  215. opt.on("--pause [BOOL]",["true","false"]){|val| options["pause"]=val||"true"}
  216. opt.on("--stream-piece-selector SELECTOR"){|val| options["stream-piece-selector"]=val}
  217. opt.on("--hash-check-only [BOOL]",["true","false"]){|val|
  218. options["hash-check-only"]=val||"true"
  219. }
  220. opt.on("--checksum TYPE_DIGEST"){|val| options["checksum"]=val}
  221. opt.on("--piece-length LENGTH"){|val| options["piece-length"]=val}
  222. opt.on("--uri-selector SELECTOR"){|val| options["uri-selector"]=val}
  223. opt.on("--max-overall-download-limit LIMIT"){|val| options["max-overall-download-limit"]=val}
  224. opt.on("--max-overall-upload-limit LIMIT"){|val| options["max-overall-upload-limit"]=val}
  225. opt.on("-j","--max-concurrent-downloads N"){|val| options["max-concurrent-downloads"]=val}
  226. opt.on("-l","--log FILE"){|val| options["log"]=val}
  227. opt.on("--max-download-result NUM"){|val| options["max-download-result"]=val}
  228. opt.on("--download-result OPT"){|val| options["download-result"]=val}
  229. opt.on("--save-session FILE"){|val| options["save-session"]=val}
  230. opt.on("--server-stat-of FILE"){|val| options["server-stat-of"]=val}
  231. opt.on("--save-cookies FILE"){|val| options["save-cookies"]=val}
  232. opt.on("--gid GID"){|val| options["gid"]=val}
  233. opt.on("--server SERVER", "hostname of XML-RPC server. Default: localhost"){|val| options["server"]=val }
  234. opt.on("--port PORT", "port of XML-RPC server. Default: 6800"){|val| options["port"]=val }
  235. opt.on("--user USERNAME", "XML-RPC username"){|val| options["user"]=val }
  236. opt.on("--passwd PASSWORD", "XML-RPC password"){|val| options["passwd"]=val }
  237. opt.on("--secure [BOOL]",["true","false"]){|val| options["secure"]=val||"true" }
  238. opt.on("--check-rpc-cert [BOOL]",["true","false"]){|val| options["check-rpc-cert"]=val||"true" }
  239. opt.on("--secret SECRET", "XML-RPC secret authorization token"){|val| options["secret"]=val }
  240. opt.banner=<<EOS
  241. Usage: #{program_name} addUri URI... [options]
  242. #{program_name} addTorrent /path/to/torrent_file URI... [options]
  243. #{program_name} addMetalink /path/to/metalink_file [options]
  244. #{program_name} remove GID [options]
  245. #{program_name} forceRemove GID [options]
  246. #{program_name} pause GID [options]
  247. #{program_name} pauseAll [options]
  248. #{program_name} forcePause GID [options]
  249. #{program_name} forcePauseAll [options]
  250. #{program_name} unpause GID [options]
  251. #{program_name} unpauseAll [options]
  252. #{program_name} changePosition GID pos how [options]
  253. #{program_name} tellStatus GID [keys] [options]
  254. #{program_name} tellActive [keys] [options]
  255. #{program_name} tellWaiting offset num [keys] [options]
  256. #{program_name} tellStopped offset num [keys] [options]
  257. #{program_name} getOption GID [options]
  258. #{program_name} getGlobalOption [options]
  259. #{program_name} getFiles GID [options]
  260. #{program_name} getUris GID [options]
  261. #{program_name} getPeers GID [options]
  262. #{program_name} getServers GID [options]
  263. #{program_name} purgeDownloadResult [options]
  264. #{program_name} removeDownloadResult GID [options]
  265. #{program_name} changeOption GID [options]
  266. #{program_name} changeGlobalOption [options]
  267. #{program_name} getVersion [options]
  268. #{program_name} getSessionInfo [options]
  269. #{program_name} shutdown [options]
  270. #{program_name} forceShutdown [options]
  271. #{program_name} getGlobalStat [options]
  272. #{program_name} saveSession [options]
  273. #{program_name} appendUri GID fileIndex URI... [options]
  274. This command calls aria2.changeUri(GID, fileIndex, [], [URI,...])
  275. internally.
  276. Options:
  277. EOS
  278. args=opt.parse(ARGV)
  279. end
  280. if !args or args.size == 0 then
  281. puts "No command specified"
  282. exit 1
  283. end
  284. command=args[0]
  285. resources=args[1..-1]
  286. auth=""
  287. if options.has_key?("user") then
  288. auth=options["user"]+":"+options["passwd"]+"@"
  289. end
  290. if not options.has_key?("server") then
  291. options["server"]="localhost"
  292. end
  293. if not options.has_key?("port") then
  294. options["port"]="6800"
  295. end
  296. if not options.has_key?("secure") then
  297. options["secure"]="false"
  298. end
  299. if not options.has_key?("check-rpc-cert") then
  300. options["check-rpc-cert"]="true"
  301. end
  302. secret = if options.has_key?("secret") then "token:"+options["secret"] else nil end
  303. client=XMLRPC::Client.new3({:host => options["server"],
  304. :port => options["port"],
  305. :path => "/rpc",
  306. :user => options["user"],
  307. :password => options["passwd"],
  308. :use_ssl => options["secure"] == "true"})
  309. if options["check-rpc-cert"] == "false" then
  310. client.instance_variable_get(:@http).instance_variable_set(:@verify_mode, OpenSSL::SSL::VERIFY_NONE)
  311. end
  312. options.delete("server")
  313. options.delete("port")
  314. options.delete("user")
  315. options.delete("passwd")
  316. options.delete("secret")
  317. options.delete("secure")
  318. options.delete("check-rpc-cert")
  319. def client_call client, secret, method, *params
  320. if secret.nil?
  321. client.call(method, *params)
  322. else
  323. client.call(method, secret, *params)
  324. end
  325. end
  326. if command == "addUri" then
  327. result=client_call(client, secret, "aria2."+command, resources, options)
  328. elsif command == "addTorrent" then
  329. torrentData=IO.read(resources[0])
  330. result=client_call(client, secret, "aria2."+command,
  331. XMLRPC::Base64.new(torrentData), resources[1..-1], options)
  332. elsif command == "addMetalink" then
  333. metalinkData=IO.read(resources[0])
  334. result=client_call(client, secret, "aria2."+command,
  335. XMLRPC::Base64.new(metalinkData), options)
  336. elsif command == "tellStatus" then
  337. result=client_call(client, secret, "aria2."+command,
  338. resources[0], resources[1..-1])
  339. elsif command == "tellActive" then
  340. result=client_call(client, secret, "aria2."+command, resources[0..-1])
  341. elsif command == "tellWaiting" then
  342. result=client_call(client, secret, "aria2."+command, resources[0].to_i(),
  343. resources[1].to_i(), resources[2..-1])
  344. elsif command == "tellStopped" then
  345. result=client_call(client, secret, "aria2."+command, resources[0].to_i(),
  346. resources[1].to_i(), resources[2..-1])
  347. elsif command == "getOption" then
  348. result=client_call(client, secret, "aria2."+command, resources[0])
  349. elsif command == "getGlobalOption" then
  350. result=client_call(client, secret, "aria2."+command)
  351. elsif command == "pause" then
  352. result=client_call(client, secret, "aria2."+command, resources[0])
  353. elsif command == "pauseAll" then
  354. result=client_call(client, secret, "aria2."+command)
  355. elsif command == "forcePause" then
  356. result=client_call(client, secret, "aria2."+command, resources[0])
  357. elsif command == "forcePauseAll" then
  358. result=client_call(client, secret, "aria2."+command)
  359. elsif command == "unpause" then
  360. result=client_call(client, secret, "aria2."+command, resources[0])
  361. elsif command == "unpauseAll" then
  362. result=client_call(client, secret, "aria2."+command)
  363. elsif command == "remove" then
  364. result=client_call(client, secret, "aria2."+command, resources[0])
  365. elsif command == "forceRemove" then
  366. result=client_call(client, secret, "aria2."+command, resources[0])
  367. elsif command == "changePosition" then
  368. result=client_call(client, secret, "aria2."+command, resources[0],
  369. resources[1].to_i(), resources[2])
  370. elsif command == "getFiles" then
  371. result=client_call(client, secret, "aria2."+command, resources[0])
  372. elsif command == "getUris" then
  373. result=client_call(client, secret, "aria2."+command, resources[0])
  374. elsif command == "getPeers" then
  375. result=client_call(client, secret, "aria2."+command, resources[0])
  376. elsif command == "getServers" then
  377. result=client_call(client, secret, "aria2."+command, resources[0])
  378. elsif command == "purgeDownloadResult" then
  379. result=client_call(client, secret, "aria2."+command)
  380. elsif command == "removeDownloadResult" then
  381. result=client_call(client, secret, "aria2."+command, resources[0])
  382. elsif command == "changeOption" then
  383. result=client_call(client, secret, "aria2."+command, resources[0], options)
  384. elsif command == "changeGlobalOption" then
  385. result=client_call(client, secret, "aria2."+command, options)
  386. elsif command == "getVersion" then
  387. result=client_call(client, secret, "aria2."+command)
  388. elsif command == "getSessionInfo" then
  389. result=client_call(client, secret, "aria2."+command)
  390. elsif command == "shutdown" then
  391. result=client_call(client, secret, "aria2."+command)
  392. elsif command == "forceShutdown" then
  393. result=client_call(client, secret, "aria2."+command)
  394. elsif command == "getGlobalStat" then
  395. result=client_call(client, secret, "aria2."+command)
  396. elsif command == "saveSession" then
  397. result=client_call(client, secret, "aria2."+command)
  398. elsif command == "appendUri" then
  399. result=client_call(client, secret, "aria2.changeUri", resources[0],
  400. resources[1].to_i(), [], resources[2..-1])
  401. else
  402. puts "Command not recognized"
  403. exit 1
  404. end
  405. pp result