Skip to content

Commit 15a1fa3

Browse files
committed
Fixed android non rar support, rearrange code
1 parent 7265a2f commit 15a1fa3

File tree

7 files changed

+188
-188
lines changed

7 files changed

+188
-188
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ htmlcov/
4040
nosetests.xml
4141
coverage.xml
4242
*,cover
43+
bsplayer_test.py
4344

4445
# Translations
4546
*.mo

addon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
22
<addon id="service.subtitles.bsplayer"
33
name="BSPlayer"
4-
version="0.2.0"
4+
version="0.2.1"
55
provider-name="realgam3">
66
<requires>
77
<import addon="xbmc.python" version="2.1.0"/>

changelog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
0.2.1 - 07/11/2015
2+
- Fixed android non rar support, rearrange code
3+
14
0.2.0 - 07/11/2015
25
- Fixed android rar support, works with smb shares
36

resources/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Dummy file to make this directory a package.

resources/lib/bsplayer.py

Lines changed: 16 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
import cookielib
2-
import gzip
3-
import logging
1+
import gzip
42
import random
5-
import struct
6-
import urllib2
7-
from StringIO import StringIO
8-
from httplib import HTTPConnection
9-
from os import path
103
from time import sleep
4+
from StringIO import StringIO
115
from xml.etree import ElementTree
126

13-
import xbmcvfs
7+
from utils import movie_size_and_hash, get_session, log
148

159
# s1-9, s101-109
1610
SUB_DOMAINS = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9',
@@ -23,121 +17,11 @@ def get_sub_domain():
2317
return API_URL_TEMPLATE.format(sub_domain=SUB_DOMAINS[random.randint(0, sub_domains_end)])
2418

2519

