Aria2 RPC Library 维护,源脚本 https://greasyfork.org/zh-CN/scripts/402652
This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/528191/1543992/Aria2%20RPC%20Edit%202.js
// ==UserScript==// @name Aria2 RPC Edit 2// @namespace https://greasyfork.org/users/667968-pyudng// @version 0.4.2// @description Aria2 RPC Library 维护,源脚本 https://greasyfork.org/zh-CN/scripts/402652// @author PY-DNG// @original-author moe.jixun, Sonic853// @original-license MIT, MIT// @original-script https://greasyfork.org/scripts/5672-aria2-rpc, https://greasyfork.org/zh-CN/scripts/402652// @license MIT// @grant GM_xmlhttpRequest// ==/UserScript==/*Information from original script https://greasyfork.org/zh-CN/scripts/402652:// Source code: https://github.com/Sonic853/Static_library/blob/master/aria2.ts// tsc .\aria2.ts --target esnext// Public Class Aria2 ( options )*/const Aria2AUTH = {noAuth: 0,basic: 1,secret: 2,0: 'noAuth',1: 'basic',2: 'secret'};class Aria2BATCH {parent;data = [];onSuccess;onFail;addRaw(fn, params) {this.data.push({method: `aria2.${fn}`,params});}add(fn, ...args) {if (this.parent[fn] === undefined)throw new Error(`Unknown function: ${fn}, please check if you had a typo.`);return this.addRaw(fn, args);}async send() {let ret = await this.parent.send(true, this.data, this.onSuccess, this.onFail);this.reset();return ret;}getActions() {return this.data.slice();}setActions(actions) {if (!actions || !actions.map)return;this.data = actions;}reset() {this.onSuccess = this.onFail = null;this.data = [];}constructor(obj, cbSuccess, cbFail) {this.parent = obj;this.onSuccess = cbSuccess;this.onFail = cbFail;}}var Aria2 = class AriaBase {/*** @constant* @type {'2.0'}*/jsonrpc_ver = '2.0';/*** last aria2 request id* @type {number}*/id;/*** @typedef {Object} Aria2Auth* @property {string} [secret]* @property {string} [user]* @property {string} [pass]*//*** @typedef {Object} Aria2Options* @property {Aria2Auth} [auth] - defaults to Aria2AUTH.noAuth* @property {string} [host='localhost']* @property {number} [port=6800]* @property {boolean} [https=false]* @property {string} [endpoint='/jsonrpc']*//** @type {Aria2Options} */options;/*** @param {Aria2Options} options*/constructor(options) {// optionsAriaBase.#Assert(!options.host || typeof options.host === 'string', 'options.host should be string', TypeError);AriaBase.#Assert(!options.port || typeof options.port === 'number', 'options.port should be number', TypeError);this.options = Object.assign({auth: { type: Aria2AUTH.noAuth },host: 'localhost',port: 6800,https: false,endpoint: '/jsonrpc'}, options);// init idthis.id = (+new Date());// warning for not-GM_xmlhttpRequest requesttypeof GM_xmlhttpRequest === 'undefined' && console.warn(['Warning: You are now using an simple implementation of GM_xmlhttpRequest','Cross-domain request are not avilible unless configured correctly @ target server.','','Some of its features are not avilible, such as `username` and `password` field.'].join('\n'));// aria2 methods implementationconst isFunction = obj => typeof obj === 'function';["addUri", "addTorrent", "addMetalink", "remove", "forceRemove","pause", "pauseAll", "forcePause", "forcePauseAll", "unpause","unpauseAll", "tellStatus", "getUris", "getFiles", "getPeers","getServers", "tellActive", "tellWaiting", "tellStopped","changePosition", "changeUri", "getOption", "changeOption","getGlobalOption", "changeGlobalOption", "getGlobalStat","purgeDownloadR###lt", "removeDownloadR###lt", "getVersion","getSessionInfo", "shutdown", "forceShutdown", "saveSession"].forEach(sMethod => {this[sMethod] = async (...args) => {let cbSuccess, cbError;if (args.length && isFunction(args[args.length - 1])) {cbSuccess = args[args.length - 1];args.splice(-1, 1);if (args.length && isFunction(args[args.length - 1])) {cbError = cbSuccess;cbSuccess = args[args.length - 1];args.splice(-1, 1);}}return await this.send(false, {method: `aria2.${sMethod}`,params: args}, cbSuccess, cbError);};});}/*** Get basic authentication header string* @returns {string}*/#getBasicAuth() {return btoa(`${this.options.auth.user}:${this.options.auth.pass}`);}async send(bIsDataBatch, data, cbSuccess, cbError) {// update request idthis.id = (+new Date());// construct payloadlet srcTaskObj = { jsonrpc: this.jsonrpc_ver, id: this.id };let payload = {method: 'POST',url: `${this.options.https ? 'https' : 'http'}://${this.options.host}:${this.options.port}${this.options.endpoint}`,headers: {'Content-Type': 'application/json; charset=UTF-8'},data: bIsDataBatch? data.map(e => { return AriaBase.#merge({}, srcTaskObj, e); }): AriaBase.#merge({}, srcTaskObj, data),onload: r => {if (r.status !== 200) {cbError && cbError(r);} else {let repData;try {repData = JSON.parse(r.responseText);repData.error && cbError(repData);} catch (error) {repData = r.responseText;}cbSuccess && cbSuccess(repData);}},onerror: cbError ? cbError.bind(null) : null};// authenticationswitch (this.options.auth.type) {case Aria2AUTH.basic: {payload.headers.Authorization = 'Basic ' + this.#getBasicAuth();break;}case Aria2AUTH.secret: {let sToken = `token:${this.options.auth.pass}`;if (bIsDataBatch) {for (let i = 0; i < payload.data.length; i++) {payload.data[i].params.splice(0, 0, sToken);}}else {if (!payload.data.params)payload.data.params = [];payload.data.params.splice(0, 0, sToken);}break;}case Aria2AUTH.noAuth:default: {break;}}return await AriaBase.#doRequest(payload);}BATCH = new Aria2BATCH(this);/*** merge moultiple source objects' properties into base object* @param {object} base* @param {...object} sources* @returns*/static #merge(base, ...sources) {const isObject = obj => typeof obj === 'object' && obj !== null;this.#Assert(isObject(base), 'base should be an object', TypeError);sources.forEach(obj => {this.#Assert(isObject(obj), 'source should be an object', TypeError);Object.keys(obj).forEach(key => {if (isObject(base[key]) && isObject(obj[key])) {base[key] = AriaBase.#merge(base[key], obj[key]);} else {base[key] = obj[key];}});});return base;}/*** throw error when condition not met* @param {boolean} condition* @param {string} message* @param {function} ErrorConstructor*/static #Assert(condition, message, ErrorConstructor = Error) {if (!condition) {throw new ErrorConstructor(message);}}static async #doRequest(details) {const { url, method, data, headers, onload, onerror } = details;if (typeof GM_xmlhttpRequest !== 'undefined') {return new Promise((resolve, reject) => {GM_xmlhttpRequest({url,method,data: typeof data === 'string' ? data : JSON.stringify(data),headers,onload(r) {onload && onload(r);resolve(r);},onerror() {onerror && onerror();reject();}});});} else {try {let response = await fetch(url, {method,body: typeof data === 'string' ? data : JSON.stringify(data),headers});let responseText = await response.text();onload && onload(responseText);return {readyState: 4,responseHeaders: response.headers,status: response.status,statusText: response.statusText,response,responseText,finalUrl: response.url};} catch (error) {onerror && onerror(error);throw error;}}}};