Compare commits
	
		
			No commits in common. "master" and "sandbox1" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										3
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						@ -1,4 +1,5 @@
 | 
				
			|||||||
<?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.12 (D:\Python27\python.exe)" project-jdk-type="Python SDK" />
 | 
					  <component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.7 (D:/Python27/python.exe)" project-jdk-type="Python SDK" />
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
								
							
							
						
						@ -6,3 +6,4 @@
 | 
				
			|||||||
    </modules>
 | 
					    </modules>
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.idea/plugin.video.torrenter.iml
									
									
									
										generated
									
									
									
								
							
							
						
						@ -2,7 +2,8 @@
 | 
				
			|||||||
<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="jdk" jdkName="Python 2.7.12 (D:\Python27\python.exe)" jdkType="Python SDK" />
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
    <orderEntry type="sourceFolder" forTests="false" />
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</module>
 | 
					</module>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2669
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
							
								
								
									
										49
									
								
								AceStream.py
									
									
									
									
									
								
							
							
						
						@ -25,10 +25,10 @@ import hashlib
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
import base64
 | 
					import base64
 | 
				
			||||||
from StringIO import StringIO
 | 
					from StringIO import StringIO
 | 
				
			||||||
import zlib
 | 
					import gzip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from functions import file_decode, file_encode
 | 
					from functions import file_decode, file_encode
 | 
				
			||||||
from functions import magnet_alert, log, loadsw_onstop
 | 
					from functions import magnet_alert, log, debug
 | 
				
			||||||
import xbmcvfs
 | 
					import xbmcvfs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,7 +81,6 @@ 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), '')
 | 
				
			||||||
@ -94,12 +93,19 @@ 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("^[htps]+?://.+$|^://.+$", torrentUrl):
 | 
					                if not re.match("^http\:.+$", torrentUrl):
 | 
				
			||||||
                    log('xbmcvfs.File for %s' % torrentUrl)
 | 
					                    content = xbmcvfs.File(file_decode(torrentUrl), "rb").read()
 | 
				
			||||||
                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
					 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    log('request for %s' % torrentUrl)
 | 
					                    request = urllib2.Request(torrentUrl)
 | 
				
			||||||
                    content = self.makeRequest(torrentUrl)
 | 
					                    request.add_header('Referer', 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)
 | 
				
			||||||
@ -113,33 +119,10 @@ 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 Libtorrent import Libtorrent
 | 
				
			||||||
            torrent = SkorbaLoader(self.storageDirectory, magnet)
 | 
					            torrent = Libtorrent(self.storageDirectory, magnet)
 | 
				
			||||||
            torrent.magnetToTorrent(magnet)
 | 
					            torrent.magnetToTorrent(magnet)
 | 
				
			||||||
            self.torrentFile = torrent.torrentFile
 | 
					            self.torrentFile = torrent.torrentFile
 | 
				
			||||||
            log('[AceStream][magnetToTorrent]: self.torrentFile '+str(self.torrentFile))
 | 
					            log('[AceStream][magnetToTorrent]: self.torrentFile '+str(self.torrentFile))
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										180
									
								
								Anteoloader.py
									
									
									
									
									
								
							
							
						
						@ -2,7 +2,6 @@
 | 
				
			|||||||
'''
 | 
					'''
 | 
				
			||||||
    Torrenter v2 plugin for XBMC/Kodi
 | 
					    Torrenter v2 plugin for XBMC/Kodi
 | 
				
			||||||
    Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2
 | 
					    Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2
 | 
				
			||||||
    https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This program is free software: you can redistribute it and/or modify
 | 
					    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
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
@ -30,7 +29,7 @@ import xbmcgui
 | 
				
			|||||||
import xbmcvfs
 | 
					import xbmcvfs
 | 
				
			||||||
import xbmcaddon
 | 
					import xbmcaddon
 | 
				
			||||||
import Localization
 | 
					import Localization
 | 
				
			||||||
from functions import localize_path, isSubtitle, loadsw_onstop, is_writable, file_url
 | 
					from functions import localize_path, isSubtitle, is_writable, file_url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
@ -41,10 +40,16 @@ from contextlib import contextmanager, closing, nested
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from functions import foldername, showMessage, clearStorage, WatchedHistoryDB, get_ids_video, log, debug, ensure_str
 | 
					from functions import foldername, showMessage, clearStorage, WatchedHistoryDB, get_ids_video, log, debug, ensure_str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if sys.modules["__main__"].__settings__.getSetting("torrent_player") == '2':
 | 
				
			||||||
from torrent2http import State, Engine, MediaType
 | 
					from torrent2http import State, Engine, MediaType
 | 
				
			||||||
author = 'Anteo'
 | 
					author = 'Anteo'
 | 
				
			||||||
__settings__ = xbmcaddon.Addon(id='script.module.torrent2http')
 | 
					__settings__ = xbmcaddon.Addon(id='script.module.torrent2http')
 | 
				
			||||||
__version__ = __settings__.getAddonInfo('version')
 | 
					__version__ = __settings__.getAddonInfo('version')
 | 
				
			||||||
 | 
					#elif sys.modules["__main__"].__settings__.getSetting("torrent_player") == '3':
 | 
				
			||||||
 | 
					#    from pyrrent2http import State, Engine, MediaType
 | 
				
			||||||
 | 
					#    author = 'Inpos'
 | 
				
			||||||
 | 
					#    __settings__ = xbmcaddon.Addon(id='script.module.pyrrent2http')
 | 
				
			||||||
 | 
					#    __version__ = __settings__.getAddonInfo('version')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ROOT = sys.modules["__main__"].__root__
 | 
					ROOT = sys.modules["__main__"].__root__
 | 
				
			||||||
RESOURCES_PATH = os.path.join(ROOT, 'resources')
 | 
					RESOURCES_PATH = os.path.join(ROOT, 'resources')
 | 
				
			||||||