26-
def get_session(proxies=None):
27-
cj = cookielib.CookieJar()
28-
proxy_handler = urllib2.ProxyHandler(proxies)
29-
return urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), proxy_handler)
30-
31-
32-
def python_logger(module, msg):
33-
logger = logging.getLogger('BSPlayer')
34-
logger.log(logging.DEBUG, (u"### [%s] - %s" % (module, msg)))
35-
36-
37-
def OpensubtitlesHashRar(firsrarfile):
38-
# log(__name__, "Hash Rar file")
39-
f = xbmcvfs.File(firsrarfile)
40-
a = f.read(4)
41-
if a != 'Rar!':
42-
raise Exception('ERROR: This is not rar file.')
43-
seek = 0
44-
for i in range(4):
45-
f.seek(max(0, seek), 0)
46-
a = f.read(100)
47-
type, flag, size = struct.unpack('<BHH', a[2:2 + 5])
48-
if 0x74 == type:
49-
if 0x30 != struct.unpack('<B', a[25:25 + 1])[0]:
50-
raise Exception('Bad compression method! Work only for "store".')
51-
s_partiizebodystart = seek + size
52-
s_partiizebody, s_unpacksize = struct.unpack('<II', a[7:7 + 2 * 4])
53-
if (flag & 0x0100):
54-
s_unpacksize = (struct.unpack('<I', a[36:36 + 4])[0] << 32) + s_unpacksize
55-
# log(__name__, 'Hash untested for files biger that 2gb. May work or may generate bad hash.')
56-
lastrarfile = getlastsplit(firsrarfile, (s_unpacksize - 1) / s_partiizebody)
57-
hash = addfilehash(firsrarfile, s_unpacksize, s_partiizebodystart)
58-
hash = addfilehash(lastrarfile, hash, (s_unpacksize % s_partiizebody) + s_partiizebodystart - 65536)
59-
f.close()
60-
return (s_unpacksize, "%016x" % hash)
61-
seek += size
62-
raise Exception('ERROR: Not Body part in rar file.')
63-
64-
65-
def getlastsplit(firsrarfile, x):
66-
if firsrarfile[-3:] == '001':
67-
return firsrarfile[:-3] + ('%03d' % (x + 1))
68-
if firsrarfile[-11:-6] == '.part':
69-
return firsrarfile[0:-6] + ('%02d' % (x + 1)) + firsrarfile[-4:]
70-
if firsrarfile[-10:-5] == '.part':
71-
return firsrarfile[0:-5] + ('%1d' % (x + 1)) + firsrarfile[-4:]
72-
return firsrarfile[0:-2] + ('%02d' % (x - 1))
73-
74-
75-
def addfilehash(name, hash, seek):
76-
f = xbmcvfs.File(name)
77-
f.seek(max(0, seek), 0)
78-
for i in range(8192):
79-
hash += struct.unpack('<q', f.read(8))[0]
80-
hash &= 0xffffffffffffffff
81-
f.close()
82-
return hash
83-
84-
85-
def movie_size_and_hash(file_path):
86-
file_ext = path.splitext(file_path)[1]
87-
if file_ext == '.rar' or file_ext =='.001':
88-
return OpensubtitlesHashRar(file_path)
89-
90-
longlong_format = '<q' # little-endian long long
91-
byte_size = struct.calcsize(longlong_format)
92-
93-
f = xbmcvfs.File(file_path)
94-
file_size = f.size()
95-
movie_hash = file_size
96-
97-
if file_size < 65536 * 2:
98-
f.close()
99-
raise Exception("SizeError")
100-
101-
for x in range(65536 / byte_size):
102-
buff = f.read(byte_size)
103-
(l_value,) = struct.unpack(longlong_format, buff)
104-
movie_hash += l_value
105-
movie_hash &= 0xFFFFFFFFFFFFFFFF # to remain as 64bit number
106-
107-
f.seek(max(0, file_size - 65536), 0)
108-
for x in range(65536 / byte_size):
109-
buff = f.read(byte_size)
110-
(l_value,) = struct.unpack(longlong_format, buff)
111-
movie_hash += l_value
112-
movie_hash &= 0xFFFFFFFFFFFFFFFF
113-
returned_movie_hash = "%016x" % movie_hash
114-
f.close()
115-
116-
return file_size, returned_movie_hash
117-
118-
119-
class HTTP10Connection(HTTPConnection):
120-
_http_vsn = 10
121-
_http_vsn_str = "HTTP/1.0"
122-
123-
124-
class HTTP10Handler(urllib2.HTTPHandler):
125-
def http_open(self, req):
126-
return self.do_open(HTTP10Connection, req)
127-
128-
12920
class BSPlayer(object):
130-
def __init__(self, search_url=None, log=python_logger, proxies=None):
131-
self.session = get_session(proxies)
21+
def __init__(self, search_url=None, proxies=None):
22+
self.session = get_session(proxies=proxies)
13223
self.search_url = search_url or get_sub_domain()
13324
self.token = None
134-
self.log = log
135-
if self.log.__name__ == 'python_logger':
136-
logging.basicConfig(
137-
format='%(asctime)s T:%(thread)d %(levelname)s: %(message)s',
138-
datefmt='%H:%M:%S',
139-
level=logging.DEBUG
140-
)
14125

14226
def __enter__(self):
14327
self.login()
@@ -163,18 +47,18 @@ def api_request(self, func_name='logIn', params='', tries=5):
16347
'<ns1:{func_name}>{params}</ns1:{func_name}></SOAP-ENV:Body></SOAP-ENV:Envelope>'
16448
).format(search_url=self.search_url, func_name=func_name, params=params)
16549

