2 # -*- coding: UTF-8 -*-
4 # Copyright (C) 2009 Arkadiusz MiĆkiewicz <arekm@pld-linux.org>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # napiprojekt.pl API is used with napiproject administration consent
20 # (given by Marek <kontakt@napiprojekt.pl> at Wed, 24 Feb 2010 14:43:00 +0100)
31 from hashlib import md5 as md5
35 prog = os.path.basename(sys.argv[0])
37 video_files = [ 'asf', 'avi', 'divx', 'm2ts', 'mkv', 'mp4', 'mpeg', 'mpg', 'ogm', 'rm', 'rmvb', 'wmv' ]
38 languages = { 'pl': 'PL', 'en': 'ENG' }
41 idx = [ 0xe, 0x3, 0x6, 0x8, 0x2 ]
42 mul = [ 2, 2, 5, 4, 3 ]
43 add = [ 0, 0xd, 0x10, 0xb, 0x5 ]
46 for i in xrange(len(idx)):
53 b.append( ("%x" % (v*m))[-1] )
58 print >> sys.stderr, "Usage: %s [OPTIONS]... [FILE|DIR]..." % prog
59 print >> sys.stderr, "Find video files and download matching subtitles from napiprojekt server."
61 print >> sys.stderr, "Supported options:"
62 print >> sys.stderr, " -h, --help display this help and exit"
63 print >> sys.stderr, " -l, --lang=LANG subtitles language"
64 print >> sys.stderr, " -n, --nobackup make no subtitle backup when in update mode"
65 print >> sys.stderr, " -c, --nocover do not download cover images"
66 print >> sys.stderr, " -u, --update fetch new and also update existing subtitles"
67 print >> sys.stderr, " -d, --dest=DIR destination directory"
69 print >> sys.stderr, "pynapi $Revision$"
71 print >> sys.stderr, "Report bugs to <arekm@pld-linux.org>."
73 def get_desc_links(digest, file=None):
75 re_link = re.compile(r'<a.*?href=[\'"](http://.*?)[ >\'"]', re.IGNORECASE)
79 url = "http://www.napiprojekt.pl/index.php3?www=opis.php3&id=%s&film=%s" % (urllib2.quote(digest), urllib2.quote(file))
80 f = urllib2.urlopen(url)
85 links = re_link.findall(d)
86 ignore = [ r'.*napiprojekt\.pl.*', r'.*nokaut\.pl.*', r'.*rodisite\.com.*' ]
87 for i in range(0, len(ignore)):
88 ignore[i] = re.compile(ignore[i], re.IGNORECASE)
96 def get_cover(digest):
99 url = "http://www.napiprojekt.pl/okladka_pobierz.php?id=%s&oceny=-1" % (urllib2.quote(digest))
100 f = urllib2.urlopen(url)
103 content_type = f.info()['Content-Type']
104 extension = mimetypes.guess_all_extensions(content_type)[-1]
107 return (cover, extension)
109 def calculate_digest(file):
112 d.update(open(file, "rb").read(10485760))
113 except (IOError, OSError), e:
114 raise Exception('Hashing video file failed: %s' % ( e ))
117 def get_subtitle(digest, lang="PL"):
118 url = "http://napiprojekt.pl/unit_napisy/dl.php?l=%s&f=%s&t=%s&v=pynapi&kolejka=false&nick=&pass=&napios=%s" % \
119 (lang, digest, f(digest), os.name)
123 error = "Fetching subtitle failed:"
127 sub = urllib2.urlopen(url)
128 if hasattr(sub, 'getcode'):
129 http_code = sub.getcode()
131 except (IOError, OSError), e:
132 error = error + " %s" % (e)
137 error = error + ",HTTP code: %s" % (str(http_code))
141 if sub.startswith('NPc') or sub.find('Blad polaczenia z baza danych') != -1:
142 raise Exception('Subtitle NOT FOUND')
146 if sub is None or sub == "":
147 raise Exception(error)
151 def main(argv=sys.argv):
154 opts, args = getopt.getopt(argv[1:], "d:hl:nuc", ["dest", "help", "lang", "nobackup", "update", "nocover"])
155 except getopt.GetoptError, err:
170 elif o in ("-h", "--help"):
173 elif o in ("-l", "--lang"):
177 print >> sys.stderr, "%s: unsupported language `%s'. Supported languages: %s" % (prog, a, str(languages.keys()))
179 elif o in ("-n", "--nobackup"):
181 elif o in ("-u", "--update"):
183 elif o in ("-c", "--nocover"):
185 elif o in ("-d", "--dest"):
188 print >> sys.stderr, "%s: unhandled option" % prog
195 print >> sys.stderr, "%s: Subtitles language `%s'. Finding video files..." % (prog, lang)
199 if os.path.isdir(arg):
200 for dirpath, dirnames, filenames in os.walk(arg, topdown=False):
201 for file in filenames:
202 if file[-4:-3] == '.' and file.lower()[-3:] in video_files:
203 files.append(os.path.join(dirpath, file))
215 vfile = file + '.txt'
219 vfile = basefile + '.txt'
221 vfile = os.path.join(dest, os.path.split(vfile)[1])
223 if not update and os.path.exists(vfile):
226 if not nobackup and os.path.exists(vfile):
227 vfile_bak = vfile + '-bak'
229 os.rename(vfile, vfile_bak)
230 except (IOError, OSError), e:
231 print >> sys.stderr, "%s: Skipping due to backup of `%s' as `%s' failure: %s" % (prog, vfile, vfile_bak, e)
234 print >> sys.stderr, "%s: Old subtitle backed up as `%s'" % (prog, vfile_bak)
236 print >> sys.stderr, "%s: %d/%d: Processing subtitle for %s" % (prog, i, i_total, file)
239 digest = calculate_digest(file)
240 sub = get_subtitle(digest, languages[lang])
242 print >> sys.stderr, "%s: %d/%d: %s" % (prog, i, i_total, sys.exc_info()[1])
245 fp = open(vfile, 'wb')
249 desc = get_desc_links(digest, file)
251 print >> sys.stderr, "%s: %d/%d: Description: " % (prog, i, i_total)
253 print >> sys.stderr, "\t\t%s" % desc_i
257 cover_data = get_cover(digest)
259 cover, extension = cover_data
260 fp = open(basefile + extension, 'wb')
263 cover_stored = ", %s COVER STORED (%d bytes)" % (extension, len(cover))
265 print >> sys.stderr, "%s: %d/%d: SUBTITLE STORED (%d bytes)%s" % (prog, i, i_total, len(sub), cover_stored)
269 if __name__ == "__main__":
273 except (KeyboardInterrupt, SystemExit):
274 print >> sys.stderr, "%s: Interrupted, aborting." % prog