diff --git a/addon.xml b/addon.xml index d67e56d..39c9855 100644 --- a/addon.xml +++ b/addon.xml @@ -1,18 +1,25 @@ - - - - - - Kodi / XBMC BSPlayer Subtitles allows for downloading subtitles from the bsplayer subtitles community. - Search and download various subtitles from the bsplayer subtitles community. - https://github.com/realgam3/service.subtitles.bsplayer - realgam3@gmail.com - GNU GENERAL PUBLIC LICENSE. Version 2, June 1991 - + + + + + + + BSPlayer Subtitles + + + Search and download various subtitles from the BSPlayer subtitles community. + + https://github.com/realgam3/service.subtitles.bsplayer + realgam3@gmail.com + GNU GENERAL PUBLIC LICENSE. Version 2, June 1991 + all + + logo.png + + \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index bfa041b..bab6f09 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +0.3.0 - 15/05/2022 +- Migrating to python 3, support kodi 19 + 0.2.1 - 07/11/2015 - Fixed android non rar support, rearrange code diff --git a/resources/__init__.py b/resources/__init__.py index b93054b..e69de29 100644 --- a/resources/__init__.py +++ b/resources/__init__.py @@ -1 +0,0 @@ -# Dummy file to make this directory a package. diff --git a/resources/lib/bsplayer.py b/resources/lib/bsplayer.py index 6052322..3042c24 100644 --- a/resources/lib/bsplayer.py +++ b/resources/lib/bsplayer.py @@ -1,26 +1,24 @@ import gzip +import socket import random from time import sleep -from StringIO import StringIO from xml.etree import ElementTree +from urllib.request import Request -from utils import movie_size_and_hash, get_session, log - -# s1-9, s101-109 -SUB_DOMAINS = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', - 's101', 's102', 's103', 's104', 's105', 's106', 's107', 's108', 's109'] -API_URL_TEMPLATE = "http://{sub_domain}.api.bsplayer-subtitles.com/v1.php" - - -def get_sub_domain(): - sub_domains_end = len(SUB_DOMAINS) - 1 - return API_URL_TEMPLATE.format(sub_domain=SUB_DOMAINS[random.randint(0, sub_domains_end)]) +from .utils import movie_size_and_hash, get_session, log class BSPlayer(object): + VERSION = "2.67" + DOMAIN = "api.bsplayer-subtitles.com" + SUB_DOMAINS = [ + 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', + 's101', 's102', 's103', 's104', 's105', 's106', 's107', 's108', 's109' + ] + def __init__(self, search_url=None, proxies=None): self.session = get_session(proxies=proxies) - self.search_url = search_url or get_sub_domain() + self.search_url = search_url or self.get_sub_domain() self.token = None def __enter__(self): @@ -30,33 +28,43 @@ def __enter__(self): def __exit__(self, exc_type, exc_val, exc_tb): return self.logout() + def get_sub_domain(self, tries=5): + for t in range(tries): + domain = f"{random.choice(self.SUB_DOMAINS)}.{self.DOMAIN}" + try: + socket.gethostbyname(domain) + return f"http://{domain}/v1.php" + except socket.gaierror: + continue + raise Exception("API Domain not found") + def api_request(self, func_name='logIn', params='', tries=5): headers = { 'User-Agent': 'BSPlayer/2.x (1022.12360)', 'Content-Type': 'text/xml; charset=utf-8', 'Connection': 'close', - 'SOAPAction': '"http://api.bsplayer-subtitles.com/v1.php#{func_name}"'.format(func_name=func_name) + 'SOAPAction': f'"http://{self.DOMAIN}/v1.php#{func_name}"' } data = ( '\n' '' + f'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="{self.search_url}">' '' - '{params}' - ).format(search_url=self.search_url, func_name=func_name, params=params) + f'{params}' + ) log('BSPlayer.api_request', 'Sending request: %s.' % func_name) - for i in xrange(tries): + for i in range(tries): try: - self.session.addheaders.extend(headers.items()) - res = self.session.open(self.search_url, data) + req = Request(self.search_url, data=data.encode(), headers=headers, method="POST") + res = self.session.open(req) return ElementTree.fromstring(res.read()) - except Exception, ex: + except Exception as ex: log("BSPlayer.api_request", "ERROR: %s." % ex) if func_name == 'logIn': - self.search_url = get_sub_domain() + self.search_url = self.get_sub_domain() sleep(1) log('BSPlayer.api_request', 'ERROR: Too many tries (%d)...' % tries) raise Exception('Too many tries...') @@ -68,9 +76,11 @@ def login(self): root = self.api_request( func_name='logIn', - params=('' - '' - 'BSPlayer v2.67') + params=( + '' + '' + f'BSPlayer v{self.VERSION}' + ) ) res = root.find('.//return') if res.find('status').text == 'OK': @@ -86,7 +96,7 @@ def logout(self): root = self.api_request( func_name='logOut', - params='{token}'.format(token=self.token) + params=f'{self.token}' ) res = root.find('.//return') self.token = None @@ -102,18 +112,21 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False): if isinstance(language_ids, (tuple, list, set)): language_ids = ",".join(language_ids) - movie_size, movie_hash = movie_size_and_hash(movie_path) - log('BSPlayer.search_subtitles', 'Movie Size: %s, Movie Hash: %s.' % (movie_size, movie_hash)) + try: + movie_size, movie_hash = movie_size_and_hash(movie_path) + except Exception as ex: + print(ex) + exit(1) + log('BSPlayer.search_subtitles', f'Movie Size: {movie_size}, Movie Hash: {movie_hash}.') root = self.api_request( func_name='searchSubtitles', params=( - '{token}' - '{movie_hash}' - '{movie_size}' - '{language_ids}' + f'{self.token}' + f'{movie_hash}' + f'{movie_size}' + f'{language_ids}' '*' - ).format(token=self.token, movie_hash=movie_hash, - movie_size=movie_size, language_ids=language_ids) + ) ) res = root.find('.//return/result') if res.find('status').text != 'OK': @@ -129,7 +142,8 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False): subDownloadLink=item.find('subDownloadLink').text, subLang=item.find('subLang').text, subName=item.find('subName').text, - subFormat=item.find('subFormat').text + subFormat=item.find('subFormat').text, + subRating=item.find('subRating').text or '0' )) if logout: @@ -141,10 +155,10 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False): def download_subtitles(download_url, dest_path, proxies=None): session = get_session(proxies=proxies, http_10=True) session.addheaders = [('User-Agent', 'Mozilla/4.0 (compatible; Synapse)'), - ('Content-Length', 0)] + ('Content-Length', 0)] res = session.open(download_url) if res: - gf = gzip.GzipFile(fileobj=StringIO(res.read())) + gf = gzip.GzipFile(fileobj=res) with open(dest_path, 'wb') as f: f.write(gf.read()) f.flush() diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 8035de1..fb645db 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -1,30 +1,28 @@ import sys import struct -import urllib2 -import urlparse -import cookielib from os import path -from httplib import HTTPConnection +from urllib import parse, request +from http.cookiejar import CookieJar +from http.client import HTTPConnection import xbmc -import xbmcvfs def log(module, msg): - xbmc.log((u"### [%s] - %s" % (module, msg)).encode('utf-8'), level=xbmc.LOGDEBUG) + xbmc.log(f"### [{module}] - {msg}", level=xbmc.LOGDEBUG) def notify(script_name, language, string_id): - xbmc.executebuiltin((u'Notification(%s,%s)' % (script_name, language(string_id))).encode('utf-8')) + xbmc.executebuiltin(f"Notification({script_name}, {language(string_id)})") def get_params(params_str=""): params_str = params_str or sys.argv[2] - return dict(urlparse.parse_qsl(params_str.lstrip('?'))) + return dict(parse.parse_qsl(params_str.lstrip('?'))) def get_video_path(xbmc_path=''): - xbmc_path = xbmc_path or urlparse.unquote(xbmc.Player().getPlayingFile().decode('utf-8')) + xbmc_path = xbmc_path or parse.unquote(xbmc.Player().getPlayingFile()) if xbmc_path.startswith('rar://'): return path.dirname(xbmc_path.replace('rar://', '')) elif xbmc_path.startswith('stack://'): @@ -50,7 +48,7 @@ class HTTP10Connection(HTTPConnection): _http_vsn_str = "HTTP/1.0" -class HTTP10Handler(urllib2.HTTPHandler): +class HTTP10Handler(request.HTTPHandler): def http_open(self, req): return self.do_open(HTTP10Connection, req) @@ -58,13 +56,13 @@ def http_open(self, req): def get_session(proxies=None, cookies=True, http_10=False): handlers = [] if proxies: - handlers.append(urllib2.ProxyHandler(proxies)) + handlers.append(request.ProxyHandler(proxies)) if cookies: - cj = cookielib.CookieJar() - handlers.append(urllib2.HTTPCookieProcessor(cj)) + cj = CookieJar() + handlers.append(request.HTTPCookieProcessor(cj)) if http_10: handlers.append(HTTP10Handler) - return urllib2.build_opener(*handlers) + return request.build_opener(*handlers) def __get_last_split(firs_rar_file, x): @@ -78,7 +76,7 @@ def __get_last_split(firs_rar_file, x): def __add_file_hash(name, file_hash, seek): - f = xbmcvfs.File(name) + f = open(name, "rb") f.seek(max(0, seek), 0) for i in range(8192): file_hash += struct.unpack('