Aria2 RPC

Aria2 RPC Library

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/5672/933444/Aria2%20RPC.js

  1. // ==UserScript==
  2. // @name Aria2 RPC
  3. // @namespace moe.jixun
  4. // @version 0.1
  5. // @license MIT
  6. // ==/UserScript==
  7.  
  8. // Public Class Aria2 ( options )
  9.  
  10. var Aria2 = (function (_isGM, _arrFn, _merge, _format, _isFunction) {
  11. var jsonrpc_ver = '2.0';
  12.  
  13. if (_isGM) {
  14. var doRequest = function ( opts ) {
  15. console.warn ([
  16. 'Warning: You are now using an simple implementation of GM_xmlhttpRequest',
  17. 'Cross-domain request are not avilible unless configured correctly @ target server.',
  18. '',
  19. 'Some of its features are not avilible, such as `username` and `password` field.'
  20. ].join('\n'));
  21.  
  22. var oReq = new XMLHttpRequest ();
  23. var cbCommon = function (cb) {
  24. return (function () {
  25. cb ({
  26. readyState: oReq.readyState,
  27. responseHeaders: opts.getHeader ? oReq.getAllResponseHeaders() : null,
  28. getHeader: oReq.getResponseHeader.bind (oReq),
  29. responseText: oReq.responseText,
  30. status: oReq.status,
  31. statusText: oReq.statusText
  32. });
  33. }).bind (opts);
  34. };
  35.  
  36. if (opts.onload) oReq.onload = cbCommon (opts.onload);
  37. if (opts.onerror) oReq.onerror = cbCommon (opts.onerror);
  38.  
  39. oReq.open(opts.method || 'GET', opts.url, !opts.synchronous);
  40.  
  41. if (opts.headers) {
  42. Object.keys(opts.headers).forEach (function (key) {
  43. oReq.setRequestHeader (key, opts.headers[key]);
  44. });
  45. }
  46. return oReq.send(opts.data || null);
  47. };
  48. } else {
  49. var doRequest = GM_xmlhttpRequest;
  50. }
  51.  
  52. var AriaBase = function ( options ) {
  53. this.options = _merge ({
  54. auth: {
  55. type: AriaBase.AUTH.noAuth,
  56. user: '',
  57. pass: ''
  58. },
  59. host: '127.0.0.1',
  60. port: 6800
  61. }, options || {});
  62.  
  63. this.id = parseInt (options, 10) || (+ new Date());
  64. };
  65. // 静态常量
  66. AriaBase.AUTH = {
  67. noAuth: 0,
  68. basic: 1,
  69. secret: 2
  70. };
  71.  
  72. // public 函数
  73. AriaBase.prototype = {
  74. getBasicAuth: function () {
  75. return btoa (_format('%s:%s', this.options.auth.user, this.options.auth.pass));
  76. },
  77.  
  78. send: function ( bIsDataBatch, data, cbSuccess, cbError ) {
  79. var srcTaskObj = { jsonrpc: jsonrpc_ver, id: this.id };
  80.  
  81. var payload = {
  82.  
  83. method: 'POST',
  84. url: _format('http://%s:%s/jsonrpc', this.options.host, this.options.port),
  85. headers: {
  86. 'Content-Type': 'application/json; charset=UTF-8'
  87. },
  88. data: bIsDataBatch
  89. ? data.map (function (e) { return _merge ({}, srcTaskObj, e); })
  90. : _merge ({}, srcTaskObj, data),
  91. onload: function (r) {
  92. var repData = JSON.parse (r.responseText);
  93. if (repData.error) {
  94. cbError && cbError (false, repData);
  95. } else {
  96. cbSuccess && cbSuccess (repData);
  97. }
  98. },
  99. onerror: cbError ? cbError.bind(null, false) : null
  100. };
  101.  
  102. switch ( parseInt (this.options.auth.type, 10) ) {
  103. case AriaBase.AUTH.noAuth:
  104. // DO NOTHING
  105. break;
  106.  
  107. case AriaBase.AUTH.basic:
  108. payload.headers.Authorization = 'Basic ' + this.getBasicAuth();
  109. break;
  110.  
  111. case AriaBase.AUTH.secret:
  112. (function (sToken) {
  113. if (bIsDataBatch) {
  114. for (var i = 0; i < payload.data.length; i++) {
  115. payload.data[i].params.splice(0, 0, sToken);
  116. }
  117. } else {
  118. if (!payload.data.params)
  119. payload.data.params = [];
  120. payload.data.params.splice(0, 0, sToken);
  121. }
  122. })(_format('token:%s', this.options.auth.pass));
  123. break;
  124.  
  125. default:
  126. throw new Error('Undefined auth type: ' + this.options.auth.type);
  127. }
  128.  
  129. payload.data = JSON.stringify ( payload.data );
  130.  
  131. return doRequest (payload);
  132. },
  133.  
  134. // batchAddUri ( foo, { uri: 'http://example.com/xxx', options: { ... } } )
  135. batchAddUri: function (fCallback) {
  136. console.warn (
  137. 'This function [%s] has deprecated! Consider use %s instead.',
  138. 'batchAddUri', 'AriaBase.BATCH'
  139. );
  140.  
  141. // { url, name }
  142. var payload = [].slice.call (arguments, 1).map (function (arg) {
  143. return {
  144. method: 'aria2.addUri',
  145. params: [ arg.uri.map ? arg.uri : [ arg.uri ] ].concat (arg.options || [])
  146. };
  147. });
  148. return this.send (true, payload, fCallback, fCallback);
  149. }
  150. };
  151.  
  152.  
  153. // 添加各类函数
  154. AriaBase.fn = {};
  155. _arrFn.forEach (function (sMethod) {
  156. // 函数链表
  157. AriaBase.fn[sMethod] = sMethod;
  158.  
  159. // arg1, arg2, ... , [cbSuccess, [cbError]]
  160. AriaBase.prototype[sMethod] = function ( ) {
  161. var args = [].slice.call (arguments);
  162.  
  163. var cbSuccess, cbError;
  164. if (args.length && _isFunction(args[args.length - 1])) {
  165. cbSuccess = args[args.length - 1];
  166. args.splice (-1, 1);
  167.  
  168. if (args.length && _isFunction(args[args.length - 1])) {
  169. cbError = cbSuccess;
  170. cbSuccess = args[args.length - 1];
  171. args.splice (-1, 1);
  172. }
  173. }
  174.  
  175. return this.send (false, {
  176. method: 'aria2.' + sMethod,
  177. params: args
  178. }, cbSuccess, cbError);
  179. };
  180. });
  181.  
  182. AriaBase.BATCH = function ( parent, cbSuccess, cbFail ) {
  183. if (!(parent instanceof AriaBase))
  184. throw new Error ('Parent is not AriaBase!');
  185.  
  186. this.parent = parent;
  187. this.data = [];
  188.  
  189. this.onSuccess = cbSuccess;
  190. this.onFail = cbFail;
  191. };
  192.  
  193. AriaBase.BATCH.prototype = {
  194. addRaw: function (fn, args) {
  195. this.data.push ({
  196. method: 'aria2.' + fn,
  197. params: args
  198. });
  199. return this;
  200. },
  201.  
  202. add: function (fn) {
  203. // People can add more without edit source.
  204. if (!AriaBase.fn[fn])
  205. throw new Error ('Unknown function: ' + fn + ', please check if you had a typo.');
  206.  
  207. return this.addRaw (fn, [].slice.call(arguments, 1));
  208. },
  209.  
  210. send: function () {
  211. // bIsDataBatch, data, cbSuccess, cbError
  212. var ret = this.parent.send ( true, this.data, this.onSuccess, this.onFail );
  213. this.reset ();
  214. return ret;
  215. },
  216.  
  217. getActions: function () {
  218. return this.data.slice();
  219. },
  220.  
  221. setActions: function (actions) {
  222. if (!actions || !actions.map) return ;
  223.  
  224. this.data = actions;
  225. },
  226.  
  227. reset: function () {
  228. this.onSuccess = this.onFail = null;
  229. this.setActions ( [] );
  230. }
  231. };
  232. return AriaBase;
  233. })
  234. // const 变量
  235. ('undefined' == typeof GM_xmlhttpRequest, [
  236. "addUri", "addTorrent", "addMetalink", "remove", "forceRemove",
  237. "pause", "pauseAll", "forcePause", "forcePauseAll", "unpause",
  238. "unpauseAll", "tellStatus", "getUris", "getFiles", "getPeers",
  239. "getServers", "tellActive", "tellWaiting", "tellStopped",
  240. "changePosition", "changeUri", "getOption", "changeOption",
  241. "getGlobalOption", "changeGlobalOption", "getGlobalStat",
  242. "purgeDownloadResult", "removeDownloadResult", "getVersion",
  243. "getSessionInfo", "shutdown", "forceShutdown", "saveSession"
  244. ],
  245. // private 函数
  246. (function (base) {
  247. var _isObject = function (obj) {
  248. return obj instanceof Object;
  249. };
  250. var _merge = function (base) {
  251. var args = arguments,
  252. argL = args.length;
  253. for ( var i = 1; i < argL; i++ ) {
  254. Object.keys (args[i]).forEach (function (key) {
  255. if (_isObject(args[i][key]) && _isObject(base[key])) {
  256. base[key] = _merge (base[key], args[i][key]);
  257. } else {
  258. base[key] = args[i][key];
  259. }
  260. });
  261. }
  262. return base;
  263. };
  264. return _merge;
  265. })(), function (src) {
  266. var args = arguments,
  267. argL = args.length;
  268.  
  269. var ret = src.slice ();
  270. for ( var i = 1; i < argL; i++ )
  271. ret = ret.replace ('%s', args[i]);
  272. return ret;
  273. }, function (foo) {
  274. return typeof foo === 'function'
  275. });