qbittorent
parent
6190cef548
commit
2ade2f21ec
2
Core.py
2
Core.py
|
@ -1654,7 +1654,7 @@ class Core:
|
||||||
dirid = 0
|
dirid = 0
|
||||||
if dirid == -1: return
|
if dirid == -1: return
|
||||||
dirname = clean[dirid]
|
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")
|
default = self.__settings__.getSetting("torrent_dir")
|
||||||
keyboard = xbmc.Keyboard(default, self.localize('Save to path') + ':')
|
keyboard = xbmc.Keyboard(default, self.localize('Save to path') + ':')
|
||||||
keyboard.doModal()
|
keyboard.doModal()
|
||||||
|
|
|
@ -172,6 +172,7 @@ class SearcherABC:
|
||||||
('<', '<'),
|
('<', '<'),
|
||||||
('>', '>'),
|
('>', '>'),
|
||||||
('"', '"'),
|
('"', '"'),
|
||||||
|
('"', '"'),
|
||||||
("'", '''),
|
("'", '''),
|
||||||
("&", '&'),
|
("&", '&'),
|
||||||
("'", '''),
|
("'", '''),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?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>
|
<requires>
|
||||||
<import addon="xbmc.python" version="2.1.0"/>
|
<import addon="xbmc.python" version="2.1.0"/>
|
||||||
<import addon="script.module.libtorrent"/>
|
<import addon="script.module.libtorrent"/>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
English changelog at http://bit.ly/1MfSVUP
|
English changelog at http://bit.ly/1MfSVUP
|
||||||
|
|
||||||
|
[B]Version 2.4.3[/B]
|
||||||
|
[+] Добавлена поддержка торрент-клиента qBittorent
|
||||||
|
|
||||||
[B]Version 2.4.2[/B]
|
[B]Version 2.4.2[/B]
|
||||||
[+] Добавлена функция История Просмотров
|
[+] Добавлена функция История Просмотров
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<setting id="torrent_dir" type="text" label="50304"/>
|
<setting id="torrent_dir" type="text" label="50304"/>
|
||||||
<setting id="torrent_replacement" type="folder" label="30426"/>
|
<setting id="torrent_replacement" type="folder" label="30426"/>
|
||||||
<setting type="sep"/>
|
<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"/>
|
default="0"/>
|
||||||
<setting id="torrent_utorrent_host" type="ipaddress" label="50312" visible="eq(-1,0)" default="127.0.0.1"/>
|
<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"/>
|
<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_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_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_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>
|
</category>
|
||||||
</settings>
|
</settings>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import json
|
||||||
import itertools
|
import itertools
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import gzip
|
import gzip
|
||||||
|
from functions import log
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
@ -455,9 +456,6 @@ class UTorrent:
|
||||||
for hash, action, ind in menu:
|
for hash, action, ind in menu:
|
||||||
self.setprio_simple(hash, action, ind)
|
self.setprio_simple(hash, action, ind)
|
||||||
|
|
||||||
def delete(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def action(self, uri, upload=None):
|
def action(self, uri, upload=None):
|
||||||
cookie, token = self.get_token()
|
cookie, token = self.get_token()
|
||||||
if not cookie:
|
if not cookie:
|
||||||
|
@ -705,9 +703,6 @@ class Transmission:
|
||||||
return None
|
return None
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def delete(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setprio(self, id, ind):
|
def setprio(self, id, ind):
|
||||||
obj = self.action({"method": "torrent-get", "arguments": {"fields": ["id", "fileStats", "files"],
|
obj = self.action({"method": "torrent-get", "arguments": {"fields": ["id", "fileStats", "files"],
|
||||||
"ids": [int(id)]}})['arguments']['torrents'][0]
|
"ids": [int(id)]}})['arguments']['torrents'][0]
|
||||||
|
@ -844,6 +839,238 @@ class Transmission:
|
||||||
return mapping[code]
|
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:
|
class Deluge:
|
||||||
def config(self, login, password, host, port, url):
|
def config(self, login, password, host, port, url):
|
||||||
self.login = login
|
self.login = login
|
||||||
|
@ -970,9 +1197,6 @@ class Deluge:
|
||||||
return None
|
return None
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def delete(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setprio(self, id, ind):
|
def setprio(self, id, ind):
|
||||||
i = -1
|
i = -1
|
||||||
prios = self.get_prio(id)
|
prios = self.get_prio(id)
|
||||||
|
@ -1170,9 +1394,6 @@ class Vuze:
|
||||||
obj = self.interface.getDownloadManager().addDownload(torrent)
|
obj = self.interface.getDownloadManager().addDownload(torrent)
|
||||||
return True if obj else None
|
return True if obj else None
|
||||||
|
|
||||||
def delete(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setprio(self, id, ind):
|
def setprio(self, id, ind):
|
||||||
self.setprioobj = self.downloads[int(id)].getDiskManagerFileInfo()
|
self.setprioobj = self.downloads[int(id)].getDiskManagerFileInfo()
|
||||||
# -1 low, 0 normal, 1 high
|
# -1 low, 0 normal, 1 high
|
||||||
|
@ -1259,6 +1480,9 @@ class Download():
|
||||||
elif self.client == 'deluge':
|
elif self.client == 'deluge':
|
||||||
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'],
|
self.client.config(host=config['host'], port=config['port'], login=config['login'], password=config['password'],
|
||||||
url=config['url'])
|
url=config['url'])
|
||||||
# print(self.client.list())
|
# print(self.client.list())
|
||||||
|
@ -1304,7 +1528,15 @@ class Download():
|
||||||
'login': '',
|
'login': '',
|
||||||
'password': self.setting.getSetting("torrent_deluge_password")
|
'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
|
return config
|
||||||
|
|
||||||
def add(self, torrent, dirname):
|
def add(self, torrent, dirname):
|
||||||
|
@ -1322,9 +1554,6 @@ class Download():
|
||||||
def listfiles(self, id):
|
def listfiles(self, id):
|
||||||
return self.client.listfiles(id)
|
return self.client.listfiles(id)
|
||||||
|
|
||||||
def delete(self, id):
|
|
||||||
return self.client.delete(id)
|
|
||||||
|
|
||||||
def setprio(self, id, ind):
|
def setprio(self, id, ind):
|
||||||
return self.client.setprio(id, ind)
|
return self.client.setprio(id, ind)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue