plugin.video.torrenter/resources/utorrent/net.py

1565 lines
52 KiB
Python

# -*- coding: utf-8 -*-
import os
import sys
import time
import re
import urllib
import urllib2
import cookielib
import base64
import mimetools
import json
import itertools
from StringIO import StringIO
import gzip
from functions import log, dump
import xbmc
import xbmcgui
import xbmcvfs
os.sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__))))
import dopal.main
__plugin__ = sys.modules["__main__"].__plugin__
__settings__ = sys.modules["__main__"].__settings__
ROOT = sys.modules["__main__"].__root__ # .decode('utf-8').encode(sys.getfilesystemencoding())
userStorageDirectory = __settings__.getSetting("storage")
USERAGENT = "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0"
URL = 'http://torrenter.host.org'
torrentFilesDirectory = 'torrents'
__addonpath__ = __settings__.getAddonInfo('path')
icon = __addonpath__ + '/icon.png'
RE = {
'content-disposition': re.compile('attachment;\sfilename="*([^"\s]+)"|\s')
}
# ################################
#
# HTTP
#
# ################################
class HTTP:
def __init__(self):
self._dirname = xbmc.translatePath('special://temp') # .decode('utf-8').encode('cp1251')
for subdir in ('xbmcup', sys.argv[0].replace('plugin://', '').replace('/', '')):
self._dirname = os.path.join(self._dirname, subdir)
if not xbmcvfs.exists(self._dirname):
xbmcvfs.mkdir(self._dirname)
def fetch(self, request, **kwargs):
self.con, self.fd, self.progress, self.cookies, self.request = None, None, None, None, request
if not isinstance(self.request, HTTPRequest):
self.request = HTTPRequest(url=self.request, **kwargs)
self.response = HTTPResponse(self.request)
# Debug('XBMCup: HTTP: request: ' + str(self.request))
try:
self._opener()
self._fetch()
except Exception, e:
xbmc.log('XBMCup: HTTP: ' + str(e), xbmc.LOGERROR)
if isinstance(e, urllib2.HTTPError):
self.response.code = e.code
self.response.error = e
else:
self.response.code = 200
if self.fd:
self.fd.close()
self.fd = None
if self.con:
self.con.close()
self.con = None
if self.progress:
self.progress.close()
self.progress = None
self.response.time = time.time() - self.response.time
xbmc.log('XBMCup: HTTP: response: ' + str(self.response), xbmc.LOGDEBUG)
return self.response
def _opener(self):
build = [urllib2.HTTPHandler()]
if self.request.redirect:
build.append(urllib2.HTTPRedirectHandler())
if self.request.proxy_host and self.request.proxy_port:
build.append(urllib2.ProxyHandler(
{self.request.proxy_protocol: self.request.proxy_host + ':' + str(self.request.proxy_port)}))
if self.request.proxy_username:
proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'uri', self.request.proxy_username,
self.request.proxy_password)
build.append(proxy_auth_handler)
if self.request.cookies:
self.request.cookies = os.path.join(self._dirname, self.request.cookies)
self.cookies = cookielib.MozillaCookieJar()
if os.path.isfile(self.request.cookies):
self.cookies.load(self.request.cookies)
build.append(urllib2.HTTPCookieProcessor(self.cookies))
urllib2.install_opener(urllib2.build_opener(*build))
def _fetch(self):
params = {} if self.request.params is None else self.request.params
if self.request.upload:
boundary, upload = self._upload(self.request.upload, params)
req = urllib2.Request(self.request.url)
req.add_data(upload)
else:
if self.request.method == 'POST':
if isinstance(params, dict) or isinstance(params, list):
params = urllib.urlencode(params)
req = urllib2.Request(self.request.url, params)
else:
req = urllib2.Request(self.request.url)
for key, value in self.request.headers.iteritems():
req.add_header(key, value)
if self.request.upload:
req.add_header('Content-type', 'multipart/form-data; boundary=%s' % boundary)
req.add_header('Content-length', len(upload))
if self.request.auth_username and self.request.auth_password:
req.add_header('Authorization', 'Basic %s' % base64.encodestring(
':'.join([self.request.auth_username, self.request.auth_password])).strip())
# self.con = urllib2.urlopen(req, timeout=self.request.timeout)
self.con = urllib2.urlopen(req)
self.response.headers = self._headers(self.con.info())
if self.request.download:
self._download()
else:
if not self.response.headers.get('content-encoding') == 'gzip':
self.response.body = self.con.read()
else:
buf = StringIO(self.con.read())
f = gzip.GzipFile(fileobj=buf)
self.response.body = f.read()
if self.request.cookies:
self.cookies.save(self.request.cookies)
def _download(self):
fd = open(self.request.download, 'wb')
if self.request.progress:
self.progress = xbmcgui.DialogProgress()
self.progress.create(u'Download')
bs = 1024 * 8
size = -1
read = 0
name = None
if self.request.progress:
if 'content-length' in self.response.headers:
size = int(self.response.headers['content-length'])
if 'content-disposition' in self.response.headers:
r = RE['content-disposition'].search(self.response.headers['content-disposition'])
if r:
name = urllib.unquote(r.group(1))
while 1:
buf = self.con.read(bs)
if buf == '':
break
read += len(buf)
fd.write(buf)
if self.request.progress:
self.progress.update(*self._progress(read, size, name))
self.response.filename = self.request.download
def _upload(self, upload, params):
res = []
boundary = mimetools.choose_boundary()
part_boundary = '--' + boundary
if params:
for name, value in params.iteritems():
res.append([part_boundary, 'Content-Disposition: form-data; name="%s"' % name, '', value])
if isinstance(upload, dict):
upload = [upload]
for obj in upload:
name = obj.get('name')
filename = obj.get('filename', 'default')
content_type = obj.get('content-type')
try:
body = obj['body'].read()
except AttributeError:
body = obj['body']
if content_type:
res.append([part_boundary,
'Content-Disposition: file; name="%s"; filename="%s"' % (name, urllib.quote(filename)),
'Content-Type: %s' % content_type, '', body])
else:
res.append([part_boundary,
'Content-Disposition: file; name="%s"; filename="%s"' % (name, urllib.quote(filename)), '',
body])
result = list(itertools.chain(*res))
result.append('--' + boundary + '--')
result.append('')
return boundary, '\r\n'.join(result)
def _headers(self, raw):
headers = {}
for line in raw.headers:
pair = line.split(':', 1)
if len(pair) == 2:
tag = pair[0].lower().strip()
value = pair[1].strip()
if tag and value:
headers[tag] = value
return headers
def _progress(self, read, size, name):
res = []
if size < 0:
res.append(1)
else:
res.append(int(float(read) / (float(size) / 100.0)))
if name:
res.append(u'File: ' + name)
if size != -1:
res.append(u'Size: ' + self._human(size))
res.append(u'Load: ' + self._human(read))
return res
def _human(self, size):
human = None
for h, f in (('KB', 1024), ('MB', 1024 * 1024), ('GB', 1024 * 1024 * 1024), ('TB', 1024 * 1024 * 1024 * 1024)):
if size / f > 0:
human = h
factor = f
else:
break
if human is None:
return (u'%10.1f %s' % (size, u'byte')).replace(u'.0', u'')
else:
return u'%10.2f %s' % (float(size) / float(factor), human)
class HTTPRequest:
def __init__(self, url, method='GET', headers=None, cookies=None, params=None, upload=None, download=None,
progress=False, auth_username=None, auth_password=None, proxy_protocol='http', proxy_host=None,
proxy_port=None, proxy_username=None, proxy_password='', timeout=20.0, redirect=True, gzip=False):
if headers is None:
headers = {}
self.url = url
self.method = method
self.headers = headers
self.cookies = cookies
self.params = params
self.upload = upload
self.download = download
self.progress = progress
self.auth_username = auth_username
self.auth_password = auth_password
self.proxy_protocol = proxy_protocol
self.proxy_host = proxy_host
self.proxy_port = proxy_port
self.proxy_username = proxy_username
self.proxy_password = proxy_password
self.timeout = timeout
self.redirect = redirect
self.gzip = gzip
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ','.join('%s=%r' % i for i in self.__dict__.iteritems()))
class HTTPResponse:
def __init__(self, request):
self.request = request
self.code = None
self.headers = {}
self.error = None
self.body = None
self.filename = None
self.time = time.time()
def __repr__(self):
args = ','.join('%s=%r' % i for i in self.__dict__.iteritems() if i[0] != 'body')
if self.body:
args += ',body=<data>'
else:
args += ',body=None'
return '%s(%s)' % (self.__class__.__name__, args)
class UTorrent:
def config(self, login, password, host, port, url=None):
self.login = login
self.password = password
self.url = 'http://' + host
if port:
self.url += ':' + str(port)
self.url += '/gui/'
self.http = HTTP()
self.re = {
'cookie': re.compile('GUID=([^;]+);'),
'token': re.compile("<div[^>]+id='token'[^>]*>([^<]+)</div>")
}
def listdirs(self):
obj = self.action('action=list-dirs')
if not obj:
return False
items = []
clean = []
for r in obj.get('download-dirs', []):
available = int(r['available'])
if available > 1024:
memory = '[%s GB]' % str(available / 1024)
else:
memory = '[%s MB]' % str(available)
items.append(r['path'] + ' ' + memory)
path = r['path']
if path[len(path) - 1:] != '\\': path += '\\'
clean.append(path)
return items, clean
def list(self):
obj = self.action('list=1')
if not obj:
return False
res = []
for r in obj.get('torrents', []):
res.append({
'id': r[0],
'status': self.get_status(r[1], r[4] / 10),
'name': r[2],
'size': r[3],
'progress': r[4] / 10,
'download': r[5],
'upload': r[6],
'ratio': float(r[7]) / 1000,
'upspeed': r[8],
'downspeed': r[9],
'eta': r[10],
'peer': r[12] + r[14],
'leach': r[12],
'seed': r[14],
'add': r[23],
'finish': r[24],
'dir': r[26]
})
return res
def listfiles(self, id):
obj = self.action('action=getfiles&hash=' + id)
if not obj:
return None
res = []
i = -1
for x in obj['files'][1]:
i += 1
if x[1] >= 1024 * 1024 * 1024:
size = str(x[1] / (1024 * 1024 * 1024)) + 'GB'
elif x[1] >= 1024 * 1024:
size = str(x[1] / (1024 * 1024)) + 'MB'
elif x[1] >= 1024:
size = str(x[1] / 1024) + 'KB'
else:
size = str(x[1]) + 'B'
res.append((x[0], (int(x[2] * 100 / x[1])), i, size))
return res
def dirid(self, dirname):
if __settings__.getSetting("torrent_save") == '0':
dirid = self.listdirs()[1].index(dirname)
else:
dirname = __settings__.getSetting("torrent_dir")
clean = self.listdirs()[1]
try:
dirid = clean.index(dirname)
except:
dirid = 0
return dirid
def add(self, torrent, dirname):
dirid = self.dirid(dirname)
res = self.action('action=add-file&download_dir=' + str(dirid),
{'name': 'torrent_file', 'download_dir': str(dirid),
'content-type': 'application/x-bittorrent', 'body': torrent})
return True if res else None
def add_url(self, torrent, dirname):
dirid = self.dirid(dirname)
res = self.action('action=add-url&download_dir=' + str(dirid) + '&s=' + urllib.quote(torrent))
return True if res else None
def setprio(self, id, ind):
obj = self.action('action=getfiles&hash=' + id)
if not obj or ind == None:
return None
i = -1
for x in obj['files'][1]:
i += 1
if x[3] == 2: self.setprio_simple(id, '0', i)
res = self.setprio_simple(id, '3', ind)
return True if res else None
def setprio_simple(self, id, prio, ind):
obj = self.action('action=setprio&hash=%s&p=%s&f=%s' % (id, prio, ind))
if not obj or ind == None:
return None
return True if obj else None
def setprio_simple_multi(self, menu):
for hash, action, ind in menu:
self.setprio_simple(hash, action, ind)
def action(self, uri, upload=None):
cookie, token = self.get_token()
if not cookie:
return None
req = HTTPRequest(self.url + '?' + uri + '&token=' + token, headers={'Cookie': cookie},
auth_username=self.login, auth_password=self.password)
if upload:
req.upload = upload
response = self.http.fetch(req)
if response.error:
return None
else:
try:
obj = json.loads(response.body)
except:
return None
else:
return obj
def action_simple(self, action, id):
obj = self.action('action=%s&hash=%s' % (action, id))
return True if obj else None
def get_token(self):
response = self.http.fetch(self.url + 'token.html', auth_username=self.login, auth_password=self.password)
if response.error:
return None, None
r = self.re['cookie'].search(response.headers.get('set-cookie', ''))
if r:
cookie = r.group(1).strip()
r = self.re['token'].search(response.body)
if r:
token = r.group(1).strip()
if cookie and token:
return 'GUID=' + cookie, token
return None, None
def get_status(self, status, progress):
mapping = {
'error': 'stopped',
'paused': 'stopped',
'forcepaused': 'stopped',
'stopped': 'stopped',
'notloaded': 'check_pending',
'checked': 'checking',
'queued': 'download_pending',
'downloading': 'downloading',
'forcedownloading': 'downloading',
'finished': 'seed_pending',
'queuedseed': 'seed_pending',
'seeding': 'seeding',
'forceseeding': 'seeding'
}
return mapping[self.get_status_raw(status, progress)]
def get_status_raw(self, status, progress):
"""
Return status: notloaded, error, checked,
paused, forcepaused,
queued,
downloading,
finished, forcedownloading
queuedseed, seeding, forceseeding
"""
started = bool(status & 1)
checking = bool(status & 2)
start_after_check = bool(status & 4)
checked = bool(status & 8)
error = bool(status & 16)
paused = bool(status & 32)
queued = bool(status & 64)
loaded = bool(status & 128)
if not loaded:
return 'notloaded'
if error:
return 'error'
if checking:
return 'checked'
if paused:
if queued:
return 'paused'
else:
return 'forcepaused'
if progress == 100:
if queued:
if started:
return 'seeding'
else:
return 'queuedseed'
else:
if started:
return 'forceseeding'
else:
return 'finished'
else:
if queued:
if started:
return 'downloading'
else:
return 'queued'
else:
if started:
return 'forcedownloading'
return 'stopped'
class Transmission:
def config(self, login, password, host, port, url):
self.login = login
self.password = password
self.url = 'http://' + host
if port:
self.url += ':' + str(port)
if url[0] != '/':
url = '/' + url
if url[-1] != '/':
url += '/'
self.url += url
self.http = HTTP()
self.token = '0'
def list(self):
obj = self.action({'method': 'torrent-get', 'arguments': {
'fields': ['id', 'status', 'name', 'totalSize', 'sizeWhenDone', 'leftUntilDone', 'downloadedEver',
'uploadedEver', 'uploadRatio', 'rateUpload', 'rateDownload', 'eta', 'peersConnected',
'peersFrom',
'addedDate', 'doneDate', 'downloadDir', 'fileStats', 'peersConnected', 'peersGettingFromUs',
'peersSendingToUs']}})
if obj is None:
return False
res = []
for r in obj['arguments'].get('torrents', []):
if len(r['fileStats']) > 1:
res.append({
'id': str(r['id']),
'status': self.get_status(r['status']),
'name': r['name'],
'size': r['totalSize'],
'progress': 0 if not r['sizeWhenDone'] else int(
100.0 * float(r['sizeWhenDone'] - r['leftUntilDone']) / float(r['sizeWhenDone'])),
'download': r['downloadedEver'],
'upload': r['uploadedEver'],
'upspeed': r['rateUpload'],
'downspeed': r['rateDownload'],
'ratio': float(r['uploadRatio']),
'eta': r['eta'],
'peer': r['peersConnected'],
'seed': r['peersSendingToUs'],
'leech': r['peersGettingFromUs'],
'add': r['addedDate'],
'finish': r['doneDate'],
'dir': os.path.join(r['downloadDir'], r['name'])
})
else:
res.append({
'id': str(r['id']),
'status': self.get_status(r['status']),
'name': r['name'],
'size': r['totalSize'],
'progress': 0 if not r['sizeWhenDone'] else int(
100.0 * float(r['sizeWhenDone'] - r['leftUntilDone']) / float(r['sizeWhenDone'])),
'download': r['downloadedEver'],
'upload': r['uploadedEver'],
'upspeed': r['rateUpload'],
'downspeed': r['rateDownload'],
'ratio': float(r['uploadRatio']),
'eta': r['eta'],
'peer': r['peersConnected'],
'seed': r['peersSendingToUs'],
'leech': r['peersGettingFromUs'],
'add': r['addedDate'],
'finish': r['doneDate'],
'dir': r['downloadDir']
})
return res
def listdirs(self):
obj = self.action({'method': 'session-get'})
if obj is None:
return False
res = [obj['arguments'].get('download-dir')]
# Debug('[Transmission][listdirs]: %s' % (str(res)))
return res, res
def listfiles(self, id):
obj = self.action({"method": "torrent-get", "arguments": {
"fields": ["id", "activityDate", "corruptEver", "desiredAvailable", "downloadedEver", "fileStats",
"haveUnchecked", "haveValid", "peers", "startDate", "trackerStats", "comment", "creator",
"dateCreated", "files", "hashString", "isPrivate", "pieceCount", "pieceSize"],
"ids": [int(id)]}})['arguments']['torrents'][0]
if obj is None:
return None
res = []
i = -1
lenf = len(obj['files'])
for x in obj['files']:
i += 1
if x['length'] >= 1024 * 1024 * 1024:
size = str(x['length'] / (1024 * 1024 * 1024)) + 'GB'
elif x['length'] >= 1024 * 1024:
size = str(x['length'] / (1024 * 1024)) + 'MB'
elif x['length'] >= 1024:
size = str(x['length'] / 1024) + 'KB'
else:
size = str(x['length']) + 'B'
if lenf > 1:
x['name'] = x['name'].strip('/\\').replace('\\', '/')
x['name'] = x['name'].replace(x['name'].split('/')[0] + '/', '')
res.append([x['name'], (int(x['bytesCompleted'] * 100 / x['length'])), i, size])
return res
def add(self, torrent, dirname):
if self.action({'method': 'torrent-add',
'arguments': {'download-dir': dirname, 'metainfo': base64.b64encode(torrent)}}) is None:
return None
return True
def add_url(self, torrent, dirname):
if self.action({'method': 'torrent-add', 'arguments': {'download-dir': dirname, 'filename': torrent}}) is None:
return None
return True
def setprio(self, id, ind):
obj = self.action({"method": "torrent-get", "arguments": {"fields": ["id", "fileStats", "files"],
"ids": [int(id)]}})['arguments']['torrents'][0]
if not obj or ind == None:
return None
inds = []
i = -1
for x in obj['fileStats']:
i += 1
if x['wanted'] == True and x['priority'] == 0:
inds.append(i)
if len(inds) > 1: self.action(
{"method": "torrent-set", "arguments": {"ids": [int(id)], "priority-high": inds, "files-unwanted": inds}})
res = self.setprio_simple(id, '3', ind)
# self.action_simple('start',id)
return True if res else None
def setprio_simple(self, id, prio, ind):
if ind == None:
return None
res = None
inds = [int(ind)]
if prio == '3':
res = self.action(
{"method": "torrent-set", "arguments": {"ids": [int(id)], "priority-high": inds, "files-wanted": inds}})
elif prio == '0':
res = self.action({"method": "torrent-set",
"arguments": {"ids": [int(id)], "priority-high": inds, "files-unwanted": inds}})
return True if res else None
def setprio_simple_multi(self, menu):
id = menu[0][0]
prio = menu[0][1]
res = None
inds = []
for hash, action, ind in menu:
inds.append(int(ind))
if prio == '3':
res = self.action(
{"method": "torrent-set", "arguments": {"ids": [int(id)], "priority-high": inds, "files-wanted": inds}})
elif prio == '0':
res = self.action({"method": "torrent-set",
"arguments": {"ids": [int(id)], "priority-high": inds, "files-unwanted": inds}})
return True if res else None
def action(self, request):
try:
jsobj = json.dumps(request)
except:
return None
else:
while True:
# пробуем сделать запрос
if self.login:
response = self.http.fetch(self.url + 'rpc/', method='POST', params=jsobj,
headers={'X-Transmission-Session-Id': self.token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'charset=UTF-8'}, auth_username=self.login,
auth_password=self.password)
else:
response = self.http.fetch(self.url + 'rpc/', method='POST', params=jsobj,
headers={'X-Transmission-Session-Id': self.token,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'charset=UTF-8'})
if response.error:
# требуется авторизация?
if response.code == 401:
if not self.get_auth():
return None
# требуется новый токен?
elif response.code == 409:
if not self.get_token(response.error):
return None
else:
return None
else:
try:
obj = json.loads(response.body)
except:
return None
else:
return obj
def action_simple(self, action, id):
actions = {'start': {"method": "torrent-start", "arguments": {"ids": [int(id)]}},
'stop': {"method": "torrent-stop", "arguments": {"ids": [int(id)]}},
'remove': {"method": "torrent-remove", "arguments": {"ids": [int(id)], "delete-local-data": False}},
'removedata': {"method": "torrent-remove",
"arguments": {"ids": [int(id)], "delete-local-data": True}}}
obj = self.action(actions[action])
return True if obj else None
def get_auth(self):
response = self.http.fetch(self.url, auth_username=self.login, auth_password=self.password)
if response.error:
if response.code == 409:
return self.get_token(response.error)
return False
def get_token(self, error):
token = error.headers.get('x-transmission-session-id')
if not token:
return False
self.token = token
return True
def get_status(self, code):
mapping = {
0: 'stopped',
1: 'check_pending',
2: 'checking',
3: 'download_pending',
4: 'downloading',
5: 'seed_pending',
6: 'seeding'
}
return mapping[code]
class qBittorrent:
def config(self, login, password, host, port, url):
self.login = login
self.password = password
self.url = 'http://'+host
if port:
self.url += ':' + str(port)
self.url += url
self.http = HTTP()
self.cookie = self.get_auth()
def list(self):
obj = self.action('/query/torrents')
log('[list]:'+str(obj))
if obj is None:
return False
res = []
if len(obj) > 0:
for r in obj:
add = {
'id': r['hash'],
'status': self.get_status(r['state']),
'name': r['name'],
'size': r['size'],
'progress': round(r['progress'], 4)*100,
'upspeed': r['upspeed'],
'downspeed': r['dlspeed'],
'ratio': round(r['ratio'], 2),
'eta': r['eta'],
'seed': r['num_seeds'],
'leech': r['num_leechs'],
'dir': r['save_path']
}
flist = self.action('/query/propertiesFiles/'+r['hash'])
if len(flist) > 1: add['dir'] = os.path.join(r['save_path'], r['name'])
res.append(add)
return res
def listdirs(self):
obj = self.action('/query/preferences')
log('[listdirs]:'+str(obj))
if obj is None:
return False
try:
res = [obj['save_path']]
except:
res = [None]
return res, res
def listfiles(self, id):
obj = self.action('/query/propertiesFiles/'+id)
log('[listfiles]:'+str(obj))
i = -1
if obj is None:
return None
res = []
if len(obj) == 1:
strip_path = None
else:
tlist = self.list()
for t in tlist:
if t['id']==id:
strip_path = t['name']
break
strip_path = None
for x in obj:
if x['size'] >= 1024 * 1024 * 1024:
size = str(x['size'] / (1024 * 1024 * 1024)) + 'GB'
elif x['size'] >= 1024 * 1024:
size = str(x['size'] / (1024 * 1024)) + 'MB'
elif x['size'] >= 1024:
size = str(x['size'] / 1024) + 'KB'
else:
size = str(x['size']) + 'B'
if strip_path:
path = x['name'].lstrip(strip_path).lstrip('\\')
else:
path = x['name']
if x['priority'] == 0:
path = path.replace('.unwanted\\','')
if x.get('progress'):
percent = int(x['progress'] * 100)
else:
percent = 0
i += 1
res.append([path.replace('\\','/'), percent, i, size])
return res
def get_prio(self, id):
res = []
obj = self.action('/query/propertiesFiles/'+id)
log('[get_prio]:'+str(obj))
if obj is None:
return None
for f in obj:
res.append(f['priority'])
log('[get_prio]:'+str(res))
return res
def add(self, torrent, dirname):
upload={'name': 'torrent_file', 'filename': 'and_nothing_else_matters.torrent',
'content-type': 'application/x-bittorrent', 'body': torrent}
res = self.action('/command/upload', upload=upload)
if res:
return True
def add_url(self, torrent, dirname):
upload={'name': 'urls', 'content-type': 'application/x-bittorrent', 'body': torrent}
res = self.action('/command/download', upload=upload)
if res:
return True
def setprio(self, id, ind):
obj = self.action('/query/propertiesFiles/'+id)
if not obj or ind == None:
return None
i = -1
for x in obj:
i += 1
print str(x)
if x['priority'] == 1: self.setprio_simple(id, '0', i)
res = self.setprio_simple(id, '7', ind)
return True if res else None
def setprio_simple(self, id, prio, ind):
#log(str((id, prio, ind)))
if prio == '3': prio = '7'
params = {'hash':id, 'priority':prio, 'id': ind}
obj = self.action_post('/command/setFilePrio', params)
if not obj or ind == None:
return None
return True if obj else None
def setprio_simple_multi(self, menu):
for hash, action, ind in menu:
self.setprio_simple(hash, action, ind)
def action(self, uri, upload=None):
req = HTTPRequest(self.url + uri, headers={'Cookie': self.cookie})
if upload:
req.upload = upload
response = self.http.fetch(req)
if response.error:
return None
if response.code == 200 and upload:
return True
else:
try:
obj = json.loads(response.body)
except:
return None
else:
return obj
def action_post(self, uri, params=None):
response = self.http.fetch(self.url + uri, headers={'Cookie': self.cookie},
method='POST', params=params, gzip=True,)
#dump(response)
if response.error:
return None
if response.code == 200:
return True
return response
def action_simple(self, action, id):
actions = {'start': ['/command/resume',{'hash':id,}],
'stop': ['/command/pause',{'hash':id,}],
'remove': ['/command/delete',{'hashes':id}],
'removedata': ['/command/deletePerm',{'hashes':id}]}
obj = self.action_post(actions[action][0],actions[action][1])
return True if obj else None
def get_auth(self):
params = {"username": self.login, "password": self.password}
response = self.http.fetch(self.url + '/login', method='POST', params=params, gzip=True)
if response.error:
return None
r = re.compile('SID=([^;]+);').search(response.headers.get('set-cookie', ''))
if r:
cookie = r.group(1).strip()
return 'SID=' + cookie
def get_status(self, code):
mapping = {
'error': 'stopped',
'pausedUP': 'seed_pending',
'checkingUP': 'checking',
'checkingDL': 'checking',
'pausedDL': 'stopped',
'queuedUP': 'seeding',
'queuedDL': 'stopped',
'downloading': 'downloading',
'stalledDL': 'downloading',
'uploading': 'seeding',
'stalledUP': 'seeding',
}
return mapping[code]
class Deluge:
def config(self, login, password, host, port, url):
self.login = login
self.password = password
self.url = 'http://'+host
if port:
self.url += ':' + str(port)
self.url += url
#log(str(self.url))
self.http = HTTP()
def get_info(self):
obj = self.action({"method": "web.update_ui",
"params": [[], {}], "id": 1})
return obj
def list(self):
obj = self.get_info()
if obj is None:
return False
res = []
if len(obj['result'].get('torrents')) > 0:
for k in obj['result'].get('torrents').keys():
r = obj['result']['torrents'][k]
add = {
'id': str(k),
'status': self.get_status(r['state']),
'name': r['name'],
'size': r['total_wanted'],
'progress': round(r['progress'], 2),
'download': r['total_done'],
'upload': r['total_uploaded'],
'upspeed': r['upload_payload_rate'],
'downspeed': r['download_payload_rate'],
'ratio': round(r['ratio'], 2),
'eta': r['eta'],
'peer': r['total_peers'],
'seed': r['num_seeds'],
'leech': r['num_peers'],
'add': r['time_added'],
'dir': r['save_path']
}
if len(r['files']) > 1: add['dir'] = os.path.join(r['save_path'], r['name'])
res.append(add)
return res
def listdirs(self):
obj = self.action({"method": "core.get_config", "params": [], "id": 5})
if obj is None:
return False
try:
res = [obj['result'].get('download_location')]
except:
res = [None]
return res, res
def listfiles(self, id):
obj = self.get_info()
i = 0
if obj is None:
return None
res = []
obj = obj['result']['torrents'][id]
# print str(obj)
if len(obj['files']) == 1:
strip_path = None
else:
strip_path = obj['name']
for x in obj['files']:
if x['size'] >= 1024 * 1024 * 1024:
size = str(x['size'] / (1024 * 1024 * 1024)) + 'GB'
elif x['size'] >= 1024 * 1024:
size = str(x['size'] / (1024 * 1024)) + 'MB'
elif x['size'] >= 1024:
size = str(x['size'] / 1024) + 'KB'
else:
size = str(x['size']) + 'B'
if strip_path:
path = x['path'].lstrip(strip_path).lstrip('/')
else:
path = x['path']
if x.get('progress'):
percent = int(x['progress'] * 100)
elif obj.get('file_progress') and len(obj['file_progress']) >= i:
percent = int(obj['file_progress'][i] * 100)
else:
percent = 0
i += 1
res.append([path, percent, x['index'], size])
return res
def get_prio(self, id):
obj = self.get_info()
if obj is None:
return None
res = obj['result']['torrents'][id]['file_priorities']
return res
def add(self, torrent, dirname):
torrentFile = os.path.join(self.http._dirname, 'deluge.torrent')
if self.action({'method': 'core.add_torrent_file',
'params': [torrentFile,
base64.b64encode(torrent), {"download_path": dirname}], "id": 3}) is None:
return None
return True
def add_url(self, torrent, dirname):
if re.match("^magnet\:.+$", torrent):
if self.action({'method': 'core.add_torrent_magnet', 'params': [torrent,
{'download_path': dirname}],
"id": 3}) is None:
return None
else:
if self.action({"method": "core.add_torrent_url", "params": [torrent, {'download_path': dirname}],
"id": 3}) is None:
return None
return True
def setprio(self, id, ind):
i = -1
prios = self.get_prio(id)
for p in prios:
i = i + 1
if p == 1:
prios.pop(i)
prios.insert(i, 0)
prios.pop(int(ind))
prios.insert(int(ind), 7)
if self.action({"method": "core.set_torrent_file_priorities", "params": [id, prios], "id": 6}) is None:
return None
return True
def setprio_simple(self, id, prio, ind):
prios = self.get_prio(id)
if ind != None:
prios.pop(int(ind))
if prio == '3':
prios.insert(int(ind), 7)
elif prio == '0':
prios.insert(int(ind), 0)
if self.action({"method": "core.set_torrent_file_priorities", "params": [id, prios], "id": 6}) is None:
return None
return True
def setprio_simple_multi(self, menu):
id = menu[0][0]
prios = self.get_prio(id)
for hash, action, ind in menu:
prios.pop(int(ind))
if action == '3':
prios.insert(int(ind), 7)
elif action == '0':
prios.insert(int(ind), 0)
if self.action({"method": "core.set_torrent_file_priorities", "params": [id, prios], "id": 6}) is None:
return None
def action(self, request):
cookie = self.get_auth()
if not cookie:
return None
try:
jsobj = json.dumps(request)
except:
return None
else:
response = self.http.fetch(self.url + '/json', method='POST', params=jsobj,
headers={'X-Requested-With': 'XMLHttpRequest', 'Cookie': cookie,
'Content-Type': 'application/json; charset=UTF-8'})
if response.error:
return None
else:
try:
obj = json.loads(response.body)
except:
return None
else:
return obj
def action_simple(self, action, id):
actions = {'start': {"method": "core.resume_torrent", "params": [[id]], "id": 4},
'stop': {"method": "core.pause_torrent", "params": [[id]], "id": 4},
'remove': {"method": "core.remove_torrent", "params": [id, False], "id": 4},
'removedata': {"method": "core.remove_torrent", "params": [id, True], "id": 4}}
obj = self.action(actions[action])
return True if obj else None
def get_auth(self):
params = json.dumps({"method": "auth.login", "params": [self.password], "id": 0})
response = self.http.fetch(self.url + '/json', method='POST', params=params, gzip=True,
headers={'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json; charset=UTF-8'})
if response.error:
return None
auth = json.loads(response.body)
if auth["result"] == False:
return False
else:
r = re.compile('_session_id=([^;]+);').search(response.headers.get('set-cookie', ''))
if r:
cookie = r.group(1).strip()
return '_session_id=' + cookie
def get_status(self, code):
mapping = {
'Queued': 'stopped',
'Error': 'stopped',
'Checking': 'checking',
'Paused': 'seed_pending',
'Downloading': 'downloading',
'Active': 'seed_pending',
'Seeding': 'seeding'
}
return mapping[code]
class Vuze:
def config(self, login, password, host, port, url):
self.login = login
self.password = password
self.connection = dopal.main.make_connection(host=host, port=port, user=login, password=password)
try:
self.interface = self.connection.getPluginInterface()
self.downloads = self.interface.getDownloadManager().getDownloads()
except:
self.downloads = False
def list(self):
if self.downloads == False:
return self.downloads
i = -1
res = []
for r in self.downloads:
i += 1
res.append({
'id': str(i),
'status': self.get_status(int(getattr(r, 'state'))),
'name': getattr(getattr(r, 'torrent'), 'name'),
'size': getattr(getattr(r, 'torrent'), 'size'),
'progress': round(
float(long(r.stats.downloaded) + 1 / (long(r.stats.downloaded) + long(r.stats.remaining) + 1)),
4) * 100,
'download': float(getattr(getattr(r, 'stats'), 'downloaded')),
'upload': getattr(getattr(r, 'stats'), 'uploaded'),
# 'upspeed': r['rateUpload'],
# 'downspeed': r['rateDownload'],
'ratio': float(r.stats.share_ratio) / 1000,
'eta': getattr(getattr(r, 'stats'), 'eta'),
'peer': getattr(getattr(r, 'scrape_result'), 'non_seed_count') + getattr(getattr(r, 'scrape_result'),
'seed_count'),
'seed': getattr(getattr(r, 'scrape_result'), 'seed_count'),
'leech': getattr(getattr(r, 'scrape_result'), 'non_seed_count'),
'add': getattr(r, 'creation_time'),
'finish': getattr(r, 'creation_time') + getattr(getattr(r, 'stats'), 'seconds_downloading'),
'dir': getattr(r, 'save_path')
})
return res
def listdirs(self):
res = []
return res, res
def listfiles(self, id):
obj = self.downloads[int(id)].getDiskManagerFileInfo()
if obj is None:
return None
res = []
i = -1
for x in obj:
i += 1
if long(x.length) >= 1024 * 1024 * 1024:
size = str(long(x.length) / (1024 * 1024 * 1024)) + 'GB'
elif long(x.length) >= 1024 * 1024:
size = str(long(x.length) / (1024 * 1024)) + 'MB'
elif x.length >= 1024:
size = str(long(x.length) / 1024) + 'KB'
else:
size = str(long(x.length)) + 'B'
if '\\' in x.file:
title = x.file.split('\\')[-1]
elif '/' in x.file:
title = x.file.split('/')[-1]
else:
title = x.file
res.append([title, (long(x.downloaded * 100 / long(x.length))), i, size])
return res
def add(self, torrent, dirname):
torrent = self.interface.getTorrentManager().createFromBEncodedData(torrent)
obj = self.interface.getDownloadManager().addDownload(torrent)
return True if obj else None
def add_url(self, torrent, dirname):
obj = self.interface.getDownloadManager().addDownload(torrent)
return True if obj else None
def setprio(self, id, ind):
self.setprioobj = self.downloads[int(id)].getDiskManagerFileInfo()
# -1 low, 0 normal, 1 high
if not self.setprioobj or ind == None:
return None
i = -1
for x in self.setprioobj:
i += 1
if not x.isPriority(): self.setprio_simple_vuze(id, i, skip=True, prio=-1)
res = self.setprio_simple_vuze(id, ind, skip=False, prio=1)
return True if res else None
def setprio_simple(self, id, prio, ind):
if ind == None:
return None
res = None
if prio == '0':
res = self.setprio_simple_vuze(id, ind, skip=True, prio=-1)
elif prio == '3':
res = self.setprio_simple_vuze(id, ind, skip=False, prio=1)
def setprio_simple_vuze(self, id, ind, skip=None, prio=None):
obj = None
self.setprioobj = self.downloads[int(id)].getDiskManagerFileInfo()
if prio != None:
obj = self.setprioobj[int(ind)].setNumericPriority(prio)
if skip != None:
obj = self.setprioobj[int(ind)].setSkipped(skip)
if not obj or ind == None:
return None
time.sleep(0.1)
return True if obj else None
def setprio_simple_multi(self, menu):
for hash, action, ind in menu:
self.setprio_simple(hash, action, ind)
def action_simple(self, action, id):
torrent = self.downloads[int(id)]
obj = None
if action == 'start':
obj = torrent.restart()
if action == 'stop':
obj = torrent.stopDownload()
if action == 'remove':
obj = torrent.remove()
if action == 'removedata':
obj = torrent.remove(True, True)
return True if obj else None
def get_status(self, status):
mapping = ['stopped', 'download_pending', 'download_pending', 'download_pending', 'downloading', 'seeding',
'seed_pending', 'stopped', 'stopped', 'download_pending']
return mapping[status]
class Download():
def __init__(self):
self.handle()
def handle(self):
config = self.get_torrent_client()
if self.client == 'utorrent':
self.client = UTorrent()
elif self.client == 'transmission':
self.client = Transmission()
elif self.client == 'vuze':
self.client = Vuze()
elif self.client == 'deluge':
self.client = Deluge()
elif self.client == 'qbittorrent':
self.client = qBittorrent()
self.client.config(host=config['host'], port=config['port'], login=config['login'], password=config['password'],
url=config['url'])
# print(self.client.list())
return True
def get_torrent_client(self):
self.setting = __settings__
client = self.setting.getSetting("torrent")
config = {}
if client == '0':
self.client = 'utorrent'
config = {
'host': self.setting.getSetting("torrent_utorrent_host"),
'port': self.setting.getSetting("torrent_utorrent_port"),
'url': '',
'login': self.setting.getSetting("torrent_utorrent_login"),
'password': self.setting.getSetting("torrent_utorrent_password")
}
elif client == '1':
self.client = 'transmission'
config = {
'host': self.setting.getSetting("torrent_transmission_host"),
'port': self.setting.getSetting("torrent_transmission_port"),
'url': self.setting.getSetting("torrent_transmission_url"),
'login': self.setting.getSetting("torrent_transmission_login"),
'password': self.setting.getSetting("torrent_transmission_password")
}
elif client == '2':
self.client = 'vuze'
config = {
'host': self.setting.getSetting("torrent_vuze_host"),
'port': self.setting.getSetting("torrent_vuze_port"),
'url': '',
'login': self.setting.getSetting("torrent_vuze_login"),
'password': self.setting.getSetting("torrent_vuze_password")
}
elif client == '3':
self.client = 'deluge'
config = {
'host': self.setting.getSetting("torrent_deluge_host"),
'port': self.setting.getSetting("torrent_deluge_port"),
'url': self.setting.getSetting("torrent_deluge_path"),
'login': '',
'password': self.setting.getSetting("torrent_deluge_password")
}
elif client == '4':
self.client = 'qbittorrent'
config = {
'host': self.setting.getSetting("torrent_qbittorrent_host"),
'port': self.setting.getSetting("torrent_qbittorrent_port"),
'url': '',
'login': self.setting.getSetting("torrent_qbittorrent_login"),
'password': self.setting.getSetting("torrent_qbittorrent_password")
}
return config
def add(self, torrent, dirname):
return self.client.add(torrent, dirname)
def add_url(self, torrent, dirname):
return self.client.add_url(torrent, dirname)
def list(self):
return self.client.list()
def listdirs(self):
return self.client.listdirs()
def listfiles(self, id):
return self.client.listfiles(id)
def setprio(self, id, ind):
return self.client.setprio(id, ind)
def setprio_simple(self, id, prio, ind):
# Debug('[setprio_simple] '+str((id, prio, ind)))
return self.client.setprio_simple(id, prio, ind)
def setprio_simple_multi(self, prio_list):
return self.client.setprio_simple_multi(prio_list)
def action_simple(self, action, id):
return self.client.action_simple(action, id)