1+ import cookielib
12import gzip
2- import struct
3+ import logging
34import random
5+ import struct
46import urllib2
5- import logging
6- from os import path
77from StringIO import StringIO
8- from xml .etree import ElementTree
98from httplib import HTTPConnection
9+ from os import path
10+ from time import sleep
11+ from xml .etree import ElementTree
1012
11- import rarfile
12-
13+ import xbmcvfs
1314
1415# s1-9, s101-109
1516SUB_DOMAINS = ['s1' , 's2' , 's3' , 's4' , 's5' , 's6' , 's7' , 's8' , 's9' ,
1617 's101' , 's102' , 's103' , 's104' , 's105' , 's106' , 's107' , 's108' , 's109' ]
1718API_URL_TEMPLATE = "http://{sub_domain}.api.bsplayer-subtitles.com/v1.php"
1819
1920
20- def check_connectivity (url , timeout = 5 ):
21- try :
22- urllib2 .urlopen (url , timeout = timeout )
23- except urllib2 .URLError :
24- return False
25- return True
26-
27-
2821def get_sub_domain ():
2922 sub_domains_end = len (SUB_DOMAINS ) - 1
30- url = API_URL_TEMPLATE .format (sub_domain = SUB_DOMAINS [random .randint (0 , sub_domains_end )])
23+ return API_URL_TEMPLATE .format (sub_domain = SUB_DOMAINS [random .randint (0 , sub_domains_end )])
3124
32- while not check_connectivity (url ):
33- url = API_URL_TEMPLATE .format (sub_domain = SUB_DOMAINS [random .randint (0 , sub_domains_end )])
3425
35- return url
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 )
3630
3731
3832def python_logger (module , msg ):
3933 logger = logging .getLogger ('BSPlayer' )
40- logger .log ((u"### [%s] - %s" % (module , msg )), level = logging .DEBUG )
41-
42-
43- def generic_open (file_path ):
44- rf = None
45- if path .splitext (file_path )[1 ] == '.rar' :
46- rf = rarfile .RarFile (file_path )
47- rfi = rf .infolist ()[0 ]
48- return rf , rf .open (rfi , 'r' ), rfi .file_size
49- return rf , open (file_path , 'rb' ), path .getsize (file_path )
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
5083
5184
5285def movie_size_and_hash (file_path ):
53- try :
54- longlong_format = '<q' # little-endian long long
55- byte_size = struct .calcsize (longlong_format )
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 )
5692
57- rf , f , file_size = generic_open (file_path )
58- movie_hash = file_size
93+ file_size = path . getsize (file_path )
94+ movie_hash = file_size
5995
60- if file_size < 65536 * 2 :
61- return "SizeError"
96+ if file_size < 65536 * 2 :
97+ raise Exception ( "SizeError" )
6298
99+ with open (file_path , 'rb' ) as f :
63100 for x in range (65536 / byte_size ):
64101 buff = f .read (byte_size )
65102 (l_value ,) = struct .unpack (longlong_format , buff )
@@ -74,14 +111,7 @@ def movie_size_and_hash(file_path):
74111 movie_hash &= 0xFFFFFFFFFFFFFFFF
75112 returned_movie_hash = "%016x" % movie_hash
76113
77- # Close File And RarFile
78- f .close ()
79- if rf :
80- rf .close ()
81-
82- return file_size , returned_movie_hash
83- except IOError :
84- return "IOError"
114+ return file_size , returned_movie_hash
85115
86116
87117class HTTP10Connection (HTTPConnection ):
@@ -95,8 +125,9 @@ def http_open(self, req):
95125
96126
97127class BSPlayer (object ):
98- def __init__ (self , search_url = get_sub_domain (), log = python_logger ):
99- self .search_url = search_url
128+ def __init__ (self , search_url = None , log = python_logger , proxies = None ):
129+ self .session = get_session (proxies )
130+ self .search_url = search_url or get_sub_domain ()
100131 self .token = None
101132 self .log = log
102133 if self .log .__name__ == 'python_logger' :
@@ -113,7 +144,7 @@ def __enter__(self):
113144 def __exit__ (self , exc_type , exc_val , exc_tb ):
114145 return self .logout ()
115146
116- def api_request (self , func_name = 'logIn' , params = '' ):
147+ def api_request (self , func_name = 'logIn' , params = '' , tries = 5 ):
117148 headers = {
118149 'User-Agent' : 'BSPlayer/2.x (1022.12360)' ,
119150 'Content-Type' : 'text/xml; charset=utf-8' ,
@@ -130,8 +161,19 @@ def api_request(self, func_name='logIn', params=''):
130161 '<ns1:{func_name}>{params}</ns1:{func_name}></SOAP-ENV:Body></SOAP-ENV:Envelope>'
131162 ).format (search_url = self .search_url , func_name = func_name , params = params )
132163
133- req = urllib2 .Request (self .search_url , data , headers )
134- return ElementTree .fromstring (urllib2 .urlopen (req ).read ())
164+ self .log ("BSPlayer.api_request" , 'Sending request: %s' % func_name )
165+ for i in xrange (tries ):
166+ try :
167+ self .session .addheaders .extend (headers .items ())
168+ res = self .session .open (self .search_url , data )
169+ return ElementTree .fromstring (res .read ())
170+ except Exception , ex :
171+ self .log ("BSPlayer.api_request" , ex )
172+ if func_name == 'logIn' :
173+ self .search_url = get_sub_domain ()
174+ sleep (1 )
175+
176+ raise Exception ('Too many tries...' )
135177
136178 def login (self ):
137179 # If already logged in
@@ -175,6 +217,7 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False):
175217 language_ids = "," .join (language_ids )
176218
177219 movie_size , movie_hash = movie_size_and_hash (movie_path )
220+ self .log ('BSPlayer.search_subtitles' , 'Movie Size: %s, Movie Hash: %s' % (movie_size , movie_hash ))
178221 root = self .api_request (
179222 func_name = 'searchSubtitles' ,
180223 params = (
@@ -209,8 +252,9 @@ def search_subtitles(self, movie_path, language_ids='heb,eng', logout=False):
209252 return subtitles
210253
211254 @staticmethod
212- def download_subtitles (download_url , dest_path = r"c:\tomerz.srt" ):
213- opener = urllib2 .build_opener (HTTP10Handler )
255+ def download_subtitles (download_url , dest_path = "Subtitle.srt" , proxies = None ):
256+ proxy_handler = urllib2 .ProxyHandler (proxies )
257+ opener = urllib2 .build_opener (HTTP10Handler , proxy_handler )
214258 opener .addheaders = [('User-Agent' , 'Mozilla/4.0 (compatible; Synapse)' ),
215259 ('Content-Length' , 0 )]
216260 res = opener .open (download_url )
@@ -222,13 +266,14 @@ def download_subtitles(download_url, dest_path=r"c:\tomerz.srt"):
222266 gf .close ()
223267 return True
224268 return False
225- #
269+
226270#
227271# if __name__ == '__main__':
228- # bsp = BSPlayer()
272+ # bsp = BSPlayer(proxies={'http': '207.91.10.234:8080'} )
229273# subs = bsp.search_subtitles(
230- # r'..\..\..\Jurassic.World.2015 .720p.BluRay .x264-SPARKS\jurassic.world.2015. 720p.bluray .x264-sparks.rar ',
274+ # 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 ',
231275# logout=True
232276# )
233- # print subs[0]['subDownloadLink']
234- # print bsp.download_subtitles(subs[0]['subDownloadLink'])
277+ # for sub in subs:
278+ # print bsp.download_subtitles(sub['subDownloadLink'], proxies={'http': '207.91.10.234:8080'})
279+ # break
0 commit comments