Рабочая версия
parent
2ab3136e24
commit
6ec2e7eea0
|
@ -73,8 +73,6 @@ dist/
|
|||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from codequick import Route, Resolver, Listitem, utils, run # @UnresolvedImport
|
||||
from codequick.storage import PersistentList # @UnresolvedImport
|
||||
import os.path
|
||||
import xbmcgui, xbmc
|
||||
from resources.lib.searchers import rutor
|
||||
from resources.lib.utils import localize, store_torrent_file, get_engine
|
||||
from resources.lib.overrrides.session import torrent_file_fetch
|
||||
from resources.lib.player import PlaybackWindow, VideoLoop
|
||||
|
||||
video_extensions = ('.mp4', '.avi', '.3gp', '.ogv', '.mkv', '.ts', '.mpg', '.mpeg', '.webm', '.flv', '.vob')
|
||||
|
||||
search_engines = [
|
||||
rutor.SearchEngine
|
||||
]
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
ICON_DIR = os.path.join(ROOT, 'resources', 'icons')
|
||||
|
||||
@Route.register
|
||||
def root(plugin, content_type='video'):
|
||||
@Route.register_delayed
|
||||
def set_view():
|
||||
xbmc.executebuiltin('Container.SetViewMode("500")')
|
||||
def build_item(a):
|
||||
cb, name, image = a
|
||||
i = Listitem.from_dict(cb, name)
|
||||
i.art.local_thumb(image)
|
||||
return i
|
||||
return map(build_item, (
|
||||
(search_history, localize(33052), 'history2.png'),
|
||||
(new_search, localize(33053), 'search.png')
|
||||
))
|
||||
@Route.register
|
||||
def search_history(plugin):
|
||||
@Route.register_delayed
|
||||
def set_view():
|
||||
xbmc.executebuiltin('Container.SetViewMode("51")')
|
||||
h_list = PersistentList('search_history')
|
||||
for i in h_list:
|
||||
item = Listitem.from_dict(search, i, params={'search_query': i})
|
||||
item.art.local_thumb('search.png')
|
||||
yield item
|
||||
else:
|
||||
yield None
|
||||
@Route.register
|
||||
def new_search(plugin):
|
||||
q = utils.keyboard('Поиск')
|
||||
if not q:
|
||||
return False
|
||||
return search(plugin, q)
|
||||
@Route.register
|
||||
def search(plugin, search_query, thumb=None):
|
||||
@Route.register_delayed
|
||||
def set_view():
|
||||
xbmc.executebuiltin('Container.SetViewMode("51")')
|
||||
with PersistentList('search_history') as h_list:
|
||||
if search_query in h_list:
|
||||
del h_list[h_list.index(search_query)]
|
||||
h_list.insert(0, search_query)
|
||||
progress = xbmcgui.DialogProgress()
|
||||
found_items = []
|
||||
progress.create(localize(33054))
|
||||
for p, se in zip(range(0, 100, 100 / len(search_engines)), search_engines):
|
||||
progress.update(p, line1=se.name)
|
||||
found_items.extend(se().search(search_query))
|
||||
res_items = []
|
||||
for i in sorted(found_items, key=lambda x: x.seeders, reverse=True):
|
||||
if '2160p' in i.title: hd = '[2160p/{}] '.format(i.size)
|
||||
elif '1080p' in i.title: hd = '[1080p/{}] '.format(i.size)
|
||||
elif '720p' in i.title: hd = '[720p/{}] '.format(i.size)
|
||||
else: hd = ''
|
||||
item = Listitem.from_dict(
|
||||
open_torrent,
|
||||
'{}{} {} ({}/{})'.format(hd, i.title, i.size, i.seeders, i.leachers),
|
||||
params={'url': i.url, 'cookies': i.cookies, 'referer': i.referer}
|
||||
)
|
||||
if thumb:
|
||||
item.art['thumb'] = thumb
|
||||
else:
|
||||
item.art.local_thumb(i.icon)
|
||||
res_items.append(item)
|
||||
progress.close()
|
||||
return res_items
|
||||
@Route.register
|
||||
def open_torrent(plugin, url='--back--', cookies={}, referer='', path=''):
|
||||
if url == '--back--':
|
||||
xbmc.executebuiltin('ActivateWindow("home")')
|
||||
yield False
|
||||
else:
|
||||
@Route.register_delayed
|
||||
def set_view():
|
||||
xbmc.executebuiltin('Container.SetViewMode("51")')
|
||||
tf = torrent_file_fetch(url, referer, cookies)
|
||||
if not tf: yield False
|
||||
t_full_path = store_torrent_file(tf)
|
||||
e = get_engine(t_full_path)
|
||||
files = sorted(list(filter(lambda x: x.name.decode('utf-8').startswith(path) and x.name.decode('utf-8').lower().endswith(video_extensions), e.list_from_info(media_types=['video']))),
|
||||
key=lambda x: x.name)
|
||||
dirs = list(set(list(map( lambda x: x.name.decode('utf-8')[len(path):].lstrip('/').split('/')[0], filter( lambda x: len(x.name.decode('utf-8')[len(path):].lstrip('/').split('/')) > 1, files ) ))))
|
||||
for d in sorted(dirs):
|
||||
item = Listitem.from_dict(open_torrent,
|
||||
d,
|
||||
params={'url': url, 'cookies': cookies, 'referer': referer, 'path': '{}/{}'.format(
|
||||
path, d
|
||||
) if path != '' else d}
|
||||
)
|
||||
item.art.local_thumb('folder.png')
|
||||
yield item
|
||||
for i in range(len(files)):
|
||||
f = files[i]
|
||||
p = f.name.decode('utf-8')[len(path):].lstrip('/').split('/')
|
||||
if len(p) == 1:
|
||||
item = Listitem.from_dict(play_file,
|
||||
'{} ({:.3f} GB)'.format(p[0], f.size / 1024.0 / 1024.0 /1024.0),
|
||||
params={'t_full_path': t_full_path, 'f_index': i}
|
||||
)
|
||||
item.art.local_thumb('video.png')
|
||||
yield item
|
||||
else:
|
||||
yield None
|
||||
@Route.register
|
||||
def play_file(plugin, t_full_path, f_index):
|
||||
vl = VideoLoop(t_full_path)
|
||||
vl.start(f_index)
|
||||
return False
|
||||
if __name__ == '__main__':
|
||||
run()
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.torrenter3" name="Torrenter3" provider-name="inpos" version="3.0.1">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.25.0"/>
|
||||
<import addon="script.module.pyrrent2http"/>
|
||||
<import addon="script.module.codequick" version="0.9.6"/>
|
||||
<import addon="script.module.pysocks" version="1.0.0"/>
|
||||
</requires>
|
||||
<extension point="xbmc.python.pluginsource" library="addon.py">
|
||||
<provides>audio video</provides>
|
||||
</extension>
|
||||
<extension point="xbmc.addon.metadata">
|
||||
<summary lang="en_GB">Plugin helps you to watch videos from p2p torrent-networks, without full predownload.</summary>
|
||||
<description lang="en_GB">Plugin helps you to watch videos from p2p torrent-networks, without full predownload.</description>
|
||||
<license>MIT</license>
|
||||
<source>https://git.ukamnya.ru/ukamnya/plugin.video.torrenter3</source>
|
||||
<forum>http://xbmc.ru/forum/showthread.php?t=14787</forum>
|
||||
<website>http://xbmc.ru/forum/showthread.php?t=14787</website>
|
||||
<email>roman@ukamnya.ru</email>
|
||||
<platform>all</platform>
|
||||
<language>en_GB ru_RU</language>
|
||||
<assets>
|
||||
<icon>resources/icon.png</icon>
|
||||
<fanart>resources/fanart.jpg</fanart>
|
||||
<!-- <screenshot>resources/screenshots/screenshot000.jpg</screenshot>
|
||||
<screenshot>resources/screenshots/screenshot001.jpg</screenshot>
|
||||
<screenshot>resources/screenshots/screenshot002.jpg</screenshot> -->
|
||||
</assets>
|
||||
<news>Initial release</news>
|
||||
<reuselanguageinvoker>true</reuselanguageinvoker>
|
||||
</extension>
|
||||
</addon>
|
|
@ -0,0 +1,61 @@
|
|||
# Kodi Media Center language file
|
||||
# Addon Name: Torrenter3
|
||||
# Addon id: plugin.video.torrenter3
|
||||
# Addon Provider: inpos
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Kodi Addons\n"
|
||||
"Report-Msgid-Bugs-To: roman@ukamnya.ru\n"
|
||||
"POT-Creation-Date: 2019-05-04 09:00+MSK\n"
|
||||
"PO-Revision-Date: 2019-05-04 12:00+MSK\n"
|
||||
"Last-Translator: Inpos\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: en_GB\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
msgctxt "#33000"
|
||||
msgid "Torrenter3"
|
||||
msgstr "Torrenter3"
|
||||
|
||||
msgctxt "#33001"
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
msgctxt "#33011"
|
||||
msgid "Storage folder"
|
||||
msgstr "Storage folder"
|
||||
|
||||
msgctxt "#33012"
|
||||
msgid "Use SOCKS proxy"
|
||||
msgstr "Use SOCKS proxy"
|
||||
|
||||
msgctxt "#33013"
|
||||
msgid "SOCKS IP address"
|
||||
msgstr "SOCKS IP addres"
|
||||
|
||||
msgctxt "#33014"
|
||||
msgid "SOCKS port"
|
||||
msgstr "SOCKS port"
|
||||
|
||||
msgctxt "#33051"
|
||||
msgid "Please specify storage folder in Settings!"
|
||||
msgstr "Please specify storage folder in Settings"
|
||||
|
||||
msgctxt "#33052"
|
||||
msgid "Search history"
|
||||
msgstr "Search history"
|
||||
|
||||
msgctxt "#33053"
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
|
||||
msgctxt "#33054"
|
||||
msgid "Search on trackers"
|
||||
msgstr "Search on trackers"
|
||||
|
||||
msgctxt "#33055"
|
||||
msgid "Waiting for download"
|
||||
msgstr "Waiting for download"
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# Kodi Media Center language file
|
||||
# Addon Name: Torrenter3
|
||||
# Addon id: plugin.video.torrenter3
|
||||
# Addon Provider: inpos
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Kodi Addons\n"
|
||||
"Report-Msgid-Bugs-To: roman@ukamnya.ru\n"
|
||||
"POT-Creation-Date: 2019-05-04 09:00+MSK\n"
|
||||
"PO-Revision-Date: 2019-05-04 12:00+MSK\n"
|
||||
"Last-Translator: Inpos\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru_RU\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
|
||||
msgctxt "#33000"
|
||||
msgid "Torrenter3"
|
||||
msgstr "Torrenter3"
|
||||
|
||||
msgctxt "#33001"
|
||||
msgid "General"
|
||||
msgstr "Основные"
|
||||
|
||||
msgctxt "#33011"
|
||||
msgid "Storage folder"
|
||||
msgstr "Папка хранения"
|
||||
|
||||
msgctxt "#33012"
|
||||
msgid "Use SOCKS proxy"
|
||||
msgstr "Использовать SOCKS-прокси"
|
||||
|
||||
msgctxt "#33013"
|
||||
msgid "SOCKS IP address"
|
||||
msgstr "Адрес IP SOCKS"
|
||||
|
||||
msgctxt "#33014"
|
||||
msgid "SOCKS port"
|
||||
msgstr "Порт SOCKS"
|
||||
|
||||
msgctxt "#33051"
|
||||
msgid "Please specify storage folder in Settings!"
|
||||
msgstr "Укажите папку хранения"
|
||||
|
||||
msgctxt "#33052"
|
||||
msgid "Search history"
|
||||
msgstr "История поиска"
|
||||
|
||||
msgctxt "#33053"
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
|
||||
msgctxt "#33054"
|
||||
msgid "Search on trackers"
|
||||
msgstr "Поиск на трекерах"
|
||||
|
||||
msgctxt "#33055"
|
||||
msgid "Waiting for download"
|
||||
msgstr "Ожидаем начало загрузки"
|
|
@ -0,0 +1,85 @@
|
|||
import urlquick # @UnresolvedImport
|
||||
from ..settings import option
|
||||
import socks
|
||||
|
||||
class SocksiPyConnection(urlquick.HTTPConnection):
|
||||
def __init__(self, proxytype, proxyaddr, proxyport=None, host='127.0.0.1', port=9050, rdns=True, username=None, password=None, **kwargs):
|
||||
self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)
|
||||
urlquick.HTTPConnection.__init__(self, host, port=port, **kwargs)
|
||||
|
||||
def connect(self):
|
||||
self.sock = socks.socksocket()
|
||||
self.sock.setproxy(*self.proxyargs)
|
||||
if type(self.timeout) in (int, float):
|
||||
self.sock.settimeout(self.timeout)
|
||||
self.sock.connect((self.host, self.port))
|
||||
|
||||
class SocksiPyConnectionS(urlquick.HTTPSConnection):
|
||||
def __init__(self, proxytype, proxyaddr, proxyport=None, host='127.0.0.1', port=9050, rdns=True, username=None, password=None, **kwargs):
|
||||
self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)
|
||||
urlquick.HTTPSConnection.__init__(self, host, port=port, **kwargs)
|
||||
|
||||
def connect(self):
|
||||
sock = socks.socksocket()
|
||||
sock.setproxy(*self.proxyargs)
|
||||
if type(self.timeout) in (int, float):
|
||||
sock.settimeout(self.timeout)
|
||||
sock.connect((self.host, self.port))
|
||||
self.sock = urlquick.ssl.wrap_socket(sock, self.key_file, self.cert_file)
|
||||
|
||||
class Session(urlquick.Session):
|
||||
def connect(self, req, timeout, verify):
|
||||
# Fetch connection from pool and attempt to reuse if available
|
||||
pool = self.request_handler[req.type]
|
||||
if req.host in pool:
|
||||
try:
|
||||
# noinspection PyTypeChecker
|
||||
return self.send_request(pool[req.host], req)
|
||||
except Exception as e:
|
||||
# Remove the connection from the pool as it's unusable
|
||||
pool[req.host].close()
|
||||
del pool[req.host]
|
||||
|
||||
# Raise the exception if it's not a subclass of UrlError
|
||||
if not isinstance(e, urlquick.UrlError):
|
||||
raise
|
||||
|
||||
|
||||
host_port = req.host.split(':')
|
||||
host = host_port[0]
|
||||
port = int(host_port[2]) if len(host_port) > 1 else 443 if req.type == 'https' else 80
|
||||
# Create a new connection
|
||||
if not option.get_boolean('use_socks'): # @UndefinedVariable
|
||||
if req.type == "https":
|
||||
context = urlquick.ssl._create_unverified_context() if verify is False else None
|
||||
conn = urlquick.HTTPSConnection(host, port, timeout=timeout, context=context)
|
||||
else:
|
||||
conn = urlquick.HTTPConnection(host, port, timeout=timeout)
|
||||
else:
|
||||
if req.type == "https":
|
||||
context = urlquick.ssl._create_unverified_context() if verify is False else None
|
||||
conn = SocksiPyConnectionS(socks.PROXY_TYPE_SOCKS5, option['socks_ip'], proxyport=int(option['socks_port']),
|
||||
host=host, port=port, timeout=timeout, context=context)
|
||||
else:
|
||||
conn = SocksiPyConnection(socks.PROXY_TYPE_SOCKS5, option['socks_ip'], proxyport=int(option['socks_port']),
|
||||
host=host, port=port, timeout=timeout)
|
||||
|
||||
# Make first connection to server
|
||||
response = self.send_request(conn, req)
|
||||
|
||||
# Add connection to the pool if the response is not set to close
|
||||
if not response.will_close:
|
||||
pool[req.host] = conn
|
||||
return response
|
||||
def torrent_file_fetch(url, referer, cookies):
|
||||
sess = Session()
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 YaBrowser/14.10.2062.12061 Safari/537.36',
|
||||
'Referer': referer
|
||||
}
|
||||
resp = sess.get(url, cookies=cookies, headers=headers)
|
||||
if resp.ok:
|
||||
return resp.content
|
||||
else:
|
||||
return None
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import xbmc, xbmcgui
|
||||
from .utils import get_engine, localize
|
||||
|
||||
EXPECTED_KBITS = 512
|
||||
|
||||
class TorrentPlayer(xbmc.Player) :
|
||||
pyrrent_engine = None
|
||||
loop = None
|
||||
def onPlayBackEnded(self):
|
||||
self.pyrrent_engine.close()
|
||||
self.loop.stopped = True
|
||||
xbmc.Player().stop()
|
||||
def onPlayBackPaused(self):
|
||||
self.pyrrent_engine.pause()
|
||||
|
||||
def onPlayBackResumed(self):
|
||||
self.pyrrent_engine.resume()
|
||||
|
||||
def onPlayBackStopped(self):
|
||||
self.pyrrent_engine.close()
|
||||
self.loop.stopped = True
|
||||
xbmc.Player().stop()
|
||||
def play(self, engine, f_index):
|
||||
self.pyrrent_engine = engine
|
||||
self.pyrrent_engine.start()
|
||||
self.pyrrent_engine.activate_file(f_index)
|
||||
monitor = xbmc.Monitor()
|
||||
pw = xbmcgui.DialogProgress()
|
||||
pw.create(localize(33055), line1='0 Kbit/s')
|
||||
while True:
|
||||
xbmc.sleep(500)
|
||||
if monitor.abortRequested() or pw.iscanceled():
|
||||
pw.close()
|
||||
self.pyrrent_engine.close()
|
||||
xbmc.Player().stop()
|
||||
self.loop.stopped = True
|
||||
return False
|
||||
status = self.pyrrent_engine.status()
|
||||
d_rate = status.download_rate
|
||||
xbmc.log('*** DRATE: {}'.format(d_rate), level=xbmc.LOGNOTICE)
|
||||
perc = d_rate / EXPECTED_KBITS * 100
|
||||
if perc > 100: perc = 100
|
||||
pw.update(perc, line1='{} kbit/s'.format(int(d_rate)))
|
||||
if perc == 100:
|
||||
pw.close()
|
||||
break
|
||||
fstat = self.pyrrent_engine.file_status(f_index)
|
||||
listitem = xbmcgui.ListItem('.'.join(fstat.name.split('.')[:-1]), path=fstat.url)
|
||||
xbmc.Player.play(self, fstat.url, listitem)
|
||||
|
||||
class VideoLoop(object):
|
||||
stopped = False
|
||||
status = None
|
||||
def __init__(self, torr_fp):
|
||||
self.e = get_engine(torr_fp)
|
||||
def start(self, f_index):
|
||||
self.mediaPlayer = TorrentPlayer()
|
||||
self.mediaPlayer.loop = self
|
||||
self.mediaPlayer.play(self.e, f_index)
|
||||
while not self.stopped:
|
||||
self.status = self.e.status()
|
||||
xbmc.sleep(1000)
|
|
@ -0,0 +1,43 @@
|
|||
from codequick.utils import urljoin_partial # @UnresolvedImport
|
||||
import urlquick # @UnresolvedImport
|
||||
from ..settings import option
|
||||
from ..overrrides import session
|
||||
#import xbmc
|
||||
|
||||
class ResultItem(object):
|
||||
def __init__(self, url, title, size, seeders, leachers, icon='video.png', cookies={}, referer=''):
|
||||
self.url = url
|
||||
self.title = title
|
||||
self.size = size
|
||||
self.seeders = seeders
|
||||
self.leachers = leachers
|
||||
self.icon = icon
|
||||
self.cookies = cookies
|
||||
self.referer = referer
|
||||
|
||||
class Searcher(object):
|
||||
base_url = None
|
||||
search_path = None
|
||||
cookies = {}
|
||||
headers = {}
|
||||
name = 'BaseClass'
|
||||
def __init__(self):
|
||||
self.session = session.Session()
|
||||
def prepare(self):
|
||||
'''Login or something else if needed'''
|
||||
def search(self, query):
|
||||
self.prepare()
|
||||
url_constructor = urljoin_partial(self.base_url)
|
||||
s_url = url_constructor(self.search_path.format(urlquick.quote(query)))
|
||||
self.set_headers()
|
||||
resp = self.session.get(s_url, cookies=self.cookies, headers=self.headers)
|
||||
self.cookies = resp.cookies
|
||||
body = resp.parse('body')
|
||||
return self.process(body)
|
||||
def process(self, body):
|
||||
'''Process element tree'''
|
||||
def set_headers(self):
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 YaBrowser/14.10.2062.12061 Safari/537.36',
|
||||
'Referer': self.base_url
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
from . import Searcher, urljoin_partial, ResultItem
|
||||
|
||||
class SearchEngine(Searcher):
|
||||
base_url = 'http://new-tor.top'
|
||||
search_path = '/search/0/0/100/2/{}'
|
||||
name = 'RuTor.org'
|
||||
icon = 'searcher_rutor.png'
|
||||
def process(self, body):
|
||||
url_constructor = urljoin_partial(self.base_url)
|
||||
rows = list(filter(lambda x: len(x.findall('.//a')) == 3, body.findall('.//tr')))
|
||||
for r in rows:
|
||||
links = r.findall('.//a')
|
||||
url = url_constructor(links[0].get('href').strip())
|
||||
title = links[2].text
|
||||
seeders = int(list(r.findall('.//span[@class="green"]')[0].itertext())[0].strip())
|
||||
leachers = int(list(r.findall('.//span[@class="red"]')[0].itertext())[0].strip())
|
||||
size = list(
|
||||
list(filter(lambda x: len(list(x.itertext())) == 1 and list(x.itertext())[0].strip().endswith(('GB', 'MB')),
|
||||
r.findall('.//td'))
|
||||
)[0].itertext()
|
||||
)[0].strip()
|
||||
yield ResultItem(url, title, size, seeders, leachers, self.icon, self.cookies, self.base_url)
|
|
@ -0,0 +1,9 @@
|
|||
from codequick.script import Settings # @UnresolvedImport
|
||||
import os
|
||||
|
||||
option = Settings()
|
||||
storage_root = os.path.abspath(os.path.join(option['storage_dir'], 'Torrenter3'))
|
||||
storage_toorents_dir = os.path.join(storage_root, 'torrents')
|
||||
storage_download_dir = os.path.join(storage_root, 'download')
|
||||
if not os.path.exists(storage_toorents_dir): os.makedirs(storage_toorents_dir)
|
||||
if not os.path.exists(storage_download_dir): os.makedirs(storage_download_dir)
|
|
@ -0,0 +1,45 @@
|
|||
from codequick.support import addon_data # @UnresolvedImport
|
||||
from urlquick import urljoin # @UnresolvedImport
|
||||
from ..settings import option, storage_toorents_dir, storage_download_dir
|
||||
import xbmcgui
|
||||
import os
|
||||
from hashlib import sha1
|
||||
from pyrrent2http import Engine # @UnresolvedImport
|
||||
import sys
|
||||
py3 = sys.version_info >= (3, 0)
|
||||
if py3:
|
||||
from urllib.request import pathname2url # @UnresolvedImport
|
||||
else:
|
||||
from urllib import pathname2url
|
||||
|
||||
def localize(sid):
|
||||
return addon_data.getLocalizedString(sid)
|
||||
def store_torrent_file(file_bytes):
|
||||
h = sha1(file_bytes).hexdigest()
|
||||
t_fname = '{}.torrent'.format(h)
|
||||
full_path = os.path.join(storage_toorents_dir, t_fname)
|
||||
if os.path.exists(full_path):
|
||||
with open(full_path, 'rb') as f:
|
||||
if sha1(f.read()).hexdigest() == h:
|
||||
return full_path
|
||||
with open(full_path, 'wb') as f:
|
||||
f.write(file_bytes)
|
||||
return full_path
|
||||
def torrent_full_path(t_fname):
|
||||
return os.path.join(storage_toorents_dir, t_fname)
|
||||
|
||||
def file_url(path):
|
||||
if not path.startswith('file:'):
|
||||
path = urljoin('file:', pathname2url(path))
|
||||
return path
|
||||
|
||||
def get_engine(torrent_uri):
|
||||
return Engine(uri=file_url(torrent_uri), download_path=storage_download_dir,
|
||||
encryption=1, keep_complete=False, keep_incomplete=False,
|
||||
dht_routers=["router.bittorrent.com:6881", "router.utorrent.com:6881"], use_random_port=False, listen_port=6881,
|
||||
user_agent='', enable_dht=True)
|
||||
|
||||
while not option['storage_dir']:
|
||||
dialog = xbmcgui.Dialog()
|
||||
dialog.ok(localize(33000), localize(33051))
|
||||
addon_data.openSettings()
|
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<settings>
|
||||
<category label="33001">
|
||||
<setting label="33011" type="folder" id="storage_dir" default=""/>
|
||||
<setting label="33012" type="bool" id="use_socks" default="false"/>
|
||||
<setting label="33013" type="ipaddress" id="socks_ip" default="127.0.0.1" visible="eq(-1,true)"/>
|
||||
<setting label="33014" type="number" id="socks_port" default="9050" visible="eq(-2,true)"/>
|
||||
</category>
|
||||
</settings>
|
Loading…
Reference in New Issue