|
@ -1,5 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.7 (D:/Python27/python.exe)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.12 (D:\Python27\python.exe)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$" />
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 2.7.12 (D:\Python27\python.exe)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
4020
.idea/workspace.xml
45
AceStream.py
|
@ -25,10 +25,10 @@ import hashlib
|
||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import gzip
|
import zlib
|
||||||
|
|
||||||
from functions import file_decode, file_encode
|
from functions import file_decode, file_encode
|
||||||
from functions import magnet_alert, log, debug
|
from functions import magnet_alert, log, loadsw_onstop
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ class AceStream:
|
||||||
|
|
||||||
def __exit__(self):
|
def __exit__(self):
|
||||||
self.TSplayer.end()
|
self.TSplayer.end()
|
||||||
|
loadsw_onstop() # Reload Search Window
|
||||||
|
|
||||||
def play_url_ind(self, ind, label, icon):
|
def play_url_ind(self, ind, label, icon):
|
||||||
self.TSplayer.play_url_ind(int(ind), label, str(icon), '')
|
self.TSplayer.play_url_ind(int(ind), label, str(icon), '')
|
||||||
|
@ -93,19 +94,12 @@ class AceStream:
|
||||||
torrentFile = self.storageDirectory + os.sep + self.torrentFilesDirectory + os.sep + self.md5(
|
torrentFile = self.storageDirectory + os.sep + self.torrentFilesDirectory + os.sep + self.md5(
|
||||||
torrentUrl) + '.torrent'
|
torrentUrl) + '.torrent'
|
||||||
try:
|
try:
|
||||||
if not re.match("^http\:.+$", torrentUrl):
|
if not re.match("^[htps]+?://.+$|^://.+$", torrentUrl):
|
||||||
content = xbmcvfs.File(file_decode(torrentUrl), "rb").read()
|
log('xbmcvfs.File for %s' % torrentUrl)
|
||||||
|
content = xbmcvfs.File(torrentUrl, "rb").read()
|
||||||
else:
|
else:
|
||||||
request = urllib2.Request(torrentUrl)
|
log('request for %s' % torrentUrl)
|
||||||
request.add_header('Referer', torrentUrl)
|
content = self.makeRequest(torrentUrl)
|
||||||
request.add_header('Accept-encoding', 'gzip')
|
|
||||||
result = urllib2.urlopen(request)
|
|
||||||
if result.info().get('Content-Encoding') == 'gzip':
|
|
||||||
buf = StringIO(result.read())
|
|
||||||
f = gzip.GzipFile(fileobj=buf)
|
|
||||||
content = f.read()
|
|
||||||
else:
|
|
||||||
content = result.read()
|
|
||||||
|
|
||||||
localFile = xbmcvfs.File(torrentFile, "w+b")
|
localFile = xbmcvfs.File(torrentFile, "w+b")
|
||||||
localFile.write(content)
|
localFile.write(content)
|
||||||
|
@ -119,6 +113,29 @@ class AceStream:
|
||||||
self.torrentFileInfo = self.TSplayer.load_torrent(base64.b64encode(content), 'RAW')
|
self.torrentFileInfo = self.TSplayer.load_torrent(base64.b64encode(content), 'RAW')
|
||||||
return self.torrentFile
|
return self.torrentFile
|
||||||
|
|
||||||
|
def makeRequest(self, torrentUrl):
|
||||||
|
torrentUrl = re.sub('^://', 'http://', torrentUrl)
|
||||||
|
x = re.search("://(.+?)/|://(.+?)$", torrentUrl)
|
||||||
|
if x:
|
||||||
|
baseurl = x.group(1) if x.group(1) else x.group(2)
|
||||||
|
else:
|
||||||
|
baseurl =''
|
||||||
|
|
||||||
|
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', 'http://%s/' % baseurl), ('Accept-encoding', 'gzip'), ]
|
||||||
|
|
||||||
|
opener = urllib2.build_opener()
|
||||||
|
opener.addheaders = headers
|
||||||
|
result = opener.open(torrentUrl)
|
||||||
|
if result.info().get('Content-Encoding') == 'gzip':
|
||||||
|
buf = StringIO(result.read())
|
||||||
|
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
||||||
|
content = decomp.decompress(buf.getvalue())
|
||||||
|
else:
|
||||||
|
content = result.read()
|
||||||
|
return content
|
||||||
|
|
||||||
def magnetToTorrent(self, magnet):
|
def magnetToTorrent(self, magnet):
|
||||||
try:
|
try:
|
||||||
from SkorbaLoader import SkorbaLoader
|
from SkorbaLoader import SkorbaLoader
|
||||||
|
|
|
@ -30,7 +30,7 @@ import xbmcgui
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
import Localization
|
import Localization
|
||||||
from functions import file_encode, isSubtitle, DownloadDB, log, debug, is_writable, unquote, file_url
|
from functions import localize_path, isSubtitle, loadsw_onstop, is_writable, file_url
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -134,7 +134,7 @@ class AnteoLoader:
|
||||||
|
|
||||||
dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
|
dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
|
||||||
user_agent = 'uTorrent/2200(24683)'
|
user_agent = 'uTorrent/2200(24683)'
|
||||||
self.engine = Engine(uri=file_url(self.torrentFile), download_path=self.storageDirectory,
|
self.engine = Engine(uri=file_url(localize_path(self.torrentFile)), download_path=self.storageDirectory,
|
||||||
connections_limit=connections_limit,
|
connections_limit=connections_limit,
|
||||||
encryption=encryption, keep_complete=keep_complete, keep_incomplete=keep_incomplete,
|
encryption=encryption, keep_complete=keep_complete, keep_incomplete=keep_incomplete,
|
||||||
dht_routers=dht_routers, use_random_port=use_random_port, listen_port=listen_port,
|
dht_routers=dht_routers, use_random_port=use_random_port, listen_port=listen_port,
|
||||||
|
@ -200,19 +200,12 @@ class AnteoLoader:
|
||||||
if not xbmcvfs.exists(self.torrentFilesPath): xbmcvfs.mkdirs(self.torrentFilesPath)
|
if not xbmcvfs.exists(self.torrentFilesPath): xbmcvfs.mkdirs(self.torrentFilesPath)
|
||||||
torrentFile = os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent')
|
torrentFile = os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent')
|
||||||
try:
|
try:
|
||||||
if not re.match("^http\:.+$", torrentUrl):
|
if not re.match("^[htps]+?://.+$|^://.+$", torrentUrl):
|
||||||
|
log('xbmcvfs.File for %s' % torrentUrl)
|
||||||
content = xbmcvfs.File(torrentUrl, "rb").read()
|
content = xbmcvfs.File(torrentUrl, "rb").read()
|
||||||
else:
|
else:
|
||||||
request = urllib2.Request(torrentUrl)
|
log('request for %s' % torrentUrl)
|
||||||
request.add_header('Referer', torrentUrl)
|
content = self.makeRequest(torrentUrl)
|
||||||
request.add_header('Accept-encoding', 'gzip')
|
|
||||||
result = urllib2.urlopen(request)
|
|
||||||
if result.info().get('Content-Encoding') == 'gzip':
|
|
||||||
buf = StringIO(result.read())
|
|
||||||
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
|
||||||
content = decomp.decompress(buf.getvalue())
|
|
||||||
else:
|
|
||||||
content = result.read()
|
|
||||||
|
|
||||||
localFile = xbmcvfs.File(torrentFile, "w+b")
|
localFile = xbmcvfs.File(torrentFile, "w+b")
|
||||||
localFile.write(content)
|
localFile.write(content)
|
||||||
|
@ -229,6 +222,29 @@ class AnteoLoader:
|
||||||
self.torrentFile = torrentFile
|
self.torrentFile = torrentFile
|
||||||
return self.torrentFile
|
return self.torrentFile
|
||||||
|
|
||||||
|
def makeRequest(self, torrentUrl):
|
||||||
|
torrentUrl = re.sub('^://', 'http://', torrentUrl)
|
||||||
|
x = re.search("://(.+?)/|://(.+?)$", torrentUrl)
|
||||||
|
if x:
|
||||||
|
baseurl = x.group(1) if x.group(1) else x.group(2)
|
||||||
|
else:
|
||||||
|
baseurl =''
|
||||||
|
|
||||||
|
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', 'http://%s/' % baseurl), ('Accept-encoding', 'gzip'), ]
|
||||||
|
|
||||||
|
opener = urllib2.build_opener()
|
||||||
|
opener.addheaders = headers
|
||||||
|
result = opener.open(torrentUrl)
|
||||||
|
if result.info().get('Content-Encoding') == 'gzip':
|
||||||
|
buf = StringIO(result.read())
|
||||||
|
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
||||||
|
content = decomp.decompress(buf.getvalue())
|
||||||
|
else:
|
||||||
|
content = result.read()
|
||||||
|
return content
|
||||||
|
|
||||||
def md5(self, string):
|
def md5(self, string):
|
||||||
hasher = hashlib.md5()
|
hasher = hashlib.md5()
|
||||||
try:
|
try:
|
||||||
|
@ -286,9 +302,12 @@ class AnteoPlayer(xbmc.Player):
|
||||||
if self.buffer():
|
if self.buffer():
|
||||||
log('[AnteoPlayer]: ************************************* GOING LOOP')
|
log('[AnteoPlayer]: ************************************* GOING LOOP')
|
||||||
if self.setup_play():
|
if self.setup_play():
|
||||||
|
WatchedHistoryDB().add(self.basename, self.torrentUrl,
|
||||||
|
foldername(self.getContentList()[self.contentId]['title']),
|
||||||
|
self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
||||||
self.setup_subs()
|
self.setup_subs()
|
||||||
self.loop()
|
self.loop()
|
||||||
WatchedHistoryDB().add(self.basename, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
WatchedHistoryDB().add(self.basename, self.torrentUrl, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
||||||
else:
|
else:
|
||||||
log('[AnteoPlayer]: ************************************* break')
|
log('[AnteoPlayer]: ************************************* break')
|
||||||
break
|
break
|
||||||
|
@ -304,6 +323,8 @@ class AnteoPlayer(xbmc.Player):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
log('[AnteoPlayer]: ************************************* NO! break')
|
log('[AnteoPlayer]: ************************************* NO! break')
|
||||||
|
showMessage(self.localize('Information'),
|
||||||
|
self.localize('Stopping the torrent2http process...'))
|
||||||
break
|
break
|
||||||
|
|
||||||
xbmc.Player().stop()
|
xbmc.Player().stop()
|
||||||
|
@ -311,14 +332,11 @@ class AnteoPlayer(xbmc.Player):
|
||||||
if '1' != self.__settings__.getSetting("keep_files") and 'Saved Files' not in self.userStorageDirectory:
|
if '1' != self.__settings__.getSetting("keep_files") and 'Saved Files' not in self.userStorageDirectory:
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
clearStorage(self.userStorageDirectory)
|
clearStorage(self.userStorageDirectory)
|
||||||
else:
|
|
||||||
#if self.seeding_status:
|
showMessage(self.localize('Information'),
|
||||||
#showMessage(self.localize('Information'),
|
self.localize('torrent2http process stopped.'))
|
||||||
# self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
|
|
||||||
#else:
|
loadsw_onstop() # Reload Search Window
|
||||||
#if self.seeding: self.db_delete()
|
|
||||||
showMessage(self.localize('Information'),
|
|
||||||
self.localize('Torrent downloading is stopped.'), forced=True)
|
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.next_contentId = False
|
self.next_contentId = False
|
||||||
|
@ -332,16 +350,6 @@ class AnteoPlayer(xbmc.Player):
|
||||||
self.torrentUrl = self.torrentUrl
|
self.torrentUrl = self.torrentUrl
|
||||||
|
|
||||||
def setup_engine(self):
|
def setup_engine(self):
|
||||||
#uri=None, binaries_path=None, platform=None, download_path=".",
|
|
||||||
#bind_host='127.0.0.1', bind_port=5001, connections_limit=None, download_kbps=None, upload_kbps=None,
|
|
||||||
#enable_dht=True, enable_lsd=True, enable_natpmp=True, enable_upnp=True, enable_scrape=False,
|
|
||||||
#log_stats=False, encryption=Encryption.ENABLED, keep_complete=False, keep_incomplete=False,
|
|
||||||
#keep_files=False, log_files_progress=False, log_overall_progress=False, log_pieces_progress=False,
|
|
||||||
#listen_port=6881, use_random_port=False, max_idle_timeout=None, no_sparse=False, resume_file=None,
|
|
||||||
#user_agent=None, startup_timeout=5, state_file=None, enable_utp=True, enable_tcp=True,
|
|
||||||
#debug_alerts=False, logger=None, torrent_connect_boost=50, connection_speed=50,
|
|
||||||
#peer_connect_timeout=15, request_timeout=20, min_reconnect_time=60, max_failcount=3,
|
|
||||||
#dht_routers=None, trackers=None)
|
|
||||||
|
|
||||||
encryption = Encryption.ENABLED if self.__settings__.getSetting('encryption') == 'true' else Encryption.DISABLED
|
encryption = Encryption.ENABLED if self.__settings__.getSetting('encryption') == 'true' else Encryption.DISABLED
|
||||||
upload_limit = int(self.__settings__.getSetting("upload_limit"))*1024/8 if self.__settings__.getSetting(
|
upload_limit = int(self.__settings__.getSetting("upload_limit"))*1024/8 if self.__settings__.getSetting(
|
||||||
|
@ -382,16 +390,10 @@ class AnteoPlayer(xbmc.Player):
|
||||||
keep_files=keep_files, user_agent=user_agent, resume_file=resume_file, enable_dht=enable_dht)
|
keep_files=keep_files, user_agent=user_agent, resume_file=resume_file, enable_dht=enable_dht)
|
||||||
|
|
||||||
def buffer(self):
|
def buffer(self):
|
||||||
#self.pre_buffer_bytes = 30*1024*1024 #30 MB
|
|
||||||
ready = False
|
ready = False
|
||||||
progressBar = xbmcgui.DialogProgress()
|
progressBar = xbmcgui.DialogProgress()
|
||||||
progressBar.create('[%sPlayer v%s] ' % (author, __version__) + self.localize('Please Wait'),
|
progressBar.create('[%sPlayer v%s] ' % (author, __version__) + self.localize('Please Wait'),
|
||||||
self.localize('Seeds searching.'))
|
self.localize('Seeds searching.'))
|
||||||
#if self.subs_dl:
|
|
||||||
# subs = self.torrent.getSubsIds(os.path.basename(self.torrent.getFilePath(self.contentId)))
|
|
||||||
# if len(subs) > 0:
|
|
||||||
# for ind, title in subs:
|
|
||||||
# self.torrent.continueSession(ind)
|
|
||||||
|
|
||||||
while not xbmc.abortRequested and not ready:
|
while not xbmc.abortRequested and not ready:
|
||||||
xbmc.sleep(500)
|
xbmc.sleep(500)
|
||||||
|
@ -503,6 +505,10 @@ class AnteoPlayer(xbmc.Player):
|
||||||
listitem.setThumbnailImage(urllib.unquote_plus(thumbnail))
|
listitem.setThumbnailImage(urllib.unquote_plus(thumbnail))
|
||||||
self.display_name = label
|
self.display_name = label
|
||||||
|
|
||||||
|
if self.get('listitem'):
|
||||||
|
listitem = self.get('listitem')
|
||||||
|
listitem.setPath(url)
|
||||||
|
|
||||||
player = xbmc.Player()
|
player = xbmc.Player()
|
||||||
player.play(url, listitem)
|
player.play(url, listitem)
|
||||||
|
|
||||||
|
@ -547,10 +553,10 @@ class AnteoPlayer(xbmc.Player):
|
||||||
status = self.engine.status()
|
status = self.engine.status()
|
||||||
file_status = self.engine.file_status(self.contentId)
|
file_status = self.engine.file_status(self.contentId)
|
||||||
self.watchedTime = xbmc.Player().getTime()
|
self.watchedTime = xbmc.Player().getTime()
|
||||||
self.totalTime = xbmc.Player().getTotalTime()
|
|
||||||
if self.iterator == 100 and debug_counter < 100:
|
if self.iterator == 100 and debug_counter < 100:
|
||||||
debug_counter += 1
|
debug_counter += 1
|
||||||
else:
|
else:
|
||||||
|
self.totalTime = xbmc.Player().getTotalTime()
|
||||||
self.print_debug(status)
|
self.print_debug(status)
|
||||||
debug_counter=0
|
debug_counter=0
|
||||||
|
|
||||||
|
@ -564,12 +570,6 @@ class AnteoPlayer(xbmc.Player):
|
||||||
log('[loop]: xbmc.Player().pause()')
|
log('[loop]: xbmc.Player().pause()')
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
|
|
||||||
#if not self.seeding_run and self.iterator == 100 and self.seeding:
|
|
||||||
#self.seeding_run = True
|
|
||||||
#self.seed(self.contentId)
|
|
||||||
#self.seeding_status = True
|
|
||||||
# xbmc.sleep(7000)
|
|
||||||
|
|
||||||
def onPlayBackStarted(self):
|
def onPlayBackStarted(self):
|
||||||
for f in self.on_playback_started:
|
for f in self.on_playback_started:
|
||||||
f()
|
f()
|
||||||
|
@ -600,10 +600,10 @@ class AnteoPlayer(xbmc.Player):
|
||||||
|
|
||||||
def _get_status_lines(self, s, f):
|
def _get_status_lines(self, s, f):
|
||||||
return [
|
return [
|
||||||
self.display_name,
|
ensure_str(self.display_name),
|
||||||
"%.2f%% %s" % (f.progress * 100, self.localize(STATE_STRS[s.state]).decode('utf-8')),
|
"%.2f%% %s" % (f.progress * 100, self.localize(STATE_STRS[s.state])),
|
||||||
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate, self.localize('kb/s').decode('utf-8'),
|
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate, self.localize('kb/s'),
|
||||||
s.upload_rate, self.localize('kb/s').decode('utf-8'),
|
s.upload_rate, self.localize('kb/s'),
|
||||||
s.num_seeds, s.num_peers)
|
s.num_seeds, s.num_peers)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
17
Content.py
|
@ -26,6 +26,7 @@ import re
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import gzip
|
import gzip
|
||||||
import HTMLParser
|
import HTMLParser
|
||||||
|
import ssl
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
import Localization
|
import Localization
|
||||||
|
@ -87,6 +88,7 @@ class Content:
|
||||||
'horror': ('Horror',),
|
'horror': ('Horror',),
|
||||||
'romance': ('Romance',),
|
'romance': ('Romance',),
|
||||||
'thriller': ('Thriller',),
|
'thriller': ('Thriller',),
|
||||||
|
'sci_fi': ('Sci-Fi',),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +133,8 @@ class Content:
|
||||||
else:
|
else:
|
||||||
get = self.category_dict[category][subcategory]
|
get = self.category_dict[category][subcategory]
|
||||||
|
|
||||||
if category == 'search': get = (get[0], get[1] % urllib.quote_plus(subcategory.encode('utf-8')))
|
if category == 'search' and subcategory != True:
|
||||||
|
get = (get[0], get[1] % urllib.quote_plus(subcategory.encode('utf-8')))
|
||||||
|
|
||||||
property = self.get_property(category, subcategory)
|
property = self.get_property(category, subcategory)
|
||||||
|
|
||||||
|
@ -172,14 +175,20 @@ class Content:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if has_property:
|
if has_property:
|
||||||
if category == 'search': property['page'] = property['page'] % urllib.quote_plus(
|
if category == 'search' and subcategory != True:
|
||||||
subcategory.encode('utf-8'))
|
property['page'] = property['page'] % urllib.quote_plus(subcategory.encode('utf-8'))
|
||||||
return property
|
return property
|
||||||
|
|
||||||
|
|
||||||
def makeRequest(self, url, data={}, headers=[]):
|
def makeRequest(self, url, data={}, headers=[]):
|
||||||
self.cookieJar = cookielib.CookieJar()
|
self.cookieJar = cookielib.CookieJar()
|
||||||
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
|
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
|
||||||
|
# python ssl Context support - PEP 0466
|
||||||
|
if hasattr(ssl, '_create_unverified_context'):
|
||||||
|
ssl_context = ssl._create_unverified_context()
|
||||||
|
opener.add_handler(urllib2.HTTPSHandler(context=ssl_context))
|
||||||
|
else:
|
||||||
|
opener.add_handler(urllib2.HTTPSHandler())
|
||||||
opener.addheaders = headers
|
opener.addheaders = headers
|
||||||
if 0 < len(data):
|
if 0 < len(data):
|
||||||
encodedData = urllib.urlencode(data)
|
encodedData = urllib.urlencode(data)
|
||||||
|
@ -211,6 +220,7 @@ class Content:
|
||||||
('>', '>'),
|
('>', '>'),
|
||||||
('"', '"'),
|
('"', '"'),
|
||||||
("'", '''),
|
("'", '''),
|
||||||
|
("'", '''),
|
||||||
(' ', ' ',),
|
(' ', ' ',),
|
||||||
('"', '«', ),
|
('"', '«', ),
|
||||||
('"', '»', ),
|
('"', '»', ),
|
||||||
|
@ -218,6 +228,7 @@ class Content:
|
||||||
('e', 'é',),
|
('e', 'é',),
|
||||||
('e', 'è',),
|
('e', 'è',),
|
||||||
('&', '&',),
|
('&', '&',),
|
||||||
|
('&', '&',),
|
||||||
('u', 'ù',),
|
('u', 'ù',),
|
||||||
('u', 'ú',),
|
('u', 'ú',),
|
||||||
('o', 'ô',),
|
('o', 'ô',),
|
||||||
|
|
386
Core.py
|
@ -30,14 +30,16 @@ class Core:
|
||||||
__plugin__ = sys.modules["__main__"].__plugin__
|
__plugin__ = sys.modules["__main__"].__plugin__
|
||||||
__settings__ = sys.modules["__main__"].__settings__
|
__settings__ = sys.modules["__main__"].__settings__
|
||||||
ROOT = sys.modules["__main__"].__root__
|
ROOT = sys.modules["__main__"].__root__
|
||||||
userStorageDirectory = localize_path(__settings__.getSetting("storage"))#file_encode(__settings__.getSetting("storage"))
|
userStorageDirectory = localize_path(xbmc.translatePath(__settings__.getSetting("storage")))#file_encode(__settings__.getSetting("storage"))
|
||||||
torrentFilesDirectory = 'torrents'
|
torrentFilesDirectory = 'torrents'
|
||||||
debug = __settings__.getSetting('debug') == 'true'
|
debug = __settings__.getSetting('debug') == 'true'
|
||||||
torrent_player = __settings__.getSetting("torrent_player")
|
torrent_player = __settings__.getSetting("torrent_player")
|
||||||
history_bool = __settings__.getSetting('history') == 'true'
|
history_bool = __settings__.getSetting('history') == 'true'
|
||||||
open_option = int(__settings__.getSetting('open_option'))
|
open_option = int(__settings__.getSetting('open_option'))
|
||||||
language = {0: 'en', 1: 'ru', 2: 'uk', 3: 'he'}.get(int(__settings__.getSetting("language")))
|
language = {0: 'en', 1: 'ru', 2: 'uk', 3: 'he', 4: 'hu'}.get(int(__settings__.getSetting("language")))
|
||||||
scrapperDB_ver = {'en':'1.1', 'ru':'1.3', 'he':'1.3'}
|
scrapperDB_ver = {'en':'1.1', 'ru':'1.3', 'he':'1.3'}
|
||||||
|
torrent_info_style = int(__settings__.getSetting('torrent_info_style'))
|
||||||
|
searchwindowmode = int(__settings__.getSetting('searchwindowmode'))
|
||||||
|
|
||||||
log('SYS ARGV: ' + str(sys.argv))
|
log('SYS ARGV: ' + str(sys.argv))
|
||||||
|
|
||||||
|
@ -52,7 +54,11 @@ class Core:
|
||||||
def sectionMenu(self):
|
def sectionMenu(self):
|
||||||
if self.__settings__.getSetting('plugin_name') != self.__plugin__:
|
if self.__settings__.getSetting('plugin_name') != self.__plugin__:
|
||||||
#Every update run
|
#Every update run
|
||||||
first_run_250()
|
first_run_260()
|
||||||
|
if self.version_check():
|
||||||
|
estuary()
|
||||||
|
|
||||||
|
self.__settings__.setSetting('first_run_260', 'True')
|
||||||
self.__settings__.setSetting('plugin_name', self.__plugin__)
|
self.__settings__.setSetting('plugin_name', self.__plugin__)
|
||||||
#check_network_advancedsettings()
|
#check_network_advancedsettings()
|
||||||
check_download_dir()
|
check_download_dir()
|
||||||
|
@ -64,49 +70,100 @@ class Core:
|
||||||
contextMenu = [(self.localize('Search Control Window'),
|
contextMenu = [(self.localize('Search Control Window'),
|
||||||
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))]
|
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))]
|
||||||
|
|
||||||
if self.history_bool:
|
#Search Window
|
||||||
HistorycontextMenu=[]
|
if self.searchwindowmode < 3:
|
||||||
|
self.drawItem('< %s >' % self.localize('Search Window'), 'searchWindow',
|
||||||
|
image=self.ROOT + '/icons/kodi.png', isFolder=False)
|
||||||
|
|
||||||
|
#History
|
||||||
|
if self.history_bool and self.searchwindowmode > 0:
|
||||||
|
HistorycontextMenu = []
|
||||||
HistorycontextMenu.extend(contextMenu)
|
HistorycontextMenu.extend(contextMenu)
|
||||||
HistorycontextMenu.append(
|
HistorycontextMenu.append(
|
||||||
(self.localize('Clear %s') % self.localize('Search History'), ListString % ('History', 'clear', 'addtime', '')))
|
(self.localize('Clear %s') % self.localize('Search History'),
|
||||||
self.drawItem('< %s >' % self.localize('Search History'), 'History',
|
ListString % ('History', 'clear', 'addtime', '')))
|
||||||
image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
|
if self.searchwindowmode == 1:
|
||||||
self.drawItem('< %s >' % self.localize('Search'), 'search', image=self.ROOT + '/icons/search.png', )
|
self.drawItem('< %s >' % self.localize('Search History'), 'swHistory',
|
||||||
|
image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
|
||||||
|
else:
|
||||||
|
self.drawItem('< %s >' % self.localize('Search History'), 'History',
|
||||||
|
image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
|
||||||
|
|
||||||
|
#Search
|
||||||
|
if self.searchwindowmode == 1:
|
||||||
|
self.drawItem('< %s >' % self.localize('Search'), 'swsearch', image=self.ROOT + '/icons/search.png',)
|
||||||
|
elif self.searchwindowmode > 1:
|
||||||
|
self.drawItem('< %s >' % self.localize('Search'), 'search', image=self.ROOT + '/icons/search.png', )
|
||||||
|
|
||||||
|
#Media
|
||||||
CLcontextMenu=[]
|
CLcontextMenu=[]
|
||||||
CLcontextMenu.extend(contextMenu)
|
CLcontextMenu.extend(contextMenu)
|
||||||
CLcontextMenu.append((self.localize('Reset All Cache DBs'),
|
CLcontextMenu.append((self.localize('Reset All Cache DBs'),
|
||||||
ListString % ('full_download', '', 'url', json.dumps({'action': 'delete'}))))
|
ListString % ('full_download', '', 'url', json.dumps({'action': 'delete'}))))
|
||||||
self.drawItem('< %s >' % self.localize('Content Lists'), 'openContent', image=self.ROOT + '/icons/media.png',
|
self.drawItem('< %s >' % self.localize('Content Lists'), 'openContent', image=self.ROOT + '/icons/media.png',
|
||||||
contextMenu=CLcontextMenu, replaceMenu=False)
|
contextMenu=CLcontextMenu, replaceMenu=False)
|
||||||
|
|
||||||
|
#DL Status
|
||||||
DLScontextMenu=[(self.localize('Start All'), ListString % ('DownloadStatus', 'startall', 'addtime', '')),
|
DLScontextMenu=[(self.localize('Start All'), ListString % ('DownloadStatus', 'startall', 'addtime', '')),
|
||||||
(self.localize('Stop All'), ListString % ('DownloadStatus', 'stopall', 'addtime', '')),]
|
(self.localize('Stop All'), ListString % ('DownloadStatus', 'stopall', 'addtime', '')),]
|
||||||
DLScontextMenu.append(
|
DLScontextMenu.append(
|
||||||
(self.localize('Clear %s') % self.localize('Download Status'), ListString % ('DownloadStatus', 'clear', 'addtime', '')))
|
(self.localize('Clear %s') % self.localize('Download Status'), ListString % ('DownloadStatus', 'clear', 'addtime', '')))
|
||||||
DLScontextMenu.extend(contextMenu)
|
DLScontextMenu.extend(contextMenu)
|
||||||
self.drawItem('< %s >' % self.localize('Download Status'), 'DownloadStatus', image=self.ROOT + '/icons/download.png',
|
|
||||||
contextMenu=DLScontextMenu, replaceMenu=False)
|
if self.searchwindowmode == 1:
|
||||||
self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'uTorrentBrowser',
|
self.drawItem('< %s >' % self.localize('Download Status'), 'swDownloadStatus',
|
||||||
image=self.ROOT + '/icons/' + self.getTorrentClientIcon())
|
image=self.ROOT + '/icons/download.png',
|
||||||
if self.history_bool:
|
contextMenu=DLScontextMenu, replaceMenu=False)
|
||||||
|
elif self.searchwindowmode > 1:
|
||||||
|
self.drawItem('< %s >' % self.localize('Download Status'), 'DownloadStatus',
|
||||||
|
image=self.ROOT + '/icons/download.png',
|
||||||
|
contextMenu=DLScontextMenu, replaceMenu=False)
|
||||||
|
|
||||||
|
#Torrent-client
|
||||||
|
if self.searchwindowmode == 1:
|
||||||
|
self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'swuTorrentBrowser',
|
||||||
|
image=self.ROOT + '/icons/' + getTorrentClientIcon())
|
||||||
|
elif self.searchwindowmode > 1:
|
||||||
|
self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'uTorrentBrowser',
|
||||||
|
image=self.ROOT + '/icons/' + getTorrentClientIcon())
|
||||||
|
|
||||||
|
#Watched
|
||||||
|
if self.history_bool and self.searchwindowmode > 0:
|
||||||
WatchedHistorycontextMenu=[]
|
WatchedHistorycontextMenu=[]
|
||||||
WatchedHistorycontextMenu.extend(contextMenu)
|
WatchedHistorycontextMenu.extend(contextMenu)
|
||||||
WatchedHistorycontextMenu.append(
|
WatchedHistorycontextMenu.append(
|
||||||
(self.localize('Clear %s') % self.localize('Watched History'), ListString % ('WatchedHistory', 'clear', 'addtime', '')))
|
(self.localize('Clear %s') % self.localize('Watched History'), ListString % ('WatchedHistory', 'clear', 'addtime', '')))
|
||||||
self.drawItem('< %s >' % self.localize('Watched History'), 'WatchedHistory',
|
if self.searchwindowmode == 1:
|
||||||
image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu, replaceMenu=False)
|
self.drawItem('< %s >' % self.localize('Watched History'), 'swWatchedHistory',
|
||||||
|
image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu,
|
||||||
|
replaceMenu=False)
|
||||||
|
else:
|
||||||
|
self.drawItem('< %s >' % self.localize('Watched History'), 'WatchedHistory',
|
||||||
|
image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu,
|
||||||
|
replaceMenu=False)
|
||||||
|
|
||||||
|
#Torr player
|
||||||
self.drawItem('< %s >' % self.localize('.torrent Player'), 'torrentPlayer',
|
self.drawItem('< %s >' % self.localize('.torrent Player'), 'torrentPlayer',
|
||||||
image=self.ROOT + '/icons/torrentPlayer.png')
|
image=self.ROOT + '/icons/torrentPlayer.png', isFolder = False)
|
||||||
|
|
||||||
|
#Search Control Window
|
||||||
self.drawItem('< %s >' % self.localize('Search Control Window'), 'controlCenter',
|
self.drawItem('< %s >' % self.localize('Search Control Window'), 'controlCenter',
|
||||||
image=self.ROOT + '/icons/settings.png', isFolder=False)
|
image=self.ROOT + '/icons/settings.png', isFolder=False)
|
||||||
|
|
||||||
|
#Magnet player
|
||||||
self.drawItem('< %s >' % self.localize('Magnet-link Player'), 'magentPlayer',
|
self.drawItem('< %s >' % self.localize('Magnet-link Player'), 'magentPlayer',
|
||||||
image=self.ROOT + '/icons/magnet.png')
|
image=self.ROOT + '/icons/magnet.png', isFolder = False)
|
||||||
|
|
||||||
|
#Debug
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.drawItem('full_download', 'full_download', image=self.ROOT + '/icons/magnet.png')
|
self.drawItem('full_download', 'full_download', image=self.ROOT + '/icons/magnet.png')
|
||||||
self.drawItem('test', 'test', image=self.ROOT + '/icons/magnet.png', isFolder=False)
|
self.drawItem('test', 'test', image=self.ROOT + '/icons/magnet.png', isFolder=False)
|
||||||
|
|
||||||
|
#Clear storage
|
||||||
if '0' != self.__settings__.getSetting("keep_files"):
|
if '0' != self.__settings__.getSetting("keep_files"):
|
||||||
self.drawItem('< %s >' % self.localize('Clear Storage'), 'clearStorage', isFolder=True,
|
self.drawItem('< %s >' % self.localize('Clear Storage'), 'clearStorage', isFolder=True,
|
||||||
image=self.ROOT + '/icons/clear.png')
|
image=self.ROOT + '/icons/clear.png')
|
||||||
|
|
||||||
view_style('sectionMenu')
|
view_style('sectionMenu')
|
||||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
||||||
|
|
||||||
|
@ -239,54 +296,42 @@ class Core:
|
||||||
lockView('wide')
|
lockView('wide')
|
||||||
|
|
||||||
def test(self, params={}):
|
def test(self, params={}):
|
||||||
#from Anteoloader import AnteoPlayer
|
pass
|
||||||
#from python_libtorrent import get_libtorrent
|
import searchwindow
|
||||||
#self.lt=get_libtorrent()
|
params = {'mode': 'file_browser', 'path':'D:\\', 'tdir':'D:\\FRAPS\\'}
|
||||||
#self.torrentFile='D:\\test.torrent'
|
searchwindow.main(params)
|
||||||
#self.session = self.lt.session()
|
|
||||||
#e=self.lt.bdecode(xbmcvfs.File(self.torrentFile,'rb').read())
|
|
||||||
#self.torrentFileInfo = self.lt.torrent_info(e)
|
|
||||||
#torrent_info={'ti': self.torrentFileInfo,
|
|
||||||
# 'save_path': self.userStorageDirectory,
|
|
||||||
# 'flags': 0x300,
|
|
||||||
# #'storage_mode': self.lt.storage_mode_t(1),
|
|
||||||
# 'paused': False,
|
|
||||||
# #'auto_managed': False,
|
|
||||||
# #'duplicate_is_error': True
|
|
||||||
# }
|
|
||||||
#self.torrentHandle = self.session.add_torrent(torrent_info)
|
|
||||||
#log(self.torrentHandle.torrent_file())
|
|
||||||
#self.session.remove_torrent(self.torrentHandle)
|
|
||||||
|
|
||||||
#params['url']='0'
|
def swHistory(self, params={}):
|
||||||
#if not xbmcvfs.exists(torrentUrl):
|
import searchwindow
|
||||||
# action = xbmcgui.Dialog()
|
params = {'mode': 'history'}
|
||||||
# torrentUrl = action.browse(1, self.localize('Choose .torrent in video library'), 'video', '.torrent')
|
searchwindow.main(params)
|
||||||
#if torrentUrl and xbmcvfs.exists(torrentUrl):
|
|
||||||
# if 0 != len(torrentUrl):
|
|
||||||
# self.Downloader = Downloader.Torrent(self.userStorageDirectory, torrentUrl)
|
|
||||||
# else:
|
|
||||||
# log(self.__plugin__ + " Unexpected access to method Anteoloader() without torrent content")
|
|
||||||
#if self.Downloader:
|
|
||||||
# x=self.Downloader.getContentList()
|
|
||||||
# print str(x)
|
|
||||||
# xbmc.sleep(1000)
|
|
||||||
# self.Downloader.__exit__()
|
|
||||||
#self.Player = AnteoPlayer(userStorageDirectory=self.userStorageDirectory, torrentUrl=torrentUrl, params=params)
|
|
||||||
|
|
||||||
#xbmcgui.Dialog().ok('Dam Son!','Now send this shit to DiMartino')
|
def swDownloadStatus(self, params={}):
|
||||||
from resources.proxy import antizapret
|
import searchwindow
|
||||||
filename = os.path.join(tempdir(),"antizapret.pac_config")
|
params = {'mode': 'downloadstatus'}
|
||||||
import shelve
|
searchwindow.main(params)
|
||||||
from contextlib import contextmanager, closing
|
|
||||||
with closing(shelve.open(filename, writeback=True)) as d:
|
def swuTorrentBrowser(self, params={}):
|
||||||
import time
|
import searchwindow
|
||||||
log(str(d))
|
params = {'mode': 'browser'}
|
||||||
log(str(time.time()))
|
searchwindow.main(params)
|
||||||
log(str((time.time() - d["created_at"])))
|
|
||||||
ttl = 24*3600
|
def swWatchedHistory(self, params={}):
|
||||||
if ttl > 0 and (time.time() - d["created_at"]) > ttl:
|
import searchwindow
|
||||||
log('xxx')
|
params = {'mode': 'watched'}
|
||||||
|
searchwindow.main(params)
|
||||||
|
|
||||||
|
def swsearch(self, params={}):
|
||||||
|
if len(Searchers().get_active())<1:
|
||||||
|
noActiveSerachers()
|
||||||
|
return
|
||||||
|
keyboard = xbmc.Keyboard('', self.localize('Search Phrase'))
|
||||||
|
keyboard.doModal()
|
||||||
|
params["query"] = keyboard.getText()
|
||||||
|
if keyboard.isConfirmed():
|
||||||
|
params["mode"] = 'search'
|
||||||
|
import searchwindow
|
||||||
|
searchwindow.main(params)
|
||||||
|
|
||||||
def DownloadStatus(self, params={}):
|
def DownloadStatus(self, params={}):
|
||||||
db = DownloadDB()
|
db = DownloadDB()
|
||||||
|
@ -419,8 +464,6 @@ class Core:
|
||||||
self.drawItem(title, 'DownloadStatus', link, image=img, contextMenu=contextMenu, replaceMenu=False)
|
self.drawItem(title, 'DownloadStatus', link, image=img, contextMenu=contextMenu, replaceMenu=False)
|
||||||
view_style('DownloadStatus')
|
view_style('DownloadStatus')
|
||||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
||||||
#xbmc.sleep(30000)
|
|
||||||
#xbmc.executebuiltin('Container.Refresh')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def History(self, params={}):
|
def History(self, params={}):
|
||||||
|
@ -521,7 +564,7 @@ class Core:
|
||||||
self.__settings__.setSetting("lastTorrent", path)
|
self.__settings__.setSetting("lastTorrent", path)
|
||||||
xbmc.executebuiltin(
|
xbmc.executebuiltin(
|
||||||
'XBMC.ActivateWindow(%s)' % 'Videos,plugin://plugin.video.torrenter/?action=%s&url=%s'
|
'XBMC.ActivateWindow(%s)' % 'Videos,plugin://plugin.video.torrenter/?action=%s&url=%s'
|
||||||
% ('torrentPlayer', path))
|
% ('torrentPlayer', path.encode('utf-8')))
|
||||||
|
|
||||||
if action2 == 'playnoseek' or action2 == 'playwithseek':
|
if action2 == 'playnoseek' or action2 == 'playwithseek':
|
||||||
filename, path, url, seek, length, ind = db.get('filename, path, url, seek, length, ind', 'addtime', str(addtime))
|
filename, path, url, seek, length, ind = db.get('filename, path, url, seek, length, ind', 'addtime', str(addtime))
|
||||||
|
@ -551,7 +594,7 @@ class Core:
|
||||||
#for favbool, bbstring in favlist:
|
#for favbool, bbstring in favlist:
|
||||||
for addtime, filename, foldername, path, url, seek, length, ind, size in items:
|
for addtime, filename, foldername, path, url, seek, length, ind, size in items:
|
||||||
seek = int(seek) if int(seek) > 3*60 else 0
|
seek = int(seek) if int(seek) > 3*60 else 0
|
||||||
watchedPercent = int((float(seek) / float(length)) * 100)
|
watchedPercent = int((float(seek) / float(length if length else 1)) * 100)
|
||||||
duration = '%02d:%02d:%02d' % ((length / (60*60)), (length / 60) % 60, length % 60)
|
duration = '%02d:%02d:%02d' % ((length / (60*60)), (length / 60) % 60, length % 60)
|
||||||
title = '[%d%%][%s] %s [%d MB]' %\
|
title = '[%d%%][%s] %s [%d MB]' %\
|
||||||
(watchedPercent, duration, filename.encode('utf-8'), int(size))
|
(watchedPercent, duration, filename.encode('utf-8'), int(size))
|
||||||
|
@ -725,6 +768,19 @@ class Core:
|
||||||
else:
|
else:
|
||||||
if provider:
|
if provider:
|
||||||
self.Content = self.contenterObject[provider]
|
self.Content = self.contenterObject[provider]
|
||||||
|
if category == 'search' and provider and subcategory == True:
|
||||||
|
keyboard = xbmc.Keyboard('', self.localize('Search Phrase') + ':')
|
||||||
|
keyboard.doModal()
|
||||||
|
query = keyboard.getText()
|
||||||
|
if not query:
|
||||||
|
return
|
||||||
|
elif keyboard.isConfirmed():
|
||||||
|
subcategory = query
|
||||||
|
if subcategory:
|
||||||
|
apps['subcategory'] = subcategory.decode('utf-8')
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
if not self.Content.isTracker():
|
if not self.Content.isTracker():
|
||||||
self.draw(apps, mode='content')
|
self.draw(apps, mode='content')
|
||||||
else:
|
else:
|
||||||
|
@ -740,6 +796,7 @@ class Core:
|
||||||
page = apps.get('page') if apps.get('page') else 1
|
page = apps.get('page') if apps.get('page') else 1
|
||||||
sort = apps.get('sort') if apps.get('sort') else 0
|
sort = apps.get('sort') if apps.get('sort') else 0
|
||||||
apps_property={'page':page, 'sort':sort}
|
apps_property={'page':page, 'sort':sort}
|
||||||
|
log('draw: '+str((category, subcategory)))
|
||||||
property = self.Content.get_property(category, subcategory)
|
property = self.Content.get_property(category, subcategory)
|
||||||
contentList = self.Content.get_contentList(category, subcategory, apps_property)
|
contentList = self.Content.get_contentList(category, subcategory, apps_property)
|
||||||
if property and property.get('page'):
|
if property and property.get('page'):
|
||||||
|
@ -895,7 +952,7 @@ class Core:
|
||||||
|
|
||||||
progressBar.update(iterator, dialogText, title, scrapers[scraper])
|
progressBar.update(iterator, dialogText, title, scrapers[scraper])
|
||||||
meta = self.Scraper.scraper(scraper, {'label': title, 'search': search, 'year': year}, self.language)
|
meta = self.Scraper.scraper(scraper, {'label': title, 'search': search, 'year': year}, self.language)
|
||||||
#print 'meta:'+str(meta)
|
log('meta:'+str(meta))
|
||||||
if self.language == 'ru':
|
if self.language == 'ru':
|
||||||
if not meta.get('info').get('title') or \
|
if not meta.get('info').get('title') or \
|
||||||
not meta.get('properties').get('fanart_image') or not meta.get('icon'):
|
not meta.get('properties').get('fanart_image') or not meta.get('icon'):
|
||||||
|
@ -991,7 +1048,7 @@ class Core:
|
||||||
title = title.encode('utf-8', 'ignore')
|
title = title.encode('utf-8', 'ignore')
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
label = info.get('label').encode('utf-8', 'ignore')
|
log(str(info))
|
||||||
|
|
||||||
if info.get('link'):
|
if info.get('link'):
|
||||||
if isinstance(info.get('link'), tuple):
|
if isinstance(info.get('link'), tuple):
|
||||||
|
@ -1112,7 +1169,7 @@ class Core:
|
||||||
images = {'icon':image, 'thumb':image}
|
images = {'icon':image, 'thumb':image}
|
||||||
images = {'icon': image, 'thumb': image,
|
images = {'icon': image, 'thumb': image,
|
||||||
'poster': image, 'banner': image,
|
'poster': image, 'banner': image,
|
||||||
'fanart': image, 'landscape': image,
|
#'fanart': image, 'landscape': image,
|
||||||
#'clearart': image, 'clearlogo': image,
|
#'clearart': image, 'clearlogo': image,
|
||||||
}
|
}
|
||||||
listitem.setArt(images)
|
listitem.setArt(images)
|
||||||
|
@ -1148,14 +1205,14 @@ class Core:
|
||||||
contextMenu = [(self.localize('Search Control Window'),
|
contextMenu = [(self.localize('Search Control Window'),
|
||||||
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))]
|
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))]
|
||||||
replaceMenu = False
|
replaceMenu = False
|
||||||
if contextMenu:
|
|
||||||
listitem.addContextMenuItems(contextMenu, replaceItems=replaceMenu)
|
|
||||||
if isFolder:
|
if isFolder:
|
||||||
listitem.setProperty("Folder", "true")
|
listitem.setProperty("Folder", "true")
|
||||||
listitem.setInfo(type='Video', infoLabels=info)
|
listitem.setInfo(type='Video', infoLabels=info)
|
||||||
else:
|
else:
|
||||||
listitem.setInfo(type='Video', infoLabels=info)
|
listitem.setInfo(type='Video', infoLabels=info)
|
||||||
listitem.setArt({'thumb': image})
|
listitem.setArt({'thumb': image})
|
||||||
|
if contextMenu:
|
||||||
|
listitem.addContextMenuItems(contextMenu, replaceItems=replaceMenu)
|
||||||
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=listitem, isFolder=isFolder)
|
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=listitem, isFolder=isFolder)
|
||||||
|
|
||||||
def getParameters(self, parameterString):
|
def getParameters(self, parameterString):
|
||||||
|
@ -1233,7 +1290,7 @@ class Core:
|
||||||
filename = os.path.join(folder, filename)
|
filename = os.path.join(folder, filename)
|
||||||
xbmc.executebuiltin('xbmc.PlayMedia("' + filename.encode('utf-8') + '")')
|
xbmc.executebuiltin('xbmc.PlayMedia("' + filename.encode('utf-8') + '")')
|
||||||
elif tdir and action == 'copy':
|
elif tdir and action == 'copy':
|
||||||
path=os.path.join(folder, tdir)
|
path = os.path.join(localize_path(folder), localize_path(tdir))
|
||||||
dirs, files=xbmcvfs.listdir(path)
|
dirs, files=xbmcvfs.listdir(path)
|
||||||
if len(dirs) > 0:
|
if len(dirs) > 0:
|
||||||
dirs.insert(0, self.localize('./ (Root folder)'))
|
dirs.insert(0, self.localize('./ (Root folder)'))
|
||||||
|
@ -1248,9 +1305,10 @@ class Core:
|
||||||
path=os.path.join(path, dirs[ret])
|
path=os.path.join(path, dirs[ret])
|
||||||
dirs, files=xbmcvfs.listdir(path)
|
dirs, files=xbmcvfs.listdir(path)
|
||||||
for file in files:
|
for file in files:
|
||||||
if not xbmcvfs.exists(os.path.join(path,file)):
|
file = localize_path(file)
|
||||||
xbmcvfs.delete(os.path.join(path,file))
|
if not xbmcvfs.exists(os.path.join(path, file)):
|
||||||
xbmcvfs.copy(os.path.join(path,file),os.path.join(folder,file))
|
xbmcvfs.delete(os.path.join(path, file))
|
||||||
|
xbmcvfs.copy(os.path.join(path, file),os.path.join(folder, file))
|
||||||
i=i+1
|
i=i+1
|
||||||
showMessage(self.localize('Torrent-client Browser'), self.localize('Copied %d files!') % i, forced=True)
|
showMessage(self.localize('Torrent-client Browser'), self.localize('Copied %d files!') % i, forced=True)
|
||||||
return
|
return
|
||||||
|
@ -1365,7 +1423,6 @@ class Core:
|
||||||
params["url"] = urllib.quote_plus(unescape(urllib.unquote_plus(query)))
|
params["url"] = urllib.quote_plus(unescape(urllib.unquote_plus(query)))
|
||||||
else:
|
else:
|
||||||
params["url"] = urllib.quote_plus(unescape(urllib.unquote_plus(defaultKeyword)))
|
params["url"] = urllib.quote_plus(unescape(urllib.unquote_plus(defaultKeyword)))
|
||||||
#print str(params)
|
|
||||||
self.torrentPlayer(params)
|
self.torrentPlayer(params)
|
||||||
|
|
||||||
def torrentPlayer(self, params={}):
|
def torrentPlayer(self, params={}):
|
||||||
|
@ -1376,13 +1433,22 @@ class Core:
|
||||||
if not url:
|
if not url:
|
||||||
action = xbmcgui.Dialog()
|
action = xbmcgui.Dialog()
|
||||||
url = action.browse(1, self.localize('Choose .torrent in video library'), 'video', '.torrent')
|
url = action.browse(1, self.localize('Choose .torrent in video library'), 'video', '.torrent')
|
||||||
|
torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
|
||||||
|
self.__settings__.setSetting("lastTorrent", torrent.saveTorrent(url))
|
||||||
|
self.__settings__.setSetting("lastTorrentUrl", url)
|
||||||
if url:
|
if url:
|
||||||
|
xbmc.executebuiltin("Dialog.Close(all,true)")
|
||||||
xbmc.executebuiltin(
|
xbmc.executebuiltin(
|
||||||
'XBMC.ActivateWindow(%s)' % 'Videos,plugin://plugin.video.torrenter/?action=%s&url=%s'
|
'XBMC.ActivateWindow(%s)' % 'Videos,plugin://plugin.video.torrenter/?action=%s&url=%s'
|
||||||
% ('torrentPlayer', url))
|
% ('torrentPlayer', url))
|
||||||
return
|
return
|
||||||
if url:
|
if url:
|
||||||
self.openTorrent(params)
|
if self.searchwindowmode > 1:
|
||||||
|
self.openTorrent(params)
|
||||||
|
else:
|
||||||
|
import searchwindow
|
||||||
|
params = {'mode': 'open_torrent', 'link': url}
|
||||||
|
searchwindow.main(params)
|
||||||
|
|
||||||
def userStorage(self, params):
|
def userStorage(self, params):
|
||||||
save=False
|
save=False
|
||||||
|
@ -1409,7 +1475,14 @@ class Core:
|
||||||
self.userStorageDirectory=dirname
|
self.userStorageDirectory=dirname
|
||||||
|
|
||||||
def playTorrent(self, params={}):
|
def playTorrent(self, params={}):
|
||||||
torrentUrl = self.__settings__.getSetting("lastTorrent")
|
if params.get('filename'):
|
||||||
|
torrentUrl = unquote(params.get('filename'))
|
||||||
|
else:
|
||||||
|
torrentUrl = self.__settings__.getSetting("lastTorrent")
|
||||||
|
#xbmc.executebuiltin('Action(Stop)')
|
||||||
|
if self.torrent_player != '1' and params.get('external') == '1' and not params.get('seek'):
|
||||||
|
params['seek'] = watched_seek(torrentUrl, params['url'])
|
||||||
|
|
||||||
self.userStorage(params)
|
self.userStorage(params)
|
||||||
if self.torrent_player == '0':
|
if self.torrent_player == '0':
|
||||||
from Player import TorrentPlayer
|
from Player import TorrentPlayer
|
||||||
|
@ -1434,9 +1507,9 @@ class Core:
|
||||||
#xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.yatp/?action=play&torrent=%s&file_index=%s")' % (urllib.quote_plus(torrentUrl), params['url']))
|
#xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.yatp/?action=play&torrent=%s&file_index=%s")' % (urllib.quote_plus(torrentUrl), params['url']))
|
||||||
elif self.torrent_player == '1':
|
elif self.torrent_player == '1':
|
||||||
__ASsettings__ = xbmcaddon.Addon(id='script.module.torrent.ts')
|
__ASsettings__ = xbmcaddon.Addon(id='script.module.torrent.ts')
|
||||||
folder=__ASsettings__.getSetting("folder")
|
folder=__ASsettings__.getSetting("path")
|
||||||
save=__ASsettings__.getSetting("save")
|
save=__ASsettings__.getSetting("save")
|
||||||
__ASsettings__.setSetting("folder", self.__settings__.getSetting("storage"))
|
__ASsettings__.setSetting("path", xbmc.translatePath(self.__settings__.getSetting("storage")))
|
||||||
__ASsettings__.setSetting("save", self.__settings__.getSetting("keep_files"))
|
__ASsettings__.setSetting("save", self.__settings__.getSetting("keep_files"))
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
torrent = Downloader.Torrent(self.userStorageDirectory, torrentUrl, self.torrentFilesDirectory)
|
torrent = Downloader.Torrent(self.userStorageDirectory, torrentUrl, self.torrentFilesDirectory)
|
||||||
|
@ -1447,7 +1520,7 @@ class Core:
|
||||||
label = unquote(get("label"), os.path.basename(path))
|
label = unquote(get("label"), os.path.basename(path))
|
||||||
torrent.play_url_ind(int(ind), label, icon)
|
torrent.play_url_ind(int(ind), label, icon)
|
||||||
torrent.__exit__()
|
torrent.__exit__()
|
||||||
__ASsettings__.setSetting("folder", folder)
|
__ASsettings__.setSetting("path", folder)
|
||||||
__ASsettings__.setSetting("save", save)
|
__ASsettings__.setSetting("save", save)
|
||||||
|
|
||||||
def saveUrlTorrent(self, url):
|
def saveUrlTorrent(self, url):
|
||||||
|
@ -1477,14 +1550,29 @@ class Core:
|
||||||
get = params.get
|
get = params.get
|
||||||
xbmc.executebuiltin('xbmc.Playlist.Clear')
|
xbmc.executebuiltin('xbmc.Playlist.Clear')
|
||||||
url = unquote(get("url"), None)
|
url = unquote(get("url"), None)
|
||||||
fileIndex = unquote(get("index"), None)
|
url2 = unquote(get("url2"), None)
|
||||||
|
index = unquote(get("index"), None)
|
||||||
if url:
|
if url:
|
||||||
self.__settings__.setSetting("lastTorrentUrl", url)
|
self.__settings__.setSetting("lastTorrentUrl", url)
|
||||||
|
classMatch = re.search('(\w+)::(.+)', url)
|
||||||
|
if classMatch:
|
||||||
|
searcher = classMatch.group(1)
|
||||||
|
url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
|
||||||
torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
|
torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
|
||||||
self.__settings__.setSetting("lastTorrent", torrent.saveTorrent(url))
|
filename = torrent.saveTorrent(url)
|
||||||
if fileIndex==None: fileIndex = chooseFile(torrent.getContentList())
|
self.__settings__.setSetting("lastTorrent", filename)
|
||||||
if fileIndex:
|
if index == None: index = chooseFile(torrent.getContentList())
|
||||||
xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.torrenter/?action=playTorrent&url='+fileIndex+'")')
|
if index:
|
||||||
|
#params = {'url': index, 'filename': filename}
|
||||||
|
#if url2: params['url2'] = url2
|
||||||
|
#self.playTorrent(params)
|
||||||
|
|
||||||
|
url = 'plugin://plugin.video.torrenter/?action=playTorrent'
|
||||||
|
url += '&url=%s' % (str(index))
|
||||||
|
if url2: url += '&url2=%s' % (url2)
|
||||||
|
if filename: url += '&filename=%s' % (urllib.quote_plus(ensure_str(filename)))
|
||||||
|
|
||||||
|
xbmc.executebuiltin('xbmc.RunPlugin("%s")' % (url))
|
||||||
|
|
||||||
def openTorrent(self, params={}):
|
def openTorrent(self, params={}):
|
||||||
get = params.get
|
get = params.get
|
||||||
|
@ -1503,7 +1591,8 @@ class Core:
|
||||||
torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
|
torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
|
||||||
if not torrent: torrent = Downloader.Torrent(self.userStorageDirectory,
|
if not torrent: torrent = Downloader.Torrent(self.userStorageDirectory,
|
||||||
torrentFilesDirectory=self.torrentFilesDirectory)
|
torrentFilesDirectory=self.torrentFilesDirectory)
|
||||||
self.__settings__.setSetting("lastTorrent", torrent.saveTorrent(url))
|
filename = torrent.saveTorrent(url)
|
||||||
|
self.__settings__.setSetting("lastTorrent", filename)
|
||||||
|
|
||||||
append_filesize = self.__settings__.getSetting("append_filesize") == 'true'
|
append_filesize = self.__settings__.getSetting("append_filesize") == 'true'
|
||||||
hasSize = False
|
hasSize = False
|
||||||
|
@ -1539,9 +1628,11 @@ class Core:
|
||||||
'XBMC.RunPlugin(%s)' % ('%s?action=%s&ind=%s') % (
|
'XBMC.RunPlugin(%s)' % ('%s?action=%s&ind=%s') % (
|
||||||
sys.argv[0], 'downloadLibtorrent', str(identifier))),
|
sys.argv[0], 'downloadLibtorrent', str(identifier))),
|
||||||
]
|
]
|
||||||
link = {'url': identifier, 'thumbnail': thumbnail, 'save_folder':save_folder}
|
link = {'url': identifier, 'thumbnail': thumbnail, 'save_folder':save_folder,
|
||||||
|
'filename':ensure_str(filename)}
|
||||||
self.drawItem(title, 'playTorrent', link, image=thumbnail, isFolder=False,
|
self.drawItem(title, 'playTorrent', link, image=thumbnail, isFolder=False,
|
||||||
action2=ids_video.rstrip(','), contextMenu=contextMenu, replaceMenu=False, fileSize=filesize)
|
action2=ids_video.rstrip(','), contextMenu=contextMenu,
|
||||||
|
replaceMenu=False, fileSize=filesize)
|
||||||
view_style('openTorrent')
|
view_style('openTorrent')
|
||||||
p_handle = int(sys.argv[1])
|
p_handle = int(sys.argv[1])
|
||||||
try:
|
try:
|
||||||
|
@ -1598,6 +1689,10 @@ class Core:
|
||||||
xbmc.executebuiltin(
|
xbmc.executebuiltin(
|
||||||
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))
|
'xbmc.RunScript(%s,)' % os.path.join(ROOT, 'controlcenter.py'))
|
||||||
|
|
||||||
|
def searchWindow(self, params={}):
|
||||||
|
import searchwindow
|
||||||
|
searchwindow.main(params)
|
||||||
|
|
||||||
def showFilesList(self, filesList, params={}):
|
def showFilesList(self, filesList, params={}):
|
||||||
get = params.get
|
get = params.get
|
||||||
thumbnail = unquote(get("thumbnail"),'')
|
thumbnail = unquote(get("thumbnail"),'')
|
||||||
|
@ -1615,8 +1710,8 @@ class Core:
|
||||||
(self.localize('Download via Libtorrent'),
|
(self.localize('Download via Libtorrent'),
|
||||||
'XBMC.RunPlugin(%s)' % ('%s?action=%s&url=%s') % (
|
'XBMC.RunPlugin(%s)' % ('%s?action=%s&url=%s') % (
|
||||||
sys.argv[0], 'downloadLibtorrent', urllib.quote_plus(link))),
|
sys.argv[0], 'downloadLibtorrent', urllib.quote_plus(link))),
|
||||||
(self.localize('Open (no return)'),
|
(self.localize('Open'),
|
||||||
'XBMC.ActivateWindow(Videos,%s)' % ('%s?action=%s%s') % (
|
'XBMC.Container.Update(%s)' % ('%s?action=%s%s') % (
|
||||||
sys.argv[0], 'openTorrent', link_url)),
|
sys.argv[0], 'openTorrent', link_url)),
|
||||||
]
|
]
|
||||||
title = self.titleMake(seeds, leechers, size, title)
|
title = self.titleMake(seeds, leechers, size, title)
|
||||||
|
@ -1676,8 +1771,8 @@ class Core:
|
||||||
(self.localize('Add to %s') % return_name,
|
(self.localize('Add to %s') % return_name,
|
||||||
'XBMC.RunPlugin(%s)' % (back_url+'&stringdata=' + urllib.quote_plus(
|
'XBMC.RunPlugin(%s)' % (back_url+'&stringdata=' + urllib.quote_plus(
|
||||||
json.dumps(sdata)))),
|
json.dumps(sdata)))),
|
||||||
(self.localize('Open (no return)'),
|
(self.localize('Open'),
|
||||||
'XBMC.ActivateWindow(Videos,%s)' % ('%s?action=%s%s') % (
|
'XBMC.Container.Update(%s)' % ('%s?action=%s%s') % (
|
||||||
sys.argv[0], 'openTorrent', link_url)),
|
sys.argv[0], 'openTorrent', link_url)),
|
||||||
(self.localize('Return to %s') % return_name,
|
(self.localize('Return to %s') % return_name,
|
||||||
'XBMC.ActivateWindow(%s)' % ('Videos,%s' % return_url)),
|
'XBMC.ActivateWindow(%s)' % ('Videos,%s' % return_url)),
|
||||||
|
@ -1693,8 +1788,28 @@ class Core:
|
||||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
||||||
|
|
||||||
def context(self, params={}):
|
def context(self, params={}):
|
||||||
xbmc.executebuiltin("Action(ContextMenu)")
|
if not self.version_check():
|
||||||
return
|
xbmc.executebuiltin("Action(ContextMenu)")
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
fixed = xbmcgui.Dialog().contextmenu(list=[(self.localize('Open')),
|
||||||
|
(self.localize('Download via Libtorrent')),
|
||||||
|
(self.localize('Download via T-client'))])
|
||||||
|
if fixed == 0:
|
||||||
|
xbmc.executebuiltin('XBMC.Container.Update(%s)' %
|
||||||
|
('%s?action=%s&url=%s') %
|
||||||
|
(sys.argv[0], 'openTorrent', params['url']))
|
||||||
|
elif fixed == 1:
|
||||||
|
xbmc.executebuiltin('XBMC.RunPlugin(%s)' %
|
||||||
|
('%s?action=%s&url=%s') %
|
||||||
|
(sys.argv[0], 'downloadLibtorrent', params['url']))
|
||||||
|
elif fixed == 2:
|
||||||
|
xbmc.executebuiltin('XBMC.RunPlugin(%s)' %
|
||||||
|
('%s?action=%s&url=%s') %
|
||||||
|
(sys.argv[0], 'downloadFilesList', params['url']))
|
||||||
|
|
||||||
|
def version_check(self):
|
||||||
|
return False if int(xbmc.getInfoLabel( "System.BuildVersion" )[:2]) < 17 else True
|
||||||
|
|
||||||
def downloadFilesList(self, params={}):
|
def downloadFilesList(self, params={}):
|
||||||
from resources.utorrent.net import Download
|
from resources.utorrent.net import Download
|
||||||
|
@ -1765,11 +1880,19 @@ class Core:
|
||||||
f = open(url, 'rb')
|
f = open(url, 'rb')
|
||||||
torrent = f.read()
|
torrent = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
|
try:
|
||||||
|
from python_libtorrent import get_libtorrent
|
||||||
|
libtorrent = get_libtorrent()
|
||||||
|
info = libtorrent.torrent_info(libtorrent.bdecode(torrent))
|
||||||
|
name = info.name()
|
||||||
|
except:
|
||||||
|
log('get_libtorrent import error, name = None')
|
||||||
|
name = None
|
||||||
success = Download().add(torrent, dirname)
|
success = Download().add(torrent, dirname)
|
||||||
if success:
|
if success:
|
||||||
showMessage(self.localize('Torrent-client Browser'), self.localize('Added!'), forced=True)
|
showMessage(self.localize('Torrent-client Browser'), self.localize('Added!'), forced=True)
|
||||||
if ind:
|
if ind:
|
||||||
id = self.chooseHASH(Download().list())[0]
|
id = self.chooseHASH(Download().list(), name)[0]
|
||||||
Download().setprio(id, ind)
|
Download().setprio(id, ind)
|
||||||
|
|
||||||
def downloadLibtorrent(self, params={}):
|
def downloadLibtorrent(self, params={}):
|
||||||
|
@ -1803,7 +1926,6 @@ class Core:
|
||||||
int(self.__settings__.getSetting("download_limit")) * 1000000 / 8) #MBits/second
|
int(self.__settings__.getSetting("download_limit")) * 1000000 / 8) #MBits/second
|
||||||
torrent.downloadProcess(ind, encryption)
|
torrent.downloadProcess(ind, encryption)
|
||||||
showMessage(self.localize('Download Status'), self.localize('Added!'))
|
showMessage(self.localize('Download Status'), self.localize('Added!'))
|
||||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
|
|
||||||
|
|
||||||
def titleMake(self, seeds, leechers, size, title):
|
def titleMake(self, seeds, leechers, size, title):
|
||||||
|
|
||||||
|
@ -1815,13 +1937,21 @@ class Core:
|
||||||
clAliceblue = '[COLOR FFF0F8FF]%s[/COLOR]'
|
clAliceblue = '[COLOR FFF0F8FF]%s[/COLOR]'
|
||||||
clRed = '[COLOR FFFF0000]%s[/COLOR]'
|
clRed = '[COLOR FFFF0000]%s[/COLOR]'
|
||||||
|
|
||||||
title = title.replace('720p', '[B]720p[/B]')
|
title = title.replace('720p', '[B]720p[/B]').replace('1080p', '[B]1080p[/B]')
|
||||||
title = clWhite % title + chr(10)
|
|
||||||
second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers) + chr(10)
|
if self.torrent_info_style == 0:
|
||||||
space = ''
|
title = clWhite % title
|
||||||
for i in range(0, 180 - len(second)):
|
second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers)
|
||||||
space += ' '
|
title += ' ' + second
|
||||||
title += space + second
|
elif self.torrent_info_style == 1:
|
||||||
|
title = clWhite % title
|
||||||
|
second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers)
|
||||||
|
title = second + ' ' + title
|
||||||
|
elif self.torrent_info_style == 2:
|
||||||
|
title = clWhite % title
|
||||||
|
second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers)
|
||||||
|
title += '\r\n' + clDimgray % second
|
||||||
|
|
||||||
return title
|
return title
|
||||||
|
|
||||||
def search(self, params={}):
|
def search(self, params={}):
|
||||||
|
@ -1852,7 +1982,7 @@ class Core:
|
||||||
else:
|
else:
|
||||||
self.openSection(params)
|
self.openSection(params)
|
||||||
|
|
||||||
def chooseHASH(self, list):
|
def chooseHASH(self, list, name = None):
|
||||||
dialog_items, dialog_items_clean = [], []
|
dialog_items, dialog_items_clean = [], []
|
||||||
dialog_files = []
|
dialog_files = []
|
||||||
dat = list
|
dat = list
|
||||||
|
@ -1862,14 +1992,29 @@ class Core:
|
||||||
for data in dat:
|
for data in dat:
|
||||||
dialog_files.append((data['id'], data['dir'].encode('utf-8')))
|
dialog_files.append((data['id'], data['dir'].encode('utf-8')))
|
||||||
dialog_items.append('[' + str(data['progress']) + '%] ' + data['name'])
|
dialog_items.append('[' + str(data['progress']) + '%] ' + data['name'])
|
||||||
if len(dialog_items) > 1:
|
dialog_items_clean.append(data['name'])
|
||||||
ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items)
|
|
||||||
if ret > -1 and ret < len(dialog_files):
|
log('[chooseHASH]: name %s ' % str(name))
|
||||||
hash = dialog_files[ret]
|
for data in dat:
|
||||||
|
# Debug('[chooseHASH]: '+str((data['name'], data['id'], data['dir'].encode('utf-8'))))
|
||||||
|
dialog_files.append((data['id'], data['dir'].encode('utf-8')))
|
||||||
|
dialog_items.append('[' + str(data['progress']) + '%] ' + data['name'])
|
||||||
|
dialog_items_clean.append(data['name'])
|
||||||
|
|
||||||
|
if name:
|
||||||
|
if decode_str(name) in dialog_items_clean:
|
||||||
|
return dialog_files[dialog_items_clean.index(decode_str(name))]
|
||||||
|
elif name in dialog_items_clean:
|
||||||
|
return dialog_files[dialog_items_clean.index(name)]
|
||||||
|
else:
|
||||||
|
if len(dialog_items) > 1:
|
||||||
|
ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items)
|
||||||
|
if ret > -1 and ret < len(dialog_files):
|
||||||
|
hash = dialog_files[ret]
|
||||||
|
return hash
|
||||||
|
elif len(dialog_items) == 1:
|
||||||
|
hash = dialog_files[0]
|
||||||
return hash
|
return hash
|
||||||
elif len(dialog_items) == 1:
|
|
||||||
hash = dialog_files[0]
|
|
||||||
return hash
|
|
||||||
|
|
||||||
def localize(self, string):
|
def localize(self, string):
|
||||||
try:
|
try:
|
||||||
|
@ -1881,19 +2026,6 @@ class Core:
|
||||||
i=delete_russian(ok=True, action='return')
|
i=delete_russian(ok=True, action='return')
|
||||||
showMessage(self.localize('Return Russian stuff'),self.localize('%d files have been returned')%i)
|
showMessage(self.localize('Return Russian stuff'),self.localize('%d files have been returned')%i)
|
||||||
|
|
||||||
def getTorrentClientIcon(self):
|
|
||||||
client = self.__settings__.getSetting("torrent")
|
|
||||||
if client == '1':
|
|
||||||
return 'transmission.png'
|
|
||||||
elif client == '2':
|
|
||||||
return 'vuze.png'
|
|
||||||
elif client == '3':
|
|
||||||
return 'deluge.png'
|
|
||||||
elif client == '4':
|
|
||||||
return 'qbittorrent.png'
|
|
||||||
else:
|
|
||||||
return 'torrent-client.png'
|
|
||||||
|
|
||||||
def callback(self, params={}):
|
def callback(self, params={}):
|
||||||
get = params.get
|
get = params.get
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,9 @@ import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
|
import xbmcplugin
|
||||||
import Localization
|
import Localization
|
||||||
from functions import encode_msg, isSubtitle, is_writable, file_url
|
from functions import loadsw_onstop, isSubtitle, is_writable, file_url, localize_path
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -166,22 +167,14 @@ class InposLoader:
|
||||||
return self.torrentFile
|
return self.torrentFile
|
||||||
else:
|
else:
|
||||||
if not xbmcvfs.exists(self.torrentFilesPath): xbmcvfs.mkdirs(self.torrentFilesPath)
|
if not xbmcvfs.exists(self.torrentFilesPath): xbmcvfs.mkdirs(self.torrentFilesPath)
|
||||||
torrentFile = os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent')
|
torrentFile = localize_path(os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent'))
|
||||||
try:
|
try:
|
||||||
if not re.match("^http\:.+$", torrentUrl):
|
if not re.match("^[htps]+?://.+$|^://.+$", torrentUrl):
|
||||||
|
log('xbmcvfs.File for %s' % torrentUrl)
|
||||||
content = xbmcvfs.File(torrentUrl, "rb").read()
|
content = xbmcvfs.File(torrentUrl, "rb").read()
|
||||||
else:
|
else:
|
||||||
request = urllib2.Request(torrentUrl)
|
log('request for %s' % torrentUrl)
|
||||||
request.add_header('Referer', torrentUrl)
|
content = self.makeRequest(torrentUrl)
|
||||||
request.add_header('Accept-encoding', 'gzip')
|
|
||||||
result = urllib2.urlopen(request)
|
|
||||||
if result.info().get('Content-Encoding') == 'gzip':
|
|
||||||
buf = StringIO(result.read())
|
|
||||||
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
|
||||||
content = decomp.decompress(buf.getvalue())
|
|
||||||
else:
|
|
||||||
content = result.read()
|
|
||||||
|
|
||||||
localFile = xbmcvfs.File(torrentFile, "w+b")
|
localFile = xbmcvfs.File(torrentFile, "w+b")
|
||||||
localFile.write(content)
|
localFile.write(content)
|
||||||
localFile.close()
|
localFile.close()
|
||||||
|
@ -197,6 +190,29 @@ class InposLoader:
|
||||||
self.torrentFile = torrentFile
|
self.torrentFile = torrentFile
|
||||||
return self.torrentFile
|
return self.torrentFile
|
||||||
|
|
||||||
|
def makeRequest(self, torrentUrl):
|
||||||
|
torrentUrl = re.sub('^://', 'http://', torrentUrl)
|
||||||
|
x = re.search("://(.+?)/|://(.+?)$", torrentUrl)
|
||||||
|
if x:
|
||||||
|
baseurl = x.group(1) if x.group(1) else x.group(2)
|
||||||
|
else:
|
||||||
|
baseurl =''
|
||||||
|
|
||||||
|
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', 'http://%s/' % baseurl), ('Accept-encoding', 'gzip'), ]
|
||||||
|
|
||||||
|
opener = urllib2.build_opener()
|
||||||
|
opener.addheaders = headers
|
||||||
|
result = opener.open(torrentUrl)
|
||||||
|
if result.info().get('Content-Encoding') == 'gzip':
|
||||||
|
buf = StringIO(result.read())
|
||||||
|
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
||||||
|
content = decomp.decompress(buf.getvalue())
|
||||||
|
else:
|
||||||
|
content = result.read()
|
||||||
|
return content
|
||||||
|
|
||||||
def md5(self, string):
|
def md5(self, string):
|
||||||
hasher = hashlib.md5()
|
hasher = hashlib.md5()
|
||||||
try:
|
try:
|
||||||
|
@ -257,9 +273,12 @@ class InposPlayer(xbmc.Player):
|
||||||
while True:
|
while True:
|
||||||
log('['+author+'Player]: ************************************* GOING LOOP')
|
log('['+author+'Player]: ************************************* GOING LOOP')
|
||||||
if self.setup_play():
|
if self.setup_play():
|
||||||
|
WatchedHistoryDB().add(self.basename, self.torrentUrl,
|
||||||
|
foldername(self.getContentList()[self.contentId]['title']),
|
||||||
|
self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
||||||
self.setup_subs()
|
self.setup_subs()
|
||||||
self.loop()
|
self.loop()
|
||||||
WatchedHistoryDB().add(self.basename, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
WatchedHistoryDB().add(self.basename, self.torrentUrl, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
|
||||||
else:
|
else:
|
||||||
log('['+author+'Player]: ************************************* break')
|
log('['+author+'Player]: ************************************* break')
|
||||||
break
|
break
|
||||||
|
@ -295,7 +314,9 @@ class InposPlayer(xbmc.Player):
|
||||||
#else:
|
#else:
|
||||||
#if self.seeding: self.db_delete()
|
#if self.seeding: self.db_delete()
|
||||||
showMessage(self.localize('Information'),
|
showMessage(self.localize('Information'),
|
||||||
self.localize('Torrent downloading is stopped.'), forced=True)
|
self.localize('Torrent downloading is stopped.'))
|
||||||
|
|
||||||
|
loadsw_onstop() # Reload Search Window
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.next_contentId = False
|
self.next_contentId = False
|
||||||
|
@ -483,6 +504,10 @@ class InposPlayer(xbmc.Player):
|
||||||
self.display_name = label
|
self.display_name = label
|
||||||
log(self.display_name)
|
log(self.display_name)
|
||||||
|
|
||||||
|
if self.get('listitem'):
|
||||||
|
listitem = self.get('listitem')
|
||||||
|
listitem.setPath(url)
|
||||||
|
|
||||||
player = xbmc.Player()
|
player = xbmc.Player()
|
||||||
player.play(url, listitem)
|
player.play(url, listitem)
|
||||||
|
|
||||||
|
@ -541,7 +566,7 @@ class InposPlayer(xbmc.Player):
|
||||||
|
|
||||||
self.iterator = int(file_status.progress * 100)
|
self.iterator = int(file_status.progress * 100)
|
||||||
|
|
||||||
if pause and self.__settings__.getSetting("pause_onplay") == 'true':
|
if pause and (self.__settings__.getSetting("pause_onplay") == 'true') and (self.getTime() > 0):
|
||||||
pause = False
|
pause = False
|
||||||
xbmc.Player().pause()
|
xbmc.Player().pause()
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
|
@ -550,7 +575,7 @@ class InposPlayer(xbmc.Player):
|
||||||
int) and self.next_contentId != False:
|
int) and self.next_contentId != False:
|
||||||
self.engine.activate_file(self.next_contentId)
|
self.engine.activate_file(self.next_contentId)
|
||||||
showMessage(self.localize('Torrent Downloading'),
|
showMessage(self.localize('Torrent Downloading'),
|
||||||
self.localize('Starting download next episode!'), forced=True)
|
self.localize('Starting download next episode!'))
|
||||||
log('[loop]: next_contentId '+str(self.next_contentId)+str(isinstance(self.next_contentId, int)))
|
log('[loop]: next_contentId '+str(self.next_contentId)+str(isinstance(self.next_contentId, int)))
|
||||||
file_status = self.engine.file_status(self.next_contentId)
|
file_status = self.engine.file_status(self.next_contentId)
|
||||||
self.basename = self.display_name = os.path.basename(file_status.name)
|
self.basename = self.display_name = os.path.basename(file_status.name)
|
||||||
|
@ -587,7 +612,7 @@ class InposPlayer(xbmc.Player):
|
||||||
|
|
||||||
def _get_status_lines(self, s, f):
|
def _get_status_lines(self, s, f):
|
||||||
return [
|
return [
|
||||||
self.display_name.encode('utf-8'),
|
ensure_str(self.display_name),
|
||||||
"%.2f%% %s" % (f.progress * 100, self.localize(STATE_STRS[s.state])),
|
"%.2f%% %s" % (f.progress * 100, self.localize(STATE_STRS[s.state])),
|
||||||
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate, self.localize('kb/s'),
|
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate, self.localize('kb/s'),
|
||||||
s.upload_rate, self.localize('kb/s'),
|
s.upload_rate, self.localize('kb/s'),
|
||||||
|
|
545
Localization.py
|
@ -23,7 +23,7 @@ try:
|
||||||
|
|
||||||
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
||||||
|
|
||||||
language = ('en', 'ru', 'uk','he')[int(__settings__.getSetting("language"))]
|
language = ('en', 'ru', 'uk','he', 'es')[int(__settings__.getSetting("language"))]
|
||||||
except:
|
except:
|
||||||
language = 'ru'
|
language = 'ru'
|
||||||
|
|
||||||
|
@ -31,7 +31,266 @@ except:
|
||||||
|
|
||||||
def localize(text):
|
def localize(text):
|
||||||
dictionary = {
|
dictionary = {
|
||||||
'he': {
|
'es': {
|
||||||
|
'Seeds searching.': 'Búsqueda de fuentes',
|
||||||
|
'Please Wait': 'Espere',
|
||||||
|
'Information': 'Información',
|
||||||
|
'Torrent downloading is stopped.': 'Se detuvo la descarga del torrent',
|
||||||
|
'Search': 'Buscar',
|
||||||
|
'Seeds': 'Semillas',
|
||||||
|
'Peers': 'Pares',
|
||||||
|
'Materials are loading now.': 'Se están cargando los materiales',
|
||||||
|
'Search Phrase': 'Términos de búsqueda',
|
||||||
|
'Magnet-link is converting': 'Se está convirtiendo el enlace magnet',
|
||||||
|
'Error': 'Error',
|
||||||
|
'Your library out of date and can\'t save magnet-links.': 'Su colección está anticuada y no pueden guardarse enlaces magnet.',
|
||||||
|
'Bookmarks': 'Favoritos',
|
||||||
|
'Logout': 'Cerrar sesión',
|
||||||
|
'Login': 'Iniciar sesión',
|
||||||
|
'Recent Materials': 'Materiales recientes ',
|
||||||
|
'Register': 'Registrar',
|
||||||
|
'Bookmark': 'Favorito',
|
||||||
|
'Item successfully added to Bookmarks': 'El elemento se ha añadido a "Favoritos"',
|
||||||
|
'Item successfully removed from Bookmarks': 'El elemento se ha eliminado de "Favoritos"',
|
||||||
|
'Bookmark not added': 'No se ha añadido a "Favoritos"',
|
||||||
|
'Bookmark not removed': 'No se ha eliminado de "Favoritos"',
|
||||||
|
'Add To Bookmarks': 'Añadir a "Favoritos"',
|
||||||
|
'Remove From Bookmarks': 'Eliminar de "Favoritos"',
|
||||||
|
'Auth': 'Validación',
|
||||||
|
'Already logged in': 'Ya se había iniciado sesión',
|
||||||
|
'Input Email (for password recovery):': 'Introduzca correo electrónico (para recuperar contraseña):',
|
||||||
|
'Input Email:': 'Introduzca correo electrónico:',
|
||||||
|
'Input Password (6+ symbols):': 'Introduzca contraseña (más de 6 caracteres):',
|
||||||
|
'Input Password:': 'Introduzca contraseña',
|
||||||
|
'Login successfull': 'Se ha iniciado sesión',
|
||||||
|
'Login failed': 'Falló el inicio de sesión',
|
||||||
|
'User not logged in': 'El usuario no ha iniciado sesión',
|
||||||
|
'User successfully logged out': 'El usuario ha cerrado sesión',
|
||||||
|
'Preloaded: ': 'Carga previa: ',
|
||||||
|
'Do you want to STOP torrent downloading and seeding?': '¿Desea detener la descarga y dejar de compartir el torrent?',
|
||||||
|
'Torrent Downloading': 'Descarga de torrent',
|
||||||
|
'Auth expired, please relogin': 'Expiró la identificación. Vuelva a iniciar sesión',
|
||||||
|
'Storage': 'Almacén',
|
||||||
|
'Storage has been cleared': 'El almacén se ha vaciado',
|
||||||
|
'Clear Storage': 'Vaciar almacén',
|
||||||
|
'Popular': 'Popular',
|
||||||
|
'Views': 'Vistas',
|
||||||
|
'Uploading': 'Subiendo',
|
||||||
|
'Download': 'Descargar',
|
||||||
|
'Input symbols from CAPTCHA image:': 'Introduzca los caracteres que aparecen en la imagen:',
|
||||||
|
'Please, rate watched video:': 'Valore el vídeo que ha visto:',
|
||||||
|
'Bad': 'Malo',
|
||||||
|
'So-So': 'Regular',
|
||||||
|
'Good': 'Bueno',
|
||||||
|
'Ratings': 'Valoraciones',
|
||||||
|
'Rating': 'Valoración',
|
||||||
|
'Retry': 'Reintentar',
|
||||||
|
'%ds has left': 'Ha quedado %ds',
|
||||||
|
'File failed to play! Do you want to RETRY and buffer more?': 'Falló la reproducción del archivo. ¿Desea volver a intentarlo y aumentar el tamaño de búfer?',
|
||||||
|
'High Priority Files': 'Archivos de prioridad alta',
|
||||||
|
'Skip All Files': 'Omitir todos los archivos',
|
||||||
|
'Start': 'Iniciar',
|
||||||
|
'Stop': 'Detener',
|
||||||
|
'Play':'Reproducir',
|
||||||
|
'High Priority': 'Prioridad alta',
|
||||||
|
'Skip File': 'Omitir archivo',
|
||||||
|
'Remove': 'Eliminar',
|
||||||
|
'Remove with files': 'Eliminar con los archivos',
|
||||||
|
'Play File': 'Reproducir archivo',
|
||||||
|
'Start All Files': 'Iniciar todos los archivos',
|
||||||
|
'Stop All Files': 'Detener todos los archivos',
|
||||||
|
'Torrent-client Browser': 'Explorador de cliente de BitTorrent',
|
||||||
|
'Remote Torrent-client': 'Cliente de BitTorrent remoto',
|
||||||
|
'You didn\'t set up replacement path in setting.': 'No se ha establecido una ruta alternativa en "Ajustes".',
|
||||||
|
'For example /media/dl_torr/ to smb://SERVER/dl_torr/. Setup now?': 'Por ejemplo, /media/dl_torr/ a smb://SERVER/dl_torr/. ¿Desea establecerla ahora?',
|
||||||
|
'Manual Torrent-client Path Edit': 'Edición manual de la ruta del cliente de BitTorrent',
|
||||||
|
'Choose .torrent in video library': 'Seleccione archivo .torrent en la colección de vídeos',
|
||||||
|
'.torrent Player': 'Gestor de archivo .torrent',
|
||||||
|
'Choose directory:': 'Seleccionar directorio:',
|
||||||
|
'Starting download next episode!': 'Iniciando descarga de episodio siguiente',
|
||||||
|
'Choose in torrent-client:': 'Elija cliente torrent',
|
||||||
|
'Search Control Window': 'Control de búsquedas',
|
||||||
|
'Magnet-link (magnet:...)': 'Enlace magnet (magnet:...)',
|
||||||
|
'Not a magnet-link!': 'No es un enlace magnet',
|
||||||
|
'Magnet-link Player': 'Gestor de enlace magnet',
|
||||||
|
'UNKNOWN STATUS': 'ESTADO DESCONOCIDO',
|
||||||
|
'Checking preloaded files...': 'Comprobando archivos precargados...',
|
||||||
|
'Waiting for website response...': 'Esperando respuesta del sitio web...',
|
||||||
|
'Search and cache information for:': 'Buscar y almacenar datos para:',
|
||||||
|
'Open Torrent': 'Abrir torrent',
|
||||||
|
'Torrent list is empty.': 'La lista de torrents está en blanco',
|
||||||
|
'Content Lists': 'Listas de contenido',
|
||||||
|
'Canceled by User': 'Cancelado por el usuario',
|
||||||
|
'Do you want to search and cache full metadata + arts?': '¿Desea buscar y almacenar los metadatos y fan-arts completos?',
|
||||||
|
'This vastly decreases load speed, but you will be asked to download premade bases!': 'Esto reduce considerablemente la velocidad de carga. Pero se le solicitará descargar desde cero',
|
||||||
|
'Do you want to preload full metadata?': '¿Desea precargar los metadatos completos?',
|
||||||
|
'It is highly recommended!': 'Altamente recomendado',
|
||||||
|
'TV Shows': 'Series de televisión',
|
||||||
|
'Cartoons': 'Dibujos animados',
|
||||||
|
'Anime': 'Anime',
|
||||||
|
'Most Recent': 'Estrenos',
|
||||||
|
'Top 250 Movies': 'Las 250 mejores películas',
|
||||||
|
'Top All Time': 'Las mejores de todos los tiempos',
|
||||||
|
'by Genre': 'Por género',
|
||||||
|
'by Year': 'Por año',
|
||||||
|
'Action': 'Acción',
|
||||||
|
'Adventure': 'Aventuras',
|
||||||
|
'Animation': 'Animación',
|
||||||
|
'Biography': 'Biografías',
|
||||||
|
'Comedy': 'Comedia',
|
||||||
|
'Crime': 'Policiacas',
|
||||||
|
'Documentary': 'Documentales',
|
||||||
|
'Drama': 'Drama',
|
||||||
|
'Family': 'Todos los públicos',
|
||||||
|
'Fantasy': 'Fantásticas',
|
||||||
|
'Film-Noir': 'Cine negro',
|
||||||
|
'History': 'Historia',
|
||||||
|
'Horror': 'Terror',
|
||||||
|
'Music': 'Música',
|
||||||
|
'Musical': 'Musicales',
|
||||||
|
'Mystery': 'Misterio',
|
||||||
|
'Romance': 'Románticas',
|
||||||
|
'Sci-Fi': 'Ciencia ficción',
|
||||||
|
'Short': 'Cortos',
|
||||||
|
'Sport': 'Deportes',
|
||||||
|
'Thriller': 'Suspense',
|
||||||
|
'War': 'Bélicas',
|
||||||
|
'Western': 'Películas del Oeste',
|
||||||
|
'[B]by Site[/B]': '[B]Por sitio[/B]',
|
||||||
|
'Cartoons Series': 'Series de dibujos animados',
|
||||||
|
'Cartoons Short': 'Cortos de dibujos animados',
|
||||||
|
'Male': 'Hombre',
|
||||||
|
'Female': 'Mujer',
|
||||||
|
'Russia & USSR': 'Rusia & URSS',
|
||||||
|
'Next Page': 'Página siguiente',
|
||||||
|
'Previous Page': 'Página anterior',
|
||||||
|
'Russian Movies': 'Películas rusas',
|
||||||
|
'israeli Movies': 'Películas israelíes',
|
||||||
|
'hebdub movies': 'Películas dobladas al hebreo',
|
||||||
|
'Movies': 'Películas',
|
||||||
|
'High Resolution Movies': 'Películas en alta resolución',
|
||||||
|
'3D Movies': 'Películas en 3D',
|
||||||
|
'Movies [Bluray]': 'Películas en formato Blu-ray',
|
||||||
|
'Anime Film': 'Películas Anime',
|
||||||
|
'Anime Series': 'Series Anime',
|
||||||
|
'Can\'t download torrent, probably no seeds available.': 'No se puede descargar el torrent, probablemente no hay fuentes disponibles.',
|
||||||
|
'Personal List': 'Lista personal',
|
||||||
|
'Add to %s': 'Añadir a %s',
|
||||||
|
'Delete from %s': 'Eliminar de %s',
|
||||||
|
'Added!': 'Añadido',
|
||||||
|
'Deleted!': 'Eliminado',
|
||||||
|
'Search History': 'Historial de búsquedas',
|
||||||
|
' History ':' Historial ',
|
||||||
|
'Torrent History':'Historial de archivos torrent',
|
||||||
|
'Watched History':'Historial de vistos',
|
||||||
|
'Favourites': 'Favoritos',
|
||||||
|
'Favourites SH': 'Favoritos SH',
|
||||||
|
'Clear %s': 'Vaciar %s',
|
||||||
|
'Clear!': 'Vacío',
|
||||||
|
'kb/s': 'kbps',
|
||||||
|
'Queued': 'Situado en cola',
|
||||||
|
'Checking': 'Comprobando',
|
||||||
|
'Downloading metadata': 'Descargando metadatos',
|
||||||
|
'Downloading': 'Descargando',
|
||||||
|
'Finished': 'Finalizado',
|
||||||
|
'Seeding': 'Compartiendo',
|
||||||
|
'Allocating': 'Reservando espacio',
|
||||||
|
'Allocating file & Checking resume': 'Reservando espacio y comprobando reanudación',
|
||||||
|
'For Kids': 'Para niños',
|
||||||
|
'Adult': 'Adultos',
|
||||||
|
'Does not support magnet links!': 'No compatible con enlaces magnet',
|
||||||
|
'Reset All Cache DBs': 'Reiniciar todas las bases de datos de la caché',
|
||||||
|
'[B]Search[/B]': '[B]Buscar[/B]',
|
||||||
|
'You can always restart this by deleting DBs via Context Menu': 'Siempre se puede reiniciar esto eliminando las bases de datos a través del menú contextual',
|
||||||
|
'Your preloaded databases are outdated!': 'Las bases de datos precargadas son obsoletas',
|
||||||
|
'Do you want to download new ones right now?': '¿Desea descargar versiones actualizadas?',
|
||||||
|
'Individual Tracker Options':'Opciones individuales del rastreador',
|
||||||
|
'Downloading and copy subtitles. Please wait.':'Descargando y copiando subtítulos. Espere.',
|
||||||
|
'International Check - First Run':'Comprobación internacional - Primera ejecución.',
|
||||||
|
'Delete Russian stuff?':'¿Desea eliminar las cosas de Rusia?',
|
||||||
|
'Save to path':'Ruta para guardar',
|
||||||
|
'Return Russian stuff':'Devolver las cosas de Rusia',
|
||||||
|
'%d files have been returned':'Han vuelto %d archivos',
|
||||||
|
'Download via T-client':'Descargar a través de cliente BitTorrent',
|
||||||
|
'Download via Libtorrent':'Descargar a través de Libtorrent',
|
||||||
|
'Download Status':'Estado de la descarga',
|
||||||
|
'Download has not finished yet':'La descarga no ha finalizado todavía',
|
||||||
|
'Stopped and Deleted!':'Detenido y eliminado',
|
||||||
|
'Unpaused!':'Despausado',
|
||||||
|
'Paused!':'Pausado',
|
||||||
|
'Stopped!':'Detenido',
|
||||||
|
'Started!':'Iniciado',
|
||||||
|
'Delete and Stop':'Eliminar y detener',
|
||||||
|
'Unpause':'Despausar',
|
||||||
|
'Pause':'Pausar',
|
||||||
|
'Delete':'Eliminar',
|
||||||
|
'Open':'Abrir',
|
||||||
|
'Torrent is seeding. To stop it use Download Status.':'El torrent se está compartiendo. Para detenerlo utilice "Estado de la descarga".',
|
||||||
|
'Start All':'Iniciar todo',
|
||||||
|
'Started All!':'Se ha iniciado todo',
|
||||||
|
'Stopped All!':'Se ha detenido todo',
|
||||||
|
'Stop All':'Detener todo',
|
||||||
|
'Keyboard':'Teclado',
|
||||||
|
'Copy Files in Root':'Copiar archivos en directorio personal de root (/root)',
|
||||||
|
'Copied %d files!':'Se han copiado %d archivos',
|
||||||
|
'Add to MyShows.ru':'Añadir a MyShows.ru',
|
||||||
|
'Return to MyShows.ru':'Volver a MyShows.ru',
|
||||||
|
'Search results:':'Resultados de la búsqueda',
|
||||||
|
'by Seeders':'Por fuentes',
|
||||||
|
'by Date':'Por fecha',
|
||||||
|
'Sort':'Ordenar',
|
||||||
|
'Close':'Cerrar',
|
||||||
|
'Views:':'Vistas:',
|
||||||
|
'Rating:':'Valoración:',
|
||||||
|
'Information not found!':'No se han encontrado datos',
|
||||||
|
'Choose searcher':'Elegir buscador',
|
||||||
|
'python-libtorrent Not Found':'No se ha encontrado python-libtorrent',
|
||||||
|
'Windows has static compiled python-libtorrent included.':'Windows incluye una versión de python-libtorrent compilada estáticamente',
|
||||||
|
'You should install "script.module.libtorrent" from "MyShows.me Kodi Repo"':'Se debe instalar "script.module.libtorrrent" desde el repositorio "MyShows.me"',
|
||||||
|
'Linux x64 has not static compiled python-libtorrent included.':'Linux x64 no incluye una versión de python-libtorrent compilada estáticamente',
|
||||||
|
'You should install it by "sudo apt-get install python-libtorrent"':'Se debe instalar con "sudo apt-get install python-libtorrent"',
|
||||||
|
'Linux has static compiled python-libtorrent included but it didn\'t work.':'Linux incluye una version de python-libtorrent compilada estáticamente, pero no ha funcionado',
|
||||||
|
'As far as I know you can compile python-libtorrent for ARMv6-7.':'Por lo que yo sé, python-libtorrent se puede compilar para ARMv6-7.',
|
||||||
|
'You should search for "OneEvil\'s OpenELEC libtorrent" or use Ace Stream.':'Se debe buscar "OpenELEC libtorrent de OneEvil" o utilizar Ace Stream',
|
||||||
|
'Please use install Ace Stream APK and choose it in Settings.':'Instale APK de Ace Stream y selecciónelo en "Ajustes"',
|
||||||
|
'It is possible to compile python-libtorrent for Android, but I don\'t know how.':'Es posible compilar python-libtorrent para Android, pero no sé como hacerlo.',
|
||||||
|
'It is possible to compile python-libtorrent for OS X.':'Es posible compilar python-libtorrent para Mac OS X.',
|
||||||
|
'But you would have to do it by yourself, there is some info on github.com.':'Pero debe hacerlo por sí mismo. Hay alguna información en github.com.',
|
||||||
|
'It is NOT possible to compile python-libtorrent for iOS.':'No es posible compilar python-libtorrent para iOS',
|
||||||
|
'But you can use torrent-client control functions.':'Pero se pueden utilizar las funciones de control del cliente de BitTorrent',
|
||||||
|
'I added custom searchers to Torrenter v2!':'Se han añadido buscadores personalizados a Torrenter v2',
|
||||||
|
'Now you can use your login on trackers or write and install your own searcher!':'Ahora puede identificarse en rastreadores o crear e instalar su propio buscador',
|
||||||
|
'Would you like to install %s from "MyShows.me Kodi Repo" in Programs section?':'¿Le gustaría instalar %s desde el repositorio "MyShows.me", sección Programas?',
|
||||||
|
'Open installation window?':'¿Abrir ventana de instalación?',
|
||||||
|
'Android Support':'Soporte de Android',
|
||||||
|
'Android has no temprorary folder':'Android no tiene carpeta temporal',
|
||||||
|
'Please specify storage folder in Settings!':'Especifique la carpeta de almacenamiento en "Ajustes"',
|
||||||
|
'You have no installed or active searchers! More info in Search Control Window!':'No se han instalado o activado buscadores. Tiene más información en Control de búsquedas',
|
||||||
|
'Please contact DiMartino on kodi.tv forum. We compiled python-libtorrent for Android,':'Póngase en contacto con DiMartino en el foro de kodi.tv. Hemos compilado python-libtorren para Android,',
|
||||||
|
'but we need your help with some Torrent is seeding. To stop it use Download Status.s on different processors.':'pero necesitamos su ayuda con algún torrent que se comparte. Para detenerlo utilice Estado de la descarga. En diferentes procesadores.',
|
||||||
|
'We added Android ARM full support to Torrenter v2!':'Hemos añadido compatibilidad completa para Android ARM a Torrenter v2',
|
||||||
|
'I deleted pre-installed ones, install them in Search Control Window!':'Se eliminaron los que estaban preinstalados; instálelos desde Control de búsquedas',
|
||||||
|
'Torrenter didn\'t find %s searcher':'Torrenter no ha encontrado el buscador %s',
|
||||||
|
'Torrenter Tracker Install':'Instalación de rastreador de Torrenter',
|
||||||
|
'Ask to save':'Preguntar para guardar',
|
||||||
|
'Would you like to save this file?':'¿Le gustaría guardar este archivo?',
|
||||||
|
'Your storage path is not writable or not local! Please change it in settings!':'La ruta del almacén está protegida contra escritura o no es local. Cámbiela en "Ajustes"',
|
||||||
|
'Upgrade advancedsettings.xml':'Actualizar archivo advancedsettings.xml',
|
||||||
|
'We would like to set some advanced settings for you!':'Nos gustaría efectuar algunos ajustes avanzados por usted',
|
||||||
|
'Do it!':'Hazlo',
|
||||||
|
'Please, restart Kodi now!':'Reinicie Kodi',
|
||||||
|
'./ (Root folder)':'./ (Carpeta de root)',
|
||||||
|
'Opening torrent file':'Abriendo archivo torrent',
|
||||||
|
'New player to Torrenter v2 - Torrent2HTTP! It should be faster, stable and better with Android, also seeking works in it.':'Nuevo reproductor para Torrenter v2 - Torrent2HTTP. Debe ser más rápido, estable y mejor en Android; además, con él funcionan los intercambios.',
|
||||||
|
'Would you like to try it?':'¿Le gustaría probarlo?',
|
||||||
|
'Torrent2HTTP enabled! Can be changed in Settings.':'Se ha activado Torrent2HTTP. Puede cambiarse en "Ajustes".',
|
||||||
|
'Seeking':'Compartiendo',
|
||||||
|
'Would you like to resume from %s?':'¿Le gustaría reanudar desde %s?',
|
||||||
|
'Seeking is working only with player Torrent2HTTP.':'Compartir funciona solamente con el reproductor Torrent2HTTP.',
|
||||||
|
'Play (from %s)':'Reproducir desde %s',
|
||||||
|
'Play (from start)':'Reproducir desde el inicio',
|
||||||
|
},
|
||||||
|
'he': {
|
||||||
'Seeds searching.': 'חיפוש זורעים',
|
'Seeds searching.': 'חיפוש זורעים',
|
||||||
'Please Wait': 'המתן',
|
'Please Wait': 'המתן',
|
||||||
'Information': 'מידע',
|
'Information': 'מידע',
|
||||||
|
@ -224,7 +483,7 @@ def localize(text):
|
||||||
'Unpause':'אל תפסיק',
|
'Unpause':'אל תפסיק',
|
||||||
'Pause':'הפסק',
|
'Pause':'הפסק',
|
||||||
'Delete':'מחק',
|
'Delete':'מחק',
|
||||||
'Open (no return)':'פתח',
|
'Open':'פתח',
|
||||||
'Torrent is seeding. To stop it use Download Status.':'Torrent is seeding. To stop it use Download Status.',
|
'Torrent is seeding. To stop it use Download Status.':'Torrent is seeding. To stop it use Download Status.',
|
||||||
'Start All':'התחל הכל',
|
'Start All':'התחל הכל',
|
||||||
'Started All!':'מיין הכל',
|
'Started All!':'מיין הכל',
|
||||||
|
@ -290,7 +549,280 @@ def localize(text):
|
||||||
'Play (from %s)':'%s נגן מ',
|
'Play (from %s)':'%s נגן מ',
|
||||||
'Play (from start)':'נגן מהתחלה',
|
'Play (from start)':'נגן מהתחלה',
|
||||||
},
|
},
|
||||||
|
'hu': {
|
||||||
|
'Seeds searching.': 'Seederek keresése.',
|
||||||
|
'Please Wait': 'Kérlek várj',
|
||||||
|
'Information': 'Információ',
|
||||||
|
'Torrent downloading is stopped.': 'A torrent letöltése befejeződött.',
|
||||||
|
'Search': 'Keresés',
|
||||||
|
'Seeds': 'Seederek',
|
||||||
|
'Peers': 'Kapcsolatok',
|
||||||
|
'Materials are loading now.': 'A tartalmak most töltődnek.',
|
||||||
|
'Search Phrase': 'Keresés kifejezésre',
|
||||||
|
'Magnet-link is converting': 'Magnet-link konvertálása',
|
||||||
|
'Error': 'Hiba',
|
||||||
|
'Your library out of date and can\'t save magnet-links.': 'A könyvtár elavult, nem lehet lementeni a magnet-linket.',
|
||||||
|
'Bookmarks': 'Könyvjelzők',
|
||||||
|
'Logout': 'Kijelentkezés',
|
||||||
|
'Login': 'Bejelentkezés',
|
||||||
|
'Recent Materials': 'Jelenlegi tartalmak',
|
||||||
|
'Register': 'Regisztráció',
|
||||||
|
'Bookmark': 'Könyvjelző',
|
||||||
|
'Item successfully added to Bookmarks': 'Az elem sikeresen hozzáadva a Könyvjelzőkhöz',
|
||||||
|
'Item successfully removed from Bookmarks': 'Az elem sikeresen törölve a Könyvjelzőkből',
|
||||||
|
'Bookmark not added': 'A könyvjelző nem lett hozzáadva',
|
||||||
|
'Bookmark not removed': 'A könyvjelző nem lett törölve',
|
||||||
|
'Add To Bookmarks': 'Hozzáadás a Könyvjelzőkhöz',
|
||||||
|
'Remove From Bookmarks': 'Eltávolítás a Könyvjelzőkből',
|
||||||
|
'Auth': 'Hitelesítés',
|
||||||
|
'Already logged in': 'Már be vagy jelentkezve',
|
||||||
|
'Input Email (for password recovery):': 'E-mail bevitel (jelszó helyreállításához):',
|
||||||
|
'Input Email:': 'E-mail bevitel:',
|
||||||
|
'Input Password (6+ symbols):': 'Jelszó bevitel (6+ karakter):',
|
||||||
|
'Input Password:': 'Jelszó bevitel:',
|
||||||
|
'Login successfull': 'Bejelentkezés sikeres',
|
||||||
|
'Login failed': 'Bejelentkezés sikertelen',
|
||||||
|
'User not logged in': 'A felhasználó nincs bejelentkezve',
|
||||||
|
'User successfully logged out': 'A felhasználó sikeresen kijelentkezett',
|
||||||
|
'Preloaded: ': 'Előtöltés: ',
|
||||||
|
'Do you want to STOP torrent downloading and seeding?': 'Be akarod fejezni a torrent letöltését és seedelését?',
|
||||||
|
'Torrent Downloading': 'Torrent letöltése',
|
||||||
|
'Auth expired, please relogin': 'Hitelesítés lejárt, kérlek jelentkezz be újra',
|
||||||
|
'Storage': 'Tárolóhely',
|
||||||
|
'Storage has been cleared': 'A tárolóhely megtisztítva',
|
||||||
|
'Clear Storage': 'Tárolóhely Megtisztítása',
|
||||||
|
'Popular': 'Népszerű',
|
||||||
|
'Views': 'Nézetek',
|
||||||
|
'Uploading': 'Feltöltés',
|
||||||
|
'Download': 'Letöltés',
|
||||||
|
'Input symbols from CAPTCHA image:': 'Szimbólumok bevitele a CAPTCHA képről:',
|
||||||
|
'Please, rate watched video:': 'Kérlek, értékeld a megnézett videót:',
|
||||||
|
'Bad': 'Rossz',
|
||||||
|
'So-So': 'Elmegy',
|
||||||
|
'Good': 'Jó',
|
||||||
|
'Ratings': 'Értékelések',
|
||||||
|
'Rating': 'Értékelés',
|
||||||
|
'Retry': 'Újra',
|
||||||
|
'%ds has left': '%ds van hátra',
|
||||||
|
'File failed to play! Do you want to RETRY and buffer more?': 'A fájl lejátszása hibába ütközött. Újra akarod indítani és többet bufferelni?',
|
||||||
|
'High Priority Files': 'Magas prioritású fájlok',
|
||||||
|
'Skip All Files': 'Összes fájl kihagyása',
|
||||||
|
'Start': 'Indít',
|
||||||
|
'Stop': 'Megállít',
|
||||||
|
'Play':'Lejátszás',
|
||||||
|
'High Priority': 'Magas prioritás',
|
||||||
|
'Skip File': 'Fájl kihagyása',
|
||||||
|
'Remove': 'Eltávolítás',
|
||||||
|
'Remove with files': 'Eltávolítás a fájlokkal együtt',
|
||||||
|
'Play File': 'Fájl lejátszása',
|
||||||
|
'Start All Files': 'Összes fájl elindítása',
|
||||||
|
'Stop All Files': 'Összes fájl megállítása',
|
||||||
|
'Torrent-client Browser': 'Torrentkliens Böngésző',
|
||||||
|
'Remote Torrent-client': 'Távoli torrentkliens',
|
||||||
|
'You didn\'t set up replacement path in setting.': 'Nem állítottál be helyettesítő elérési utat a beállításokban.',
|
||||||
|
'For example /media/dl_torr/ to smb://SERVER/dl_torr/. Setup now?': 'Például /media/dl_torr/ a smb://SERVER/dl_torr/ - hez. Beállítod most?',
|
||||||
|
'Manual Torrent-client Path Edit': 'Kézi torrentkliens elérési út módosítás',
|
||||||
|
'Choose .torrent in video library': '.torrent kiválasztása a videó könyvtárban',
|
||||||
|
'.torrent Player': '.torrent Lejátszó',
|
||||||
|
'Choose directory:': 'Könyvtár kiválasztása:',
|
||||||
|
'Starting download next episode!': 'Elindul a következő epizód letöltése!',
|
||||||
|
'Choose in torrent-client:': 'Kiválasztás a torrentkliensben:',
|
||||||
|
'Search Control Window': 'Keresést Kezelő Ablak',
|
||||||
|
'Magnet-link (magnet:...)': 'Magnet-link (magnet:...)',
|
||||||
|
'Not a magnet-link!': 'Ez nem magnet-link!',
|
||||||
|
'Magnet-link Player': 'Magnet-link Lejátszó',
|
||||||
|
'UNKNOWN STATUS': 'ISMERETLEN STÁTUSZ',
|
||||||
|
'Checking preloaded files...': 'Előtöltött fájlok ellenőrzése...',
|
||||||
|
'Waiting for website response...': 'Várakozás a weboldal válaszára...',
|
||||||
|
'Search and cache information for:': 'Információ keresése és gyorsítótárazása:',
|
||||||
|
'Open Torrent': 'Torrent megnyitása',
|
||||||
|
'Torrent list is empty.': 'A torrent lista üres.',
|
||||||
|
'Content Lists': 'Tartalmak Listája',
|
||||||
|
'Canceled by User': 'Leállítva felhasználó által',
|
||||||
|
'Do you want to search and cache full metadata + arts?': 'Szeretnéd lekérni és gyorsítótárazni a metaadatokat és a képeket?',
|
||||||
|
'This vastly decreases load speed, but you will be asked to download premade bases!': 'Ez jelentősen csökkenti a betöltési sebességet, megkérünk, hogy töltsd le az előre elkészített adatbázisokat!',
|
||||||
|
'Do you want to preload full metadata?': 'Előtöltöd a metaadatokat?',
|
||||||
|
'It is highly recommended!': 'Ez erősen ajánlott!',
|
||||||
|
'TV Shows': 'Sorozatok',
|
||||||
|
'Cartoons': 'Rajzfilmek',
|
||||||
|
'Anime': 'Anime',
|
||||||
|
'Most Recent': 'Legújabb',
|
||||||
|
'Top 250 Movies': 'Top 250 Filmek',
|
||||||
|
'Top All Time': 'Top Mindenkori',
|
||||||
|
'by Genre': 'Műfaj alapján',
|
||||||
|
'by Year': 'Évszám alapján',
|
||||||
|
'Action': 'Akció',
|
||||||
|
'Adventure': 'Kaland',
|
||||||
|
'Animation': 'Animációs',
|
||||||
|
'Biography': 'Életrajzi',
|
||||||
|
'Comedy': 'Vígjáték',
|
||||||
|
'Crime': 'Bűnügyi',
|
||||||
|
'Documentary': 'Dokumentum',
|
||||||
|
'Drama': 'Dráma',
|
||||||
|
'Family': 'Családi',
|
||||||
|
'Fantasy': 'Fantasy',
|
||||||
|
'Film-Noir': 'Film-Noir',
|
||||||
|
'History': 'Történelmi',
|
||||||
|
'Horror': 'Horror',
|
||||||
|
'Music': 'Zenei',
|
||||||
|
'Musical': 'Musical',
|
||||||
|
'Mystery': 'Misztikus',
|
||||||
|
'Romance': 'Romantikus',
|
||||||
|
'Sci-Fi': 'Sci-Fi',
|
||||||
|
'Short': 'Rövidfilm',
|
||||||
|
'Sport': 'Sport',
|
||||||
|
'Thriller': 'Thriller',
|
||||||
|
'War': 'Háborús',
|
||||||
|
'Western': 'Western',
|
||||||
|
'[B]by Site[/B]': '[B]Weboldal alapján[/B]',
|
||||||
|
'Cartoons Series': 'Rajzfilmsorozatok',
|
||||||
|
'Cartoons Short': 'Rövid rajzfilmek',
|
||||||
|
'Male': 'Férfi',
|
||||||
|
'Female': 'Női',
|
||||||
|
'Russia & USSR': 'Oroszország & Szovjetunió',
|
||||||
|
'Next Page': 'Következő oldal',
|
||||||
|
'Previous Page': 'Előző oldal',
|
||||||
|
'Russian Movies': 'Orosz filmek',
|
||||||
|
'israeli Movies': 'Izraeli fimek',
|
||||||
|
'hebdub movies': 'hebdub filmek',
|
||||||
|
'Movies': 'Filmek',
|
||||||
|
'High Resolution Movies': 'HD filmek',
|
||||||
|
'3D Movies': '3D filmek',
|
||||||
|
'Movies [Bluray]': 'Filmek [Bluray]',
|
||||||
|
'Anime Film': 'Anime filmek',
|
||||||
|
'Anime Series': 'Anime sorozatok',
|
||||||
|
'Can\'t download torrent, probably no seeds available.': 'Nem lehet letölteni a torrentet, valószínűleg nincsenek elérhető seederek.',
|
||||||
|
'Personal List': 'Saját lista',
|
||||||
|
'Add to %s': 'Hozzáadás ehhez %s',
|
||||||
|
'Delete from %s': 'Eltávolítás innen %s',
|
||||||
|
'Added!': 'Hozzáadva!',
|
||||||
|
'Deleted!': 'Eltávolítva!',
|
||||||
|
'Search History': 'Keresési Előzmények',
|
||||||
|
' History ':' Előzmények ',
|
||||||
|
'Torrent History':'Torrent Előzmények',
|
||||||
|
'Watched History':'Megtekintett Előzmények',
|
||||||
|
'Favourites': 'Kedvencek',
|
||||||
|
'Favourites SH': 'Kedvencek SH',
|
||||||
|
'Clear %s': 'Tisztítás %s',
|
||||||
|
'Clear!': 'Tisztítás!',
|
||||||
|
'kb/s': 'kb/s',
|
||||||
|
'Queued': 'Sorba állítva',
|
||||||
|
'Checking': 'Ellenőrzés',
|
||||||
|
'Downloading metadata': 'Metaadatok letöltése',
|
||||||
|
'Downloading': 'Letöltés',
|
||||||
|
'Finished': 'Befejezve',
|
||||||
|
'Seeding': 'Seedelés',
|
||||||
|
'Allocating': 'Összeállítás',
|
||||||
|
'Allocating file & Checking resume': 'Fájl összeállítása és folytatás ellenőrzése',
|
||||||
|
'For Kids': 'Gyerekek számára',
|
||||||
|
'Adult': 'Felnőtt',
|
||||||
|
'Does not support magnet links!': 'Nem támogatja a magnet-linkeket!',
|
||||||
|
'Reset All Cache DBs': 'Összes gyorsítótár adatbázis visszaállítása',
|
||||||
|
'[B]Search[/B]': '[B]Keresés[/B]',
|
||||||
|
'You can always restart this by deleting DBs via Context Menu': 'Mindig visszaállíthatja az adatbázis törlésével a helyi menün keresztül',
|
||||||
|
'Your preloaded databases are outdated!': 'Az előtöltött adatbázisok elavultak!',
|
||||||
|
'Do you want to download new ones right now?': 'Szeretnéd letölteni az újakat most?',
|
||||||
|
'Individual Tracker Options':'Egyéni tracker beállítások',
|
||||||
|
'Downloading and copy subtitles. Please wait.':'Feliratok letöltése és másolása. Kérlek, várj.',
|
||||||
|
'International Check - First Run':'International ellenőrzés - első futtatás',
|
||||||
|
'Delete Russian stuff?':'Orosz tartalom törlése?',
|
||||||
|
'Save to path':'Mentés a mappába',
|
||||||
|
'Return Russian stuff':'Orosz tartalom visszaállítása',
|
||||||
|
'%d files have been returned':'%d fájlok visszaállítva',
|
||||||
|
'Download via T-client':'Letöltés T-kliensen keresztül',
|
||||||
|
'Download via Libtorrent':'Letöltés Libtorrenten keresztül',
|
||||||
|
'Download Status':'Letöltési Állapot',
|
||||||
|
'Download has not finished yet':'A letöltés még nem fejeződött be',
|
||||||
|
'Stopped and Deleted!':'Leállítva és eltávolítva!',
|
||||||
|
'Unpaused!':'Újra elindítva!',
|
||||||
|
'Paused!':'Szünetelve!',
|
||||||
|
'Stopped!':'Megállítva!',
|
||||||
|
'Started!':'Elindítva!',
|
||||||
|
'Delete and Stop':'Megállít és eltávolít',
|
||||||
|
'Unpause':'Újra elindít',
|
||||||
|
'Pause':'Szüneteltet',
|
||||||
|
'Delete':'Eltávolít',
|
||||||
|
'Open':'Megnyitás',
|
||||||
|
'Torrent is seeding. To stop it use Download Status.':'Torrent seedelés alatt. Ahhoz, hogy megállítsd használd a Letöltési Állapotot.',
|
||||||
|
'Start All':'Összes elindítása',
|
||||||
|
'Started All!':'Összes elindítva!',
|
||||||
|
'Stopped All!':'Összes megállítva!',
|
||||||
|
'Stop All':'Összes megállítása',
|
||||||
|
'Keyboard':'Billentyűzet',
|
||||||
|
'Copy Files in Root':'Fájlok másolása a Rendszerkönyvtárba',
|
||||||
|
'Copied %d files!':'%d fájl átmásolva!',
|
||||||
|
'Add to MyShows.ru':'Hozzáadás MyShows.ru-hoz',
|
||||||
|
'Return to MyShows.ru':'Visszatérés a MyShows.ru-hoz',
|
||||||
|
'Search results:':'Keresési eredmények:',
|
||||||
|
'by Seeders':'Seederek alapján',
|
||||||
|
'by Date':'Dátum alapján',
|
||||||
|
'Sort':'Rendezés',
|
||||||
|
'Close':'Bezár',
|
||||||
|
'Views:':'Nézetek:',
|
||||||
|
'Rating:':'Értékelés:',
|
||||||
|
'Information not found!':'Nem található információ!',
|
||||||
|
'Choose searcher':'Válassz keresőt',
|
||||||
|
'python-libtorrent Not Found':'python-libtorrent nem található',
|
||||||
|
'Windows has static compiled python-libtorrent included.':'A Windows statikusan fordított python-libtorrentet tartalmaz.',
|
||||||
|
'You should install "script.module.libtorrent" from "MyShows.me Kodi Repo"':'Telepítsd a "script.module.libtorrent"-et a "MyShows.me Kodi Repo"-ból',
|
||||||
|
'Linux x64 has not static compiled python-libtorrent included.':'A Linux x64 statikusan fordított python-libtorrentet nem tartalmaz.',
|
||||||
|
'You should install it by "sudo apt-get install python-libtorrent"':'Telepítsd ezzel a paranccsal "sudo apt-get install python-libtorrent"',
|
||||||
|
'Linux has static compiled python-libtorrent included but it didn\'t work.':'A Linux statikusan fordított python-libtorrentet tartalmaz de nem működik.',
|
||||||
|
'As far as I know you can compile python-libtorrent for ARMv6-7.':'Ahogy én tudom, le lehet fordítani a python-libtorrentet ARMv6-7-ra',
|
||||||
|
'You should search for "OneEvil\'s OpenELEC libtorrent" or use Ace Stream.':'Keress rá "OneEvil\'s OpenELEC libtorrent"-re vagy használj Ace Streamet',
|
||||||
|
'Please use install Ace Stream APK and choose it in Settings.':'Kérlek használj Ace Stream APK-t és válaszd ki a beállításokban.',
|
||||||
|
'It is possible to compile python-libtorrent for Android, but I don\'t know how.':'Lehetséges, hogy lefordítható a python-libtorrent Android-ra, de nem tudom hogyan.',
|
||||||
|
'It is possible to compile python-libtorrent for OS X.':'Lehetséges, hogy lefordítható a python-libtorrent OS X-re.',
|
||||||
|
'But you would have to do it by yourself, there is some info on github.com.':'De ezt magadnak kell megcsinálnod, van néhány infó erről a github.com-on.',
|
||||||
|
'It is NOT possible to compile python-libtorrent for iOS.':'iOS-re nem lehet lefordítani a python-libtorrentet.',
|
||||||
|
'But you can use torrent-client control functions.':'De a torrentkliens kezelőt funkciót tudod használni.',
|
||||||
|
'I added custom searchers to Torrenter v2!':'Hozzáadtam egyéni keresőket a Torrenter v2-höz!',
|
||||||
|
'Now you can use your login on trackers or write and install your own searcher!':'Most már be tudsz lépni a trackerekre, vagy megírhatod és feltelepítheted a saját keresődet!',
|
||||||
|
'Would you like to install %s from "MyShows.me Kodi Repo" in Programs section?':'Szeretnéd telepíteni %s a "MyShows.me Kodi Repo"-ból?',
|
||||||
|
'Open installation window?':'Telepítő ablak megnyitása?',
|
||||||
|
'Android Support':'Android támogatás',
|
||||||
|
'Android has no temprorary folder':'Az Android nem rendelkezik ideiglenes mappával',
|
||||||
|
'Please specify storage folder in Settings!':'Kérlek add meg a tárolóhely mappáját a beállításokban!',
|
||||||
|
'You have no installed or active searchers! More info in Search Control Window!':'Nincsenek telepített vagy aktív keresők! Több információ a Keresést Kezelő Abalakban.',
|
||||||
|
'Please contact DiMartino on kodi.tv forum. We compiled python-libtorrent for Android,':'Kérünk lépj kapcsolatba DiMartino-val a kodi.tv fórumon. Lefordítottuk a python-libtorrentet Androidhoz,',
|
||||||
|
'but we need your help with some tests on different processors.':'de szükségünk lesz még néhány tesztre különböző processzorokon.',
|
||||||
|
'We added Android ARM full support to Torrenter v2!':'A Torrenter v2 számara teljesen támogatottá tettük az Android ARM-t!',
|
||||||
|
'I deleted pre-installed ones, install them in Search Control Window!':'Töröltem az összes előre telepítettet, telepítsd őket a Keresést Kezelő Ablakban!',
|
||||||
|
'Torrenter didn\'t find %s searcher':'A Torrenter nem találja a %s keresőt',
|
||||||
|
'Torrenter Tracker Install':'Torrent tracker telepítés',
|
||||||
|
'Ask to save':'Mentés kérése',
|
||||||
|
'Would you like to save this file?':'El szeretnéd menteni ez a fájlt?',
|
||||||
|
'Your storage path is not writable or not local! Please change it in settings!':'A tárolóhely elérési útja nem írható vagy nem elérhető! Kérlek változtatsd meg a beállításokban!',
|
||||||
|
'Upgrade advancedsettings.xml':'advancedsettings.xml frissítése',
|
||||||
|
'We would like to set some advanced settings for you!':'Be szeretnénk állítani néhány haladó beállítást!',
|
||||||
|
'Do it!':'Csináld!',
|
||||||
|
'Please, restart Kodi now!':'Kérlek, indítsd újra a Kodit, most.',
|
||||||
|
'./ (Root folder)':'./ (Rendszerkönyvtár)',
|
||||||
|
'Opening torrent file':'Torrent fájl megnyitása',
|
||||||
|
'New player to Torrenter v2 - Torrent2HTTP! It should be faster, stable and better with Android, also seeking works in it.':'Új lejátszó a Torrenter v2-höz - Torrent2HTTP: Gyorsabb, stabilabb és jobb Androiddal, valamint a keresés is működik vele.',
|
||||||
|
'Would you like to try it?':'Ki szeretnéd próbálni?',
|
||||||
|
'Torrent2HTTP enabled! Can be changed in Settings.':'Torrent2HTTP engedélyezve! Ezen a beállításokban tudsz változtatni.',
|
||||||
|
'Seeking':'Keresés',
|
||||||
|
'Would you like to resume from %s?':'Szeretnéd folytatni innen: %s?',
|
||||||
|
'Seeking is working only with player Torrent2HTTP.':'A keresés csak a Torrent2HTTP lejátszóval működik.',
|
||||||
|
'Play (from %s)':'Lejátszás (innen %s)',
|
||||||
|
'Play (from start)':'Lejátszás (az elejétől)',
|
||||||
|
},
|
||||||
'ru': {
|
'ru': {
|
||||||
|
'Torrenter has a better view style for Kodi 17 default skin.':'У Torrenter есть оптимизированный вид под новый скин Kodi 17.',
|
||||||
|
'is recommended for Kodi 17 users and now out of beta.': 'рекомендовано пользователям Kodi 17 и вышло из беты.',
|
||||||
|
'You can disable it usage in Settings.':'Его можно отключить в настройках плагина.',
|
||||||
|
'Move Up': 'Вверх',
|
||||||
|
'Torrenter Search Window': 'Окно Поиска Torrenter',
|
||||||
|
'Cancel': 'Отмена',
|
||||||
|
'Clear History': 'Очистить Историю',
|
||||||
|
'Play (with seek)': 'Играть (перемотка)',
|
||||||
|
'Mass Control':'Массовое Управление',
|
||||||
|
'Info':'Инфо',
|
||||||
|
'Delete torrent with files?':'Вы уверены, что хотите удалить торрент с файлами?',
|
||||||
|
'Fav. / Unfav.':'Доб./удал. Избранное',
|
||||||
|
'Search Window': 'Окно поиска',
|
||||||
|
'Context menu': 'Контекстное меню',
|
||||||
'Seeds searching.': 'Идёт поиск сидов.',
|
'Seeds searching.': 'Идёт поиск сидов.',
|
||||||
'Please Wait': 'Подождите',
|
'Please Wait': 'Подождите',
|
||||||
'Information': 'Информация',
|
'Information': 'Информация',
|
||||||
|
@ -376,7 +908,7 @@ def localize(text):
|
||||||
'Checking preloaded files...': 'Проверка файлов...',
|
'Checking preloaded files...': 'Проверка файлов...',
|
||||||
'Waiting for website response...': 'Ожидание ответа сайта...',
|
'Waiting for website response...': 'Ожидание ответа сайта...',
|
||||||
'Search and cache information for:': 'Поиск и кэширование информации для:',
|
'Search and cache information for:': 'Поиск и кэширование информации для:',
|
||||||
'Open Torrent': 'Открыть Список файлов',
|
'Open Torrent': 'Открыть Торрент',
|
||||||
'Torrent list is empty.': 'Список раздач пуст.',
|
'Torrent list is empty.': 'Список раздач пуст.',
|
||||||
'Content Lists': 'Списки Медиа',
|
'Content Lists': 'Списки Медиа',
|
||||||
'Canceled by User': 'Отменено пользователем',
|
'Canceled by User': 'Отменено пользователем',
|
||||||
|
@ -483,7 +1015,7 @@ def localize(text):
|
||||||
'Unpause':'Возобновить',
|
'Unpause':'Возобновить',
|
||||||
'Pause':'Пауза',
|
'Pause':'Пауза',
|
||||||
'Delete':'Удалить',
|
'Delete':'Удалить',
|
||||||
'Open (no return)':'Открыть (без возврата)',
|
'Open':'Открыть',
|
||||||
'Torrent is seeding. To stop it use Download Status.':'Сидирование. Для остановки используйте Статус Загрузки.',
|
'Torrent is seeding. To stop it use Download Status.':'Сидирование. Для остановки используйте Статус Загрузки.',
|
||||||
'Start All':'Запустить Все',
|
'Start All':'Запустить Все',
|
||||||
'Started All!':'Все Запущены!',
|
'Started All!':'Все Запущены!',
|
||||||
|
@ -491,6 +1023,7 @@ def localize(text):
|
||||||
'Stop All':'Остановить Все',
|
'Stop All':'Остановить Все',
|
||||||
'Keyboard':'Клавиатура',
|
'Keyboard':'Клавиатура',
|
||||||
'Copy Files in Root':'Скопировать файлы в Корень',
|
'Copy Files in Root':'Скопировать файлы в Корень',
|
||||||
|
'Copy in Root': 'Скопировать в Корень',
|
||||||
'Copied %d files!':'Скопировано %d файлов!',
|
'Copied %d files!':'Скопировано %d файлов!',
|
||||||
'Return to %s':'Вернуться в %s',
|
'Return to %s':'Вернуться в %s',
|
||||||
'Search results:':'Результаты поиска:',
|
'Search results:':'Результаты поиска:',
|
||||||
|
@ -741,7 +1274,7 @@ def localize(text):
|
||||||
'Unpause':'Відновити',
|
'Unpause':'Відновити',
|
||||||
'Pause':'Пауза',
|
'Pause':'Пауза',
|
||||||
'Delete':'Видалити',
|
'Delete':'Видалити',
|
||||||
'Open (no return)':'Відкрити (без повернення)',
|
'Open':'Відкрити',
|
||||||
'Torrent is seeding. To stop it use Download Status.':'Сідування. Для зупинки використовуйте Статус завантаження.',
|
'Torrent is seeding. To stop it use Download Status.':'Сідування. Для зупинки використовуйте Статус завантаження.',
|
||||||
'Start All':'Запустити все',
|
'Start All':'Запустити все',
|
||||||
'Started All!':'Все запущене!',
|
'Started All!':'Все запущене!',
|
||||||
|
|
34
Player.py
|
@ -30,7 +30,7 @@ import Downloader
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import Localization
|
import Localization
|
||||||
from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, DownloadDB, get_ids_video, log, debug, foldername
|
from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, DownloadDB, get_ids_video, log, debug, foldername, ensure_str, loadsw_onstop
|
||||||
|
|
||||||
ROOT = sys.modules["__main__"].__root__
|
ROOT = sys.modules["__main__"].__root__
|
||||||
RESOURCES_PATH = os.path.join(ROOT, 'resources')
|
RESOURCES_PATH = os.path.join(ROOT, 'resources')
|
||||||
|
@ -166,8 +166,12 @@ class TorrentPlayer(xbmc.Player):
|
||||||
debug('************************************* GOING LOOP')
|
debug('************************************* GOING LOOP')
|
||||||
self.torrent.startSession()
|
self.torrent.startSession()
|
||||||
self.torrent.continueSession(self.contentId)
|
self.torrent.continueSession(self.contentId)
|
||||||
|
WatchedHistoryDB().add(self.basename, self.torrentUrl,
|
||||||
|
foldername(self.torrent.getContentList()[self.contentId]['title']),
|
||||||
|
self.watchedTime, self.totalTime, self.contentId,
|
||||||
|
self.fullSize / 1024 / 1024)
|
||||||
self.loop()
|
self.loop()
|
||||||
WatchedHistoryDB().add(self.basename, foldername(self.torrent.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize / 1024 / 1024)
|
WatchedHistoryDB().add(self.basename, self.torrentUrl, foldername(self.torrent.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize / 1024 / 1024)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
debug('************************************* GO NEXT?')
|
debug('************************************* GO NEXT?')
|
||||||
|
@ -193,11 +197,13 @@ class TorrentPlayer(xbmc.Player):
|
||||||
else:
|
else:
|
||||||
if self.seeding_status:
|
if self.seeding_status:
|
||||||
showMessage(self.localize('Information'),
|
showMessage(self.localize('Information'),
|
||||||
self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
|
self.localize('Torrent is seeding. To stop it use Download Status.'))
|
||||||
else:
|
else:
|
||||||
if self.seeding: self.db_delete()
|
if self.seeding: self.db_delete()
|
||||||
showMessage(self.localize('Information'),
|
showMessage(self.localize('Information'),
|
||||||
self.localize('Torrent downloading is stopped.'), forced=True)
|
self.localize('Torrent downloading is stopped.'))
|
||||||
|
|
||||||
|
loadsw_onstop() # Reload Search Window
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.next_dl = True if self.__settings__.getSetting('next_dl') == 'true' and self.ids_video else False
|
self.next_dl = True if self.__settings__.getSetting('next_dl') == 'true' and self.ids_video else False
|
||||||
|
@ -338,12 +344,12 @@ class TorrentPlayer(xbmc.Player):
|
||||||
response = json.loads(request)
|
response = json.loads(request)
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
|
|
||||||
|
if self.get('listitem'):
|
||||||
|
listitem = self.get('listitem')
|
||||||
|
listitem.setPath(path)
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
xbmc.Player().play(path, listitem)
|
xbmc.Player().play(path, listitem)
|
||||||
#playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
|
||||||
#playlist.clear()
|
|
||||||
#playlist.add(path, listitem)
|
|
||||||
#xbmc.Player().play(playlist)
|
|
||||||
|
|
||||||
xbmc.sleep(2000) # very important, do not edit this, podavan
|
xbmc.sleep(2000) # very important, do not edit this, podavan
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -367,7 +373,7 @@ class TorrentPlayer(xbmc.Player):
|
||||||
if len(subs) > 0:
|
if len(subs) > 0:
|
||||||
self.torrent.startSession()
|
self.torrent.startSession()
|
||||||
showMessage(self.localize('Information'),
|
showMessage(self.localize('Information'),
|
||||||
self.localize('Downloading and copy subtitles. Please wait.'), forced=True)
|
self.localize('Downloading and copy subtitles. Please wait.'))
|
||||||
for ind, title in subs:
|
for ind, title in subs:
|
||||||
self.torrent.continueSession(ind)
|
self.torrent.continueSession(ind)
|
||||||
while iterator < 100:
|
while iterator < 100:
|
||||||
|
@ -455,7 +461,7 @@ class TorrentPlayer(xbmc.Player):
|
||||||
if self.iterator == 100 and self.next_dl and not self.next_dling and isinstance(self.next_contentId,
|
if self.iterator == 100 and self.next_dl and not self.next_dling and isinstance(self.next_contentId,
|
||||||
int) and self.next_contentId != False:
|
int) and self.next_contentId != False:
|
||||||
showMessage(self.localize('Torrent Downloading'),
|
showMessage(self.localize('Torrent Downloading'),
|
||||||
self.localize('Starting download next episode!'), forced=True)
|
self.localize('Starting download next episode!'))
|
||||||
self.torrent.stopSession()
|
self.torrent.stopSession()
|
||||||
# xbmc.sleep(1000)
|
# xbmc.sleep(1000)
|
||||||
path = self.torrent.getFilePath(self.next_contentId)
|
path = self.torrent.getFilePath(self.next_contentId)
|
||||||
|
@ -465,10 +471,10 @@ class TorrentPlayer(xbmc.Player):
|
||||||
|
|
||||||
def _get_status_lines(self, s):
|
def _get_status_lines(self, s):
|
||||||
return [
|
return [
|
||||||
self.display_name+'; '+self.torrent.get_debug_info('dht_state'),
|
ensure_str(self.display_name),
|
||||||
"%.2f%% %s; %s" % (s.progress * 100, self.localize(STATE_STRS[s.state]).decode('utf-8'), self.torrent.get_debug_info('trackers_sum')),
|
"%.2f%% %s" % (s.progress * 100, self.localize(STATE_STRS[s.state])),
|
||||||
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1024, self.localize('kb/s').decode('utf-8'),
|
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1024, self.localize('kb/s'),
|
||||||
s.upload_rate / 1024, self.localize('kb/s').decode('utf-8'),
|
s.upload_rate / 1024, self.localize('kb/s'),
|
||||||
s.num_seeds, s.num_peers)
|
s.num_seeds, s.num_peers)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,9 @@ import xbmc
|
||||||
import Localization
|
import Localization
|
||||||
from functions import log, debug, showMessage
|
from functions import log, debug, showMessage
|
||||||
|
|
||||||
|
import ssl
|
||||||
|
|
||||||
|
#ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
class SearcherABC:
|
class SearcherABC:
|
||||||
searchIcon = '/icons/video.png'
|
searchIcon = '/icons/video.png'
|
||||||
sourceWeight = 1
|
sourceWeight = 1
|
||||||
|
@ -103,19 +105,25 @@ class SearcherABC:
|
||||||
|
|
||||||
def makeRequest(self, url, data={}, headers={}):
|
def makeRequest(self, url, data={}, headers={}):
|
||||||
self.load_cookie()
|
self.load_cookie()
|
||||||
opener = None
|
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
|
||||||
if self.proxy == 1:
|
if self.proxy == 1:
|
||||||
try:
|
try:
|
||||||
from resources.proxy import antizapret
|
from resources.proxy import antizapret
|
||||||
opener = urllib2.build_opener(antizapret.AntizapretProxyHandler(), urllib2.HTTPCookieProcessor(self.cookieJar))
|
opener.add_handler(antizapret.AntizapretProxyHandler())
|
||||||
config = antizapret.config()
|
config = antizapret.config()
|
||||||
self.debug('[antizapret]: '+str(config["domains"]))
|
self.debug('[antizapret]: '+str(config["domains"]))
|
||||||
self.debug('[antizapret]: '+str(config["server"]))
|
self.debug('[antizapret]: '+str(config["server"]))
|
||||||
except:
|
except:
|
||||||
showMessage('AntiZapret', Localization.localize('Error'))
|
showMessage('AntiZapret', Localization.localize('Error'))
|
||||||
self.debug('[antizapret]: OFF!')
|
self.debug('[antizapret]: OFF!')
|
||||||
if not opener:
|
# python ssl Context support - PEP 0466
|
||||||
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
|
if 'https:' in url:
|
||||||
|
ssl_context = ssl.create_default_context()
|
||||||
|
ssl_context.check_hostname = False
|
||||||
|
ssl_context.verify_mode = ssl.CERT_NONE
|
||||||
|
log('urllib2.HTTPSHandler(context=ssl_context)')
|
||||||
|
opener.add_handler(urllib2.HTTPSHandler(context=ssl_context))
|
||||||
|
|
||||||
opener.addheaders = headers
|
opener.addheaders = headers
|
||||||
if 0 < len(data):
|
if 0 < len(data):
|
||||||
encodedData = urllib.urlencode(data)
|
encodedData = urllib.urlencode(data)
|
||||||
|
@ -134,13 +142,14 @@ class SearcherABC:
|
||||||
self.log('[makeRequest]: HTTP Error, e.code=' + str(e.code))
|
self.log('[makeRequest]: HTTP Error, e.code=' + str(e.code))
|
||||||
return
|
return
|
||||||
#self.cookieJar.extract_cookies(response, urllib2)
|
#self.cookieJar.extract_cookies(response, urllib2)
|
||||||
|
#self.log(response.info().get('Set-Cookie'))
|
||||||
if response.info().get('Content-Encoding') == 'gzip':
|
if response.info().get('Content-Encoding') == 'gzip':
|
||||||
buf = StringIO(response.read())
|
buf = StringIO(response.read())
|
||||||
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
||||||
response = decomp.decompress(buf.getvalue())
|
text = decomp.decompress(buf.getvalue())
|
||||||
else:
|
else:
|
||||||
response = response.read()
|
text = response.read()
|
||||||
return response
|
return text
|
||||||
|
|
||||||
def askCaptcha(self, url):
|
def askCaptcha(self, url):
|
||||||
temp_dir = self.tempdir()
|
temp_dir = self.tempdir()
|
||||||
|
|
|
@ -32,7 +32,7 @@ import xbmcgui
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import Localization
|
import Localization
|
||||||
from functions import isSubtitle, DownloadDB, log, debug, is_writable,\
|
from functions import isSubtitle, DownloadDB, log, debug, is_writable,\
|
||||||
vista_check, windows_check, localize_path
|
vista_check, windows_check, localize_path, decode_str
|
||||||
|
|
||||||
class SkorbaLoader:
|
class SkorbaLoader:
|
||||||
magnetLink = None
|
magnetLink = None
|
||||||
|
@ -54,7 +54,7 @@ class SkorbaLoader:
|
||||||
if not is_writable(self.storageDirectory):
|
if not is_writable(self.storageDirectory):
|
||||||
xbmcgui.Dialog().ok(Localization.localize('Torrenter v2'),
|
xbmcgui.Dialog().ok(Localization.localize('Torrenter v2'),
|
||||||
Localization.localize('Your storage path is not writable or not local! Please change it in settings!'),
|
Localization.localize('Your storage path is not writable or not local! Please change it in settings!'),
|
||||||
Localization.localize(self.storageDirectory))
|
self.storageDirectory)
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -93,24 +93,14 @@ class SkorbaLoader:
|
||||||
else:
|
else:
|
||||||
if not xbmcvfs.exists(self.torrentFilesPath):
|
if not xbmcvfs.exists(self.torrentFilesPath):
|
||||||
xbmcvfs.mkdirs(self.torrentFilesPath)
|
xbmcvfs.mkdirs(self.torrentFilesPath)
|
||||||
torrentFile = self.torrentFilesPath + self.md5(
|
torrentFile = localize_path(os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent'))
|
||||||
torrentUrl) + '.torrent'
|
|
||||||
try:
|
try:
|
||||||
if not re.match("^http\:.+$", torrentUrl):
|
if not re.match("^[htps]+?://.+$|^://.+$", torrentUrl):
|
||||||
contentFile = xbmcvfs.File(torrentUrl, "rb")
|
log('xbmcvfs.File for %s' % torrentUrl)
|
||||||
content = contentFile.read()
|
content = xbmcvfs.File(torrentUrl, "rb").read()
|
||||||
contentFile.close()
|
|
||||||
else:
|
else:
|
||||||
request = urllib2.Request(torrentUrl)
|
log('request for %s' % torrentUrl)
|
||||||
request.add_header('Referer', torrentUrl)
|
content = self.makeRequest(torrentUrl)
|
||||||
request.add_header('Accept-encoding', 'gzip')
|
|
||||||
result = urllib2.urlopen(request)
|
|
||||||
if result.info().get('Content-Encoding') == 'gzip':
|
|
||||||
buf = StringIO(result.read())
|
|
||||||
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
|
||||||
content = decomp.decompress(buf.getvalue())
|
|
||||||
else:
|
|
||||||
content = result.read()
|
|
||||||
|
|
||||||
localFile = xbmcvfs.File(torrentFile, "w+b")
|
localFile = xbmcvfs.File(torrentFile, "w+b")
|
||||||
localFile.write(content)
|
localFile.write(content)
|
||||||
|
@ -128,7 +118,7 @@ class SkorbaLoader:
|
||||||
return
|
return
|
||||||
if not xbmcvfs.exists(self.torrentFilesPath):
|
if not xbmcvfs.exists(self.torrentFilesPath):
|
||||||
xbmcvfs.mkdirs(self.torrentFilesPath)
|
xbmcvfs.mkdirs(self.torrentFilesPath)
|
||||||
newFile = self.torrentFilesPath + self.md5(torrentUrl) + '.torrent'
|
newFile = localize_path(self.torrentFilesPath + self.md5(torrentUrl) + '.torrent')
|
||||||
if newFile != torrentFile:
|
if newFile != torrentFile:
|
||||||
if xbmcvfs.exists(newFile):
|
if xbmcvfs.exists(newFile):
|
||||||
xbmcvfs.delete(newFile)
|
xbmcvfs.delete(newFile)
|
||||||
|
@ -145,7 +135,30 @@ class SkorbaLoader:
|
||||||
self.torrentFileInfo = self.lt.torrent_info(e)
|
self.torrentFileInfo = self.lt.torrent_info(e)
|
||||||
self.torrentFile = torrentFile
|
self.torrentFile = torrentFile
|
||||||
return self.torrentFile
|
return self.torrentFile
|
||||||
|
|
||||||
|
def makeRequest(self, torrentUrl):
|
||||||
|
torrentUrl = re.sub('^://', 'http://', torrentUrl)
|
||||||
|
x = re.search("://(.+?)/|://(.+?)$", torrentUrl)
|
||||||
|
if x:
|
||||||
|
baseurl = x.group(1) if x.group(1) else x.group(2)
|
||||||
|
else:
|
||||||
|
baseurl =''
|
||||||
|
|
||||||
|
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', 'http://%s/' % baseurl), ('Accept-encoding', 'gzip'), ]
|
||||||
|
|
||||||
|
opener = urllib2.build_opener()
|
||||||
|
opener.addheaders = headers
|
||||||
|
result = opener.open(torrentUrl)
|
||||||
|
if result.info().get('Content-Encoding') == 'gzip':
|
||||||
|
buf = StringIO(result.read())
|
||||||
|
decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
||||||
|
content = decomp.decompress(buf.getvalue())
|
||||||
|
else:
|
||||||
|
content = result.read()
|
||||||
|
return content
|
||||||
|
|
||||||
def getMagnetInfo(self):
|
def getMagnetInfo(self):
|
||||||
magnetSettings = {
|
magnetSettings = {
|
||||||
'url': self.magnetLink,
|
'url': self.magnetLink,
|
||||||
|
@ -157,14 +170,11 @@ class SkorbaLoader:
|
||||||
}
|
}
|
||||||
progressBar = xbmcgui.DialogProgress()
|
progressBar = xbmcgui.DialogProgress()
|
||||||
progressBar.create(Localization.localize('Please Wait'), Localization.localize('Magnet-link is converting'))
|
progressBar.create(Localization.localize('Please Wait'), Localization.localize('Magnet-link is converting'))
|
||||||
#try:
|
|
||||||
self.torrentHandle = self.session.add_torrent(magnetSettings)
|
self.torrentHandle = self.session.add_torrent(magnetSettings)
|
||||||
#except:
|
|
||||||
# self.torrentHandle = self.lt.add_magnet_uri(self.session, self.magnetLink, magnetSettings)
|
|
||||||
iterator = 0
|
iterator = 0
|
||||||
|
if self.enable_dht: self.torrentHandle.force_dht_announce()
|
||||||
while iterator < 100:
|
while iterator < 100:
|
||||||
xbmc.sleep(500)
|
xbmc.sleep(500)
|
||||||
if self.enable_dht: self.torrentHandle.force_dht_announce()
|
|
||||||
progressBar.update(iterator, Localization.localize('Please Wait'), Localization.localize('Magnet-link is converting')+'.' * (iterator % 4), ' ')
|
progressBar.update(iterator, Localization.localize('Please Wait'), Localization.localize('Magnet-link is converting')+'.' * (iterator % 4), ' ')
|
||||||
iterator += 1
|
iterator += 1
|
||||||
if progressBar.iscanceled():
|
if progressBar.iscanceled():
|
||||||
|
@ -237,8 +247,9 @@ class SkorbaLoader:
|
||||||
|
|
||||||
def getContentList(self):
|
def getContentList(self):
|
||||||
filelist = []
|
filelist = []
|
||||||
|
#from functions import decode_str
|
||||||
for contentId, contentFile in enumerate(self.torrentFileInfo.files()):
|
for contentId, contentFile in enumerate(self.torrentFileInfo.files()):
|
||||||
stringdata = {"title": localize_path(contentFile.path), "size": contentFile.size, "ind": int(contentId),
|
stringdata = {"title": contentFile.path, "size": contentFile.size, "ind": int(contentId),
|
||||||
'offset': contentFile.offset}
|
'offset': contentFile.offset}
|
||||||
filelist.append(stringdata)
|
filelist.append(stringdata)
|
||||||
return filelist
|
return filelist
|
||||||
|
@ -307,13 +318,13 @@ class SkorbaLoader:
|
||||||
else:
|
else:
|
||||||
for i in range(self.torrentFileInfo.num_pieces()):
|
for i in range(self.torrentFileInfo.num_pieces()):
|
||||||
self.torrentHandle.piece_priority(i, 6)
|
self.torrentHandle.piece_priority(i, 6)
|
||||||
|
del db
|
||||||
thread.start_new_thread(self.downloadLoop, (title,))
|
thread.start_new_thread(self.downloadLoop, (title,))
|
||||||
|
|
||||||
def downloadLoop(self, title):
|
def downloadLoop(self, title):
|
||||||
db = DownloadDB()
|
db = DownloadDB()
|
||||||
status = 'downloading'
|
status = 'downloading'
|
||||||
while db.get(title) and status != 'stopped':
|
while db.get(title) and status != 'stopped':
|
||||||
xbmc.sleep(3000)
|
|
||||||
status = db.get_status(title)
|
status = db.get_status(title)
|
||||||
if not self.paused:
|
if not self.paused:
|
||||||
if status == 'pause':
|
if status == 'pause':
|
||||||
|
@ -332,7 +343,9 @@ class SkorbaLoader:
|
||||||
iterator = int(s.progress * 100)
|
iterator = int(s.progress * 100)
|
||||||
info['progress'] = iterator
|
info['progress'] = iterator
|
||||||
db.update(title, info)
|
db.update(title, info)
|
||||||
self.debug()
|
#self.debug()
|
||||||
|
xbmc.sleep(3000)
|
||||||
|
log('out of downloadLoop')
|
||||||
self.session.remove_torrent(self.torrentHandle)
|
self.session.remove_torrent(self.torrentHandle)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
19
addon.xml
|
@ -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.5.2" provider-name="DiMartino">
|
<addon id="plugin.video.torrenter" name="Torrenter" version="2.6.2" provider-name="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"/>
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
<import addon="script.module.torrent2http"/>
|
<import addon="script.module.torrent2http"/>
|
||||||
<import addon="script.module.pyrrent2http"/>
|
<import addon="script.module.pyrrent2http"/>
|
||||||
<import addon="script.module.chardet" />
|
<import addon="script.module.chardet" />
|
||||||
|
<import addon="script.module.pyxbmct"/>
|
||||||
</requires>
|
</requires>
|
||||||
<extension point="xbmc.python.pluginsource" provides="video" library="default.py">
|
<extension point="xbmc.python.pluginsource" provides="video" library="default.py">
|
||||||
<provides>video</provides>
|
<provides>video</provides>
|
||||||
|
@ -23,10 +24,14 @@
|
||||||
</summary>
|
</summary>
|
||||||
<description lang='ru'>Так же плагин может добавлять, проигрывать и управлять скачками в торрент клиентах (uTorrent, Transmisson, Deluge и Vuse, qBittorrent) или средставми python-libtorrent.
|
<description lang='ru'>Так же плагин может добавлять, проигрывать и управлять скачками в торрент клиентах (uTorrent, Transmisson, Deluge и Vuse, qBittorrent) или средставми python-libtorrent.
|
||||||
</description>
|
</description>
|
||||||
<disclaimer lang='ru'>GNU GPLv3 http://www.gnu.org/licenses/</disclaimer>
|
<disclaimer lang='ru'>GNU GPLv3 http://www.gnu.org/licenses/</disclaimer>
|
||||||
<forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum>
|
<summary lang='es'>Complemento que nos permite ver vídeos que se distribuyen en redes BitTorrent sin necesidad de descargarlos previamente por completo.
|
||||||
<website>http://xbmc.ru/forum/showthread.php?t=6837</website>
|
</summary>
|
||||||
<email>skype:kyonkodura</email>
|
<description lang='es'>También gestiona torrents y nos deja elegir entre su propio cliente interno y otros externos (μTorrent, Transmission, Deluge, Vuze, qBittorrent), el cliente BitTorrent con el que realizar las descargas.
|
||||||
<source>https://github.com/DiMartinoXBMC/plugin.video.torrenter</source>
|
</description>
|
||||||
|
<forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum>
|
||||||
|
<website>http://xbmc.ru/forum/showthread.php?t=6837</website>
|
||||||
|
<email>skype:kyonkodura</email>
|
||||||
|
<source>https://github.com/DiMartinoXBMC/plugin.video.torrenter</source>
|
||||||
</extension>
|
</extension>
|
||||||
</addon>
|
</addon>
|
||||||
|
|
|
@ -1,13 +1,40 @@
|
||||||
English changelog at http://bit.ly/1MfSVUP
|
English changelog at http://bit.ly/1MfSVUP
|
||||||
|
|
||||||
|
[B]Version 2.6.2[/B]
|
||||||
|
[+] История Просмотров: Перемотка при внешнем вызове
|
||||||
|
|
||||||
|
[B]Version 2.6.1[/B]
|
||||||
|
[+] Окно Поиска: Использование окна в сторонних плагинах
|
||||||
|
|
||||||
|
[B]Version 2.6.0[/B]
|
||||||
|
[+] Окно Поиска: Полноценный релиз
|
||||||
|
[+] Настройки: Добавлена возможность отключения уведомлений
|
||||||
|
[+] История Просмотров: При аварийном выходе данные остаются
|
||||||
|
|
||||||
|
[B]Version 2.5.6[/B]
|
||||||
|
[+] Списки Медиа: Добавлен RuTorOrg
|
||||||
|
|
||||||
|
[B]Version 2.5.5[/B]
|
||||||
|
[+] Control Center: Исправлена работа выбора трекеров для определенного запроса
|
||||||
|
[+] Торрент-клиент: При скачивании одного файла торрент-клиентом теперь автоматически выбирается раздача
|
||||||
|
[+] .torrent Player: Исправлена работа (спасибо kolosovski)
|
||||||
|
[+] Окно Поиска: Добавлено Окно Поиска в режиме тестирования
|
||||||
|
|
||||||
|
[B]Version 2.5.4[/B]
|
||||||
|
[+] Исправлено "открыть без возврата". Спасибо viorel-m.
|
||||||
|
|
||||||
|
[B]Version 2.5.3[/B]
|
||||||
|
[+] Венгерский язык
|
||||||
|
[+] Совместимость с Коди 17
|
||||||
|
|
||||||
[B]Version 2.5.2[/B]
|
[B]Version 2.5.2[/B]
|
||||||
[+] Упорядочивание по разверу файла.
|
[+] Упорядочивание по размеру файла
|
||||||
|
|
||||||
[B]Version 2.5.1[/B]
|
[B]Version 2.5.1[/B]
|
||||||
[+] Исправлена работа с кодировками.
|
[+] Исправлена работа с кодировками
|
||||||
|
|
||||||
[B]Version 2.5.0[/B]
|
[B]Version 2.5.0[/B]
|
||||||
[+] НОВЫЙ проигрыватель pyrrent2http от inpos! Аналог torrent2http написаный на python, а не на GO.
|
[+] НОВЫЙ проигрыватель pyrrent2http от inpos! Аналог torrent2http написаный на python, а не на GO
|
||||||
[+] Проигрыватель: Ускорена повторная работа с торрентом - resume data (спасибо srg70 и RussakHH)
|
[+] Проигрыватель: Ускорена повторная работа с торрентом - resume data (спасибо srg70 и RussakHH)
|
||||||
|
|
||||||
[B]Version 2.4.6[/B]
|
[B]Version 2.4.6[/B]
|
||||||
|
|
|
@ -24,7 +24,7 @@ import xbmcaddon
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
from functions import getParameters, HistoryDB, Searchers, log
|
from functions import getParameters, HistoryDB, Searchers, log
|
||||||
from resources.pyxbmct.addonwindow import *
|
import pyxbmct
|
||||||
|
|
||||||
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
||||||
__language__ = __settings__.getLocalizedString
|
__language__ = __settings__.getLocalizedString
|
||||||
|
@ -39,7 +39,7 @@ if len(sys.argv) > 1:
|
||||||
else:
|
else:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
class ControlCenter(AddonDialogWindow):
|
class ControlCenter(pyxbmct.AddonDialogWindow):
|
||||||
def __init__(self, title, addtime=None):
|
def __init__(self, title, addtime=None):
|
||||||
super(ControlCenter, self).__init__(title)
|
super(ControlCenter, self).__init__(title)
|
||||||
|
|
||||||
|
@ -57,18 +57,17 @@ class ControlCenter(AddonDialogWindow):
|
||||||
if not providers:
|
if not providers:
|
||||||
self.db.set_providers(addtime, self.dic)
|
self.db.set_providers(addtime, self.dic)
|
||||||
else:
|
else:
|
||||||
for searcher in self.keys:
|
for searcher in self.dic.keys():
|
||||||
self.dic[searcher] = False
|
self.dic[searcher] = False
|
||||||
for searcher in providers:
|
for searcher in providers:
|
||||||
try:
|
try:
|
||||||
if searcher in self.keys:
|
if searcher in self.dic.keys():
|
||||||
self.dic[searcher] = True
|
self.dic[searcher] = True
|
||||||
except:
|
except:
|
||||||
pass
|
log('self.dic[searcher] except')
|
||||||
|
|
||||||
self.keys = self.dic.keys()
|
self.keys = self.dic.keys()
|
||||||
self.placed, self.button_columns, self.last_column_row = self.place()
|
self.placed, self.button_columns, self.last_column_row = self.place()
|
||||||
#print str((self.placed, self.button_columns, self.last_column_row))
|
|
||||||
else:
|
else:
|
||||||
self.button_columns=0
|
self.button_columns=0
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.set_active_controls()
|
self.set_active_controls()
|
||||||
self.set_navigation()
|
self.set_navigation()
|
||||||
# Connect a key action (Backspace) to close the window.
|
# Connect a key action (Backspace) to close the window.
|
||||||
self.connect(ACTION_NAV_BACK, self.close)
|
self.connect(pyxbmct.ACTION_NAV_BACK, self.close)
|
||||||
|
|
||||||
def place(self):
|
def place(self):
|
||||||
placed = {}
|
placed = {}
|
||||||
|
@ -90,7 +89,6 @@ class ControlCenter(AddonDialogWindow):
|
||||||
else:
|
else:
|
||||||
i += 1
|
i += 1
|
||||||
placed[item] = (j, i)
|
placed[item] = (j, i)
|
||||||
#print item+str((j, i))
|
|
||||||
return placed, j, i
|
return placed, j, i
|
||||||
|
|
||||||
def set_info_controls(self):
|
def set_info_controls(self):
|
||||||
|
@ -103,7 +101,7 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.radiobutton_top, self.radiobutton_bottom = [None, None, None], [None, None, None]
|
self.radiobutton_top, self.radiobutton_bottom = [None, None, None], [None, None, None]
|
||||||
for searcher in self.keys:
|
for searcher in self.keys:
|
||||||
place = self.placed[searcher]
|
place = self.placed[searcher]
|
||||||
self.radiobutton[searcher] = RadioButton(searcher)
|
self.radiobutton[searcher] = pyxbmct.RadioButton(searcher)
|
||||||
self.placeControl(self.radiobutton[searcher], place[0], place[1])
|
self.placeControl(self.radiobutton[searcher], place[0], place[1])
|
||||||
self.radiobutton[searcher].setSelected(self.dic[searcher])
|
self.radiobutton[searcher].setSelected(self.dic[searcher])
|
||||||
self.connect(self.radiobutton[searcher], self.radio_update)
|
self.connect(self.radiobutton[searcher], self.radio_update)
|
||||||
|
@ -112,32 +110,32 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
|
self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_install = Button(__language__(30415))
|
self.button_install = pyxbmct.Button(__language__(30415))
|
||||||
self.placeControl(self.button_install, 2 + self.button_columns, 0)
|
self.placeControl(self.button_install, 2 + self.button_columns, 0)
|
||||||
self.connect(self.button_install, self.installSearcher)
|
self.connect(self.button_install, self.installSearcher)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_openserchset = Button(__language__(30416))
|
self.button_openserchset = pyxbmct.Button(__language__(30416))
|
||||||
self.placeControl(self.button_openserchset, 2 + self.button_columns, 1)
|
self.placeControl(self.button_openserchset, 2 + self.button_columns, 1)
|
||||||
self.connect(self.button_openserchset, self.openSearcherSettings)
|
self.connect(self.button_openserchset, self.openSearcherSettings)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_clearstor = Button(__language__(30417))
|
self.button_clearstor = pyxbmct.Button(__language__(30417))
|
||||||
self.placeControl(self.button_clearstor, 2 + self.button_columns, 2)
|
self.placeControl(self.button_clearstor, 2 + self.button_columns, 2)
|
||||||
self.connect(self.button_clearstor, self.clearStorage)
|
self.connect(self.button_clearstor, self.clearStorage)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_openset = Button(__language__(30413))
|
self.button_openset = pyxbmct.Button(__language__(30413))
|
||||||
self.placeControl(self.button_openset, 3 + self.button_columns, 0)
|
self.placeControl(self.button_openset, 3 + self.button_columns, 0)
|
||||||
self.connect(self.button_openset, self.openSettings)
|
self.connect(self.button_openset, self.openSettings)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_utorrent = Button(__language__(30414))
|
self.button_utorrent = pyxbmct.Button(__language__(30414))
|
||||||
self.placeControl(self.button_utorrent, 3 + self.button_columns, 1)
|
self.placeControl(self.button_utorrent, 3 + self.button_columns, 1)
|
||||||
self.connect(self.button_utorrent, self.openUtorrent)
|
self.connect(self.button_utorrent, self.openUtorrent)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_close = Button(__language__(30412))
|
self.button_close = pyxbmct.Button(__language__(30412))
|
||||||
self.placeControl(self.button_close, 3 + self.button_columns, 2)
|
self.placeControl(self.button_close, 3 + self.button_columns, 2)
|
||||||
self.connect(self.button_close, self.close)
|
self.connect(self.button_close, self.close)
|
||||||
|
|
||||||
|
@ -171,8 +169,6 @@ class ControlCenter(AddonDialogWindow):
|
||||||
ser = placed_keys[placed_values.index((place[0], place[1] - 1))]
|
ser = placed_keys[placed_values.index((place[0], place[1] - 1))]
|
||||||
self.radiobutton[searcher].controlLeft(self.radiobutton[ser])
|
self.radiobutton[searcher].controlLeft(self.radiobutton[ser])
|
||||||
|
|
||||||
#print str((self.button_columns, self.last_column_row))
|
|
||||||
#print searcher
|
|
||||||
if self.more_two_searcher:
|
if self.more_two_searcher:
|
||||||
if place == (self.button_columns, self.last_column_row) and self.last_column_row < 2:
|
if place == (self.button_columns, self.last_column_row) and self.last_column_row < 2:
|
||||||
ser = placed_keys[placed_values.index((place[0] - 1, place[1] + 1))]
|
ser = placed_keys[placed_values.index((place[0] - 1, place[1] + 1))]
|
||||||
|
@ -247,7 +243,10 @@ class ControlCenter(AddonDialogWindow):
|
||||||
def openSearcherSettings(self):
|
def openSearcherSettings(self):
|
||||||
slist=Searchers().activeExternal()
|
slist=Searchers().activeExternal()
|
||||||
if len(slist)>0:
|
if len(slist)>0:
|
||||||
ret = xbmcgui.Dialog().select(__language__(30418), slist)
|
if len(slist) == 1:
|
||||||
|
ret = 0
|
||||||
|
else:
|
||||||
|
ret = xbmcgui.Dialog().select(__language__(30418), slist)
|
||||||
if ret > -1 and ret < len(slist):
|
if ret > -1 and ret < len(slist):
|
||||||
sid = slist[ret]
|
sid = slist[ret]
|
||||||
Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
|
Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
|
||||||
|
|
288
functions.py
|
@ -43,7 +43,8 @@ except:
|
||||||
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
||||||
__language__ = __settings__.getLocalizedString
|
__language__ = __settings__.getLocalizedString
|
||||||
ROOT = __settings__.getAddonInfo('path') # .decode('utf-8').encode(sys.getfilesystemencoding())
|
ROOT = __settings__.getAddonInfo('path') # .decode('utf-8').encode(sys.getfilesystemencoding())
|
||||||
userStorageDirectory = __settings__.getSetting("storage")
|
userStorageDirectory = xbmc.translatePath(__settings__.getSetting("storage"))
|
||||||
|
torrentFilesDirectory = 'torrents'
|
||||||
USERAGENT = "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0"
|
USERAGENT = "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0"
|
||||||
__addonpath__ = __settings__.getAddonInfo('path')
|
__addonpath__ = __settings__.getAddonInfo('path')
|
||||||
icon = os.path.join(__addonpath__, 'icon.png')
|
icon = os.path.join(__addonpath__, 'icon.png')
|
||||||
|
@ -92,10 +93,10 @@ def clearStorage(userStorageDirectory, force = False):
|
||||||
if saved_bool:
|
if saved_bool:
|
||||||
shutil.move(saved_temp, saved)
|
shutil.move(saved_temp, saved)
|
||||||
|
|
||||||
showMessage(Localization.localize('Storage'), Localization.localize('Storage has been cleared'), forced=True)
|
showMessage(Localization.localize('Storage'), Localization.localize('Storage has been cleared'))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'), forced=True)
|
showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'))
|
||||||
log('[clearStorage]: fail storage '+userStorageDirectory + os.sep)
|
log('[clearStorage]: fail storage '+userStorageDirectory + os.sep)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -151,8 +152,9 @@ def debug(msg, forced=False):
|
||||||
|
|
||||||
|
|
||||||
def showMessage(heading, message, times=10000, forced=False):
|
def showMessage(heading, message, times=10000, forced=False):
|
||||||
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s, "%s")' % (
|
if forced or not getSettingAsBool('disable_notifications'):
|
||||||
heading.replace('"', "'"), message.replace('"', "'"), times, icon))
|
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s, "%s")' % (
|
||||||
|
heading.replace('"', "'"), message.replace('"', "'"), times, icon))
|
||||||
debug(str((heading.replace('"', "'"), message.replace('"', "'"), times, icon)))
|
debug(str((heading.replace('"', "'"), message.replace('"', "'"), times, icon)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -575,32 +577,52 @@ def view_style(func):
|
||||||
styles['sectionMenu'] = styles['Seasons'] = 'list'
|
styles['sectionMenu'] = styles['Seasons'] = 'list'
|
||||||
styles['uTorrentBrowser'] = styles['torrentPlayer'] = styles['openTorrent'] = 'wide'
|
styles['uTorrentBrowser'] = styles['torrentPlayer'] = styles['openTorrent'] = 'wide'
|
||||||
styles['showFilesList'] = styles['DownloadStatus'] = 'wide'
|
styles['showFilesList'] = styles['DownloadStatus'] = 'wide'
|
||||||
elif view_style in [1, 4, 5]:
|
elif view_style in [1, 4, 5, 7]:
|
||||||
styles['searchOption'] = 'info'
|
styles['searchOption'] = 'info'
|
||||||
styles['drawContent'] = styles['torrentPlayer'] = styles['openTorrent'] = styles['drawtrackerList'] = 'info'
|
styles['drawContent'] = styles['torrentPlayer'] = styles['openTorrent'] = styles['drawtrackerList'] = 'info'
|
||||||
styles['uTorrentBrowser'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
styles['uTorrentBrowser'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
||||||
styles['showFilesList'] = styles['sectionMenu'] = 'wide'
|
styles['showFilesList'] = styles['sectionMenu'] = 'wide'
|
||||||
styles['List'] = styles['drawcontentList'] = 'info3'
|
styles['List'] = styles['drawcontentList'] = 'info3'
|
||||||
|
|
||||||
if view_style == 1:
|
if view_style in [1, 7]:
|
||||||
styles['uTorrentBrowser'] = styles['torrentPlayer'] = 'wide'
|
styles['uTorrentBrowser'] = styles['torrentPlayer'] = 'wide'
|
||||||
styles['openTorrent'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
styles['openTorrent'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
||||||
styles['sectionMenu'] = 'icons'
|
styles['sectionMenu'] = 'icons'
|
||||||
elif view_style == 5:
|
elif view_style == 5:
|
||||||
styles['uTorrentBrowser'] = styles['torrentPlayer'] = 'wide'
|
styles['uTorrentBrowser'] = styles['torrentPlayer'] = 'wide'
|
||||||
styles['openTorrent'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
styles['openTorrent'] = styles['History'] = styles['DownloadStatus'] = 'wide'
|
||||||
styles['drawtrackerList'] = styles['drawContent'] = styles['List'] = styles['sectionMenu'] = 'icons'
|
styles['drawtrackerList'] = styles['drawContent'] = styles['List'] = styles['sectionMenu'] = 'list'
|
||||||
styles['searchOption'] = 'info'
|
styles['searchOption'] = 'info'
|
||||||
|
|
||||||
|
if view_style == 8:
|
||||||
|
styles['sectionMenu'] = 'thumbnails' #меню
|
||||||
|
styles['List'] = 'biglist'
|
||||||
|
styles['Seasons'] = 'biglist'
|
||||||
|
styles['uTorrentBrowser'] = 'biglist'
|
||||||
|
styles['torrentPlayer'] = 'biglist'
|
||||||
|
styles['openTorrent'] = 'biglist'
|
||||||
|
styles['History'] = 'biglist' #история поиска
|
||||||
|
styles['DownloadStatus'] = 'biglist' #статус загрузки
|
||||||
|
styles['drawtrackerList'] = 'biglist'
|
||||||
|
styles['drawContent'] = 'list' #списки медиа
|
||||||
|
styles['drawcontentList'] = 'extrainfo' #списки медиа - лист
|
||||||
|
styles['searchOption'] = 'biglist'
|
||||||
|
styles['showFilesList'] = 'biglist'
|
||||||
|
|
||||||
|
|
||||||
if view_style in [1, 3, 4, 5]:
|
if view_style in [1, 3, 4, 5]:
|
||||||
num_skin = 0
|
num_skin = 0
|
||||||
elif view_style == 2:
|
elif view_style == 2:
|
||||||
num_skin = 1
|
num_skin = 1
|
||||||
elif view_style == 6:
|
elif view_style == 6:
|
||||||
num_skin = 2
|
num_skin = 2
|
||||||
|
elif view_style == 7:
|
||||||
|
num_skin = 3
|
||||||
|
if view_style == 8:
|
||||||
|
num_skin = 4
|
||||||
|
|
||||||
style = styles.get(func)
|
style = styles.get(func)
|
||||||
# debug('[view_style]: lock '+str(style))
|
log('[view_style]: lock '+str(style)+' for '+str(func))
|
||||||
lockView(style, num_skin)
|
lockView(style, num_skin)
|
||||||
|
|
||||||
|
|
||||||
|
@ -610,23 +632,38 @@ def lockView(viewId='info', num_skin=0):
|
||||||
{'list': 50, 'info': 50, 'wide': 51, 'icons': 500, 'info3': 515, }, # Confluence
|
{'list': 50, 'info': 50, 'wide': 51, 'icons': 500, 'info3': 515, }, # Confluence
|
||||||
{'list': 50, 'info': 51, 'wide': 52, 'icons': 53, }, # Transperency!
|
{'list': 50, 'info': 51, 'wide': 52, 'icons': 53, }, # Transperency!
|
||||||
{'list': 55, 'info': 55, 'wide': 55, 'icons': 55, 'info3': 55, }, # Aeon Nox
|
{'list': 55, 'info': 55, 'wide': 55, 'icons': 55, 'info3': 55, }, # Aeon Nox
|
||||||
|
{'list': 50, 'info': 54, 'wide': 55, 'icons': 54, 'info3': 500, }, # Estuary
|
||||||
|
{'list': 50, 'bigwide': 51, 'biglist': 52, 'poster': 53, 'banner': 54, 'wall': 55, 'mediainfo': 56, 'extrainfo': 57, "cards":58, "bannerwall":59, 'thumbnails': 500, 'postersquare': 503, 'wallsquare': 505, }, # Arctic: Zephyr
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
|
if viewId == 'wide' and num_skin == 3:
|
||||||
|
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
||||||
xbmc.executebuiltin("Container.SetViewMode(%s)" % str(skinOptimizations[num_skin][viewId]))
|
xbmc.executebuiltin("Container.SetViewMode(%s)" % str(skinOptimizations[num_skin][viewId]))
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
''' Estuary
|
||||||
|
<include>View_50_List</include>
|
||||||
|
<include>View_51_Poster</include>
|
||||||
|
<include>View_52_IconWall</include>
|
||||||
|
<include>View_53_Shift</include>
|
||||||
|
<include>View_54_InfoWall</include>
|
||||||
|
<include>View_55_WideList</include>
|
||||||
|
<include>View_500_SmallThumb</include>
|
||||||
|
<include>View_501_Banner</include>
|
||||||
|
<include>View_502_FanArt</include>
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
<include>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
|
||||||
|
<include>MediaListView3</include> <!-- view id = 503 -->
|
||||||
|
<include>MediaListView2</include> <!-- view id = 504 -->
|
||||||
|
<include>MediaListView4</include> <!-- view id = 515 -->
|
||||||
|
<include>WideIconView</include> <!-- view id = 505 -->
|
||||||
|
<include>MusicVideoInfoListView</include> <!-- view id = 511 -->
|
||||||
|
<include>AddonInfoListView1</include> <!-- view id = 550 -->
|
||||||
|
<include>AddonInfoThumbView1</include> <!-- view id = 551 -->
|
||||||
|
<include>LiveTVView1</include> <!-- view id = 560 -->
|
||||||
'''
|
'''
|
||||||
<include>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
|
|
||||||
<include>MediaListView3</include> <!-- view id = 503 -->
|
|
||||||
<include>MediaListView2</include> <!-- view id = 504 -->
|
|
||||||
<include>MediaListView4</include> <!-- view id = 515 -->
|
|
||||||
<include>WideIconView</include> <!-- view id = 505 -->
|
|
||||||
<include>MusicVideoInfoListView</include> <!-- view id = 511 -->
|
|
||||||
<include>AddonInfoListView1</include> <!-- view id = 550 -->
|
|
||||||
<include>AddonInfoThumbView1</include> <!-- view id = 551 -->
|
|
||||||
<include>LiveTVView1</include> <!-- view id = 560 -->
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def torrent_dir():
|
def torrent_dir():
|
||||||
|
@ -899,7 +936,6 @@ class HistoryDB:
|
||||||
self.cur.execute('select providers from history where addtime="' + addtime + '"')
|
self.cur.execute('select providers from history where addtime="' + addtime + '"')
|
||||||
x = self.cur.fetchone()
|
x = self.cur.fetchone()
|
||||||
self._close()
|
self._close()
|
||||||
# print 'get_providers: '+str(x[0].split(',') if x and x[0]!='' else None)
|
|
||||||
return x[0].split(',') if x and x[0] != '' else None
|
return x[0].split(',') if x and x[0] != '' else None
|
||||||
|
|
||||||
def set_providers(self, addtime, providers):
|
def set_providers(self, addtime, providers):
|
||||||
|
@ -916,7 +952,7 @@ class HistoryDB:
|
||||||
self._close()
|
self._close()
|
||||||
|
|
||||||
def change_providers(self, addtime, searcher):
|
def change_providers(self, addtime, searcher):
|
||||||
self._connect()
|
#self._connect()
|
||||||
providers = self.get_providers(addtime)
|
providers = self.get_providers(addtime)
|
||||||
keys = Searchers().dic().keys()
|
keys = Searchers().dic().keys()
|
||||||
if providers and len(providers) > 0:
|
if providers and len(providers) > 0:
|
||||||
|
@ -928,8 +964,8 @@ class HistoryDB:
|
||||||
if i not in keys:
|
if i not in keys:
|
||||||
providers.remove(i)
|
providers.remove(i)
|
||||||
self.set_providers(addtime, providers)
|
self.set_providers(addtime, providers)
|
||||||
self.db.commit()
|
#self.db.commit()
|
||||||
self._close()
|
#self._close()
|
||||||
|
|
||||||
def add(self, url):
|
def add(self, url):
|
||||||
self._connect()
|
self._connect()
|
||||||
|
@ -1035,13 +1071,23 @@ class WatchedHistoryDB:
|
||||||
self._close()
|
self._close()
|
||||||
return x if x else None
|
return x if x else None
|
||||||
|
|
||||||
def add(self, filename, foldername = None, seek = 0, length = 1, ind = 0, size = 0):
|
def getbypathind(self, path, ind):
|
||||||
watchedPercent = int((float(seek) / float(length)) * 100)
|
self._connect()
|
||||||
|
self.cur.execute('select seek from history where path="' + path + '" AND ind=' + ind)
|
||||||
|
x = self.cur.fetchone()
|
||||||
|
self._close()
|
||||||
|
return x if x else None
|
||||||
|
|
||||||
|
def add(self, filename, path, foldername = None, seek = 0, length = 1, ind = 0, size = 0):
|
||||||
|
try:
|
||||||
|
watchedPercent = int((float(seek) / float(length if length else 1)) * 100)
|
||||||
|
except:
|
||||||
|
watchedPercent = 0
|
||||||
max_history_add = int(__settings__.getSetting('max_history_add'))
|
max_history_add = int(__settings__.getSetting('max_history_add'))
|
||||||
if self.history_bool and watchedPercent <= max_history_add:
|
if self.history_bool and watchedPercent <= max_history_add:
|
||||||
self._connect()
|
self._connect()
|
||||||
url = __settings__.getSetting("lastTorrentUrl")
|
url = __settings__.getSetting("lastTorrentUrl")
|
||||||
path = __settings__.getSetting("lastTorrent")
|
#path = __settings__.getSetting("lastTorrent")
|
||||||
if not foldername:
|
if not foldername:
|
||||||
foldername = ''
|
foldername = ''
|
||||||
self.cur.execute('delete from history where filename="' + decode(filename) + '"')
|
self.cur.execute('delete from history where filename="' + decode(filename) + '"')
|
||||||
|
@ -1289,9 +1335,76 @@ def search(url, searchersList, isApi=None):
|
||||||
progressBar.close()
|
progressBar.close()
|
||||||
|
|
||||||
for k in result.keys():
|
for k in result.keys():
|
||||||
filesList.extend(result[k])
|
if result.get(k):
|
||||||
|
filesList.extend(result[k])
|
||||||
return filesList
|
return filesList
|
||||||
|
|
||||||
|
def get_filesList(query, searchersList, addtime = None):
|
||||||
|
if __settings__.getSetting('history')=='true':
|
||||||
|
HistoryDB().add(query)
|
||||||
|
|
||||||
|
filesList=search(query, searchersList)
|
||||||
|
if __settings__.getSetting('sort_search')=='true':
|
||||||
|
__settings__.setSetting('sort_search','1')
|
||||||
|
if int(__settings__.getSetting('sort_search'))==0:
|
||||||
|
filesList = sorted(filesList, key=lambda x: x[0], reverse=True)
|
||||||
|
elif int(__settings__.getSetting('sort_search'))==2:
|
||||||
|
filesList = sorted(filesList, key=lambda x: x[4], reverse=False)
|
||||||
|
|
||||||
|
debug('get_filesList filesList: '+str(filesList))
|
||||||
|
|
||||||
|
return filesList
|
||||||
|
|
||||||
|
def get_searchersList(addtime = None):
|
||||||
|
searchersList = []
|
||||||
|
if addtime:
|
||||||
|
providers=HistoryDB().get_providers(addtime)
|
||||||
|
if providers:
|
||||||
|
for searcher in providers:
|
||||||
|
searchersList.append(searcher)
|
||||||
|
if not addtime or not searchersList:
|
||||||
|
searchersList = Searchers().get_active()
|
||||||
|
|
||||||
|
debug('get_searchersList: '+str(searchersList))
|
||||||
|
|
||||||
|
return searchersList
|
||||||
|
|
||||||
|
def get_contentList(url):
|
||||||
|
import Downloader
|
||||||
|
|
||||||
|
url = urllib.unquote_plus(url)
|
||||||
|
debug('0' + __settings__.getSetting("lastTorrent"))
|
||||||
|
|
||||||
|
__settings__.setSetting("lastTorrentUrl", url)
|
||||||
|
classMatch = re.search('(\w+)::(.+)', url)
|
||||||
|
if classMatch:
|
||||||
|
searcher = classMatch.group(1)
|
||||||
|
url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
|
||||||
|
__settings__.setSetting("lastTorrent", url)
|
||||||
|
|
||||||
|
torrent = Downloader.Torrent(userStorageDirectory, url, torrentFilesDirectory=torrentFilesDirectory)
|
||||||
|
|
||||||
|
debug('1'+__settings__.getSetting("lastTorrent"))
|
||||||
|
filename = torrent.saveTorrent(url)
|
||||||
|
__settings__.setSetting("lastTorrent", filename)
|
||||||
|
debug('2'+__settings__.getSetting("lastTorrent"))
|
||||||
|
|
||||||
|
append_filesize = __settings__.getSetting("append_filesize") == 'true'
|
||||||
|
|
||||||
|
contentList = []
|
||||||
|
for filedict in torrent.getContentList():
|
||||||
|
fileTitle = filedict.get('title')
|
||||||
|
size = filedict.get('size')
|
||||||
|
if size:
|
||||||
|
if append_filesize:
|
||||||
|
fileTitle += ' [%d MB]' % (size / 1024 / 1024)
|
||||||
|
|
||||||
|
contentList.append([unescape(fileTitle), str(filedict.get('ind')), size])
|
||||||
|
# contentList = sorted(contentList, key=lambda x: x[0])
|
||||||
|
|
||||||
|
debug('get_contentList contentList: ' + str(contentList))
|
||||||
|
|
||||||
|
return contentList, filename
|
||||||
|
|
||||||
def join_list(l, char=', ', replace=''):
|
def join_list(l, char=', ', replace=''):
|
||||||
string=''
|
string=''
|
||||||
|
@ -1306,6 +1419,8 @@ class Contenters():
|
||||||
|
|
||||||
def first_time(self, scrapperDB_ver, language='ru'):
|
def first_time(self, scrapperDB_ver, language='ru'):
|
||||||
from resources.scrapers.scrapers import Scrapers
|
from resources.scrapers.scrapers import Scrapers
|
||||||
|
if language not in ['en','ru','he']:
|
||||||
|
language = 'ru'
|
||||||
searcher = 'metadata'
|
searcher = 'metadata'
|
||||||
redl = False
|
redl = False
|
||||||
scrapperDB_ver = scrapperDB_ver[language]
|
scrapperDB_ver = scrapperDB_ver[language]
|
||||||
|
@ -1358,7 +1473,7 @@ class Contenters():
|
||||||
searchersList = []
|
searchersList = []
|
||||||
dirList = os.listdir(ROOT + os.sep + 'resources' + os.sep + 'contenters')
|
dirList = os.listdir(ROOT + os.sep + 'resources' + os.sep + 'contenters')
|
||||||
for searcherFile in dirList:
|
for searcherFile in dirList:
|
||||||
if re.match('^(\w+)\.py$', searcherFile):
|
if re.match('^(\w+)\.py$', searcherFile) and searcherFile != '__init__.py':
|
||||||
searchersList.append(searcherFile.replace('.py', ''))
|
searchersList.append(searcherFile.replace('.py', ''))
|
||||||
return searchersList
|
return searchersList
|
||||||
|
|
||||||
|
@ -1770,6 +1885,29 @@ def first_run_250():
|
||||||
#ok = xbmcgui.Dialog().ok('< %s >' % (Localization.localize('Torrenter Update ') + '2.4.2'),
|
#ok = xbmcgui.Dialog().ok('< %s >' % (Localization.localize('Torrenter Update ') + '2.4.2'),
|
||||||
# Localization.localize('Torrent2HTTP enabled! Can be changed in Settings.'))
|
# Localization.localize('Torrent2HTTP enabled! Can be changed in Settings.'))
|
||||||
|
|
||||||
|
def first_run_260():
|
||||||
|
if not __settings__.getSetting('first_run_260') == 'True':
|
||||||
|
yes=xbmcgui.Dialog().yesno('< %s >' % (Localization.localize('Torrenter Update ') + '2.6.0'),
|
||||||
|
Localization.localize('Torrenter Search Window')+' '
|
||||||
|
+Localization.localize('is recommended for Kodi 17 users and now out of beta.')
|
||||||
|
+Localization.localize('You can disable it usage in Settings.'),
|
||||||
|
Localization.localize('Would you like to try it?'),)
|
||||||
|
if yes:
|
||||||
|
import searchwindow
|
||||||
|
searchwindow.main()
|
||||||
|
|
||||||
|
|
||||||
|
def estuary():
|
||||||
|
if __settings__.getSetting('skin_optimization') not in ['7', '0'] and \
|
||||||
|
__settings__.getSetting('ask17_skin_optimization') != 'True':
|
||||||
|
|
||||||
|
yes = xbmcgui.Dialog().yesno('< %s >' % (Localization.localize('Torrenter Update ') + '2.6.0'),
|
||||||
|
Localization.localize('Torrenter has a better view style for Kodi 17 default skin.'),
|
||||||
|
Localization.localize('Would you like to try it?'), )
|
||||||
|
if yes:
|
||||||
|
__settings__.setSetting('skin_optimization', '7')
|
||||||
|
__settings__.setSetting('ask_skin_optimization', 'True')
|
||||||
|
|
||||||
def seeking_warning(seek):
|
def seeking_warning(seek):
|
||||||
if __settings__.getSetting('torrent_player')!='1':
|
if __settings__.getSetting('torrent_player')!='1':
|
||||||
seek_point = '%02d:%02d:%02d' % ((seek / (60*60)), (seek / 60) % 60, seek % 60)
|
seek_point = '%02d:%02d:%02d' % ((seek / (60*60)), (seek / 60) % 60, seek % 60)
|
||||||
|
@ -1910,7 +2048,7 @@ def check_network_advancedsettings():
|
||||||
file_cont='''<advancedsettings>
|
file_cont='''<advancedsettings>
|
||||||
<network>
|
<network>
|
||||||
<buffermode>2</buffermode>
|
<buffermode>2</buffermode>
|
||||||
<curlclienttimeout>30</curlclienttimeout>
|
<curlclienttimeout>30</curlclienttimeout>
|
||||||
<cachemembuffersize>252420</cachemembuffersize>
|
<cachemembuffersize>252420</cachemembuffersize>
|
||||||
<readbufferfactor>5</readbufferfactor>
|
<readbufferfactor>5</readbufferfactor>
|
||||||
</network>
|
</network>
|
||||||
|
@ -1927,7 +2065,7 @@ def check_network_advancedsettings():
|
||||||
'''<advancedsettings>
|
'''<advancedsettings>
|
||||||
<network>
|
<network>
|
||||||
<buffermode>2</buffermode>
|
<buffermode>2</buffermode>
|
||||||
<curlclienttimeout>30</curlclienttimeout>
|
<curlclienttimeout>30</curlclienttimeout>
|
||||||
<cachemembuffersize>252420</cachemembuffersize>
|
<cachemembuffersize>252420</cachemembuffersize>
|
||||||
<readbufferfactor>5</readbufferfactor>
|
<readbufferfactor>5</readbufferfactor>
|
||||||
</network>
|
</network>
|
||||||
|
@ -2063,13 +2201,19 @@ def localize_path(path):
|
||||||
|
|
||||||
def encode_msg(msg):
|
def encode_msg(msg):
|
||||||
try:
|
try:
|
||||||
msg = isinstance(msg, unicode) and msg.encode('utf-8') or msg
|
msg = isinstance(msg, unicode) and msg.encode(
|
||||||
|
(sys.getfilesystemencoding() not in ('ascii', 'ANSI_X3.4-1968')) and sys.getfilesystemencoding() or 'utf-8') or msg
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
log(traceback.format_exc())
|
log(traceback.format_exc())
|
||||||
msg = ensure_str(msg)
|
msg = ensure_str(msg)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
def decode_str(string, encoding='utf-8'):
|
||||||
|
if not isinstance(string, unicode):
|
||||||
|
string = string.decode(encoding)
|
||||||
|
return string
|
||||||
|
|
||||||
def get_platform():
|
def get_platform():
|
||||||
ret = {
|
ret = {
|
||||||
"arch": sys.maxsize > 2 ** 32 and "x64" or "x86",
|
"arch": sys.maxsize > 2 ** 32 and "x64" or "x86",
|
||||||
|
@ -2101,4 +2245,84 @@ def get_platform():
|
||||||
ret["os"] = "ios"
|
ret["os"] = "ios"
|
||||||
ret["arch"] = "arm"
|
ret["arch"] = "arm"
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def getTorrentClientIcon():
|
||||||
|
client = __settings__.getSetting("torrent")
|
||||||
|
if client == '1':
|
||||||
|
return 'transmission.png'
|
||||||
|
elif client == '2':
|
||||||
|
return 'vuze.png'
|
||||||
|
elif client == '3':
|
||||||
|
return 'deluge.png'
|
||||||
|
elif client == '4':
|
||||||
|
return 'qbittorrent.png'
|
||||||
|
else:
|
||||||
|
return 'torrent-client.png'
|
||||||
|
|
||||||
|
def get_item():
|
||||||
|
#some plugin.video.quasar magic
|
||||||
|
item = xbmcgui.ListItem(
|
||||||
|
path='',
|
||||||
|
label=xbmc.getInfoLabel("ListItem.Label"),
|
||||||
|
label2=xbmc.getInfoLabel("ListItem.label2"),
|
||||||
|
thumbnailImage=xbmc.getInfoLabel("ListItem.Art(thumb)"))
|
||||||
|
_infoLabels = {
|
||||||
|
"Title": xbmc.getInfoLabel("ListItem.Title"),
|
||||||
|
"OriginalTitle": xbmc.getInfoLabel("ListItem.OriginalTitle"),
|
||||||
|
"TVShowTitle": xbmc.getInfoLabel("ListItem.TVShowTitle"),
|
||||||
|
"Season": xbmc.getInfoLabel("ListItem.Season"),
|
||||||
|
"Episode": xbmc.getInfoLabel("ListItem.Episode"),
|
||||||
|
"Premiered": xbmc.getInfoLabel("ListItem.Premiered"),
|
||||||
|
"Plot": xbmc.getInfoLabel("ListItem.Plot"),
|
||||||
|
# "Date": xbmc.getInfoLabel("ListItem.Date"),
|
||||||
|
"VideoCodec": xbmc.getInfoLabel("ListItem.VideoCodec"),
|
||||||
|
"VideoResolution": xbmc.getInfoLabel("ListItem.VideoResolution"),
|
||||||
|
"VideoAspect": xbmc.getInfoLabel("ListItem.VideoAspect"),
|
||||||
|
"DBID": xbmc.getInfoLabel("ListItem.DBID"),
|
||||||
|
"DBTYPE": xbmc.getInfoLabel("ListItem.DBTYPE"),
|
||||||
|
"Writer": xbmc.getInfoLabel("ListItem.Writer"),
|
||||||
|
"Director": xbmc.getInfoLabel("ListItem.Director"),
|
||||||
|
"Rating": xbmc.getInfoLabel("ListItem.Rating"),
|
||||||
|
"Votes": xbmc.getInfoLabel("ListItem.Votes"),
|
||||||
|
"IMDBNumber": xbmc.getInfoLabel("ListItem.IMDBNumber"),
|
||||||
|
}
|
||||||
|
infoLabels = {}
|
||||||
|
for key, value in _infoLabels.iteritems():
|
||||||
|
if value:
|
||||||
|
infoLabels[key] = value
|
||||||
|
|
||||||
|
poster = xbmc.getInfoLabel("ListItem.Art(poster)")
|
||||||
|
if not poster:
|
||||||
|
poster = xbmc.getInfoLabel("ListItem.Art(tvshow.poster)")
|
||||||
|
|
||||||
|
item.setArt({
|
||||||
|
"poster": poster,
|
||||||
|
"banner": xbmc.getInfoLabel("ListItem.Art(banner)"),
|
||||||
|
"fanart": xbmc.getInfoLabel("ListItem.Art(fanart)")
|
||||||
|
})
|
||||||
|
|
||||||
|
item.setInfo(type='Video', infoLabels=infoLabels)
|
||||||
|
return item
|
||||||
|
|
||||||
|
def loadsw_onstop():
|
||||||
|
if __settings__.getSetting('loadsw_onstop') == 'true':
|
||||||
|
import searchwindow
|
||||||
|
params = {'mode': 'load'}
|
||||||
|
searchwindow.main(params)
|
||||||
|
|
||||||
|
def watched_seek(filename, ind):
|
||||||
|
db = WatchedHistoryDB()
|
||||||
|
seek = db.getbypathind(filename, ind)
|
||||||
|
log('[watched_seek] seek - '+str(seek))
|
||||||
|
if seek:
|
||||||
|
seek = seek[0]
|
||||||
|
seek = int(seek) if int(seek) > 3 * 60 else 0
|
||||||
|
if seek > 0:
|
||||||
|
seek_text = '%02d:%02d:%02d' % ((seek / (60 * 60)), (seek / 60) % 60, seek % 60)
|
||||||
|
dialog_items = [Localization.localize('Play (from %s)') % seek_text,
|
||||||
|
Localization.localize('Play (from start)')]
|
||||||
|
ret = xbmcgui.Dialog().select(Localization.localize('Play (with seek)'), dialog_items)
|
||||||
|
if ret == 0:
|
||||||
|
return str(seek)
|
||||||
|
return '0'
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
|
@ -99,27 +99,28 @@ class IMDB(Content.Content):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_contentList(self, category, subcategory=None, apps_property=None):
|
def get_contentList(self, category, subcategory=None, apps_property=None):
|
||||||
|
self.debug = self.log
|
||||||
contentList = []
|
contentList = []
|
||||||
url = self.get_url(category, subcategory, apps_property)
|
url = self.get_url(category, subcategory, apps_property)
|
||||||
|
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
if None != response and 0 < len(response):
|
if None != response and 0 < len(response):
|
||||||
#print response
|
self.debug(response)
|
||||||
if category in ['top']:
|
if category in ['top']:
|
||||||
contentList = self.topmode(response)
|
contentList = self.topmode(response)
|
||||||
elif category == 'search':
|
elif category == 'search':
|
||||||
contentList = self.searchmode(response)
|
contentList = self.searchmode(response)
|
||||||
else: #if category in ['genre']:
|
else: #if category in ['genre']:
|
||||||
contentList = self.genremode(response)
|
contentList = self.genremode(response)
|
||||||
#print str(contentList)
|
self.debug(str(contentList))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def searchmode(self, response):
|
def searchmode(self, response):
|
||||||
contentList = []
|
contentList = []
|
||||||
pars = HTMLParser.HTMLParser()
|
pars = HTMLParser.HTMLParser()
|
||||||
Soup = BeautifulSoup(response)
|
Soup = BeautifulSoup(response)
|
||||||
result = Soup.findAll('tr', {'class': ['findResult odd', 'findResult even']})
|
result = Soup.findAll('tr', {'class': 'lister-item mode-advanced'})
|
||||||
num = 250
|
num = 250
|
||||||
for tr in result:
|
for tr in result:
|
||||||
#main
|
#main
|
||||||
|
@ -147,7 +148,7 @@ class IMDB(Content.Content):
|
||||||
int(int(self.sourceWeight) * (251 - int(num))),
|
int(int(self.sourceWeight) * (251 - int(num))),
|
||||||
originaltitle, title, int(year), img, info,
|
originaltitle, title, int(year), img, info,
|
||||||
))
|
))
|
||||||
#print result
|
self.debug(str(result))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def genremode(self, response):
|
def genremode(self, response):
|
||||||
|
@ -181,7 +182,7 @@ class IMDB(Content.Content):
|
||||||
int(int(self.sourceWeight) * (251 - int(num))),
|
int(int(self.sourceWeight) * (251 - int(num))),
|
||||||
originaltitle, title, int(year), img, info,
|
originaltitle, title, int(year), img, info,
|
||||||
))
|
))
|
||||||
#print result
|
self.debug(str(result))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def biggerImg(self, img):
|
def biggerImg(self, img):
|
||||||
|
|
|
@ -48,7 +48,7 @@ class KickAssSo(Content.Content):
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
baseurl = "http://kat.cr"
|
baseurl = "http://kat.am"
|
||||||
headers = [('User-Agent',
|
headers = [('User-Agent',
|
||||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124' + \
|
'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'),
|
' YaBrowser/14.10.2062.12061 Safari/537.36'),
|
||||||
|
@ -82,25 +82,25 @@ class KickAssSo(Content.Content):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_contentList(self, category, subcategory=None, apps_property=None):
|
def get_contentList(self, category, subcategory=None, apps_property=None):
|
||||||
|
self.debug = self.log
|
||||||
contentList = []
|
contentList = []
|
||||||
url = self.get_url(category, subcategory, apps_property)
|
url = self.get_url(category, subcategory, apps_property)
|
||||||
|
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
if None != response and 0 < len(response):
|
if None != response and 0 < len(response):
|
||||||
# print response
|
self.debug(response)
|
||||||
if category:
|
if category:
|
||||||
contentList = self.mode(response)
|
contentList = self.mode(response)
|
||||||
# print str(contentList)
|
self.debug(str(contentList))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def mode(self, response):
|
def mode(self, response):
|
||||||
contentList = []
|
contentList = []
|
||||||
# print str(result)
|
|
||||||
num = 51
|
num = 51
|
||||||
good_forums = ['TV', 'Anime', 'Movies']
|
good_forums = ['TV', 'Anime', 'Movies']
|
||||||
regex = '''<tr class=".+?" id=.+?</tr>'''
|
regex = '''<tr class=".+?" id=.+?</tr>'''
|
||||||
regex_tr = r'''title="Download torrent file" href="(.+?)" class=".+?"><i.+?<a.+?<a.+?<a href="(.+?html)" class=".+?">(.+?)</a>.+? in <span.+?"><strong>.+?">(.+?)</a>.+?<td class="nobr center">(.+?)</td>.+?<td class="center".+?>(\d+ .+?)</td>.+?<td class="green center">(\d+?)</td>.+?<td class="red lasttd center">(\d+?)</td>'''
|
regex_tr = r'''<a data-download .+? href="(.+?)" class=".+?"><i.+?<a.+?<a.+?<a href="(.+?html)" class=".+?">(.+?)</a>.+? in <span.+?"><strong>.+?">(.+?)</a>.+?<td class="nobr center">(.+?)</td>.+?<td class="center".+?>(\d+ .+?)</td>.+?<td class="green center">(\d+?)</td>.+?<td class="red lasttd center">(\d+?)</td>'''
|
||||||
for tr in re.compile(regex, re.DOTALL).findall(response):
|
for tr in re.compile(regex, re.DOTALL).findall(response):
|
||||||
result=re.compile(regex_tr, re.DOTALL).findall(tr)
|
result=re.compile(regex_tr, re.DOTALL).findall(tr)
|
||||||
if result:
|
if result:
|
||||||
|
@ -129,6 +129,7 @@ class KickAssSo(Content.Content):
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def get_info(self, url):
|
def get_info(self, url):
|
||||||
|
self.debug = self.log
|
||||||
movieInfo = {}
|
movieInfo = {}
|
||||||
color = '[COLOR blue]%s:[/COLOR] %s\r\n'
|
color = '[COLOR blue]%s:[/COLOR] %s\r\n'
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
@ -143,7 +144,7 @@ class KickAssSo(Content.Content):
|
||||||
'kinopoisk': ''}
|
'kinopoisk': ''}
|
||||||
try:
|
try:
|
||||||
img = result.find('a', {'class': 'movieCover'}).find('img').get('src')
|
img = result.find('a', {'class': 'movieCover'}).find('img').get('src')
|
||||||
movieInfo['poster'] = 'http:' + img
|
movieInfo['poster'] = img if img.startswith('http:') else 'http:' + img
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
|
@ -190,7 +191,5 @@ class KickAssSo(Content.Content):
|
||||||
if i == 'IMDb link':
|
if i == 'IMDb link':
|
||||||
movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
|
movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
|
||||||
|
|
||||||
|
self.debug(str(movieInfo))
|
||||||
# print str(info)
|
|
||||||
|
|
||||||
return movieInfo
|
return movieInfo
|
||||||
|
|
|
@ -104,22 +104,23 @@ class KinoPoisk(Content.Content):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_contentList(self, category, subcategory=None, apps_property=None):
|
def get_contentList(self, category, subcategory=None, apps_property=None):
|
||||||
|
#self.debug=self.log
|
||||||
socket.setdefaulttimeout(15)
|
socket.setdefaulttimeout(15)
|
||||||
contentList = []
|
contentList = []
|
||||||
url = self.get_url(category, subcategory, apps_property)
|
url = self.get_url(category, subcategory, apps_property)
|
||||||
|
|
||||||
#print url
|
self.debug('get_contentList: url = '+url)
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
if None != response and 0 < len(response):
|
if None != response and 0 < len(response):
|
||||||
#print response
|
self.debug(str(response))
|
||||||
if category in ['hot']:
|
if category in ['hot']:
|
||||||
contentList = self.popmode(response)
|
contentList = self.popmode(response)
|
||||||
elif url.startswith(self.baseurl + '/s/type/film/list/'):
|
elif url.startswith(self.baseurl + '/s/type/film/list/'):
|
||||||
contentList = self.infomode(response)
|
contentList = self.infomode(response)
|
||||||
else:
|
else:
|
||||||
contentList = self.topmode(response)
|
contentList = self.topmode(response)
|
||||||
#print str(contentList)
|
self.debug('get_contentList: contentList = '+str(contentList))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def stripTtl(self, title):
|
def stripTtl(self, title):
|
||||||
|
@ -132,12 +133,12 @@ class KinoPoisk(Content.Content):
|
||||||
contentList = []
|
contentList = []
|
||||||
Soup = BeautifulSoup(response)
|
Soup = BeautifulSoup(response)
|
||||||
result = Soup.find('div', 'stat').findAll('div', 'el')
|
result = Soup.find('div', 'stat').findAll('div', 'el')
|
||||||
#print str(result)
|
self.debug('popmode: '+str(result))
|
||||||
for tr in result:
|
for tr in result:
|
||||||
#main
|
#main
|
||||||
a = tr.findAll('a')
|
a = tr.findAll('a')
|
||||||
num = a[0].text
|
num = a[0].text
|
||||||
#print num
|
|
||||||
info = {}
|
info = {}
|
||||||
year = 0
|
year = 0
|
||||||
img = ''
|
img = ''
|
||||||
|
@ -152,12 +153,14 @@ class KinoPoisk(Content.Content):
|
||||||
img = self.id2img(id[0])
|
img = self.id2img(id[0])
|
||||||
try:
|
try:
|
||||||
title, year = re.compile('(.+?) \((\d\d\d\d)\)', re.DOTALL).findall(a[1].text)[0]
|
title, year = re.compile('(.+?) \((\d\d\d\d)\)', re.DOTALL).findall(a[1].text)[0]
|
||||||
|
#self.log('popmode 1'+str((title, year)))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if not year:
|
if not year:
|
||||||
try:
|
try:
|
||||||
title, year = re.compile('(.+?) \(.*(\d\d\d\d)').findall(a[1].text)[0]
|
title, year = re.compile('(.+?) \(.*(\d\d\d\d)').findall(a[1].text)[0]
|
||||||
info['tvshowtitle'] = title
|
info['tvshowtitle'] = title
|
||||||
|
#self.log('popmode 2' + str((title, year)))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
title = self.stripHtml(self.stripTtl(title))
|
title = self.stripHtml(self.stripTtl(title))
|
||||||
|
@ -176,7 +179,7 @@ class KinoPoisk(Content.Content):
|
||||||
contentList = []
|
contentList = []
|
||||||
Soup = BeautifulSoup(response)
|
Soup = BeautifulSoup(response)
|
||||||
result = Soup.find('table', {'cellpadding': '3'}).findAll('tr')[2:]
|
result = Soup.find('table', {'cellpadding': '3'}).findAll('tr')[2:]
|
||||||
#print str(result)
|
self.debug('topmode: ' + str(result))
|
||||||
for tr in result:
|
for tr in result:
|
||||||
#main
|
#main
|
||||||
td = tr.findAll('td')
|
td = tr.findAll('td')
|
||||||
|
@ -198,8 +201,12 @@ class KinoPoisk(Content.Content):
|
||||||
year = re.compile('(.+) \((\d\d\d\d)\)').findall(a_all.text)
|
year = re.compile('(.+) \((\d\d\d\d)\)').findall(a_all.text)
|
||||||
if not year:
|
if not year:
|
||||||
try:
|
try:
|
||||||
title, year = re.compile('(.+) \(.*(\d\d\d\d)').findall(a_all.text)[0]
|
match = re.search(r"(.+) \((\d\d\d\d) –|(.+) \(.*(\d\d\d\d)", a_all.text,
|
||||||
info['tvshowtitle'] = title
|
re.IGNORECASE | re.MULTILINE)
|
||||||
|
if match:
|
||||||
|
title = match.group(1)
|
||||||
|
year = match.group(2)
|
||||||
|
info['tvshowtitle'] = title
|
||||||
except:
|
except:
|
||||||
title = a_all.text
|
title = a_all.text
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,249 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Torrenter plugin for XBMC
|
||||||
|
Copyright (C) 2012 Vadim Skorba
|
||||||
|
vadim.skorba@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
'''
|
||||||
|
import re, sys
|
||||||
|
|
||||||
|
import Content
|
||||||
|
from BeautifulSoup import BeautifulSoup
|
||||||
|
|
||||||
|
#http://anti-tor.org/browse/0/1/0/0 date movie
|
||||||
|
#http://anti-tor.org/browse/1/1/0/0 page 2
|
||||||
|
#http://anti-tor.org/browse/0/1/0/2 seed movie
|
||||||
|
# page/cat/?/sort
|
||||||
|
|
||||||
|
|
||||||
|
class RuTorOrg(Content.Content):
|
||||||
|
category_dict = {
|
||||||
|
'movies': ('Movies', '/browse/0/1/0',
|
||||||
|
{'page': '/browse/%d/1/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'rus_movies': ('Russian Movies', '/browse/0/5/0',
|
||||||
|
{'page': '/browse/%d/5/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'tvshows': ('TV Shows', '/browse/0/4/0',
|
||||||
|
{'page': '/browse/%d/4/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'science': ('Научно - популярные фильмы', '/browse/0/12/0',
|
||||||
|
{'page': '/browse/%d/12/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'cartoons': ('Cartoons', '/browse/0/7/0',
|
||||||
|
{'page': '/browse/%d/7/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'anime': ('Anime', '/browse/0/10/0',
|
||||||
|
{'page': '/browse/%d/10/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'sport': ('Спорт и Здоровье', '/browse/0/13/0',
|
||||||
|
{'page': '/browse/%d/13/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'tele': ('Телевизор', '/browse/0/6/0',
|
||||||
|
{'page': '/browse/%d/6/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
'humor': ('Юмор', '/browse/0/15/0',
|
||||||
|
{'page': '/browse/%d/15/0', 'increase': 1, 'second_page': 1,
|
||||||
|
'sort': [{'name': 'by Seeders', 'url_after': '/2'},
|
||||||
|
{'name': 'by Date', 'url_after': '/0'}]}),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#'hot': ('Most Recent',),
|
||||||
|
|
||||||
|
|
||||||
|
baseurl = "anti-tor.org"
|
||||||
|
|
||||||
|
'''
|
||||||
|
Weight of source with this searcher provided.
|
||||||
|
Will be multiplied on default weight.
|
||||||
|
Default weight is seeds number
|
||||||
|
'''
|
||||||
|
sourceWeight = 1
|
||||||
|
|
||||||
|
def isTracker(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isSearcher(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def isScrappable(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def isInfoLink(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isPages(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isSort(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isSearchOption(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_contentList(self, category, subcategory=None, apps_property=None):
|
||||||
|
self.debug = self.log
|
||||||
|
contentList = []
|
||||||
|
url = 'http://%s' % self.get_url(category, subcategory, apps_property)
|
||||||
|
self.debug(url)
|
||||||
|
|
||||||
|
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', 'http://%s' % self.baseurl), ('Accept-encoding', 'gzip'),
|
||||||
|
('Cookie', str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")))]
|
||||||
|
|
||||||
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
|
if None != response and 0 < len(response):
|
||||||
|
#self.debug(response)
|
||||||
|
cookie = re.compile("document.cookie='(.+?)';").findall(response)
|
||||||
|
if cookie and str(cookie[0]) != str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")):
|
||||||
|
cookie = cookie[0]
|
||||||
|
self.log('ok found new cookie: ' + str(cookie))
|
||||||
|
sys.modules["__main__"].__settings__.setSetting("rutor-auth", cookie)
|
||||||
|
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', 'http://%s' % self.baseurl), ('Accept-encoding', 'gzip'),
|
||||||
|
('Cookie', str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")))]
|
||||||
|
response = self.makeRequest(url, headers=headers)
|
||||||
|
self.debug(response)
|
||||||
|
|
||||||
|
if category:
|
||||||
|
contentList = self.mode(response.decode('utf-8'))
|
||||||
|
self.debug(str(contentList))
|
||||||
|
return contentList
|
||||||
|
|
||||||
|
def mode(self, response):
|
||||||
|
contentList = []
|
||||||
|
num = 101
|
||||||
|
|
||||||
|
|
||||||
|
regex = '''<tr class="[tg].+?</tr>'''
|
||||||
|
regex_tr = '<td>(.+?)</td><td ><a.+?href="(.+?download/\d+)">.+?<a href=".+?">.+?<a href="(.+?)">(.+?)</a></td>.+?<td align="right">(\d*?\..+? .+?)</td>.+?<img .+?alt="S".+?> (\d+)</span>.+?alt="L".+?> (\d+)'
|
||||||
|
for tr in re.compile(regex, re.DOTALL).findall(response):
|
||||||
|
result=re.compile(regex_tr, re.DOTALL).findall(tr)
|
||||||
|
if result:
|
||||||
|
self.debug(tr + ' -> ' + str(result[0]))
|
||||||
|
(date, link, infolink, title, size, seeds, leechers)=result[0]
|
||||||
|
# main
|
||||||
|
info = {}
|
||||||
|
num = num - 1
|
||||||
|
original_title = None
|
||||||
|
year = 0
|
||||||
|
img = ''
|
||||||
|
|
||||||
|
# info
|
||||||
|
title = self.unescape(self.stripHtml(title.strip()))
|
||||||
|
info['label'] = info['title'] = title
|
||||||
|
|
||||||
|
if link[0] == '/': link = 'http://%s%s' % (self.baseurl, link)
|
||||||
|
info['link'] = link
|
||||||
|
|
||||||
|
#if infolink[0] == '/': infolink = 'http://%s%s' % (self.baseurl, infolink)
|
||||||
|
#info['infolink'] = infolink
|
||||||
|
|
||||||
|
size = size.replace(' ', ' ')
|
||||||
|
date = date.replace(' ', ' ')
|
||||||
|
|
||||||
|
info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s: %s' % (
|
||||||
|
size, seeds, leechers, self.localize('Date'), date)
|
||||||
|
|
||||||
|
#regex_title = '(.+?) / (.+?) \((\d\d\d\d)\)'
|
||||||
|
#regex_result = re.compile(regex_title, re.DOTALL).findall(title)
|
||||||
|
#if regex_result:
|
||||||
|
# title, original_title, year = regex_result[0]
|
||||||
|
# info['title'] = title
|
||||||
|
|
||||||
|
contentList.append((
|
||||||
|
int(int(self.sourceWeight) * (int(num))),
|
||||||
|
original_title, title, int(year), img, info,
|
||||||
|
))
|
||||||
|
|
||||||
|
return contentList
|
||||||
|
|
||||||
|
def get_info(self, url):
|
||||||
|
self.debug = self.log
|
||||||
|
movieInfo = {}
|
||||||
|
color = '[COLOR blue]%s:[/COLOR] %s\r\n'
|
||||||
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
|
if None != response and 0 < len(response):
|
||||||
|
Soup = BeautifulSoup(response)
|
||||||
|
result = Soup.find('div', 'torrentMediaInfo')
|
||||||
|
if not result:
|
||||||
|
return None
|
||||||
|
li = result.findAll('li')
|
||||||
|
info, movieInfo = {'Cast': ''}, {'desc': '', 'poster': '', 'title': '', 'views': '0', 'rating': '50',
|
||||||
|
'kinopoisk': ''}
|
||||||
|
try:
|
||||||
|
img = result.find('a', {'class': 'movieCover'}).find('img').get('src')
|
||||||
|
movieInfo['poster'] = img if img.startswith('http:') else 'http:' + img
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
movie = re.compile('View all <strong>(.+?)</strong> episodes</a>').match(str(result))
|
||||||
|
if movie:
|
||||||
|
info['Movie'] = movie.group(1)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
for i in li:
|
||||||
|
name = i.find('strong').text
|
||||||
|
if name:
|
||||||
|
info[name.rstrip(':')] = i.text.replace(name, '', 1)
|
||||||
|
plot = result.find('div', {'id': 'summary'})
|
||||||
|
if plot:
|
||||||
|
cut = plot.find('strong').text
|
||||||
|
info['plot'] = plot.text.replace(cut, '', 1).replace('report summary', '')
|
||||||
|
# print str(result)
|
||||||
|
cast = re.compile('<a href="/movies/actor/.+?">(.+?)</a>').findall(str(result))
|
||||||
|
if cast:
|
||||||
|
for actor in cast:
|
||||||
|
info['Cast'] += actor + ", "
|
||||||
|
if 'Genres' in info:
|
||||||
|
info['Genres'] = info['Genres'].replace(', ', ',').replace(',', ', ')
|
||||||
|
for key in info.keys():
|
||||||
|
if not 'Movie' in info and info[key] == 'addto bookmarks':
|
||||||
|
movieInfo['title'] = self.unescape(key)
|
||||||
|
info['TV Show'] = self.unescape(key)
|
||||||
|
if not 'plot' in info and 'Summary' in key:
|
||||||
|
info['plot'] = info[key]
|
||||||
|
|
||||||
|
for i in ['Movie', 'TV Show', 'Release date', 'Original run', 'Episode', 'Air date', 'Genres', 'Language',
|
||||||
|
'Director', 'Writers', 'Cast', 'Original run', 'IMDb rating', 'AniDB rating']:
|
||||||
|
if info.get(i) and info.get(i) not in ['']:
|
||||||
|
movieInfo['desc'] += color % (i, info.get(i))
|
||||||
|
if i == 'Movie':
|
||||||
|
movieInfo['title'] = info.get(i)
|
||||||
|
|
||||||
|
for i in ['plot', 'IMDb link', 'RottenTomatoes']:
|
||||||
|
if info.get(i) and info.get(i) not in ['']:
|
||||||
|
if i == 'plot':
|
||||||
|
movieInfo['desc'] += '\r\n[COLOR blue]Plot:[/COLOR]\r\n' + self.unescape(info.get(i))
|
||||||
|
if i == 'RottenTomatoes':
|
||||||
|
movieInfo['rating'] = str(info.get(i).split('%')[0])
|
||||||
|
if i == 'IMDb link':
|
||||||
|
movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
|
||||||
|
|
||||||
|
self.debug(str(movieInfo))
|
||||||
|
return movieInfo
|
|
@ -23,6 +23,7 @@ import Content
|
||||||
|
|
||||||
|
|
||||||
class ThePirateBaySe(Content.Content):
|
class ThePirateBaySe(Content.Content):
|
||||||
|
# debug = log
|
||||||
category_dict = {
|
category_dict = {
|
||||||
'tvshows': ('TV Shows', '/browse/205', {'page': '/browse/208/%d', 'increase': 1, 'second_page': 1,
|
'tvshows': ('TV Shows', '/browse/205', {'page': '/browse/208/%d', 'increase': 1, 'second_page': 1,
|
||||||
'sort': [{'name': 'by Seeders', 'url_after': '/0/7/0'},
|
'sort': [{'name': 'by Seeders', 'url_after': '/0/7/0'},
|
||||||
|
@ -45,11 +46,11 @@ class ThePirateBaySe(Content.Content):
|
||||||
'heb_movies': ('סרטים מדובבים', '/search/Hebrew-dubbed/0/7/0'),
|
'heb_movies': ('סרטים מדובבים', '/search/Hebrew-dubbed/0/7/0'),
|
||||||
}
|
}
|
||||||
|
|
||||||
baseurl = "thepiratebay.rs"
|
baseurl = "http://thepiratebay.ae"
|
||||||
headers = [('User-Agent',
|
headers = [('User-Agent',
|
||||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124' + \
|
'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'),
|
' YaBrowser/14.10.2062.12061 Safari/537.36'),
|
||||||
('Referer', 'http://kickass.so/'), ('Accept-Encoding', 'gzip')]
|
('Referer', 'http://thepiratebay.ae/'), ('Accept-Encoding', 'gzip')]
|
||||||
'''
|
'''
|
||||||
Weight of source with this searcher provided.
|
Weight of source with this searcher provided.
|
||||||
Will be multiplied on default weight.
|
Will be multiplied on default weight.
|
||||||
|
@ -82,7 +83,8 @@ class ThePirateBaySe(Content.Content):
|
||||||
contentList = []
|
contentList = []
|
||||||
url = self.get_url(category, subcategory, apps_property)
|
url = self.get_url(category, subcategory, apps_property)
|
||||||
|
|
||||||
response = self.open2(url)
|
import requests
|
||||||
|
response = requests.get(url).text
|
||||||
|
|
||||||
if None != response and 0 < len(response):
|
if None != response and 0 < len(response):
|
||||||
# print response
|
# print response
|
||||||
|
@ -91,40 +93,35 @@ class ThePirateBaySe(Content.Content):
|
||||||
# print str(contentList)
|
# print str(contentList)
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def open2(self, url=''):
|
|
||||||
import httplib
|
|
||||||
conn = httplib.HTTPConnection(self.baseurl)
|
|
||||||
conn.request("GET", url.replace(self.baseurl,''))
|
|
||||||
r1 = conn.getresponse()
|
|
||||||
status = str(r1.status) + " " + r1.reason
|
|
||||||
content = r1.read()
|
|
||||||
#print str(status)
|
|
||||||
#print str(content)
|
|
||||||
return content
|
|
||||||
|
|
||||||
def mode(self, response):
|
def mode(self, response):
|
||||||
contentList = []
|
contentList = []
|
||||||
# print str(result)
|
self.debug = self.log
|
||||||
num = 31
|
num = 31
|
||||||
result = re.compile(
|
self.debug(response)
|
||||||
r'''<div class="detName">.+?">(.+?)</a>.+?<a href="(.+?)".+?<font class="detDesc">Uploaded (.+?), Size (.+?), .+?</font>.+?<td align="right">(\d+?)</td>.+?<td align="right">(\d+?)</td>''',
|
regex = '''<tr>.+?</tr>'''
|
||||||
re.DOTALL).findall(response)
|
regex_tr = r'<div class="detName">.+?">(.+?)</a>.+?<a href="(.+?)".+?<font class="detDesc">Uploaded (.+?), Size (.+?), .+?</font>.+?<td align="right">(\d+?)</td>.+?<td align="right">(\d+?)</td>'
|
||||||
for title, link, date, size, seeds, leechers in result:
|
for tr in re.compile(regex, re.DOTALL).findall(response):
|
||||||
info = {}
|
result = re.compile(regex_tr, re.DOTALL).findall(tr)
|
||||||
num = num - 1
|
self.debug(tr + ' -> ' + str(result))
|
||||||
original_title = None
|
if result:
|
||||||
year = 0
|
(title, link, date, size, seeds, leechers) = result[0]
|
||||||
img = ''
|
|
||||||
size = size.replace(' ', ' ')
|
|
||||||
date = self.stripHtml(date.replace(' ', ' '))
|
|
||||||
|
|
||||||
# info
|
info = {}
|
||||||
|
num = num - 1
|
||||||
|
original_title = None
|
||||||
|
year = 0
|
||||||
|
img = ''
|
||||||
|
size = size.replace(' ', ' ')
|
||||||
|
date = self.stripHtml(date.replace(' ', ' '))
|
||||||
|
|
||||||
info['label'] = info['title'] = self.unescape(title)
|
# info
|
||||||
info['link'] = link
|
|
||||||
info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date)
|
info['label'] = info['title'] = self.unescape(title)
|
||||||
contentList.append((
|
info['link'] = link
|
||||||
int(int(self.sourceWeight) * (int(num))),
|
self.log(info['link'])
|
||||||
original_title, title, int(year), img, info,
|
info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date)
|
||||||
))
|
contentList.append((
|
||||||
|
int(int(self.sourceWeight) * (int(num))),
|
||||||
|
original_title, title, int(year), img, info,
|
||||||
|
))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
|
@ -28,7 +28,7 @@ class EZTV(Content.Content):
|
||||||
'hot': ('Most Recent', '/', {'page': '/page_%d', 'increase': 1, 'second_page': 1}),
|
'hot': ('Most Recent', '/', {'page': '/page_%d', 'increase': 1, 'second_page': 1}),
|
||||||
}
|
}
|
||||||
|
|
||||||
baseurl = "https://eztv.ch"
|
baseurl = "https://eztv.ag"
|
||||||
headers = [('User-Agent',
|
headers = [('User-Agent',
|
||||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124' + \
|
'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'),
|
' YaBrowser/14.10.2062.12061 Safari/537.36'),
|
|
@ -68,11 +68,24 @@
|
||||||
<string id="30068">pyrrent2http (python-libtorrent via http)</string>
|
<string id="30068">pyrrent2http (python-libtorrent via http)</string>
|
||||||
<string id="30069">Append size to file name</string>
|
<string id="30069">Append size to file name</string>
|
||||||
<string id="30070">Enable DHT</string>
|
<string id="30070">Enable DHT</string>
|
||||||
|
<string id="30071">Estuary (by DiMartino)</string>
|
||||||
|
<string id="30072">Стиль информации о раздаче</string>
|
||||||
|
<string id="30073">In the end</string>
|
||||||
|
<string id="30074">In the beginning</string>
|
||||||
|
<string id="30075">Second string</string>
|
||||||
|
<string id="30076">Arctic: Zephyr (by xbmc00)</string>
|
||||||
<string id="30101">Interface</string>
|
<string id="30101">Interface</string>
|
||||||
<string id="30102">P2P Network</string>
|
<string id="30102">P2P Network</string>
|
||||||
<string id="30103">Advanced</string>
|
<string id="30103">Advanced</string>
|
||||||
<string id="30104">Torrent-client</string>
|
<string id="30104">Torrent-client</string>
|
||||||
<string id="30105">Hentai (fine-tuning)</string>
|
<string id="30105">Hentai (fine-tuning)</string>
|
||||||
|
<string id="30106">Search Window Mode</string>
|
||||||
|
<string id="30107">Enabled, hide old style</string>
|
||||||
|
<string id="30108">Enabled, replace old style</string>
|
||||||
|
<string id="30109">Enabled, optional</string>
|
||||||
|
<string id="30110">Disabled</string>
|
||||||
|
<string id="30111">Search Window Transparent Background</string>
|
||||||
|
<string id="30112">Disable Notifications</string>
|
||||||
<string id="50301">Save path</string>
|
<string id="50301">Save path</string>
|
||||||
<string id="50302">Call dialog</string>
|
<string id="50302">Call dialog</string>
|
||||||
<string id="50303">Default</string>
|
<string id="50303">Default</string>
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<strings>
|
||||||
|
<string id="30001">Kezelőfelület nyelve</string>
|
||||||
|
<string id="30002">Mappák nézetének lezárása</string>
|
||||||
|
<string id="30003">Ki</string>
|
||||||
|
<string id="30004">Fájlok mentése mappába (nem FAT32)</string>
|
||||||
|
<string id="30007">Magnet-linkek használata</string>
|
||||||
|
<string id="30008">Letöltött fájlok megtartása</string>
|
||||||
|
<string id="30009">Letöltött fájlok seedben tartása</string>
|
||||||
|
<string id="30010">Feltöltési sebességkorlát MBits/sec (0 - korlátlan)</string>
|
||||||
|
<string id="30011">Letöltési sebességkorlát MBits/sec (0 - korlátlan)</string>
|
||||||
|
<string id="30012">Csak rendszerszintű libtorrent használata</string>
|
||||||
|
<string id="30013">A következő epizód előtöltése és lejátszása</string>
|
||||||
|
<string id="30014">Metaadatok letöltése a Tartalmak Listájába</string>
|
||||||
|
<string id="30015">Hibakeresés (Fejlesztői Mód)</string>
|
||||||
|
<string id="30016">Confluence (by slng)</string>
|
||||||
|
<string id="30017">Transperency (by slng)</string>
|
||||||
|
<string id="30018">Confluence (by DiMartino)</string>
|
||||||
|
<string id="30019">Confluence (by RussakHH)</string>
|
||||||
|
<string id="30020">Keresési Előzmények engedélyezése</string>
|
||||||
|
<string id="30021">python-libtorrent</string>
|
||||||
|
<string id="30022">Ace Stream</string>
|
||||||
|
<string id="30023">P2P Lejátszó</string>
|
||||||
|
<string id="30024">Egyéb beállítások a programban - AceStream Client</string>
|
||||||
|
<string id="30025">Keresés időkorlátja</string>
|
||||||
|
<string id="30026">Rövid (10s)</string>
|
||||||
|
<string id="30027">Normál (20s)</string>
|
||||||
|
<string id="30028">Hosszú (30s)</string>
|
||||||
|
<string id="30029">Feliratok előtöltése az összes mappából</string>
|
||||||
|
<string id="30030">Seedben tartás megtekintés után</string>
|
||||||
|
<string id="30031">Kérdezzen rá a tárolóhely váltására lejátszás előtt</string>
|
||||||
|
<string id="30032">Orosz tartalmak törlése</string>
|
||||||
|
<string id="30033">Orosz tartalmak visszaállítása</string>
|
||||||
|
<string id="30034">Torrentre kattintás művelete</string>
|
||||||
|
<string id="30035">Torrent fájl megnyitása</string>
|
||||||
|
<string id="30036">Helyi menü megnyitása</string>
|
||||||
|
<string id="30037">Letöltés torrentkliensen keresztül</string>
|
||||||
|
<string id="30038">Letöltés python-libtorrenten keresztül</string>
|
||||||
|
<string id="30039">Keresések rendezése seed alapján</string>
|
||||||
|
<string id="30040">Egyéni keresési lehetőség kifejezésre</string>
|
||||||
|
<string id="30041">Titkosítás</string>
|
||||||
|
<string id="30042">Keresési szálak száma</string>
|
||||||
|
<string id="30043">Törölje a fájlokat</string>
|
||||||
|
<string id="30044">Mentse a fájlokat</string>
|
||||||
|
<string id="30045">Kérdezzen rá</string>
|
||||||
|
<string id="30046">Torrent2HTTP (libtorrent via http)</string>
|
||||||
|
<string id="30047">Proxy automatikus feloldása</string>
|
||||||
|
<string id="30048">Ki</string>
|
||||||
|
<string id="30049">Anti-zapret</string>
|
||||||
|
<string id="30050">Immunicity</string>
|
||||||
|
<string id="30051">Max. kapcsolatok (0 - korlátlan)</string>
|
||||||
|
<string id="30052">Véletlen port használata</string>
|
||||||
|
<string id="30053">Port a bejövő kapcsolatokhoz</string>
|
||||||
|
<string id="30054">Előtöltendő adat lejátszás előtt (MB)</string>
|
||||||
|
<string id="30055">Következő epizód automatikus lejátszása (vagy kérdezzen)</string>
|
||||||
|
<string id="30056">Eszköz konfiguráció</string>
|
||||||
|
<string id="30057">Átlagos/Jó PC</string>
|
||||||
|
<string id="30058">Átlag alatti PC/router</string>
|
||||||
|
<string id="30059">Tárolóhely legkisebb mérete automatikus tisztítás miatt (GB)</string>
|
||||||
|
<string id="30060">Videó szüneteltetése elindítás után</string>
|
||||||
|
<string id="30061">Keresési eredmények rendezése</string>
|
||||||
|
<string id="30062">Seed alapján</string>
|
||||||
|
<string id="30063">Ne rendezze</string>
|
||||||
|
<string id="30064">Név alapján</string>
|
||||||
|
<string id="30065">Ne adja Megtek. Előzm.-hez ennél kevesebb lejátszásnál (%)</string>
|
||||||
|
<string id="30066">Confluence (by safonov_ivan)</string>
|
||||||
|
<string id="30067">Aeon Nox (by joyrider)</string>
|
||||||
|
<string id="30068">pyrrent2http (python-libtorrent via http)</string>
|
||||||
|
<string id="30069">Méret mellékelése a fájl nevéhez</string>
|
||||||
|
<string id="30070">DHT engedélyezése</string>
|
||||||
|
<string id="30101">Kezelőfelület</string>
|
||||||
|
<string id="30102">P2P Hálózat</string>
|
||||||
|
<string id="30103">Haladó</string>
|
||||||
|
<string id="30104">Torrentkliens</string>
|
||||||
|
<string id="30105">Hentai (finomhangolás)</string>
|
||||||
|
<string id="50301">Mentési útvonal</string>
|
||||||
|
<string id="50302">Párbeszédablak</string>
|
||||||
|
<string id="50303">Alapértelmezett</string>
|
||||||
|
<string id="50304">Elérési út</string>
|
||||||
|
<string id="50305">Alkönyvtár készítése a leolvasó számára</string>
|
||||||
|
<string id="50312">Gazdagép</string>
|
||||||
|
<string id="50313">Port</string>
|
||||||
|
<string id="50314">URL</string>
|
||||||
|
<string id="50315">Felhasználónév</string>
|
||||||
|
<string id="50316">Jelszó</string>
|
||||||
|
<string id="50311">Torrentkliens</string>
|
||||||
|
<string id="50317">URL (csak No SSL)</string>
|
||||||
|
<string id="30426">Elérési út helyettesítése (csak távoli)</string>
|
||||||
|
<string id="30412">Bezár</string>
|
||||||
|
<string id="30413">Beállítások megnyitása</string>
|
||||||
|
<string id="30414">Torrentkliens Böngésző</string>
|
||||||
|
<string id="30415">Trackerek telepítése</string>
|
||||||
|
<string id="30416">Tracker beállítások</string>
|
||||||
|
<string id="30417">Tárolóhely tisztítása</string>
|
||||||
|
<string id="30418">Kereső választása</string>
|
||||||
|
<string id="30419">Nem rendelkezel külső keresővel. Kérlek, telepíts egyet.</string>
|
||||||
|
</strings>
|
|
@ -68,11 +68,24 @@
|
||||||
<string id="30068">pyrrent2http (python-libtorrent по http)</string>
|
<string id="30068">pyrrent2http (python-libtorrent по http)</string>
|
||||||
<string id="30069">Добавлять размер к имени файла</string>
|
<string id="30069">Добавлять размер к имени файла</string>
|
||||||
<string id="30070">Включить DHT</string>
|
<string id="30070">Включить DHT</string>
|
||||||
|
<string id="30071">Estuary (от DiMartino)</string>
|
||||||
|
<string id="30072">Стиль информации о раздаче</string>
|
||||||
|
<string id="30073">В конце</string>
|
||||||
|
<string id="30074">В начале</string>
|
||||||
|
<string id="30075">Второй строкой</string>
|
||||||
|
<string id="30076">Arctic: Zephyr (от xbmc00)</string>
|
||||||
<string id="30101">Интерфейс</string>
|
<string id="30101">Интерфейс</string>
|
||||||
<string id="30102">P2P Сеть</string>
|
<string id="30102">P2P Сеть</string>
|
||||||
<string id="30103">Дополнительные</string>
|
<string id="30103">Дополнительные</string>
|
||||||
<string id="30104">Торрент-клиент</string>
|
<string id="30104">Торрент-клиент</string>
|
||||||
<string id="30105">Hentai (тонкая настр.)</string>
|
<string id="30105">Hentai (тонкая настр.)</string>
|
||||||
|
<string id="30106">Режим работы Окна Поиска</string>
|
||||||
|
<string id="30107">Включен, убрать старый вид</string>
|
||||||
|
<string id="30108">Включен, заменить старый вид</string>
|
||||||
|
<string id="30109">Включен, как опция</string>
|
||||||
|
<string id="30110">Отключен</string>
|
||||||
|
<string id="30111">Прозрачность Окна Поиска</string>
|
||||||
|
<string id="30112">Отключить Уведомления</string>
|
||||||
<string id="50301">Директория для сохранения файлов</string>
|
<string id="50301">Директория для сохранения файлов</string>
|
||||||
<string id="50302">Вызывать диалог</string>
|
<string id="50302">Вызывать диалог</string>
|
||||||
<string id="50303">Задать по умолчанию</string>
|
<string id="50303">Задать по умолчанию</string>
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<strings>
|
||||||
|
<string id="30001">Idioma de la interfaz</string>
|
||||||
|
<string id="30002">Modo vista de carpetas</string>
|
||||||
|
<string id="30003">No fijar</string>
|
||||||
|
<string id="30004">Carpeta en la que guardar archivos (no FAT32)</string>
|
||||||
|
<string id="30007">Utilizar enlaces magnet</string>
|
||||||
|
<string id="30008">Almacenaje de archivos descargados</string>
|
||||||
|
<string id="30009">Seguir compartiendo archivos descargados</string>
|
||||||
|
<string id="30010">Máx. vel. de subida en Mbit/s (0 = ilimitada)</string>
|
||||||
|
<string id="30011">Máx. vel. de descarga en Mbit/s (0 = ilimitada)</string>
|
||||||
|
<string id="30012">Utilizar solo libtorrent</string>
|
||||||
|
<string id="30013">Lanzar descarga de episodio siguiente</string>
|
||||||
|
<string id="30014">Descargar metadatos para listas de contenido</string>
|
||||||
|
<string id="30015">Depuración (Modo desarrollador)</string>
|
||||||
|
<string id="30016">Confluence (de slng)</string>
|
||||||
|
<string id="30017">Transperency (de slng)</string>
|
||||||
|
<string id="30018">Confluence (de DiMartino)</string>
|
||||||
|
<string id="30019">Confluence (de RussakHH)</string>
|
||||||
|
<string id="30020">Habilitar el historial de búsquedas</string>
|
||||||
|
<string id="30021">python-libtorrent</string>
|
||||||
|
<string id="30022">Ace Stream</string>
|
||||||
|
<string id="30023">Reproductor P2P</string>
|
||||||
|
<string id="30024">Restablecer ajustes en Add-ons de programas -- AceStream client</string>
|
||||||
|
<string id="30025">Duración de las búsquedas</string>
|
||||||
|
<string id="30026">Breve (10 s)</string>
|
||||||
|
<string id="30027">Normal (20 s)</string>
|
||||||
|
<string id="30028">Larga (30 s)</string>
|
||||||
|
<string id="30029">Predescargar los subtítulos de todas las carpetas</string>
|
||||||
|
<string id="30030">Seguir compartiendo después de ver el vídeo</string>
|
||||||
|
<string id="30031">Preguntar para cambiar de almacén antes de la descarga</string>
|
||||||
|
<string id="30032">Eliminar material ruso</string>
|
||||||
|
<string id="30033">Restituir material ruso</string>
|
||||||
|
<string id="30034">Efecto de clic sobre torrent</string>
|
||||||
|
<string id="30035">Abrir archivo torrent</string>
|
||||||
|
<string id="30036">Abrir menú contextual</string>
|
||||||
|
<string id="30037">Descargar vía cliente BitTorrent</string>
|
||||||
|
<string id="30038">Descargar vía python-libtorrent</string>
|
||||||
|
<string id="30039">Ordenar resultados por fuentes</string>
|
||||||
|
<string id="30040">Términos para búsqueda personalizada</string>
|
||||||
|
<string id="30041">Cifrado</string>
|
||||||
|
<string id="30042">Número de hilos de búsqueda</string>
|
||||||
|
<string id="30043">Eliminar archivos</string>
|
||||||
|
<string id="30044">Guardar archivos</string>
|
||||||
|
<string id="30045">Preguntar para guardar</string>
|
||||||
|
<string id="30046">Torrent2HTTP (libtorrent vía HTTP)</string>
|
||||||
|
<string id="30047">Desbloqueo automático de proxy</string>
|
||||||
|
<string id="30048">Ninguno</string>
|
||||||
|
<string id="30049">Anti-zapret (antirestricción)</string>
|
||||||
|
<string id="30050">Inmunidad</string>
|
||||||
|
<string id="30051">Núm. máx. de conexiones (0 = ilimitadas)</string>
|
||||||
|
<string id="30052">Utilizar puertos aleatorios</string>
|
||||||
|
<string id="30053">Puerto para conexiones entrantes</string>
|
||||||
|
<string id="30054">Tamaño de precarga para empezar a reproducir (MB)</string>
|
||||||
|
<string id="30055">Autorreproducir episodio siguiente (o preguntar)</string>
|
||||||
|
<string id="30056">Configuración de dispositivo</string>
|
||||||
|
<string id="30057">Promedio/Buen PC</string>
|
||||||
|
<string id="30058">Por debajo de la media, PC/router</string>
|
||||||
|
<string id="30059">Tamaño mínimo de almacenaje para autoborrado (GB)</string>
|
||||||
|
<string id="30060">Diferir inicio del reproductor</string>
|
||||||
|
<string id="30061">Ordenar resultados de la búsqueda</string>
|
||||||
|
<string id="30062">Por fuentes</string>
|
||||||
|
<string id="30063">No ordenar</string>
|
||||||
|
<string id="30064">Por nombre</string>
|
||||||
|
<string id="30065">Añadir al historial de vistos después del (%)</string>
|
||||||
|
<string id="30066">Confluence (de safonov_ivan)</string>
|
||||||
|
<string id="30067">Aeon Nox (de joyrider)</string>
|
||||||
|
<string id="30068">pyrrent2http (python-libtorrent vía HTTP)</string>
|
||||||
|
<string id="30069">Añadir tamaño a nombre de archivo</string>
|
||||||
|
<string id="30070">Activar protocolo DHT</string>
|
||||||
|
<string id="30071">Estuary (de DiMartino)</string>
|
||||||
|
<string id="30072">Modo presentación de datos</string>
|
||||||
|
<string id="30073">Al final</string>
|
||||||
|
<string id="30074">Al principio</string>
|
||||||
|
<string id="30075">En segunda línea</string>
|
||||||
|
<string id="30076">Arctic: Zephyr (de xbmc00)</string>
|
||||||
|
<string id="30101">Interfaz</string>
|
||||||
|
<string id="30102">Red P2P</string>
|
||||||
|
<string id="30103">Avanzado</string>
|
||||||
|
<string id="30104">Cliente de BitTorrent</string>
|
||||||
|
<string id="30105">Hentai (reajustes)</string>
|
||||||
|
<string id="30106">Modo ventana de búsquedas</string>
|
||||||
|
<string id="30107">Activado ocultar estilo anterior</string>
|
||||||
|
<string id="30108">Activado remplazar estilo anterior</string>
|
||||||
|
<string id="30109">Activado opcional</string>
|
||||||
|
<string id="30110">Desactivado</string>
|
||||||
|
<string id="30111">Fondo transparente de ventana de búsquedas</string>
|
||||||
|
<string id="30112">Desactivar notificaciones</string>
|
||||||
|
<string id="50301">Ruta para guardar</string>
|
||||||
|
<string id="50302">Preguntar</string>
|
||||||
|
<string id="50303">Por defecto</string>
|
||||||
|
<string id="50304">Ruta</string>
|
||||||
|
<string id="50305">Crear subdirectorio para scrapper</string>
|
||||||
|
<string id="50312">Host</string>
|
||||||
|
<string id="50313">Puerto</string>
|
||||||
|
<string id="50314">URL</string>
|
||||||
|
<string id="50315">Usuario</string>
|
||||||
|
<string id="50316">Contraseña</string>
|
||||||
|
<string id="50311">Cliente de BitTorrent</string>
|
||||||
|
<string id="50317">URL (no SSL)</string>
|
||||||
|
<string id="30426">Sustitución de ruta (Solo remoto)</string>
|
||||||
|
<string id="30412">Cerrar</string>
|
||||||
|
<string id="30413">Abrir "Ajustes"</string>
|
||||||
|
<string id="30414">Navegador de cliente BitTorrent</string>
|
||||||
|
<string id="30415">Instalar rastreadores</string>
|
||||||
|
<string id="30416">Ajustes de rastreadores</string>
|
||||||
|
<string id="30417">Vaciar almacén</string>
|
||||||
|
<string id="30418">Seleccionar buscador</string>
|
||||||
|
<string id="30419">No hay buscador externo. Instale uno primero.</string>
|
||||||
|
</strings>
|
|
@ -1,66 +1,72 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os, re, fnmatch, threading, urllib2
|
import os, re, fnmatch, threading, urllib2, time, shelve, anydbm
|
||||||
from contextlib import contextmanager, closing
|
from contextlib import contextmanager, closing
|
||||||
from functions import log, debug, tempdir
|
from functions import log, debug, tempdir
|
||||||
|
|
||||||
LOCKS = {}
|
|
||||||
PAC_URL = "http://antizapret.prostovpn.org/proxy.pac"
|
PAC_URL = "http://antizapret.prostovpn.org/proxy.pac"
|
||||||
CACHE_DIR = tempdir()
|
CACHE_DIR = tempdir()
|
||||||
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
|
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
|
||||||
|
CONFIG_LOCK = threading.Lock()
|
||||||
|
|
||||||
if not os.path.exists(CACHE_DIR):
|
if not os.path.exists(CACHE_DIR):
|
||||||
os.makedirs(CACHE_DIR)
|
os.makedirs(CACHE_DIR)
|
||||||
|
|
||||||
CACHE = 24 * 3600 # 24 hour caching
|
CACHE_LIFETIME = 24 * 3600 # 24 hour caching
|
||||||
|
|
||||||
#@contextmanager
|
|
||||||
def shelf(filename, ttl=0):
|
|
||||||
import shelve
|
|
||||||
filename = os.path.join(CACHE_DIR, filename)
|
|
||||||
with LOCKS.get(filename, threading.RLock()):
|
|
||||||
# with closing(shelve.open(filename, writeback=True)) as d:
|
|
||||||
d = shelve.open(filename, writeback=True)
|
|
||||||
try:
|
|
||||||
import time
|
|
||||||
if not dict(d):
|
|
||||||
d.update({
|
|
||||||
"created_at": time.time(),
|
|
||||||
"data": {},
|
|
||||||
})
|
|
||||||
elif ttl > 0 and (time.time() - d["created_at"]) > ttl:
|
|
||||||
d["created_at"] = time.time()
|
|
||||||
d["data"] = {}
|
|
||||||
return d
|
|
||||||
except:
|
|
||||||
d.close()
|
|
||||||
raise
|
|
||||||
|
|
||||||
_config = {}
|
|
||||||
|
|
||||||
def config():
|
def config():
|
||||||
global _config
|
shelf = None
|
||||||
if not _config:
|
try:
|
||||||
# with shelf("antizapret.pac_config", ttl=CACHE) as pac_config:
|
CONFIG_LOCK.acquire()
|
||||||
d = shelf("antizapret.pac_config2", ttl=CACHE)
|
filename = os.path.join(CACHE_DIR, "antizapret.pac_config2")
|
||||||
pac_config = d['data']
|
try:
|
||||||
if not pac_config:
|
shelf = shelve.open(filename)
|
||||||
log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
|
except anydbm.error:
|
||||||
try:
|
os.remove(filename)
|
||||||
pac_data = urllib2.urlopen(PAC_URL).read()
|
shelf = shelve.open(filename)
|
||||||
except:
|
|
||||||
pac_data = ""
|
|
||||||
|
|
||||||
r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
|
created_at = 0
|
||||||
if r:
|
data = {}
|
||||||
pac_config["server"] = r.group(1)
|
|
||||||
pac_config["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
|
if 'created_at' in shelf:
|
||||||
else:
|
created_at = shelf['created_at']
|
||||||
pac_config["server"] = None
|
|
||||||
pac_config["domains"] = []
|
if 'data' in shelf:
|
||||||
d.close()
|
data = shelf['data']
|
||||||
_config = pac_config
|
|
||||||
return _config
|
if((time.time() - created_at) <= CACHE_LIFETIME
|
||||||
|
and 'domains' in data
|
||||||
|
and len(data['domains']) > 0):
|
||||||
|
return data
|
||||||
|
|
||||||
|
log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
|
||||||
|
try:
|
||||||
|
pac_data = urllib2.urlopen(PAC_URL).read()
|
||||||
|
except:
|
||||||
|
pac_data = ""
|
||||||
|
|
||||||
|
r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
|
||||||
|
if r:
|
||||||
|
data["server"] = r.group(1)
|
||||||
|
data["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
|
||||||
|
else:
|
||||||
|
data["server"] = None
|
||||||
|
data["domains"] = []
|
||||||
|
|
||||||
|
shelf.clear()
|
||||||
|
shelf.update({
|
||||||
|
"created_at": time.time(),
|
||||||
|
"data": data,
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
except Exception as ex:
|
||||||
|
debug("[antizapret]: " + str(ex))
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
if shelf:
|
||||||
|
shelf.close()
|
||||||
|
if CONFIG_LOCK.locked():
|
||||||
|
CONFIG_LOCK.release()
|
||||||
|
|
||||||
class AntizapretProxyHandler(urllib2.ProxyHandler, object):
|
class AntizapretProxyHandler(urllib2.ProxyHandler, object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -73,7 +79,8 @@ class AntizapretProxyHandler(urllib2.ProxyHandler, object):
|
||||||
def proxy_open(self, req, proxy, type):
|
def proxy_open(self, req, proxy, type):
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
if socket.gethostbyname(req.get_host().split(":")[0]) in self.config["domains"]:
|
hostname = req.get_host().split(":")[0]
|
||||||
|
if socket.gethostbyname(hostname) in self.config["domains"] or hostname in self.config["domains"]:
|
||||||
debug("[antizapret]: Pass request through proxy " + self.config["server"])
|
debug("[antizapret]: Pass request through proxy " + self.config["server"])
|
||||||
return urllib2.ProxyHandler.proxy_open(self, req, self.config["server"], type)
|
return urllib2.ProxyHandler.proxy_open(self, req, self.config["server"], type)
|
||||||
|
|
||||||
|
@ -104,5 +111,4 @@ def url_get(url, params={}, headers={}, post = None):
|
||||||
return data
|
return data
|
||||||
except urllib2.HTTPError as e:
|
except urllib2.HTTPError as e:
|
||||||
log("[antizapret]: HTTP Error(%s): %s" % (e.errno, e.strerror))
|
log("[antizapret]: HTTP Error(%s): %s" % (e.errno, e.strerror))
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1,786 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This is a "local" version of PyXBMCt to be used in standalone addons.
|
|
||||||
#
|
|
||||||
# PyXBMCt is a mini-framework for creating XBMC Python addons with arbitrary UI
|
|
||||||
# made of controls - decendants of xbmcgui.Control class.
|
|
||||||
# The framework uses image textures from XBMC Confluence skin.
|
|
||||||
#
|
|
||||||
# Licence: GPL v.3 http://www.gnu.org/licenses/gpl.html
|
|
||||||
#
|
|
||||||
## @package addonwindow
|
|
||||||
# PyXBMCt framework module
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import xbmc
|
|
||||||
import xbmcgui
|
|
||||||
|
|
||||||
|
|
||||||
# _addon = xbmcaddon.Addon()
|
|
||||||
_images = os.path.join(os.path.dirname(__file__), 'textures', 'default')
|
|
||||||
|
|
||||||
|
|
||||||
# Text alighnment constants. Mixed variants are obtained by bit OR (|)
|
|
||||||
ALIGN_LEFT = 0
|
|
||||||
ALIGN_RIGHT = 1
|
|
||||||
ALIGN_CENTER_X = 2
|
|
||||||
ALIGN_CENTER_Y = 4
|
|
||||||
ALIGN_CENTER = 6
|
|
||||||
ALIGN_TRUNCATED = 8
|
|
||||||
ALIGN_JUSTIFY = 10
|
|
||||||
|
|
||||||
# XBMC key action codes.
|
|
||||||
# More codes at https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
|
|
||||||
## ESC action
|
|
||||||
ACTION_PREVIOUS_MENU = 10
|
|
||||||
## Backspace action
|
|
||||||
ACTION_NAV_BACK = 92
|
|
||||||
## Left arrow key
|
|
||||||
ACTION_MOVE_LEFT = 1
|
|
||||||
## Right arrow key
|
|
||||||
ACTION_MOVE_RIGHT = 2
|
|
||||||
## Up arrow key
|
|
||||||
ACTION_MOVE_UP = 3
|
|
||||||
## Down arrow key
|
|
||||||
ACTION_MOVE_DOWN = 4
|
|
||||||
## Mouse wheel up
|
|
||||||
ACTION_MOUSE_WHEEL_UP = 104
|
|
||||||
## Mouse wheel down
|
|
||||||
ACTION_MOUSE_WHEEL_DOWN = 105
|
|
||||||
## Mouse drag
|
|
||||||
ACTION_MOUSE_DRAG = 106
|
|
||||||
## Mouse move
|
|
||||||
ACTION_MOUSE_MOVE = 107
|
|
||||||
|
|
||||||
|
|
||||||
def _set_textures(textures={}, kwargs={}):
|
|
||||||
"""Set texture arguments for controls."""
|
|
||||||
for texture in textures.keys():
|
|
||||||
try:
|
|
||||||
kwargs[texture]
|
|
||||||
except KeyError:
|
|
||||||
kwargs[texture] = textures[texture]
|
|
||||||
|
|
||||||
|
|
||||||
class AddonWindowError(Exception):
|
|
||||||
"""Custom exception."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Label(xbmcgui.ControlLabel):
|
|
||||||
"""ControlLabel class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
|
|
||||||
alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
hasPath: bool - True=stores a path / False=no path.
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)"
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.label = Label('Status', angle=45)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(Label, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class FadeLabel(xbmcgui.ControlFadeLabel):
|
|
||||||
"""Control that scrolls label text.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of fadelabel's labels. (e.g. '0xFFFFFFFF')
|
|
||||||
_alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.fadelabel = FadeLabel(textColor='0xFFFFFFFF')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(FadeLabel, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TextBox(xbmcgui.ControlTextBox):
|
|
||||||
"""ControlTextBox class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of textbox's text. (e.g. '0xFFFFFFFF')
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.textbox = TextBox(textColor='0xFFFFFFFF')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(TextBox, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Image(xbmcgui.ControlImage):
|
|
||||||
"""ControlImage class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
filename: string - image filename.
|
|
||||||
colorKey: hexString - (example, '0xFFFF3300')
|
|
||||||
aspectRatio: integer - (values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars)
|
|
||||||
colorDiffuse: hexString - (example, '0xC0FF0000' (red tint)).
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.image = Image('d:\images\picture.jpg', aspectRatio=2)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(Image, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Button(xbmcgui.ControlButton):
|
|
||||||
"""ControlButton class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
focusTexture: string - filename for focus texture.
|
|
||||||
noFocusTexture: string - filename for no focus texture.
|
|
||||||
textOffsetX: integer - x offset of label.
|
|
||||||
textOffsetY: integer - y offset of label.
|
|
||||||
alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled button's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled button's label. (e.g. '0xFFFF3300')
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
|
|
||||||
shadowColor: hexstring - color of button's label's shadow. (e.g. '0xFF000000')
|
|
||||||
focusedColor: hexstring - color of focused button's label. (e.g. '0xFF00FFFF')
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.button = Button('Status', font='font14')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'Button', 'KeyboardKey.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'Button', 'KeyboardKeyNF.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
try:
|
|
||||||
kwargs['alignment']
|
|
||||||
except KeyError:
|
|
||||||
kwargs['alignment'] = ALIGN_CENTER
|
|
||||||
return super(Button, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class RadioButton(xbmcgui.ControlRadioButton):
|
|
||||||
"""ControlRadioButton class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
focusTexture: string - filename for focus texture.
|
|
||||||
noFocusTexture: string - filename for no focus texture.
|
|
||||||
textOffsetX: integer - x offset of label.
|
|
||||||
textOffsetY: integer - y offset of label.
|
|
||||||
_alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled radio button's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled radio button's label. (e.g. '0xFFFF3300')
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
|
|
||||||
shadowColor: hexstring - color of radio button's label's shadow. (e.g. '0xFF000000')
|
|
||||||
focusedColor: hexstring - color of focused radio button's label. (e.g. '0xFF00FFFF')
|
|
||||||
focusOnTexture: string - filename for radio focused/checked texture.
|
|
||||||
noFocusOnTexture: string - filename for radio not focused/checked texture.
|
|
||||||
focusOffTexture: string - filename for radio focused/unchecked texture.
|
|
||||||
noFocusOffTexture: string - filename for radio not focused/unchecked texture.
|
|
||||||
Note: To customize RadioButton all 4 abovementioned textures need to be provided.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.radiobutton = RadioButton('Status', font='font14')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
if int(xbmc.getInfoLabel('System.BuildVersion')[:2]) >= 13:
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'RadioButton', 'MenuItemFO.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'RadioButton', 'MenuItemNF.png'),
|
|
||||||
'focusOnTexture': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'noFocusOnTexture': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'focusOffTexture': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png'),
|
|
||||||
'noFocusOffTexture': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png')}
|
|
||||||
else: # This is for compatibility with Frodo and earlier versions.
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'RadioButton', 'MenuItemFO.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'RadioButton', 'MenuItemNF.png'),
|
|
||||||
'TextureRadioFocus': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'TextureRadioNoFocus': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(RadioButton, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Edit(xbmcgui.ControlEdit):
|
|
||||||
"""
|
|
||||||
ControlEdit class.
|
|
||||||
|
|
||||||
Edit(label[, font, textColor, disabledColor, alignment, focusTexture, noFocusTexture])
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label : string or unicode - text string.
|
|
||||||
font : [opt] string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor : [opt] hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor : [opt] hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
|
|
||||||
_alignment : [opt] integer - alignment of label - *Note, see xbfont.h
|
|
||||||
focusTexture : [opt] string - filename for focus texture.
|
|
||||||
noFocusTexture : [opt] string - filename for no focus texture.
|
|
||||||
isPassword : [opt] bool - if true, mask text value.
|
|
||||||
|
|
||||||
*Note, You can use the above as keywords for arguments and skip certain optional arguments.
|
|
||||||
Once you use a keyword, all following arguments require the keyword.
|
|
||||||
After you create the control, you need to add it to the window with palceControl().
|
|
||||||
|
|
||||||
example:
|
|
||||||
- self.edit = Edit('Status')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'Edit', 'button-focus.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'Edit', 'black-back2.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(Edit, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class List(xbmcgui.ControlList):
|
|
||||||
"""ControlList class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for items label. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of items label. (e.g. '0xFFFFFFFF')
|
|
||||||
buttonTexture: string - filename for no focus texture.
|
|
||||||
buttonFocusTexture: string - filename for focus texture.
|
|
||||||
selectedColor: integer - x offset of label.
|
|
||||||
_imageWidth: integer - width of items icon or thumbnail.
|
|
||||||
_imageHeight: integer - height of items icon or thumbnail.
|
|
||||||
_itemTextXOffset: integer - x offset of items label.
|
|
||||||
_itemTextYOffset: integer - y offset of items label.
|
|
||||||
_itemHeight: integer - height of items.
|
|
||||||
_space: integer - space between items.
|
|
||||||
_alignmentY: integer - Y-axis alignment of items label - *Note, see xbfont.h
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.cList = List('font14', space=5)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'buttonTexture': os.path.join(_images, 'List', 'MenuItemNF.png'),
|
|
||||||
'buttonFocusTexture': os.path.join(_images, 'List', 'MenuItemFO.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(List, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Slider(xbmcgui.ControlSlider):
|
|
||||||
"""ControlSlider class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
textureback: string - image filename.
|
|
||||||
texture: string - image filename.
|
|
||||||
texturefocus: string - image filename.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.slider = Slider()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'textureback': os.path.join(_images, 'Slider', 'osd_slider_bg.png'),
|
|
||||||
'texture': os.path.join(_images, 'Slider', 'osd_slider_nibNF.png'),
|
|
||||||
'texturefocus': os.path.join(_images, 'Slider', 'osd_slider_nib.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(Slider, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class _AbstractWindow(object):
|
|
||||||
"""
|
|
||||||
Top-level control window.
|
|
||||||
|
|
||||||
The control windows serves as a parent widget for other XBMC UI controls
|
|
||||||
much like Tkinter.Tk or PyQt QWidget class.
|
|
||||||
This is an abstract class which is not supposed to be instantiated directly
|
|
||||||
and will raise exeptions.
|
|
||||||
|
|
||||||
This class is a basic "skeleton" for a control window.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Constructor method."""
|
|
||||||
self.actions_connected = []
|
|
||||||
self.controls_connected = []
|
|
||||||
|
|
||||||
def setGeometry(self, width_, height_, rows_, columns_, pos_x=-1, pos_y=-1):
|
|
||||||
"""
|
|
||||||
Set width, height, Grid layout, and coordinates (optional) for a new control window.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
width_, height_: widgh and height of the created window.
|
|
||||||
rows_, columns_: rows and colums of the Grid layout to place controls on.
|
|
||||||
pos_x, pos_y (optional): coordinates of the top left corner of the window.
|
|
||||||
If pos_x and pos_y are not privided, the window will be placed
|
|
||||||
at the center of the screen.
|
|
||||||
Example:
|
|
||||||
self.setGeometry(400, 500, 5, 4)
|
|
||||||
"""
|
|
||||||
self.width = width_
|
|
||||||
self.height = height_
|
|
||||||
self.rows = rows_
|
|
||||||
self.columns = columns_
|
|
||||||
if pos_x > 0 and pos_y > 0:
|
|
||||||
self.x = pos_x
|
|
||||||
self.y = pos_y
|
|
||||||
else:
|
|
||||||
self.x = 640 - self.width / 2
|
|
||||||
self.y = 360 - self.height / 2
|
|
||||||
self.setGrid()
|
|
||||||
|
|
||||||
def setGrid(self):
|
|
||||||
"""
|
|
||||||
Set window grid layout of rows * columns.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
self.grid_x = self.x
|
|
||||||
self.grid_y = self.y
|
|
||||||
self.tile_width = self.width / self.columns
|
|
||||||
self.tile_height = self.height / self.rows
|
|
||||||
|
|
||||||
def placeControl(self, control, row, column, rowspan=1, columnspan=1, pad_x=5, pad_y=5):
|
|
||||||
"""
|
|
||||||
Place a control within the window grid layout.
|
|
||||||
|
|
||||||
pad_x, pad_y: horisontal and vertical padding for control's
|
|
||||||
size and aspect adjustments. Negative values can be used
|
|
||||||
to make a control overlap with grid cells next to it, if necessary.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
Example:
|
|
||||||
self.placeControl(self.label, 0, 1)
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
control_x = (self.grid_x + self.tile_width * column) + pad_x
|
|
||||||
control_y = (self.grid_y + self.tile_height * row) + pad_y
|
|
||||||
control_width = self.tile_width * columnspan - 2 * pad_x
|
|
||||||
control_height = self.tile_height * rowspan - 2 * pad_y
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
control.setPosition(control_x, control_y)
|
|
||||||
control.setWidth(control_width)
|
|
||||||
control.setHeight(control_height)
|
|
||||||
self.addControl(control)
|
|
||||||
self.setAnimation(control)
|
|
||||||
|
|
||||||
def getX(self):
|
|
||||||
"""Get X coordinate of the top-left corner of the window."""
|
|
||||||
try:
|
|
||||||
return self.x
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getY(self):
|
|
||||||
"""Get Y coordinate of the top-left corner of the window."""
|
|
||||||
try:
|
|
||||||
return self.y
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getWindowWidth(self):
|
|
||||||
"""Get window width."""
|
|
||||||
try:
|
|
||||||
return self.width
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getWindowHeight(self):
|
|
||||||
"""Get window height."""
|
|
||||||
try:
|
|
||||||
return self.height
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getRows(self):
|
|
||||||
"""
|
|
||||||
Get grid rows count.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.rows
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Grid layot is not set! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getColumns(self):
|
|
||||||
"""
|
|
||||||
Get grid columns count.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.columns
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Grid layout is not set! Call setGeometry first.')
|
|
||||||
|
|
||||||
def connect(self, event, function):
|
|
||||||
"""
|
|
||||||
Connect an event to a function.
|
|
||||||
|
|
||||||
An event can be an inctance of a Control object or an integer key action code.
|
|
||||||
Several basic key action codes are provided by PyXBMCT. More action codes can be found at
|
|
||||||
https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
|
|
||||||
|
|
||||||
You can connect the following Controls: Button, RadioButton and List. Other Controls do not
|
|
||||||
generate any control events when activated so their connections won't work.
|
|
||||||
To catch Slider events you need to connect the following key actions:
|
|
||||||
ACTION_MOVE_LEFT, ACTION_MOVE_RIGHT and ACTION_MOUSE_DRAG, and do a check
|
|
||||||
whether the Slider is focused.
|
|
||||||
|
|
||||||
"function" parameter is a function or a method to be executed. Note that you must provide
|
|
||||||
a function object [without brackets ()], not a function call!
|
|
||||||
lambda can be used as a function to call another function or method with parameters.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
self.connect(self.exit_button, self.close)
|
|
||||||
or
|
|
||||||
self.connect(ACTION_NAV_BACK, self.close)
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.disconnect(event)
|
|
||||||
except AddonWindowError:
|
|
||||||
if type(event) == int:
|
|
||||||
self.actions_connected.append([event, function])
|
|
||||||
else:
|
|
||||||
self.controls_connected.append([event, function])
|
|
||||||
|
|
||||||
def connectEventList(self, events, function):
|
|
||||||
"""
|
|
||||||
Connect a list of controls/action codes to a function.
|
|
||||||
See connect docstring for more info.
|
|
||||||
"""
|
|
||||||
[self.connect(event, function) for event in events]
|
|
||||||
|
|
||||||
def disconnect(self, event):
|
|
||||||
"""
|
|
||||||
Disconnect an event from a function.
|
|
||||||
|
|
||||||
An event can be an inctance of a Control object or an integer key action code
|
|
||||||
which has previously been connected to a function or a method.
|
|
||||||
Raises AddonWindowError if an event is not connected to any function.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
self.disconnect(self.exit_button)
|
|
||||||
or
|
|
||||||
self.disconnect(ACTION_NAV_BACK)
|
|
||||||
"""
|
|
||||||
if type(event) == int:
|
|
||||||
event_list = self.actions_connected
|
|
||||||
else:
|
|
||||||
event_list = self.controls_connected
|
|
||||||
for index in range(len(event_list)):
|
|
||||||
if event == event_list[index][0]:
|
|
||||||
event_list.pop(index)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise AddonWindowError('The action or control %s is not connected!' % event)
|
|
||||||
|
|
||||||
def disconnectEventList(self, events):
|
|
||||||
"""
|
|
||||||
Disconnect a list of controls/action codes from functions.
|
|
||||||
See disconnect docstring for more info.
|
|
||||||
Raises AddonWindowError if at least one event in the list
|
|
||||||
is not connected to any function.
|
|
||||||
"""
|
|
||||||
[self.disconnect(event) for event in events]
|
|
||||||
|
|
||||||
def executeConnected(self, event, connected_list):
|
|
||||||
"""
|
|
||||||
Execute a connected event (an action or a control).
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
for item in connected_list:
|
|
||||||
if event == item[0]:
|
|
||||||
item[1]()
|
|
||||||
break
|
|
||||||
|
|
||||||
def setAnimation(self, control):
|
|
||||||
"""
|
|
||||||
This method is called to set animation properties for all controls
|
|
||||||
added to the current addon window instance - both built-in controls
|
|
||||||
(window background, title bar etc.) and controls added with placeControl().
|
|
||||||
It receives a control instance as the 2nd positional argument (besides self).
|
|
||||||
By default the method does nothing, i.e. no animation is set for controls.
|
|
||||||
To add animation you need to re-implement this menthod in your child class.
|
|
||||||
|
|
||||||
E.g:
|
|
||||||
def setAnimation(self, control):
|
|
||||||
control.setAnimations([('WindowOpen', 'effect=fade start=0 end=100 time=1000',),
|
|
||||||
('WindowClose', 'effect=fade start=100 end=0 time=1000',)])
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class _AddonWindow(_AbstractWindow):
|
|
||||||
"""
|
|
||||||
Top-level control window.
|
|
||||||
|
|
||||||
The control windows serves as a parent widget for other XBMC UI controls
|
|
||||||
much like Tkinter.Tk or PyQt QWidget class.
|
|
||||||
This is an abstract class which is not supposed to be instantiated directly
|
|
||||||
and will raise exeptions. It is designed to be implemented in a grand-child class
|
|
||||||
with the second inheritance from xbmcgui.Window or xbmcgui.WindowDialog
|
|
||||||
in a direct child class.
|
|
||||||
|
|
||||||
This class provides a control window with a background and a header
|
|
||||||
similar to top-level widgets of desktop UI frameworks.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, title=''):
|
|
||||||
"""Constructor method."""
|
|
||||||
super(_AddonWindow, self).__init__()
|
|
||||||
self.setFrame(title)
|
|
||||||
|
|
||||||
def setFrame(self, title):
|
|
||||||
"""
|
|
||||||
Define paths to images for window background and title background textures,
|
|
||||||
and set control position adjustment constants used in setGrid.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
# Window background image
|
|
||||||
self.background_img = os.path.join(_images, 'AddonWindow', 'ContentPanel.png')
|
|
||||||
# Background for a window header
|
|
||||||
self.title_background_img = os.path.join(_images, 'AddonWindow', 'dialogheader.png')
|
|
||||||
# Horisontal adjustment for a header background if the main background has transparent edges.
|
|
||||||
self.X_MARGIN = 5
|
|
||||||
# Vertical adjustment for a header background if the main background has transparent edges
|
|
||||||
self.Y_MARGIN = 5
|
|
||||||
# Header position adjustment if the main backround has visible borders.
|
|
||||||
self.Y_SHIFT = 4
|
|
||||||
# The height of a window header (for the title background and the title label).
|
|
||||||
self.HEADER_HEIGHT = 35
|
|
||||||
self.background = xbmcgui.ControlImage(-10, -10, 1, 1, self.background_img)
|
|
||||||
self.addControl(self.background)
|
|
||||||
self.setAnimation(self.background)
|
|
||||||
self.title_background = xbmcgui.ControlImage(-10, -10, 1, 1, self.title_background_img)
|
|
||||||
self.addControl(self.title_background)
|
|
||||||
self.setAnimation(self.title_background)
|
|
||||||
self.title_bar = xbmcgui.ControlLabel(-10, -10, 1, 1, title, alignment=ALIGN_CENTER, textColor='0xFFFFA500',
|
|
||||||
font='font13_title')
|
|
||||||
self.addControl(self.title_bar)
|
|
||||||
self.setAnimation(self.title_bar)
|
|
||||||
self.window_close_button = xbmcgui.ControlButton(-100, -100, 60, 30, '',
|
|
||||||
focusTexture=os.path.join(_images, 'AddonWindow',
|
|
||||||
'DialogCloseButton-focus.png'),
|
|
||||||
noFocusTexture=os.path.join(_images, 'AddonWindow',
|
|
||||||
'DialogCloseButton.png'))
|
|
||||||
self.addControl(self.window_close_button)
|
|
||||||
self.setAnimation(self.window_close_button)
|
|
||||||
|
|
||||||
def setGeometry(self, width_, height_, rows_, columns_, pos_x=-1, pos_y=-1, padding=5):
|
|
||||||
"""
|
|
||||||
Set width, height, Grid layout, and coordinates (optional) for a new control window.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
width_, height_: widgh and height of the created window.
|
|
||||||
rows_, columns_: rows and colums of the Grid layout to place controls on.
|
|
||||||
pos_x, pos_y (optional): coordinates of the top left corner of the window.
|
|
||||||
If pos_x and pos_y are not privided, the window will be placed
|
|
||||||
at the center of the screen.
|
|
||||||
padding (optional): padding between outer edges of the window and
|
|
||||||
controls placed on it.
|
|
||||||
Example:
|
|
||||||
self.setGeometry(400, 500, 5, 4)
|
|
||||||
"""
|
|
||||||
self.win_padding = padding
|
|
||||||
super(_AddonWindow, self).setGeometry(width_, height_, rows_, columns_, pos_x, pos_y)
|
|
||||||
self.background.setPosition(self.x, self.y)
|
|
||||||
self.background.setWidth(self.width)
|
|
||||||
self.background.setHeight(self.height)
|
|
||||||
self.title_background.setPosition(self.x + self.X_MARGIN, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
self.title_background.setWidth(self.width - 2 * self.X_MARGIN)
|
|
||||||
self.title_background.setHeight(self.HEADER_HEIGHT)
|
|
||||||
self.title_bar.setPosition(self.x + self.X_MARGIN, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
self.title_bar.setWidth(self.width - 2 * self.X_MARGIN)
|
|
||||||
self.title_bar.setHeight(self.HEADER_HEIGHT)
|
|
||||||
self.window_close_button.setPosition(self.x + self.width - 70, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
|
|
||||||
def setGrid(self):
|
|
||||||
"""
|
|
||||||
Set window grid layout of rows * columns.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
self.grid_x = self.x + self.X_MARGIN + self.win_padding
|
|
||||||
self.grid_y = self.y + self.Y_MARGIN + self.Y_SHIFT + self.HEADER_HEIGHT + self.win_padding
|
|
||||||
self.tile_width = (self.width - 2 * (self.X_MARGIN + self.win_padding)) / self.columns
|
|
||||||
self.tile_height = (
|
|
||||||
self.height - self.HEADER_HEIGHT - self.Y_SHIFT - 2 * (
|
|
||||||
self.Y_MARGIN + self.win_padding)) / self.rows
|
|
||||||
|
|
||||||
def setWindowTitle(self, title=''):
|
|
||||||
"""
|
|
||||||
Set window title.
|
|
||||||
This method must be called AFTER (!!!) setGeometry(),
|
|
||||||
otherwise there is some werid bug with all skin text labels set to the 'title' text.
|
|
||||||
Example:
|
|
||||||
self.setWindowTitle('My Cool Addon')
|
|
||||||
"""
|
|
||||||
self.title_bar.setLabel(title)
|
|
||||||
|
|
||||||
def getWindowTitle(self):
|
|
||||||
"""Get window title."""
|
|
||||||
return self.title_bar.getLabel()
|
|
||||||
|
|
||||||
|
|
||||||
class _FullWindow(xbmcgui.Window):
|
|
||||||
"""An abstract class to define window event processing."""
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
"""
|
|
||||||
Catch button actions.
|
|
||||||
Note that, despite being compared to an integer,
|
|
||||||
action is an instance of xbmcgui.Action class.
|
|
||||||
"""
|
|
||||||
if action == ACTION_PREVIOUS_MENU:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(action, self.actions_connected)
|
|
||||||
|
|
||||||
def onControl(self, control):
|
|
||||||
"""
|
|
||||||
Catch activated controls.
|
|
||||||
Control is an instance of xbmcgui.Control class.
|
|
||||||
"""
|
|
||||||
if control == self.window_close_button:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(control, self.controls_connected)
|
|
||||||
|
|
||||||
|
|
||||||
class _DialogWindow(xbmcgui.WindowDialog):
|
|
||||||
"""An abstract class to define window event processing."""
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
"""
|
|
||||||
Catch button actions.
|
|
||||||
Note that, despite being compared to an integer,
|
|
||||||
action is an instance of xbmcgui.Action class.
|
|
||||||
"""
|
|
||||||
if action == ACTION_PREVIOUS_MENU:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(action, self.actions_connected)
|
|
||||||
|
|
||||||
def onControl(self, control):
|
|
||||||
"""
|
|
||||||
Catch activated controls.
|
|
||||||
Control is an instance of xbmcgui.Control class.
|
|
||||||
"""
|
|
||||||
if control == self.window_close_button:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(control, self.controls_connected)
|
|
||||||
|
|
||||||
|
|
||||||
class BlankFullWindow(_FullWindow, _AbstractWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a solid background.
|
|
||||||
This is a blank window with a black background and without any elements whatsoever.
|
|
||||||
The decoration and layout are completely up to an addon developer.
|
|
||||||
The window controls can hide under video or music visualization.
|
|
||||||
Window ID can be passed on class instantiation an agrument
|
|
||||||
but __init__ must have the 2nd fake argument, e.g:
|
|
||||||
|
|
||||||
def __init__(self, *args)
|
|
||||||
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BlankDialogWindow(_DialogWindow, _AbstractWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a transparent background.
|
|
||||||
This is a blank window with a transparent background and without any elements whatsoever.
|
|
||||||
The decoration and layout are completely up to an addon developer.
|
|
||||||
The window controls are always displayed over video or music visualization.
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AddonFullWindow(_FullWindow, _AddonWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a solid background.
|
|
||||||
Control window is displayed on top of the main background image - self.main_bg.
|
|
||||||
Video and music visualization are displayed unhindered.
|
|
||||||
Window ID can be passed on class instantiation as the 2nd positional agrument
|
|
||||||
but __init__ must have the 3rd fake argument, e.g:
|
|
||||||
|
|
||||||
def __init__(self, title='', *args)
|
|
||||||
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, title='', *args, **kwargs):
|
|
||||||
return super(AddonFullWindow, cls).__new__(cls, *args, **kwargs)
|
|
||||||
|
|
||||||
def setFrame(self, title):
|
|
||||||
"""
|
|
||||||
Set the image for for the fullscreen background.
|
|
||||||
"""
|
|
||||||
# Image for the fullscreen background.
|
|
||||||
self.main_bg_img = os.path.join(_images, 'AddonWindow', 'SKINDEFAULT.jpg')
|
|
||||||
# Fullscreen background image control.
|
|
||||||
self.main_bg = xbmcgui.ControlImage(1, 1, 1280, 720, self.main_bg_img)
|
|
||||||
self.addControl(self.main_bg)
|
|
||||||
super(AddonFullWindow, self).setFrame(title)
|
|
||||||
|
|
||||||
def setBackground(self, image=''):
|
|
||||||
"""
|
|
||||||
Set the main bacground to an image file.
|
|
||||||
image: path to an image file as str.
|
|
||||||
Example:
|
|
||||||
self.setBackground('d:\images\bacground.png')
|
|
||||||
"""
|
|
||||||
self.main_bg.setImage(image)
|
|
||||||
|
|
||||||
|
|
||||||
class AddonDialogWindow(_DialogWindow, _AddonWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a transparent background.
|
|
||||||
Control window is displayed on top of XBMC UI,
|
|
||||||
including video an music visualization!
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
|
@ -1,11 +1,12 @@
|
||||||
<settings>
|
<settings>
|
||||||
<category label="30101">
|
<category label="30101">
|
||||||
<setting id="language" type="enum" label="30001" default="1" values="English|Russian|Ukrainian|Hebrew" />
|
<setting id="language" type="enum" label="30001" default="1" values="English|Russian|Ukrainian|Hebrew|Spanish|Hungarian" />
|
||||||
<setting id="metadata" type="bool" label="30014" default="false"/>
|
<setting id="metadata" type="bool" label="30014" default="false"/>
|
||||||
<setting id="history" type="bool" label="30020" default="true"/>
|
<setting id="history" type="bool" label="30020" default="true"/>
|
||||||
<setting id="sort_search" type="enum" label="30061" default="0" lvalues="30062|30063|30064"/>
|
<setting id="sort_search" type="enum" label="30061" default="0" lvalues="30062|30063|30064"/>
|
||||||
<setting id="skin_optimization" type="enum" label="30002" default="1" lvalues="30003|30018|30017|30016|30019|30066|30067"/>
|
<setting id="skin_optimization" type="enum" label="30002" default="1" lvalues="30003|30018|30017|30016|30019|30066|30067|30071|30076"/>
|
||||||
<setting id="open_option" type="enum" label="30034" default="0" lvalues="30035|30036|30037|30038"/>
|
<setting id="open_option" type="enum" label="30034" default="0" lvalues="30035|30036|30037|30038"/>
|
||||||
|
<setting id="searchwindowmode" type="enum" label="30106" default="1" lvalues="30107|30108|30109|30110"/>
|
||||||
</category>
|
</category>
|
||||||
<category label="30103">
|
<category label="30103">
|
||||||
<setting id="timeout" type="enum" lvalues="30026|30027|30028" label="30025" default="1"/>
|
<setting id="timeout" type="enum" lvalues="30026|30027|30028" label="30025" default="1"/>
|
||||||
|
@ -61,15 +62,18 @@
|
||||||
<setting id="torrent_qbittorrent_password" type="text" label="50316" visible="eq(-21,4)" default="admin" option="hidden"/>
|
<setting id="torrent_qbittorrent_password" type="text" label="50316" visible="eq(-21,4)" default="admin" option="hidden"/>
|
||||||
</category>
|
</category>
|
||||||
<category label="30105">
|
<category label="30105">
|
||||||
<setting id="torrent_player" type="enum" label="30023" default="2" lvalues="30021|30022|30046|30068" />
|
<setting id="torrent_player" type="enum" label="30023" default="2" lvalues="30021|30022|30046|30068" />
|
||||||
<setting id="ask_dir" type="bool" label="30031" default="false"/>
|
<setting id="ask_dir" type="bool" label="30031" default="false"/>
|
||||||
<setting id="connections_limit" type="number" label="30051" default="200" visible=" eq(-2,2)"/>
|
<setting id="connections_limit" type="number" label="30051" default="200" visible=" eq(-2,2)"/>
|
||||||
<setting id="use_random_port" type="bool" label="30052" default="false" visible=" eq(-3,2)"/>
|
<setting id="use_random_port" type="bool" label="30052" default="false" visible=" eq(-3,2)"/>
|
||||||
<setting id="listen_port" type="number" label="30053" default="6881" visible="!eq(-4,1)"/>
|
<setting id="listen_port" type="number" label="30053" default="6881" visible="!eq(-4,1)"/>
|
||||||
<setting id="min_storage_size" type="slider" label="30059" default="0" visible="!eq(-5,1)" range="0,2,100" option="int"/>
|
<setting id="min_storage_size" type="slider" label="30059" default="0" visible="!eq(-5,1)" range="0,2,100" option="int"/>
|
||||||
<setting id="pause_onplay" type="bool" label="30060" default="false" visible="!eq(-6,1)"/>
|
<setting id="pause_onplay" type="bool" label="30060" default="false" visible="!eq(-6,1)"/>
|
||||||
<setting id="max_history_add" type="slider" label="30065" default="100" visible="!eq(-7,1)" range="0,2,100" option="int"/>
|
<setting id="max_history_add" type="slider" label="30065" default="100" visible="!eq(-7,1)" range="0,2,100" option="int"/>
|
||||||
<setting id="enable_dht" type="bool" label="30070" default="true" visible="!eq(-8,1)"/>
|
<setting id="enable_dht" type="bool" label="30070" default="true" visible="!eq(-8,1)"/>
|
||||||
<setting id="append_filesize" type="bool" label="30069" default="true"/>
|
<setting id="append_filesize" type="bool" label="30069" default="true"/>
|
||||||
|
<setting id="torrent_info_style" type="enum" label="30072" default="0" lvalues="30073|30074|30075"/>
|
||||||
|
<setting id="disable_notifications" type="bool" label="30112" default="false"/>
|
||||||
|
<setting id="sw_transparent_back" type="bool" label="30111" default="false"/>
|
||||||
</category>
|
</category>
|
||||||
</settings>
|
</settings>
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
<window>
|
|
||||||
<coordinates>
|
|
||||||
<system>1</system>
|
|
||||||
<posx>240</posx>
|
|
||||||
<posy>20</posy>
|
|
||||||
</coordinates>
|
|
||||||
<include>dialogeffect</include>
|
|
||||||
<controls>
|
|
||||||
<control type="group">
|
|
||||||
<animation effect="fade" time="250">WindowOpen</animation>
|
|
||||||
<animation effect="fade" time="250">WindowClose</animation>
|
|
||||||
<control type="image">
|
|
||||||
<description>background image</description>
|
|
||||||
<posx>0</posx>
|
|
||||||
<posy>0</posy>
|
|
||||||
<width>800</width>
|
|
||||||
<height>680</height>
|
|
||||||
<texture border="40">ConfluenceDialogBack.png</texture>
|
|
||||||
</control>
|
|
||||||
<control type="image">
|
|
||||||
<description>Dialog Header image</description>
|
|
||||||
<posx>40</posx>
|
|
||||||
<posy>16</posy>
|
|
||||||
<width>720</width>
|
|
||||||
<height>40</height>
|
|
||||||
<texture>Confluencedialogheader.png</texture>
|
|
||||||
</control>
|
|
||||||
<control type="label" id="1">
|
|
||||||
<description>header label</description>
|
|
||||||
<posx>40</posx>
|
|
||||||
<posy>20</posy>
|
|
||||||
<width>720</width>
|
|
||||||
<height>30</height>
|
|
||||||
<font>font13_title</font>
|
|
||||||
<label>Информация о фильме</label>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<textcolor>selected</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="button" id="2">
|
|
||||||
<description>Close Window button</description>
|
|
||||||
<posx>710</posx>
|
|
||||||
<posy>15</posy>
|
|
||||||
<width>64</width>
|
|
||||||
<height>32</height>
|
|
||||||
<label>-</label>
|
|
||||||
<font>-</font>
|
|
||||||
<onclick>PreviousMenu</onclick>
|
|
||||||
<texturefocus>ConfluenceDialogCloseButton-focus.png</texturefocus>
|
|
||||||
<texturenofocus>ConfluenceDialogCloseButton.png</texturenofocus>
|
|
||||||
<onleft>10</onleft>
|
|
||||||
<onright>10</onright>
|
|
||||||
<onup>10</onup>
|
|
||||||
<ondown>10</ondown>
|
|
||||||
<visible>system.getbool(input.enablemouse)</visible>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="scrollbar" id="60">
|
|
||||||
<posx>760</posx>
|
|
||||||
<posy>100</posy>
|
|
||||||
<width>25</width>
|
|
||||||
<height>495</height>
|
|
||||||
<texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
|
|
||||||
<texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
|
|
||||||
<texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
|
|
||||||
<textureslidernib>ScrollBarNib.png</textureslidernib>
|
|
||||||
<textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
|
|
||||||
<onleft>30</onleft>
|
|
||||||
<onright>131</onright>
|
|
||||||
<showonepage>true</showonepage>
|
|
||||||
<visible>IntegerGreaterThan(Container(32).NumPages,1)</visible>
|
|
||||||
<orientation>vertical</orientation>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="image" id="31">
|
|
||||||
<description>Dialog Header image</description>
|
|
||||||
<posx>33</posx>
|
|
||||||
<posy>85</posy>
|
|
||||||
<width>104</width>
|
|
||||||
<height>149</height>
|
|
||||||
<texture></texture>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="label" id="34">
|
|
||||||
<description>rating</description>
|
|
||||||
<posx>34</posx>
|
|
||||||
<posy>240</posy>
|
|
||||||
<width>102</width>
|
|
||||||
<height>20</height>
|
|
||||||
<visible>true</visible>
|
|
||||||
<align>left</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<scroll>false</scroll>
|
|
||||||
<label></label>
|
|
||||||
<haspath>false</haspath>
|
|
||||||
<font>font10</font>
|
|
||||||
<textcolor>white</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
<wrapmultiline>false</wrapmultiline>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="label" id="35">
|
|
||||||
<description>rating</description>
|
|
||||||
<posx>34</posx>
|
|
||||||
<posy>260</posy>
|
|
||||||
<width>102</width>
|
|
||||||
<height>20</height>
|
|
||||||
<visible>true</visible>
|
|
||||||
<align>left</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<scroll>false</scroll>
|
|
||||||
<label>[COLOR blue]Рейтинг:[/COLOR] [COLOR red]-200[/COLOR]</label>
|
|
||||||
<haspath>false</haspath>
|
|
||||||
<font>font10</font>
|
|
||||||
<textcolor>white</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
<wrapmultiline>false</wrapmultiline>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="image" id="36">
|
|
||||||
<description>kinopoisk</description>
|
|
||||||
<posx>34</posx>
|
|
||||||
<posy>292</posy>
|
|
||||||
<width>102</width>
|
|
||||||
<height>38</height>
|
|
||||||
<texture></texture>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="textbox" id="32">
|
|
||||||
<description>filepath</description>
|
|
||||||
<posx>180</posx>
|
|
||||||
<posy>70</posy>
|
|
||||||
<width>550</width>
|
|
||||||
<pagecontrol>60</pagecontrol>
|
|
||||||
<height max="470">470</height>
|
|
||||||
<align>left</align>
|
|
||||||
<aligny>top</aligny>
|
|
||||||
<font>font18</font>
|
|
||||||
<text>Нет описания</text>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<textcolor>white</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
<wrapmultiline>true</wrapmultiline>
|
|
||||||
</control>
|
|
||||||
<control type="group" id="9001">
|
|
||||||
<posy>615</posy>
|
|
||||||
<posx>50</posx>
|
|
||||||
|
|
||||||
<control type="button" id="22">
|
|
||||||
<description>close</description>
|
|
||||||
<posx>350</posx>
|
|
||||||
<posy>0</posy>
|
|
||||||
<width>320</width>
|
|
||||||
<height>40</height>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<font>font12_title</font>
|
|
||||||
<label></label>
|
|
||||||
<onleft>33</onleft>
|
|
||||||
<onright>60</onright>
|
|
||||||
<onup>30</onup>
|
|
||||||
<ondown>30</ondown>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="button" id="131">
|
|
||||||
<description>play</description>
|
|
||||||
<posx>20</posx>
|
|
||||||
<posy>-50</posy>
|
|
||||||
<width>320</width>
|
|
||||||
<height>40</height>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<font>font12_title</font>
|
|
||||||
<label></label>
|
|
||||||
<onleft>60</onleft>
|
|
||||||
<onright>30</onright>
|
|
||||||
<onup>33</onup>
|
|
||||||
<ondown>33</ondown>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="button" id="30">
|
|
||||||
<description>libtorrent</description>
|
|
||||||
<posx>350</posx>
|
|
||||||
<posy>-50</posy>
|
|
||||||
<width>320</width>
|
|
||||||
<height>40</height>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<font>font12_title</font>
|
|
||||||
<label></label>
|
|
||||||
<onleft>131</onleft>
|
|
||||||
<onright>60</onright>
|
|
||||||
<onup>22</onup>
|
|
||||||
<ondown>22</ondown>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="button" id="33">
|
|
||||||
<description>tclient</description>
|
|
||||||
<posx>20</posx>
|
|
||||||
<posy>0</posy>
|
|
||||||
<width>320</width>
|
|
||||||
<height>40</height>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<font>font12_title</font>
|
|
||||||
<label>T-client</label>
|
|
||||||
<onleft>22</onleft>
|
|
||||||
<onright>22</onright>
|
|
||||||
<onup>131</onup>
|
|
||||||
<ondown>131</ondown>
|
|
||||||
</control>
|
|
||||||
</control>
|
|
||||||
</control>
|
|
||||||
</controls>
|
|
||||||
</window>
|
|
|
@ -1,127 +0,0 @@
|
||||||
<window>
|
|
||||||
<coordinates>
|
|
||||||
<system>1</system>
|
|
||||||
<posx>240</posx>
|
|
||||||
<posy>20</posy>
|
|
||||||
</coordinates>
|
|
||||||
<include>dialogeffect</include>
|
|
||||||
<controls>
|
|
||||||
<control type="group">
|
|
||||||
<animation effect="fade" time="250">WindowOpen</animation>
|
|
||||||
<animation effect="fade" time="250">WindowClose</animation>
|
|
||||||
<control type="image">
|
|
||||||
<description>background image</description>
|
|
||||||
<posx>0</posx>
|
|
||||||
<posy>0</posy>
|
|
||||||
<width>800</width>
|
|
||||||
<height>680</height>
|
|
||||||
<texture border="40">DialogBack.png</texture>
|
|
||||||
</control>
|
|
||||||
<control type="image">
|
|
||||||
<description>Dialog Header image</description>
|
|
||||||
<posx>40</posx>
|
|
||||||
<posy>16</posy>
|
|
||||||
<width>720</width>
|
|
||||||
<height>40</height>
|
|
||||||
<texture>dialogheader.png</texture>
|
|
||||||
</control>
|
|
||||||
<control type="label" id="1">
|
|
||||||
<description>header label</description>
|
|
||||||
<posx>40</posx>
|
|
||||||
<posy>20</posy>
|
|
||||||
<width>720</width>
|
|
||||||
<height>30</height>
|
|
||||||
<font>font13_title</font>
|
|
||||||
<label>Отзывы о фильме</label>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<textcolor>selected</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="button" id="2">
|
|
||||||
<description>Close Window button</description>
|
|
||||||
<posx>710</posx>
|
|
||||||
<posy>15</posy>
|
|
||||||
<width>64</width>
|
|
||||||
<height>32</height>
|
|
||||||
<label>-</label>
|
|
||||||
<font>-</font>
|
|
||||||
<onclick>PreviousMenu</onclick>
|
|
||||||
<texturefocus>DialogCloseButton-focus.png</texturefocus>
|
|
||||||
<texturenofocus>DialogCloseButton.png</texturenofocus>
|
|
||||||
<onleft>10</onleft>
|
|
||||||
<onright>10</onright>
|
|
||||||
<onup>10</onup>
|
|
||||||
<ondown>10</ondown>
|
|
||||||
<visible>system.getbool(input.enablemouse)</visible>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="scrollbar" id="60">
|
|
||||||
<posx>760</posx>
|
|
||||||
<posy>100</posy>
|
|
||||||
<width>25</width>
|
|
||||||
<height>495</height>
|
|
||||||
<texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
|
|
||||||
<texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
|
|
||||||
<texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
|
|
||||||
<textureslidernib>ScrollBarNib.png</textureslidernib>
|
|
||||||
<textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
|
|
||||||
<onleft>22</onleft>
|
|
||||||
<onright>22</onright>
|
|
||||||
<showonepage>true</showonepage>
|
|
||||||
<visible>IntegerGreaterThan(Container(32).NumPages,1)</visible>
|
|
||||||
<orientation>vertical</orientation>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
<control type="image" id="31">
|
|
||||||
<description>Dialog Header image</description>
|
|
||||||
<posx>33</posx>
|
|
||||||
<posy>85</posy>
|
|
||||||
<width>104</width>
|
|
||||||
<height>149</height>
|
|
||||||
<texture></texture>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
|
|
||||||
<control type="textbox" id="32">
|
|
||||||
<description>filepath</description>
|
|
||||||
<posx>60</posx>
|
|
||||||
<posy>70</posy>
|
|
||||||
<width>690</width>
|
|
||||||
<pagecontrol>60</pagecontrol>
|
|
||||||
<height max="530">530</height>
|
|
||||||
<align>left</align>
|
|
||||||
<aligny>top</aligny>
|
|
||||||
<font>font12</font>
|
|
||||||
<text>Нет отзывов</text>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<textcolor>white</textcolor>
|
|
||||||
<shadowcolor>black</shadowcolor>
|
|
||||||
<wrapmultiline>true</wrapmultiline>
|
|
||||||
</control>
|
|
||||||
<control type="group" id="9001">
|
|
||||||
<posy>615</posy>
|
|
||||||
<posx>50</posx>
|
|
||||||
|
|
||||||
<control type="button" id="22">
|
|
||||||
<description>close</description>
|
|
||||||
<posx>20</posx>
|
|
||||||
<posy>0</posy>
|
|
||||||
<width>650</width>
|
|
||||||
<height>40</height>
|
|
||||||
<align>center</align>
|
|
||||||
<aligny>center</aligny>
|
|
||||||
<font>font12_title</font>
|
|
||||||
<label>Закрыть окно</label>
|
|
||||||
<onleft>60</onleft>
|
|
||||||
<onright>60</onright>
|
|
||||||
<onup>60</onup>
|
|
||||||
<ondown>60</ondown>
|
|
||||||
</control>
|
|
||||||
|
|
||||||
</control>
|
|
||||||
</control>
|
|
||||||
</controls>
|
|
||||||
</window>
|
|
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.8 KiB |
|
@ -1,63 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import re
|
|
||||||
import htmlentitydefs
|
|
||||||
|
|
||||||
import xbmcgui
|
|
||||||
|
|
||||||
pattern = re.compile("&(\w+?);")
|
|
||||||
|
|
||||||
def html_entity_decode_char(m, defs=htmlentitydefs.entitydefs):
|
|
||||||
try:
|
|
||||||
return defs[m.group(1)]
|
|
||||||
except KeyError:
|
|
||||||
return m.group(0)
|
|
||||||
|
|
||||||
def html_entity_decode(string):
|
|
||||||
return pattern.sub(html_entity_decode_char, string)
|
|
||||||
|
|
||||||
KEY_BUTTON_BACK = 275
|
|
||||||
KEY_KEYBOARD_ESC = 61467
|
|
||||||
ACTION_PREVIOUS_MENU = 10
|
|
||||||
ACTION_NAV_BACK = 92
|
|
||||||
class DialogReviews(xbmcgui.WindowXMLDialog):
|
|
||||||
def onInit(self):
|
|
||||||
print "DialogReviews(): Window Initialized"
|
|
||||||
self.reviews_box = self.getControl(32)
|
|
||||||
self.reviews_box.setText(self.get_reviews())
|
|
||||||
|
|
||||||
self.setFocus(self.getControl(22))
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
buttonCode = action.getButtonCode()
|
|
||||||
if (action == ACTION_NAV_BACK or action == ACTION_PREVIOUS_MENU):
|
|
||||||
self.close()
|
|
||||||
if (buttonCode == KEY_BUTTON_BACK or buttonCode == KEY_KEYBOARD_ESC):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def onClick(self, controlID):
|
|
||||||
if (controlID == 2 or controlID == 22):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
def onFocus(self, controlID):
|
|
||||||
#print "onFocus(): control %i" % controlID
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def doModal(self, movieHtml):
|
|
||||||
self.movieHtml = movieHtml
|
|
||||||
xbmcgui.WindowXMLDialog.doModal(self)
|
|
||||||
|
|
||||||
|
|
||||||
def get_reviews(self):
|
|
||||||
reviews_texts = re.compile('<div class="comment" id="[^"]+">([^<]+)</div>',re.S).findall(self.movieHtml)
|
|
||||||
reviews_autors = re.compile('<div class="member"><a href="[^"]+"><strong>([^<]+)</strong></a></div>',re.S).findall(self.movieHtml)
|
|
||||||
reviews_dates = re.compile('<div class="date">([^<]+)</div>',re.S).findall(self.movieHtml)
|
|
||||||
texts = ''
|
|
||||||
i = 0
|
|
||||||
for text in reviews_texts:
|
|
||||||
texts = texts+"\n[B][COLOR purple]"+reviews_autors[i]+"[/COLOR][/B] [I]"+reviews_dates[i]+"[/I]\n"
|
|
||||||
texts = texts+html_entity_decode(text)+"\n"
|
|
||||||
i = i + 1
|
|
||||||
return texts
|
|
|
@ -1,83 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import xbmcgui
|
|
||||||
import Localization
|
|
||||||
import xbmc
|
|
||||||
|
|
||||||
KEY_BUTTON_BACK = 275
|
|
||||||
KEY_KEYBOARD_ESC = 61467
|
|
||||||
ACTION_PREVIOUS_MENU = 10
|
|
||||||
ACTION_NAV_BACK = 92
|
|
||||||
|
|
||||||
|
|
||||||
class DialogXml(xbmcgui.WindowXMLDialog):
|
|
||||||
def onInit(self):
|
|
||||||
print "onInit(): Window Initialized"
|
|
||||||
localize = Localization.localize
|
|
||||||
color = '[COLOR %s]%s[/COLOR]'
|
|
||||||
self.movie_label = self.getControl(32)
|
|
||||||
self.movie_label.setText(self.movieInfo['desc'])
|
|
||||||
|
|
||||||
if self.movieInfo.get('views'):
|
|
||||||
self.view_label = self.getControl(34)
|
|
||||||
self.view_label.setLabel(color % ('blue', localize('Views:')) + self.movieInfo['views'])
|
|
||||||
|
|
||||||
self.view_label = self.getControl(35)
|
|
||||||
self.ratingcolor = 'green'
|
|
||||||
self.ratingint = int(self.movieInfo['rating'])
|
|
||||||
if (self.ratingint < 70):
|
|
||||||
self.ratingcolor = 'red'
|
|
||||||
self.view_label.setLabel(
|
|
||||||
color % ('blue', localize('Rating:')) + color % (self.ratingcolor, self.movieInfo['rating']))
|
|
||||||
|
|
||||||
self.movie_label = self.getControl(1)
|
|
||||||
self.movie_label.setLabel(self.movieInfo['title'])
|
|
||||||
|
|
||||||
self.movie_label = self.getControl(32)
|
|
||||||
self.movie_label.setText(self.movieInfo['desc'])
|
|
||||||
|
|
||||||
self.poster = self.getControl(31)
|
|
||||||
self.poster.setImage(self.movieInfo['poster'])
|
|
||||||
|
|
||||||
self.poster = self.getControl(36)
|
|
||||||
self.poster.setImage(self.movieInfo['kinopoisk'])
|
|
||||||
self.getControl(22).setLabel(localize('Close'))
|
|
||||||
self.getControl(33).setLabel(localize('Download via T-client'))
|
|
||||||
self.getControl(30).setLabel(localize('Download via Libtorrent'))
|
|
||||||
self.getControl(131).setLabel(localize('Play'))
|
|
||||||
|
|
||||||
self.setFocus(self.getControl(22))
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
buttonCode = action.getButtonCode()
|
|
||||||
if (action == ACTION_NAV_BACK or action == ACTION_PREVIOUS_MENU):
|
|
||||||
self.close()
|
|
||||||
if (buttonCode == KEY_BUTTON_BACK or buttonCode == KEY_KEYBOARD_ESC):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def onClick(self, controlID):
|
|
||||||
if (controlID == 2 or controlID == 22):
|
|
||||||
self.close()
|
|
||||||
if (controlID == 30):
|
|
||||||
self.RunPlugin('downloadLibtorrent')
|
|
||||||
if (controlID == 33):
|
|
||||||
self.RunPlugin('downloadFilesList')
|
|
||||||
if (controlID == 131):
|
|
||||||
self.RunPlugin('openTorrent&external=1')
|
|
||||||
|
|
||||||
def RunPlugin(self, action):
|
|
||||||
if self.link:
|
|
||||||
exec_str = 'XBMC.RunPlugin(%s)' % \
|
|
||||||
('%s?action=%s&url=%s') % \
|
|
||||||
(sys.argv[0], action, self.link)
|
|
||||||
xbmc.executebuiltin(exec_str)
|
|
||||||
|
|
||||||
def onFocus(self, controlID):
|
|
||||||
# print "onFocus(): control %i" % controlID
|
|
||||||
pass
|
|
||||||
|
|
||||||
def doModal(self, movieInfo, url):
|
|
||||||
self.movieInfo = movieInfo
|
|
||||||
self.link = url
|
|
||||||
xbmcgui.WindowXMLDialog.doModal(self)
|
|