qbittorent
parent
6190cef548
commit
2ade2f21ec
2
Core.py
2
Core.py
|
@ -1654,7 +1654,7 @@ class Core:
|
|||
dirid = 0
|
||||
if dirid == -1: return
|
||||
dirname = clean[dirid]
|
||||
if self.__settings__.getSetting("torrent") in ['1','2']:
|
||||
if self.__settings__.getSetting("torrent") in ['1','2','4']:
|
||||
default = self.__settings__.getSetting("torrent_dir")
|
||||
keyboard = xbmc.Keyboard(default, self.localize('Save to path') + ':')
|
||||
keyboard.doModal()
|
||||
|
|
|
@ -172,6 +172,7 @@ class SearcherABC:
|
|||
('<', '<'),
|
||||
('>', '>'),
|
||||
('"', '"'),
|
||||
('"', '"'),
|
||||
("'", '''),
|
||||
("&", '&'),
|
||||
("'", '''),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.torrenter" name="Torrenter" version="2.4.2a" provider-name="vadim.skorba, DiMartino">
|
||||
<addon id="plugin.video.torrenter" name="Torrenter" version="2.4.3" provider-name="vadim.skorba, DiMartino">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.1.0"/>
|
||||
<import addon="script.module.libtorrent"/>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
English changelog at http://bit.ly/1MfSVUP
|
||||
|
||||
[B]Version 2.4.3[/B]
|
||||
[+] Добавлена поддержка торрент-клиента qBittorent
|
||||
|
||||
[B]Version 2.4.2[/B]
|
||||
[+] Добавлена функция История Просмотров
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<setting id="torrent_dir" type="text" label="50304"/>
|
||||
<setting id="torrent_replacement" type="folder" label="30426"/>
|
||||
<setting type="sep"/>
|
||||
<setting id="torrent" type="enum" label="50311" values="µTorrent WebUI|Transmission|Vuze (XML over HTTP plugin)|Deluge WebUI"
|
||||
<setting id="torrent" type="enum" label="50311" values="µTorrent WebUI|Transmission|Vuze (XML over HTTP plugin)|Deluge|qBittorent"
|
||||
default="0"/>
|
||||
<setting id="torrent_utorrent_host" type="ipaddress" label="50312" visible="eq(-1,0)" default="127.0.0.1"/>
|
||||
<setting id="torrent_utorrent_port" type="number" label="50313" visible="eq(-2,0)" default="8080"/>
|
||||
|
@ -57,5 +57,9 @@
|
|||
<setting id="torrent_deluge_path" type="text" label="50317" visible="eq(-15,3)" default="/"/>
|
||||
<setting id="torrent_deluge_port" type="number" label="50313" visible="eq(-16,3)" default="8112"/>
|
||||
<setting id="torrent_deluge_password" type="text" label="50316" visible="eq(-17,3)" default="deluge" option="hidden"/>
|
||||
<setting id="torrent_qbittorrent_host" type="ipaddress" label="50312" visible="eq(-18,4)" default="127.0.0.1"/>
|
||||
<setting id="torrent_qbittorrent_port" type="number" label="50313" visible="eq(-19,4)" default="8080"/>
|
||||
<setting id="torrent_qbittorrent_login" type="text" label="50315" visible="eq(-20,4)" default="admin"/>
|
||||
<setting id="torrent_qbittorrent_password" type="text" label="50316" visible="eq(-21,4)" default="admin" option="hidden"/>
|
||||
</category>
|
||||
</settings>
|
||||
|
|
|
@ -13,6 +13,7 @@ import json
|
|||
import itertools
|
||||
from StringIO import StringIO
|
||||
import gzip
|
||||
from functions import log
|
||||
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
|
@ -455,9 +456,6 @@ class UTorrent:
|
|||
for hash, action, ind in menu:
|
||||
self.setprio_simple(hash, action, ind)
|
||||
|
||||
def delete(self, id):
|
||||
pass
|
||||
|
||||
def action(self, uri, upload=None):
|
||||
cookie, token = self.get_token()
|
||||
if not cookie:
|
||||
|
@ -705,9 +703,6 @@ class Transmission:
|
|||
return None
|
||||
return True
|
||||
|
||||
def delete(self, id):
|
||||
pass
|
||||
|
||||
def setprio(self, id, ind):
|
||||
obj = self.action({"method": "torrent-get", "arguments": {"fields": ["id", "fileStats", "files"],
|
||||
"ids": [int(id)]}})['arguments']['torrents'][0]
|
||||
|
@ -844,6 +839,238 @@ class Transmission:
|
|||
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()
|
||||
|
||||
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']
|
||||
}
|
||||
#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('/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):
|
||||
cookie = self.get_auth()
|
||||
if not cookie:
|
||||
return None
|
||||
|
||||
req = HTTPRequest(self.url + uri, headers={'Cookie': 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):
|
||||
cookie = self.get_auth()
|
||||
if not cookie:
|
||||
return None
|
||||
|
||||
response = self.http.fetch(self.url + uri, headers={'Cookie': cookie}, method='POST', params=params, gzip=True)
|
||||
|
||||
if response.error:
|
||||
return None
|
||||
|
||||
if response.code == 200:
|
||||
return True
|
||||
|
||||
return response
|
||||
|
||||
def action_simple(self, action, id):
|
||||
actions = {'start': '/command/resume',
|
||||
'stop': '/command/pause',
|
||||
'remove': '/command/delete',
|
||||
'removedata': '/command/deletePerm'}
|
||||
obj = self.action_post(actions[action], {'hash':id})
|
||||
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
|
||||
|
@ -970,9 +1197,6 @@ class Deluge:
|
|||
return None
|
||||
return True
|
||||
|
||||
def delete(self, id):
|
||||
pass
|
||||
|
||||
def setprio(self, id, ind):
|
||||
i = -1
|
||||
prios = self.get_prio(id)
|
||||
|
@ -1170,9 +1394,6 @@ class Vuze:
|
|||
obj = self.interface.getDownloadManager().addDownload(torrent)
|
||||
return True if obj else None
|
||||
|
||||
def delete(self, id):
|
||||
pass
|
||||
|
||||
def setprio(self, id, ind):
|
||||
self.setprioobj = self.downloads[int(id)].getDiskManagerFileInfo()
|
||||
# -1 low, 0 normal, 1 high
|
||||
|
@ -1259,6 +1480,9 @@ class Download():
|
|||
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())
|
||||
|
@ -1304,7 +1528,15 @@ class Download():
|
|||
'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):
|
||||
|
@ -1322,9 +1554,6 @@ class Download():
|
|||
def listfiles(self, id):
|
||||
return self.client.listfiles(id)
|
||||
|
||||
def delete(self, id):
|
||||
return self.client.delete(id)
|
||||
|
||||
def setprio(self, id, ind):
|
||||
return self.client.setprio(id, ind)
|
||||
|
||||
|
|
Loading…
Reference in New Issue