Merge pull request #15 from DiMartinoXBMC/master

Merge from Dimartino
pull/16/merge
Роман 2017-07-10 20:51:01 +03:00 committed by GitHub
commit 1fa43deb29
85 changed files with 5569 additions and 3498 deletions

View File

@ -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>

View File

@ -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>

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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'),
# self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
#else:
#if self.seeding: self.db_delete()
showMessage(self.localize('Information'), showMessage(self.localize('Information'),
self.localize('Torrent downloading is stopped.'), forced=True) self.localize('torrent2http process stopped.'))
loadsw_onstop() # Reload Search Window
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)
] ]

View File

@ -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:
('>', '&gt;'), ('>', '&gt;'),
('"', '&quot;'), ('"', '&quot;'),
("'", '&#39;'), ("'", '&#39;'),
("'", '&#039;'),
(' ', '&nbsp;',), (' ', '&nbsp;',),
('"', '&laquo;', ), ('"', '&laquo;', ),
('"', '&raquo;', ), ('"', '&raquo;', ),
@ -218,6 +228,7 @@ class Content:
('e', '&#233;',), ('e', '&#233;',),
('e', '&#232;',), ('e', '&#232;',),
('&', '&#38;',), ('&', '&#38;',),
('&', '&#038;',),
('u', '&#249;',), ('u', '&#249;',),
('u', '&#250;',), ('u', '&#250;',),
('o', '&#244;',), ('o', '&#244;',),

354
Core.py
View File

@ -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'),
ListString % ('History', 'clear', 'addtime', '')))
if self.searchwindowmode == 1:
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', self.drawItem('< %s >' % self.localize('Search History'), 'History',
image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False) 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', ) 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',
if self.searchwindowmode == 1:
self.drawItem('< %s >' % self.localize('Download Status'), 'swDownloadStatus',
image=self.ROOT + '/icons/download.png',
contextMenu=DLScontextMenu, replaceMenu=False) 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', self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'uTorrentBrowser',
image=self.ROOT + '/icons/' + self.getTorrentClientIcon()) image=self.ROOT + '/icons/' + getTorrentClientIcon())
if self.history_bool:
#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', '')))
if self.searchwindowmode == 1:
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', self.drawItem('< %s >' % self.localize('Watched History'), 'WatchedHistory',
image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu, replaceMenu=False) 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:
if self.searchwindowmode > 1:
self.openTorrent(params) 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={}):
if params.get('filename'):
torrentUrl = unquote(params.get('filename'))
else:
torrentUrl = self.__settings__.getSetting("lastTorrent") 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={}):
if not self.version_check():
xbmc.executebuiltin("Action(ContextMenu)") xbmc.executebuiltin("Action(ContextMenu)")
return 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,6 +1992,21 @@ 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'])
dialog_items_clean.append(data['name'])
log('[chooseHASH]: name %s ' % str(name))
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: if len(dialog_items) > 1:
ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items) ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items)
if ret > -1 and ret < len(dialog_files): if ret > -1 and ret < len(dialog_files):
@ -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

View File

@ -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'),

View File

@ -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,6 +31,265 @@ except:
def localize(text): def localize(text):
dictionary = { dictionary = {
'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': { 'he': {
'Seeds searching.': 'חיפוש זורעים', 'Seeds searching.': 'חיפוש זורעים',
'Please Wait': 'המתן', 'Please Wait': 'המתן',
@ -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': '',
'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!':'Все запущене!',

View File

@ -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)
] ]

View File

@ -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()

View File

@ -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)
@ -146,6 +136,29 @@ class SkorbaLoader:
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

View File

@ -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>
@ -24,6 +25,10 @@
<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>
<summary lang='es'>Complemento que nos permite ver vídeos que se distribuyen en redes BitTorrent sin necesidad de descargarlos previamente por completo.
</summary>
<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.
</description>
<forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum> <forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum>
<website>http://xbmc.ru/forum/showthread.php?t=6837</website> <website>http://xbmc.ru/forum/showthread.php?t=6837</website>
<email>skype:kyonkodura</email> <email>skype:kyonkodura</email>

