1- import cookielib
2- import gzip
3- import logging
1+ import gzip
42import random
5- import struct
6- import urllib2
7- from StringIO import StringIO
8- from httplib import HTTPConnection
9- from os import path
103from time import sleep
4+ from StringIO import StringIO
115from 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
1610SUB_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-
12920class 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