1
from xmlrpclib import ServerProxy
8
from flexget.manager import Session, Base
9
from flexget.plugin import register_plugin
10
from sqlalchemy import Column, Integer, String, DateTime, PickleType
11
from datetime import datetime, timedelta
12
from flexget.utils.tools import urlopener
18
class SubtitleQueue(Base):
20
__tablename__ = 'subtitle_queue'
22
id = Column(Integer, primary_key=True)
24
imdb_id = Column(String)
25
added = Column(DateTime)
27
def __init__(self, feed, imdb_id):
29
self.imdb_id = imdb_id
30
self.added = datetime.now()
33
return '<SubtitleQueue(%s=%s)>' % (self.feed, self.imdb_id)
37
* add new option, retry: [n] days
38
* add everything into queue using above class
39
* consume queue (look up by feed name), configuration is available from feed
40
* remove successful downloads
41
* remove queue items that are part retry: n days
45
log = logging.getLogger('subtitles')
47
# movie hash, won't work here though
48
# http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes#Python
51
# http://trac.opensubtitles.org/projects/opensubtitles/wiki/XMLRPC
54
class Subtitles(object):
56
Fetch subtitles from opensubtitles.org
60
from flexget import validator
61
subs = validator.factory('dict')
62
langs = subs.accept('list', key='languages')
64
subs.accept('number', key='min_sub_rating')
65
subs.accept('number', key='match_limit')
66
subs.accept('path', key='output')
69
def get_config(self, feed):
70
config = feed.config['subtitles']
71
if not isinstance(config, dict):
73
config.setdefault('output', feed.manager.config_base)
74
config.setdefault('languages', ['eng'])
75
config.setdefault('min_sub_rating', 0.0)
76
config.setdefault('match_limit', 0.8)
77
config['output'] = os.path.expanduser(config['output'])
80
def on_feed_download(self, feed):
82
# filter all entries that have IMDB ID set
84
entries = filter(lambda x: x['imdb_url'] is not None, feed.accepted)
86
# No imdb urls on this feed, skip it
87
# TODO: should do lookup via imdb_lookup plugin?
91
s = ServerProxy("http://api.opensubtitles.org/xml-rpc")
92
res = s.LogIn("", "", "en", "FlexGet")
94
log.warning('Error connecting to opensubtitles.org')
97
if res['status'] != '200 OK':
98
raise Exception("Login to opensubtitles.org XML-RPC interface failed")
100
config = self.get_config(feed)
105
languages = config['languages']
106
min_sub_rating = config['min_sub_rating']
107
match_limit = config['match_limit'] # no need to change this, but it should be configurable
109
# loop through the entries
110
for entry in entries:
111
# dig out the raw imdb id
112
m = re.search("tt(\d+)/$", entry['imdb_url'])
114
log.debug("no match for %s" % entry['imdb_url'])
120
for language in languages:
121
query.append({'sublanguageid': language, 'imdbid': imdbid})
123
subtitles = s.SearchSubtitles(token, query)
124
subtitles = subtitles['data']
126
# nothing found -> continue
131
subtitles = filter(lambda x: x['SubBad'] == '0', subtitles)
132
# some quality required (0.0 == not reviewed)
133
subtitles = filter(lambda x: float(x['SubRating']) >= min_sub_rating or float(x['SubRating']) == 0.0, subtitles)
137
# find the best rated subs for each language
138
for language in languages:
139
langsubs = filter(lambda x: x['SubLanguageID'] == language, subtitles)
141
# did we find any subs for this language?
144
def seqmatch(subfile):
145
s = difflib.SequenceMatcher(lambda x: x in " ._", entry['title'], subfile)
146
#print "matching: ", entry['title'], subfile, s.ratio()
147
return s.ratio() > match_limit
149
# filter only those that have matching release names
150
langsubs = filter(lambda x: seqmatch(x['MovieReleaseName']), subtitles)
153
# find the best one by SubRating
154
langsubs.sort(key=lambda x: float(x['SubRating']))
156
filtered_subs.append(langsubs[0])
159
for sub in filtered_subs:
160
log.debug('SUBS FOUND: ', sub['MovieReleaseName'], sub['SubRating'], sub['SubLanguageID'])
162
f = urlopener(sub['ZipDownloadLink'], log)
163
subfilename = re.match('^attachment; filename="(.*)"$', f.info()['content-disposition']).group(1)
164
outfile = os.path.join(config['output'], subfilename)
165
fp = file(outfile, 'w')
172
register_plugin(Subtitles, 'subtitles')