4
from flexget.plugin import register_plugin, DependencyError
5
from flexget.utils.tools import urlopener
8
import simplejson as json
13
raise DependencyError(issued_by='trakt_acquired', missing='simplejson',
14
message='trakt_acquired requires either '
15
'simplejson module or python > 2.5')
17
log = logging.getLogger('trakt_acquired')
20
class TraktAcquired(object):
21
"""Marks all accepted TV episodes or movies as acquired in your trakt.tv library."""
24
from flexget import validator
25
root = validator.factory('dict')
26
root.accept('text', key='username', required=True)
27
root.accept('text', key='password', required=True)
28
root.accept('text', key='api_key', required=True)
29
root.accept('choice', key='type', required=True).accept_choices(['movies', 'series'])
32
def on_feed_exit(self, feed, config):
33
"""Finds accepted movies and series episodes and submits them to trakt as acquired."""
34
# Change password to an SHA1 digest of the password
35
config['password'] = hashlib.sha1(config['password']).hexdigest()
37
for entry in feed.accepted:
38
if config['type'] == 'series':
39
# Check entry is a series episode
40
if entry.get('series_name') and entry.get('series_season') and entry.get('series_episode'):
41
series = found.setdefault(entry['series_name'], {})
43
# If this is the first episode found from this series, set the parameters
44
series['title'] = entry.get('series_name_tvdb', entry['series_name'])
45
if entry.get('imdb_id'):
46
series['imdb_id'] = entry['imdb_id']
47
if entry.get('thetvdb_id'):
48
series['tvdb_id'] = entry['thetvdb_id']
49
series['episodes'] = []
50
episode = {'season': entry['series_season'], 'episode': entry['series_episode']}
51
series['episodes'].append(episode)
52
log.debug('Marking %s S%02dE%02d for submission to trakt.tv library.' % \
53
(entry['series_name'], entry['series_season'], entry['series_episode']))
55
# Check entry is a movie
56
if entry.get('imdb_id') or entry.get('tmdb_id'):
58
# We know imdb_id or tmdb_id is filled in, so don't cause any more lazy lookups
59
if entry.get('movie_name', eval_lazy=False):
60
movie['title'] = entry['movie_name']
61
if entry.get('movie_year', eval_lazy=False):
62
movie['year'] = entry['movie_year']
63
if entry.get('tmdb_id', eval_lazy=False):
64
movie['tmdb_id'] = entry['tmdb_id']
65
if entry.get('imdb_id', eval_lazy=False):
66
movie['imdb_id'] = entry['imdb_id']
67
# We use an extra container dict so that the found dict is usable in the same way as found series
68
found.setdefault('movies', {}).setdefault('movies', []).append(movie)
69
log.debug('Marking %s for submission to trakt.tv library.' % entry['title'])
72
log.debug('Nothing to submit to trakt.')
75
if feed.manager.options.test:
76
log.info('Not submitting to trakt.tv because of test mode.')
79
# Submit our found items to trakt
80
if config['type'] == 'series':
81
post_url = 'http://api.trakt.tv/show/episode/library/' + config['api_key']
83
post_url = 'http://api.trakt.tv/movie/library/' + config['api_key']
84
for item in found.itervalues():
85
# Add username and password to the dict to submit
86
item.update({'username': config['username'], 'password': config['password']})
88
self.post_json_to_trakt(post_url, item)
89
except (urllib2.HTTPError, urllib2.URLError), e:
90
if hasattr(e, 'code'):
92
# Remove some info from posted json and print the rest to aid debugging
93
for key in ['username', 'password', 'episodes']:
95
log.error('%s not found on trakt: %s' % (config['type'].capitalize(), item))
98
log.error('Error authenticating with trakt. Check your username/password/api_key')
100
log.error('Error submitting data to trakt.tv: %s' % e)
103
def post_json_to_trakt(self, url, data):
104
"""Dumps data as json and POSTs it to the specified url."""
105
req = urllib2.Request(url, json.dumps(data), {'content-type': 'application/json'})
106
return urlopener(req, log)
109
register_plugin(TraktAcquired, 'trakt_acquired', api_ver=2)