166-
self.log("BSPlayer.api_request", 'Sending request: %s' % func_name)
50+
log('BSPlayer.api_request', 'Sending request: %s.' % func_name)
16751
for i in xrange(tries):
16852
try:
16953
self.session.addheaders.extend(headers.items())
17054
res = self.session.open(self.search_url, data)
17155
return ElementTree.fromstring(res.read())
17256
except Exception, ex:
173-
self.log("BSPlayer.api_request", ex)
57+
log("BSPlayer.api_request", "ERROR: %s." % ex)
17458
if func_name == 'logIn':
17559
self.search_url = get_sub_domain()
17660
sleep(1)
177-
61+
log('BSPlayer.api_request', 'ERROR: Too many tries (%d)...' % tries)
17862
raise Exception('Too many tries...')
17963

18064
def login(self):
@@ -191,7 +75,7 @@ def login(self):
19175
res = root.find('.//return')
19276
if res.find('status').text == 'OK':
19377
self.token = res.find('data').text
194-
self.log("BSPlayer.login", "Logged In Successfully.")
78+
log("BSPlayer.login", "Logged In Successfully.")
19579
return True
19680
return False
19781

@@ -207,7 +91,7 @@ def logout(self):
20791
res = root.find('.//return')
20892
self.token = None
20993
if res.find('status').text == 'OK':
210-
self.log("BSPlayer.logout", "Logged Out Successfully.")
94+
log("BSPlayer.logout", "Logged Out Successfully.")
21195
return True
21296
return False
21397

@@ -219,7 +103,7 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False):
219103
language_ids = ",".join(language_ids)
220104

221105
movie_size, movie_hash = movie_size_and_hash(movie_path)
222-
self.log('BSPlayer.search_subtitles', 'Movie Size: %s, Movie Hash: %s' % (movie_size, movie_hash))
106+
log('BSPlayer.search_subtitles', 'Movie Size: %s, Movie Hash: %s.' % (movie_size, movie_hash))
223107
root = self.api_request(
224108
func_name='searchSubtitles',
225109
params=(
@@ -238,7 +122,7 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False):
238122
items = root.findall('.//return/data/item')
239123
subtitles = []
240124
if items:
241-
self.log("BSPlayer.search_subtitles", "Subtitles Found.")
125+
log("BSPlayer.search_subtitles", "Subtitles Found.")
242126
for item in items:
243127
subtitles.append(dict(
244128
subID=item.find('subID').text,
@@ -254,12 +138,11 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False):
254138
return subtitles
255139

256140
@staticmethod
257-
def download_subtitles(download_url, dest_path="Subtitle.srt", proxies=None):
258-
proxy_handler = urllib2.ProxyHandler(proxies)
259-
opener = urllib2.build_opener(HTTP10Handler, proxy_handler)
260-
opener.addheaders = [('User-Agent', 'Mozilla/4.0 (compatible; Synapse)'),
141+
def download_subtitles(download_url, dest_path, proxies=None):
142+
session = get_session(proxies=proxies, http_10=True)
143+
session.addheaders = [('User-Agent', 'Mozilla/4.0 (compatible; Synapse)'),
261144
('Content-Length', 0)]
262-
res = opener.open(download_url)
145+
res = session.open(download_url)
263146
if res:
264147
gf = gzip.GzipFile(fileobj=StringIO(res.read()))
265148
with open(dest_path, 'wb') as f:
@@ -268,14 +151,3 @@ def download_subtitles(download_url, dest_path="Subtitle.srt", proxies=None):
268151
gf.close()
269152
return True
270153
return False
271-
272-
273-
if __name__ == '__main__':
274-
bsp = BSPlayer(proxies={'http': '207.91.10.234:8080'})
275-
subs = bsp.search_subtitles(
276-
r'V:\Movies\Jackass.Presents.Bad.Grandpa.0.5.2014.720p.Bluray.x264.DTS-EVO\Jackass.Presents.Bad.Grandpa.0.5.2014.720p.Bluray.x264.DTS-EVO.mkv',
277-
logout=True
278-
)
279-
for sub in subs:
280-
print bsp.download_subtitles(sub['subDownloadLink'], proxies={'http': '207.91.10.234:8080'})
281-
break

0 commit comments

Comments
 (0)