Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Sep 18th, 2012  |  syntax: Python  |  size: 7.01 KB  |  hits: 19  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env python3
  2.  
  3. __version__   = 'version 0.6'
  4. __author__    = 'Marcin ``MySZ`` Sztolcman <marcin@urzenia.net> (based od napi.py from http://hacking.apcoh.com/2008/01/napi_06.html - 0.15b)'
  5. __copyright__ = '(r) 2008 - 2012'
  6. __program__   = 'napi.py - find and download polish subtitles for films (from http://www.napiprojekt.pl/)'
  7. __date__      = '2008-11-21'
  8. __license__   = 'GPL v.2'
  9.  
  10. __desc__      = '''%(desc)s
  11. %(author)s %(copyright)s
  12. license: %(license)s
  13. %(version)s (%(date)s)''' % {
  14.   'desc': __program__,
  15.   'author': __author__,
  16.   'copyright': __copyright__,
  17.   'license': __license__,
  18.   'version': __version__,
  19.   'date': __date__
  20. }
  21.  
  22.  
  23.  
  24. import hashlib
  25. import os, os.path
  26. import re
  27. import subprocess
  28. import sys
  29. import tempfile
  30. import urllib.request
  31.  
  32. def calculate_md5 (path):
  33.     with open (path, 'rb') as fh:
  34.         return hashlib.md5 (fh.read (10485760)).hexdigest ()
  35.  
  36. def calculate_f (md5digest):
  37.     idx = ( 0xe, 0x3,  0x6, 0x8, 0x2 )
  38.     mul = (   2,   2,    5,   4,   3 )
  39.     add = (   0, 0xd, 0x10, 0xb, 0x5 )
  40.  
  41.     b = []
  42.     for a, m, i in zip (add, mul, idx):
  43.         t = a + int (md5digest[i], 16)
  44.         v = int (md5digest[t:t+2], 16)
  45.         b.append ( ('%x' % (v*m))[-1] )
  46.  
  47.     return ''.join (b)
  48.  
  49. def extract_subtitles (data):
  50.     # create temporary archive for 7zip
  51.     with tempfile.NamedTemporaryFile (mode='wb', prefix='sub_') as fh:
  52.         fh.write (data)
  53.         fh_arch_path = fh.name
  54.  
  55.         # extract archive and write it to second temporary file
  56.         cmd = ('7za', 'x', '-y', '-so', '-bd', '-piBlm8NTigvru0Jr0', fh_arch_path, )
  57.  
  58.         p = subprocess.Popen (cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  59.         stdout, stderr = p.communicate ()
  60.  
  61.         if p.returncode != 0:
  62.             return False
  63.  
  64.     # return content of subtitles
  65.     return stdout
  66.  
  67. def get_subtitles (film, output=None):
  68.     if not os.path.isfile (film):
  69.         return False
  70.  
  71.     md5 = calculate_md5 (film)
  72.  
  73.     url = 'http://napiprojekt.pl/unit_napisy/dl.php?l=PL&f=%s&t=%s&v=other&kolejka=false&nick=&pass=&napios=%s'
  74.     url %= (md5, calculate_f (md5), os.name)
  75.  
  76.     # download and extract subtitles if found
  77.     data = urllib.request.urlopen (url).read ()
  78.     data = extract_subtitles (data)
  79.     if not data:
  80.         return False
  81.  
  82.     # find output directory and correct subtitles filename
  83.     dname, fname = os.path.split (film)
  84.     if output and os.path.isdir (output):
  85.         dname   = output
  86.     elif not dname:
  87.         dname   = os.getcwd ()
  88.  
  89.     # write subtitles file in right directory
  90.     fname = os.path.splitext (fname)[0] + '.txt'
  91.     with open (os.path.join (dname, fname), 'wb') as fh:
  92.         fh.write (data)
  93.  
  94.     return True
  95.  
  96. def has_subtitle (film):
  97.     p = os.path.splitext (film)
  98.     return os.path.isfile (p[0] + '.txt')
  99.  
  100. def is_film (path):
  101.     if os.path.isfile (path) and re.search ('\.(?:avi|mpe?g|mp4|mkv|rmvb)$', path, re.I):
  102.         return True
  103.     return False
  104.  
  105. def find_films__recursive (path):
  106.     ret = []
  107.     for root, dirs, files in os.walk (path):
  108.         for f in files:
  109.             p = os.path.join (root, f)
  110.             if is_film (p):
  111.                 ret.append (p)
  112.     return ret
  113.  
  114. def find_films__nonrecursive (path):
  115.     ret = []
  116.     for fname in os.listdir (path):
  117.         p = os.path.join (path, fname)
  118.         if is_film (p):
  119.             ret.append (p)
  120.     return ret
  121.  
  122. def find_films (path, recursive=False):
  123.     if not os.path.isdir (path):
  124.         return
  125.  
  126.     if recursive:
  127.         return find_films__recursive (path)
  128.     else:
  129.         return find_films__nonrecursive (path)
  130.  
  131.  
  132. def main ():
  133.     import getopt
  134.  
  135.     usage = __desc__ + "\n\n" + '''%s [-h|--help] [-v|--version] [-d|--directory] [-r|--recursive] [-o|--output output_dir] [-n|--no-validate] [-w|--overwrite] input1 input2 .. inputN
  136. -h|--help           - this help message
  137. -d|--directory      - if specified, scan every passed argument (input1 .. inputN) for files with extensions: avi, mpeg, mpg, mp4, mkv, rmvb
  138. -r|--recursive      - if specified, every directory passed as input will be scanned recursively. Skipped when -d is not specified
  139. -o|--output_dir     - specify directory when you want to save downloaded files. If not specified, try to save every subtitle in films directory
  140. -n|--no-validate    - if given, specified list of films will not be validated for being movie files (work only without -d parameter)
  141. -w|--overwrite      - if specified, existent subtitles will not be overwritten
  142. input1 .. inputN    - if -d is not specified, this is treaten like films files, to which you want to download subtitles. In other case, this is list of directories whis are scanned for files''' % (os.path.basename (sys.argv[0]),)
  143.  
  144.     ## parsing getopt options
  145.     opts_short  = 'hdo:rnw'
  146.     opts_long   = ['help', 'directory', 'output=', 'recursive', 'no-validate', 'overwrite']
  147.     try:
  148.         opts, args = getopt.gnu_getopt (sys.argv[1:], opts_short, opts_long)
  149.     except getopt.GetoptError as e:
  150.         print (e)
  151.         raise SystemExit (1)
  152.  
  153.     recursive       = False
  154.     directory       = False
  155.     output          = None
  156.     validate        = True
  157.     overwrite       = False
  158.     for o, a in opts:
  159.         if o in ('-h', '--help'):
  160.             print (usage)
  161.             raise SystemExit (0)
  162.         elif o in ('-v', '--version'):
  163.             print (__version__)
  164.             raise SystemExit (0)
  165.         elif o in ('-d', '--directory'):
  166.             directory = True
  167.         elif o in ('-r', '--recursive'):
  168.             recursive = True
  169.         elif o in ('-o', '--output'):
  170.             output = a
  171.         elif o in ('-n', '--no-validate'):
  172.             validate = False
  173.         elif o in ('-w', '--overwrite'):
  174.             overwrite = True
  175.  
  176.     ## find all films
  177.     fnames = []
  178.     if directory:
  179.         dirs = []
  180.         if not args:
  181.             dirs.append (os.getcwd ())
  182.         else:
  183.             dirs.extend (args)
  184.         for d in dirs:
  185.             f = find_films (d, recursive)
  186.             if f:
  187.                 fnames.extend (f)
  188.  
  189.     ## all files from current dir
  190.     elif not args:
  191.         fnames.extend (find_films (os.getcwd ()))
  192.  
  193.     ## check files given by user
  194.     elif validate:
  195.         fnames.extend (f for f in args if is_film (f))
  196.  
  197.     ## don't check, every given file is a file (skip only nonfile)
  198.     else:
  199.         fnames.extend (f for f in args if os.path.isfile (f))
  200.  
  201.     ## skip searching for existent subtitles
  202.     if not overwrite:
  203.         fnames = [ f for f in fnames if not has_subtitle (f) ]
  204.  
  205.     if not fnames:
  206.         print ('Cannot find any film.')
  207.         raise SystemExit (2)
  208.  
  209.     # find longest filename
  210.     length = max (map (len, fnames)) + 1
  211.  
  212.     ## download all subtitles
  213.     for fname in fnames:
  214.         r = get_subtitles (fname, output)
  215.         if r:
  216.             status = 'done'
  217.         else:
  218.             status = 'not found'
  219.         fname += ' '
  220.         print ('%s: %s' % (fname.ljust (length, '-'), status))
  221.  
  222.  
  223. if __name__ == '__main__':
  224.     main ()
  225.  
  226. # vim: ft=python