Skip to content

Instantly share code, notes, and snippets.

@vasc
Created August 9, 2010 00:25
Show Gist options
  • Save vasc/514732 to your computer and use it in GitHub Desktop.
Save vasc/514732 to your computer and use it in GitHub Desktop.
'''
Created on 3 de Ago de 2010
@author: Vasco
'''
import struct
import os.path
import httplib
from util import UnavailableError, retry
import traceback
import sys
import shelve
@retry(UnavailableError, 10, 3)
def getsub(h1, headers, subs, good, lang):
h1.request('GET', '/isdb/dl.php?id=%s&ticket=%s' % (good[lang][0]['num'], subs['ticket']), headers=headers)
response2 = h1.getresponse()
if not response2.status == 200:
raise UnavailableError()
return response2
def download(name, hash, filesize, db):
h1 = httplib.HTTPConnection('www.opensubtitles.org')
headers = {'User-Agent': 'Media Player Classic',
'Host': 'www.opensubtitles.org',
'Connection': 'keep-alive'}
print '/isdb/index.php?player=mpc&name[0]=%s&size[0]=%016x&hash[0]=%s' % (name, filesize, hash)
h1.request('GET',
'/isdb/index.php?player=mpc&name[0]=%s&size[0]=%016x&hash[0]=%s' % (name, filesize, hash),
headers=headers)
response = h1.getresponse()
if not response.status == 200: raise Exception("status: %s" % response.status)
response_headers = response.getheaders()
#print response_headers
cookie = [h[1].split(';')[0] for h in response_headers if h[0] == 'set-cookie'][0]
#print cookie
#print response_headers
headers['Cookie'] = cookie
data = response.read()
print '%s %s' % (response.status, name)
#print data
if data == '':
db[name] = None
return {}
subs = parse_os_data(data)
good = {'en': [], 'pt': [], 'pb': []}
for s in subs:
v = subs[s]
if 'iso639_2' in v and (v['iso639_2'] == 'en' or v['iso639_2'] == 'pt' or v['iso639_2'] == 'pb'):
v['num'] = s
good[v['iso639_2']].append(v)
#print 'ticket: %s' % subs['ticket']
subtitle_data = {}
for lang in ('pt', 'pb', 'en'):
if(len(good[lang]) > 0):
#print good[lang][0]['num']
try:
response2 = getsub(h1, headers, subs, good, lang)
except:
continue
data = response2.read()
#print response.status
#print data
subtitle_data[lang] = data
return subtitle_data
def parse_os_data(data):
subtitles = {}
current = 'none'
subtitles[current] ={}
lines = data.splitlines()
subtitles[lines[0].split('=')[0]] = lines[0].split('=')[1]
for l in lines[1:]:
if l.startswith('subtitle='):
current=l.split('=')[1]
subtitles[current] = {}
elif l == 'endsubtitle':
pass
elif not l.find('=') == -1:
field = l.split('=')
subtitles[current][field[0]] = field[1]
return subtitles
def download_subtitle(path, name, ext, db):
#if not name == 'bones.s05e12.hdtv.xvid-fqm': return
if os.path.exists(path+'\\'+name+'.pt.srt'): return
if os.path.exists(path+'\\'+name+'.pb.srt'): return
if os.path.exists(path+'\\'+name+'.en.srt'): return
if db.has_key(name+ext): return
fullpath = path+'\\'+name+ext
hash = hashFile(fullpath)
filesize = os.path.getsize(fullpath)
if filesize < 20000000: return
sub_data = {}
try:
sub_data = download(name+ext, hash, filesize, db)
except Exception as e:
print e
#traceback.print_exc(file=sys.stdout)
for lang in ('pt', 'pb', 'en'):
subfile = path+'\\'+name+'.'+lang+'.srt'
if os.path.exists(subfile): return
elif lang in sub_data:
print subfile
f = open(subfile, "wb")
f.write(sub_data[lang])
f.close()
db[name+ext] = lang
return
def hashFile(path):
try:
longlongformat = 'q' # long long
bytesize = struct.calcsize(longlongformat)
f = open(path, "rb")
filesize = os.path.getsize(path)
hash = filesize
if filesize < 65536 * 2:
return "SizeError"
for x in range(65536/bytesize):
buffer = f.read(bytesize)
(l_value,)= struct.unpack(longlongformat, buffer)
hash += l_value
hash = hash & 0xFFFFFFFFFFFFFFFF #to remain as 64bit number
f.seek(max(0,filesize-65536),0)
for x in range(65536/bytesize):
buffer = f.read(bytesize)
(l_value,)= struct.unpack(longlongformat, buffer)
hash += l_value
hash = hash & 0xFFFFFFFFFFFFFFFF
f.close()
returnedhash = "%016x" % hash
return returnedhash
except(IOError):
return "IOError"
'''
Created on 3 de Ago de 2010
@author: Vasco
'''
import os
import re
import httplib
import opensubtitles as osub
import shelve
class Renamer:
main_path = None
def __init__(self, main_path):
self.main_path = main_path
def rename(self, r=True):
self.recursive_rename(self.main_path, r)
def recursive_rename(self, folder, rename):
#print "Entering folder: %s" % folder
db = shelve.open('videosubs.db')
for f in os.listdir(folder):
fullpath = folder + '\\' + f
newf = f.lower();
if os.path.isdir(fullpath) and not f.startswith('_'): self.recursive_rename(fullpath, rename)
elif os.path.isfile(fullpath):
if newf.endswith(('.avi', '.mkv', '.mp4')) and rename:
if not re.search(r'\.s\d\de\d\d\.',newf):
if re.search(r'\.\dx\d\d\.', newf):
newf = re.sub(r'\.(\d)x(\d\d+)\.', r'.s0\1e\2.', newf)
elif re.search(r'\.\d\d+x\d\d\.', newf):
newf = re.sub(r'\.(\d\d+)x(\d\d+)\.', r'.s\1e\2.', newf)
elif re.search(r'\.\d{4}\.', newf):
newf = re.sub(r'\.(\d\d)(\d\d)\.', r'.s\1e\2.', newf)
elif re.search(r'\.\d{3}\.', newf):
newf = re.sub(r'\.(\d)(\d\d)\.', r'.s0\1e\2.', newf)
if not f == newf:
os.rename(folder+'\\'+f, folder+'\\'+newf)
print "Renamed %s to %s" % (f, newf)
if newf.endswith(('.avi', '.mkv', '.mp4')):
osub.download_subtitle(folder, newf[:-4], newf[-4:], db)
db.close()
if __name__ == '__main__':
Renamer("C:\\Users\\Public\\Videos\\Shows").rename()
Renamer("C:\\Users\\Public\\Videos\\Movies").rename(False)
'''
Created on 4 de Ago de 2010
@author: Vasco
'''
import time
class UnavailableError(Exception):
pass
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2):
"""Retry decorator
original from http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
"""
def deco_retry(f):
def f_retry(*args, **kwargs):
mtries, mdelay = tries, delay
try_one_last_time = True
while mtries > 1:
try:
return f(*args, **kwargs)
try_one_last_time = False
break
except ExceptionToCheck, e:
print "%s, Retrying in %d seconds..." % (str(e), mdelay)
time.sleep(mdelay)
mtries -= 1
mdelay *= backoff
if try_one_last_time:
return f(*args, **kwargs)
return
return f_retry # true decorator
return deco_retry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment