mirror of https://github.com/IoTcat/PyOne.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
390 lines
14 KiB
390 lines
14 KiB
#-*- coding=utf-8 -*- |
|
import requests |
|
import json |
|
import subprocess |
|
import os |
|
import time |
|
import base64 |
|
import sys |
|
if sys.version_info[0]==2: |
|
import xmlrpclib |
|
else: |
|
import xmlrpc.client as xmlrpclib |
|
from self_config import * |
|
|
|
|
|
class PyAria2(object): |
|
|
|
def __init__(self,host,port,secret,scheme,session=None): |
|
''' |
|
PyAria2 constructor. |
|
host: string, aria2 rpc host, default is 'localhost' |
|
port: integer, aria2 rpc port, default is 6800 |
|
session: string, aria2 rpc session saving. |
|
''' |
|
if not isAria2Installed(): |
|
raise Exception('aria2 is not installed, please install it before.') |
|
|
|
if not isAria2rpcRunning(): |
|
cmd = 'aria2c' \ |
|
' --enable-rpc' \ |
|
' --rpc-listen-port {}' \ |
|
' --continue' \ |
|
' --max-concurrent-downloads=20' \ |
|
' --max-connection-per-server=10' \ |
|
' --rpc-max-request-size=1024M'.format(port) |
|
|
|
if not session is None: |
|
cmd += ' --input-file=%s' \ |
|
' --save-session-interval=60' \ |
|
' --save-session=%s' % (session, session) |
|
|
|
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) |
|
|
|
count = 0 |
|
while True: |
|
if isAria2rpcRunning(): |
|
break |
|
else: |
|
count += 1 |
|
time.sleep(3) |
|
if count == 5: |
|
raise Exception('aria2 RPC server started failure.') |
|
print('aria2 RPC server is started.') |
|
else: |
|
print('aria2 RPC server is already running.') |
|
self.server_uri = scheme+'://{}:{}/jsonrpc'.format(host, port) |
|
self.secret = secret |
|
self.server = xmlrpclib.ServerProxy(self.server_uri, allow_none=True) |
|
|
|
def sendJsonRPC(self, data): |
|
r = requests.post(self.server_uri, data=data) |
|
return r.text |
|
|
|
def getRPCBody(self, method, params=None): |
|
'''Create RPC body''' |
|
uid = '1' |
|
params = params if params else [] |
|
if self.secret is not None and self.secret!='': |
|
params.insert(0, 'token:{}'.format(self.secret)) |
|
j = json.dumps([{ |
|
'jsonrpc': '2.0', |
|
'id': uid, |
|
'method': method, |
|
'params': params, |
|
}]) |
|
return j |
|
|
|
def addUri(self, uris, options=None, position=None): |
|
''' |
|
This method adds new HTTP(S)/FTP/BitTorrent Magnet URI. |
|
uris: list, list of URIs |
|
options: dict, additional options |
|
position: integer, position in download queue |
|
return: This method returns GID of registered download. |
|
''' |
|
params = [[uris]] |
|
if options: |
|
params.append(options) |
|
#params.append(position) |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.addUri', params)) |
|
|
|
def addTorrent(self, torrent, uris=None, options=None, position=None): |
|
''' |
|
This method adds BitTorrent download by uploading ".torrent" file. |
|
torrent: string, torrent file path |
|
uris: list, list of webseed URIs |
|
options: dict, additional options |
|
position: integer, position in download queue |
|
return: This method returns GID of registered download. |
|
''' |
|
return self.server.aria2.addTorrent(xmlrpclib.Binary(open(torrent, 'rb').read()), uris, options, position) |
|
|
|
def addMetalink(self, metalink, options=None, position=None): |
|
''' |
|
This method adds Metalink download by uploading ".metalink" file. |
|
metalink: string, metalink file path |
|
options: dict, additional options |
|
position: integer, position in download queue |
|
return: This method returns list of GID of registered download. |
|
''' |
|
return self.server.aria2.addMetalink(xmlrpclib.Binary(open(metalink, 'rb').read()), options, position) |
|
|
|
def remove(self, gid): |
|
''' |
|
This method removes the download denoted by gid. |
|
gid: string, GID. |
|
return: This method returns GID of removed download. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.remove', params)) |
|
|
|
|
|
def forceRemove(self, gid): |
|
''' |
|
This method removes the download denoted by gid. |
|
gid: string, GID. |
|
return: This method returns GID of removed download. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.forceRemove', params)) |
|
|
|
def pause(self, gid): |
|
''' |
|
This method pauses the download denoted by gid. |
|
gid: string, GID. |
|
return: This method returns GID of paused download. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.pause', params)) |
|
|
|
def pauseAll(self): |
|
''' |
|
This method is equal to calling aria2.pause() for every active/waiting download. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.pauseAll')) |
|
|
|
def forcePause(self, gid): |
|
''' |
|
This method pauses the download denoted by gid. |
|
gid: string, GID. |
|
return: This method returns GID of paused download. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.forcePause', params)) |
|
|
|
def forcePauseAll(self): |
|
''' |
|
This method is equal to calling aria2.forcePause() for every active/waiting download. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.forcePauseAll')) |
|
|
|
def unpause(self, gid): |
|
''' |
|
This method changes the status of the download denoted by gid from paused to waiting. |
|
gid: string, GID. |
|
return: This method returns GID of unpaused download. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.unpause', params)) |
|
|
|
def unpauseAll(self): |
|
''' |
|
This method is equal to calling aria2.unpause() for every active/waiting download. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.unpauseAll')) |
|
|
|
def tellStatus(self, gid, keys=None): |
|
''' |
|
This method returns download progress of the download denoted by gid. |
|
gid: string, GID. |
|
keys: list, keys for method response. |
|
return: The method response is of type dict and it contains following keys. |
|
''' |
|
params = [gid] |
|
if keys: |
|
params.append(keys) |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.tellStatus', params)) |
|
|
|
|
|
def getUris(self, gid): |
|
''' |
|
This method returns URIs used in the download denoted by gid. |
|
gid: string, GID. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getUris', params)) |
|
|
|
def getFiles(self, gid): |
|
''' |
|
This method returns file list of the download denoted by gid. |
|
gid: string, GID. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getFiles', params)) |
|
|
|
|
|
def getPeers(self, gid): |
|
''' |
|
This method returns peer list of the download denoted by gid. |
|
gid: string, GID. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
return self.server.aria2.getPeers(gid) |
|
|
|
def getServers(self, gid): |
|
''' |
|
This method returns currently connected HTTP(S)/FTP servers of the download denoted by gid. |
|
gid: string, GID. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
return self.server.aria2.getServers(gid) |
|
|
|
def tellActive(self, keys=None): |
|
''' |
|
This method returns the list of active downloads. |
|
keys: keys for method response. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
return self.server.aria2.tellActive(keys) |
|
|
|
def tellWaiting(self, offset, num, keys=None): |
|
''' |
|
This method returns the list of waiting download, including paused downloads. |
|
offset: integer, the offset from the download waiting at the front. |
|
num: integer, the number of downloads to be returned. |
|
keys: keys for method response. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
return self.server.aria2.tellWaiting(offset, num, keys) |
|
|
|
def tellStopped(self, offset, num, keys=None): |
|
''' |
|
This method returns the list of stopped download. |
|
offset: integer, the offset from the download waiting at the front. |
|
num: integer, the number of downloads to be returned. |
|
keys: keys for method response. |
|
return: The method response is of type list and its element is of type dict and it contains following keys. |
|
''' |
|
return self.server.aria2.tellStopped(offset, num, keys) |
|
|
|
def changePosition(self, gid, pos, how): |
|
''' |
|
This method changes the position of the download denoted by gid. |
|
gid: string, GID. |
|
pos: integer, the position relative which to be changed. |
|
how: string. |
|
POS_SET, it moves the download to a position relative to the beginning of the queue. |
|
POS_CUR, it moves the download to a position relative to the current position. |
|
POS_END, it moves the download to a position relative to the end of the queue. |
|
return: The response is of type integer and it is the destination position. |
|
''' |
|
return self.server.aria2.changePosition(gid, pos, how) |
|
|
|
def changeUri(self, gid, fileIndex, delUris, addUris, position=None): |
|
''' |
|
This method removes URIs in delUris from and appends URIs in addUris to download denoted by gid. |
|
gid: string, GID. |
|
fileIndex: integer, file to affect (1-based) |
|
delUris: list, URIs to be removed |
|
addUris: list, URIs to be added |
|
position: integer, where URIs are inserted, after URIs have been removed |
|
return: This method returns a list which contains 2 integers. The first integer is the number of URIs deleted. The second integer is the number of URIs added. |
|
''' |
|
return self.server.aria2.changeUri(gid, fileIndex, delUris, addUris, position) |
|
|
|
def getOption(self, gid): |
|
''' |
|
This method returns options of the download denoted by gid. |
|
gid: string, GID. |
|
return: The response is of type dict. |
|
''' |
|
params = [gid] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getOption', params)) |
|
|
|
def changeOption(self, gid, options): |
|
''' |
|
This method changes options of the download denoted by gid dynamically. |
|
gid: string, GID. |
|
options: dict, the options. |
|
return: This method returns OK for success. |
|
''' |
|
params = [gid,options] |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.changeOption', params)) |
|
# return self.server.aria2.changeOption(gid, options) |
|
|
|
def getGlobalOption(self): |
|
''' |
|
This method returns global options. |
|
return: The method response is of type dict. |
|
''' |
|
return self.server.aria2.getGlobalOption() |
|
|
|
def changeGlobalOption(self, options): |
|
''' |
|
This method changes global options dynamically. |
|
options: dict, the options. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.changeGlobalOption', options)) |
|
|
|
|
|
def getGlobalStat(self): |
|
''' |
|
This method returns global statistics such as overall download and upload speed. |
|
return: The method response is of type struct and contains following keys. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getGlobalStat')) |
|
|
|
|
|
def purgeDownloadResult(self): |
|
''' |
|
This method purges completed/error/removed downloads to free memory. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.purgeDownloadResult')) |
|
|
|
|
|
def removeDownloadResult(self, gid): |
|
''' |
|
This method removes completed/error/removed download denoted by gid from memory. |
|
return: This method returns OK for success. |
|
''' |
|
return self.server.aria2.removeDownloadResult(gid) |
|
|
|
def getVersion(self): |
|
''' |
|
This method returns version of the program and the list of enabled features. |
|
return: The method response is of type dict and contains following keys. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getSessionInfo')) |
|
|
|
|
|
def getSessionInfo(self): |
|
''' |
|
This method returns session information. |
|
return: The response is of type dict. |
|
''' |
|
return self.sendJsonRPC(data=self.getRPCBody('aria2.getSessionInfo')) |
|
|
|
|
|
def shutdown(self): |
|
''' |
|
This method shutdowns aria2. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(self.server_uri, data=self.getRPCBody('aria2.shutdown')) |
|
|
|
|
|
def forceShutdown(self): |
|
''' |
|
This method shutdowns aria2. |
|
return: This method returns OK for success. |
|
''' |
|
return self.sendJsonRPC(self.server_uri, data=self.getRPCBody('aria2.forceShutdown')) |
|
|
|
|
|
def isAria2Installed(): |
|
for cmdpath in os.environ['PATH'].split(':'): |
|
if os.path.isdir(cmdpath) and 'aria2c' in os.listdir(cmdpath): |
|
return True |
|
return False |
|
|
|
|
|
def isAria2rpcRunning(): |
|
pgrep_process = subprocess.Popen( |
|
'pgrep -l aria2', shell=True, stdout=subprocess.PIPE) |
|
if pgrep_process.stdout.readline() == b'': |
|
return False |
|
else: |
|
return True |
|
|
|
if __name__=='__main__': |
|
p = PyAria2() |
|
|
|
|
|
|