@ -133,8 +138,8 @@ class AnteoLoader:
 | 
				
			|||||||
            keep_incomplete = True
 | 
					            keep_incomplete = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
 | 
					        dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
 | 
				
			||||||
        user_agent = ''
 | 
					        user_agent = 'uTorrent/2200(24683)'
 | 
				
			||||||
        self.engine = Engine(uri=file_url(localize_path(self.torrentFile)), download_path=self.storageDirectory,
 | 
					        self.engine = Engine(uri=file_url(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,
 | 
				
			||||||
@ -148,8 +153,8 @@ class AnteoLoader:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def getContentList(self):
 | 
					    def getContentList(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            from SkorbaLoader import SkorbaLoader
 | 
					            from Libtorrent import Libtorrent
 | 
				
			||||||
            torrent = SkorbaLoader(self.storageDirectory, self.torrentFile)
 | 
					            torrent = Libtorrent(self.storageDirectory, self.torrentFile)
 | 
				
			||||||
            return torrent.getContentList()
 | 
					            return torrent.getContentList()
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            import traceback
 | 
					            import traceback
 | 
				
			||||||
@ -160,7 +165,7 @@ class AnteoLoader:
 | 
				
			|||||||
        self.setup_engine()
 | 
					        self.setup_engine()
 | 
				
			||||||
        files = []
 | 
					        files = []
 | 
				
			||||||
        filelist = []
 | 
					        filelist = []
 | 
				
			||||||
        with closing(self.engine):
 | 
					        try:
 | 
				
			||||||
            self.engine.start()
 | 
					            self.engine.start()
 | 
				
			||||||
            #media_types=[MediaType.VIDEO, MediaType.AUDIO, MediaType.SUBTITLES, MediaType.UNKNOWN]
 | 
					            #media_types=[MediaType.VIDEO, MediaType.AUDIO, MediaType.SUBTITLES, MediaType.UNKNOWN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -187,6 +192,11 @@ class AnteoLoader:
 | 
				
			|||||||
                stringdata = {"title": ensure_str(fs.name), "size": fs.size, "ind": fs.index,
 | 
					                stringdata = {"title": ensure_str(fs.name), "size": fs.size, "ind": fs.index,
 | 
				
			||||||
                              'offset': fs.offset}
 | 
					                              'offset': fs.offset}
 | 
				
			||||||
                filelist.append(stringdata)
 | 
					                filelist.append(stringdata)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            import traceback
 | 
				
			||||||
 | 
					            log(traceback.format_exc())
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            self.engine.close()
 | 
				
			||||||
        return filelist
 | 
					        return filelist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def saveTorrent(self, torrentUrl):
 | 
					    def saveTorrent(self, torrentUrl):
 | 
				
			||||||
@ -200,12 +210,19 @@ 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("^[htps]+?://.+$|^://.+$", torrentUrl):
 | 
					                if not re.match("^http\:.+$", torrentUrl):
 | 
				
			||||||
                    log('xbmcvfs.File for %s' % torrentUrl)
 | 
					 | 
				
			||||||
                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
					                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    log('request for %s' % torrentUrl)
 | 
					                    request = urllib2.Request(torrentUrl)
 | 
				
			||||||
                    content = self.makeRequest(torrentUrl)
 | 
					                    request.add_header('Referer', 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)
 | 
				
			||||||
@ -222,29 +239,6 @@ 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:
 | 
				
			||||||
@ -255,13 +249,13 @@ class AnteoLoader:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def magnetToTorrent(self, magnet):
 | 
					    def magnetToTorrent(self, magnet):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            from SkorbaLoader import SkorbaLoader
 | 
					            from Libtorrent import Libtorrent
 | 
				
			||||||
            torrent = SkorbaLoader(self.storageDirectory, magnet)
 | 
					            torrent = Libtorrent(self.storageDirectory, magnet)
 | 
				
			||||||
            torrent.magnetToTorrent(magnet)
 | 
					            torrent.magnetToTorrent(magnet)
 | 
				
			||||||
            self.torrentFile = torrent.torrentFile
 | 
					            self.torrentFile = torrent.torrentFile
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            self.torrentFile = magnet
 | 
					            self.torrentFile = magnet
 | 
				
			||||||
        log('[AnteoLoader][magnetToTorrent]: self.torrentFile '+ensure_str(self.torrentFile))
 | 
					        log('['+author+'Loader][magnetToTorrent]: self.torrentFile '+str(self.torrentFile))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AnteoPlayer(xbmc.Player):
 | 
					class AnteoPlayer(xbmc.Player):
 | 
				
			||||||
    __plugin__ = sys.modules["__main__"].__plugin__
 | 
					    __plugin__ = sys.modules["__main__"].__plugin__
 | 
				
			||||||
@ -285,12 +279,6 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
    def __init__(self, userStorageDirectory, torrentUrl, params={}):
 | 
					    def __init__(self, userStorageDirectory, torrentUrl, params={}):
 | 
				
			||||||
        self.userStorageDirectory = userStorageDirectory
 | 
					        self.userStorageDirectory = userStorageDirectory
 | 
				
			||||||
        self.torrentUrl = torrentUrl
 | 
					        self.torrentUrl = torrentUrl
 | 
				
			||||||
        if not is_writable(self.userStorageDirectory):
 | 
					 | 
				
			||||||
            xbmcgui.Dialog().ok(Localization.localize('Torrenter v2'),
 | 
					 | 
				
			||||||
                    Localization.localize('Your storage path is not writable or not local! Please change it in settings!'),
 | 
					 | 
				
			||||||
                    self.storageDirectory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            sys.exit(1)
 | 
					 | 
				
			||||||
        xbmc.Player.__init__(self)
 | 
					        xbmc.Player.__init__(self)
 | 
				
			||||||
        log("["+author+"Player] Initalized v"+__version__)
 | 
					        log("["+author+"Player] Initalized v"+__version__)
 | 
				
			||||||
        self.params = params
 | 
					        self.params = params
 | 
				
			||||||
@ -298,51 +286,52 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
        self.contentId = int(self.get("url"))
 | 
					        self.contentId = int(self.get("url"))
 | 
				
			||||||
        if self.get("seek"):
 | 
					        if self.get("seek"):
 | 
				
			||||||
            self.seek = int(self.get("seek"))
 | 
					            self.seek = int(self.get("seek"))
 | 
				
			||||||
        #self.torrent = AnteoLoader(self.userStorageDirectory, self.torrentUrl, self.torrentFilesDirectory)
 | 
					 | 
				
			||||||
        self.init()
 | 
					        self.init()
 | 
				
			||||||
        self.setup_engine()
 | 
					        self.setup_engine()
 | 
				
			||||||
        with closing(self.engine):
 | 
					        try:
 | 
				
			||||||
            self.engine.start(self.contentId)
 | 
					            self.engine.start(self.contentId)
 | 
				
			||||||
            self.setup_nextep()
 | 
					            self.setup_nextep()
 | 
				
			||||||
            while True:
 | 
					            while True:
 | 
				
			||||||
                if self.buffer():
 | 
					                if self.buffer():
 | 
				
			||||||
                    log('[AnteoPlayer]: ************************************* 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, self.torrentUrl, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
 | 
					                        WatchedHistoryDB().add(self.basename, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        log('[AnteoPlayer]: ************************************* break')
 | 
					                        log('['+author+'Player]: ************************************* break')
 | 
				
			||||||
                        break
 | 
					                        break
 | 
				
			||||||
                    log('[AnteoPlayer]: ************************************* GO NEXT?')
 | 
					                    log('['+author+'Player]: ************************************* GO NEXT?')
 | 
				
			||||||
                    if self.next_dl and self.next_contentId != False and isinstance(self.next_contentId, int) and self.iterator == 100:
 | 
					                    if self.next_dl and self.next_contentId != False and isinstance(self.next_contentId, int) and self.iterator == 100:
 | 
				
			||||||
                        if not self.next_play:
 | 
					                        if not self.next_play:
 | 
				
			||||||
                            xbmc.sleep(3000)
 | 
					                            xbmc.sleep(3000)
 | 
				
			||||||
                            if not xbmcgui.Dialog().yesno(
 | 
					                            if not xbmcgui.Dialog().yesno(
 | 
				
			||||||
                                self.localize('[%sPlayer v%s] ' % (author, __version__)),
 | 
					                                self.localize('Torrent2HTTP'),
 | 
				
			||||||
                                self.localize('Would you like to play next episode?')):
 | 
					                                self.localize('Would you like to play next episode?')):
 | 
				
			||||||
                                break
 | 
					                                break
 | 
				
			||||||
                        self.contentId = self.next_contentId
 | 
					                        self.contentId = self.next_contentId
 | 
				
			||||||
                        continue
 | 
					                        continue
 | 
				
			||||||
 | 
					                    log('['+author+'Player]: ************************************* NO! break')
 | 
				
			||||||
                    log('[AnteoPlayer]: ************************************* NO! break')
 | 
					 | 
				
			||||||
                    showMessage(self.localize('Information'),
 | 
					 | 
				
			||||||
                                self.localize('Stopping the torrent2http process...'))
 | 
					 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            import traceback
 | 
				
			||||||
 | 
					            log(traceback.format_exc())
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            self.engine.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        xbmc.Player().stop()
 | 
					        xbmc.Player().stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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:
 | 
				
			||||||
        showMessage(self.localize('Information'),
 | 
					            #if self.seeding_status:
 | 
				
			||||||
                    self.localize('torrent2http process stopped.'))
 | 
					            #showMessage(self.localize('Information'),
 | 
				
			||||||
 | 
					            #            self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
 | 
				
			||||||
        loadsw_onstop()  # Reload Search Window
 | 
					            #else:
 | 
				
			||||||
 | 
					            #if self.seeding: self.db_delete()
 | 
				
			||||||
 | 
					            showMessage(self.localize('Information'),
 | 
				
			||||||
 | 
					                        self.localize('Torrent downloading is stopped.'), forced=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init(self):
 | 
					    def init(self):
 | 
				
			||||||
        self.next_contentId = False
 | 
					        self.next_contentId = False
 | 
				
			||||||
@ -356,6 +345,16 @@ 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(
 | 
				
			||||||
@ -384,22 +383,28 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
            keep_files = True
 | 
					            keep_files = True
 | 
				
			||||||
            resume_file=os.path.join(self.userStorageDirectory, 'torrents', os.path.basename(self.torrentUrl)+'.resume_data')
 | 
					            resume_file=os.path.join(self.userStorageDirectory, 'torrents', os.path.basename(self.torrentUrl)+'.resume_data')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enable_dht = self.__settings__.getSetting("enable_dht") == 'true'
 | 
					 | 
				
			||||||
        dht_routers = ["router.bittorrent.com:6881","router.utorrent.com:6881"]
 | 
					        dht_routers = ["router.bittorrent.com:6881","router.utorrent.com:6881"]
 | 
				
			||||||
        user_agent = ''
 | 
					        user_agent = 'uTorrent/2200(24683)'
 | 
				
			||||||
        self.pre_buffer_bytes = int(self.__settings__.getSetting("pre_buffer_bytes"))*1024*1024
 | 
					        self.pre_buffer_bytes = int(self.__settings__.getSetting("pre_buffer_bytes"))*1024*1024
 | 
				
			||||||
 | 
					        showMessage('[%sPlayer v%s] ' % (author, __version__), self.localize('Please Wait'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.engine = Engine(uri=file_url(self.torrentUrl), download_path=self.userStorageDirectory,
 | 
					        self.engine = Engine(uri=file_url(self.torrentUrl), download_path=self.userStorageDirectory,
 | 
				
			||||||
                             connections_limit=connections_limit, download_kbps=download_limit, upload_kbps=upload_limit,
 | 
					                             connections_limit=connections_limit, download_kbps=download_limit, upload_kbps=upload_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,
 | 
				
			||||||
                             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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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)
 | 
				
			||||||
@ -465,7 +470,7 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.next_dl = False
 | 
					            self.next_dl = False
 | 
				
			||||||
        self.next_play = self.__settings__.getSetting('next_play') == 'true'
 | 
					        self.next_play = self.__settings__.getSetting('next_play') == 'true'
 | 
				
			||||||
        log('[AnteoPlayer]: next_dl - %s, next_play - %s, ids_video - %s' % (str(self.next_dl), str(self.next_play), str(self.ids_video)))
 | 
					        log('['+author+'Player]: next_dl - %s, next_play - %s, ids_video - %s' % (str(self.next_dl), str(self.next_play), str(self.ids_video)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setup_play(self):
 | 
					    def setup_play(self):
 | 
				
			||||||
        file_status = self.engine.file_status(self.contentId)
 | 
					        file_status = self.engine.file_status(self.contentId)
 | 
				
			||||||
@ -484,7 +489,7 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
                self.next_contentId = int(self.ids_video[next_contentId_index])
 | 
					                self.next_contentId = int(self.ids_video[next_contentId_index])
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.next_contentId = False
 | 
					                self.next_contentId = False
 | 
				
			||||||
            log('[AnteoPlayer][setup_play]: next_contentId: '+str(self.next_contentId))
 | 
					            log('['+author+'Player][setup_play]: next_contentId: '+str(self.next_contentId))
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            seasonId = self.get("seasonId")
 | 
					            seasonId = self.get("seasonId")
 | 
				
			||||||
            self.episodeId = self.get("episodeId") if not self.episodeId else int(self.episodeId) + 1
 | 
					            self.episodeId = self.get("episodeId") if not self.episodeId else int(self.episodeId) + 1
 | 
				
			||||||
@ -504,17 +509,13 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
                                                           'season': int(seasonId),
 | 
					                                                           'season': int(seasonId),
 | 
				
			||||||
                                                           'tvshowtitle': title})
 | 
					                                                           'tvshowtitle': title})
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            log('[AnteoPlayer]: Operation INFO failed!')
 | 
					            log('['+author+'Player]: Operation INFO failed!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        thumbnail = self.get("thumbnail")
 | 
					        thumbnail = self.get("thumbnail")
 | 
				
			||||||
        if thumbnail:
 | 
					        if thumbnail:
 | 
				
			||||||
            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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -524,12 +525,12 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
            xbmc.sleep(200)
 | 
					            xbmc.sleep(200)
 | 
				
			||||||
            i += 1
 | 
					            i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log('[AnteoPlayer]: self.isPlaying() = %s, i = %d, xbmc.abortRequested - %s' % (str(self.isPlaying()), i, str(xbmc.abortRequested)))
 | 
					        log('['+author+'Player]: self.isPlaying() = %s, i = %d, xbmc.abortRequested - %s' % (str(self.isPlaying()), i, str(xbmc.abortRequested)))
 | 
				
			||||||
        if not self.isPlaying() or xbmc.abortRequested:
 | 
					        if not self.isPlaying() or xbmc.abortRequested:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.seek > 0:
 | 
					        if self.seek > 0:
 | 
				
			||||||
            log('[AnteoPlayer]: seekTime - '+str(self.seek))
 | 
					            log('['+author+'Player]: seekTime - '+str(self.seek))
 | 
				
			||||||
            self.seekTime(self.seek)
 | 
					            self.seekTime(self.seek)
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -543,7 +544,7 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
                if isSubtitle(filename, i.name):
 | 
					                if isSubtitle(filename, i.name):
 | 
				
			||||||
                    subs.append(i)
 | 
					                    subs.append(i)
 | 
				
			||||||
            if subs:
 | 
					            if subs:
 | 
				
			||||||
                log("[AnteoPlayer][setup_subs]: Detected subtitles: %s" % str(subs))
 | 
					                log("["+author+"Player][setup_subs]: Detected subtitles: %s" % str(subs))
 | 
				
			||||||
                for sub in subs:
 | 
					                for sub in subs:
 | 
				
			||||||
                    xbmc.Player().setSubtitles(sub.url)
 | 
					                    xbmc.Player().setSubtitles(sub.url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -559,10 +560,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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -573,9 +574,14 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
                    if pause and self.__settings__.getSetting("pause_onplay") == 'true':
 | 
					                    if pause and self.__settings__.getSetting("pause_onplay") == 'true':
 | 
				
			||||||
                        pause = False
 | 
					                        pause = False
 | 
				
			||||||
                        xbmc.Player().pause()
 | 
					                        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()
 | 
				
			||||||
@ -606,10 +612,10 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def _get_status_lines(self, s, f):
 | 
					    def _get_status_lines(self, s, f):
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            ensure_str(self.display_name),
 | 
					            localize_path(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]).decode('utf-8')),
 | 
				
			||||||
            "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').decode('utf-8'),
 | 
				
			||||||
                                             s.upload_rate, self.localize('kb/s'),
 | 
					                                             s.upload_rate, self.localize('kb/s').decode('utf-8'),
 | 
				
			||||||
                                             s.num_seeds, s.num_peers)
 | 
					                                             s.num_seeds, s.num_peers)
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -631,7 +637,7 @@ class AnteoPlayer(xbmc.Player):
 | 
				
			|||||||
        if not status:
 | 
					        if not status:
 | 
				
			||||||
            status = self.engine.status()
 | 
					            status = self.engine.status()
 | 
				
			||||||
        self.engine.check_torrent_error(status)
 | 
					        self.engine.check_torrent_error(status)
 | 
				
			||||||
        log('[AnteoPlayer]: %.2f%% complete (down: %.1f kb/s up: %.1f kb/s peers: %d) %s' % \
 | 
					        log('['+author+'Player]: %.2f%% complete (down: %.1f kb/s up: %.1f kb/s peers: %d) %s' % \
 | 
				
			||||||
              (status.progress * 100, status.download_rate,
 | 
					              (status.progress * 100, status.download_rate,
 | 
				
			||||||
               status.upload_rate, status.num_peers, status.state_str))
 | 
					               status.upload_rate, status.num_peers, status.state_str))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -668,8 +674,7 @@ class OverlayText(object):
 | 
				
			|||||||
        self._shown = False
 | 
					        self._shown = False
 | 
				
			||||||
        self._text = ""
 | 
					        self._text = ""
 | 
				
			||||||
        self._label = xbmcgui.ControlLabel(x, y, w, h, self._text, *args, **kwargs)
 | 
					        self._label = xbmcgui.ControlLabel(x, y, w, h, self._text, *args, **kwargs)
 | 
				
			||||||
        filename = os.path.join(RESOURCES_PATH, "images", "black.png")
 | 
					        self._background = xbmcgui.ControlImage(x, y, w, h, os.path.join(RESOURCES_PATH, "images", "black.png"))
 | 
				
			||||||
        self._background = xbmcgui.ControlImage(x, y, w, h, filename)
 | 
					 | 
				
			||||||
        self._background.setColorDiffuse("0xD0000000")
 | 
					        self._background.setColorDiffuse("0xD0000000")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def show(self):
 | 
					    def show(self):
 | 
				
			||||||
@ -703,10 +708,5 @@ class OverlayText(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        skin_path = xbmc.translatePath("special://skin/")
 | 
					        skin_path = xbmc.translatePath("special://skin/")
 | 
				
			||||||
        tree = ET.parse(os.path.join(skin_path, "addon.xml"))
 | 
					        tree = ET.parse(os.path.join(skin_path, "addon.xml"))
 | 
				
			||||||
        res = None
 | 
					        res = tree.findall("./extension/res")[0]
 | 
				
			||||||
        for element in tree.findall("./extension/res"):
 | 
					 | 
				
			||||||
            if element.attrib["default"] == 'true':
 | 
					 | 
				
			||||||
                res = element
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
        if res is None: res = tree.findall("./extension/res")[0]
 | 
					 | 
				
			||||||
        return int(res.attrib["width"]), int(res.attrib["height"])
 | 
					        return int(res.attrib["width"]), int(res.attrib["height"])
 | 
				
			||||||
							
								
								
									
										29
									
								
								Content.py
									
									
									
									
									
								
							
							
						
						@ -19,15 +19,6 @@
 | 
				
			|||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import abc
 | 
					import abc
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
proxy = int(sys.modules["__main__"].__settings__.getSetting("cl_proxy"))
 | 
					 | 
				
			||||||
if proxy == 1:
 | 
					 | 
				
			||||||
    socks_ip = sys.modules["__main__"].__settings__.getSetting("socks_ip")
 | 
					 | 
				
			||||||
    import socket
 | 
					 | 
				
			||||||
    from resources.proxy import socks
 | 
					 | 
				
			||||||
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, socks_ip,
 | 
					 | 
				
			||||||
                          int(sys.modules["__main__"].__settings__.getSetting("socks_port")))
 | 
					 | 
				
			||||||
    socket.socket = socks.socksocket
 | 
					 | 
				
			||||||
import urllib
 | 
					import urllib
 | 
				
			||||||
import urllib2
 | 
					import urllib2
 | 
				
			||||||
import cookielib
 | 
					import cookielib
 | 
				
			||||||
@ -35,8 +26,6 @@ import re
 | 
				
			|||||||
from StringIO import StringIO
 | 
					from StringIO import StringIO
 | 
				
			||||||
import gzip
 | 
					import gzip
 | 
				
			||||||
import HTMLParser
 | 
					import HTMLParser
 | 
				
			||||||
import ssl
 | 
					 | 
				
			||||||
from datetime import date
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Localization
 | 
					import Localization
 | 
				
			||||||
from functions import log, debug
 | 
					from functions import log, debug
 | 
				
			||||||
@ -97,11 +86,10 @@ class Content:
 | 
				
			|||||||
                  'horror': ('Horror',),
 | 
					                  'horror': ('Horror',),
 | 
				
			||||||
                  'romance': ('Romance',),
 | 
					                  'romance': ('Romance',),
 | 
				
			||||||
                  'thriller': ('Thriller',),
 | 
					                  'thriller': ('Thriller',),
 | 
				
			||||||
                  'sci_fi': ('Sci-Fi',),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for y in range(date.today().year, 1970, -1):
 | 
					    for y in range(2015, 1970, -1):
 | 
				
			||||||
        category_dict['year'][str(y)] = (str(y), '/top/y/%s/' % str(y))
 | 
					        category_dict['year'][str(y)] = (str(y), '/top/y/%s/' % str(y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_contentList(self, category, subcategory=None, apps_property=None):
 | 
					    def get_contentList(self, category, subcategory=None, apps_property=None):
 | 
				
			||||||
@ -142,8 +130,7 @@ class Content:
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            get = self.category_dict[category][subcategory]
 | 
					            get = self.category_dict[category][subcategory]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if category == 'search' and subcategory != True:
 | 
					        if category == 'search': get = (get[0], get[1] % urllib.quote_plus(subcategory.encode('utf-8')))
 | 
				
			||||||
            get = (get[0], get[1] % urllib.quote_plus(subcategory.encode('utf-8')))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        property = self.get_property(category, subcategory)
 | 
					        property = self.get_property(category, subcategory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -184,20 +171,14 @@ class Content:
 | 
				
			|||||||
                        except:
 | 
					                        except:
 | 
				
			||||||
                            pass
 | 
					                            pass
 | 
				
			||||||
        if has_property:
 | 
					        if has_property:
 | 
				
			||||||
            if category == 'search' and subcategory != True:
 | 
					            if category == 'search': property['page'] = property['page'] % urllib.quote_plus(
 | 
				
			||||||
                property['page'] = property['page'] % urllib.quote_plus(subcategory.encode('utf-8'))
 | 
					                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)
 | 
				
			||||||
@ -229,7 +210,6 @@ class Content:
 | 
				
			|||||||
        ('>', '>'),
 | 
					        ('>', '>'),
 | 
				
			||||||
        ('"', '"'),
 | 
					        ('"', '"'),
 | 
				
			||||||
        ("'", '''),
 | 
					        ("'", '''),
 | 
				
			||||||
        ("'", '''),
 | 
					 | 
				
			||||||
        (' ', ' ',),
 | 
					        (' ', ' ',),
 | 
				
			||||||
        ('"', '«', ),
 | 
					        ('"', '«', ),
 | 
				
			||||||
        ('"', '»', ),
 | 
					        ('"', '»', ),
 | 
				
			||||||
@ -237,7 +217,6 @@ class Content:
 | 
				
			|||||||
        ('e', 'é',),
 | 
					        ('e', 'é',),
 | 
				
			||||||
        ('e', 'è',),
 | 
					        ('e', 'è',),
 | 
				
			||||||
        ('&', '&',),
 | 
					        ('&', '&',),
 | 
				
			||||||
        ('&', '&',),
 | 
					 | 
				
			||||||
        ('u', 'ù',),
 | 
					        ('u', 'ù',),
 | 
				
			||||||
        ('u', 'ú',),
 | 
					        ('u', 'ú',),
 | 
				
			||||||
        ('o', 'ô',),
 | 
					        ('o', 'ô',),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										479
									
								
								Core.py
									
									
									
									
									
								
							
							
						
						@ -18,6 +18,8 @@
 | 
				
			|||||||
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Downloader
 | 
					import Downloader
 | 
				
			||||||
import xbmc
 | 
					import xbmc
 | 
				
			||||||
import xbmcaddon
 | 
					import xbmcaddon
 | 
				
			||||||
@ -30,16 +32,14 @@ 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(xbmc.translatePath(__settings__.getSetting("storage")))#file_encode(__settings__.getSetting("storage"))
 | 
					    userStorageDirectory = localize_path(__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', 4: 'hu'}.get(int(__settings__.getSetting("language")))
 | 
					    language = {0: 'en', 1: 'ru', 2: 'uk', 3: 'he'}.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))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,11 +54,7 @@ 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_260()
 | 
					            first_run_250()
 | 
				
			||||||
            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()
 | 
				
			||||||
@ -70,100 +66,49 @@ 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'))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #Search Window
 | 
					        if self.history_bool:
 | 
				
			||||||
        if self.searchwindowmode < 3:
 | 
					            HistorycontextMenu=[]
 | 
				
			||||||
            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'),
 | 
					                (self.localize('Clear %s') % self.localize('Search History'), ListString % ('History', 'clear', 'addtime', '')))
 | 
				
			||||||
                 ListString % ('History', 'clear', 'addtime', '')))
 | 
					            self.drawItem('< %s >' % self.localize('Search History'), 'History',
 | 
				
			||||||
            if self.searchwindowmode == 1:
 | 
					                          image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
 | 
				
			||||||
                self.drawItem('< %s >' % self.localize('Search History'), 'swHistory',
 | 
					        self.drawItem('< %s >' % self.localize('Search'), 'search', image=self.ROOT + '/icons/search.png', )
 | 
				
			||||||
                              image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.drawItem('< %s >' % self.localize('Search History'), 'History',
 | 
					 | 
				
			||||||
                              image=self.ROOT + '/icons/history2.png', contextMenu=HistorycontextMenu, replaceMenu=False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Search
 | 
					 | 
				
			||||||
        if self.searchwindowmode == 1:
 | 
					 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Search'), 'swsearch', image=self.ROOT + '/icons/search.png',)
 | 
					 | 
				
			||||||
        elif self.searchwindowmode > 1:
 | 
					 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Search'), 'search', image=self.ROOT + '/icons/search.png', )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Media
 | 
					 | 
				
			||||||
        CLcontextMenu=[]
 | 
					        CLcontextMenu=[]
 | 
				
			||||||
        CLcontextMenu.extend(contextMenu)
 | 
					        CLcontextMenu.extend(contextMenu)
 | 
				
			||||||
        CLcontextMenu.append((self.localize('Reset All Cache DBs'),
 | 
					        CLcontextMenu.append((self.localize('Reset All Cache DBs'),
 | 
				
			||||||
                            ListString % ('full_download', '', 'url', json.dumps({'action': 'delete'}))))
 | 
					                            ListString % ('full_download', '', 'url', json.dumps({'action': 'delete'}))))
 | 
				
			||||||
        self.drawItem('< %s >' % self.localize('Content Lists'), 'openContent', image=self.ROOT + '/icons/media.png',
 | 
					        self.drawItem('< %s >' % self.localize('Content Lists'), 'openContent', image=self.ROOT + '/icons/media.png',
 | 
				
			||||||
                      contextMenu=CLcontextMenu, replaceMenu=False)
 | 
					                      contextMenu=CLcontextMenu, replaceMenu=False)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        #DL Status
 | 
					 | 
				
			||||||
        DLScontextMenu=[(self.localize('Start All'), ListString % ('DownloadStatus', 'startall', 'addtime', '')),
 | 
					        DLScontextMenu=[(self.localize('Start All'), ListString % ('DownloadStatus', 'startall', 'addtime', '')),
 | 
				
			||||||
                        (self.localize('Stop All'), ListString % ('DownloadStatus', 'stopall', 'addtime', '')),]
 | 
					                        (self.localize('Stop All'), ListString % ('DownloadStatus', 'stopall', 'addtime', '')),]
 | 
				
			||||||
        DLScontextMenu.append(
 | 
					        DLScontextMenu.append(
 | 
				
			||||||
                (self.localize('Clear %s') % self.localize('Download Status'), ListString % ('DownloadStatus', 'clear', 'addtime', '')))
 | 
					                (self.localize('Clear %s') % self.localize('Download Status'), ListString % ('DownloadStatus', 'clear', 'addtime', '')))
 | 
				
			||||||
        DLScontextMenu.extend(contextMenu)
 | 
					        DLScontextMenu.extend(contextMenu)
 | 
				
			||||||
 | 
					        self.drawItem('< %s >' % self.localize('Download Status'), 'DownloadStatus', image=self.ROOT + '/icons/download.png',
 | 
				
			||||||
        if self.searchwindowmode == 1:
 | 
					                      contextMenu=DLScontextMenu, replaceMenu=False)
 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Download Status'), 'swDownloadStatus',
 | 
					        self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'uTorrentBrowser',
 | 
				
			||||||
                          image=self.ROOT + '/icons/download.png',
 | 
					                      image=self.ROOT + '/icons/' + self.getTorrentClientIcon())
 | 
				
			||||||
                          contextMenu=DLScontextMenu, replaceMenu=False)
 | 
					        if self.history_bool:
 | 
				
			||||||
        elif self.searchwindowmode > 1:
 | 
					 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Download Status'), 'DownloadStatus',
 | 
					 | 
				
			||||||
                          image=self.ROOT + '/icons/download.png',
 | 
					 | 
				
			||||||
                          contextMenu=DLScontextMenu, replaceMenu=False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Torrent-client
 | 
					 | 
				
			||||||
        if self.searchwindowmode == 1:
 | 
					 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'swuTorrentBrowser',
 | 
					 | 
				
			||||||
                          image=self.ROOT + '/icons/' + getTorrentClientIcon())
 | 
					 | 
				
			||||||
        elif self.searchwindowmode > 1:
 | 
					 | 
				
			||||||
            self.drawItem('< %s >' % self.localize('Torrent-client Browser'), 'uTorrentBrowser',
 | 
					 | 
				
			||||||
                          image=self.ROOT + '/icons/' + getTorrentClientIcon())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Watched
 | 
					 | 
				
			||||||
        if self.history_bool and self.searchwindowmode > 0:
 | 
					 | 
				
			||||||
            WatchedHistorycontextMenu=[]
 | 
					            WatchedHistorycontextMenu=[]
 | 
				
			||||||
            WatchedHistorycontextMenu.extend(contextMenu)
 | 
					            WatchedHistorycontextMenu.extend(contextMenu)
 | 
				
			||||||
            WatchedHistorycontextMenu.append(
 | 
					            WatchedHistorycontextMenu.append(
 | 
				
			||||||
                (self.localize('Clear %s') % self.localize('Watched History'), ListString % ('WatchedHistory', 'clear', 'addtime', '')))
 | 
					                (self.localize('Clear %s') % self.localize('Watched History'), ListString % ('WatchedHistory', 'clear', 'addtime', '')))
 | 
				
			||||||
            if self.searchwindowmode == 1:
 | 
					            self.drawItem('< %s >' % self.localize('Watched History'), 'WatchedHistory',
 | 
				
			||||||
                self.drawItem('< %s >' % self.localize('Watched History'), 'swWatchedHistory',
 | 
					                      image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu, replaceMenu=False)
 | 
				
			||||||
                              image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu,
 | 
					 | 
				
			||||||
                              replaceMenu=False)
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.drawItem('< %s >' % self.localize('Watched History'), 'WatchedHistory',
 | 
					 | 
				
			||||||
                      image=self.ROOT + '/icons/watched.png', contextMenu=WatchedHistorycontextMenu,
 | 
					 | 
				
			||||||
                              replaceMenu=False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #Torr player
 | 
					 | 
				
			||||||
        self.drawItem('< %s >' % self.localize('.torrent Player'), 'torrentPlayer',
 | 
					        self.drawItem('< %s >' % self.localize('.torrent Player'), 'torrentPlayer',
 | 
				
			||||||
                      image=self.ROOT + '/icons/torrentPlayer.png', isFolder = False)
 | 
					                      image=self.ROOT + '/icons/torrentPlayer.png')
 | 
				
			||||||
 | 
					 | 
				
			||||||
        #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', isFolder = False)
 | 
					                      image=self.ROOT + '/icons/magnet.png')
 | 
				
			||||||
 | 
					 | 
				
			||||||
        #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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -296,50 +241,54 @@ class Core:
 | 
				
			|||||||
        lockView('wide')
 | 
					        lockView('wide')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test(self, params={}):
 | 
					    def test(self, params={}):
 | 
				
			||||||
        pass
 | 
					        #from Anteoloader import AnteoPlayer
 | 
				
			||||||
        xbmc.Player().play('D:\\filmz\\The Missing (2014).mp4')
 | 
					        #from python_libtorrent import get_libtorrent
 | 
				
			||||||
        from Anteoloader import OverlayText, OVERLAY_WIDTH, OVERLAY_HEIGHT, XBFONT_CENTER_X,XBFONT_CENTER_Y
 | 
					        #self.lt=get_libtorrent()
 | 
				
			||||||
        overlay = OverlayText(w=OVERLAY_WIDTH, h=OVERLAY_HEIGHT,
 | 
					        #self.torrentFile='D:\\test.torrent'
 | 
				
			||||||
                    alignment=XBFONT_CENTER_X | XBFONT_CENTER_Y)
 | 
					        #self.session = self.lt.session()
 | 
				
			||||||
        overlay.show()
 | 
					        #e=self.lt.bdecode(xbmcvfs.File(self.torrentFile,'rb').read())
 | 
				
			||||||
        overlay.text = 'XXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXXXXXXXXXXXXXXXXXX\r\n' \
 | 
					        #self.torrentFileInfo = self.lt.torrent_info(e)
 | 
				
			||||||
                       'YYyyyYyYYyYyY'
 | 
					        #torrent_info={'ti': self.torrentFileInfo,
 | 
				
			||||||
        time.sleep(5)
 | 
					        #      'save_path': self.userStorageDirectory,
 | 
				
			||||||
        overlay.hide()
 | 
					        #      'flags': 0x300,
 | 
				
			||||||
        time.sleep(1)
 | 
					        #       #'storage_mode': self.lt.storage_mode_t(1),
 | 
				
			||||||
        xbmc.Player().stop()
 | 
					        #       '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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def swHistory(self, params={}):
 | 
					        #params['url']='0'
 | 
				
			||||||
        import searchwindow
 | 
					        #if not xbmcvfs.exists(torrentUrl):
 | 
				
			||||||
        params = {'mode': 'history'}
 | 
					        #    action = xbmcgui.Dialog()
 | 
				
			||||||
        searchwindow.main(params)
 | 
					        #    torrentUrl = action.browse(1, self.localize('Choose .torrent in video library'), 'video', '.torrent')
 | 
				
			||||||
 | 
					        #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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def swDownloadStatus(self, params={}):
 | 
					        #xbmcgui.Dialog().ok('Dam Son!','Now send this shit to DiMartino')
 | 
				
			||||||
        import searchwindow
 | 
					        from resources.proxy import antizapret
 | 
				
			||||||
        params = {'mode': 'downloadstatus'}
 | 
					        filename = os.path.join(tempdir(),"antizapret.pac_config")
 | 
				
			||||||
        searchwindow.main(params)
 | 
					        import shelve
 | 
				
			||||||
 | 
					        from contextlib import contextmanager, closing
 | 
				
			||||||
    def swuTorrentBrowser(self, params={}):
 | 
					        with closing(shelve.open(filename, writeback=True)) as d:
 | 
				
			||||||
        import searchwindow
 | 
					            import time
 | 
				
			||||||
        params = {'mode': 'browser'}
 | 
					            log(str(d))
 | 
				
			||||||
        searchwindow.main(params)
 | 
					            log(str(time.time()))
 | 
				
			||||||
 | 
					            log(str((time.time() - d["created_at"])))
 | 
				
			||||||
    def swWatchedHistory(self, params={}):
 | 
					            ttl = 24*3600
 | 
				
			||||||
        import searchwindow
 | 
					            if ttl > 0 and (time.time() - d["created_at"]) > ttl:
 | 
				
			||||||
        params = {'mode': 'watched'}
 | 
					                log('xxx')
 | 
				
			||||||
        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()
 | 
				
			||||||
@ -472,6 +421,8 @@ 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={}):
 | 
				
			||||||
@ -572,7 +523,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.encode('utf-8')))
 | 
					            % ('torrentPlayer', path))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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))
 | 
				
			||||||
@ -602,7 +553,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 if length else 1)) * 100)
 | 
					                    watchedPercent = int((float(seek) / float(length)) * 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))
 | 
				
			||||||
@ -776,19 +727,6 @@ 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:
 | 
				
			||||||
@ -804,7 +742,6 @@ 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'):
 | 
				
			||||||
@ -960,7 +897,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)
 | 
				
			||||||
                log('meta:'+str(meta))
 | 
					                #print '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'):
 | 
				
			||||||
@ -974,7 +911,7 @@ class Core:
 | 
				
			|||||||
                        kinometa = self.Scraper.scraper(scraper, {'label': title, 'search': search,
 | 
					                        kinometa = self.Scraper.scraper(scraper, {'label': title, 'search': search,
 | 
				
			||||||
                                                                  'year': year}, self.language)
 | 
					                                                                  'year': year}, self.language)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        log('kinometa:'+str(kinometa))
 | 
					                        #print 'kinometa:'+str(kinometa)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        for section in kinometa.keys():
 | 
					                        for section in kinometa.keys():
 | 
				
			||||||
                            if isinstance(kinometa[section], dict):
 | 
					                            if isinstance(kinometa[section], dict):
 | 
				
			||||||
@ -1000,13 +937,7 @@ class Core:
 | 
				
			|||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        title = meta.get('info').get('title')
 | 
					                        title = meta.get('info').get('title')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            listitem = xbmcgui.ListItem(title)
 | 
					            listitem = xbmcgui.ListItem(title, iconImage=img, thumbnailImage=img)
 | 
				
			||||||
            images = {'thumb': img, #'icon': img,
 | 
					 | 
				
			||||||
                      'poster': img,# 'banner': img,
 | 
					 | 
				
			||||||
                      #'fanart': img, 'landscape': img,
 | 
					 | 
				
			||||||
                      # 'clearart': image, 'clearlogo': image,
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
            listitem.setArt(images)
 | 
					 | 
				
			||||||
            listitem.setInfo(type='Video', infoLabels=info)
 | 
					            listitem.setInfo(type='Video', infoLabels=info)
 | 
				
			||||||
            if meta:
 | 
					            if meta:
 | 
				
			||||||
                listitem=itemScrap(listitem, meta)
 | 
					                listitem=itemScrap(listitem, meta)
 | 
				
			||||||
@ -1056,7 +987,7 @@ class Core:
 | 
				
			|||||||
                title = title.encode('utf-8', 'ignore')
 | 
					                title = title.encode('utf-8', 'ignore')
 | 
				
			||||||
            except:
 | 
					            except:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            log(str(info))
 | 
					            label = info.get('label').encode('utf-8', 'ignore')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if info.get('link'):
 | 
					            if info.get('link'):
 | 
				
			||||||
                if isinstance(info.get('link'), tuple):
 | 
					                if isinstance(info.get('link'), tuple):
 | 
				
			||||||
@ -1093,6 +1024,28 @@ class Core:
 | 
				
			|||||||
                self.drawItem(title, 'downloadLibtorrent', link, image=img, info=info, contextMenu=contextMenu, replaceMenu=False)
 | 
					                self.drawItem(title, 'downloadLibtorrent', link, image=img, info=info, contextMenu=contextMenu, replaceMenu=False)
 | 
				
			||||||
            #self.drawItem(title, 'openTorrent', link, img, info=info, contextMenu=contextMenu, replaceMenu=False)
 | 
					            #self.drawItem(title, 'openTorrent', link, img, info=info, contextMenu=contextMenu, replaceMenu=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def ActionInfo(self, params={}):
 | 
				
			||||||
 | 
					        from resources.skins.DialogXml import DialogXml
 | 
				
			||||||
 | 
					        get = params.get
 | 
				
			||||||
 | 
					        contenter=get('provider')
 | 
				
			||||||
 | 
					        infolink=get('url')
 | 
				
			||||||
 | 
					        link=get('link')
 | 
				
			||||||
 | 
					        if ROOT + os.sep + 'resources' + os.sep + 'contenters' not in sys.path:
 | 
				
			||||||
 | 
					            sys.path.insert(0, ROOT + os.sep + 'resources' + os.sep + 'contenters')
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.Content = getattr(__import__(contenter), contenter)()
 | 
				
			||||||
 | 
					        except Exception, e:
 | 
				
			||||||
 | 
					            log('Unable to use contenter: ' + contenter + ' at ' + ' ActionInfo(). Exception: ' + str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        movieInfo=self.Content.get_info(infolink)
 | 
				
			||||||
 | 
					        if movieInfo:
 | 
				
			||||||
 | 
					            w = DialogXml("movieinfo.xml", ROOT, "Default")
 | 
				
			||||||
 | 
					            w.doModal(movieInfo, link)
 | 
				
			||||||
 | 
					            del w
 | 
				
			||||||
 | 
					            del movieInfo
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            showMessage(self.localize('Information'),self.localize('Information not found!'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def searchOption(self, params={}):
 | 
					    def searchOption(self, params={}):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            apps = json.loads(urllib.unquote_plus(params.get("url")))
 | 
					            apps = json.loads(urllib.unquote_plus(params.get("url")))
 | 
				
			||||||
@ -1150,30 +1103,8 @@ class Core:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def drawItem(self, title, action, link='', image='', isFolder=True, contextMenu=None, replaceMenu=True, action2='', fileSize=0L,
 | 
					    def drawItem(self, title, action, link='', image='', isFolder=True, contextMenu=None, replaceMenu=True, action2='', fileSize=0L,
 | 
				
			||||||
                 info={}):
 | 
					                 info={}):
 | 
				
			||||||
 | 
					        listitem = xbmcgui.ListItem(title, iconImage=image, thumbnailImage=image)
 | 
				
			||||||
        #log('[drawItem]:'+str((title, action, image, isFolder, contextMenu, replaceMenu, action2, info)))
 | 
					        #log('[drawItem]:'+str((title, action, image, isFolder, contextMenu, replaceMenu, action2, info)))
 | 
				
			||||||
        listitem = xbmcgui.ListItem(title)
 | 
					 | 
				
			||||||
        images = {'icon':image, 'thumb':image}
 | 
					 | 
				
			||||||
        images = {'icon': image, 'thumb': image,
 | 
					 | 
				
			||||||
                  'poster': image, 'banner': image,
 | 
					 | 
				
			||||||
                  #'fanart': image, 'landscape': image,
 | 
					 | 
				
			||||||
                  #'clearart': image, 'clearlogo': image,
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
        listitem.setArt(images)
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        setArt(values) -- Sets the listitem's art
 | 
					 | 
				
			||||||
         values : dictionary - pairs of { label: value }.
 | 
					 | 
				
			||||||
            - Some default art values (any string possible):
 | 
					 | 
				
			||||||
                - thumb : string - image filename
 | 
					 | 
				
			||||||
                - poster : string - image filename
 | 
					 | 
				
			||||||
                - banner : string - image filename
 | 
					 | 
				
			||||||
                - fanart : string - image filename
 | 
					 | 
				
			||||||
                - clearart : string - image filename
 | 
					 | 
				
			||||||
                - clearlogo : string - image filename
 | 
					 | 
				
			||||||
                - landscape : string - image filename
 | 
					 | 
				
			||||||
                - icon : string - image filename
 | 
					 | 
				
			||||||
        example:
 | 
					 | 
				
			||||||
                - self.list.getSelectedItem().setArt({ 'poster': 'poster.png', 'banner' : 'banner.png' })
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        if not info: info = {"Title": title, "plot": title}
 | 
					        if not info: info = {"Title": title, "plot": title}
 | 
				
			||||||
        if not isFolder and fileSize:
 | 
					        if not isFolder and fileSize:
 | 
				
			||||||
            info['size'] = fileSize
 | 
					            info['size'] = fileSize
 | 
				
			||||||
@ -1186,19 +1117,19 @@ class Core:
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            url = '%s?action=%s&url=%s' % (sys.argv[0], action, urllib.quote_plus(link))
 | 
					            url = '%s?action=%s&url=%s' % (sys.argv[0], action, urllib.quote_plus(link))
 | 
				
			||||||
        if action2:
 | 
					        if action2:
 | 
				
			||||||
            url = url + '&url2=%s' % urllib.quote_plus(ensure_str(action2))
 | 
					            url = url + '&url2=%s' % urllib.quote_plus(action2)
 | 
				
			||||||
        if not contextMenu:
 | 
					        if not contextMenu:
 | 
				
			||||||
            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):
 | 
				
			||||||
@ -1276,7 +1207,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(localize_path(folder), localize_path(tdir))
 | 
					                    path=os.path.join(folder, 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)'))
 | 
				
			||||||
@ -1291,10 +1222,9 @@ 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:
 | 
				
			||||||
                        file = localize_path(file)
 | 
					                        if not xbmcvfs.exists(os.path.join(path,file)):
 | 
				
			||||||
                        if not xbmcvfs.exists(os.path.join(path, file)):
 | 
					                            xbmcvfs.delete(os.path.join(path,file))
 | 
				
			||||||
                            xbmcvfs.delete(os.path.join(path, file))
 | 
					                        xbmcvfs.copy(os.path.join(path,file),os.path.join(folder,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
 | 
				
			||||||
@ -1409,6 +1339,7 @@ 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={}):
 | 
				
			||||||
@ -1419,23 +1350,13 @@ 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')
 | 
				
			||||||
            url = urllib.quote_plus(url)
 | 
					 | 
				
			||||||
            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
 | 
				
			||||||
@ -1462,14 +1383,7 @@ class Core:
 | 
				
			|||||||
                self.userStorageDirectory=dirname
 | 
					                self.userStorageDirectory=dirname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def playTorrent(self, params={}):
 | 
					    def playTorrent(self, params={}):
 | 
				
			||||||
        if params.get('filename'):
 | 
					        torrentUrl = self.__settings__.getSetting("lastTorrent")
 | 
				
			||||||
            torrentUrl = unquote(params.get('filename'))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            torrentUrl = self.__settings__.getSetting("lastTorrent")
 | 
					 | 
				
			||||||
        #xbmc.executebuiltin('Action(Stop)')
 | 
					 | 
				
			||||||
        if self.torrent_player != '1' and params.get('external') == '1' and not params.get('seek'):
 | 
					 | 
				
			||||||
            params['seek'] = watched_seek(torrentUrl, params['url'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.userStorage(params)
 | 
					        self.userStorage(params)
 | 
				
			||||||
        if self.torrent_player == '0':
 | 
					        if self.torrent_player == '0':
 | 
				
			||||||
            from Player import TorrentPlayer
 | 
					            from Player import TorrentPlayer
 | 
				
			||||||
@ -1489,14 +1403,11 @@ class Core:
 | 
				
			|||||||
                self.Player = InposPlayer(userStorageDirectory=self.userStorageDirectory, torrentUrl=torrentUrl, params=params)
 | 
					                self.Player = InposPlayer(userStorageDirectory=self.userStorageDirectory, torrentUrl=torrentUrl, params=params)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                log(self.__plugin__ + " Unexpected access to method playTorrent() without torrent content")
 | 
					                log(self.__plugin__ + " Unexpected access to method playTorrent() without torrent content")
 | 
				
			||||||
        elif self.torrent_player == '4':
 | 
					 | 
				
			||||||
            xbmc.executebuiltin('XBMC.ActivateWindow(%s)' % 'Videos,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("path")
 | 
					            folder=__ASsettings__.getSetting("folder")
 | 
				
			||||||
            save=__ASsettings__.getSetting("save")
 | 
					            save=__ASsettings__.getSetting("save")
 | 
				
			||||||
            __ASsettings__.setSetting("path", xbmc.translatePath(self.__settings__.getSetting("storage")))
 | 
					            __ASsettings__.setSetting("folder", 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)
 | 
				
			||||||
@ -1507,7 +1418,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("path", folder)
 | 
					            __ASsettings__.setSetting("folder", folder)
 | 
				
			||||||
            __ASsettings__.setSetting("save", save)
 | 
					            __ASsettings__.setSetting("save", save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def saveUrlTorrent(self, url):
 | 
					    def saveUrlTorrent(self, url):
 | 
				
			||||||
@ -1518,11 +1429,9 @@ class Core:
 | 
				
			|||||||
            request.add_header('Accept-encoding', 'gzip')
 | 
					            request.add_header('Accept-encoding', 'gzip')
 | 
				
			||||||
            result = urllib2.urlopen(request)
 | 
					            result = urllib2.urlopen(request)
 | 
				
			||||||
            if result.info().get('Content-Encoding') == 'gzip':
 | 
					            if result.info().get('Content-Encoding') == 'gzip':
 | 
				
			||||||
                from StringIO import StringIO
 | 
					 | 
				
			||||||
                import zlib
 | 
					 | 
				
			||||||
                buf = StringIO(result.read())
 | 
					                buf = StringIO(result.read())
 | 
				
			||||||
                decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
 | 
					                f = gzip.GzipFile(fileobj=buf)
 | 
				
			||||||
                content = decomp.decompress(buf.getvalue())
 | 
					                content = f.read()
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                content = result.read()
 | 
					                content = result.read()
 | 
				
			||||||
            localFile = xbmcvfs.File(torrentFile, "wb+")
 | 
					            localFile = xbmcvfs.File(torrentFile, "wb+")
 | 
				
			||||||
@ -1537,34 +1446,19 @@ 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)
 | 
				
			||||||
        url2 = unquote(get("url2"), None)
 | 
					        fileIndex = unquote(get("index"), 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)
 | 
				
			||||||
            filename = torrent.saveTorrent(url)
 | 
					            self.__settings__.setSetting("lastTorrent", torrent.saveTorrent(url))
 | 
				
			||||||
            self.__settings__.setSetting("lastTorrent", filename)
 | 
					            if fileIndex==None: fileIndex = chooseFile(torrent.getContentList())
 | 
				
			||||||
            if index == None: index = chooseFile(torrent.getContentList())
 | 
					            if fileIndex:
 | 
				
			||||||
            if index:
 | 
					                xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.torrenter/?action=playTorrent&url='+fileIndex+'")')
 | 
				
			||||||
                #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
 | 
				
			||||||
        tdir = unquote(get("url2"),None)
 | 
					        tdir = unquote(get("url2"),None)
 | 
				
			||||||
        thumbnail = unquote(get("thumbnail"), False) or 'DefaultVideo.png'
 | 
					        thumbnail = unquote(get("thumbnail"), False) and True or 'DefaultVideo.png'
 | 
				
			||||||
        save_folder = unquote(get("save_folder"),'')
 | 
					        save_folder = unquote(get("save_folder"),'')
 | 
				
			||||||
        url = urllib.unquote_plus(get("url"))
 | 
					        url = urllib.unquote_plus(get("url"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1575,12 +1469,10 @@ class Core:
 | 
				
			|||||||
            url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
 | 
					            url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
 | 
				
			||||||
            self.__settings__.setSetting("lastTorrent", url)
 | 
					            self.__settings__.setSetting("lastTorrent", url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        torrent = Downloader.Torrent(self.userStorageDirectory,
 | 
					        torrent = Downloader.Torrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
 | 
				
			||||||
                                     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)
 | 
				
			||||||
        filename = torrent.saveTorrent(url)
 | 
					        self.__settings__.setSetting("lastTorrent", 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
 | 
				
			||||||
@ -1592,7 +1484,7 @@ class Core:
 | 
				
			|||||||
                if append_filesize:
 | 
					                if append_filesize:
 | 
				
			||||||
                    fileTitle += ' [%d MB]' % (size / 1024 / 1024)
 | 
					                    fileTitle += ' [%d MB]' % (size / 1024 / 1024)
 | 
				
			||||||
                hasSize = True
 | 
					                hasSize = True
 | 
				
			||||||
            contentList.append([unescape(fileTitle), str(filedict.get('ind')), size])
 | 
					            contentList.append((unescape(fileTitle), str(filedict.get('ind')), size))
 | 
				
			||||||
        #contentList = sorted(contentList, key=lambda x: x[0])
 | 
					        #contentList = sorted(contentList, key=lambda x: x[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dirList, contentListNew = cutFolder(contentList, tdir)
 | 
					        dirList, contentListNew = cutFolder(contentList, tdir)
 | 
				
			||||||
@ -1616,11 +1508,9 @@ 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,
 | 
					                          action2=ids_video.rstrip(','), contextMenu=contextMenu, replaceMenu=False, fileSize=filesize)
 | 
				
			||||||
                          replaceMenu=False, fileSize=filesize)
 | 
					 | 
				
			||||||
        view_style('openTorrent')
 | 
					        view_style('openTorrent')
 | 
				
			||||||
        p_handle = int(sys.argv[1])
 | 
					        p_handle = int(sys.argv[1])
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
@ -1677,10 +1567,6 @@ 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"),'')
 | 
				
			||||||
@ -1698,8 +1584,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'),
 | 
					                (self.localize('Open (no return)'),
 | 
				
			||||||
                 'XBMC.Container.Update(%s)' % ('%s?action=%s%s') % (
 | 
					                 'XBMC.ActivateWindow(Videos,%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)
 | 
				
			||||||
@ -1759,8 +1645,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'),
 | 
					                        (self.localize('Open (no return)'),
 | 
				
			||||||
                         'XBMC.Container.Update(%s)' % ('%s?action=%s%s') % (
 | 
					                         'XBMC.ActivateWindow(Videos,%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)),
 | 
				
			||||||
@ -1776,28 +1662,8 @@ 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
 | 
				
			||||||
@ -1868,23 +1734,15 @@ 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(), name)[0]
 | 
					                    id = self.chooseHASH(Download().list())[0]
 | 
				
			||||||
                    Download().setprio(id, ind)
 | 
					                    Download().setprio(id, ind)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def downloadLibtorrent(self, params={}):
 | 
					    def downloadLibtorrent(self, params={}):
 | 
				
			||||||
        import SkorbaLoader
 | 
					        import Libtorrent
 | 
				
			||||||
        get = params.get
 | 
					        get = params.get
 | 
				
			||||||
        storage=get('storage')
 | 
					        storage=get('storage')
 | 
				
			||||||
        if not storage: self.userStorage(params)
 | 
					        if not storage: self.userStorage(params)
 | 
				
			||||||
@ -1900,7 +1758,7 @@ class Core:
 | 
				
			|||||||
            if classMatch:
 | 
					            if classMatch:
 | 
				
			||||||
                searcher = classMatch.group(1)
 | 
					                searcher = classMatch.group(1)
 | 
				
			||||||
                url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
 | 
					                url = Searchers().downloadWithSearcher(classMatch.group(2), searcher)
 | 
				
			||||||
        torrent = SkorbaLoader.SkorbaLoader(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
 | 
					        torrent = Libtorrent.Libtorrent(self.userStorageDirectory, torrentFilesDirectory=self.torrentFilesDirectory)
 | 
				
			||||||
        torrent.initSession()
 | 
					        torrent.initSession()
 | 
				
			||||||
        encryption = self.__settings__.getSetting('encryption') == 'true'
 | 
					        encryption = self.__settings__.getSetting('encryption') == 'true'
 | 
				
			||||||
        if encryption:
 | 
					        if encryption:
 | 
				
			||||||
@ -1914,6 +1772,7 @@ 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):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1925,21 +1784,13 @@ 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]').replace('1080p', '[B]1080p[/B]')
 | 
					        title = title.replace('720p', '[B]720p[/B]')
 | 
				
			||||||
 | 
					        title = clWhite % title + chr(10)
 | 
				
			||||||
        if self.torrent_info_style == 0:
 | 
					        second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers) + chr(10)
 | 
				
			||||||
            title = clWhite % title
 | 
					        space = ''
 | 
				
			||||||
            second = '[I](%s) [S/L: %d/%d] [/I]' % (size, seeds, leechers)
 | 
					        for i in range(0, 180 - len(second)):
 | 
				
			||||||
            title += '  ' + second
 | 
					            space += ' '
 | 
				
			||||||
        elif self.torrent_info_style == 1:
 | 
					        title += space + second
 | 
				
			||||||
            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={}):
 | 
				
			||||||
@ -1970,7 +1821,7 @@ class Core:
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.openSection(params)
 | 
					            self.openSection(params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def chooseHASH(self, list, name = None):
 | 
					    def chooseHASH(self, list):
 | 
				
			||||||
        dialog_items, dialog_items_clean = [], []
 | 
					        dialog_items, dialog_items_clean = [], []
 | 
				
			||||||
        dialog_files = []
 | 
					        dialog_files = []
 | 
				
			||||||
        dat = list
 | 
					        dat = list
 | 
				
			||||||
@ -1980,29 +1831,14 @@ 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'])
 | 
					        if len(dialog_items) > 1:
 | 
				
			||||||
 | 
					            ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items)
 | 
				
			||||||
        log('[chooseHASH]: name %s ' % str(name))
 | 
					            if ret > -1 and ret < len(dialog_files):
 | 
				
			||||||
        for data in dat:
 | 
					                hash = dialog_files[ret]
 | 
				
			||||||
            # Debug('[chooseHASH]: '+str((data['name'], data['id'], data['dir'].encode('utf-8'))))
 | 
					 | 
				
			||||||
            dialog_files.append((data['id'], data['dir'].encode('utf-8')))
 | 
					 | 
				
			||||||
            dialog_items.append('[' + str(data['progress']) + '%] ' + data['name'])
 | 
					 | 
				
			||||||
            dialog_items_clean.append(data['name'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if name:
 | 
					 | 
				
			||||||
            if decode_str(name) in dialog_items_clean:
 | 
					 | 
				
			||||||
                return dialog_files[dialog_items_clean.index(decode_str(name))]
 | 
					 | 
				
			||||||
            elif name in dialog_items_clean:
 | 
					 | 
				
			||||||
                return dialog_files[dialog_items_clean.index(name)]
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            if len(dialog_items) > 1:
 | 
					 | 
				
			||||||
                ret = xbmcgui.Dialog().select(self.localize('Choose in torrent-client:'), dialog_items)
 | 
					 | 
				
			||||||
                if ret > -1 and ret < len(dialog_files):
 | 
					 | 
				
			||||||
                    hash = dialog_files[ret]
 | 
					 | 
				
			||||||
                    return hash
 | 
					 | 
				
			||||||
            elif len(dialog_items) == 1:
 | 
					 | 
				
			||||||
                hash = dialog_files[0]
 | 
					 | 
				
			||||||
                return hash
 | 
					                return hash
 | 
				
			||||||
 | 
					        elif len(dialog_items) == 1:
 | 
				
			||||||
 | 
					            hash = dialog_files[0]
 | 
				
			||||||
 | 
					            return hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def localize(self, string):
 | 
					    def localize(self, string):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
@ -2014,9 +1850,23 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        external = unquote(get("external"), None)
 | 
				
			||||||
        subaction = unquote(get("subaction"), None)
 | 
					        subaction = unquote(get("subaction"), None)
 | 
				
			||||||
        url = unquote(get("url"),'')
 | 
					        url = unquote(get("url"),'')
 | 
				
			||||||
        sdata = unquote(get("sdata"),'{}')
 | 
					        sdata = unquote(get("sdata"),'{}')
 | 
				
			||||||
@ -2054,6 +1904,5 @@ class Core:
 | 
				
			|||||||
                xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.torrenter/?action=playTorrent&url=' + fileIndex + '")')
 | 
					                xbmc.executebuiltin('xbmc.RunPlugin("plugin://plugin.video.torrenter/?action=playTorrent&url=' + fileIndex + '")')
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sdata['filename'] = ensure_str(url)
 | 
					        sdata['filename'] = url
 | 
				
			||||||
        #log('[call]: '+sdata['filename']+json.loads(json.dumps(sdata))['filename'])
 | 
					        xbmc.executebuiltin('xbmc.RunPlugin("' + back_url + '&stringdata=' + json.dumps(sdata) + '")')
 | 
				
			||||||
        xbmc.executebuiltin('xbmc.RunPlugin(%s&stringdata=%s)' % (back_url, urllib.quote_plus(json.dumps(sdata))))
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,10 @@
 | 
				
			|||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Libtorrent
 | 
				
			||||||
 | 
					import AceStream
 | 
				
			||||||
 | 
					import Anteoloader
 | 
				
			||||||
 | 
					import Inposloader
 | 
				
			||||||
from functions import log
 | 
					from functions import log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Torrent():
 | 
					class Torrent():
 | 
				
			||||||
@ -29,19 +33,15 @@ class Torrent():
 | 
				
			|||||||
    def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
 | 
					    def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
 | 
				
			||||||
        self.get_torrent_client()
 | 
					        self.get_torrent_client()
 | 
				
			||||||
        if self.player == 'libtorrent':
 | 
					        if self.player == 'libtorrent':
 | 
				
			||||||
            import SkorbaLoader
 | 
					            self.player = Libtorrent.Libtorrent(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
				
			||||||
            self.player = SkorbaLoader.SkorbaLoader(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif self.player == 'acestream':
 | 
					        elif self.player == 'acestream':
 | 
				
			||||||
            import AceStream
 | 
					 | 
				
			||||||
            self.player = AceStream.AceStream(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
					            self.player = AceStream.AceStream(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif self.player == 'anteo':
 | 
					        elif self.player == 'anteo':
 | 
				
			||||||
            import Anteoloader
 | 
					 | 
				
			||||||
            self.player = Anteoloader.AnteoLoader(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
					            self.player = Anteoloader.AnteoLoader(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        elif self.player == 'inpos':
 | 
					        elif self.player == 'inpos':
 | 
				
			||||||
            import Inposloader
 | 
					 | 
				
			||||||
            self.player = Inposloader.InposLoader(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
					            self.player = Inposloader.InposLoader(storageDirectory, torrentFile, torrentFilesDirectory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __exit__(self):
 | 
					    def __exit__(self):
 | 
				
			||||||
@ -49,7 +49,7 @@ class Torrent():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def get_torrent_client(self):
 | 
					    def get_torrent_client(self):
 | 
				
			||||||
        player = self.__settings__.getSetting("torrent_player")
 | 
					        player = self.__settings__.getSetting("torrent_player")
 | 
				
			||||||
        if player == '0' or player == '4':
 | 
					        if player == '0':
 | 
				
			||||||
            self.player = 'libtorrent'
 | 
					            self.player = 'libtorrent'
 | 
				
			||||||
        elif player == '1':
 | 
					        elif player == '1':
 | 
				
			||||||
            self.player = 'acestream'
 | 
					            self.player = 'acestream'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										163
									
								
								Inposloader.py
									
									
									
									
									
								
							
							
						
						@ -28,9 +28,8 @@ import xbmc
 | 
				
			|||||||
import xbmcgui
 | 
					import xbmcgui
 | 
				
			||||||
import xbmcvfs
 | 
					import xbmcvfs
 | 
				
			||||||
import xbmcaddon
 | 
					import xbmcaddon
 | 
				
			||||||
import xbmcplugin
 | 
					 | 
				
			||||||
import Localization
 | 
					import Localization
 | 
				
			||||||
from functions import loadsw_onstop, isSubtitle, is_writable, file_url, localize_path
 | 
					from functions import localize_path, isSubtitle, is_writable, file_url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
@ -138,14 +137,13 @@ class InposLoader:
 | 
				
			|||||||
            keep_complete = True
 | 
					            keep_complete = True
 | 
				
			||||||
            keep_incomplete = True
 | 
					            keep_incomplete = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enable_dht = self.__settings__.getSetting("enable_dht") == 'true'
 | 
					 | 
				
			||||||
        dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
 | 
					        dht_routers = ["router.bittorrent.com:6881", "router.utorrent.com:6881"]
 | 
				
			||||||
        user_agent = ''
 | 
					        user_agent = 'uTorrent/2200(24683)'
 | 
				
			||||||
        self.engine = Engine(uri=file_url(self.torrentFile), download_path=self.storageDirectory,
 | 
					        self.engine = Engine(uri=file_url(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,
 | 
				
			||||||
                             user_agent=user_agent, enable_dht=enable_dht)
 | 
					                             user_agent=user_agent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def localize(self, string):
 | 
					    def localize(self, string):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
@ -154,10 +152,48 @@ class InposLoader:
 | 
				
			|||||||
            return string
 | 
					            return string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getContentList(self):
 | 
					    def getContentList(self):
 | 
				
			||||||
        from SkorbaLoader import SkorbaLoader
 | 
					        from Libtorrent import Libtorrent
 | 
				
			||||||
        torrent = SkorbaLoader(self.storageDirectory, self.torrentFile)
 | 
					        torrent = Libtorrent(self.storageDirectory, self.torrentFile)
 | 
				
			||||||
        return torrent.getContentList()
 | 
					        return torrent.getContentList()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    '''def getContentList_engine(self):
 | 
				
			||||||
 | 
					        self.setup_engine()
 | 
				
			||||||
 | 
					        files = []
 | 
				
			||||||
 | 
					        filelist = []
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.engine.start()
 | 
				
			||||||
 | 
					            #media_types=[MediaType.VIDEO, MediaType.AUDIO, MediaType.SUBTITLES, MediaType.UNKNOWN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            iterator = 0
 | 
				
			||||||
 | 
					            text = Localization.localize('Magnet-link is converting') if self.magnetLink\
 | 
				
			||||||
 | 
					                else Localization.localize('Opening torrent file')
 | 
				
			||||||
 | 
					            while not files and not xbmc.abortRequested and iterator < 100:
 | 
				
			||||||
 | 
					                files = self.engine.list()
 | 
				
			||||||
 | 
					                self.engine.check_torrent_error()
 | 
				
			||||||
 | 
					                if iterator==4:
 | 
				
			||||||
 | 
					                    progressBar = xbmcgui.DialogProgress()
 | 
				
			||||||
 | 
					                    progressBar.create(Localization.localize('Please Wait'),
 | 
				
			||||||
 | 
					                               Localization.localize('Magnet-link is converting'))
 | 
				
			||||||
 | 
					                elif iterator>4:
 | 
				
			||||||
 | 
					                    progressBar.update(iterator, Localization.localize('Please Wait'),text+'.' * (iterator % 4), ' ')
 | 
				
			||||||
 | 
					                    if progressBar.iscanceled():
 | 
				
			||||||
 | 
					                        progressBar.update(0)
 | 
				
			||||||
 | 
					                        progressBar.close()
 | 
				
			||||||
 | 
					                        return []
 | 
				
			||||||
 | 
					                xbmc.sleep(500)
 | 
				
			||||||
 | 
					                iterator += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for fs in files:
 | 
				
			||||||
 | 
					                stringdata = {"title": ensure_str(fs.name), "size": fs.size, "ind": fs.index,
 | 
				
			||||||
 | 
					                              'offset': fs.offset}
 | 
				
			||||||
 | 
					                filelist.append(stringdata)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            import traceback
 | 
				
			||||||
 | 
					            log(traceback.format_exc())
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            self.engine.close()
 | 
				
			||||||
 | 
					        return filelist'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def saveTorrent(self, torrentUrl):
 | 
					    def saveTorrent(self, torrentUrl):
 | 
				
			||||||
        #if not xbmcvfs.exists(torrentUrl) or re.match("^http.+$", torrentUrl):
 | 
					        #if not xbmcvfs.exists(torrentUrl) or re.match("^http.+$", torrentUrl):
 | 
				
			||||||
        if re.match("^magnet\:.+$", torrentUrl):
 | 
					        if re.match("^magnet\:.+$", torrentUrl):
 | 
				
			||||||
@ -167,14 +203,22 @@ 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 = localize_path(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("^[htps]+?://.+$|^://.+$", torrentUrl):
 | 
					                if not re.match("^http\:.+$", torrentUrl):
 | 
				
			||||||
                    log('xbmcvfs.File for %s' % torrentUrl)
 | 
					 | 
				
			||||||
                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
					                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    log('request for %s' % torrentUrl)
 | 
					                    request = urllib2.Request(torrentUrl)
 | 
				
			||||||
                    content = self.makeRequest(torrentUrl)
 | 
					                    request.add_header('Referer', 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()
 | 
				
			||||||
@ -190,29 +234,6 @@ 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:
 | 
				
			||||||
@ -223,13 +244,13 @@ class InposLoader:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def magnetToTorrent(self, magnet):
 | 
					    def magnetToTorrent(self, magnet):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            from SkorbaLoader import SkorbaLoader
 | 
					            from Libtorrent import Libtorrent
 | 
				
			||||||
            torrent = SkorbaLoader(self.storageDirectory, magnet)
 | 
					            torrent = Libtorrent(self.storageDirectory, magnet)
 | 
				
			||||||
            torrent.magnetToTorrent(magnet)
 | 
					            torrent.magnetToTorrent(magnet)
 | 
				
			||||||
            self.torrentFile = torrent.torrentFile
 | 
					            self.torrentFile = torrent.torrentFile
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            self.torrentFile = magnet
 | 
					            self.torrentFile = magnet
 | 
				
			||||||
        log('['+author+'Loader][magnetToTorrent]: self.torrentFile '+ensure_str((self.torrentFile)))
 | 
					        log('['+author+'Loader][magnetToTorrent]: self.torrentFile '+str(self.torrentFile))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InposPlayer(xbmc.Player):
 | 
					class InposPlayer(xbmc.Player):
 | 
				
			||||||
    __plugin__ = sys.modules["__main__"].__plugin__
 | 
					    __plugin__ = sys.modules["__main__"].__plugin__
 | 
				
			||||||
@ -253,12 +274,6 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
    def __init__(self, userStorageDirectory, torrentUrl, params={}):
 | 
					    def __init__(self, userStorageDirectory, torrentUrl, params={}):
 | 
				
			||||||
        self.userStorageDirectory = userStorageDirectory
 | 
					        self.userStorageDirectory = userStorageDirectory
 | 
				
			||||||
        self.torrentUrl = torrentUrl
 | 
					        self.torrentUrl = torrentUrl
 | 
				
			||||||
        if not is_writable(self.userStorageDirectory):
 | 
					 | 
				
			||||||
            xbmcgui.Dialog().ok(Localization.localize('Torrenter v2'),
 | 
					 | 
				
			||||||
                    Localization.localize('Your storage path is not writable or not local! Please change it in settings!'),
 | 
					 | 
				
			||||||
                    self.storageDirectory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            sys.exit(1)
 | 
					 | 
				
			||||||
        xbmc.Player.__init__(self)
 | 
					        xbmc.Player.__init__(self)
 | 
				
			||||||
        log("["+author+"Player] Initalized v"+__version__)
 | 
					        log("["+author+"Player] Initalized v"+__version__)
 | 
				
			||||||
        self.params = params
 | 
					        self.params = params
 | 
				
			||||||
@ -268,23 +283,16 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
            self.seek = int(self.get("seek"))
 | 
					            self.seek = int(self.get("seek"))
 | 
				
			||||||
        self.init()
 | 
					        self.init()
 | 
				
			||||||
        self.setup_engine()
 | 
					        self.setup_engine()
 | 
				
			||||||
        self.on_playback_resumed.append(self.engine.resume)
 | 
					 | 
				
			||||||
        self.on_playback_paused.append(self.engine.pause)
 | 
					 | 
				
			||||||
        showMessage('[%sPlayer v%s] ' % (author, __version__), self.localize('Please Wait'))
 | 
					 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.engine.start()
 | 
					            self.engine.start(self.contentId)
 | 
				
			||||||
            self.setup_nextep()
 | 
					            self.setup_nextep()
 | 
				
			||||||
            self.engine.activate_file(self.contentId)
 | 
					            while True:
 | 
				
			||||||
            if self.buffer():
 | 
					                if self.buffer():
 | 
				
			||||||
                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, self.torrentUrl, foldername(self.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize)
 | 
					                        WatchedHistoryDB().add(self.basename, 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
 | 
				
			||||||
@ -293,15 +301,13 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
                        if not self.next_play:
 | 
					                        if not self.next_play:
 | 
				
			||||||
                            xbmc.sleep(3000)
 | 
					                            xbmc.sleep(3000)
 | 
				
			||||||
                            if not xbmcgui.Dialog().yesno(
 | 
					                            if not xbmcgui.Dialog().yesno(
 | 
				
			||||||
                                self.localize('[%sPlayer v%s] ' % (author, __version__)),
 | 
					                                self.localize('Torrent2HTTP'),
 | 
				
			||||||
                                self.localize('Would you like to play next episode?')):
 | 
					                                self.localize('Would you like to play next episode?')):
 | 
				
			||||||
                                break
 | 
					                                break
 | 
				
			||||||
                        self.contentId = self.next_contentId
 | 
					                        self.contentId = self.next_contentId
 | 
				
			||||||
                        self.engine.activate_file(self.contentId)
 | 
					 | 
				
			||||||
                        showMessage('[%sPlayer v%s] ' % (author, __version__), self.localize('Please Wait'))
 | 
					 | 
				
			||||||
                        continue
 | 
					                        continue
 | 
				
			||||||
                    log('['+author+'Player]: ************************************* NO! break')
 | 
					                    log('['+author+'Player]: ************************************* NO! break')
 | 
				
			||||||
                    break
 | 
					                break
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            import traceback
 | 
					            import traceback
 | 
				
			||||||
            log(traceback.format_exc())
 | 
					            log(traceback.format_exc())
 | 
				
			||||||
@ -320,9 +326,7 @@ 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.'))
 | 
					                        self.localize('Torrent downloading is stopped.'), forced=True)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        loadsw_onstop()  # Reload Search Window
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init(self):
 | 
					    def init(self):
 | 
				
			||||||
        self.next_contentId = False
 | 
					        self.next_contentId = False
 | 
				
			||||||
@ -375,10 +379,9 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
            resume_file=os.path.join(self.userStorageDirectory, 'torrents', os.path.basename(self.torrentUrl)+'.resume_data')
 | 
					            resume_file=os.path.join(self.userStorageDirectory, 'torrents', os.path.basename(self.torrentUrl)+'.resume_data')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dht_routers = ["router.bittorrent.com:6881","router.utorrent.com:6881"]
 | 
					        dht_routers = ["router.bittorrent.com:6881","router.utorrent.com:6881"]
 | 
				
			||||||
        user_agent = ''
 | 
					        user_agent = 'uTorrent/2200(24683)'
 | 
				
			||||||
        self.pre_buffer_bytes = int(self.__settings__.getSetting("pre_buffer_bytes"))*1024*1024
 | 
					        self.pre_buffer_bytes = int(self.__settings__.getSetting("pre_buffer_bytes"))*1024*1024
 | 
				
			||||||
        if self.__settings__.getSetting('debug') == 'true':
 | 
					        showMessage('[%sPlayer v%s] ' % (author, __version__), self.localize('Please Wait'))
 | 
				
			||||||
            showMessage('[%sPlayer v%s] ' % (author, __version__), self.localize('Please Wait'))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.engine = Engine(uri=file_url(self.torrentUrl), download_path=self.userStorageDirectory,
 | 
					        self.engine = Engine(uri=file_url(self.torrentUrl), download_path=self.userStorageDirectory,
 | 
				
			||||||
                             connections_limit=connections_limit, download_kbps=download_limit, upload_kbps=upload_limit,
 | 
					                             connections_limit=connections_limit, download_kbps=download_limit, upload_kbps=upload_limit,
 | 
				
			||||||
@ -473,7 +476,6 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
        label = os.path.basename(file_status.name)
 | 
					        label = os.path.basename(file_status.name)
 | 
				
			||||||
        self.basename = label
 | 
					        self.basename = label
 | 
				
			||||||
        self.seeding_run = False
 | 
					        self.seeding_run = False
 | 
				
			||||||
        self.next_dling = False
 | 
					 | 
				
			||||||
        listitem = xbmcgui.ListItem(label, path=url)
 | 
					        listitem = xbmcgui.ListItem(label, path=url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.next_dl:
 | 
					        if self.next_dl:
 | 
				
			||||||
@ -508,11 +510,6 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
        if thumbnail:
 | 
					        if thumbnail:
 | 
				
			||||||
            listitem.setThumbnailImage(urllib.unquote_plus(thumbnail))
 | 
					            listitem.setThumbnailImage(urllib.unquote_plus(thumbnail))
 | 
				
			||||||
        self.display_name = label
 | 
					        self.display_name = label
 | 
				
			||||||
        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)
 | 
				
			||||||
@ -556,10 +553,7 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
                while not xbmc.abortRequested and self.isPlaying():
 | 
					                while not xbmc.abortRequested and self.isPlaying():
 | 
				
			||||||
                    #self.print_fulldebug()
 | 
					                    #self.print_fulldebug()
 | 
				
			||||||
                    status = self.engine.status()
 | 
					                    status = self.engine.status()
 | 
				
			||||||
                    if not self.next_dling:
 | 
					                    file_status = self.engine.file_status(self.contentId)
 | 
				
			||||||
                        file_status = self.engine.file_status(self.contentId)
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        file_status = self.engine.file_status(self.next_contentId)
 | 
					 | 
				
			||||||
                    self.watchedTime = xbmc.Player().getTime()
 | 
					                    self.watchedTime = xbmc.Player().getTime()
 | 
				
			||||||
                    self.totalTime = xbmc.Player().getTotalTime()
 | 
					                    self.totalTime = xbmc.Player().getTotalTime()
 | 
				
			||||||
                    if self.iterator == 100 and debug_counter < 100:
 | 
					                    if self.iterator == 100 and debug_counter < 100:
 | 
				
			||||||
@ -572,21 +566,16 @@ 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') and (self.getTime() > 0):
 | 
					                    if pause and self.__settings__.getSetting("pause_onplay") == 'true':
 | 
				
			||||||
                        pause = False
 | 
					                        pause = False
 | 
				
			||||||
                        xbmc.Player().pause()
 | 
					                        xbmc.Player().pause()
 | 
				
			||||||
                    xbmc.sleep(1000)
 | 
					                    xbmc.sleep(1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if self.iterator == 100 and self.next_dl and not self.next_dling and isinstance(self.next_contentId,
 | 
					                    #if not self.seeding_run and self.iterator == 100 and self.seeding:
 | 
				
			||||||
                                                                                                    int) and self.next_contentId != False:
 | 
					                        #self.seeding_run = True
 | 
				
			||||||
                        self.engine.activate_file(self.next_contentId)
 | 
					                        #self.seed(self.contentId)
 | 
				
			||||||
                        showMessage(self.localize('Torrent Downloading'),
 | 
					                        #self.seeding_status = True
 | 
				
			||||||
                                    self.localize('Starting download next episode!'))
 | 
					                        # xbmc.sleep(7000)
 | 
				
			||||||
                        log('[loop]: next_contentId '+str(self.next_contentId)+str(isinstance(self.next_contentId, int)))
 | 
					 | 
				
			||||||
                        file_status = self.engine.file_status(self.next_contentId)
 | 
					 | 
				
			||||||
                        self.basename = self.display_name = os.path.basename(file_status.name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        self.next_dling = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def onPlayBackStarted(self):
 | 
					    def onPlayBackStarted(self):
 | 
				
			||||||
        for f in self.on_playback_started:
 | 
					        for f in self.on_playback_started:
 | 
				
			||||||
@ -618,7 +607,7 @@ class InposPlayer(xbmc.Player):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def _get_status_lines(self, s, f):
 | 
					    def _get_status_lines(self, s, f):
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            ensure_str(self.display_name),
 | 
					            localize_path(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'),
 | 
				
			||||||
 | 
				
			|||||||
@ -32,9 +32,9 @@ 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, decode_str
 | 
					    vista_check, windows_check, localize_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SkorbaLoader:
 | 
					class Libtorrent:
 | 
				
			||||||
    magnetLink = None
 | 
					    magnetLink = None
 | 
				
			||||||
    startPart = 0
 | 
					    startPart = 0
 | 
				
			||||||
    endPart = 0
 | 
					    endPart = 0
 | 
				
			||||||
@ -46,7 +46,6 @@ class SkorbaLoader:
 | 
				
			|||||||
    lt = None
 | 
					    lt = None
 | 
				
			||||||
    save_resume_data = None
 | 
					    save_resume_data = None
 | 
				
			||||||
    __settings__ = sys.modules["__main__"].__settings__
 | 
					    __settings__ = sys.modules["__main__"].__settings__
 | 
				
			||||||
    enable_dht = __settings__.getSetting("enable_dht") == 'true'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
 | 
					    def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
 | 
				
			||||||
        self.storageDirectory = storageDirectory
 | 
					        self.storageDirectory = storageDirectory
 | 
				
			||||||
@ -54,7 +53,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!'),
 | 
				
			||||||
                    self.storageDirectory)
 | 
					                    Localization.localize(self.storageDirectory))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            sys.exit(1)
 | 
					            sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,14 +92,24 @@ 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 = localize_path(os.path.join(self.torrentFilesPath, self.md5(torrentUrl) + '.torrent'))
 | 
					            torrentFile = self.torrentFilesPath + self.md5(
 | 
				
			||||||
 | 
					                torrentUrl) + '.torrent'
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                if not re.match("^[htps]+?://.+$|^://.+$", torrentUrl):
 | 
					                if not re.match("^http\:.+$", torrentUrl):
 | 
				
			||||||
                    log('xbmcvfs.File for %s' % torrentUrl)
 | 
					                    contentFile = xbmcvfs.File(torrentUrl, "rb")
 | 
				
			||||||
                    content = xbmcvfs.File(torrentUrl, "rb").read()
 | 
					                    content = contentFile.read()
 | 
				
			||||||
 | 
					                    contentFile.close()
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    log('request for %s' % torrentUrl)
 | 
					                    request = urllib2.Request(torrentUrl)
 | 
				
			||||||
                    content = self.makeRequest(torrentUrl)
 | 
					                    request.add_header('Referer', 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)
 | 
				
			||||||
@ -118,7 +127,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 = localize_path(self.torrentFilesPath + self.md5(torrentUrl) + '.torrent')
 | 
					                newFile = 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)
 | 
				
			||||||
@ -136,29 +145,6 @@ 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,
 | 
				
			||||||
@ -170,11 +156,14 @@ 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)
 | 
				
			||||||
 | 
					            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():
 | 
				
			||||||
@ -199,9 +188,10 @@ class SkorbaLoader:
 | 
				
			|||||||
        if torrentInfo:
 | 
					        if torrentInfo:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                torrentFile = self.lt.create_torrent(torrentInfo)
 | 
					                torrentFile = self.lt.create_torrent(torrentInfo)
 | 
				
			||||||
 | 
					                baseName = os.path.basename(self.storageDirectory + os.sep + torrentInfo.files()[0].path)
 | 
				
			||||||
                if not xbmcvfs.exists(self.torrentFilesPath):
 | 
					                if not xbmcvfs.exists(self.torrentFilesPath):
 | 
				
			||||||
                    xbmcvfs.mkdirs(self.torrentFilesPath)
 | 
					                    xbmcvfs.mkdirs(self.torrentFilesPath)
 | 
				
			||||||
                self.torrentFile = self.torrentFilesPath + self.md5(magnet) + '.torrent'
 | 
					                self.torrentFile = self.torrentFilesPath + self.md5(baseName) + '.torrent'
 | 
				
			||||||
                torentFileHandler = xbmcvfs.File(self.torrentFile, "w+b")
 | 
					                torentFileHandler = xbmcvfs.File(self.torrentFile, "w+b")
 | 
				
			||||||
                torentFileHandler.write(self.lt.bencode(torrentFile.generate()))
 | 
					                torentFileHandler.write(self.lt.bencode(torrentFile.generate()))
 | 
				
			||||||
                torentFileHandler.close()
 | 
					                torentFileHandler.close()
 | 
				
			||||||
@ -243,13 +233,12 @@ class SkorbaLoader:
 | 
				
			|||||||
        return self.getContentList()[contentId]['size']
 | 
					        return self.getContentList()[contentId]['size']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getFilePath(self, contentId=0):
 | 
					    def getFilePath(self, contentId=0):
 | 
				
			||||||
        return os.path.join(self.storageDirectory, decode_str(self.getContentList()[contentId]['title']))
 | 
					        return os.path.join(self.storageDirectory, self.getContentList()[contentId]['title'])  # .decode('utf8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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": contentFile.path, "size": contentFile.size, "ind": int(contentId),
 | 
					            stringdata = {"title": localize_path(contentFile.path), "size": contentFile.size, "ind": int(contentId),
 | 
				
			||||||
                          'offset': contentFile.offset}
 | 
					                          'offset': contentFile.offset}
 | 
				
			||||||
            filelist.append(stringdata)
 | 
					            filelist.append(stringdata)
 | 
				
			||||||
        return filelist
 | 
					        return filelist
 | 
				
			||||||
@ -318,13 +307,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':
 | 
				
			||||||
@ -343,9 +332,7 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -353,10 +340,9 @@ class SkorbaLoader:
 | 
				
			|||||||
        self.session = self.lt.session()
 | 
					        self.session = self.lt.session()
 | 
				
			||||||
        self.session.set_alert_mask(self.lt.alert.category_t.error_notification | self.lt.alert.category_t.status_notification | self.lt.alert.category_t.storage_notification)
 | 
					        self.session.set_alert_mask(self.lt.alert.category_t.error_notification | self.lt.alert.category_t.status_notification | self.lt.alert.category_t.storage_notification)
 | 
				
			||||||
        #self.session.set_alert_mask(self.lt.alert.category_t.all_categories)
 | 
					        #self.session.set_alert_mask(self.lt.alert.category_t.all_categories)
 | 
				
			||||||
        if self.enable_dht:
 | 
					        self.session.add_dht_router("router.bittorrent.com", 6881)
 | 
				
			||||||
            self.session.add_dht_router("router.bittorrent.com", 6881)
 | 
					        self.session.add_dht_router("router.utorrent.com", 6881)
 | 
				
			||||||
            self.session.add_dht_router("router.utorrent.com", 6881)
 | 
					        self.session.start_dht()
 | 
				
			||||||
            self.session.start_dht()
 | 
					 | 
				
			||||||
        self.session.start_lsd()
 | 
					        self.session.start_lsd()
 | 
				
			||||||
        self.session.start_upnp()
 | 
					        self.session.start_upnp()
 | 
				
			||||||
        self.session.start_natpmp()
 | 
					        self.session.start_natpmp()
 | 
				
			||||||
@ -381,7 +367,7 @@ class SkorbaLoader:
 | 
				
			|||||||
            session_settings['rate_limit_ip_overhead'] = True
 | 
					            session_settings['rate_limit_ip_overhead'] = True
 | 
				
			||||||
            session_settings['request_timeout'] = 1
 | 
					            session_settings['request_timeout'] = 1
 | 
				
			||||||
            session_settings['torrent_connect_boost'] = 50
 | 
					            session_settings['torrent_connect_boost'] = 50
 | 
				
			||||||
            session_settings['user_agent'] = ''
 | 
					            session_settings['user_agent'] = 'uTorrent/2200(24683)'
 | 
				
			||||||
            if pc_config == 0:
 | 
					            if pc_config == 0:
 | 
				
			||||||
                #good pc
 | 
					                #good pc
 | 
				
			||||||
                session_settings['connections_limit'] = 200
 | 
					                session_settings['connections_limit'] = 200
 | 
				
			||||||
@ -412,7 +398,7 @@ class SkorbaLoader:
 | 
				
			|||||||
            session_settings.rate_limit_ip_overhead = True
 | 
					            session_settings.rate_limit_ip_overhead = True
 | 
				
			||||||
            session_settings.request_timeout = 1
 | 
					            session_settings.request_timeout = 1
 | 
				
			||||||
            session_settings.torrent_connect_boost = 100
 | 
					            session_settings.torrent_connect_boost = 100
 | 
				
			||||||
            session_settings.user_agent = ''
 | 
					            session_settings.user_agent = 'uTorrent/2200(24683)'
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        self.session.set_settings(session_settings)
 | 
					        self.session.set_settings(session_settings)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -496,7 +482,7 @@ class SkorbaLoader:
 | 
				
			|||||||
            self.session.stop_natpmp()
 | 
					            self.session.stop_natpmp()
 | 
				
			||||||
            self.session.stop_upnp()
 | 
					            self.session.stop_upnp()
 | 
				
			||||||
            self.session.stop_lsd()
 | 
					            self.session.stop_lsd()
 | 
				
			||||||
            if self.enable_dht: self.session.stop_dht()
 | 
					            self.session.stop_dht()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resume_data(self):
 | 
					    def resume_data(self):
 | 
				
			||||||
        wasPaused=self.session.is_paused()
 | 
					        wasPaused=self.session.is_paused()
 | 
				
			||||||
							
								
								
									
										549
									
								
								Localization.py
									
									
									
									
									
								
							
							
						
						@ -23,7 +23,7 @@ try:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    __settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
 | 
					    __settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    language = ('en', 'ru', 'uk','he', 'es')[int(__settings__.getSetting("language"))]
 | 
					    language = ('en', 'ru', 'uk','he')[int(__settings__.getSetting("language"))]
 | 
				
			||||||
except:
 | 
					except:
 | 
				
			||||||
    language = 'ru'
 | 
					    language = 'ru'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,266 +31,7 @@ except:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def localize(text):
 | 
					def localize(text):
 | 
				
			||||||
    dictionary = {
 | 
					    dictionary = {
 | 
				
			||||||
    	'es': {
 | 
						 'he': {
 | 
				
			||||||
            'Seeds searching.': 'Búsqueda de fuentes',
 | 
					 | 
				
			||||||
            'Please Wait': 'Espere',
 | 
					 | 
				
			||||||
            'Information': 'Información',
 | 
					 | 
				
			||||||
            'Torrent downloading is stopped.': 'Se detuvo la descarga del torrent',
 | 
					 | 
				
			||||||
            'Search': 'Buscar',
 | 
					 | 
				
			||||||
            'Seeds': 'Semillas',
 | 
					 | 
				
			||||||
            'Peers': 'Pares',
 | 
					 | 
				
			||||||
            'Materials are loading now.': 'Se están cargando los materiales',
 | 
					 | 
				
			||||||
            'Search Phrase': 'Términos de búsqueda',
 | 
					 | 
				
			||||||
            'Magnet-link is converting': 'Se está convirtiendo el enlace magnet',
 | 
					 | 
				
			||||||
            'Error': 'Error',
 | 
					 | 
				
			||||||
            'Your library out of date and can\'t save magnet-links.': 'Su colección está anticuada y no pueden guardarse enlaces magnet.',
 | 
					 | 
				
			||||||
            'Bookmarks': 'Favoritos',
 | 
					 | 
				
			||||||
            'Logout': 'Cerrar sesión',
 | 
					 | 
				
			||||||
            'Login': 'Iniciar sesión',
 | 
					 | 
				
			||||||
            'Recent Materials': 'Materiales recientes ',
 | 
					 | 
				
			||||||
            'Register': 'Registrar',
 | 
					 | 
				
			||||||
            'Bookmark': 'Favorito',
 | 
					 | 
				
			||||||
            'Item successfully added to Bookmarks': 'El elemento se ha añadido a "Favoritos"',
 | 
					 | 
				
			||||||
            'Item successfully removed from Bookmarks': 'El elemento se ha eliminado de "Favoritos"',
 | 
					 | 
				
			||||||
            'Bookmark not added': 'No se ha añadido a "Favoritos"',
 | 
					 | 
				
			||||||
            'Bookmark not removed': 'No se ha eliminado de "Favoritos"',
 | 
					 | 
				
			||||||
            'Add To Bookmarks': 'Añadir a "Favoritos"',
 | 
					 | 
				
			||||||
            'Remove From Bookmarks': 'Eliminar de "Favoritos"',
 | 
					 | 
				
			||||||
            'Auth': 'Validación',
 | 
					 | 
				
			||||||
            'Already logged in': 'Ya se había iniciado sesión',
 | 
					 | 
				
			||||||
            'Input Email (for password recovery):': 'Introduzca correo electrónico (para recuperar contraseña):',
 | 
					 | 
				
			||||||
            'Input Email:': 'Introduzca correo electrónico:',
 | 
					 | 
				
			||||||
            'Input Password (6+ symbols):': 'Introduzca contraseña (más de 6 caracteres):',
 | 
					 | 
				
			||||||
            'Input Password:': 'Introduzca contraseña',
 | 
					 | 
				
			||||||
            'Login successfull': 'Se ha iniciado sesión',
 | 
					 | 
				
			||||||
            'Login failed': 'Falló el inicio de sesión',
 | 
					 | 
				
			||||||
            'User not logged in': 'El usuario no ha iniciado sesión',
 | 
					 | 
				
			||||||
            'User successfully logged out': 'El usuario ha cerrado sesión',
 | 
					 | 
				
			||||||
            'Preloaded: ': 'Carga previa: ',
 | 
					 | 
				
			||||||
            'Do you want to STOP torrent downloading and seeding?': '¿Desea detener la descarga y dejar de compartir el torrent?',
 | 
					 | 
				
			||||||
            'Torrent Downloading': 'Descarga de torrent',
 | 
					 | 
				
			||||||
            'Auth expired, please relogin': 'Expiró la identificación. Vuelva a iniciar sesión',
 | 
					 | 
				
			||||||
            'Storage': 'Almacén',
 | 
					 | 
				
			||||||
            'Storage has been cleared': 'El almacén se ha vaciado',
 | 
					 | 
				
			||||||
            'Clear Storage': 'Vaciar almacén',
 | 
					 | 
				
			||||||
            'Popular': 'Popular',
 | 
					 | 
				
			||||||
            'Views': 'Vistas',
 | 
					 | 
				
			||||||
            'Uploading': 'Subiendo',
 | 
					 | 
				
			||||||
            'Download': 'Descargar',
 | 
					 | 
				
			||||||
            'Input symbols from CAPTCHA image:': 'Introduzca los caracteres que aparecen en la imagen:',
 | 
					 | 
				
			||||||
            'Please, rate watched video:': 'Valore el vídeo que ha visto:',
 | 
					 | 
				
			||||||
            'Bad': 'Malo',
 | 
					 | 
				
			||||||
            'So-So': 'Regular',
 | 
					 | 
				
			||||||
            'Good': 'Bueno',
 | 
					 | 
				
			||||||
            'Ratings': 'Valoraciones',
 | 
					 | 
				
			||||||
            'Rating': 'Valoración',
 | 
					 | 
				
			||||||
            'Retry': 'Reintentar',
 | 
					 | 
				
			||||||
            '%ds has left': 'Ha quedado %ds',
 | 
					 | 
				
			||||||
            'File failed to play! Do you want to RETRY and buffer more?': 'Falló la reproducción del archivo. ¿Desea volver a intentarlo y aumentar el tamaño de búfer?',
 | 
					 | 
				
			||||||
            'High Priority Files': 'Archivos de prioridad alta',
 | 
					 | 
				
			||||||
            'Skip All Files': 'Omitir todos los archivos',
 | 
					 | 
				
			||||||
            'Start': 'Iniciar',
 | 
					 | 
				
			||||||
            'Stop': 'Detener',
 | 
					 | 
				
			||||||
            'Play':'Reproducir',
 | 
					 | 
				
			||||||
            'High Priority': 'Prioridad alta',
 | 
					 | 
				
			||||||
            'Skip File': 'Omitir archivo',
 | 
					 | 
				
			||||||
            'Remove': 'Eliminar',
 | 
					 | 
				
			||||||
            'Remove with files': 'Eliminar con los archivos',
 | 
					 | 
				
			||||||
            'Play File': 'Reproducir archivo',
 | 
					 | 
				
			||||||
            'Start All Files': 'Iniciar todos los archivos',
 | 
					 | 
				
			||||||
            'Stop All Files': 'Detener todos los archivos',
 | 
					 | 
				
			||||||
            'Torrent-client Browser': 'Explorador de cliente de BitTorrent',
 | 
					 | 
				
			||||||
            'Remote Torrent-client': 'Cliente de BitTorrent remoto',
 | 
					 | 
				
			||||||
            'You didn\'t set up replacement path in setting.': 'No se ha establecido una ruta alternativa en "Ajustes".',
 | 
					 | 
				
			||||||
            'For example /media/dl_torr/ to smb://SERVER/dl_torr/. Setup now?': 'Por ejemplo, /media/dl_torr/ a smb://SERVER/dl_torr/. ¿Desea establecerla ahora?',
 | 
					 | 
				
			||||||
            'Manual Torrent-client Path Edit': 'Edición manual de la ruta del cliente de BitTorrent',
 | 
					 | 
				
			||||||
            'Choose .torrent in video library': 'Seleccione archivo .torrent en la colección de vídeos',
 | 
					 | 
				
			||||||
            '.torrent Player': 'Gestor de archivo .torrent',
 | 
					 | 
				
			||||||
            'Choose directory:': 'Seleccionar directorio:',
 | 
					 | 
				
			||||||
            'Starting download next episode!': 'Iniciando descarga de episodio siguiente',
 | 
					 | 
				
			||||||
            'Choose in torrent-client:': 'Elija cliente torrent',
 | 
					 | 
				
			||||||
            'Search Control Window': 'Control de búsquedas',
 | 
					 | 
				
			||||||
            'Magnet-link (magnet:...)': 'Enlace magnet (magnet:...)',
 | 
					 | 
				
			||||||
            'Not a magnet-link!': 'No es un enlace magnet',
 | 
					 | 
				
			||||||
            'Magnet-link Player': 'Gestor de enlace magnet',
 | 
					 | 
				
			||||||
            'UNKNOWN STATUS': 'ESTADO DESCONOCIDO',
 | 
					 | 
				
			||||||
            'Checking preloaded files...': 'Comprobando archivos precargados...',
 | 
					 | 
				
			||||||
            'Waiting for website response...': 'Esperando respuesta del sitio web...',
 | 
					 | 
				
			||||||
            'Search and cache information for:': 'Buscar y almacenar datos para:',
 | 
					 | 
				
			||||||
            'Open Torrent': 'Abrir torrent',
 | 
					 | 
				
			||||||
            'Torrent list is empty.': 'La lista de torrents está en blanco',
 | 
					 | 
				
			||||||
            'Content Lists': 'Listas de contenido',
 | 
					 | 
				
			||||||
            'Canceled by User': 'Cancelado por el usuario',
 | 
					 | 
				
			||||||
            'Do you want to search and cache full metadata + arts?': '¿Desea buscar y almacenar los metadatos y fan-arts completos?',
 | 
					 | 
				
			||||||
            'This vastly decreases load speed, but you will be asked to download premade bases!': 'Esto reduce considerablemente la velocidad de carga. Pero se le solicitará descargar desde cero',
 | 
					 | 
				
			||||||
            'Do you want to preload full metadata?': '¿Desea precargar los metadatos completos?',
 | 
					 | 
				
			||||||
            'It is highly recommended!': 'Altamente recomendado',
 | 
					 | 
				
			||||||
            'TV Shows': 'Series de televisión',
 | 
					 | 
				
			||||||
            'Cartoons': 'Dibujos animados',
 | 
					 | 
				
			||||||
            'Anime': 'Anime',
 | 
					 | 
				
			||||||
            'Most Recent': 'Estrenos',
 | 
					 | 
				
			||||||
            'Top 250 Movies': 'Las 250 mejores películas',
 | 
					 | 
				
			||||||
            'Top All Time': 'Las mejores de todos los tiempos',
 | 
					 | 
				
			||||||
            'by Genre': 'Por género',
 | 
					 | 
				
			||||||
            'by Year': 'Por año',
 | 
					 | 
				
			||||||
            'Action': 'Acción',
 | 
					 | 
				
			||||||
            'Adventure': 'Aventuras',
 | 
					 | 
				
			||||||
            'Animation': 'Animación',
 | 
					 | 
				
			||||||
            'Biography': 'Biografías',
 | 
					 | 
				
			||||||
            'Comedy': 'Comedia',
 | 
					 | 
				
			||||||
            'Crime': 'Policiacas',
 | 
					 | 
				
			||||||
            'Documentary': 'Documentales',
 | 
					 | 
				
			||||||
            'Drama': 'Drama',
 | 
					 | 
				
			||||||
            'Family': 'Todos los públicos',
 | 
					 | 
				
			||||||
            'Fantasy': 'Fantásticas',
 | 
					 | 
				
			||||||
            'Film-Noir': 'Cine negro',
 | 
					 | 
				
			||||||
            'History': 'Historia',
 | 
					 | 
				
			||||||
            'Horror': 'Terror',
 | 
					 | 
				
			||||||
            'Music': 'Música',
 | 
					 | 
				
			||||||
            'Musical': 'Musicales',
 | 
					 | 
				
			||||||
            'Mystery': 'Misterio',
 | 
					 | 
				
			||||||
            'Romance': 'Románticas',
 | 
					 | 
				
			||||||
            'Sci-Fi': 'Ciencia ficción',
 | 
					 | 
				
			||||||
            'Short': 'Cortos',
 | 
					 | 
				
			||||||
            'Sport': 'Deportes',
 | 
					 | 
				
			||||||
            'Thriller': 'Suspense',
 | 
					 | 
				
			||||||
            'War': 'Bélicas',
 | 
					 | 
				
			||||||
            'Western': 'Películas del Oeste',
 | 
					 | 
				
			||||||
            '[B]by Site[/B]': '[B]Por sitio[/B]',
 | 
					 | 
				
			||||||
            'Cartoons Series': 'Series de dibujos animados',
 | 
					 | 
				
			||||||
            'Cartoons Short': 'Cortos de dibujos animados',
 | 
					 | 
				
			||||||
            'Male': 'Hombre',
 | 
					 | 
				
			||||||
            'Female': 'Mujer',
 | 
					 | 
				
			||||||
            'Russia & USSR': 'Rusia & URSS',
 | 
					 | 
				
			||||||
            'Next Page': 'Página siguiente',
 | 
					 | 
				
			||||||
            'Previous Page': 'Página anterior',
 | 
					 | 
				
			||||||
            'Russian Movies': 'Películas rusas',
 | 
					 | 
				
			||||||
            'israeli Movies': 'Películas israelíes',
 | 
					 | 
				
			||||||
            'hebdub movies': 'Películas dobladas al hebreo',
 | 
					 | 
				
			||||||
            'Movies': 'Películas',
 | 
					 | 
				
			||||||
            'High Resolution Movies': 'Películas en alta resolución',
 | 
					 | 
				
			||||||
            '3D Movies': 'Películas en 3D',
 | 
					 | 
				
			||||||
            'Movies [Bluray]': 'Películas en formato Blu-ray',
 | 
					 | 
				
			||||||
            'Anime Film': 'Películas Anime',
 | 
					 | 
				
			||||||
            'Anime Series': 'Series Anime',
 | 
					 | 
				
			||||||
            'Can\'t download torrent, probably no seeds available.': 'No se puede descargar el torrent, probablemente no hay fuentes disponibles.',
 | 
					 | 
				
			||||||
            'Personal List': 'Lista personal',
 | 
					 | 
				
			||||||
            'Add to %s': 'Añadir a %s',
 | 
					 | 
				
			||||||
            'Delete from %s': 'Eliminar de %s',
 | 
					 | 
				
			||||||
            'Added!': 'Añadido',
 | 
					 | 
				
			||||||
            'Deleted!': 'Eliminado',
 | 
					 | 
				
			||||||
            'Search History': 'Historial de búsquedas',
 | 
					 | 
				
			||||||
            ' History ':' Historial ',
 | 
					 | 
				
			||||||
            'Torrent History':'Historial de archivos torrent',
 | 
					 | 
				
			||||||
            'Watched History':'Historial de vistos',
 | 
					 | 
				
			||||||
            'Favourites': 'Favoritos',
 | 
					 | 
				
			||||||
            'Favourites SH': 'Favoritos SH',
 | 
					 | 
				
			||||||
            'Clear %s': 'Vaciar %s',
 | 
					 | 
				
			||||||
            'Clear!': 'Vacío',
 | 
					 | 
				
			||||||
            'kb/s': 'kbps',
 | 
					 | 
				
			||||||
            'Queued': 'Situado en cola',
 | 
					 | 
				
			||||||
            'Checking': 'Comprobando',
 | 
					 | 
				
			||||||
            'Downloading metadata': 'Descargando metadatos',
 | 
					 | 
				
			||||||
            'Downloading': 'Descargando',
 | 
					 | 
				
			||||||
            'Finished': 'Finalizado',
 | 
					 | 
				
			||||||
            'Seeding': 'Compartiendo',
 | 
					 | 
				
			||||||
            'Allocating': 'Reservando espacio',
 | 
					 | 
				
			||||||
            'Allocating file & Checking resume': 'Reservando espacio y comprobando reanudación',
 | 
					 | 
				
			||||||
            'For Kids': 'Para niños',
 | 
					 | 
				
			||||||
            'Adult': 'Adultos',
 | 
					 | 
				
			||||||
            'Does not support magnet links!': 'No compatible con enlaces magnet',
 | 
					 | 
				
			||||||
            'Reset All Cache DBs': 'Reiniciar todas las bases de datos de la caché',
 | 
					 | 
				
			||||||
            '[B]Search[/B]': '[B]Buscar[/B]',
 | 
					 | 
				
			||||||
            'You can always restart this by deleting DBs via Context Menu': 'Siempre se puede reiniciar esto eliminando las bases de datos a través del menú contextual',
 | 
					 | 
				
			||||||
            'Your preloaded databases are outdated!': 'Las bases de datos precargadas son obsoletas',
 | 
					 | 
				
			||||||
            'Do you want to download new ones right now?': '¿Desea descargar versiones actualizadas?',
 | 
					 | 
				
			||||||
            'Individual Tracker Options':'Opciones individuales del rastreador',
 | 
					 | 
				
			||||||
            'Downloading and copy subtitles. Please wait.':'Descargando y copiando subtítulos. Espere.',
 | 
					 | 
				
			||||||
            'International Check - First Run':'Comprobación internacional - Primera ejecución.',
 | 
					 | 
				
			||||||
            'Delete Russian stuff?':'¿Desea eliminar las cosas de Rusia?',
 | 
					 | 
				
			||||||
            'Save to path':'Ruta para guardar',
 | 
					 | 
				
			||||||
            'Return Russian stuff':'Devolver las cosas de Rusia',
 | 
					 | 
				
			||||||
            '%d files have been returned':'Han vuelto %d archivos',
 | 
					 | 
				
			||||||
            'Download via T-client':'Descargar a través de cliente BitTorrent',
 | 
					 | 
				
			||||||
            'Download via Libtorrent':'Descargar a través de Libtorrent',
 | 
					 | 
				
			||||||
            'Download Status':'Estado de la descarga',
 | 
					 | 
				
			||||||
            'Download has not finished yet':'La descarga no ha finalizado todavía',
 | 
					 | 
				
			||||||
            'Stopped and Deleted!':'Detenido y eliminado',
 | 
					 | 
				
			||||||
            'Unpaused!':'Despausado',
 | 
					 | 
				
			||||||
            'Paused!':'Pausado',
 | 
					 | 
				
			||||||
            'Stopped!':'Detenido',
 | 
					 | 
				
			||||||
            'Started!':'Iniciado',
 | 
					 | 
				
			||||||
            'Delete and Stop':'Eliminar y detener',
 | 
					 | 
				
			||||||
            'Unpause':'Despausar',
 | 
					 | 
				
			||||||
            'Pause':'Pausar',
 | 
					 | 
				
			||||||
            'Delete':'Eliminar',
 | 
					 | 
				
			||||||
            'Open':'Abrir',
 | 
					 | 
				
			||||||
            'Torrent is seeding. To stop it use Download Status.':'El torrent se está compartiendo. Para detenerlo utilice "Estado de la descarga".',
 | 
					 | 
				
			||||||
            'Start All':'Iniciar todo',
 | 
					 | 
				
			||||||
            'Started All!':'Se ha iniciado todo',
 | 
					 | 
				
			||||||
            'Stopped All!':'Se ha detenido todo',
 | 
					 | 
				
			||||||
            'Stop All':'Detener todo',
 | 
					 | 
				
			||||||
            'Keyboard':'Teclado',
 | 
					 | 
				
			||||||
            'Copy Files in Root':'Copiar archivos en directorio personal de root (/root)',
 | 
					 | 
				
			||||||
            'Copied %d files!':'Se han copiado %d archivos',
 | 
					 | 
				
			||||||
            'Add to MyShows.ru':'Añadir a MyShows.ru',
 | 
					 | 
				
			||||||
            'Return to MyShows.ru':'Volver a MyShows.ru',
 | 
					 | 
				
			||||||
            'Search results:':'Resultados de la búsqueda',
 | 
					 | 
				
			||||||
            'by Seeders':'Por fuentes',
 | 
					 | 
				
			||||||
            'by Date':'Por fecha',
 | 
					 | 
				
			||||||
            'Sort':'Ordenar',
 | 
					 | 
				
			||||||
            'Close':'Cerrar',
 | 
					 | 
				
			||||||
            'Views:':'Vistas:',
 | 
					 | 
				
			||||||
            'Rating:':'Valoración:',
 | 
					 | 
				
			||||||
            'Information not found!':'No se han encontrado datos',
 | 
					 | 
				
			||||||
            'Choose searcher':'Elegir buscador',
 | 
					 | 
				
			||||||
            'python-libtorrent Not Found':'No se ha encontrado python-libtorrent',
 | 
					 | 
				
			||||||
            'Windows has static compiled python-libtorrent included.':'Windows incluye una versión de python-libtorrent compilada estáticamente',
 | 
					 | 
				
			||||||
            'You should install "script.module.libtorrent" from "MyShows.me Kodi Repo"':'Se debe instalar "script.module.libtorrrent" desde el repositorio "MyShows.me"',
 | 
					 | 
				
			||||||
            'Linux x64 has not static compiled python-libtorrent included.':'Linux x64 no incluye una versión de python-libtorrent compilada estáticamente',
 | 
					 | 
				
			||||||
            'You should install it by "sudo apt-get install python-libtorrent"':'Se debe instalar con "sudo apt-get install python-libtorrent"',
 | 
					 | 
				
			||||||
            'Linux has static compiled python-libtorrent included but it didn\'t work.':'Linux incluye una version de python-libtorrent compilada estáticamente, pero no ha funcionado',
 | 
					 | 
				
			||||||
            'As far as I know you can compile python-libtorrent for ARMv6-7.':'Por lo que yo sé, python-libtorrent se puede compilar para ARMv6-7.',
 | 
					 | 
				
			||||||
            'You should search for "OneEvil\'s OpenELEC libtorrent" or use Ace Stream.':'Se debe buscar "OpenELEC libtorrent de OneEvil" o utilizar Ace Stream',
 | 
					 | 
				
			||||||
            'Please use install Ace Stream APK and choose it in Settings.':'Instale APK de Ace Stream y selecciónelo en "Ajustes"',
 | 
					 | 
				
			||||||
            'It is possible to compile python-libtorrent for Android, but I don\'t know how.':'Es posible compilar python-libtorrent para Android, pero no sé como hacerlo.',
 | 
					 | 
				
			||||||
            'It is possible to compile python-libtorrent for OS X.':'Es posible compilar python-libtorrent para Mac OS X.',
 | 
					 | 
				
			||||||
            'But you would have to do it by yourself, there is some info on github.com.':'Pero debe hacerlo por sí mismo. Hay alguna información en github.com.',
 | 
					 | 
				
			||||||
            'It is NOT possible to compile python-libtorrent for iOS.':'No es posible compilar python-libtorrent para iOS',
 | 
					 | 
				
			||||||
            'But you can use torrent-client control functions.':'Pero se pueden utilizar las funciones de control del cliente de BitTorrent',
 | 
					 | 
				
			||||||
            'I added custom searchers to Torrenter v2!':'Se han añadido buscadores personalizados a Torrenter v2',
 | 
					 | 
				
			||||||
            'Now you can use your login on trackers or write and install your own searcher!':'Ahora puede identificarse en rastreadores o crear e instalar su propio buscador',
 | 
					 | 
				
			||||||
            'Would you like to install %s from "MyShows.me Kodi Repo" in Programs section?':'¿Le gustaría instalar %s desde el repositorio "MyShows.me", sección Programas?',
 | 
					 | 
				
			||||||
            'Open installation window?':'¿Abrir ventana de instalación?',
 | 
					 | 
				
			||||||
            'Android Support':'Soporte de Android',
 | 
					 | 
				
			||||||
            'Android has no temprorary folder':'Android no tiene carpeta temporal',
 | 
					 | 
				
			||||||
            'Please specify storage folder in Settings!':'Especifique la carpeta de almacenamiento en "Ajustes"',
 | 
					 | 
				
			||||||
            'You have no installed or active searchers! More info in Search Control Window!':'No se han instalado o activado buscadores. Tiene más información en Control de búsquedas',
 | 
					 | 
				
			||||||
            'Please contact DiMartino on kodi.tv forum. We compiled python-libtorrent for Android,':'Póngase en contacto con DiMartino en el foro de kodi.tv. Hemos compilado python-libtorren para Android,',
 | 
					 | 
				
			||||||
            'but we need your help with some Torrent is seeding. To stop it use Download Status.s on different processors.':'pero necesitamos su ayuda con algún torrent que se comparte. Para detenerlo utilice Estado de la descarga. En diferentes procesadores.',
 | 
					 | 
				
			||||||
            'We added Android ARM full support to Torrenter v2!':'Hemos añadido compatibilidad completa para Android ARM a Torrenter v2',
 | 
					 | 
				
			||||||
            'I deleted pre-installed ones, install them in Search Control Window!':'Se eliminaron los que estaban preinstalados; instálelos desde Control de búsquedas',
 | 
					 | 
				
			||||||
            'Torrenter didn\'t find %s searcher':'Torrenter no ha encontrado el buscador %s',
 | 
					 | 
				
			||||||
            'Torrenter Tracker Install':'Instalación de rastreador de Torrenter',
 | 
					 | 
				
			||||||
            'Ask to save':'Preguntar para guardar',
 | 
					 | 
				
			||||||
            'Would you like to save this file?':'¿Le gustaría guardar este archivo?',
 | 
					 | 
				
			||||||
            'Your storage path is not writable or not local! Please change it in settings!':'La ruta del almacén está protegida contra escritura o no es local. Cámbiela en "Ajustes"',
 | 
					 | 
				
			||||||
            'Upgrade advancedsettings.xml':'Actualizar archivo advancedsettings.xml',
 | 
					 | 
				
			||||||
            'We would like to set some advanced settings for you!':'Nos gustaría efectuar algunos ajustes avanzados por usted',
 | 
					 | 
				
			||||||
            'Do it!':'Hazlo',
 | 
					 | 
				
			||||||
            'Please, restart Kodi now!':'Reinicie Kodi',
 | 
					 | 
				
			||||||
            './ (Root folder)':'./ (Carpeta de root)',
 | 
					 | 
				
			||||||
            'Opening torrent file':'Abriendo archivo torrent',
 | 
					 | 
				
			||||||
            'New player to Torrenter v2 - Torrent2HTTP! It should be faster, stable and better with Android, also seeking works in it.':'Nuevo reproductor para Torrenter v2 - Torrent2HTTP. Debe ser más rápido, estable y mejor en Android; además, con él funcionan los intercambios.',
 | 
					 | 
				
			||||||
            'Would you like to try it?':'¿Le gustaría probarlo?',
 | 
					 | 
				
			||||||
            'Torrent2HTTP enabled! Can be changed in Settings.':'Se ha activado Torrent2HTTP. Puede cambiarse en "Ajustes".',
 | 
					 | 
				
			||||||
            'Seeking':'Compartiendo',
 | 
					 | 
				
			||||||
            'Would you like to resume from %s?':'¿Le gustaría reanudar desde %s?',
 | 
					 | 
				
			||||||
            'Seeking is working only with player Torrent2HTTP.':'Compartir funciona solamente con el reproductor Torrent2HTTP.',
 | 
					 | 
				
			||||||
            'Play (from %s)':'Reproducir desde %s',
 | 
					 | 
				
			||||||
            'Play (from start)':'Reproducir desde el inicio',
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	'he': {
 | 
					 | 
				
			||||||
            'Seeds searching.': 'חיפוש זורעים',
 | 
					            'Seeds searching.': 'חיפוש זורעים',
 | 
				
			||||||
            'Please Wait': 'המתן',
 | 
					            'Please Wait': 'המתן',
 | 
				
			||||||
            'Information': 'מידע',
 | 
					            'Information': 'מידע',
 | 
				
			||||||
@ -330,7 +71,7 @@ def localize(text):
 | 
				
			|||||||
            'Torrent Downloading': 'טורנט בהורדה',
 | 
					            'Torrent Downloading': 'טורנט בהורדה',
 | 
				
			||||||
            'Auth expired, please relogin': 'Auth expired, please relogin',
 | 
					            'Auth expired, please relogin': 'Auth expired, please relogin',
 | 
				
			||||||
            'Storage': 'אחסון',
 | 
					            'Storage': 'אחסון',
 | 
				
			||||||
            'Storage has been cleared': 'אחסון נוקה',
 | 
					            'Storage was cleared': 'אחסון נוקה',
 | 
				
			||||||
            'Clear Storage': 'נקה אחסון',
 | 
					            'Clear Storage': 'נקה אחסון',
 | 
				
			||||||
            'Popular': 'פופולארי',
 | 
					            'Popular': 'פופולארי',
 | 
				
			||||||
            'Views': 'צפיות',
 | 
					            'Views': 'צפיות',
 | 
				
			||||||
@ -483,7 +224,7 @@ def localize(text):
 | 
				
			|||||||
            'Unpause':'אל תפסיק',
 | 
					            'Unpause':'אל תפסיק',
 | 
				
			||||||
            'Pause':'הפסק',
 | 
					            'Pause':'הפסק',
 | 
				
			||||||
            'Delete':'מחק',
 | 
					            'Delete':'מחק',
 | 
				
			||||||
            'Open':'פתח',
 | 
					            'Open (no return)':'פתח',
 | 
				
			||||||
            '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!':'מיין הכל',
 | 
				
			||||||
@ -549,280 +290,7 @@ def localize(text):
 | 
				
			|||||||
            'Play (from %s)':'%s נגן מ',
 | 
					            'Play (from %s)':'%s נגן מ',
 | 
				
			||||||
            'Play (from start)':'נגן מהתחלה',
 | 
					            'Play (from start)':'נגן מהתחלה',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    	'hu': {
 | 
					 | 
				
			||||||
            'Seeds searching.': 'Seederek keresése.',
 | 
					 | 
				
			||||||
            'Please Wait': 'Kérlek várj',
 | 
					 | 
				
			||||||
            'Information': 'Információ',
 | 
					 | 
				
			||||||
            'Torrent downloading is stopped.': 'A torrent letöltése befejeződött.',
 | 
					 | 
				
			||||||
            'Search': 'Keresés',
 | 
					 | 
				
			||||||
            'Seeds': 'Seederek',
 | 
					 | 
				
			||||||
            'Peers': 'Kapcsolatok',
 | 
					 | 
				
			||||||
            'Materials are loading now.': 'A tartalmak most töltődnek.',
 | 
					 | 
				
			||||||
            'Search Phrase': 'Keresés kifejezésre',
 | 
					 | 
				
			||||||
            'Magnet-link is converting': 'Magnet-link konvertálása',
 | 
					 | 
				
			||||||
            'Error': 'Hiba',
 | 
					 | 
				
			||||||
            'Your library out of date and can\'t save magnet-links.': 'A könyvtár elavult, nem lehet lementeni a magnet-linket.',
 | 
					 | 
				
			||||||
            'Bookmarks': 'Könyvjelzők',
 | 
					 | 
				
			||||||
            'Logout': 'Kijelentkezés',
 | 
					 | 
				
			||||||
            'Login': 'Bejelentkezés',
 | 
					 | 
				
			||||||
            'Recent Materials': 'Jelenlegi tartalmak',
 | 
					 | 
				
			||||||
            'Register': 'Regisztráció',
 | 
					 | 
				
			||||||
            'Bookmark': 'Könyvjelző',
 | 
					 | 
				
			||||||
            'Item successfully added to Bookmarks': 'Az elem sikeresen hozzáadva a Könyvjelzőkhöz',
 | 
					 | 
				
			||||||
            'Item successfully removed from Bookmarks': 'Az elem sikeresen törölve a Könyvjelzőkből',
 | 
					 | 
				
			||||||
            'Bookmark not added': 'A könyvjelző nem lett hozzáadva',
 | 
					 | 
				
			||||||
            'Bookmark not removed': 'A könyvjelző nem lett törölve',
 | 
					 | 
				
			||||||
            'Add To Bookmarks': 'Hozzáadás a Könyvjelzőkhöz',
 | 
					 | 
				
			||||||
            'Remove From Bookmarks': 'Eltávolítás a Könyvjelzőkből',
 | 
					 | 
				
			||||||
            'Auth': 'Hitelesítés',
 | 
					 | 
				
			||||||
            'Already logged in': 'Már be vagy jelentkezve',
 | 
					 | 
				
			||||||
            'Input Email (for password recovery):': 'E-mail bevitel (jelszó helyreállításához):',
 | 
					 | 
				
			||||||
            'Input Email:': 'E-mail bevitel:',
 | 
					 | 
				
			||||||
            'Input Password (6+ symbols):': 'Jelszó bevitel (6+ karakter):',
 | 
					 | 
				
			||||||
            'Input Password:': 'Jelszó bevitel:',
 | 
					 | 
				
			||||||
            'Login successfull': 'Bejelentkezés sikeres',
 | 
					 | 
				
			||||||
            'Login failed': 'Bejelentkezés sikertelen',
 | 
					 | 
				
			||||||
            'User not logged in': 'A felhasználó nincs bejelentkezve',
 | 
					 | 
				
			||||||
            'User successfully logged out': 'A felhasználó sikeresen kijelentkezett',
 | 
					 | 
				
			||||||
            'Preloaded: ': 'Előtöltés: ',
 | 
					 | 
				
			||||||
            'Do you want to STOP torrent downloading and seeding?': 'Be akarod fejezni a torrent letöltését és seedelését?',
 | 
					 | 
				
			||||||
            'Torrent Downloading': 'Torrent letöltése',
 | 
					 | 
				
			||||||
            'Auth expired, please relogin': 'Hitelesítés lejárt, kérlek jelentkezz be újra',
 | 
					 | 
				
			||||||
            'Storage': 'Tárolóhely',
 | 
					 | 
				
			||||||
            'Storage has been cleared': 'A tárolóhely megtisztítva',
 | 
					 | 
				
			||||||
            'Clear Storage': 'Tárolóhely Megtisztítása',
 | 
					 | 
				
			||||||
            'Popular': 'Népszerű',
 | 
					 | 
				
			||||||
            'Views': 'Nézetek',
 | 
					 | 
				
			||||||
            'Uploading': 'Feltöltés',
 | 
					 | 
				
			||||||
            'Download': 'Letöltés',
 | 
					 | 
				
			||||||
            'Input symbols from CAPTCHA image:': 'Szimbólumok bevitele a CAPTCHA képről:',
 | 
					 | 
				
			||||||
            'Please, rate watched video:': 'Kérlek, értékeld a megnézett videót:',
 | 
					 | 
				
			||||||
            'Bad': 'Rossz',
 | 
					 | 
				
			||||||
            'So-So': 'Elmegy',
 | 
					 | 
				
			||||||
            'Good': 'Jó',
 | 
					 | 
				
			||||||
            'Ratings': 'Értékelések',
 | 
					 | 
				
			||||||
            'Rating': 'Értékelés',
 | 
					 | 
				
			||||||
            'Retry': 'Újra',
 | 
					 | 
				
			||||||
            '%ds has left': '%ds van hátra',
 | 
					 | 
				
			||||||
            'File failed to play! Do you want to RETRY and buffer more?': 'A fájl lejátszása hibába ütközött. Újra akarod indítani és többet bufferelni?',
 | 
					 | 
				
			||||||
            'High Priority Files': 'Magas prioritású fájlok',
 | 
					 | 
				
			||||||
            'Skip All Files': 'Összes fájl kihagyása',
 | 
					 | 
				
			||||||
            'Start': 'Indít',
 | 
					 | 
				
			||||||
            'Stop': 'Megállít',
 | 
					 | 
				
			||||||
            'Play':'Lejátszás',
 | 
					 | 
				
			||||||
            'High Priority': 'Magas prioritás',
 | 
					 | 
				
			||||||
            'Skip File': 'Fájl kihagyása',
 | 
					 | 
				
			||||||
            'Remove': 'Eltávolítás',
 | 
					 | 
				
			||||||
            'Remove with files': 'Eltávolítás a fájlokkal együtt',
 | 
					 | 
				
			||||||
            'Play File': 'Fájl lejátszása',
 | 
					 | 
				
			||||||
            'Start All Files': 'Összes fájl elindítása',
 | 
					 | 
				
			||||||
            'Stop All Files': 'Összes fájl megállítása',
 | 
					 | 
				
			||||||
            'Torrent-client Browser': 'Torrentkliens Böngésző',
 | 
					 | 
				
			||||||
            'Remote Torrent-client': 'Távoli torrentkliens',
 | 
					 | 
				
			||||||
            'You didn\'t set up replacement path in setting.': 'Nem állítottál be helyettesítő elérési utat a beállításokban.',
 | 
					 | 
				
			||||||
            'For example /media/dl_torr/ to smb://SERVER/dl_torr/. Setup now?': 'Például /media/dl_torr/ a smb://SERVER/dl_torr/ - hez. Beállítod most?',
 | 
					 | 
				
			||||||
            'Manual Torrent-client Path Edit': 'Kézi torrentkliens elérési út módosítás',
 | 
					 | 
				
			||||||
            'Choose .torrent in video library': '.torrent kiválasztása a videó könyvtárban',
 | 
					 | 
				
			||||||
            '.torrent Player': '.torrent Lejátszó',
 | 
					 | 
				
			||||||
            'Choose directory:': 'Könyvtár kiválasztása:',
 | 
					 | 
				
			||||||
            'Starting download next episode!': 'Elindul a következő epizód letöltése!',
 | 
					 | 
				
			||||||
            'Choose in torrent-client:': 'Kiválasztás a torrentkliensben:',
 | 
					 | 
				
			||||||
            'Search Control Window': 'Keresést Kezelő Ablak',
 | 
					 | 
				
			||||||
            'Magnet-link (magnet:...)': 'Magnet-link (magnet:...)',
 | 
					 | 
				
			||||||
            'Not a magnet-link!': 'Ez nem magnet-link!',
 | 
					 | 
				
			||||||
            'Magnet-link Player': 'Magnet-link Lejátszó',
 | 
					 | 
				
			||||||
            'UNKNOWN STATUS': 'ISMERETLEN STÁTUSZ',
 | 
					 | 
				
			||||||
            'Checking preloaded files...': 'Előtöltött fájlok ellenőrzése...',
 | 
					 | 
				
			||||||
            'Waiting for website response...': 'Várakozás a weboldal válaszára...',
 | 
					 | 
				
			||||||
            'Search and cache information for:': 'Információ keresése és gyorsítótárazása:',
 | 
					 | 
				
			||||||
            'Open Torrent': 'Torrent megnyitása',
 | 
					 | 
				
			||||||
            'Torrent list is empty.': 'A torrent lista üres.',
 | 
					 | 
				
			||||||
            'Content Lists': 'Tartalmak Listája',
 | 
					 | 
				
			||||||
            'Canceled by User': 'Leállítva felhasználó által',
 | 
					 | 
				
			||||||
            'Do you want to search and cache full metadata + arts?': 'Szeretnéd lekérni és gyorsítótárazni a metaadatokat és a képeket?',
 | 
					 | 
				
			||||||
            'This vastly decreases load speed, but you will be asked to download premade bases!': 'Ez jelentősen csökkenti a betöltési sebességet, megkérünk, hogy töltsd le az előre elkészített adatbázisokat!',
 | 
					 | 
				
			||||||
            'Do you want to preload full metadata?': 'Előtöltöd a metaadatokat?',
 | 
					 | 
				
			||||||
            'It is highly recommended!': 'Ez erősen ajánlott!',
 | 
					 | 
				
			||||||
            'TV Shows': 'Sorozatok',
 | 
					 | 
				
			||||||
            'Cartoons': 'Rajzfilmek',
 | 
					 | 
				
			||||||
            'Anime': 'Anime',
 | 
					 | 
				
			||||||
            'Most Recent': 'Legújabb',
 | 
					 | 
				
			||||||
            'Top 250 Movies': 'Top 250 Filmek',
 | 
					 | 
				
			||||||
            'Top All Time': 'Top Mindenkori',
 | 
					 | 
				
			||||||
            'by Genre': 'Műfaj alapján',
 | 
					 | 
				
			||||||
            'by Year': 'Évszám alapján',
 | 
					 | 
				
			||||||
            'Action': 'Akció',
 | 
					 | 
				
			||||||
            'Adventure': 'Kaland',
 | 
					 | 
				
			||||||
            'Animation': 'Animációs',
 | 
					 | 
				
			||||||
            'Biography': 'Életrajzi',
 | 
					 | 
				
			||||||
            'Comedy': 'Vígjáték',
 | 
					 | 
				
			||||||
            'Crime': 'Bűnügyi',
 | 
					 | 
				
			||||||
            'Documentary': 'Dokumentum',
 | 
					 | 
				
			||||||
            'Drama': 'Dráma',
 | 
					 | 
				
			||||||
            'Family': 'Családi',
 | 
					 | 
				
			||||||
            'Fantasy': 'Fantasy',
 | 
					 | 
				
			||||||
            'Film-Noir': 'Film-Noir',
 | 
					 | 
				
			||||||
            'History': 'Történelmi',
 | 
					 | 
				
			||||||
            'Horror': 'Horror',
 | 
					 | 
				
			||||||
            'Music': 'Zenei',
 | 
					 | 
				
			||||||
            'Musical': 'Musical',
 | 
					 | 
				
			||||||
            'Mystery': 'Misztikus',
 | 
					 | 
				
			||||||
            'Romance': 'Romantikus',
 | 
					 | 
				
			||||||
            'Sci-Fi': 'Sci-Fi',
 | 
					 | 
				
			||||||
            'Short': 'Rövidfilm',
 | 
					 | 
				
			||||||
            'Sport': 'Sport',
 | 
					 | 
				
			||||||
            'Thriller': 'Thriller',
 | 
					 | 
				
			||||||
            'War': 'Háborús',
 | 
					 | 
				
			||||||
            'Western': 'Western',
 | 
					 | 
				
			||||||
            '[B]by Site[/B]': '[B]Weboldal alapján[/B]',
 | 
					 | 
				
			||||||
            'Cartoons Series': 'Rajzfilmsorozatok',
 | 
					 | 
				
			||||||
            'Cartoons Short': 'Rövid rajzfilmek',
 | 
					 | 
				
			||||||
            'Male': 'Férfi',
 | 
					 | 
				
			||||||
            'Female': 'Női',
 | 
					 | 
				
			||||||
            'Russia & USSR': 'Oroszország & Szovjetunió',
 | 
					 | 
				
			||||||
            'Next Page': 'Következő oldal',
 | 
					 | 
				
			||||||
            'Previous Page': 'Előző oldal',
 | 
					 | 
				
			||||||
            'Russian Movies': 'Orosz filmek',
 | 
					 | 
				
			||||||
            'israeli Movies': 'Izraeli fimek',
 | 
					 | 
				
			||||||
            'hebdub movies': 'hebdub filmek',
 | 
					 | 
				
			||||||
            'Movies': 'Filmek',
 | 
					 | 
				
			||||||
            'High Resolution Movies': 'HD filmek',
 | 
					 | 
				
			||||||
            '3D Movies': '3D filmek',
 | 
					 | 
				
			||||||
            'Movies [Bluray]': 'Filmek [Bluray]',				
 | 
					 | 
				
			||||||
            'Anime Film': 'Anime filmek',
 | 
					 | 
				
			||||||
            'Anime Series': 'Anime sorozatok',
 | 
					 | 
				
			||||||
            'Can\'t download torrent, probably no seeds available.': 'Nem lehet letölteni a torrentet, valószínűleg nincsenek elérhető seederek.',
 | 
					 | 
				
			||||||
            'Personal List': 'Saját lista',
 | 
					 | 
				
			||||||
            'Add to %s': 'Hozzáadás ehhez %s',
 | 
					 | 
				
			||||||
            'Delete from %s': 'Eltávolítás innen %s',
 | 
					 | 
				
			||||||
            'Added!': 'Hozzáadva!',
 | 
					 | 
				
			||||||
            'Deleted!': 'Eltávolítva!',
 | 
					 | 
				
			||||||
            'Search History': 'Keresési Előzmények',
 | 
					 | 
				
			||||||
            ' History ':' Előzmények ',
 | 
					 | 
				
			||||||
            'Torrent History':'Torrent Előzmények',
 | 
					 | 
				
			||||||
            'Watched History':'Megtekintett Előzmények',
 | 
					 | 
				
			||||||
            'Favourites': 'Kedvencek',
 | 
					 | 
				
			||||||
            'Favourites SH': 'Kedvencek SH',
 | 
					 | 
				
			||||||
            'Clear %s': 'Tisztítás %s',
 | 
					 | 
				
			||||||
            'Clear!': 'Tisztítás!',
 | 
					 | 
				
			||||||
            'kb/s': 'kb/s',
 | 
					 | 
				
			||||||
            'Queued': 'Sorba állítva',
 | 
					 | 
				
			||||||
            'Checking': 'Ellenőrzés',
 | 
					 | 
				
			||||||
            'Downloading metadata': 'Metaadatok letöltése',
 | 
					 | 
				
			||||||
            'Downloading': 'Letöltés',
 | 
					 | 
				
			||||||
            'Finished': 'Befejezve',
 | 
					 | 
				
			||||||
            'Seeding': 'Seedelés',
 | 
					 | 
				
			||||||
            'Allocating': 'Összeállítás',
 | 
					 | 
				
			||||||
            'Allocating file & Checking resume': 'Fájl összeállítása és folytatás ellenőrzése',
 | 
					 | 
				
			||||||
            'For Kids': 'Gyerekek számára',
 | 
					 | 
				
			||||||
            'Adult': 'Felnőtt',
 | 
					 | 
				
			||||||
            'Does not support magnet links!': 'Nem támogatja a magnet-linkeket!',
 | 
					 | 
				
			||||||
            'Reset All Cache DBs': 'Összes gyorsítótár adatbázis visszaállítása',
 | 
					 | 
				
			||||||
            '[B]Search[/B]': '[B]Keresés[/B]',
 | 
					 | 
				
			||||||
            'You can always restart this by deleting DBs via Context Menu': 'Mindig visszaállíthatja az adatbázis törlésével a helyi menün keresztül',
 | 
					 | 
				
			||||||
            'Your preloaded databases are outdated!': 'Az előtöltött adatbázisok elavultak!',
 | 
					 | 
				
			||||||
            'Do you want to download new ones right now?': 'Szeretnéd letölteni az újakat most?',
 | 
					 | 
				
			||||||
            'Individual Tracker Options':'Egyéni tracker beállítások',
 | 
					 | 
				
			||||||
            'Downloading and copy subtitles. Please wait.':'Feliratok letöltése és másolása. Kérlek, várj.',
 | 
					 | 
				
			||||||
            'International Check - First Run':'International ellenőrzés - első futtatás',
 | 
					 | 
				
			||||||
            'Delete Russian stuff?':'Orosz tartalom törlése?',
 | 
					 | 
				
			||||||
            'Save to path':'Mentés a mappába',
 | 
					 | 
				
			||||||
            'Return Russian stuff':'Orosz tartalom visszaállítása',
 | 
					 | 
				
			||||||
            '%d files have been returned':'%d fájlok visszaállítva',
 | 
					 | 
				
			||||||
            'Download via T-client':'Letöltés T-kliensen keresztül',
 | 
					 | 
				
			||||||
            'Download via Libtorrent':'Letöltés Libtorrenten keresztül',
 | 
					 | 
				
			||||||
            'Download Status':'Letöltési Állapot',
 | 
					 | 
				
			||||||
            'Download has not finished yet':'A letöltés még nem fejeződött be',
 | 
					 | 
				
			||||||
            'Stopped and Deleted!':'Leállítva és eltávolítva!',
 | 
					 | 
				
			||||||
            'Unpaused!':'Újra elindítva!',
 | 
					 | 
				
			||||||
            'Paused!':'Szünetelve!',
 | 
					 | 
				
			||||||
            'Stopped!':'Megállítva!',
 | 
					 | 
				
			||||||
            'Started!':'Elindítva!',
 | 
					 | 
				
			||||||
            'Delete and Stop':'Megállít és eltávolít',
 | 
					 | 
				
			||||||
            'Unpause':'Újra elindít',
 | 
					 | 
				
			||||||
            'Pause':'Szüneteltet',
 | 
					 | 
				
			||||||
            'Delete':'Eltávolít',
 | 
					 | 
				
			||||||
            'Open':'Megnyitás',
 | 
					 | 
				
			||||||
            'Torrent is seeding. To stop it use Download Status.':'Torrent seedelés alatt. Ahhoz, hogy megállítsd használd a Letöltési Állapotot.',
 | 
					 | 
				
			||||||
            'Start All':'Összes elindítása',
 | 
					 | 
				
			||||||
            'Started All!':'Összes elindítva!',
 | 
					 | 
				
			||||||
            'Stopped All!':'Összes megállítva!',
 | 
					 | 
				
			||||||
            'Stop All':'Összes megállítása',
 | 
					 | 
				
			||||||
            'Keyboard':'Billentyűzet',
 | 
					 | 
				
			||||||
            'Copy Files in Root':'Fájlok másolása a Rendszerkönyvtárba',
 | 
					 | 
				
			||||||
            'Copied %d files!':'%d fájl átmásolva!',
 | 
					 | 
				
			||||||
            'Add to MyShows.ru':'Hozzáadás MyShows.ru-hoz',
 | 
					 | 
				
			||||||
            'Return to MyShows.ru':'Visszatérés a MyShows.ru-hoz',
 | 
					 | 
				
			||||||
            'Search results:':'Keresési eredmények:',
 | 
					 | 
				
			||||||
            'by Seeders':'Seederek alapján',
 | 
					 | 
				
			||||||
            'by Date':'Dátum alapján',
 | 
					 | 
				
			||||||
            'Sort':'Rendezés',
 | 
					 | 
				
			||||||
            'Close':'Bezár',
 | 
					 | 
				
			||||||
            'Views:':'Nézetek:',
 | 
					 | 
				
			||||||
            'Rating:':'Értékelés:',
 | 
					 | 
				
			||||||
            'Information not found!':'Nem található információ!',
 | 
					 | 
				
			||||||
            'Choose searcher':'Válassz keresőt',
 | 
					 | 
				
			||||||
            'python-libtorrent Not Found':'python-libtorrent nem található',
 | 
					 | 
				
			||||||
            'Windows has static compiled python-libtorrent included.':'A Windows statikusan fordított python-libtorrentet tartalmaz.',
 | 
					 | 
				
			||||||
            'You should install "script.module.libtorrent" from "MyShows.me Kodi Repo"':'Telepítsd a "script.module.libtorrent"-et a "MyShows.me Kodi Repo"-ból',
 | 
					 | 
				
			||||||
            'Linux x64 has not static compiled python-libtorrent included.':'A Linux x64 statikusan fordított python-libtorrentet nem tartalmaz.',
 | 
					 | 
				
			||||||
            'You should install it by "sudo apt-get install python-libtorrent"':'Telepítsd ezzel a paranccsal "sudo apt-get install python-libtorrent"',
 | 
					 | 
				
			||||||
            'Linux has static compiled python-libtorrent included but it didn\'t work.':'A Linux statikusan fordított python-libtorrentet tartalmaz de nem működik.',
 | 
					 | 
				
			||||||
            'As far as I know you can compile python-libtorrent for ARMv6-7.':'Ahogy én tudom, le lehet fordítani a python-libtorrentet ARMv6-7-ra',
 | 
					 | 
				
			||||||
            'You should search for "OneEvil\'s OpenELEC libtorrent" or use Ace Stream.':'Keress rá "OneEvil\'s OpenELEC libtorrent"-re vagy használj Ace Streamet',
 | 
					 | 
				
			||||||
            'Please use install Ace Stream APK and choose it in Settings.':'Kérlek használj Ace Stream APK-t és válaszd ki a beállításokban.',
 | 
					 | 
				
			||||||
            'It is possible to compile python-libtorrent for Android, but I don\'t know how.':'Lehetséges, hogy lefordítható a python-libtorrent Android-ra, de nem tudom hogyan.',
 | 
					 | 
				
			||||||
            'It is possible to compile python-libtorrent for OS X.':'Lehetséges, hogy lefordítható a python-libtorrent OS X-re.',
 | 
					 | 
				
			||||||
            'But you would have to do it by yourself, there is some info on github.com.':'De ezt magadnak kell megcsinálnod, van néhány infó erről a github.com-on.',
 | 
					 | 
				
			||||||
            'It is NOT possible to compile python-libtorrent for iOS.':'iOS-re nem lehet lefordítani a python-libtorrentet.',
 | 
					 | 
				
			||||||
            'But you can use torrent-client control functions.':'De a torrentkliens kezelőt funkciót tudod használni.',
 | 
					 | 
				
			||||||
            'I added custom searchers to Torrenter v2!':'Hozzáadtam egyéni keresőket a Torrenter v2-höz!',
 | 
					 | 
				
			||||||
            'Now you can use your login on trackers or write and install your own searcher!':'Most már be tudsz lépni a trackerekre, vagy megírhatod és feltelepítheted a saját keresődet!',
 | 
					 | 
				
			||||||
            'Would you like to install %s from "MyShows.me Kodi Repo" in Programs section?':'Szeretnéd telepíteni %s a "MyShows.me Kodi Repo"-ból?',
 | 
					 | 
				
			||||||
            'Open installation window?':'Telepítő ablak megnyitása?',
 | 
					 | 
				
			||||||
            'Android Support':'Android támogatás',
 | 
					 | 
				
			||||||
            'Android has no temprorary folder':'Az Android nem rendelkezik ideiglenes mappával',
 | 
					 | 
				
			||||||
            'Please specify storage folder in Settings!':'Kérlek add meg a tárolóhely mappáját a beállításokban!',
 | 
					 | 
				
			||||||
            'You have no installed or active searchers! More info in Search Control Window!':'Nincsenek telepített vagy aktív keresők! Több információ a Keresést Kezelő Abalakban.',
 | 
					 | 
				
			||||||
            'Please contact DiMartino on kodi.tv forum. We compiled python-libtorrent for Android,':'Kérünk lépj kapcsolatba DiMartino-val a kodi.tv fórumon. Lefordítottuk a python-libtorrentet Androidhoz,',
 | 
					 | 
				
			||||||
            'but we need your help with some tests on different processors.':'de szükségünk lesz még néhány tesztre különböző processzorokon.',
 | 
					 | 
				
			||||||
            'We added Android ARM full support to Torrenter v2!':'A Torrenter v2 számara teljesen támogatottá tettük az Android ARM-t!',
 | 
					 | 
				
			||||||
            'I deleted pre-installed ones, install them in Search Control Window!':'Töröltem az összes előre telepítettet, telepítsd őket a Keresést Kezelő Ablakban!',
 | 
					 | 
				
			||||||
            'Torrenter didn\'t find %s searcher':'A Torrenter nem találja a %s keresőt',
 | 
					 | 
				
			||||||
            'Torrenter Tracker Install':'Torrent tracker telepítés',
 | 
					 | 
				
			||||||
            'Ask to save':'Mentés kérése',
 | 
					 | 
				
			||||||
            'Would you like to save this file?':'El szeretnéd menteni ez a fájlt?',
 | 
					 | 
				
			||||||
            'Your storage path is not writable or not local! Please change it in settings!':'A tárolóhely elérési útja nem írható vagy nem elérhető! Kérlek változtatsd meg a beállításokban!',
 | 
					 | 
				
			||||||
            'Upgrade advancedsettings.xml':'advancedsettings.xml frissítése',
 | 
					 | 
				
			||||||
            'We would like to set some advanced settings for you!':'Be szeretnénk állítani néhány haladó beállítást!',
 | 
					 | 
				
			||||||
            'Do it!':'Csináld!',
 | 
					 | 
				
			||||||
            'Please, restart Kodi now!':'Kérlek, indítsd újra a Kodit, most.',
 | 
					 | 
				
			||||||
            './ (Root folder)':'./ (Rendszerkönyvtár)',
 | 
					 | 
				
			||||||
            'Opening torrent file':'Torrent fájl megnyitása',
 | 
					 | 
				
			||||||
            'New player to Torrenter v2 - Torrent2HTTP! It should be faster, stable and better with Android, also seeking works in it.':'Új lejátszó a Torrenter v2-höz - Torrent2HTTP: Gyorsabb, stabilabb és jobb Androiddal, valamint a keresés is működik vele.',
 | 
					 | 
				
			||||||
            'Would you like to try it?':'Ki szeretnéd próbálni?',
 | 
					 | 
				
			||||||
            'Torrent2HTTP enabled! Can be changed in Settings.':'Torrent2HTTP engedélyezve! Ezen a beállításokban tudsz változtatni.',
 | 
					 | 
				
			||||||
            'Seeking':'Keresés',
 | 
					 | 
				
			||||||
            'Would you like to resume from %s?':'Szeretnéd folytatni innen: %s?',
 | 
					 | 
				
			||||||
            'Seeking is working only with player Torrent2HTTP.':'A keresés csak a Torrent2HTTP lejátszóval működik.',
 | 
					 | 
				
			||||||
            'Play (from %s)':'Lejátszás (innen %s)',
 | 
					 | 
				
			||||||
            'Play (from start)':'Lejátszás (az elejétől)',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        'ru': {
 | 
					        'ru': {
 | 
				
			||||||
            'Torrenter has a better view style for Kodi 17 default skin.':'У Torrenter есть оптимизированный вид под новый скин Kodi 17.',
 | 
					 | 
				
			||||||
            'is recommended for Kodi 17 users and now out of beta.': 'рекомендовано пользователям Kodi 17 и вышло из беты.',
 | 
					 | 
				
			||||||
            'You can disable it usage in Settings.':'Его можно отключить в настройках плагина.',
 | 
					 | 
				
			||||||
            'Move Up': 'Вверх',
 | 
					 | 
				
			||||||
            'Torrenter Search Window': 'Окно Поиска Torrenter',
 | 
					 | 
				
			||||||
            'Cancel': 'Отмена',
 | 
					 | 
				
			||||||
            'Clear History': 'Очистить Историю',
 | 
					 | 
				
			||||||
            'Play (with seek)': 'Играть (перемотка)',
 | 
					 | 
				
			||||||
            'Mass Control':'Массовое Управление',
 | 
					 | 
				
			||||||
            'Info':'Инфо',
 | 
					 | 
				
			||||||
            'Delete torrent with files?':'Вы уверены, что хотите удалить торрент с файлами?',
 | 
					 | 
				
			||||||
            'Fav. / Unfav.':'Доб./удал. Избранное',
 | 
					 | 
				
			||||||
            'Search Window': 'Окно поиска',
 | 
					 | 
				
			||||||
            'Context menu': 'Контекстное меню',
 | 
					 | 
				
			||||||
            'Seeds searching.': 'Идёт поиск сидов.',
 | 
					            'Seeds searching.': 'Идёт поиск сидов.',
 | 
				
			||||||
            'Please Wait': 'Подождите',
 | 
					            'Please Wait': 'Подождите',
 | 
				
			||||||
            'Information': 'Информация',
 | 
					            'Information': 'Информация',
 | 
				
			||||||
@ -862,7 +330,7 @@ def localize(text):
 | 
				
			|||||||
            'Torrent Downloading': 'Загрузка торрента',
 | 
					            'Torrent Downloading': 'Загрузка торрента',
 | 
				
			||||||
            'Auth expired, please relogin': 'Авторизация истекла, пожалуйста войдите снова',
 | 
					            'Auth expired, please relogin': 'Авторизация истекла, пожалуйста войдите снова',
 | 
				
			||||||
            'Storage': 'Хранилище',
 | 
					            'Storage': 'Хранилище',
 | 
				
			||||||
            'Storage has been cleared': 'Хранилище очищено',
 | 
					            'Storage was cleared': 'Хранилище очищено',
 | 
				
			||||||
            'Clear Storage': 'Очистить хранилище',
 | 
					            'Clear Storage': 'Очистить хранилище',
 | 
				
			||||||
            'Popular': 'Популярное',
 | 
					            'Popular': 'Популярное',
 | 
				
			||||||
            'Views': 'Просмотров',
 | 
					            'Views': 'Просмотров',
 | 
				
			||||||
@ -908,7 +376,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': 'Отменено пользователем',
 | 
				
			||||||
@ -1015,7 +483,7 @@ def localize(text):
 | 
				
			|||||||
            'Unpause':'Возобновить',
 | 
					            'Unpause':'Возобновить',
 | 
				
			||||||
            'Pause':'Пауза',
 | 
					            'Pause':'Пауза',
 | 
				
			||||||
            'Delete':'Удалить',
 | 
					            'Delete':'Удалить',
 | 
				
			||||||
            'Open':'Открыть',
 | 
					            'Open (no return)':'Открыть (без возврата)',
 | 
				
			||||||
            '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!':'Все Запущены!',
 | 
				
			||||||
@ -1023,7 +491,6 @@ 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:':'Результаты поиска:',
 | 
				
			||||||
@ -1274,7 +741,7 @@ def localize(text):
 | 
				
			|||||||
            'Unpause':'Відновити',
 | 
					            'Unpause':'Відновити',
 | 
				
			||||||
            'Pause':'Пауза',
 | 
					            'Pause':'Пауза',
 | 
				
			||||||
            'Delete':'Видалити',
 | 
					            'Delete':'Видалити',
 | 
				
			||||||
            'Open':'Відкрити',
 | 
					            'Open (no return)':'Відкрити (без повернення)',
 | 
				
			||||||
            '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!':'Все запущене!',
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										41
									
								
								Player.py
									
									
									
									
									
								
							
							
						
						@ -30,7 +30,7 @@ import Downloader
 | 
				
			|||||||
import xbmcgui
 | 
					import xbmcgui
 | 
				
			||||||
import xbmcvfs
 | 
					import xbmcvfs
 | 
				
			||||||
import Localization
 | 
					import Localization
 | 
				
			||||||
from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, DownloadDB, get_ids_video, log, debug, foldername, ensure_str, loadsw_onstop, decode_str
 | 
					from functions import calculate, showMessage, clearStorage, WatchedHistoryDB, DownloadDB, get_ids_video, log, debug, foldername
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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,12 +166,8 @@ 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, self.torrentUrl, foldername(self.torrent.getContentList()[self.contentId]['title']), self.watchedTime, self.totalTime, self.contentId, self.fullSize / 1024 / 1024)
 | 
					                    WatchedHistoryDB().add(self.basename, 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?')
 | 
				
			||||||
@ -197,13 +193,11 @@ 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.'))
 | 
					                            self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
 | 
				
			||||||
            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.'))
 | 
					                            self.localize('Torrent downloading is stopped.'), forced=True)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        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
 | 
				
			||||||
@ -344,12 +338,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
 | 
				
			||||||
@ -373,7 +367,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.'))
 | 
					                        self.localize('Downloading and copy subtitles. Please wait.'), forced=True)
 | 
				
			||||||
            for ind, title in subs:
 | 
					            for ind, title in subs:
 | 
				
			||||||
                self.torrent.continueSession(ind)
 | 
					                self.torrent.continueSession(ind)
 | 
				
			||||||
            while iterator < 100:
 | 
					            while iterator < 100:
 | 
				
			||||||
@ -388,11 +382,10 @@ class TorrentPlayer(xbmc.Player):
 | 
				
			|||||||
                addition = os.path.dirname(title).lstrip(folder + os.sep).replace(os.sep, '.').replace(' ', '_').strip()
 | 
					                addition = os.path.dirname(title).lstrip(folder + os.sep).replace(os.sep, '.').replace(' ', '_').strip()
 | 
				
			||||||
                ext = temp.split('.')[-1]
 | 
					                ext = temp.split('.')[-1]
 | 
				
			||||||
                temp = temp[:len(temp) - len(ext) - 1] + '.' + addition + '.' + ext
 | 
					                temp = temp[:len(temp) - len(ext) - 1] + '.' + addition + '.' + ext
 | 
				
			||||||
                newFileName = os.path.join(ensure_str(os.path.dirname(decode_str(path))), ensure_str(temp))
 | 
					                newFileName = os.path.join(os.path.dirname(path), temp)
 | 
				
			||||||
                debug('[setup_subs]: {} {}'.format(newFileName, title))
 | 
					                debug('[setup_subs]: '+str((os.path.join(os.path.dirname(os.path.dirname(path)),title),newFileName)))
 | 
				
			||||||
                if not xbmcvfs.exists(newFileName):
 | 
					                if not xbmcvfs.exists(newFileName):
 | 
				
			||||||
                    fileName = os.path.join(ensure_str(os.path.dirname(os.path.dirname(decode_str(path)))), ensure_str(title))
 | 
					                    xbmcvfs.copy(os.path.join(os.path.dirname(os.path.dirname(path)), title), newFileName)
 | 
				
			||||||
                    xbmcvfs.copy(fileName, newFileName)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def onPlayBackStarted(self):
 | 
					    def onPlayBackStarted(self):
 | 
				
			||||||
        for f in self.on_playback_started:
 | 
					        for f in self.on_playback_started:
 | 
				
			||||||
@ -462,7 +455,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!'))
 | 
					                                    self.localize('Starting download next episode!'), forced=True)
 | 
				
			||||||
                        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)
 | 
				
			||||||
@ -472,10 +465,10 @@ class TorrentPlayer(xbmc.Player):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def _get_status_lines(self, s):
 | 
					    def _get_status_lines(self, s):
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            ensure_str(self.display_name),
 | 
					            self.display_name+'; '+self.torrent.get_debug_info('dht_state'),
 | 
				
			||||||
            "%.2f%% %s" % (s.progress * 100, self.localize(STATE_STRS[s.state])),
 | 
					            "%.2f%% %s; %s" % (s.progress * 100, self.localize(STATE_STRS[s.state]).decode('utf-8'), self.torrent.get_debug_info('trackers_sum')),
 | 
				
			||||||
            "D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1024, self.localize('kb/s'),
 | 
					            "D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1024, self.localize('kb/s').decode('utf-8'),
 | 
				
			||||||
                                             s.upload_rate / 1024, self.localize('kb/s'),
 | 
					                                             s.upload_rate / 1024, self.localize('kb/s').decode('utf-8'),
 | 
				
			||||||
                                             s.num_seeds, s.num_peers)
 | 
					                                             s.num_seeds, s.num_peers)
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,38 +18,30 @@
 | 
				
			|||||||
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import urllib
 | 
				
			||||||
 | 
					import urllib2
 | 
				
			||||||
 | 
					import cookielib
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from StringIO import StringIO
 | 
					from StringIO import StringIO
 | 
				
			||||||
import zlib
 | 
					import gzip
 | 
				
			||||||
import socket
 | 
					import socket
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proxy = int(sys.modules["__main__"].__settings__.getSetting("proxy"))
 | 
					 | 
				
			||||||
if proxy == 2:
 | 
					 | 
				
			||||||
    socks_ip = sys.modules["__main__"].__settings__.getSetting("socks_ip")
 | 
					 | 
				
			||||||
    from resources.proxy import socks
 | 
					 | 
				
			||||||
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, socks_ip,
 | 
					 | 
				
			||||||
                          int(sys.modules["__main__"].__settings__.getSetting("socks_port")))
 | 
					 | 
				
			||||||
    socket.socket = socks.socksocket
 | 
					 | 
				
			||||||
import urllib
 | 
					 | 
				
			||||||
import urllib2
 | 
					 | 
				
			||||||
import cookielib
 | 
					 | 
				
			||||||
import xbmcgui
 | 
					import xbmcgui
 | 
				
			||||||
import xbmc
 | 
					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
 | 
				
			||||||
    cookieJar = None
 | 
					    cookieJar = None
 | 
				
			||||||
    timeout_multi=int(sys.modules["__main__"].__settings__.getSetting("timeout"))
 | 
					    timeout_multi=int(sys.modules["__main__"].__settings__.getSetting("timeout"))
 | 
				
			||||||
 | 
					    proxy=int(sys.modules["__main__"].__settings__.getSetting("proxy"))
 | 
				
			||||||
    __plugin__='Empty v 0 0 0'
 | 
					    __plugin__='Empty v 0 0 0'
 | 
				
			||||||
    baseurl = 'site.com'
 | 
					    baseurl = 'site.com'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -111,25 +103,25 @@ class SearcherABC:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def makeRequest(self, url, data={}, headers={}):
 | 
					    def makeRequest(self, url, data={}, headers={}):
 | 
				
			||||||
        self.load_cookie()
 | 
					        self.load_cookie()
 | 
				
			||||||
        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
 | 
					        opener = None
 | 
				
			||||||
        if proxy == 1:
 | 
					        if self.proxy == 1:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                from resources.proxy import antizapret
 | 
					                from resources.proxy import antizapret
 | 
				
			||||||
                opener.add_handler(antizapret.AntizapretProxyHandler())
 | 
					                opener = urllib2.build_opener(antizapret.AntizapretProxyHandler(), urllib2.HTTPCookieProcessor(self.cookieJar))
 | 
				
			||||||
                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!')
 | 
				
			||||||
        # python ssl Context support - PEP 0466
 | 
					        #elif self.proxy == 2:
 | 
				
			||||||
        if 'https:' in url:
 | 
					        #    from resources.proxy import immunicity
 | 
				
			||||||
            ssl_context = ssl.create_default_context()
 | 
					        #    opener = urllib2.build_opener(immunicity.ImmunicityProxyHandler(), urllib2.HTTPCookieProcessor(self.cookieJar))
 | 
				
			||||||
            ssl_context.check_hostname = False
 | 
					        #    config = immunicity.config()
 | 
				
			||||||
            ssl_context.verify_mode = ssl.CERT_NONE
 | 
					        #    self.debug('[immunicity]: '+str(config["domains"]))
 | 
				
			||||||
            log('urllib2.HTTPSHandler(context=ssl_context)')
 | 
					        #    self.debug('[immunicity]: '+str(config["server"]))
 | 
				
			||||||
            opener.add_handler(urllib2.HTTPSHandler(context=ssl_context))
 | 
					        if not opener:
 | 
				
			||||||
 | 
					            opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
 | 
				
			||||||
        opener.addheaders = headers
 | 
					        opener.addheaders = headers
 | 
				
			||||||
        if 0 < len(data):
 | 
					        if 0 < len(data):
 | 
				
			||||||
            encodedData = urllib.urlencode(data)
 | 
					            encodedData = urllib.urlencode(data)
 | 
				
			||||||
@ -148,14 +140,13 @@ 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)
 | 
					            f = gzip.GzipFile(fileobj=buf)
 | 
				
			||||||
            text = decomp.decompress(buf.getvalue())
 | 
					            response = f.read()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            text = response.read()
 | 
					            response = response.read()
 | 
				
			||||||
        return text
 | 
					        return response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def askCaptcha(self, url):
 | 
					    def askCaptcha(self, url):
 | 
				
			||||||
        temp_dir = self.tempdir()
 | 
					        temp_dir = self.tempdir()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								addon.xml
									
									
									
									
									
								
							
							
						
						@ -1,5 +1,5 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
				
			||||||
<addon id="plugin.video.torrenter" name="Torrenter" version="2.6.7" provider-name="inpos">
 | 
					<addon id="plugin.video.torrenter" name="Torrenter" version="2.5.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,7 +8,6 @@
 | 
				
			|||||||
        <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,13 +23,10 @@
 | 
				
			|||||||
        </summary>
 | 
					        </summary>
 | 
				
			||||||
        <description lang='ru'>Так же плагин может добавлять, проигрывать и управлять скачками в торрент клиентах (uTorrent, Transmisson, Deluge и Vuse, qBittorrent) или средставми python-libtorrent.
 | 
					        <description lang='ru'>Так же плагин может добавлять, проигрывать и управлять скачками в торрент клиентах (uTorrent, Transmisson, Deluge и Vuse, qBittorrent) или средставми python-libtorrent.
 | 
				
			||||||
        </description>
 | 
					        </description>
 | 
				
			||||||
	<disclaimer lang='ru'>GNU GPLv3 http://www.gnu.org/licenses/</disclaimer>
 | 
					        <disclaimer lang='ru'>GNU GPLv3 http://www.gnu.org/licenses/</disclaimer>
 | 
				
			||||||
	<summary lang='es'>Complemento que nos permite ver vídeos que se distribuyen en redes BitTorrent sin necesidad de descargarlos previamente por completo.
 | 
							<forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum>
 | 
				
			||||||
        </summary>
 | 
							<website>http://xbmc.ru/forum/showthread.php?t=6837</website>
 | 
				
			||||||
        <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.
 | 
							<email>skype:kyonkodura</email>
 | 
				
			||||||
        </description>    	
 | 
							<source>https://github.com/DiMartinoXBMC/plugin.video.torrenter</source>
 | 
				
			||||||
	<forum>https://forums.tvaddons.ag/addon-releases/29224-torrenter-v2.html</forum>
 | 
					 | 
				
			||||||
	<website>http://xbmc.ru/forum/showthread.php?t=6837</website>
 | 
					 | 
				
			||||||
	<source>https://github.com/inpos/plugin.video.torrenter</source>
 | 
					 | 
				
			||||||
    </extension>
 | 
					    </extension>
 | 
				
			||||||
</addon>
 | 
					</addon>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,58 +1,13 @@
 | 
				
			|||||||
[B]Version 2.6.7[/B]
 | 
					English changelog at http://bit.ly/1MfSVUP
 | 
				
			||||||
[+] Теперь можно указать порт SOCKS-прокси, при использоании прокси Tor
 | 
					 | 
				
			||||||
[+] Списки медиа: исправлен RiperAM
 | 
					 | 
				
			||||||
[+] .torrent Player: Исправлена работа c длинными названиями
 | 
					 | 
				
			||||||
[-] Удален user-agent "uTorrent/2200(24683)" во избежании бана
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.6[/B]
 | 
					 | 
				
			||||||
[+] Добавлена поддержка прокси для windows
 | 
					 | 
				
			||||||
[+] Теперь можно указать адрес SOCKS-прокси, при использоании прокси Tor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.5[/B]
 | 
					 | 
				
			||||||
[+] Восстановлена работа RiperAM в списках медиа.
 | 
					 | 
				
			||||||
[+] Разделена настройка прокси: для поиска и для списков медиа
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.4[/B]
 | 
					 | 
				
			||||||
[+] Проблемы с сетью: добавлена поддержка Tor для поиска торрентов и заказчки torrent-файлов
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.3[/B]
 | 
					 | 
				
			||||||
[+] Списки медиа: возобновлена работа получения метаданных
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.2[/B]
 | 
					 | 
				
			||||||
[+] История Просмотров: Перемотка при внешнем вызове
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.1[/B]
 | 
					 | 
				
			||||||
[+] Окно Поиска: Использование окна в сторонних плагинах
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.6.0[/B]
 | 
					 | 
				
			||||||
[+] Окно Поиска: Полноценный релиз
 | 
					 | 
				
			||||||
[+] Настройки: Добавлена возможность отключения уведомлений
 | 
					 | 
				
			||||||
[+] История Просмотров: При аварийном выходе данные остаются
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.5.6[/B]
 | 
					 | 
				
			||||||
[+] Списки Медиа: Добавлен RuTorOrg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.5.5[/B]
 | 
					 | 
				
			||||||
[+] Control Center: Исправлена работа выбора трекеров для определенного запроса
 | 
					 | 
				
			||||||
[+] Торрент-клиент: При скачивании одного файла торрент-клиентом теперь автоматически выбирается раздача
 | 
					 | 
				
			||||||
[+] .torrent Player: Исправлена работа (спасибо kolosovski)
 | 
					 | 
				
			||||||
[+] Окно Поиска: Добавлено Окно Поиска в режиме тестирования
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.5.4[/B]
 | 
					 | 
				
			||||||
[+] Исправлено "открыть без возврата". Спасибо viorel-m.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[B]Version 2.5.3[/B]
 | 
					 | 
				
			||||||
[+] Венгерский язык
 | 
					 | 
				
			||||||
[+] Совместимость с Коди 17
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[B]Version 2.5.2[/B]
 | 
					[B]Version 2.5.2[/B]
 | 
				
			||||||
[+] Упорядочивание по размеру файла
 | 
					[+] Упорядочивание по разверу файла.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[B]Version 2.5.1[/B]
 | 
					[B]Version 2.5.1[/B]
 | 
				
			||||||
[+] Исправлена работа с кодировками
 | 
					[+] Исправлена работа с кодировками.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[B]Version 2.5.0[/B]
 | 
					[B]Version 2.5.0[/B]
 | 
				
			||||||
[+] НОВЫЙ проигрыватель pyrrent2http от inpos!  Аналог torrent2http написаный на python, а не на GO
 | 
					[+] НОВЫЙ проигрыватель pyrrent2http от inpos!  Аналог torrent2http написаный на python, а не на GO.
 | 
				
			||||||
[+] Проигрыватель: Ускорена повторная работа с торрентом - resume data (спасибо srg70 и RussakHH)
 | 
					[+] Проигрыватель: Ускорена повторная работа с торрентом - resume data (спасибо srg70 и RussakHH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[B]Version 2.4.6[/B]
 | 
					[B]Version 2.4.6[/B]
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ import xbmcaddon
 | 
				
			|||||||
import xbmc
 | 
					import xbmc
 | 
				
			||||||
import xbmcgui
 | 
					import xbmcgui
 | 
				
			||||||
from functions import getParameters, HistoryDB, Searchers, log
 | 
					from functions import getParameters, HistoryDB, Searchers, log
 | 
				
			||||||
import pyxbmct
 | 
					from resources.pyxbmct.addonwindow import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__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(pyxbmct.AddonDialogWindow):
 | 
					class ControlCenter(AddonDialogWindow):
 | 
				
			||||||
    def __init__(self, title, addtime=None):
 | 
					    def __init__(self, title, addtime=None):
 | 
				
			||||||
        super(ControlCenter, self).__init__(title)
 | 
					        super(ControlCenter, self).__init__(title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -57,17 +57,18 @@ class ControlCenter(pyxbmct.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.dic.keys():
 | 
					                    for searcher in self.keys:
 | 
				
			||||||
                        self.dic[searcher] = False
 | 
					                        self.dic[searcher] = False
 | 
				
			||||||
                    for searcher in providers:
 | 
					                    for searcher in providers:
 | 
				
			||||||
                        try:
 | 
					                        try:
 | 
				
			||||||
                            if searcher in self.dic.keys():
 | 
					                            if searcher in self.keys:
 | 
				
			||||||
                                self.dic[searcher] = True
 | 
					                                self.dic[searcher] = True
 | 
				
			||||||
                        except:
 | 
					                        except:
 | 
				
			||||||
                            log('self.dic[searcher] except')
 | 
					                            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,7 +78,7 @@ class ControlCenter(pyxbmct.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(pyxbmct.ACTION_NAV_BACK, self.close)
 | 
					        self.connect(ACTION_NAV_BACK, self.close)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def place(self):
 | 
					    def place(self):
 | 
				
			||||||
        placed = {}
 | 
					        placed = {}
 | 
				
			||||||
@ -89,6 +90,7 @@ class ControlCenter(pyxbmct.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):
 | 
				
			||||||
@ -101,7 +103,7 @@ class ControlCenter(pyxbmct.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] = pyxbmct.RadioButton(searcher)
 | 
					                self.radiobutton[searcher] = 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)
 | 
				
			||||||
@ -110,32 +112,32 @@ class ControlCenter(pyxbmct.AddonDialogWindow):
 | 
				
			|||||||
                self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
 | 
					                self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Button
 | 
					        # Button
 | 
				
			||||||
        self.button_install = pyxbmct.Button(__language__(30415))
 | 
					        self.button_install = 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 = pyxbmct.Button(__language__(30416))
 | 
					        self.button_openserchset = 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 = pyxbmct.Button(__language__(30417))
 | 
					        self.button_clearstor = 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 = pyxbmct.Button(__language__(30413))
 | 
					        self.button_openset = 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 = pyxbmct.Button(__language__(30414))
 | 
					        self.button_utorrent = 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 = pyxbmct.Button(__language__(30412))
 | 
					        self.button_close = 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -169,6 +171,8 @@ class ControlCenter(pyxbmct.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))]
 | 
				
			||||||
@ -243,10 +247,7 @@ class ControlCenter(pyxbmct.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 = xbmcgui.Dialog().select(__language__(30418), slist)
 | 
				
			||||||
                ret = 0
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                ret = xbmcgui.Dialog().select(__language__(30418), slist)
 | 
					 | 
				
			||||||
            if ret > -1 and ret < len(slist):
 | 
					            if ret > -1 and ret < len(slist):
 | 
				
			||||||
                sid = slist[ret]
 | 
					                sid = slist[ret]
 | 
				
			||||||
                Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
 | 
					                Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										328
									
								
								functions.py
									
									
									
									
									
								
							
							
						
						@ -43,8 +43,7 @@ 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 = xbmc.translatePath(__settings__.getSetting("storage"))
 | 
					userStorageDirectory = __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')
 | 
				
			||||||
@ -56,7 +55,7 @@ def clearStorage(userStorageDirectory, force = False):
 | 
				
			|||||||
    userStorageDirectory = decode(userStorageDirectory)
 | 
					    userStorageDirectory = decode(userStorageDirectory)
 | 
				
			||||||
    #log('[clearStorage]: storage '+str(userStorageDirectory) + os.sep)
 | 
					    #log('[clearStorage]: storage '+str(userStorageDirectory) + os.sep)
 | 
				
			||||||
    min_storage_size = __settings__.getSetting("min_storage_size")
 | 
					    min_storage_size = __settings__.getSetting("min_storage_size")
 | 
				
			||||||
    storage_size = getDirectorySizeInGB(userStorageDirectory.encode('utf-8'))
 | 
					    storage_size = getDirectorySizeInGB(userStorageDirectory)
 | 
				
			||||||
    if storage_size >= min_storage_size or force:
 | 
					    if storage_size >= min_storage_size or force:
 | 
				
			||||||
        if xbmcvfs.exists(userStorageDirectory + os.sep) or os.path.exists(userStorageDirectory):
 | 
					        if xbmcvfs.exists(userStorageDirectory + os.sep) or os.path.exists(userStorageDirectory):
 | 
				
			||||||
            log('[clearStorage]: storage exists')
 | 
					            log('[clearStorage]: storage exists')
 | 
				
			||||||
@ -84,8 +83,7 @@ def clearStorage(userStorageDirectory, force = False):
 | 
				
			|||||||
                shutil.move(saved, saved_temp)
 | 
					                shutil.move(saved, saved_temp)
 | 
				
			||||||
                saved_bool = True
 | 
					                saved_bool = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            shutil.rmtree(userStorageDirectory, ignore_errors=True)
 | 
					            shutil.rmtree(userStorageDirectory.encode('utf-8'), ignore_errors=True)
 | 
				
			||||||
            #log(str(xbmcvfs.listdir(userStorageDirectory)))
 | 
					 | 
				
			||||||
            xbmcvfs.mkdir(userStorageDirectory)
 | 
					            xbmcvfs.mkdir(userStorageDirectory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if torrents_bool:
 | 
					            if torrents_bool:
 | 
				
			||||||
@ -93,10 +91,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'))
 | 
					            showMessage(Localization.localize('Storage'), Localization.localize('Storage has been cleared'), forced=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'))
 | 
					            showMessage(Localization.localize('Storage'), Localization.localize('Does not exists'), forced=True)
 | 
				
			||||||
            log('[clearStorage]: fail storage '+userStorageDirectory + os.sep)
 | 
					            log('[clearStorage]: fail storage '+userStorageDirectory + os.sep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
@ -104,6 +102,8 @@ def clearStorage(userStorageDirectory, force = False):
 | 
				
			|||||||
        except Exception, e:
 | 
					        except Exception, e:
 | 
				
			||||||
            log('[clearStorage]: DownloadDB().clear() failed. '+str(e))
 | 
					            log('[clearStorage]: DownloadDB().clear() failed. '+str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        showMessage(Localization.localize('Storage'), Localization.localize('Storage was cleared'), forced=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sortcomma(dict, json):
 | 
					def sortcomma(dict, json):
 | 
				
			||||||
    for x in dict:
 | 
					    for x in dict:
 | 
				
			||||||
@ -152,9 +152,8 @@ 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)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -423,7 +422,6 @@ def cutFolder(contentList, tdir=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if len(contentList) > 1:
 | 
					    if len(contentList) > 1:
 | 
				
			||||||
        common_folder = contentList[0][0]
 | 
					        common_folder = contentList[0][0]
 | 
				
			||||||
        debug('[cutFolder]: common_folder '+common_folder)
 | 
					 | 
				
			||||||
        if '\\' in common_folder:
 | 
					        if '\\' in common_folder:
 | 
				
			||||||
            common_folder = common_folder.split('\\')[0]
 | 
					            common_folder = common_folder.split('\\')[0]
 | 
				
			||||||
        elif '/' in common_folder:
 | 
					        elif '/' in common_folder:
 | 
				
			||||||
@ -431,36 +429,38 @@ def cutFolder(contentList, tdir=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        common = True
 | 
					        common = True
 | 
				
			||||||
        for item in contentList:
 | 
					        for item in contentList:
 | 
				
			||||||
            if common_folder not in item[0]:
 | 
					            fileTitle = item[0]
 | 
				
			||||||
 | 
					            if common_folder not in fileTitle:
 | 
				
			||||||
                common = False
 | 
					                common = False
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # print common_folder
 | 
				
			||||||
        for item in contentList:
 | 
					        for item in contentList:
 | 
				
			||||||
 | 
					            fileTitle = item[0]
 | 
				
			||||||
 | 
					            contentId = item[1]
 | 
				
			||||||
            dir = None
 | 
					            dir = None
 | 
				
			||||||
            if common:
 | 
					            if common:
 | 
				
			||||||
                item[0] = item[0][len(common_folder) + 1:]
 | 
					                fileTitle = fileTitle[len(common_folder) + 1:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #debug('[cutFolder]: item[0] '+item[0])
 | 
					            # print fileTitle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if '\\' in item[0]:
 | 
					            if '\\' in fileTitle:
 | 
				
			||||||
                dir = item[0].split('\\')[0]
 | 
					                dir = fileTitle.split('\\')[0]
 | 
				
			||||||
            elif '/' in item[0]:
 | 
					            elif '/' in fileTitle:
 | 
				
			||||||
                dir = item[0].split('/')[0]
 | 
					                dir = fileTitle.split('/')[0]
 | 
				
			||||||
            elif not tdir:
 | 
					            elif not tdir:
 | 
				
			||||||
                contentListNew.append(item)
 | 
					                contentListNew.append(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if tdir and ensure_str(dir) == ensure_str(tdir):
 | 
					            if tdir and dir == tdir:
 | 
				
			||||||
                tupleContent = list(item)
 | 
					                tupleContent = list(item)
 | 
				
			||||||
                tupleContent[0] = item[0][len(dir) + 1:]
 | 
					                tupleContent[0] = fileTitle[len(dir) + 1:]
 | 
				
			||||||
                contentListNew.append(list(tupleContent))
 | 
					                contentListNew.append(tuple(tupleContent))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not tdir and dir and dir not in dirList:
 | 
					            if not tdir and dir and dir not in dirList:
 | 
				
			||||||
                dirList.append(dir)
 | 
					                dirList.append(dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        debug('[cutFolder]: dirList, contentListNew '+str(dirList)+str(contentListNew))
 | 
					 | 
				
			||||||
        return dirList, contentListNew
 | 
					        return dirList, contentListNew
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        debug('[cutFolder]: dirList, contentList '+str(dirList)+str(contentList))
 | 
					 | 
				
			||||||
        return dirList, contentList
 | 
					        return dirList, contentList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -577,52 +577,32 @@ 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, 7]:
 | 
					    elif view_style in [1, 4, 5]:
 | 
				
			||||||
        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 in [1, 7]:
 | 
					    if view_style == 1:
 | 
				
			||||||
        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'] = 'list'
 | 
					        styles['drawtrackerList'] = styles['drawContent'] = styles['List'] = styles['sectionMenu'] = 'icons'
 | 
				
			||||||
        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)
 | 
				
			||||||
    log('[view_style]: lock '+str(style)+' for '+str(func))
 | 
					    # debug('[view_style]: lock '+str(style))
 | 
				
			||||||
    lockView(style, num_skin)
 | 
					    lockView(style, num_skin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -632,38 +612,23 @@ def lockView(viewId='info', num_skin=0):
 | 
				
			|||||||
        {'list': 50, 'info': 50, 'wide': 51, 'icons': 500, 'info3': 515, },  # Confluence
 | 
					        {'list': 50, 'info': 50, 'wide': 51, 'icons': 500, 'info3': 515, },  # Confluence
 | 
				
			||||||
        {'list': 50, 'info': 51, 'wide': 52, 'icons': 53, },  # Transperency!
 | 
					        {'list': 50, 'info': 51, 'wide': 52, 'icons': 53, },  # Transperency!
 | 
				
			||||||
        {'list': 55, 'info': 55, 'wide': 55, 'icons': 55, 'info3': 55, },  # Aeon Nox
 | 
					        {'list': 55, 'info': 55, 'wide': 55, 'icons': 55, 'info3': 55, },  # Aeon Nox
 | 
				
			||||||
        {'list': 50, 'info': 54, 'wide': 55, 'icons': 54, 'info3': 500, },  # Estuary
 | 
					 | 
				
			||||||
        {'list': 50, 'bigwide': 51, 'biglist': 52, 'poster': 53, 'banner': 54, 'wall': 55, 'mediainfo': 56, 'extrainfo': 57, "cards":58, "bannerwall":59, 'thumbnails': 500, 'postersquare': 503, 'wallsquare': 505, },  # Arctic: Zephyr
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        if viewId == 'wide' and num_skin == 3:
 | 
					 | 
				
			||||||
            xbmcplugin.setContent(int(sys.argv[1]), 'files')
 | 
					 | 
				
			||||||
        xbmc.executebuiltin("Container.SetViewMode(%s)" % str(skinOptimizations[num_skin][viewId]))
 | 
					        xbmc.executebuiltin("Container.SetViewMode(%s)" % str(skinOptimizations[num_skin][viewId]))
 | 
				
			||||||
    except:
 | 
					    except:
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ''' Estuary
 | 
					 | 
				
			||||||
                <include>View_50_List</include>
 | 
					 | 
				
			||||||
                <include>View_51_Poster</include>
 | 
					 | 
				
			||||||
                <include>View_52_IconWall</include>
 | 
					 | 
				
			||||||
                <include>View_53_Shift</include>
 | 
					 | 
				
			||||||
                <include>View_54_InfoWall</include>
 | 
					 | 
				
			||||||
                <include>View_55_WideList</include>
 | 
					 | 
				
			||||||
                <include>View_500_SmallThumb</include>
 | 
					 | 
				
			||||||
                <include>View_501_Banner</include>
 | 
					 | 
				
			||||||
                <include>View_502_FanArt</include>
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
            <include>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
 | 
					 | 
				
			||||||
            <include>MediaListView3</include> <!-- view id = 503 -->
 | 
					 | 
				
			||||||
            <include>MediaListView2</include> <!-- view id = 504 -->
 | 
					 | 
				
			||||||
            <include>MediaListView4</include> <!-- view id = 515 -->
 | 
					 | 
				
			||||||
            <include>WideIconView</include> <!-- view id = 505 -->
 | 
					 | 
				
			||||||
            <include>MusicVideoInfoListView</include> <!-- view id = 511 -->
 | 
					 | 
				
			||||||
            <include>AddonInfoListView1</include> <!-- view id = 550 -->
 | 
					 | 
				
			||||||
            <include>AddonInfoThumbView1</include> <!-- view id = 551 -->
 | 
					 | 
				
			||||||
            <include>LiveTVView1</include> <!-- view id = 560 -->
 | 
					 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
 | 
								<include>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
 | 
				
			||||||
 | 
								<include>MediaListView3</include> <!-- view id = 503 -->
 | 
				
			||||||
 | 
								<include>MediaListView2</include> <!-- view id = 504 -->
 | 
				
			||||||
 | 
								<include>MediaListView4</include> <!-- view id = 515 -->
 | 
				
			||||||
 | 
								<include>WideIconView</include> <!-- view id = 505 -->
 | 
				
			||||||
 | 
								<include>MusicVideoInfoListView</include> <!-- view id = 511 -->
 | 
				
			||||||
 | 
								<include>AddonInfoListView1</include> <!-- view id = 550 -->
 | 
				
			||||||
 | 
								<include>AddonInfoThumbView1</include> <!-- view id = 551 -->
 | 
				
			||||||
 | 
								<include>LiveTVView1</include> <!-- view id = 560 -->
 | 
				
			||||||
 | 
						'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def torrent_dir():
 | 
					def torrent_dir():
 | 
				
			||||||
@ -936,6 +901,7 @@ 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):
 | 
				
			||||||
@ -952,7 +918,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:
 | 
				
			||||||
@ -964,8 +930,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()
 | 
				
			||||||
@ -1071,23 +1037,13 @@ class WatchedHistoryDB:
 | 
				
			|||||||
        self._close()
 | 
					        self._close()
 | 
				
			||||||
        return x if x else None
 | 
					        return x if x else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getbypathind(self, path, ind):
 | 
					    def add(self, filename, foldername = None, seek = 0, length = 1, ind = 0, size = 0):
 | 
				
			||||||
        self._connect()
 | 
					        watchedPercent = int((float(seek) / float(length)) * 100)
 | 
				
			||||||
        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) + '"')
 | 
				
			||||||
@ -1335,76 +1291,9 @@ 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=''
 | 
				
			||||||
@ -1419,8 +1308,6 @@ 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]
 | 
				
			||||||
@ -1473,7 +1360,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) and searcherFile != '__init__.py':
 | 
					            if re.match('^(\w+)\.py$', searcherFile):
 | 
				
			||||||
                searchersList.append(searcherFile.replace('.py', ''))
 | 
					                searchersList.append(searcherFile.replace('.py', ''))
 | 
				
			||||||
        return searchersList
 | 
					        return searchersList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1885,29 +1772,6 @@ 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)
 | 
				
			||||||
@ -2048,7 +1912,7 @@ def check_network_advancedsettings():
 | 
				
			|||||||
        file_cont='''<advancedsettings>
 | 
					        file_cont='''<advancedsettings>
 | 
				
			||||||
  <network>
 | 
					  <network>
 | 
				
			||||||
    <buffermode>2</buffermode>
 | 
					    <buffermode>2</buffermode>
 | 
				
			||||||
    <curlclienttimeout>30</curlclienttimeout>
 | 
						<curlclienttimeout>30</curlclienttimeout>
 | 
				
			||||||
    <cachemembuffersize>252420</cachemembuffersize>
 | 
					    <cachemembuffersize>252420</cachemembuffersize>
 | 
				
			||||||
    <readbufferfactor>5</readbufferfactor>
 | 
					    <readbufferfactor>5</readbufferfactor>
 | 
				
			||||||
  </network>
 | 
					  </network>
 | 
				
			||||||
@ -2065,7 +1929,7 @@ def check_network_advancedsettings():
 | 
				
			|||||||
'''<advancedsettings>
 | 
					'''<advancedsettings>
 | 
				
			||||||
  <network>
 | 
					  <network>
 | 
				
			||||||
    <buffermode>2</buffermode>
 | 
					    <buffermode>2</buffermode>
 | 
				
			||||||
    <curlclienttimeout>30</curlclienttimeout>
 | 
						<curlclienttimeout>30</curlclienttimeout>
 | 
				
			||||||
    <cachemembuffersize>252420</cachemembuffersize>
 | 
					    <cachemembuffersize>252420</cachemembuffersize>
 | 
				
			||||||
    <readbufferfactor>5</readbufferfactor>
 | 
					    <readbufferfactor>5</readbufferfactor>
 | 
				
			||||||
  </network>
 | 
					  </network>
 | 
				
			||||||
@ -2190,30 +2054,20 @@ def uri2path(uri):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def localize_path(path):
 | 
					def localize_path(path):
 | 
				
			||||||
    import chardet
 | 
					    import chardet
 | 
				
			||||||
    if not isinstance(path, unicode):
 | 
					    if not isinstance(path, unicode): path = path.decode(chardet.detect(path)['encoding'])
 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            path = path.decode(chardet.detect(path).get('encoding') or 'utf-8')
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
    if not sys.platform.startswith('win'):
 | 
					    if not sys.platform.startswith('win'):
 | 
				
			||||||
        path = encode_msg(path)
 | 
					        path = encode_msg(path)
 | 
				
			||||||
    return path
 | 
					    return path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def encode_msg(msg):
 | 
					def encode_msg(msg):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        msg = isinstance(msg, unicode) and msg.encode(
 | 
					        msg = isinstance(msg, unicode) and msg.encode(True and sys.getfilesystemencoding() or 'utf-8') or msg
 | 
				
			||||||
            (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 = msg.encode('utf-8')
 | 
				
			||||||
    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",
 | 
				
			||||||
@ -2246,83 +2100,3 @@ 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'
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 1.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/kodi.png
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 23 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 8.9 KiB  | 
| 
		 Before Width: | Height: | Size: 16 KiB  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 8.8 KiB  | 
| 
		 Before Width: | Height: | Size: 5.4 KiB  | 
| 
		 Before Width: | Height: | Size: 19 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB  | 
| 
		 Before Width: | Height: | Size: 5.1 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 8.9 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 1.4 KiB  | 
| 
		 Before Width: | Height: | Size: 19 KiB  | 
| 
		 Before Width: | Height: | Size: 9.0 KiB  | 
| 
		 Before Width: | Height: | Size: 5.7 KiB  | 
| 
		 Before Width: | Height: | Size: 20 KiB  | 
| 
		 Before Width: | Height: | Size: 3.3 KiB  | 
| 
		 Before Width: | Height: | Size: 5.2 KiB  | 
@ -22,7 +22,7 @@ import re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import Content
 | 
					import Content
 | 
				
			||||||
from BeautifulSoup import BeautifulSoup
 | 
					from BeautifulSoup import BeautifulSoup
 | 
				
			||||||
from datetime import date
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def make_category_dict():
 | 
					def make_category_dict():
 | 
				
			||||||
    category_dict = {
 | 
					    category_dict = {
 | 
				
			||||||
@ -72,7 +72,7 @@ def make_category_dict():
 | 
				
			|||||||
            x[0], x[1] + 'view=list', {'page': x[1] + 'view=list&page=%d', 'increase': 1, 'second_page': 1})
 | 
					            x[0], x[1] + 'view=list', {'page': x[1] + 'view=list&page=%d', 'increase': 1, 'second_page': 1})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    category_dict['year'] = {'year': 'by Year', }
 | 
					    category_dict['year'] = {'year': 'by Year', }
 | 
				
			||||||
    for y in range(date.today().year, 1970, -1):
 | 
					    for y in range(2015, 1970, -1):
 | 
				
			||||||
        category_dict['year'][str(y)] = (str(y), '/films/year/%s/' % str(y),
 | 
					        category_dict['year'][str(y)] = (str(y), '/films/year/%s/' % str(y),
 | 
				
			||||||
                                         {'page': '/films/year/%s/' % str(y) + '?view=list&page=%d', 'increase': 1,
 | 
					                                         {'page': '/films/year/%s/' % str(y) + '?view=list&page=%d', 'increase': 1,
 | 
				
			||||||
                                          'second_page': 1})
 | 
					                                          'second_page': 1})
 | 
				
			||||||
@ -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.ag"
 | 
					    baseurl = "https://eztv.ch"
 | 
				
			||||||
    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'),
 | 
				
			||||||
@ -23,7 +23,6 @@ import HTMLParser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import Content
 | 
					import Content
 | 
				
			||||||
from BeautifulSoup import BeautifulSoup
 | 
					from BeautifulSoup import BeautifulSoup
 | 
				
			||||||
from datetime import date
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IMDB(Content.Content):
 | 
					class IMDB(Content.Content):
 | 
				
			||||||
@ -66,7 +65,7 @@ class IMDB(Content.Content):
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for y in range(date.today().year, 1970, -1):
 | 
					    for y in range(2015, 1970, -1):
 | 
				
			||||||
        category_dict['year'][str(y)] = (str(y), '/year/%s/' % str(y))
 | 
					        category_dict['year'][str(y)] = (str(y), '/year/%s/' % str(y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    regex_list = []
 | 
					    regex_list = []
 | 
				
			||||||
@ -99,28 +98,27 @@ 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):
 | 
				
			||||||
            self.debug(response)
 | 
					            #print 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)
 | 
				
			||||||
        self.debug(str(contentList))
 | 
					        #print 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': 'lister-item mode-advanced'})
 | 
					        result = Soup.findAll('tr', {'class': ['findResult odd', 'findResult even']})
 | 
				
			||||||
        num = 250
 | 
					        num = 250
 | 
				
			||||||
        for tr in result:
 | 
					        for tr in result:
 | 
				
			||||||
            #main
 | 
					            #main
 | 
				
			||||||
@ -148,7 +146,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,
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
        self.debug(str(result))
 | 
					        #print result
 | 
				
			||||||
        return contentList
 | 
					        return contentList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def genremode(self, response):
 | 
					    def genremode(self, response):
 | 
				
			||||||
@ -182,7 +180,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,
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
        self.debug(str(result))
 | 
					        #print result
 | 
				
			||||||
        return contentList
 | 
					        return contentList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def biggerImg(self, img):
 | 
					    def biggerImg(self, img):
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ class KickAssSo(Content.Content):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    baseurl = "http://kat.am"
 | 
					    baseurl = "http://kat.cr"
 | 
				
			||||||
    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):
 | 
				
			||||||
            self.debug(response)
 | 
					            # print response
 | 
				
			||||||
            if category:
 | 
					            if category:
 | 
				
			||||||
                contentList = self.mode(response)
 | 
					                contentList = self.mode(response)
 | 
				
			||||||
        self.debug(str(contentList))
 | 
					        # print 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'''<a data-download .+? href="(.+?)" class=".+?"><i.+?<a.+?<a.+?<a href="(.+?html)" class=".+?">(.+?)</a>.+? in <span.+?"><strong>.+?">(.+?)</a>.+?<td class="nobr center">(.+?)</td>.+?<td class="center".+?>(\d+ .+?)</td>.+?<td class="green center">(\d+?)</td>.+?<td class="red lasttd center">(\d+?)</td>'''
 | 
					        regex_tr = r'''title="Download torrent file" href="(.+?)" class=".+?"><i.+?<a.+?<a.+?<a href="(.+?html)" class=".+?">(.+?)</a>.+? in <span.+?"><strong>.+?">(.+?)</a>.+?<td class="nobr center">(.+?)</td>.+?<td class="center".+?>(\d+ .+?)</td>.+?<td class="green center">(\d+?)</td>.+?<td class="red lasttd center">(\d+?)</td>'''
 | 
				
			||||||
        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,7 +129,6 @@ 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)
 | 
				
			||||||
@ -144,7 +143,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'] = img if img.startswith('http:') else 'http:' + img
 | 
					                movieInfo['poster'] = 'http:' + img
 | 
				
			||||||
            except:
 | 
					            except:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
@ -191,5 +190,7 @@ 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
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import socket
 | 
					import socket
 | 
				
			||||||
from datetime import date
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Content
 | 
					import Content
 | 
				
			||||||
from BeautifulSoup import BeautifulSoup
 | 
					from BeautifulSoup import BeautifulSoup
 | 
				
			||||||
@ -71,7 +70,7 @@ class KinoPoisk(Content.Content):
 | 
				
			|||||||
                x[0], x[1] + 'perpage/25/', {'page': x[1] + 'perpage/25/page/%d/', 'increase': 1, 'second_page': 2})
 | 
					                x[0], x[1] + 'perpage/25/', {'page': x[1] + 'perpage/25/page/%d/', 'increase': 1, 'second_page': 2})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    category_dict['year'] = {'year': 'by Year', }
 | 
					    category_dict['year'] = {'year': 'by Year', }
 | 
				
			||||||
    for y in range(date.today().year, 1970, -1):
 | 
					    for y in range(2015, 1970, -1):
 | 
				
			||||||
        category_dict['year'][str(y)] = (str(y), '/s/type/film/list/1/m_act[year]/%s/' % str(y) + 'perpage/25/',
 | 
					        category_dict['year'][str(y)] = (str(y), '/s/type/film/list/1/m_act[year]/%s/' % str(y) + 'perpage/25/',
 | 
				
			||||||
                                         {'page': '/s/type/film/list/1/m_act[year]/%s/' % str(y) + 'perpage/25/page/%d/',
 | 
					                                         {'page': '/s/type/film/list/1/m_act[year]/%s/' % str(y) + 'perpage/25/page/%d/',
 | 
				
			||||||
                                          'increase': 1, 'second_page': 2})
 | 
					                                          'increase': 1, 'second_page': 2})
 | 
				
			||||||
@ -104,23 +103,22 @@ 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.debug('get_contentList: url = '+url)
 | 
					        #print 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):
 | 
				
			||||||
            self.debug(str(response))
 | 
					            #print 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)
 | 
				
			||||||
        self.debug('get_contentList: contentList = '+str(contentList))
 | 
					        #print str(contentList)
 | 
				
			||||||
        return contentList
 | 
					        return contentList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def stripTtl(self, title):
 | 
					    def stripTtl(self, title):
 | 
				
			||||||
@ -133,12 +131,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')
 | 
				
			||||||
        self.debug('popmode: '+str(result))
 | 
					        #print 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 = ''
 | 
				
			||||||
@ -153,14 +151,12 @@ 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))
 | 
				
			||||||
@ -179,7 +175,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:]
 | 
				
			||||||
        self.debug('topmode: ' + str(result))
 | 
					        #print str(result)
 | 
				
			||||||
        for tr in result:
 | 
					        for tr in result:
 | 
				
			||||||
            #main
 | 
					            #main
 | 
				
			||||||
            td = tr.findAll('td')
 | 
					            td = tr.findAll('td')
 | 
				
			||||||
@ -201,12 +197,8 @@ 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:
 | 
				
			||||||
                        match = re.search(r"(.+) \((\d\d\d\d) –|(.+) \(.*(\d\d\d\d)", a_all.text,
 | 
					                        title, year = re.compile('(.+) \(.*(\d\d\d\d)').findall(a_all.text)[0]
 | 
				
			||||||
                                          re.IGNORECASE | re.MULTILINE)
 | 
					                        info['tvshowtitle'] = title
 | 
				
			||||||
                        if match:
 | 
					 | 
				
			||||||
                            title = match.group(1)
 | 
					 | 
				
			||||||
                            year = match.group(2)
 | 
					 | 
				
			||||||
                            info['tvshowtitle'] = title
 | 
					 | 
				
			||||||
                    except:
 | 
					                    except:
 | 
				
			||||||
                        title = a_all.text
 | 
					                        title = a_all.text
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ class RiperAM(Content.Content):
 | 
				
			|||||||
        'hot': ('Most Recent', '/', {'page': '/portal.php?tp=%d', 'increase': 30, 'second_page': 30}),
 | 
					        'hot': ('Most Recent', '/', {'page': '/portal.php?tp=%d', 'increase': 30, 'second_page': 30}),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    baseurl = "http://riperam.org/"
 | 
					    baseurl = "http://riperam.org"
 | 
				
			||||||
    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'),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,249 +0,0 @@
 | 
				
			|||||||
# -*- coding: utf-8 -*-
 | 
					 | 
				
			||||||
'''
 | 
					 | 
				
			||||||
    Torrenter plugin for XBMC
 | 
					 | 
				
			||||||
    Copyright (C) 2012 Vadim Skorba
 | 
					 | 
				
			||||||
    vadim.skorba@gmail.com
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
    it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
    the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
    (at your option) any later version.
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
    GNU General Public License for more details.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
'''
 | 
					 | 
				
			||||||
import re, sys
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import Content
 | 
					 | 
				
			||||||
from BeautifulSoup import BeautifulSoup
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#http://anti-tor.org/browse/0/1/0/0 date movie
 | 
					 | 
				
			||||||
#http://anti-tor.org/browse/1/1/0/0 page 2
 | 
					 | 
				
			||||||
#http://anti-tor.org/browse/0/1/0/2 seed movie
 | 
					 | 
				
			||||||
#                          page/cat/?/sort
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RuTorOrg(Content.Content):
 | 
					 | 
				
			||||||
    category_dict = {
 | 
					 | 
				
			||||||
        'movies': ('Movies', '/browse/0/1/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/1/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                                                'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                                                         {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'rus_movies': ('Russian Movies', '/browse/0/5/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/5/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'tvshows': ('TV Shows', '/browse/0/4/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/4/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'science': ('Научно - популярные фильмы', '/browse/0/12/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/12/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'cartoons': ('Cartoons', '/browse/0/7/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/7/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'anime': ('Anime', '/browse/0/10/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/10/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'sport': ('Спорт и Здоровье', '/browse/0/13/0',
 | 
					 | 
				
			||||||
                   {'page': '/browse/%d/13/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                    'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                             {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'tele': ('Телевизор', '/browse/0/6/0',
 | 
					 | 
				
			||||||
                  {'page': '/browse/%d/6/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                   'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                            {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
        'humor': ('Юмор', '/browse/0/15/0',
 | 
					 | 
				
			||||||
                 {'page': '/browse/%d/15/0', 'increase': 1, 'second_page': 1,
 | 
					 | 
				
			||||||
                  'sort': [{'name': 'by Seeders', 'url_after': '/2'},
 | 
					 | 
				
			||||||
                           {'name': 'by Date', 'url_after': '/0'}]}),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #'hot': ('Most Recent',),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    baseurl = "anti-tor.org"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
    Weight of source with this searcher provided.
 | 
					 | 
				
			||||||
    Will be multiplied on default weight.
 | 
					 | 
				
			||||||
    Default weight is seeds number
 | 
					 | 
				
			||||||
    '''
 | 
					 | 
				
			||||||
    sourceWeight = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isTracker(self):
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isSearcher(self):
 | 
					 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isScrappable(self):
 | 
					 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isInfoLink(self):
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isPages(self):
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isSort(self):
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isSearchOption(self):
 | 
					 | 
				
			||||||
        return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_contentList(self, category, subcategory=None, apps_property=None):
 | 
					 | 
				
			||||||
        #self.debug = self.log
 | 
					 | 
				
			||||||
        contentList = []
 | 
					 | 
				
			||||||
        url = 'http://%s' % self.get_url(category, subcategory, apps_property)
 | 
					 | 
				
			||||||
        self.debug(url)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.headers = [('User-Agent',
 | 
					 | 
				
			||||||
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 YaBrowser/14.10.2062.12061 Safari/537.36'),
 | 
					 | 
				
			||||||
           ('Referer', 'http://%s' % self.baseurl), ('Accept-encoding', 'gzip'),
 | 
					 | 
				
			||||||
           ('Cookie', str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")))]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response = self.makeRequest(url, headers=self.headers)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if None != response and 0 < len(response):
 | 
					 | 
				
			||||||
            #self.debug(response)
 | 
					 | 
				
			||||||
            cookie = re.compile("document.cookie='(.+?)';").findall(response)
 | 
					 | 
				
			||||||
            if cookie and str(cookie[0]) != str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")):
 | 
					 | 
				
			||||||
                cookie = cookie[0]
 | 
					 | 
				
			||||||
                self.log('ok found new cookie: ' + str(cookie))
 | 
					 | 
				
			||||||
                sys.modules["__main__"].__settings__.setSetting("rutor-auth", cookie)
 | 
					 | 
				
			||||||
                headers = [('User-Agent',
 | 
					 | 
				
			||||||
                            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 YaBrowser/14.10.2062.12061 Safari/537.36'),
 | 
					 | 
				
			||||||
                           ('Referer', 'http://%s' % self.baseurl), ('Accept-encoding', 'gzip'),
 | 
					 | 
				
			||||||
                           ('Cookie', str(sys.modules["__main__"].__settings__.getSetting("rutor-auth")))]
 | 
					 | 
				
			||||||
                response = self.makeRequest(url, headers=headers)
 | 
					 | 
				
			||||||
                self.debug(response)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if category:
 | 
					 | 
				
			||||||
                contentList = self.mode(response.decode('utf-8'))
 | 
					 | 
				
			||||||
        self.debug(str(contentList))
 | 
					 | 
				
			||||||
        return contentList
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def mode(self, response):
 | 
					 | 
				
			||||||
        contentList = []
 | 
					 | 
				
			||||||
        num = 101
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        regex = '''<tr class="[tg].+?</tr>'''
 | 
					 | 
				
			||||||
        regex_tr = '<td>(.+?)</td><td ><a.+?href="(.+?download/\d+)">.+?<a href=".+?">.+?<a href="(.+?)">(.+?)</a></td>.+?<td align="right">(\d*?\..+? .+?)</td>.+?<img .+?alt="S".+?> (\d+)</span>.+?alt="L".+?> (\d+)'
 | 
					 | 
				
			||||||
        for tr in re.compile(regex, re.DOTALL).findall(response):
 | 
					 | 
				
			||||||
            result=re.compile(regex_tr, re.DOTALL).findall(tr)
 | 
					 | 
				
			||||||
            if result:
 | 
					 | 
				
			||||||
                self.debug(tr + ' -> ' + str(result[0]))
 | 
					 | 
				
			||||||
                (date, link, infolink, title, size, seeds, leechers)=result[0]
 | 
					 | 
				
			||||||
                # main
 | 
					 | 
				
			||||||
                info = {}
 | 
					 | 
				
			||||||
                num = num - 1
 | 
					 | 
				
			||||||
                original_title = None
 | 
					 | 
				
			||||||
                year = 0
 | 
					 | 
				
			||||||
                img = ''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # info
 | 
					 | 
				
			||||||
                title = self.unescape(self.stripHtml(title.strip()))
 | 
					 | 
				
			||||||
                info['label'] = info['title'] = title
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if link[0] == '/': link = 'http://%s%s' % (self.baseurl, link)
 | 
					 | 
				
			||||||
                info['link'] = link
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                #if infolink[0] == '/': infolink = 'http://%s%s' % (self.baseurl, infolink)
 | 
					 | 
				
			||||||
                #info['infolink'] = infolink
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                size = size.replace(' ', ' ')
 | 
					 | 
				
			||||||
                date = date.replace(' ', ' ')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s: %s' % (
 | 
					 | 
				
			||||||
                size, seeds, leechers, self.localize('Date'), date)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                #regex_title = '(.+?) / (.+?) \((\d\d\d\d)\)'
 | 
					 | 
				
			||||||
                #regex_result = re.compile(regex_title, re.DOTALL).findall(title)
 | 
					 | 
				
			||||||
                #if regex_result:
 | 
					 | 
				
			||||||
                #    title, original_title, year = regex_result[0]
 | 
					 | 
				
			||||||
                #    info['title'] = title
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                contentList.append((
 | 
					 | 
				
			||||||
                    int(int(self.sourceWeight) * (int(num))),
 | 
					 | 
				
			||||||
                    original_title, title, int(year), img, info,
 | 
					 | 
				
			||||||
                ))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return contentList
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_info(self, url):
 | 
					 | 
				
			||||||
        self.debug = self.log
 | 
					 | 
				
			||||||
        movieInfo = {}
 | 
					 | 
				
			||||||
        color = '[COLOR blue]%s:[/COLOR] %s\r\n'
 | 
					 | 
				
			||||||
        response = self.makeRequest(url, headers=self.headers)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if None != response and 0 < len(response):
 | 
					 | 
				
			||||||
            Soup = BeautifulSoup(response)
 | 
					 | 
				
			||||||
            result = Soup.find('div', 'torrentMediaInfo')
 | 
					 | 
				
			||||||
            if not result:
 | 
					 | 
				
			||||||
                return None
 | 
					 | 
				
			||||||
            li = result.findAll('li')
 | 
					 | 
				
			||||||
            info, movieInfo = {'Cast': ''}, {'desc': '', 'poster': '', 'title': '', 'views': '0', 'rating': '50',
 | 
					 | 
				
			||||||
                                             'kinopoisk': ''}
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                img = result.find('a', {'class': 'movieCover'}).find('img').get('src')
 | 
					 | 
				
			||||||
                movieInfo['poster'] = img if img.startswith('http:') else 'http:' + img
 | 
					 | 
				
			||||||
            except:
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                movie = re.compile('View all <strong>(.+?)</strong> episodes</a>').match(str(result))
 | 
					 | 
				
			||||||
                if movie:
 | 
					 | 
				
			||||||
                    info['Movie'] = movie.group(1)
 | 
					 | 
				
			||||||
            except:
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
            for i in li:
 | 
					 | 
				
			||||||
                name = i.find('strong').text
 | 
					 | 
				
			||||||
                if name:
 | 
					 | 
				
			||||||
                    info[name.rstrip(':')] = i.text.replace(name, '', 1)
 | 
					 | 
				
			||||||
            plot = result.find('div', {'id': 'summary'})
 | 
					 | 
				
			||||||
            if plot:
 | 
					 | 
				
			||||||
                cut = plot.find('strong').text
 | 
					 | 
				
			||||||
                info['plot'] = plot.text.replace(cut, '', 1).replace('report summary', '')
 | 
					 | 
				
			||||||
            # print str(result)
 | 
					 | 
				
			||||||
            cast = re.compile('<a href="/movies/actor/.+?">(.+?)</a>').findall(str(result))
 | 
					 | 
				
			||||||
            if cast:
 | 
					 | 
				
			||||||
                for actor in cast:
 | 
					 | 
				
			||||||
                    info['Cast'] += actor + ", "
 | 
					 | 
				
			||||||
            if 'Genres' in info:
 | 
					 | 
				
			||||||
                info['Genres'] = info['Genres'].replace(', ', ',').replace(',', ', ')
 | 
					 | 
				
			||||||
            for key in info.keys():
 | 
					 | 
				
			||||||
                if not 'Movie' in info and info[key] == 'addto bookmarks':
 | 
					 | 
				
			||||||
                    movieInfo['title'] = self.unescape(key)
 | 
					 | 
				
			||||||
                    info['TV Show'] = self.unescape(key)
 | 
					 | 
				
			||||||
                if not 'plot' in info and 'Summary' in key:
 | 
					 | 
				
			||||||
                    info['plot'] = info[key]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for i in ['Movie', 'TV Show', 'Release date', 'Original run', 'Episode', 'Air date', 'Genres', 'Language',
 | 
					 | 
				
			||||||
                      'Director', 'Writers', 'Cast', 'Original run', 'IMDb rating', 'AniDB rating']:
 | 
					 | 
				
			||||||
                if info.get(i) and info.get(i) not in ['']:
 | 
					 | 
				
			||||||
                    movieInfo['desc'] += color % (i, info.get(i))
 | 
					 | 
				
			||||||
                    if i == 'Movie':
 | 
					 | 
				
			||||||
                        movieInfo['title'] = info.get(i)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for i in ['plot', 'IMDb link', 'RottenTomatoes']:
 | 
					 | 
				
			||||||
                if info.get(i) and info.get(i) not in ['']:
 | 
					 | 
				
			||||||
                    if i == 'plot':
 | 
					 | 
				
			||||||
                        movieInfo['desc'] += '\r\n[COLOR blue]Plot:[/COLOR]\r\n' + self.unescape(info.get(i))
 | 
					 | 
				
			||||||
                    if i == 'RottenTomatoes':
 | 
					 | 
				
			||||||
                        movieInfo['rating'] = str(info.get(i).split('%')[0])
 | 
					 | 
				
			||||||
                    if i == 'IMDb link':
 | 
					 | 
				
			||||||
                        movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.debug(str(movieInfo))
 | 
					 | 
				
			||||||
        return movieInfo
 | 
					 | 
				
			||||||
@ -23,7 +23,6 @@ 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'},
 | 
				
			||||||
@ -46,11 +45,11 @@ class ThePirateBaySe(Content.Content):
 | 
				
			|||||||
		'heb_movies': ('סרטים מדובבים', '/search/Hebrew-dubbed/0/7/0'),
 | 
							'heb_movies': ('סרטים מדובבים', '/search/Hebrew-dubbed/0/7/0'),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    baseurl = "http://thepiratebay.ae"
 | 
					    baseurl = "thepiratebay.rs"
 | 
				
			||||||
    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://thepiratebay.ae/'), ('Accept-Encoding', 'gzip')]
 | 
					               ('Referer', 'http://kickass.so/'), ('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.
 | 
				
			||||||
@ -83,8 +82,7 @@ class ThePirateBaySe(Content.Content):
 | 
				
			|||||||
        contentList = []
 | 
					        contentList = []
 | 
				
			||||||
        url = self.get_url(category, subcategory, apps_property)
 | 
					        url = self.get_url(category, subcategory, apps_property)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        import requests
 | 
					        response = self.open2(url)
 | 
				
			||||||
        response = requests.get(url).text
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if None != response and 0 < len(response):
 | 
					        if None != response and 0 < len(response):
 | 
				
			||||||
            # print response
 | 
					            # print response
 | 
				
			||||||
@ -93,35 +91,40 @@ 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 = []
 | 
				
			||||||
        self.debug = self.log
 | 
					        # print str(result)
 | 
				
			||||||
        num = 31
 | 
					        num = 31
 | 
				
			||||||
        self.debug(response)
 | 
					        result = re.compile(
 | 
				
			||||||
        regex = '''<tr>.+?</tr>'''
 | 
					            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 = r'<div class="detName">.+?">(.+?)</a>.+?<a href="(.+?)".+?<font class="detDesc">Uploaded (.+?), Size (.+?), .+?</font>.+?<td align="right">(\d+?)</td>.+?<td align="right">(\d+?)</td>'
 | 
					            re.DOTALL).findall(response)
 | 
				
			||||||
        for tr in re.compile(regex, re.DOTALL).findall(response):
 | 
					        for title, link, date, size, seeds, leechers in result:
 | 
				
			||||||
            result = re.compile(regex_tr, re.DOTALL).findall(tr)
 | 
					            info = {}
 | 
				
			||||||
            self.debug(tr + ' -> ' + str(result))
 | 
					            num = num - 1
 | 
				
			||||||
            if result:
 | 
					            original_title = None
 | 
				
			||||||
                (title, link, date, size, seeds, leechers) = result[0]
 | 
					            year = 0
 | 
				
			||||||
 | 
					            img = ''
 | 
				
			||||||
 | 
					            size = size.replace(' ', ' ')
 | 
				
			||||||
 | 
					            date = self.stripHtml(date.replace(' ', ' '))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                info = {}
 | 
					            # info
 | 
				
			||||||
                num = num - 1
 | 
					 | 
				
			||||||
                original_title = None
 | 
					 | 
				
			||||||
                year = 0
 | 
					 | 
				
			||||||
                img = ''
 | 
					 | 
				
			||||||
                size = size.replace(' ', ' ')
 | 
					 | 
				
			||||||
                date = self.stripHtml(date.replace(' ', ' '))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # info
 | 
					            info['label'] = info['title'] = self.unescape(title)
 | 
				
			||||||
 | 
					            info['link'] = link
 | 
				
			||||||
                info['label'] = info['title'] = self.unescape(title)
 | 
					            info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date)
 | 
				
			||||||
                info['link'] = link
 | 
					            contentList.append((
 | 
				
			||||||
                self.log(info['link'])
 | 
					                int(int(self.sourceWeight) * (int(num))),
 | 
				
			||||||
                info['plot'] = info['title'] + '\r\n[I](%s) [S/L: %s/%s] [/I]\r\n%s' % (size, seeds, leechers, date)
 | 
					                original_title, title, int(year), img, info,
 | 
				
			||||||
                contentList.append((
 | 
					            ))
 | 
				
			||||||
                    int(int(self.sourceWeight) * (int(num))),
 | 
					 | 
				
			||||||
                    original_title, title, int(year), img, info,
 | 
					 | 
				
			||||||
                ))
 | 
					 | 
				
			||||||
        return contentList
 | 
					        return contentList
 | 
				
			||||||
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 95 B  | 
@ -44,13 +44,9 @@
 | 
				
			|||||||
    <string id="30044">Save files</string>
 | 
					    <string id="30044">Save files</string>
 | 
				
			||||||
    <string id="30045">Ask to save</string>
 | 
					    <string id="30045">Ask to save</string>
 | 
				
			||||||
    <string id="30046">Torrent2HTTP (libtorrent via http)</string>
 | 
					    <string id="30046">Torrent2HTTP (libtorrent via http)</string>
 | 
				
			||||||
    <string id="30047">Proxy for Search</string>
 | 
					    <string id="30047">Auto-unblocking proxy</string>
 | 
				
			||||||
    <string id="31047">Proxy for Content Lists</string>
 | 
					 | 
				
			||||||
    <string id="32047">SOCKS-proxy IP</string>
 | 
					 | 
				
			||||||
    <string id="32048">SOCKS-proxy Port</string>
 | 
					 | 
				
			||||||
    <string id="30048">None</string>
 | 
					    <string id="30048">None</string>
 | 
				
			||||||
    <string id="30049">Anti-zapret</string>
 | 
					    <string id="30049">Anti-zapret</string>
 | 
				
			||||||
    <string id="31050">Tor</string>
 | 
					 | 
				
			||||||
    <string id="30050">Immunicity</string>
 | 
					    <string id="30050">Immunicity</string>
 | 
				
			||||||
    <string id="30051">Max. connections (0 - unlimited)</string>
 | 
					    <string id="30051">Max. connections (0 - unlimited)</string>
 | 
				
			||||||
    <string id="30052">Use random ports</string>
 | 
					    <string id="30052">Use random ports</string>
 | 
				
			||||||
@ -71,25 +67,11 @@
 | 
				
			|||||||
    <string id="30067">Aeon Nox (by joyrider)</string>
 | 
					    <string id="30067">Aeon Nox (by joyrider)</string>
 | 
				
			||||||
    <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="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>
 | 
				
			||||||
 | 
				
			|||||||
@ -44,10 +44,9 @@
 | 
				
			|||||||
    <string id="30044">שמור קבצים</string>
 | 
					    <string id="30044">שמור קבצים</string>
 | 
				
			||||||
    <string id="30045">שאל לשמירה</string>
 | 
					    <string id="30045">שאל לשמירה</string>
 | 
				
			||||||
    <string id="30046">Torrent2HTTP (python-libtorrent via http)</string>
 | 
					    <string id="30046">Torrent2HTTP (python-libtorrent via http)</string>
 | 
				
			||||||
    <string id="30047">Proxy</string>
 | 
					    <string id="30047">ביטול אוטומטי של חסימת proxy</string>
 | 
				
			||||||
    <string id="30048">ללא</string>
 | 
					    <string id="30048">ללא</string>
 | 
				
			||||||
    <string id="30049">Anti-zapret</string>
 | 
					    <string id="30049">Anti-zapret</string>
 | 
				
			||||||
    <string id="31050">Tor</string>
 | 
					 | 
				
			||||||
    <string id="30050">Immunicity</string>
 | 
					    <string id="30050">Immunicity</string>
 | 
				
			||||||
    <string id="30101">ממשק</string>
 | 
					    <string id="30101">ממשק</string>
 | 
				
			||||||
    <string id="30102">רשת P2P</string>
 | 
					    <string id="30102">רשת P2P</string>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,98 +0,0 @@
 | 
				
			|||||||
<?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</string>
 | 
					 | 
				
			||||||
    <string id="30048">Ki</string>
 | 
					 | 
				
			||||||
    <string id="30049">Anti-zapret</string>
 | 
					 | 
				
			||||||
    <string id="31050">Tor</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>
 | 
					 | 
				
			||||||
@ -44,13 +44,9 @@
 | 
				
			|||||||
    <string id="30044">Сохранять файлы</string>
 | 
					    <string id="30044">Сохранять файлы</string>
 | 
				
			||||||
    <string id="30045">Спросить о сохранении</string>
 | 
					    <string id="30045">Спросить о сохранении</string>
 | 
				
			||||||
    <string id="30046">Torrent2HTTP (libtorrent по http)</string>
 | 
					    <string id="30046">Torrent2HTTP (libtorrent по http)</string>
 | 
				
			||||||
    <string id="30047">Прокси для поиска</string>
 | 
					    <string id="30047">Антизапрет (прокси)</string>
 | 
				
			||||||
    <string id="31047">Прокси для списков медиа</string>
 | 
					 | 
				
			||||||
    <string id="32047">IP SOCKS-прокси</string>
 | 
					 | 
				
			||||||
    <string id="32048">Порт SOCKS-прокси</string>
 | 
					 | 
				
			||||||
    <string id="30048">Не использовать</string>
 | 
					    <string id="30048">Не использовать</string>
 | 
				
			||||||
    <string id="30049">Anti-zapret</string>
 | 
					    <string id="30049">Anti-zapret</string>
 | 
				
			||||||
    <string id="31050">Tor</string>
 | 
					 | 
				
			||||||
    <string id="30050">Immunicity</string>
 | 
					    <string id="30050">Immunicity</string>
 | 
				
			||||||
    <string id="30051">Макс. соединений (0 - безлимит)</string>
 | 
					    <string id="30051">Макс. соединений (0 - безлимит)</string>
 | 
				
			||||||
    <string id="30052">Использовать случайные порты</string>
 | 
					    <string id="30052">Использовать случайные порты</string>
 | 
				
			||||||
@ -71,25 +67,11 @@
 | 
				
			|||||||
    <string id="30067">Aeon Nox (от joyrider)</string>
 | 
					    <string id="30067">Aeon Nox (от joyrider)</string>
 | 
				
			||||||
    <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="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>
 | 
				
			||||||
 | 
				
			|||||||
@ -44,10 +44,9 @@
 | 
				
			|||||||
    <string id="30044">Uložiť súbory</string>
 | 
					    <string id="30044">Uložiť súbory</string>
 | 
				
			||||||
    <string id="30045">Ponúknuť uloženie</string>
 | 
					    <string id="30045">Ponúknuť uloženie</string>
 | 
				
			||||||
    <string id="30046">Torrent2HTTP (libtorrent cez http)</string>
 | 
					    <string id="30046">Torrent2HTTP (libtorrent cez http)</string>
 | 
				
			||||||
    <string id="30047">Proxy</string>
 | 
					    <string id="30047">Auto-odblokovanie proxy</string>
 | 
				
			||||||
    <string id="30048"Žiadny</string>
 | 
					    <string id="30048"Žiadny</string>
 | 
				
			||||||
    <string id="30049">Anti-zapret</string>
 | 
					    <string id="30049">Anti-zapret</string>
 | 
				
			||||||
    <string id="31050">Tor</string>
 | 
					 | 
				
			||||||
    <string id="30050">Immunicity</string>
 | 
					    <string id="30050">Immunicity</string>
 | 
				
			||||||
    <string id="30051">Max. pripojenia (0 - neobmedzene)</string>
 | 
					    <string id="30051">Max. pripojenia (0 - neobmedzene)</string>
 | 
				
			||||||
    <string id="30052">Požit náhodný port</string>
 | 
					    <string id="30052">Požit náhodný port</string>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,111 +0,0 @@
 | 
				
			|||||||
<?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">Proxy</string>
 | 
					 | 
				
			||||||
    <string id="30048">Ninguno</string>
 | 
					 | 
				
			||||||
    <string id="30049">Anti-zapret (antirestricción)</string>
 | 
					 | 
				
			||||||
    <string id="31050">Tor</string>
 | 
					 | 
				
			||||||
    <string id="30050">Inmunidad</string>
 | 
					 | 
				
			||||||
    <string id="30051">Núm. máx. de conexiones (0 = ilimitadas)</string>
 | 
					 | 
				
			||||||
    <string id="30052">Utilizar puertos aleatorios</string>
 | 
					 | 
				
			||||||
    <string id="30053">Puerto para conexiones entrantes</string>
 | 
					 | 
				
			||||||
    <string id="30054">Tamaño de precarga para empezar a reproducir (MB)</string>
 | 
					 | 
				
			||||||
    <string id="30055">Autorreproducir episodio siguiente (o preguntar)</string>
 | 
					 | 
				
			||||||
    <string id="30056">Configuración de dispositivo</string>
 | 
					 | 
				
			||||||
    <string id="30057">Promedio/Buen PC</string>
 | 
					 | 
				
			||||||
    <string id="30058">Por debajo de la media, PC/router</string>
 | 
					 | 
				
			||||||
    <string id="30059">Tamaño mínimo de almacenaje para autoborrado (GB)</string>
 | 
					 | 
				
			||||||
    <string id="30060">Diferir inicio del reproductor</string>
 | 
					 | 
				
			||||||
    <string id="30061">Ordenar resultados de la búsqueda</string>
 | 
					 | 
				
			||||||
    <string id="30062">Por fuentes</string>
 | 
					 | 
				
			||||||
    <string id="30063">No ordenar</string>
 | 
					 | 
				
			||||||
    <string id="30064">Por nombre</string>
 | 
					 | 
				
			||||||
    <string id="30065">Añadir al historial de vistos después del (%)</string>
 | 
					 | 
				
			||||||
    <string id="30066">Confluence (de safonov_ivan)</string>
 | 
					 | 
				
			||||||
    <string id="30067">Aeon Nox (de joyrider)</string>
 | 
					 | 
				
			||||||
    <string id="30068">pyrrent2http (python-libtorrent vía HTTP)</string>
 | 
					 | 
				
			||||||
    <string id="30069">Añadir tamaño a nombre de archivo</string>
 | 
					 | 
				
			||||||
    <string id="30070">Activar protocolo DHT</string>
 | 
					 | 
				
			||||||
    <string id="30071">Estuary (de DiMartino)</string>
 | 
					 | 
				
			||||||
    <string id="30072">Modo presentación de datos</string>
 | 
					 | 
				
			||||||
    <string id="30073">Al final</string>
 | 
					 | 
				
			||||||
    <string id="30074">Al principio</string>
 | 
					 | 
				
			||||||
    <string id="30075">En segunda línea</string>
 | 
					 | 
				
			||||||
    <string id="30076">Arctic: Zephyr (de xbmc00)</string>
 | 
					 | 
				
			||||||
    <string id="30101">Interfaz</string>
 | 
					 | 
				
			||||||
    <string id="30102">Red P2P</string>
 | 
					 | 
				
			||||||
    <string id="30103">Avanzado</string>
 | 
					 | 
				
			||||||
    <string id="30104">Cliente de BitTorrent</string>
 | 
					 | 
				
			||||||
    <string id="30105">Hentai (reajustes)</string>
 | 
					 | 
				
			||||||
    <string id="30106">Modo ventana de búsquedas</string>
 | 
					 | 
				
			||||||
    <string id="30107">Activado ocultar estilo anterior</string>
 | 
					 | 
				
			||||||
    <string id="30108">Activado remplazar estilo anterior</string>
 | 
					 | 
				
			||||||
    <string id="30109">Activado opcional</string>
 | 
					 | 
				
			||||||
    <string id="30110">Desactivado</string>
 | 
					 | 
				
			||||||
    <string id="30111">Fondo transparente de ventana de búsquedas</string>
 | 
					 | 
				
			||||||
    <string id="30112">Desactivar notificaciones</string>
 | 
					 | 
				
			||||||
    <string id="50301">Ruta para guardar</string>
 | 
					 | 
				
			||||||
    <string id="50302">Preguntar</string>
 | 
					 | 
				
			||||||
    <string id="50303">Por defecto</string>
 | 
					 | 
				
			||||||
    <string id="50304">Ruta</string>
 | 
					 | 
				
			||||||
    <string id="50305">Crear subdirectorio para scrapper</string>
 | 
					 | 
				
			||||||
    <string id="50312">Host</string>
 | 
					 | 
				
			||||||
    <string id="50313">Puerto</string>
 | 
					 | 
				
			||||||
    <string id="50314">URL</string>
 | 
					 | 
				
			||||||
    <string id="50315">Usuario</string>
 | 
					 | 
				
			||||||
    <string id="50316">Contraseña</string>
 | 
					 | 
				
			||||||
    <string id="50311">Cliente de BitTorrent</string>
 | 
					 | 
				
			||||||
    <string id="50317">URL (no SSL)</string>
 | 
					 | 
				
			||||||
    <string id="30426">Sustitución de ruta (Solo remoto)</string>
 | 
					 | 
				
			||||||
    <string id="30412">Cerrar</string>
 | 
					 | 
				
			||||||
    <string id="30413">Abrir "Ajustes"</string>
 | 
					 | 
				
			||||||
    <string id="30414">Navegador de cliente BitTorrent</string>
 | 
					 | 
				
			||||||
    <string id="30415">Instalar rastreadores</string>
 | 
					 | 
				
			||||||
    <string id="30416">Ajustes de rastreadores</string>
 | 
					 | 
				
			||||||
    <string id="30417">Vaciar almacén</string>
 | 
					 | 
				
			||||||
    <string id="30418">Seleccionar buscador</string>
 | 
					 | 
				
			||||||
    <string id="30419">No hay buscador externo. Instale uno primero.</string>
 | 
					 | 
				
			||||||
</strings>
 | 
					 | 
				
			||||||
@ -1,72 +1,66 @@
 | 
				
			|||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os, re, fnmatch, threading, urllib2, time, shelve, anydbm
 | 
					import os, re, fnmatch, threading, urllib2
 | 
				
			||||||
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_LIFETIME = 24 * 3600 # 24 hour caching
 | 
					CACHE = 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():
 | 
				
			||||||
    shelf = None
 | 
					    global _config
 | 
				
			||||||
    try:
 | 
					    if not _config:
 | 
				
			||||||
        CONFIG_LOCK.acquire()
 | 
					#        with shelf("antizapret.pac_config", ttl=CACHE) as pac_config:
 | 
				
			||||||
        filename = os.path.join(CACHE_DIR, "antizapret.pac_config2")
 | 
					        d = shelf("antizapret.pac_config2", ttl=CACHE)
 | 
				
			||||||
        try:
 | 
					        pac_config = d['data']
 | 
				
			||||||
            shelf = shelve.open(filename)
 | 
					        if not pac_config:
 | 
				
			||||||
        except anydbm.error:
 | 
					            log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
 | 
				
			||||||
            os.remove(filename)
 | 
					            try:
 | 
				
			||||||
            shelf = shelve.open(filename)
 | 
					                pac_data = urllib2.urlopen(PAC_URL).read()
 | 
				
			||||||
 | 
					            except:
 | 
				
			||||||
 | 
					                pac_data = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        created_at = 0
 | 
					            r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
 | 
				
			||||||
        data = {}
 | 
					            if r:
 | 
				
			||||||
 | 
					                pac_config["server"] = r.group(1)
 | 
				
			||||||
        if 'created_at' in shelf:
 | 
					                pac_config["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
 | 
				
			||||||
            created_at = shelf['created_at']
 | 
					            else:
 | 
				
			||||||
 | 
					                pac_config["server"] = None
 | 
				
			||||||
        if 'data' in shelf:
 | 
					                pac_config["domains"] = []
 | 
				
			||||||
            data = shelf['data']
 | 
					        d.close()
 | 
				
			||||||
 | 
					        _config = pac_config
 | 
				
			||||||
        if((time.time() - created_at) <= CACHE_LIFETIME
 | 
					    return _config
 | 
				
			||||||
                and 'domains' in data
 | 
					 | 
				
			||||||
                and len(data['domains']) > 0):
 | 
					 | 
				
			||||||
            return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        log("[antizapret]: Fetching Antizapret PAC file on %s" %PAC_URL)
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            pac_data = urllib2.urlopen(PAC_URL).read()
 | 
					 | 
				
			||||||
        except:
 | 
					 | 
				
			||||||
            pac_data = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        r = re.search(r"\"PROXY (.*); DIRECT", pac_data)
 | 
					 | 
				
			||||||
        if r:
 | 
					 | 
				
			||||||
            data["server"] = r.group(1)
 | 
					 | 
				
			||||||
            data["domains"] = map(lambda x: x.replace(r"\Z(?ms)", "").replace("\\", ""), map(fnmatch.translate, re.findall(r"\"(.*?)\",", pac_data)))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            data["server"] = None
 | 
					 | 
				
			||||||
            data["domains"] = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        shelf.clear()
 | 
					 | 
				
			||||||
        shelf.update({
 | 
					 | 
				
			||||||
            "created_at": time.time(),
 | 
					 | 
				
			||||||
            "data": data,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        return data
 | 
					 | 
				
			||||||
    except Exception as ex:
 | 
					 | 
				
			||||||
        debug("[antizapret]: " + str(ex))
 | 
					 | 
				
			||||||
        raise
 | 
					 | 
				
			||||||
    finally:
 | 
					 | 
				
			||||||
        if shelf:
 | 
					 | 
				
			||||||
            shelf.close()
 | 
					 | 
				
			||||||
        if CONFIG_LOCK.locked():
 | 
					 | 
				
			||||||
            CONFIG_LOCK.release()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AntizapretProxyHandler(urllib2.ProxyHandler, object):
 | 
					class AntizapretProxyHandler(urllib2.ProxyHandler, object):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
@ -79,8 +73,7 @@ class AntizapretProxyHandler(urllib2.ProxyHandler, object):
 | 
				
			|||||||
    def proxy_open(self, req, proxy, type):
 | 
					    def proxy_open(self, req, proxy, type):
 | 
				
			||||||
        import socket
 | 
					        import socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        hostname = req.get_host().split(":")[0]
 | 
					        if socket.gethostbyname(req.get_host().split(":")[0]) in self.config["domains"]:
 | 
				
			||||||
        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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,3 +105,4 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,802 +0,0 @@
 | 
				
			|||||||
"""
 | 
					 | 
				
			||||||
SocksiPy - Python SOCKS module.
 | 
					 | 
				
			||||||
Version 1.6.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright 2006 Dan-Haim. All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Redistribution and use in source and binary forms, with or without modification,
 | 
					 | 
				
			||||||
are permitted provided that the following conditions are met:
 | 
					 | 
				
			||||||
1. Redistributions of source code must retain the above copyright notice, this
 | 
					 | 
				
			||||||
   list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
2. Redistributions in binary form must reproduce the above copyright notice,
 | 
					 | 
				
			||||||
   this list of conditions and the following disclaimer in the documentation
 | 
					 | 
				
			||||||
   and/or other materials provided with the distribution.
 | 
					 | 
				
			||||||
3. Neither the name of Dan Haim nor the names of his contributors may be used
 | 
					 | 
				
			||||||
   to endorse or promote products derived from this software without specific
 | 
					 | 
				
			||||||
   prior written permission.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
					 | 
				
			||||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
					 | 
				
			||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | 
					 | 
				
			||||||
EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
					 | 
				
			||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
 | 
					 | 
				
			||||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
					 | 
				
			||||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
					 | 
				
			||||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This module provides a standard socket-like interface for Python
 | 
					 | 
				
			||||||
for tunneling connections through SOCKS proxies.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
===============================================================================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Minor modifications made by Christopher Gilbert (http://motomastyle.com/)
 | 
					 | 
				
			||||||
for use in PyLoris (http://pyloris.sourceforge.net/)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/)
 | 
					 | 
				
			||||||
mainly to merge bug fixes found in Sourceforge
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Modifications made by Anorov (https://github.com/Anorov)
 | 
					 | 
				
			||||||
-Forked and renamed to PySocks
 | 
					 | 
				
			||||||
-Fixed issue with HTTP proxy failure checking (same bug that was in the old ___recvall() method)
 | 
					 | 
				
			||||||
-Included SocksiPyHandler (sockshandler.py), to be used as a urllib2 handler,
 | 
					 | 
				
			||||||
 courtesy of e000 (https://github.com/e000): https://gist.github.com/869791#file_socksipyhandler.py
 | 
					 | 
				
			||||||
-Re-styled code to make it readable
 | 
					 | 
				
			||||||
    -Aliased PROXY_TYPE_SOCKS5 -> SOCKS5 etc.
 | 
					 | 
				
			||||||
    -Improved exception handling and output
 | 
					 | 
				
			||||||
    -Removed irritating use of sequence indexes, replaced with tuple unpacked variables
 | 
					 | 
				
			||||||
    -Fixed up Python 3 bytestring handling - chr(0x03).encode() -> b"\x03"
 | 
					 | 
				
			||||||
    -Other general fixes
 | 
					 | 
				
			||||||
-Added clarification that the HTTP proxy connection method only supports CONNECT-style tunneling HTTP proxies
 | 
					 | 
				
			||||||
-Various small bug fixes
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__version__ = "1.6.5"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import socket
 | 
					 | 
				
			||||||
import struct
 | 
					 | 
				
			||||||
from errno import EOPNOTSUPP, EINVAL, EAGAIN
 | 
					 | 
				
			||||||
from io import BytesIO
 | 
					 | 
				
			||||||
from os import SEEK_CUR
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
from collections import Callable
 | 
					 | 
				
			||||||
from base64 import b64encode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if os.name == "nt" and sys.version_info < (3, 0):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        from resources.proxy import win_inet_pton
 | 
					 | 
				
			||||||
    except ImportError:
 | 
					 | 
				
			||||||
        raise ImportError("To run PySocks on Windows you must install win_inet_pton")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PROXY_TYPE_SOCKS4 = SOCKS4 = 1
 | 
					 | 
				
			||||||
PROXY_TYPE_SOCKS5 = SOCKS5 = 2
 | 
					 | 
				
			||||||
PROXY_TYPE_HTTP = HTTP = 3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PROXY_TYPES = {"SOCKS4": SOCKS4, "SOCKS5": SOCKS5, "HTTP": HTTP}
 | 
					 | 
				
			||||||
PRINTABLE_PROXY_TYPES = dict(zip(PROXY_TYPES.values(), PROXY_TYPES.keys()))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_orgsocket = _orig_socket = socket.socket
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ProxyError(IOError):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    socket_err contains original socket.error exception.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    def __init__(self, msg, socket_err=None):
 | 
					 | 
				
			||||||
        self.msg = msg
 | 
					 | 
				
			||||||
        self.socket_err = socket_err
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if socket_err:
 | 
					 | 
				
			||||||
            self.msg += ": {0}".format(socket_err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__(self):
 | 
					 | 
				
			||||||
        return self.msg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class GeneralProxyError(ProxyError): pass
 | 
					 | 
				
			||||||
class ProxyConnectionError(ProxyError): pass
 | 
					 | 
				
			||||||
class SOCKS5AuthError(ProxyError): pass
 | 
					 | 
				
			||||||
class SOCKS5Error(ProxyError): pass
 | 
					 | 
				
			||||||
class SOCKS4Error(ProxyError): pass
 | 
					 | 
				
			||||||
class HTTPError(ProxyError): pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SOCKS4_ERRORS = { 0x5B: "Request rejected or failed",
 | 
					 | 
				
			||||||
                  0x5C: "Request rejected because SOCKS server cannot connect to identd on the client",
 | 
					 | 
				
			||||||
                  0x5D: "Request rejected because the client program and identd report different user-ids"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SOCKS5_ERRORS = { 0x01: "General SOCKS server failure",
 | 
					 | 
				
			||||||
                  0x02: "Connection not allowed by ruleset",
 | 
					 | 
				
			||||||
                  0x03: "Network unreachable",
 | 
					 | 
				
			||||||
                  0x04: "Host unreachable",
 | 
					 | 
				
			||||||
                  0x05: "Connection refused",
 | 
					 | 
				
			||||||
                  0x06: "TTL expired",
 | 
					 | 
				
			||||||
                  0x07: "Command not supported, or protocol error",
 | 
					 | 
				
			||||||
                  0x08: "Address type not supported"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEFAULT_PORTS = { SOCKS4: 1080,
 | 
					 | 
				
			||||||
                  SOCKS5: 1080,
 | 
					 | 
				
			||||||
                  HTTP: 8080
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    set_default_proxy(proxy_type, addr[, port[, rdns[, username, password]]])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Sets a default proxy which all further socksocket objects will use,
 | 
					 | 
				
			||||||
    unless explicitly changed. All parameters are as for socket.set_proxy().
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    socksocket.default_proxy = (proxy_type, addr, port, rdns,
 | 
					 | 
				
			||||||
                                username.encode() if username else None,
 | 
					 | 
				
			||||||
                                password.encode() if password else None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
setdefaultproxy = set_default_proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_default_proxy():
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Returns the default proxy, set by set_default_proxy.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    return socksocket.default_proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
getdefaultproxy = get_default_proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def wrap_module(module):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Attempts to replace a module's socket library with a SOCKS socket. Must set
 | 
					 | 
				
			||||||
    a default proxy using set_default_proxy(...) first.
 | 
					 | 
				
			||||||
    This will only work on modules that import socket directly into the namespace;
 | 
					 | 
				
			||||||
    most of the Python Standard Library falls into this category.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    if socksocket.default_proxy:
 | 
					 | 
				
			||||||
        module.socket.socket = socksocket
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        raise GeneralProxyError("No default proxy specified")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
wrapmodule = wrap_module
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def create_connection(dest_pair, proxy_type=None, proxy_addr=None,
 | 
					 | 
				
			||||||
                      proxy_port=None, proxy_rdns=True,
 | 
					 | 
				
			||||||
                      proxy_username=None, proxy_password=None,
 | 
					 | 
				
			||||||
                      timeout=None, source_address=None,
 | 
					 | 
				
			||||||
                      socket_options=None):
 | 
					 | 
				
			||||||
    """create_connection(dest_pair, *[, timeout], **proxy_args) -> socket object
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Like socket.create_connection(), but connects to proxy
 | 
					 | 
				
			||||||
    before returning the socket object.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dest_pair - 2-tuple of (IP/hostname, port).
 | 
					 | 
				
			||||||
    **proxy_args - Same args passed to socksocket.set_proxy() if present.
 | 
					 | 
				
			||||||
    timeout - Optional socket timeout value, in seconds.
 | 
					 | 
				
			||||||
    source_address - tuple (host, port) for the socket to bind to as its source
 | 
					 | 
				
			||||||
    address before connecting (only for compatibility)
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    # Remove IPv6 brackets on the remote address and proxy address.
 | 
					 | 
				
			||||||
    remote_host, remote_port = dest_pair
 | 
					 | 
				
			||||||
    if remote_host.startswith('['):
 | 
					 | 
				
			||||||
        remote_host = remote_host.strip('[]')
 | 
					 | 
				
			||||||
    if proxy_addr and proxy_addr.startswith('['):
 | 
					 | 
				
			||||||
        proxy_addr = proxy_addr.strip('[]')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    err = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Allow the SOCKS proxy to be on IPv4 or IPv6 addresses.
 | 
					 | 
				
			||||||
    for r in socket.getaddrinfo(proxy_addr, proxy_port, 0, socket.SOCK_STREAM):
 | 
					 | 
				
			||||||
        family, socket_type, proto, canonname, sa = r
 | 
					 | 
				
			||||||
        sock = None
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            sock = socksocket(family, socket_type, proto)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if socket_options:
 | 
					 | 
				
			||||||
                for opt in socket_options:
 | 
					 | 
				
			||||||
                    sock.setsockopt(*opt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if isinstance(timeout, (int, float)):
 | 
					 | 
				
			||||||
                sock.settimeout(timeout)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if proxy_type:
 | 
					 | 
				
			||||||
                sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns,
 | 
					 | 
				
			||||||
                               proxy_username, proxy_password)
 | 
					 | 
				
			||||||
            if source_address:
 | 
					 | 
				
			||||||
                sock.bind(source_address)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            sock.connect((remote_host, remote_port))
 | 
					 | 
				
			||||||
            return sock
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        except (socket.error, ProxyConnectionError) as e:
 | 
					 | 
				
			||||||
            err = e
 | 
					 | 
				
			||||||
            if sock:
 | 
					 | 
				
			||||||
                sock.close()
 | 
					 | 
				
			||||||
                sock = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if err:
 | 
					 | 
				
			||||||
        raise err
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    raise socket.error("gai returned empty list.")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class _BaseSocket(socket.socket):
 | 
					 | 
				
			||||||
    """Allows Python 2's "delegated" methods such as send() to be overridden
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    def __init__(self, *pos, **kw):
 | 
					 | 
				
			||||||
        _orig_socket.__init__(self, *pos, **kw)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self._savedmethods = dict()
 | 
					 | 
				
			||||||
        for name in self._savenames:
 | 
					 | 
				
			||||||
            self._savedmethods[name] = getattr(self, name)
 | 
					 | 
				
			||||||
            delattr(self, name)  # Allows normal overriding mechanism to work
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _savenames = list()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _makemethod(name):
 | 
					 | 
				
			||||||
    return lambda self, *pos, **kw: self._savedmethods[name](*pos, **kw)
 | 
					 | 
				
			||||||
for name in ("sendto", "send", "recvfrom", "recv"):
 | 
					 | 
				
			||||||
    method = getattr(_BaseSocket, name, None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Determine if the method is not defined the usual way
 | 
					 | 
				
			||||||
    # as a function in the class.
 | 
					 | 
				
			||||||
    # Python 2 uses __slots__, so there are descriptors for each method,
 | 
					 | 
				
			||||||
    # but they are not functions.
 | 
					 | 
				
			||||||
    if not isinstance(method, Callable):
 | 
					 | 
				
			||||||
        _BaseSocket._savenames.append(name)
 | 
					 | 
				
			||||||
        setattr(_BaseSocket, name, _makemethod(name))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class socksocket(_BaseSocket):
 | 
					 | 
				
			||||||
    """socksocket([family[, type[, proto]]]) -> socket object
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Open a SOCKS enabled socket. The parameters are the same as
 | 
					 | 
				
			||||||
    those of the standard socket init. In order for SOCKS to work,
 | 
					 | 
				
			||||||
    you must specify family=AF_INET and proto=0.
 | 
					 | 
				
			||||||
    The "type" argument must be either SOCK_STREAM or SOCK_DGRAM.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default_proxy = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, *args, **kwargs):
 | 
					 | 
				
			||||||
        if type not in (socket.SOCK_STREAM, socket.SOCK_DGRAM):
 | 
					 | 
				
			||||||
            msg = "Socket type must be stream or datagram, not {!r}"
 | 
					 | 
				
			||||||
            raise ValueError(msg.format(type))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _BaseSocket.__init__(self, family, type, proto, *args, **kwargs)
 | 
					 | 
				
			||||||
        self._proxyconn = None  # TCP connection to keep UDP relay alive
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.default_proxy:
 | 
					 | 
				
			||||||
            self.proxy = self.default_proxy
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            self.proxy = (None, None, None, None, None, None)
 | 
					 | 
				
			||||||
        self.proxy_sockname = None
 | 
					 | 
				
			||||||
        self.proxy_peername = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self._timeout = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _readall(self, file, count):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Receive EXACTLY the number of bytes requested from the file object.
 | 
					 | 
				
			||||||
        Blocks until the required number of bytes have been received.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        data = b""
 | 
					 | 
				
			||||||
        while len(data) < count:
 | 
					 | 
				
			||||||
            d = file.read(count - len(data))
 | 
					 | 
				
			||||||
            if not d:
 | 
					 | 
				
			||||||
                raise GeneralProxyError("Connection closed unexpectedly")
 | 
					 | 
				
			||||||
            data += d
 | 
					 | 
				
			||||||
        return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def settimeout(self, timeout):
 | 
					 | 
				
			||||||
        self._timeout = timeout
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            # test if we're connected, if so apply timeout
 | 
					 | 
				
			||||||
            peer = self.get_proxy_peername()
 | 
					 | 
				
			||||||
            _BaseSocket.settimeout(self, self._timeout)
 | 
					 | 
				
			||||||
        except socket.error:
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def gettimeout(self):
 | 
					 | 
				
			||||||
        return self._timeout
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setblocking(self, v):
 | 
					 | 
				
			||||||
        if v:
 | 
					 | 
				
			||||||
            self.settimeout(None)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            self.settimeout(0.0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def set_proxy(self, proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None):
 | 
					 | 
				
			||||||
        """set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]])
 | 
					 | 
				
			||||||
        Sets the proxy to be used.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        proxy_type -    The type of the proxy to be used. Three types
 | 
					 | 
				
			||||||
                        are supported: PROXY_TYPE_SOCKS4 (including socks4a),
 | 
					 | 
				
			||||||
                        PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
 | 
					 | 
				
			||||||
        addr -        The address of the server (IP or DNS).
 | 
					 | 
				
			||||||
        port -        The port of the server. Defaults to 1080 for SOCKS
 | 
					 | 
				
			||||||
                       servers and 8080 for HTTP proxy servers.
 | 
					 | 
				
			||||||
        rdns -        Should DNS queries be performed on the remote side
 | 
					 | 
				
			||||||
                       (rather than the local side). The default is True.
 | 
					 | 
				
			||||||
                       Note: This has no effect with SOCKS4 servers.
 | 
					 | 
				
			||||||
        username -    Username to authenticate with to the server.
 | 
					 | 
				
			||||||
                       The default is no authentication.
 | 
					 | 
				
			||||||
        password -    Password to authenticate with to the server.
 | 
					 | 
				
			||||||
                       Only relevant when username is also provided.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        self.proxy = (proxy_type, addr, port, rdns,
 | 
					 | 
				
			||||||
                      username.encode() if username else None,
 | 
					 | 
				
			||||||
                      password.encode() if password else None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setproxy = set_proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def bind(self, *pos, **kw):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Implements proxy connection for UDP sockets,
 | 
					 | 
				
			||||||
        which happens during the bind() phase.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        proxy_type, proxy_addr, proxy_port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
        if not proxy_type or self.type != socket.SOCK_DGRAM:
 | 
					 | 
				
			||||||
            return _orig_socket.bind(self, *pos, **kw)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self._proxyconn:
 | 
					 | 
				
			||||||
            raise socket.error(EINVAL, "Socket already bound to an address")
 | 
					 | 
				
			||||||
        if proxy_type != SOCKS5:
 | 
					 | 
				
			||||||
            msg = "UDP only supported by SOCKS5 proxy type"
 | 
					 | 
				
			||||||
            raise socket.error(EOPNOTSUPP, msg)
 | 
					 | 
				
			||||||
        _BaseSocket.bind(self, *pos, **kw)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Need to specify actual local port because
 | 
					 | 
				
			||||||
        # some relays drop packets if a port of zero is specified.
 | 
					 | 
				
			||||||
        # Avoid specifying host address in case of NAT though.
 | 
					 | 
				
			||||||
        _, port = self.getsockname()
 | 
					 | 
				
			||||||
        dst = ("0", port)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self._proxyconn = _orig_socket()
 | 
					 | 
				
			||||||
        proxy = self._proxy_addr()
 | 
					 | 
				
			||||||
        self._proxyconn.connect(proxy)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        UDP_ASSOCIATE = b"\x03"
 | 
					 | 
				
			||||||
        _, relay = self._SOCKS5_request(self._proxyconn, UDP_ASSOCIATE, dst)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # The relay is most likely on the same host as the SOCKS proxy,
 | 
					 | 
				
			||||||
        # but some proxies return a private IP address (10.x.y.z)
 | 
					 | 
				
			||||||
        host, _ = proxy
 | 
					 | 
				
			||||||
        _, port = relay
 | 
					 | 
				
			||||||
        _BaseSocket.connect(self, (host, port))
 | 
					 | 
				
			||||||
        _BaseSocket.settimeout(self, self._timeout)
 | 
					 | 
				
			||||||
        self.proxy_sockname = ("0.0.0.0", 0)  # Unknown
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def sendto(self, bytes, *args, **kwargs):
 | 
					 | 
				
			||||||
        if self.type != socket.SOCK_DGRAM:
 | 
					 | 
				
			||||||
            return _BaseSocket.sendto(self, bytes, *args, **kwargs)
 | 
					 | 
				
			||||||
        if not self._proxyconn:
 | 
					 | 
				
			||||||
            self.bind(("", 0))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        address = args[-1]
 | 
					 | 
				
			||||||
        flags = args[:-1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        header = BytesIO()
 | 
					 | 
				
			||||||
        RSV = b"\x00\x00"
 | 
					 | 
				
			||||||
        header.write(RSV)
 | 
					 | 
				
			||||||
        STANDALONE = b"\x00"
 | 
					 | 
				
			||||||
        header.write(STANDALONE)
 | 
					 | 
				
			||||||
        self._write_SOCKS5_address(address, header)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sent = _BaseSocket.send(self, header.getvalue() + bytes, *flags, **kwargs)
 | 
					 | 
				
			||||||
        return sent - header.tell()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def send(self, bytes, flags=0, **kwargs):
 | 
					 | 
				
			||||||
        if self.type == socket.SOCK_DGRAM:
 | 
					 | 
				
			||||||
            return self.sendto(bytes, flags, self.proxy_peername, **kwargs)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return _BaseSocket.send(self, bytes, flags, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def recvfrom(self, bufsize, flags=0):
 | 
					 | 
				
			||||||
        if self.type != socket.SOCK_DGRAM:
 | 
					 | 
				
			||||||
            return _BaseSocket.recvfrom(self, bufsize, flags)
 | 
					 | 
				
			||||||
        if not self._proxyconn:
 | 
					 | 
				
			||||||
            self.bind(("", 0))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        buf = BytesIO(_BaseSocket.recv(self, bufsize + 1024, flags))
 | 
					 | 
				
			||||||
        buf.seek(2, SEEK_CUR)
 | 
					 | 
				
			||||||
        frag = buf.read(1)
 | 
					 | 
				
			||||||
        if ord(frag):
 | 
					 | 
				
			||||||
            raise NotImplementedError("Received UDP packet fragment")
 | 
					 | 
				
			||||||
        fromhost, fromport = self._read_SOCKS5_address(buf)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.proxy_peername:
 | 
					 | 
				
			||||||
            peerhost, peerport = self.proxy_peername
 | 
					 | 
				
			||||||
            if fromhost != peerhost or peerport not in (0, fromport):
 | 
					 | 
				
			||||||
                raise socket.error(EAGAIN, "Packet filtered")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (buf.read(bufsize), (fromhost, fromport))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def recv(self, *pos, **kw):
 | 
					 | 
				
			||||||
        bytes, _ = self.recvfrom(*pos, **kw)
 | 
					 | 
				
			||||||
        return bytes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					 | 
				
			||||||
        if self._proxyconn:
 | 
					 | 
				
			||||||
            self._proxyconn.close()
 | 
					 | 
				
			||||||
        return _BaseSocket.close(self)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_proxy_sockname(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Returns the bound IP address and port number at the proxy.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return self.proxy_sockname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getproxysockname = get_proxy_sockname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_proxy_peername(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Returns the IP and port number of the proxy.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return _BaseSocket.getpeername(self)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getproxypeername = get_proxy_peername
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_peername(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Returns the IP address and port number of the destination
 | 
					 | 
				
			||||||
        machine (note: get_proxy_peername returns the proxy)
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return self.proxy_peername
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getpeername = get_peername
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _negotiate_SOCKS5(self, *dest_addr):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Negotiates a stream connection through a SOCKS5 server.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        CONNECT = b"\x01"
 | 
					 | 
				
			||||||
        self.proxy_peername, self.proxy_sockname = self._SOCKS5_request(self,
 | 
					 | 
				
			||||||
            CONNECT, dest_addr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _SOCKS5_request(self, conn, cmd, dst):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Send SOCKS5 request with given command (CMD field) and
 | 
					 | 
				
			||||||
        address (DST field). Returns resolved DST address that was used.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        proxy_type, addr, port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        writer = conn.makefile("wb")
 | 
					 | 
				
			||||||
        reader = conn.makefile("rb", 0)  # buffering=0 renamed in Python 3
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            # First we'll send the authentication packages we support.
 | 
					 | 
				
			||||||
            if username and password:
 | 
					 | 
				
			||||||
                # The username/password details were supplied to the
 | 
					 | 
				
			||||||
                # set_proxy method so we support the USERNAME/PASSWORD
 | 
					 | 
				
			||||||
                # authentication (in addition to the standard none).
 | 
					 | 
				
			||||||
                writer.write(b"\x05\x02\x00\x02")
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                # No username/password were entered, therefore we
 | 
					 | 
				
			||||||
                # only support connections with no authentication.
 | 
					 | 
				
			||||||
                writer.write(b"\x05\x01\x00")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # We'll receive the server's response to determine which
 | 
					 | 
				
			||||||
            # method was selected
 | 
					 | 
				
			||||||
            writer.flush()
 | 
					 | 
				
			||||||
            chosen_auth = self._readall(reader, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if chosen_auth[0:1] != b"\x05":
 | 
					 | 
				
			||||||
                # Note: string[i:i+1] is used because indexing of a bytestring
 | 
					 | 
				
			||||||
                # via bytestring[i] yields an integer in Python 3
 | 
					 | 
				
			||||||
                raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Check the chosen authentication method
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if chosen_auth[1:2] == b"\x02":
 | 
					 | 
				
			||||||
                # Okay, we need to perform a basic username/password
 | 
					 | 
				
			||||||
                # authentication.
 | 
					 | 
				
			||||||
                writer.write(b"\x01" + chr(len(username)).encode()
 | 
					 | 
				
			||||||
                             + username
 | 
					 | 
				
			||||||
                             + chr(len(password)).encode()
 | 
					 | 
				
			||||||
                             + password)
 | 
					 | 
				
			||||||
                writer.flush()
 | 
					 | 
				
			||||||
                auth_status = self._readall(reader, 2)
 | 
					 | 
				
			||||||
                if auth_status[0:1] != b"\x01":
 | 
					 | 
				
			||||||
                    # Bad response
 | 
					 | 
				
			||||||
                    raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
 | 
					 | 
				
			||||||
                if auth_status[1:2] != b"\x00":
 | 
					 | 
				
			||||||
                    # Authentication failed
 | 
					 | 
				
			||||||
                    raise SOCKS5AuthError("SOCKS5 authentication failed")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Otherwise, authentication succeeded
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # No authentication is required if 0x00
 | 
					 | 
				
			||||||
            elif chosen_auth[1:2] != b"\x00":
 | 
					 | 
				
			||||||
                # Reaching here is always bad
 | 
					 | 
				
			||||||
                if chosen_auth[1:2] == b"\xFF":
 | 
					 | 
				
			||||||
                    raise SOCKS5AuthError("All offered SOCKS5 authentication methods were rejected")
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Now we can request the actual connection
 | 
					 | 
				
			||||||
            writer.write(b"\x05" + cmd + b"\x00")
 | 
					 | 
				
			||||||
            resolved = self._write_SOCKS5_address(dst, writer)
 | 
					 | 
				
			||||||
            writer.flush()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Get the response
 | 
					 | 
				
			||||||
            resp = self._readall(reader, 3)
 | 
					 | 
				
			||||||
            if resp[0:1] != b"\x05":
 | 
					 | 
				
			||||||
                raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            status = ord(resp[1:2])
 | 
					 | 
				
			||||||
            if status != 0x00:
 | 
					 | 
				
			||||||
                # Connection failed: server returned an error
 | 
					 | 
				
			||||||
                error = SOCKS5_ERRORS.get(status, "Unknown error")
 | 
					 | 
				
			||||||
                raise SOCKS5Error("{0:#04x}: {1}".format(status, error))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Get the bound address/port
 | 
					 | 
				
			||||||
            bnd = self._read_SOCKS5_address(reader)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            _BaseSocket.settimeout(self, self._timeout)
 | 
					 | 
				
			||||||
            return (resolved, bnd)
 | 
					 | 
				
			||||||
        finally:
 | 
					 | 
				
			||||||
            reader.close()
 | 
					 | 
				
			||||||
            writer.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _write_SOCKS5_address(self, addr, file):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Return the host and port packed for the SOCKS5 protocol,
 | 
					 | 
				
			||||||
        and the resolved address as a tuple object.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        host, port = addr
 | 
					 | 
				
			||||||
        proxy_type, _, _, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
        family_to_byte = {socket.AF_INET: b"\x01", socket.AF_INET6: b"\x04"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # If the given destination address is an IP address, we'll
 | 
					 | 
				
			||||||
        # use the IP address request even if remote resolving was specified.
 | 
					 | 
				
			||||||
        # Detect whether the address is IPv4/6 directly.
 | 
					 | 
				
			||||||
        for family in (socket.AF_INET, socket.AF_INET6):
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                addr_bytes = socket.inet_pton(family, host)
 | 
					 | 
				
			||||||
                file.write(family_to_byte[family] + addr_bytes)
 | 
					 | 
				
			||||||
                host = socket.inet_ntop(family, addr_bytes)
 | 
					 | 
				
			||||||
                file.write(struct.pack(">H", port))
 | 
					 | 
				
			||||||
                return host, port
 | 
					 | 
				
			||||||
            except socket.error:
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Well it's not an IP number, so it's probably a DNS name.
 | 
					 | 
				
			||||||
        if rdns:
 | 
					 | 
				
			||||||
            # Resolve remotely
 | 
					 | 
				
			||||||
            host_bytes = host.encode('idna')
 | 
					 | 
				
			||||||
            file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # Resolve locally
 | 
					 | 
				
			||||||
            addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG)
 | 
					 | 
				
			||||||
            # We can't really work out what IP is reachable, so just pick the
 | 
					 | 
				
			||||||
            # first.
 | 
					 | 
				
			||||||
            target_addr = addresses[0]
 | 
					 | 
				
			||||||
            family = target_addr[0]
 | 
					 | 
				
			||||||
            host = target_addr[4][0]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            addr_bytes = socket.inet_pton(family, host)
 | 
					 | 
				
			||||||
            file.write(family_to_byte[family] + addr_bytes)
 | 
					 | 
				
			||||||
            host = socket.inet_ntop(family, addr_bytes)
 | 
					 | 
				
			||||||
        file.write(struct.pack(">H", port))
 | 
					 | 
				
			||||||
        return host, port
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _read_SOCKS5_address(self, file):
 | 
					 | 
				
			||||||
        atyp = self._readall(file, 1)
 | 
					 | 
				
			||||||
        if atyp == b"\x01":
 | 
					 | 
				
			||||||
            addr = socket.inet_ntoa(self._readall(file, 4))
 | 
					 | 
				
			||||||
        elif atyp == b"\x03":
 | 
					 | 
				
			||||||
            length = self._readall(file, 1)
 | 
					 | 
				
			||||||
            addr = self._readall(file, ord(length))
 | 
					 | 
				
			||||||
        elif atyp == b"\x04":
 | 
					 | 
				
			||||||
            addr = socket.inet_ntop(socket.AF_INET6, self._readall(file, 16))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise GeneralProxyError("SOCKS5 proxy server sent invalid data")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        port = struct.unpack(">H", self._readall(file, 2))[0]
 | 
					 | 
				
			||||||
        return addr, port
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _negotiate_SOCKS4(self, dest_addr, dest_port):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Negotiates a connection through a SOCKS4 server.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        proxy_type, addr, port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        writer = self.makefile("wb")
 | 
					 | 
				
			||||||
        reader = self.makefile("rb", 0)  # buffering=0 renamed in Python 3
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            # Check if the destination address provided is an IP address
 | 
					 | 
				
			||||||
            remote_resolve = False
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                addr_bytes = socket.inet_aton(dest_addr)
 | 
					 | 
				
			||||||
            except socket.error:
 | 
					 | 
				
			||||||
                # It's a DNS name. Check where it should be resolved.
 | 
					 | 
				
			||||||
                if rdns:
 | 
					 | 
				
			||||||
                    addr_bytes = b"\x00\x00\x00\x01"
 | 
					 | 
				
			||||||
                    remote_resolve = True
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    addr_bytes = socket.inet_aton(socket.gethostbyname(dest_addr))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Construct the request packet
 | 
					 | 
				
			||||||
            writer.write(struct.pack(">BBH", 0x04, 0x01, dest_port))
 | 
					 | 
				
			||||||
            writer.write(addr_bytes)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # The username parameter is considered userid for SOCKS4
 | 
					 | 
				
			||||||
            if username:
 | 
					 | 
				
			||||||
                writer.write(username)
 | 
					 | 
				
			||||||
            writer.write(b"\x00")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # DNS name if remote resolving is required
 | 
					 | 
				
			||||||
            # NOTE: This is actually an extension to the SOCKS4 protocol
 | 
					 | 
				
			||||||
            # called SOCKS4A and may not be supported in all cases.
 | 
					 | 
				
			||||||
            if remote_resolve:
 | 
					 | 
				
			||||||
                writer.write(dest_addr.encode('idna') + b"\x00")
 | 
					 | 
				
			||||||
            writer.flush()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Get the response from the server
 | 
					 | 
				
			||||||
            resp = self._readall(reader, 8)
 | 
					 | 
				
			||||||
            if resp[0:1] != b"\x00":
 | 
					 | 
				
			||||||
                # Bad data
 | 
					 | 
				
			||||||
                raise GeneralProxyError("SOCKS4 proxy server sent invalid data")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            status = ord(resp[1:2])
 | 
					 | 
				
			||||||
            if status != 0x5A:
 | 
					 | 
				
			||||||
                # Connection failed: server returned an error
 | 
					 | 
				
			||||||
                error = SOCKS4_ERRORS.get(status, "Unknown error")
 | 
					 | 
				
			||||||
                raise SOCKS4Error("{0:#04x}: {1}".format(status, error))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Get the bound address/port
 | 
					 | 
				
			||||||
            self.proxy_sockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0])
 | 
					 | 
				
			||||||
            if remote_resolve:
 | 
					 | 
				
			||||||
                self.proxy_peername = socket.inet_ntoa(addr_bytes), dest_port
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.proxy_peername = dest_addr, dest_port
 | 
					 | 
				
			||||||
        finally:
 | 
					 | 
				
			||||||
            reader.close()
 | 
					 | 
				
			||||||
            writer.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _negotiate_HTTP(self, dest_addr, dest_port):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Negotiates a connection through an HTTP server.
 | 
					 | 
				
			||||||
        NOTE: This currently only supports HTTP CONNECT-style proxies.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        proxy_type, addr, port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # If we need to resolve locally, we do this now
 | 
					 | 
				
			||||||
        addr = dest_addr if rdns else socket.gethostbyname(dest_addr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        http_headers = [
 | 
					 | 
				
			||||||
            b"CONNECT " + addr.encode('idna') + b":" + str(dest_port).encode() + b" HTTP/1.1",
 | 
					 | 
				
			||||||
            b"Host: " + dest_addr.encode('idna')
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if username and password:
 | 
					 | 
				
			||||||
            http_headers.append(b"Proxy-Authorization: basic " + b64encode(username + b":" + password))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        http_headers.append(b"\r\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.sendall(b"\r\n".join(http_headers))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # We just need the first line to check if the connection was successful
 | 
					 | 
				
			||||||
        fobj = self.makefile()
 | 
					 | 
				
			||||||
        status_line = fobj.readline()
 | 
					 | 
				
			||||||
        fobj.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if not status_line:
 | 
					 | 
				
			||||||
            raise GeneralProxyError("Connection closed unexpectedly")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            proto, status_code, status_msg = status_line.split(" ", 2)
 | 
					 | 
				
			||||||
        except ValueError:
 | 
					 | 
				
			||||||
            raise GeneralProxyError("HTTP proxy server sent invalid response")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if not proto.startswith("HTTP/"):
 | 
					 | 
				
			||||||
            raise GeneralProxyError("Proxy server does not appear to be an HTTP proxy")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            status_code = int(status_code)
 | 
					 | 
				
			||||||
        except ValueError:
 | 
					 | 
				
			||||||
            raise HTTPError("HTTP proxy server did not return a valid HTTP status")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if status_code != 200:
 | 
					 | 
				
			||||||
            error = "{0}: {1}".format(status_code, status_msg)
 | 
					 | 
				
			||||||
            if status_code in (400, 403, 405):
 | 
					 | 
				
			||||||
                # It's likely that the HTTP proxy server does not support the CONNECT tunneling method
 | 
					 | 
				
			||||||
                error += ("\n[*] Note: The HTTP proxy server may not be supported by PySocks"
 | 
					 | 
				
			||||||
                          " (must be a CONNECT tunnel proxy)")
 | 
					 | 
				
			||||||
            raise HTTPError(error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.proxy_sockname = (b"0.0.0.0", 0)
 | 
					 | 
				
			||||||
        self.proxy_peername = addr, dest_port
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _proxy_negotiators = {
 | 
					 | 
				
			||||||
                           SOCKS4: _negotiate_SOCKS4,
 | 
					 | 
				
			||||||
                           SOCKS5: _negotiate_SOCKS5,
 | 
					 | 
				
			||||||
                           HTTP: _negotiate_HTTP
 | 
					 | 
				
			||||||
                         }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def connect(self, dest_pair):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Connects to the specified destination through a proxy.
 | 
					 | 
				
			||||||
        Uses the same API as socket's connect().
 | 
					 | 
				
			||||||
        To select the proxy server, use set_proxy().
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dest_pair - 2-tuple of (IP/hostname, port).
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        if len(dest_pair) != 2 or dest_pair[0].startswith("["):
 | 
					 | 
				
			||||||
            # Probably IPv6, not supported -- raise an error, and hope
 | 
					 | 
				
			||||||
            # Happy Eyeballs (RFC6555) makes sure at least the IPv4
 | 
					 | 
				
			||||||
            # connection works...
 | 
					 | 
				
			||||||
            raise socket.error("PySocks doesn't support IPv6")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dest_addr, dest_port = dest_pair
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.type == socket.SOCK_DGRAM:
 | 
					 | 
				
			||||||
            if not self._proxyconn:
 | 
					 | 
				
			||||||
                self.bind(("", 0))
 | 
					 | 
				
			||||||
            dest_addr = socket.gethostbyname(dest_addr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # If the host address is INADDR_ANY or similar, reset the peer
 | 
					 | 
				
			||||||
            # address so that packets are received from any peer
 | 
					 | 
				
			||||||
            if dest_addr == "0.0.0.0" and not dest_port:
 | 
					 | 
				
			||||||
                self.proxy_peername = None
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.proxy_peername = (dest_addr, dest_port)
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        proxy_type, proxy_addr, proxy_port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Do a minimal input check first
 | 
					 | 
				
			||||||
        if (not isinstance(dest_pair, (list, tuple))
 | 
					 | 
				
			||||||
                or len(dest_pair) != 2
 | 
					 | 
				
			||||||
                or not dest_addr
 | 
					 | 
				
			||||||
                or not isinstance(dest_port, int)):
 | 
					 | 
				
			||||||
            raise GeneralProxyError("Invalid destination-connection (host, port) pair")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # We set the timeout here so that we don't hang in connection or during
 | 
					 | 
				
			||||||
        # negotiation.
 | 
					 | 
				
			||||||
        _BaseSocket.settimeout(self, self._timeout)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if proxy_type is None:
 | 
					 | 
				
			||||||
            # Treat like regular socket object
 | 
					 | 
				
			||||||
            self.proxy_peername = dest_pair
 | 
					 | 
				
			||||||
            _BaseSocket.settimeout(self, self._timeout)
 | 
					 | 
				
			||||||
            _BaseSocket.connect(self, (dest_addr, dest_port))
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        proxy_addr = self._proxy_addr()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            # Initial connection to proxy server.
 | 
					 | 
				
			||||||
            _BaseSocket.connect(self, proxy_addr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        except socket.error as error:
 | 
					 | 
				
			||||||
            # Error while connecting to proxy
 | 
					 | 
				
			||||||
            self.close()
 | 
					 | 
				
			||||||
            proxy_addr, proxy_port = proxy_addr
 | 
					 | 
				
			||||||
            proxy_server = "{0}:{1}".format(proxy_addr, proxy_port)
 | 
					 | 
				
			||||||
            printable_type = PRINTABLE_PROXY_TYPES[proxy_type]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            msg = "Error connecting to {0} proxy {1}".format(printable_type,
 | 
					 | 
				
			||||||
                                                           proxy_server)
 | 
					 | 
				
			||||||
            raise ProxyConnectionError(msg, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # Connected to proxy server, now negotiate
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                # Calls negotiate_{SOCKS4, SOCKS5, HTTP}
 | 
					 | 
				
			||||||
                negotiate = self._proxy_negotiators[proxy_type]
 | 
					 | 
				
			||||||
                negotiate(self, dest_addr, dest_port)
 | 
					 | 
				
			||||||
            except socket.error as error:
 | 
					 | 
				
			||||||
                # Wrap socket errors
 | 
					 | 
				
			||||||
                self.close()
 | 
					 | 
				
			||||||
                raise GeneralProxyError("Socket error", error)
 | 
					 | 
				
			||||||
            except ProxyError:
 | 
					 | 
				
			||||||
                # Protocol error while negotiating with proxy
 | 
					 | 
				
			||||||
                self.close()
 | 
					 | 
				
			||||||
                raise
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _proxy_addr(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Return proxy address to connect to as tuple object
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        proxy_type, proxy_addr, proxy_port, rdns, username, password = self.proxy
 | 
					 | 
				
			||||||
        proxy_port = proxy_port or DEFAULT_PORTS.get(proxy_type)
 | 
					 | 
				
			||||||
        if not proxy_port:
 | 
					 | 
				
			||||||
            raise GeneralProxyError("Invalid proxy type")
 | 
					 | 
				
			||||||
        return proxy_addr, proxy_port
 | 
					 | 
				
			||||||
@ -1,84 +0,0 @@
 | 
				
			|||||||
# This software released into the public domain. Anyone is free to copy,
 | 
					 | 
				
			||||||
# modify, publish, use, compile, sell, or distribute this software,
 | 
					 | 
				
			||||||
# either in source code form or as a compiled binary, for any purpose,
 | 
					 | 
				
			||||||
# commercial or non-commercial, and by any means.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import socket
 | 
					 | 
				
			||||||
import ctypes
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class sockaddr(ctypes.Structure):
 | 
					 | 
				
			||||||
    _fields_ = [("sa_family", ctypes.c_short),
 | 
					 | 
				
			||||||
                ("__pad1", ctypes.c_ushort),
 | 
					 | 
				
			||||||
                ("ipv4_addr", ctypes.c_byte * 4),
 | 
					 | 
				
			||||||
                ("ipv6_addr", ctypes.c_byte * 16),
 | 
					 | 
				
			||||||
                ("__pad2", ctypes.c_ulong)]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if hasattr(ctypes, 'windll'):
 | 
					 | 
				
			||||||
    WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA
 | 
					 | 
				
			||||||
    WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    def not_windows():
 | 
					 | 
				
			||||||
        raise SystemError(
 | 
					 | 
				
			||||||
            "Invalid platform. ctypes.windll must be available."
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    WSAStringToAddressA = not_windows
 | 
					 | 
				
			||||||
    WSAAddressToStringA = not_windows
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def inet_pton(address_family, ip_string):
 | 
					 | 
				
			||||||
    addr = sockaddr()
 | 
					 | 
				
			||||||
    addr.sa_family = address_family
 | 
					 | 
				
			||||||
    addr_size = ctypes.c_int(ctypes.sizeof(addr))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if WSAStringToAddressA(
 | 
					 | 
				
			||||||
            ip_string,
 | 
					 | 
				
			||||||
            address_family,
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
            ctypes.byref(addr),
 | 
					 | 
				
			||||||
            ctypes.byref(addr_size)
 | 
					 | 
				
			||||||
    ) != 0:
 | 
					 | 
				
			||||||
        raise socket.error(ctypes.FormatError())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if address_family == socket.AF_INET:
 | 
					 | 
				
			||||||
        return ctypes.string_at(addr.ipv4_addr, 4)
 | 
					 | 
				
			||||||
    if address_family == socket.AF_INET6:
 | 
					 | 
				
			||||||
        return ctypes.string_at(addr.ipv6_addr, 16)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    raise socket.error('unknown address family')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def inet_ntop(address_family, packed_ip):
 | 
					 | 
				
			||||||
    addr = sockaddr()
 | 
					 | 
				
			||||||
    addr.sa_family = address_family
 | 
					 | 
				
			||||||
    addr_size = ctypes.c_int(ctypes.sizeof(addr))
 | 
					 | 
				
			||||||
    ip_string = ctypes.create_string_buffer(128)
 | 
					 | 
				
			||||||
    ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if address_family == socket.AF_INET:
 | 
					 | 
				
			||||||
        if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr):
 | 
					 | 
				
			||||||
            raise socket.error('packed IP wrong length for inet_ntoa')
 | 
					 | 
				
			||||||
        ctypes.memmove(addr.ipv4_addr, packed_ip, 4)
 | 
					 | 
				
			||||||
    elif address_family == socket.AF_INET6:
 | 
					 | 
				
			||||||
        if len(packed_ip) != ctypes.sizeof(addr.ipv6_addr):
 | 
					 | 
				
			||||||
            raise socket.error('packed IP wrong length for inet_ntoa')
 | 
					 | 
				
			||||||
        ctypes.memmove(addr.ipv6_addr, packed_ip, 16)
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        raise socket.error('unknown address family')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if WSAAddressToStringA(
 | 
					 | 
				
			||||||
            ctypes.byref(addr),
 | 
					 | 
				
			||||||
            addr_size,
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
            ip_string,
 | 
					 | 
				
			||||||
            ctypes.byref(ip_string_size)
 | 
					 | 
				
			||||||
    ) != 0:
 | 
					 | 
				
			||||||
        raise socket.error(ctypes.FormatError())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ip_string[:ip_string_size.value - 1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Adding our two functions to the socket library
 | 
					 | 
				
			||||||
if os.name == 'nt':
 | 
					 | 
				
			||||||
    socket.inet_pton = inet_pton
 | 
					 | 
				
			||||||
    socket.inet_ntop = inet_ntop
 | 
					 | 
				
			||||||
							
								
								
									
										786
									
								
								resources/pyxbmct/addonwindow.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,786 @@
 | 
				
			|||||||
 | 
					# -*- 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
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/AddonWindow/ContentPanel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 52 KiB  | 
| 
		 After Width: | Height: | Size: 5.1 KiB  | 
| 
		 After Width: | Height: | Size: 4.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/AddonWindow/SKINDEFAULT.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 122 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/AddonWindow/dialogheader.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Button/KeyboardKey.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Button/KeyboardKeyNF.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Edit/black-back2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Edit/button-focus.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/List/MenuItemFO.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/List/MenuItemNF.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/RadioButton/MenuItemFO.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/RadioButton/MenuItemNF.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.1 KiB  | 
| 
		 After Width: | Height: | Size: 5.1 KiB  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Slider/osd_slider_bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Slider/osd_slider_bg_2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Slider/osd_slider_nib.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/pyxbmct/textures/default/Slider/osd_slider_nibNF.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.7 KiB  | 
@ -19,7 +19,7 @@ class TmDb:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, language='en'):
 | 
					    def __init__(self, language='en'):
 | 
				
			||||||
        tmdb.configure("33dd11cb87f2b5fd9ecaff4a81d47edb", language=language)
 | 
					        tmdb.configure("f7f51775877e0bb6703520952b3c7840", language=language)
 | 
				
			||||||
        dbname='tmdb.%s.db' % language
 | 
					        dbname='tmdb.%s.db' % language
 | 
				
			||||||
        self.cache = Cache(dbname, 1.0)
 | 
					        self.cache = Cache(dbname, 1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,21 +1,17 @@
 | 
				
			|||||||
<settings>
 | 
					<settings>
 | 
				
			||||||
    <category label="30101">
 | 
					    <category label="30101">
 | 
				
			||||||
        <setting id="language"          type="enum"     label="30001" default="1"   values="English|Russian|Ukrainian|Hebrew|Spanish|Hungarian" />
 | 
					        <setting id="language"          type="enum"     label="30001" default="1"   values="English|Russian|Ukrainian|Hebrew" />
 | 
				
			||||||
        <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|30071|30076"/>
 | 
					        <setting id="skin_optimization" type="enum"     label="30002" default="1"   lvalues="30003|30018|30017|30016|30019|30066|30067"/>
 | 
				
			||||||
        <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"/>
 | 
				
			||||||
        <setting id="search_phrase"     type="text"     label="30040"/>
 | 
					        <setting id="search_phrase"     type="text"     label="30040"/>
 | 
				
			||||||
        <setting id="num_threads"       type="slider"   label="30042" default="3" range="1,1,9" option="int"/>
 | 
					        <setting id="num_threads"       type="slider"   label="30042" default="3" range="1,1,9" option="int"/>
 | 
				
			||||||
        <setting id="proxy"             type="enum"     lvalues="30048|30049|31050" label="30047" default="0"/>
 | 
					        <setting id="proxy"             type="enum"     lvalues="30048|30049|" label="30047" default="0"/>
 | 
				
			||||||
		<setting id="cl_proxy"          type="enum"     lvalues="30048|31050" label="31047" default="0"/>
 | 
					 | 
				
			||||||
        <setting id="socks_ip"			type="ipaddress" label="32047" default="127.0.0.1"  visible="eq(-2,2)|eq(-1,1)"/>
 | 
					 | 
				
			||||||
        <setting id="socks_port"		type="number"    label="32048" default="9050"  visible="eq(-3,2)|eq(-2,1)"/>
 | 
					 | 
				
			||||||
        <setting id="debug"             type="bool"     label="30015" default="false"/>
 | 
					        <setting id="debug"             type="bool"     label="30015" default="false"/>
 | 
				
			||||||
    </category>
 | 
					    </category>
 | 
				
			||||||
    <category label="30102">
 | 
					    <category label="30102">
 | 
				
			||||||
@ -65,18 +61,14 @@
 | 
				
			|||||||
        <setting id="torrent_qbittorrent_password"  type="text"         label="50316" visible="eq(-21,4)" default="admin" option="hidden"/>
 | 
					        <setting id="torrent_qbittorrent_password"  type="text"         label="50316" visible="eq(-21,4)" default="admin" option="hidden"/>
 | 
				
			||||||
    </category>
 | 
					    </category>
 | 
				
			||||||
    <category label="30105">
 | 
					    <category label="30105">
 | 
				
			||||||
        <setting id="torrent_player"        type="enum"     label="30023" default="2"       lvalues="30021|30022|30046|30068" />
 | 
					        <setting id="torrent_player"    type="enum"     label="30023" default="2"       lvalues="30021|30022|30046|30068" />
 | 
				
			||||||
        <setting id="ask_dir"               type="bool"     label="30031" default="false"/>
 | 
					        <setting id="ask_dir"           type="bool"     label="30031" default="false"/>
 | 
				
			||||||
        <setting id="connections_limit"     type="number"   label="30051" default="200"     visible=" eq(-2,2)"/>
 | 
					        <setting id="connections_limit" type="number"   label="30051" default="200"     visible=" eq(-2,2)"/>
 | 
				
			||||||
        <setting id="use_random_port"       type="bool"     label="30052" default="false"   visible=" eq(-3,2)"/>
 | 
					        <setting id="use_random_port"   type="bool"     label="30052" default="false"   visible=" eq(-3,2)"/>
 | 
				
			||||||
        <setting id="listen_port"           type="number"   label="30053" default="6881"    visible="!eq(-4,1)"/>
 | 
					        <setting id="listen_port"       type="number"   label="30053" default="6881"    visible="!eq(-4,1)"/>
 | 
				
			||||||
        <setting id="min_storage_size"      type="slider"   label="30059" default="0"       visible="!eq(-5,1)"  range="0,2,100" option="int"/>
 | 
					        <setting id="min_storage_size"  type="slider"   label="30059" default="0"       visible="!eq(-5,1)"  range="0,2,100" option="int"/>
 | 
				
			||||||
        <setting id="pause_onplay"          type="bool"     label="30060" default="false"   visible="!eq(-6,1)"/>
 | 
					        <setting id="pause_onplay"      type="bool"     label="30060" default="false"   visible="!eq(-6,1)"/>
 | 
				
			||||||
        <setting id="max_history_add"       type="slider"   label="30065" default="100"     visible="!eq(-7,1)"  range="0,2,100" option="int"/>
 | 
					        <setting id="max_history_add"   type="slider"   label="30065" default="100"     visible="!eq(-7,1)"  range="0,2,100" option="int"/>
 | 
				
			||||||
        <setting id="enable_dht"            type="bool"     label="30070" default="true"    visible="!eq(-8,1)"/>
 | 
					        <setting id="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>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										218
									
								
								resources/skins/Default/720p/movieinfo.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,218 @@
 | 
				
			|||||||
 | 
					<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>
 | 
				
			||||||
							
								
								
									
										127
									
								
								resources/skins/Default/720p/reviews.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					<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>
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								resources/skins/Default/media/ConfluenceDialogBack.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.4 KiB  | 
| 
		 After Width: | Height: | Size: 5.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/skins/Default/media/ConfluenceDialogCloseButton.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								resources/skins/Default/media/Confluencedialogheader.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.8 KiB  | 
							
								
								
									
										63
									
								
								resources/skins/DialogReviews.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					# -*- 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
 | 
				
			||||||
							
								
								
									
										83
									
								
								resources/skins/DialogXml.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					# -*- 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)
 | 
				
			||||||
@ -1064,10 +1064,7 @@ class qBittorrent:
 | 
				
			|||||||
            'uploading': 'seeding',
 | 
					            'uploading': 'seeding',
 | 
				
			||||||
            'stalledUP': 'seeding',
 | 
					            'stalledUP': 'seeding',
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if code in mapping:
 | 
					        return mapping[code]
 | 
				
			||||||
            return mapping[code]
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return 'unknown'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Deluge:
 | 
					class Deluge:
 | 
				
			||||||
 | 
				
			|||||||