View File

@ -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]

View File

@ -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,6 +243,9 @@ class ControlCenter(AddonDialogWindow):
def openSearcherSettings(self): def openSearcherSettings(self):
slist=Searchers().activeExternal() slist=Searchers().activeExternal()
if len(slist)>0: if len(slist)>0:
if len(slist) == 1:
ret = 0
else:
ret = xbmcgui.Dialog().select(__language__(30418), slist) 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]

View File

@ -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,6 +152,7 @@ def debug(msg, forced=False):
def showMessage(heading, message, times=10000, forced=False): def showMessage(heading, message, times=10000, forced=False):
if forced or not getSettingAsBool('disable_notifications'):
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s, "%s")' % ( xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s, "%s")' % (
heading.replace('"', "'"), message.replace('"', "'"), times, icon)) 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,12 +632,27 @@ 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>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
<include>MediaListView3</include> <!-- view id = 503 --> <include>MediaListView3</include> <!-- view id = 503 -->
@ -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():
if result.get(k):
filesList.extend(result[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)
@ -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",
@ -2102,3 +2246,83 @@ def get_platform():
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'

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
icons/kodi.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -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):

View File

@ -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+&nbsp;.+?)</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+&nbsp;.+?)</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

View File

@ -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,7 +201,11 @@ 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) &ndash;|(.+) \(.*(\d\d\d\d)", a_all.text,
re.IGNORECASE | re.MULTILINE)
if match:
title = match.group(1)
year = match.group(2)
info['tvshowtitle'] = title info['tvshowtitle'] = title
except: except:
title = a_all.text title = a_all.text

View File

@ -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*?\..+?&nbsp;.+?)</td>.+?<img .+?alt="S".+?>&nbsp;(\d+)</span>.+?alt="L".+?>&nbsp;(\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('&nbsp;', ' ')
date = date.replace('&nbsp;', ' ')
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

View File

@ -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,25 +93,19 @@ 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):
result = re.compile(regex_tr, re.DOTALL).findall(tr)
self.debug(tr + ' -> ' + str(result))
if result:
(title, link, date, size, seeds, leechers) = result[0]
info = {} info = {}
num = num - 1 num = num - 1
original_title = None original_title = None
@ -122,6 +118,7 @@ class ThePirateBaySe(Content.Content):
info['label'] = info['title'] = self.unescape(title) info['label'] = info['title'] = self.unescape(title)
info['link'] = link info['link'] = link
self.log(info['link'])
info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date) info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date)
contentList.append(( contentList.append((
int(int(self.sourceWeight) * (int(num))), int(int(self.sourceWeight) * (int(num))),

View File

@ -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'),

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,50 +1,44 @@
# -*- 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)
except anydbm.error:
os.remove(filename)
shelf = shelve.open(filename)
created_at = 0
data = {}
if 'created_at' in shelf:
created_at = shelf['created_at']
if 'data' in shelf:
data = shelf['data']
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) log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
try: try:
pac_data = urllib2.urlopen(PAC_URL).read() pac_data = urllib2.urlopen(PAC_URL).read()
@ -53,14 +47,26 @@ def config():
r = re.search(r"\"PROXY (.*); DIRECT", pac_data) r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
if r: if r:
pac_config["server"] = r.group(1) data["server"] = r.group(1)
pac_config["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data))) data["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
else: else:
pac_config["server"] = None data["server"] = None
pac_config["domains"] = [] data["domains"] = []
d.close()
_config = pac_config shelf.clear()
return _config 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)
@ -105,4 +112,3 @@ def url_get(url, params={}, headers={}, post = None):
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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -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"/>
@ -71,5 +72,8 @@
<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>

View File

@ -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>

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -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

View File

@ -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)

1371
searchwindow.py 100644

File diff suppressed because it is too large Load Diff