├── example ├── style.css ├── index.html ├── callback.js ├── promise.js └── websocket.js ├── bin ├── call.gif ├── console.gif ├── debug.js ├── README.md ├── call.js ├── cli.js └── console.js ├── .gitignore ├── .npmignore ├── .travis.yml ├── .editorconfig ├── LICENSE.md ├── test ├── index.html ├── integration.js └── unit.js ├── package.json ├── README.md └── index.js /example/style.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bin/call.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djyde/aria2.js/HEAD/bin/call.gif -------------------------------------------------------------------------------- /bin/console.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djyde/aria2.js/HEAD/bin/console.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !.editorconfig 2 | !.gitignore 3 | !.npmignore 4 | !.travis.yml 5 | 6 | bundle.js 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example/ 2 | test/ 3 | 4 | .editorconfig 5 | .gitignore 6 | .npmignore 7 | .travis.yml 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | 5 | node_js: 6 | - '0.12' 7 | - '4' 8 | - '5' 9 | - '6' 10 | -------------------------------------------------------------------------------- /bin/debug.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function (cli) { 4 | return function () { 5 | if (cli.debug) { 6 | console.log.apply(console, arguments) 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aria2.js example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/README.md: -------------------------------------------------------------------------------- 1 | aria2rpc 2 | ======== 3 | 4 | Use and control [aria2](https://aria2.github.io) RPC from the command line. 5 | 6 | ## Install 7 | 8 | `npm install -g aria2` 9 | 10 | Install aria2 and start it in daemon mode with 11 | 12 | `aria2c --enable-rpc --rpc-listen-all=true --rpc-allow-origin-all` 13 | 14 | Check `aria2rpc -h` and https://aria2.github.io/manual/en/html/aria2c.html#methods for more information. 15 | 16 | ## call 17 | 18 | Uses HTTP transport. 19 | 20 | ![](./call.gif) 21 | 22 | ## console 23 | 24 | Uses Websocket transport. 25 | 26 | ![](./console.gif) 27 | -------------------------------------------------------------------------------- /bin/call.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var Aria2 = require('..') 4 | 5 | module.exports = function (cli, options, method, params) { 6 | var debug = require('./debug')(cli) 7 | 8 | var client = new Aria2(options) 9 | client.onsend = function (m) { 10 | debug('OUT', m) 11 | } 12 | client.onmessage = function (m) { 13 | debug('IN', m) 14 | } 15 | 16 | var cb = function (err, res) { 17 | if (err) { 18 | console.error(err) 19 | process.exit(1) 20 | } 21 | 22 | console.log(res) 23 | process.exit(0) 24 | } 25 | 26 | var args = [method].concat(params, cb) 27 | 28 | client.send.apply(client, args) 29 | } 30 | -------------------------------------------------------------------------------- /example/callback.js: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | 'use strict' 3 | 4 | var Aria2 5 | 6 | // Node.js, browserify, ... 7 | if (typeof module !== 'undefined' && module.exports) { 8 | Aria2 = require('..') 9 | // browsers 10 | } else { 11 | Aria2 = window.Aria2 12 | } 13 | 14 | // those are default options 15 | var options = {'host': 'localhost', 'port': 6800, 'secure': false} 16 | var aria2 = new Aria2(options) 17 | 18 | aria2.getVersion(function (err, res) { 19 | console.log(err || res) 20 | }) 21 | 22 | // OR 23 | 24 | aria2.send('getVersion', function (err, res) { 25 | console.log(err || res) 26 | }) 27 | }()) 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## ISC License 2 | 3 | Copyright (c) 2015, Sonny Piers 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8 | -------------------------------------------------------------------------------- /example/promise.js: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | 'use strict' 3 | 4 | var Aria2 5 | 6 | // Node.js, browserify, ... 7 | if (typeof module !== 'undefined' && module.exports) { 8 | Aria2 = require('..') 9 | // browsers 10 | } else { 11 | Aria2 = window.Aria2 12 | } 13 | 14 | // those are default options 15 | var options = {'host': 'localhost', 'port': 6800, 'secure': false} 16 | var aria2 = new Aria2(options) 17 | 18 | aria2.getVersion().then( 19 | function (res) { 20 | console.log('result', res) 21 | }, 22 | function (err) { 23 | console.log('error', err) 24 | } 25 | ) 26 | 27 | // OR 28 | 29 | aria2.send('getVersion').then( 30 | function (res) { 31 | console.log('result', res) 32 | }, 33 | function (err) { 34 | console.log('error', err) 35 | } 36 | ) 37 | }()) 38 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aria2.js tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict' 4 | 5 | var url = require('url') 6 | var cli = require('commander') 7 | 8 | process.title = 'aria2rpc' 9 | 10 | var makeOptions = function () { 11 | var options = {'secret': cli.secret} 12 | if (cli.url) { 13 | var parsed = url.parse(cli.url) 14 | options.secure = parsed.protocol === 'wss:' 15 | options.host = parsed.hostname 16 | options.port = parsed.port 17 | options.path = parsed.path 18 | } 19 | return options 20 | } 21 | 22 | cli 23 | .version(require('../package.json').version) 24 | .option('-d, --debug', 'output debug information') 25 | .option('-u, --url [url]', 'websocket url to connect to', 'ws://localhost:6800/jsonrpc') 26 | .option('-s, --secret [secret]', 'aria2 secret to use') 27 | 28 | // call 29 | cli 30 | .command('call [params...]') 31 | .description('call an aria2 RPC method and print result') 32 | .action(function (method, params) { 33 | var options = makeOptions() 34 | require('./call')(cli, options, method, params) 35 | }) 36 | 37 | // console 38 | cli 39 | .command('console') 40 | .description('start interactive console') 41 | .action(function () { 42 | var options = makeOptions() 43 | require('./console')(cli, options) 44 | }) 45 | 46 | cli.parse(process.argv) 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aria2", 3 | "version": "3.0.0", 4 | "description": "Library and cli for aria2, \"The next generation download utility.\"", 5 | "homepage": "https://github.com/sonnyp/aria2.js", 6 | "bugs": "https://github.com/sonnyp/aria2.js/issues", 7 | "license": "ISC", 8 | "author": "Sonny Piers ", 9 | "keywords": [ 10 | "aria2", 11 | "download", 12 | "BitTorrent", 13 | "HTTP", 14 | "HTTPS", 15 | "FTP", 16 | "SFTP", 17 | "MetaLink", 18 | "magnet", 19 | "torrent" 20 | ], 21 | "bin": { 22 | "aria2rpc": "./bin/cli.js" 23 | }, 24 | "scripts": { 25 | "preversion": "npm test", 26 | "lint": "standard", 27 | "bundle": "cat node_modules/polygoat/index.js index.js > bundle.js", 28 | "unit": "mocha test/unit.js", 29 | "integration": "mocha test/integration.js", 30 | "test": "npm run bundle && npm run unit && npm run lint" 31 | }, 32 | "repository": "github:sonnyp/aria2.js", 33 | "dependencies": { 34 | "commander": "^2.9.0", 35 | "node-fetch": "^1.6.3", 36 | "polygoat": "^1.1.4", 37 | "ws": "^1.1.1" 38 | }, 39 | "devDependencies": { 40 | "chai": "^3.4.1", 41 | "mocha": "^3.1.0", 42 | "sinon": "^1.17.2", 43 | "sinon-chai": "^2.8.0", 44 | "standard": "^8.2.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /bin/console.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var readline = require('readline') 4 | var Aria2 = require('..') 5 | 6 | module.exports = function (cli, options) { 7 | var debug = require('./debug')(cli) 8 | 9 | var client = new Aria2(options) 10 | client.onsend = function (m) { 11 | debug('OUT', m) 12 | } 13 | client.onmessage = function (m) { 14 | debug('IN', m) 15 | if (m.id === undefined) { 16 | console.log(m) 17 | } 18 | } 19 | debug('CONNECTING') 20 | client.open(function (err) { 21 | if (err) { 22 | console.error(err) 23 | process.exit(1) 24 | } 25 | 26 | debug('CONNECTED') 27 | 28 | var rl = readline.createInterface({ 29 | 'input': process.stdin, 30 | 'output': process.stdout 31 | }) 32 | rl.setPrompt('aria2rpc ≻ ') 33 | rl.prompt() 34 | rl.on('line', function (line) { 35 | line = line.trim() 36 | if (!line) return rl.prompt() 37 | var params = line.split(' ') 38 | var cb = function (err, res) { 39 | if (err) console.error(err) 40 | else console.log(res) 41 | rl.prompt() 42 | } 43 | 44 | var args = params.concat(cb) 45 | 46 | client.send.apply(client, args) 47 | }) 48 | rl.on('close', function () { 49 | debug('CLOSING') 50 | client.close(function () { 51 | debug('CLOSED') 52 | process.exit(0) 53 | }) 54 | }) 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /example/websocket.js: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | 'use strict' 3 | 4 | var Aria2 5 | 6 | // Node.js, browserify, ... 7 | if (typeof module !== 'undefined' && module.exports) { 8 | Aria2 = require('..') 9 | // browsers 10 | } else { 11 | Aria2 = window.Aria2 12 | } 13 | 14 | // those are default options 15 | var options = {'host': 'localhost', 'port': 6800, 'secure': false} 16 | var aria2 = new Aria2(options) 17 | 18 | // triggered when a message is being sent 19 | aria2.onsend = function (m) { 20 | console.log('aria2 OUT:', m) 21 | } 22 | 23 | // triggered when a message has been received 24 | aria2.onmessage = function (m) { 25 | console.log('aria2 IN:', m) 26 | } 27 | 28 | // triggered when socket is open 29 | aria2.onopen = function () { 30 | console.log('aria2 OPEN') 31 | } 32 | 33 | // triggered when socket is closed 34 | aria2.onclose = function () { 35 | console.log('aria2 CLOSED') 36 | } 37 | 38 | aria2.onDownloadStart = function (gid) { 39 | console.log('downloadStart', gid) 40 | } 41 | 42 | // WebSocket is not open so HTTP transport will be used 43 | aria2.send('getVersion', function (err, res) { 44 | console.log('version: ', err || res) 45 | 46 | // open WebSocket 47 | aria2.open(function () { 48 | console.log('open') 49 | 50 | // WebSocket is open so WebSocket transport will be used 51 | aria2.getGlobalOption(function (err, res) { 52 | console.log('global options: ', err || res) 53 | 54 | aria2.send('addUri', ['http://example.org/file', 'http://mirror/file'], {'dir': '/tmp'}, function (err, gid) { 55 | console.log(err || 'gid: ' + gid) 56 | 57 | // close socket 58 | aria2.close(function () { 59 | console.log('closed') 60 | }) 61 | }) 62 | }) 63 | }) 64 | }) 65 | }()) 66 | -------------------------------------------------------------------------------- /test/integration.js: -------------------------------------------------------------------------------- 1 | // import Aria2 from '..' 2 | // import sinon from 'sinon' 3 | // import sinonChai from 'sinon-chai' 4 | // import chai from 'chai' 5 | // const expect = chai.expect 6 | 7 | // chai.use(sinonChai) 8 | 9 | // describe('Aria2', () => { 10 | 11 | // let client 12 | 13 | // beforeEach(function() { 14 | // client = new Aria2() 15 | // }) 16 | 17 | // it('should be an instance of Aria2', () => { 18 | // expect(client).to.be.an.instanceOf(Aria2) 19 | // }) 20 | 21 | // describe('instance properties', () => { 22 | 23 | // it('should have a lastId number property', () => { 24 | // expect(client.lastId).to.be.a('number') 25 | // expect(client.lastId).to.equal(0) 26 | // }) 27 | 28 | // it('should have a callback hash property', () => { 29 | // expect(client.callbacks).to.be.a('object') 30 | // }) 31 | 32 | // it('should have default options properties', () => { 33 | // for (const i in Aria2.options) { 34 | // expect(client[i]).to.equal(Aria2.options[i]) 35 | // } 36 | // }) 37 | 38 | // it('should have a function property for each events', () => { 39 | // Aria2.events.forEach((event) => { 40 | // expect(client[event]).to.be.a('function') 41 | // }) 42 | // }) 43 | 44 | // it('should have a function property for each methods', () => { 45 | // Aria2.methods.forEach((method) => { 46 | // expect(client[method]).to.be.a('function') 47 | // }) 48 | // }) 49 | 50 | // it('should have a function property for each notifications', () => { 51 | // Aria2.notifications.forEach((notification) => { 52 | // expect(client[notification]).to.be.a('function') 53 | // }) 54 | // }) 55 | // }) 56 | 57 | // describe('instance methods', () => { 58 | 59 | // describe('send', () => { 60 | 61 | // it('throws a TypeError if method is not a string', () => { 62 | // expect(client.send.bind(client, null)).to.throw(TypeError) 63 | // }) 64 | 65 | // it('should call onsend once with one argument', () => { 66 | // const spy = sinon.spy(client, 'onsend') 67 | // client.send('barfoo') 68 | // expect(spy).to.have.been.calledOnce 69 | // expect(spy.args[0].length).to.equal(1) 70 | // }) 71 | 72 | // it('should add lastId to the computed message and increment it', () => { 73 | // const spy = sinon.spy(client, 'onsend') 74 | // const lastId = client.lastId 75 | // client.send('barfoo') 76 | // expect(spy.args[0][0]).to.have.deep.property('id', lastId) 77 | // expect(client.lastId).to.equal(lastId + 1) 78 | // }) 79 | 80 | // it('should prefix the method with "aria2."', () => { 81 | // const spy = sinon.spy(client, 'onsend') 82 | // client.send('foobar') 83 | // expect(spy.args[0][0].method).to.equal('aria2.foobar') 84 | // }) 85 | 86 | // it('should add json-rpc property to the computed message', () => { 87 | // const spy = sinon.spy(client, 'onsend') 88 | // client.send('foobar') 89 | // expect(spy.args[0][0]['json-rpc']).to.equal('2.0') 90 | // }) 91 | 92 | // it('should compute arguments > 1 into an array and assign it to the params property', () => { 93 | // const spy = sinon.spy(client, 'onsend') 94 | // client.send('foobar', 'far', 'boo') 95 | // expect(spy.args[0][0].params).to.be.an('array') 96 | // expect(spy.args[0][0].params).to.deep.equal(['far', 'boo']) 97 | // }) 98 | 99 | // it('should add the secret token to params if defined', () => { 100 | // const spy = sinon.spy(client, 'onsend') 101 | // client.secret = 'oo' 102 | // client.send('foobar', 'far', 'boo') 103 | // expect(spy.args[0][0].params[0]).to.equal('token:oo') 104 | // }) 105 | 106 | // it('should add the function argument to callbacks', () => { 107 | // const spy = sinon.spy(client, 'onsend') 108 | // client.secret = 'oo' 109 | // const cb = function() {} 110 | // client.send('foobar', 'foo', 'bar', cb) 111 | // expect(spy.args[0][0].params).to.be.an('array') 112 | // expect(spy.args[0][0].params).to.deep.equal(['token:oo', 'foo', 'bar']) 113 | // const id = spy.args[0][0].id 114 | // expect(client.callbacks[id]).to.equal(cb) 115 | // }) 116 | // }) 117 | 118 | // describe('_onmessage', () => { 119 | 120 | // it('should call the notification function once with correct arguments when receiving a notification', () => { 121 | // Aria2.notifications.forEach((notification) => { 122 | // const spy = sinon.spy(client, notification) 123 | // const message = {'method': 'aria2.' + notification, 'params': ['foo', 'bar']} 124 | // client._onmessage(message) 125 | 126 | // expect(spy).to.have.been.calledOnce 127 | // expect(spy).to.have.been.calledWith('foo', 'bar') 128 | // }) 129 | // }) 130 | 131 | // it('should call the callback of a request when receiving a response', () => { 132 | // const spySend = sinon.spy(client, 'onsend') 133 | // const callback = sinon.spy() 134 | // client.send('foobar', callback) 135 | // const id = spySend.args[0][0].id 136 | // expect(client.callbacks[id]).to.equal(callback) 137 | // const message = {'method': 'aria2.foobar', id} 138 | // client._onmessage(message) 139 | 140 | // expect(callback).to.have.been.calledOnce 141 | // }) 142 | 143 | // it('should call and delete the callback of a request with error when receiving a response with error', () => { 144 | // const spySend = sinon.spy(client, 'onsend') 145 | // const callback = sinon.spy() 146 | // client.send('foobar', callback) 147 | // const id = spySend.args[0][0].id 148 | // expect(client.callbacks[id]).to.equal(callback) 149 | // const message = {'method': 'aria2.foobar', id, 'error': 'whatever'} 150 | // client._onmessage(message) 151 | 152 | // expect(callback).to.have.been.calledWith('whatever') 153 | // expect(client.callbacks[id]).to.equal(undefined) 154 | // }) 155 | 156 | // it('should call and delete the callback of a request with result when receiving a response with result', () => { 157 | // const spySend = sinon.spy(client, 'onsend') 158 | // const callback = sinon.spy() 159 | // client.send('foobar', callback) 160 | // const id = spySend.args[0][0].id 161 | // expect(client.callbacks[id]).to.equal(callback) 162 | // const message = { 163 | // id, 164 | // 'method': 'aria2.foobar', 165 | // 'result': 'foobar', 166 | // } 167 | // client._onmessage(message) 168 | 169 | // expect(callback).to.have.been.calledWith(null, 'foobar') 170 | // expect(client.callbacks[id]).to.equal(undefined) 171 | // }) 172 | // }) 173 | 174 | // describe('aria2 methods', () => { 175 | 176 | // it('should call send once with correct arguments for each methods function', () => { 177 | // const spy = sinon.spy(client, 'send') 178 | // Aria2.methods.forEach(function(method) { 179 | // client[method]('foo', 'bar') 180 | // expect(spy).to.have.been.calledWith(method, 'foo', 'bar') 181 | // }) 182 | // }) 183 | // }) 184 | // }) 185 | // }) 186 | -------------------------------------------------------------------------------- /test/unit.js: -------------------------------------------------------------------------------- 1 | ;(function (global) { 2 | 'use strict' 3 | 4 | /* global describe, it, beforeEach */ 5 | 6 | var Aria2 7 | var sinon 8 | var chai 9 | var expect 10 | var sinonChai 11 | 12 | if (typeof module !== 'undefined' && module.exports) { 13 | Aria2 = require('..') 14 | sinon = require('sinon') 15 | chai = require('chai') 16 | sinonChai = require('sinon-chai') 17 | chai.use(sinonChai) 18 | } else { 19 | Aria2 = global.Aria2 20 | sinon = global.sinon 21 | chai = global.chai 22 | sinonChai = global.sinonChai 23 | } 24 | 25 | expect = chai.expect 26 | 27 | describe('Aria2', function () { 28 | var client 29 | 30 | beforeEach(function () { 31 | client = new Aria2() 32 | client.http = sinon.stub() 33 | }) 34 | 35 | it('should be an instance of Aria2', function () { 36 | expect(client).to.be.an.instanceOf(Aria2) 37 | }) 38 | 39 | describe('instance properties', function () { 40 | it('should have a lastId number property', function () { 41 | expect(client.lastId).to.be.a('number') 42 | expect(client.lastId).to.equal(0) 43 | }) 44 | 45 | it('should have a callback hash property', function () { 46 | expect(client.callbacks).to.be.a('object') 47 | }) 48 | 49 | it('should have default options properties', function () { 50 | for (var i in Aria2.options) { 51 | expect(client[i]).to.equal(Aria2.options[i]) 52 | } 53 | }) 54 | 55 | it('should have a function property for each events', function () { 56 | Aria2.events.forEach(function (event) { 57 | expect(client[event]).to.be.a('function') 58 | }) 59 | }) 60 | 61 | it('should have a function property for each methods', function () { 62 | Aria2.methods.forEach(function (method) { 63 | var sufix = method.indexOf('system.') === 0 ? method.split('system.')[1] : method 64 | expect(client[sufix]).to.be.a('function') 65 | }) 66 | }) 67 | 68 | it('should have a function property for each notifications', function () { 69 | Aria2.notifications.forEach(function (notification) { 70 | expect(client[notification]).to.be.a('function') 71 | }) 72 | }) 73 | }) 74 | 75 | describe('instance methods', function () { 76 | describe('send', function () { 77 | it('throws a TypeError if method is not a string', function () { 78 | expect(client.send.bind(client, null)).to.throw(TypeError) 79 | }) 80 | 81 | it('should call onsend once with one argument', function () { 82 | var spy = sinon.spy(client, 'onsend') 83 | client.send('barfoo') 84 | expect(spy).to.have.been.calledOnce 85 | expect(spy.args[0].length).to.equal(1) 86 | }) 87 | 88 | it('should add lastId to the computed message and increment it', function () { 89 | var spy = sinon.spy(client, 'onsend') 90 | var lastId = client.lastId 91 | client.send('barfoo') 92 | expect(spy.args[0][0]).to.have.deep.property('id', lastId) 93 | expect(client.lastId).to.equal(lastId + 1) 94 | }) 95 | 96 | it('should prefix the method with "aria2."', function () { 97 | var spy = sinon.spy(client, 'onsend') 98 | client.send('foobar') 99 | expect(spy.args[0][0].method).to.equal('aria2.foobar') 100 | }) 101 | 102 | it('shouldn\'t prefix the method with "aria2." if it starts with "system."', function () { 103 | var spy = sinon.spy(client, 'onsend') 104 | client.send('system.foobar') 105 | expect(spy.args[0][0].method).to.equal('system.foobar') 106 | }) 107 | 108 | it('shouldn\'t prefix the method with "aria2." if it starts with "aria2."', function () { 109 | var spy = sinon.spy(client, 'onsend') 110 | client.send('aria2.foobar') 111 | expect(spy.args[0][0].method).to.equal('aria2.foobar') 112 | }) 113 | 114 | it('should add json-rpc property to the computed message', function () { 115 | var spy = sinon.spy(client, 'onsend') 116 | client.send('foobar') 117 | expect(spy.args[0][0]['json-rpc']).to.equal('2.0') 118 | }) 119 | 120 | it('should compute arguments > 1 into an array and assign it to the params property', function () { 121 | var spy = sinon.spy(client, 'onsend') 122 | client.send('foobar', 'far', 'boo') 123 | expect(spy.args[0][0].params).to.be.an('array') 124 | expect(spy.args[0][0].params).to.deep.equal(['far', 'boo']) 125 | }) 126 | 127 | it('should add the secret token to params if defined', function () { 128 | var spy = sinon.spy(client, 'onsend') 129 | client.secret = 'oo' 130 | client.send('foobar', 'far', 'boo') 131 | expect(spy.args[0][0].params[0]).to.equal('token:oo') 132 | }) 133 | 134 | it('should add the function argument to callbacks', function () { 135 | var spy = sinon.spy(client, 'onsend') 136 | client.secret = 'oo' 137 | var cb = function () {} 138 | client.send('foobar', 'foo', 'bar', cb) 139 | expect(spy.args[0][0].params).to.be.an('array') 140 | expect(spy.args[0][0].params).to.deep.equal(['token:oo', 'foo', 'bar']) 141 | var id = spy.args[0][0].id 142 | expect(client.callbacks[id]).to.be.a('function') 143 | }) 144 | }) 145 | 146 | describe('_onmessage', function () { 147 | it('should call the notification function once with correct arguments when receiving a notification', function () { 148 | Aria2.notifications.forEach(function (notification) { 149 | var spy = sinon.spy(client, notification) 150 | var message = {'method': 'aria2.' + notification, 'params': ['foo', 'bar']} 151 | client._onmessage(message) 152 | 153 | expect(spy).to.have.been.calledOnce 154 | expect(spy).to.have.been.calledWith('foo', 'bar') 155 | }) 156 | }) 157 | 158 | it('should call the callback of a request when receiving a response', function () { 159 | var spySend = sinon.spy(client, 'onsend') 160 | var callback = sinon.spy() 161 | client.send('foobar', callback) 162 | var id = spySend.args[0][0].id 163 | expect(client.callbacks[id]).to.be.a('function') 164 | var message = {'method': 'aria2.foobar', 'id': id} 165 | client._onmessage(message) 166 | 167 | expect(callback).to.have.been.calledOnce 168 | }) 169 | 170 | it('should call and delete the callback of a request with error when receiving a response with error', function () { 171 | var spySend = sinon.spy(client, 'onsend') 172 | var callback = sinon.spy() 173 | client.send('foobar', callback) 174 | var id = spySend.args[0][0].id 175 | expect(client.callbacks[id]).to.be.a('function') 176 | var message = {'method': 'aria2.foobar', 'id': id, 'error': 'whatever'} 177 | client._onmessage(message) 178 | 179 | expect(callback).to.have.been.calledWith('whatever') 180 | expect(client.callbacks[id]).to.equal(undefined) 181 | }) 182 | 183 | it('should call and delete the callback of a request with result when receiving a response with result', function () { 184 | var spySend = sinon.spy(client, 'onsend') 185 | var callback = sinon.spy() 186 | client.send('foobar', callback) 187 | var id = spySend.args[0][0].id 188 | expect(client.callbacks[id]).to.be.a('function') 189 | var message = { 190 | 'id': id, 191 | 'method': 'aria2.foobar', 192 | 'result': 'foobar' 193 | } 194 | client._onmessage(message) 195 | 196 | expect(callback).to.have.been.calledWith(null, 'foobar') 197 | expect(client.callbacks[id]).to.equal(undefined) 198 | }) 199 | }) 200 | 201 | describe('aria2 methods', function () { 202 | it('should call send once with correct arguments for each methods function', function () { 203 | var spy = sinon.spy(client, 'send') 204 | var cb = function () {} 205 | Aria2.methods.forEach(function (method) { 206 | var sufix = method.indexOf('system.') === 0 ? method.split('system.')[1] : method 207 | client[sufix]('foo', 'bar', cb) 208 | expect(spy).to.have.been.calledWith(method, 'foo', 'bar', cb) 209 | }) 210 | }) 211 | }) 212 | }) 213 | }) 214 | }(typeof global !== 'undefined' ? global : this)) 215 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | aria2.js 2 | ======== 3 | 4 | JavaScript (Node.js and browsers) library and [cli](https://github.com/sonnyp/aria2.js/blob/master/bin/README.md) for [aria2, "The next generation download utility."](https://aria2.github.io/) 5 | 6 | [![Build Status](https://img.shields.io/travis/sonnyp/aria2.js/master.svg?style=flat-square)](https://travis-ci.org/sonnyp/aria2.js/branches) 7 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/) 8 | 9 | [![Dependency Status](https://img.shields.io/david/sonnyp/aria2.js.svg?style=flat-square)](https://david-dm.org/sonnyp/aria2.js) 10 | [![devDependency Status](https://img.shields.io/david/dev/sonnyp/aria2.js.svg?style=flat-square)](https://david-dm.org/sonnyp/aria2.js#info=devDependencies) 11 | 12 | - [Introduction](#introduction) 13 | - [Getting started](#getting-started) 14 | - [Usage](#usage) 15 | - [open](#open) 16 | - [close](#close) 17 | - [onsend and onmessage](#onsend-and-onmessage) 18 | - [aria2 methods](#aria2-methods) 19 | - [addUri](https://aria2.github.io/manual/en/html/aria2c.html#aria2.addUri) 20 | - [addTorrent](https://aria2.github.io/manual/en/html/aria2c.html#aria2.addTorrent) 21 | - [addMetaLink](https://aria2.github.io/manual/en/html/aria2c.html#aria2.addMetalink) 22 | - [remove](https://aria2.github.io/manual/en/html/aria2c.html#aria2.remove) 23 | - [forceRemove](https://aria2.github.io/manual/en/html/aria2c.html#aria2.forceRemove) 24 | - [pause](https://aria2.github.io/manual/en/html/aria2c.html#aria2.pause) 25 | - [pauseAll](https://aria2.github.io/manual/en/html/aria2c.html#aria2.pauseAll) 26 | - [forcePause](https://aria2.github.io/manual/en/html/aria2c.html#aria2.forcePause) 27 | - [forcePauseAll](https://aria2.github.io/manual/en/html/aria2c.html#aria2.forcePauseAll) 28 | - [unpause](https://aria2.github.io/manual/en/html/aria2c.html#aria2.unpause) 29 | - [unpauseAll](https://aria2.github.io/manual/en/html/aria2c.html#aria2.unpauseAll) 30 | - [tellStatus](https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellStatus) 31 | - [getUris](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getUris) 32 | - [getFiles](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getFiles) 33 | - [getPeers](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getPeers) 34 | - [getServers](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getServers) 35 | - [tellActive](https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellActive) 36 | - [tellWaiting](https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellWaiting) 37 | - [tellStopped](https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellStopped) 38 | - [changePosition](https://aria2.github.io/manual/en/html/aria2c.html#aria2.changePosition) 39 | - [changeUri](https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeUri) 40 | - [getOption](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getOption) 41 | - [changeOption](https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeOption) 42 | - [getGlobalOption](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getGlobalOption) 43 | - [changeGlobalOption](https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeGlobalOption) 44 | - [getGlobalStat](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getGlobalStat) 45 | - [purgeDownloadResult](https://aria2.github.io/manual/en/html/aria2c.html#aria2.purgeDownloadResult) 46 | - [removeDownloadResult](https://aria2.github.io/manual/en/html/aria2c.html#aria2.removeDownloadResult) 47 | - [getVersion](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getVersion) 48 | - [getSessionInfo](https://aria2.github.io/manual/en/html/aria2c.html#aria2.getSessionInfo) 49 | - [shutdown](https://aria2.github.io/manual/en/html/aria2c.html#aria2.shutdown) 50 | - [forceShutdown](https://aria2.github.io/manual/en/html/aria2c.html#aria2.forceShutdown) 51 | - [saveSession](https://aria2.github.io/manual/en/html/aria2c.html#aria2.saveSession) 52 | - [system.multicall](https://aria2.github.io/manual/en/html/aria2c.html#system.multicall) 53 | - [system.listMethods](https://aria2.github.io/manual/en/html/aria2c.html#system.listMethods) 54 | - [system.listNotifications](https://aria2.github.io/manual/en/html/aria2c.html#system.listNotifications) 55 | - [aria2 events](#aria2-events) 56 | - [onDownloadStart](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadStart) 57 | - [onDownloadPause](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadPause) 58 | - [onDownloadStop](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadStop) 59 | - [onDownloadComplete](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadComplete) 60 | - [onDownloadError](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadError) 61 | - [onBtDownloadComplete](https://aria2.github.io/manual/en/html/aria2c.html#aria2.onBtDownloadComplete) 62 | - [Example](#example) 63 | - [Contributing](#contributing) 64 | 65 | 66 | # Introduction 67 | 68 | aria2.js controls aria2 via its [JSON-RPC interface](https://aria2.github.io/manual/en/html/aria2c.html#rpc-interface) and features 69 | 70 | - Node.js and browsers support 71 | - multiple transports 72 | - [HTTP](https://aria2.github.io/manual/en/html/aria2c.html#rpc-interface) 73 | - [WebSocket](https://aria2.github.io/manual/en/html/aria2c.html#json-rpc-over-websocket) 74 | - ~~[JSONP](https://aria2.github.io/manual/en/html/aria2c.html#json-rpc-using-http-get)~~ [#25](https://github.com/sonnyp/aria2.js/pull/25) 75 | - callback API 76 | - promise API 77 | - light (1.5KB minified and gzipped) 78 | 79 | [↑](#aria2js) 80 | 81 | # Getting started 82 | 83 | 84 | `npm install aria2` 85 | 86 | ---- 87 | 88 | ```javascript 89 | var Aria2 = require('aria2'); 90 | ``` 91 | 92 | or 93 | 94 | ```xml 95 | 96 | ``` 97 | ```javascript 98 | var Aria2 = window.Aria2 99 | ``` 100 | 101 | ---- 102 | 103 | Start aria2c in daemon mode with 104 | 105 | `aria2c --enable-rpc --rpc-listen-all=true --rpc-allow-origin-all` 106 | 107 | [↑](#aria2js) 108 | 109 | # Usage 110 | 111 | ```javascript 112 | var aria2 = new Aria2([options]); 113 | ``` 114 | 115 | default options match aria2c defaults and are 116 | 117 | ```javascript 118 | { 119 | host: 'localhost', 120 | port: 6800, 121 | secure: false, 122 | secret: '', 123 | path: '/jsonrpc' 124 | } 125 | ``` 126 | 127 | `secret` is optional and refers to [--rpc-secret](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption--rpc-secret). 128 | 129 | If the WebSocket is open (via the [open method](#open)) aria2.js will use the WebSocket transport, otherwise the HTTP transport. 130 | 131 | For HTTP, aria2.js makes use of the new fetch standard, you might need a [polyfill](https://github.com/github/fetch) if you want to support older browsers. 132 | 133 | [↑](#aria2js) 134 | 135 | ## open 136 | 137 | `aria2.open()` opens the WebSocket connection. 138 | 139 | ```javascript 140 | aria2.onopen = function() { 141 | console.log('aria2 open'); 142 | }; 143 | 144 | aria2.open([cb]); 145 | // or 146 | aria2.open().then(fn) 147 | ``` 148 | 149 | [↑](#aria2js) 150 | 151 | ## close 152 | 153 | `aria2.close()` closes the WebSocket connection. 154 | 155 | ```javascript 156 | aria2.onclose = function() { 157 | console.log('aria2 closed!'); 158 | }; 159 | 160 | aria2.close([cb]); // callback style 161 | // or 162 | aria2.close().then(fn); // promise style 163 | ``` 164 | 165 | [↑](#aria2js) 166 | 167 | ## onsend and onmessage 168 | 169 | `aria2.onsend()` is called for every message sent. 170 | `aria2.onmessage()` is called for every message received. 171 | 172 | ```javascript 173 | aria2.onsend = function(m) { 174 | console.log('aria2 OUT', m); 175 | }; 176 | aria2.onmessage = function(m) { 177 | console.log('aria2 IN', m); 178 | }; 179 | ``` 180 | 181 | [↑](#aria2js) 182 | 183 | ## aria2 methods 184 | For a complete listing see [aria2 methods](https://aria2.github.io/manual/en/html/aria2c.html#methods). 185 | 186 | If you passed the secret option to aria2.js, it will be automatically added to every request so there is no need to include it. 187 | 188 | For every aria2 methods you can use 189 | 190 | #### callback style 191 | ```javascript 192 | aria2.getVersion([params,] function(err, res) { 193 | console.log(err || res); 194 | }); 195 | ``` 196 | 197 | or 198 | 199 | ```javascript 200 | aria2.send('getVersion', [params,] function(err, res) { 201 | console.log(err || res); 202 | }); 203 | ``` 204 | 205 | #### promise style 206 | 207 | ```javascript 208 | aria2.getVersion([params,]).then(fn) 209 | ``` 210 | 211 | or 212 | 213 | ```javascript 214 | aria2.send('getVersion', [params,]).then(fn) 215 | ``` 216 | 217 | [↑](#aria2js) 218 | 219 | ## aria2 events 220 | 221 | For a complete listing see [aria2 notifications](https://aria2.github.io/manual/en/html/aria2c.html#json-rpc-over-websocket). 222 | 223 | For every notifications you can bind a function. 224 | 225 | ```javascript 226 | aria2.onDownloadStart = function(gid) { 227 | console.log(gid); 228 | }; 229 | ``` 230 | 231 | [↑](#aria2js) 232 | 233 | # Example 234 | 235 | See [example](https://github.com/sonnyp/aria2.js/blob/master/example/). 236 | 237 | [↑](#aria2js) 238 | 239 | # Tests 240 | 241 | ``` 242 | npm install 243 | npm test 244 | ``` 245 | 246 | [↑](#aria2js) 247 | 248 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | ;(function (global) { 2 | 'use strict' 3 | 4 | var WebSocket 5 | var fetch 6 | var pg 7 | 8 | var isNode = typeof module !== 'undefined' && module.exports 9 | 10 | if (isNode) { 11 | WebSocket = require('ws') 12 | fetch = require('node-fetch') 13 | pg = require('polygoat') 14 | } else { 15 | WebSocket = global.WebSocket 16 | fetch = global.fetch 17 | pg = global.polygoat 18 | } 19 | 20 | var Aria2 = function (opts) { 21 | this.callbacks = Object.create(null) 22 | this.lastId = 0 23 | 24 | for (var i in Aria2.options) { 25 | this[i] = typeof opts === 'object' && i in opts ? opts[i] : Aria2.options[i] 26 | } 27 | } 28 | 29 | Aria2.prototype.http = function (m, fn) { 30 | var that = this 31 | var content = { 32 | method: m.method, 33 | id: m.id 34 | } 35 | 36 | if (Array.isArray(m.params) && m.params.length > 0) { 37 | content.params = m.params 38 | } 39 | 40 | var url = 'http' + (this.secure ? 's' : '') + '://' + this.host + ':' + this.port + this.path 41 | fetch(url, { 42 | method: 'POST', 43 | body: JSON.stringify(content), 44 | headers: { 45 | 'Accept': 'application/json', 46 | 'Content-Type': 'application/json' 47 | }}) 48 | .then(function (res) { 49 | return res.json() 50 | }) 51 | .then(function (msg) { 52 | that._onmessage(msg) 53 | }) 54 | .catch(fn) 55 | } 56 | 57 | Aria2.prototype.send = function (method /* [,param] [,param] [,...] [, fn] */) { 58 | var params = Array.prototype.slice.call(arguments, 1) 59 | var cb = typeof params[params.length - 1] === 'function' ? params.pop() : null 60 | return this.exec(method, params, cb) 61 | } 62 | 63 | Aria2.prototype.exec = function (method, parameters, cb) { 64 | if (typeof method !== 'string') { 65 | throw new TypeError(method + ' is not a string') 66 | } 67 | 68 | if (method.indexOf('system.') !== 0 && method.indexOf('aria2.') !== 0) { 69 | method = 'aria2.' + method 70 | } 71 | 72 | var m = { 73 | 'method': method, 74 | 'json-rpc': '2.0', 75 | 'id': this.lastId++ 76 | } 77 | 78 | var params = this.secret ? ['token:' + this.secret] : [] 79 | if (Array.isArray(parameters)) { 80 | params = params.concat(parameters) 81 | } 82 | 83 | if (params.length > 0) m.params = params 84 | 85 | this.onsend(m) 86 | 87 | var that = this 88 | 89 | // send via websocket 90 | if (this.socket && this.socket.readyState === 1) { 91 | this.socket.send(JSON.stringify(m)) 92 | // send via http 93 | } else { 94 | this.http(m, function (err) { 95 | that.callbacks[m.id](err) 96 | delete that.callbacks[m.id] 97 | }) 98 | } 99 | 100 | return pg(function (done) { 101 | that.callbacks[m.id] = done 102 | }, cb) 103 | } 104 | 105 | Aria2.prototype._onmessage = function (m) { 106 | this.onmessage(m) 107 | 108 | if (m.id !== undefined) { 109 | var callback = this.callbacks[m.id] 110 | if (callback) { 111 | if (m.error) { 112 | callback(m.error) 113 | } else { 114 | callback(null, m.result) 115 | } 116 | delete this.callbacks[m.id] 117 | } 118 | } else if (m.method) { 119 | var n = m.method.split('aria2.')[1] 120 | if (n.indexOf('on') === 0 && typeof this[n] === 'function' && Aria2.notifications.indexOf(n) > -1) { 121 | this[n].apply(this, m.params) 122 | } 123 | } 124 | } 125 | 126 | Aria2.prototype.open = function (fn) { 127 | var url = 'ws' + (this.secure ? 's' : '') + '://' + this.host + ':' + this.port + this.path 128 | var socket = this.socket = new WebSocket(url) 129 | var that = this 130 | var called = false 131 | 132 | socket.onclose = function () { 133 | that.onclose() 134 | } 135 | socket.onmessage = function (event) { 136 | that._onmessage(JSON.parse(event.data)) 137 | } 138 | 139 | return pg(function (done) { 140 | socket.onopen = function () { 141 | if (!called) { 142 | done() 143 | called = true 144 | } 145 | that.onopen() 146 | } 147 | socket.onerror = function (err) { 148 | if (!called) { 149 | done(err) 150 | called = true 151 | } 152 | } 153 | }, fn) 154 | } 155 | 156 | Aria2.prototype.close = function (fn) { 157 | var socket = this.socket 158 | return pg(function (done) { 159 | if (!socket) { 160 | done() 161 | } else { 162 | socket.addEventListener('close', function () { 163 | done() 164 | }) 165 | socket.close() 166 | } 167 | }, fn) 168 | } 169 | 170 | // https://aria2.github.io/manual/en/html/aria2c.html#methods 171 | Aria2.methods = [ 172 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.addUri 173 | 'addUri', 174 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.addTorrent 175 | 'addTorrent', 176 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.addMetalink 177 | 'addMetalink', 178 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.remove 179 | 'remove', 180 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.forceRemove 181 | 'forceRemove', 182 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.pause 183 | 'pause', 184 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.pauseAll 185 | 'pauseAll', 186 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.forcePause 187 | 'forcePause', 188 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.forcePauseAll 189 | 'forcePauseAll', 190 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.unpause 191 | 'unpause', 192 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.unpauseAll 193 | 'unpauseAll', 194 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellStatus 195 | 'tellStatus', 196 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getUris 197 | 'getUris', 198 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getFiles 199 | 'getFiles', 200 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getPeers 201 | 'getPeers', 202 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getServers 203 | 'getServers', 204 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellActive 205 | 'tellActive', 206 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellWaiting 207 | 'tellWaiting', 208 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.tellStopped 209 | 'tellStopped', 210 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.changePosition 211 | 'changePosition', 212 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeUri 213 | 'changeUri', 214 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getOption 215 | 'getOption', 216 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeOption 217 | 'changeOption', 218 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getGlobalOption 219 | 'getGlobalOption', 220 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.changeGlobalOption 221 | 'changeGlobalOption', 222 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getGlobalStat 223 | 'getGlobalStat', 224 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.purgeDownloadResult 225 | 'purgeDownloadResult', 226 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.removeDownloadResult 227 | 'removeDownloadResult', 228 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getVersion 229 | 'getVersion', 230 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.getSessionInfo 231 | 'getSessionInfo', 232 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.shutdown 233 | 'shutdown', 234 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.forceShutdown 235 | 'forceShutdown', 236 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.saveSession 237 | 'saveSession', 238 | // https://aria2.github.io/manual/en/html/aria2c.html#system.multicall 239 | 'system.multicall', 240 | // https://aria2.github.io/manual/en/html/aria2c.html#system.listMethods 241 | 'system.listMethods', 242 | // https://aria2.github.io/manual/en/html/aria2c.html#system.listNotifications 243 | 'system.listNotifications' 244 | ] 245 | 246 | // https://aria2.github.io/manual/en/html/aria2c.html#notifications 247 | Aria2.notifications = [ 248 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadStart 249 | 'onDownloadStart', 250 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadPause 251 | 'onDownloadPause', 252 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadStop 253 | 'onDownloadStop', 254 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadComplete 255 | 'onDownloadComplete', 256 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onDownloadError 257 | 'onDownloadError', 258 | // https://aria2.github.io/manual/en/html/aria2c.html#aria2.onBtDownloadComplete 259 | 'onBtDownloadComplete' 260 | ] 261 | 262 | Aria2.events = [ 263 | 'onopen', 264 | 'onclose', 265 | 'onsend', 266 | 'onmessage' 267 | ] 268 | 269 | Aria2.options = { 270 | 'secure': false, 271 | 'host': 'localhost', 272 | 'port': 6800, 273 | 'secret': '', 274 | 'path': '/jsonrpc' 275 | } 276 | 277 | Aria2.methods.forEach(function (method) { 278 | var sufix = method.indexOf('.') > -1 ? method.split('.')[1] : method 279 | Aria2.prototype[sufix] = function (/* [param] [,param] [,...] */) { 280 | return this.send.apply(this, [method].concat(Array.prototype.slice.call(arguments))) 281 | } 282 | }) 283 | 284 | Aria2.notifications.forEach(function (notification) { 285 | Aria2.prototype[notification] = function () {} 286 | }) 287 | 288 | Aria2.events.forEach(function (event) { 289 | Aria2.prototype[event] = function () {} 290 | }) 291 | 292 | if (isNode) { 293 | module.exports = Aria2 294 | } else { 295 | global.Aria2 = Aria2 296 | } 297 | }(this)) 298 | --------------------------------------------------------------------------------