예제 #1
0
파일: trakt_list.py 프로젝트: umeku/Flexget
 def __init__(self, config):
     self.config = config
     if self.config.get('account') and not self.config.get('username'):
         self.config['username'] = '******'
     self.session = get_session(self.config.get('account'))
     # Lists may not have modified results if modified then accessed in quick succession.
     self.session.add_domain_limiter(TimedLimiter('trakt.tv', '2 seconds'))
     self._items = None
예제 #2
0
 def __init__(self, config):
     self.config = config
     if self.config.get('account') and not self.config.get('username'):
         self.config['username'] = '******'
     self.session = get_session(self.config.get('account'))
     # Lists may not have modified results if modified then accessed in quick succession.
     self.session.add_domain_limiter(TimedLimiter('trakt.tv', '2 seconds'))
     self._items = None
예제 #3
0
    def on_task_input(self, task, config):
        if config.get('account') and not config.get('username'):
            config['username'] = '******'
        session = get_session(account=config.get('account'))
        endpoint = ['users', config['username']]
        if type(config['list']) is dict:
            endpoint += ('ratings', config['type'], config['list']['rating'])
        elif config['list'] in ['collection', 'watchlist', 'watched', 'ratings']:
            endpoint += (config['list'], config['type'])
        else:
            endpoint += ('lists', make_list_slug(config['list']), 'items')

        log.verbose('Retrieving `%s` list `%s`' % (config['type'], config['list']))
        try:
            result = session.get(get_api_url(endpoint))
            try:
                data = result.json()
            except ValueError:
                log.debug('Could not decode json from response: %s', result.text)
                raise plugin.PluginError('Error getting list from trakt.')
        except RequestException as e:
            raise plugin.PluginError('Could not retrieve list from trakt (%s)' % e.args[0])

        if not data:
            log.warning('No data returned from trakt for %s list %s.' % (config['type'], config['list']))
            return

        entries = []
        list_type = (config['type']).rstrip('s')
        for item in data:
            # Collection and watched lists don't return 'type' along with the items (right now)
            if 'type' in item and item['type'] != list_type:
                log.debug('Skipping %s because it is not a %s' % (item[item['type']].get('title', 'unknown'),
                                                                  list_type))
                continue
            if not item[list_type]['title']:
                # There seems to be some bad shows sometimes in lists with no titles. Skip them.
                log.warning('Item in trakt list does not appear to have a title, skipping.')
                continue
            entry = Entry()
            if list_type == 'episode':
                entry['url'] = 'http://trakt.tv/shows/%s/seasons/%s/episodes/%s' % (
                    item['show']['ids']['slug'], item['episode']['season'], item['episode']['number'])
            else:
                entry['url'] = 'http://trakt.tv/%s/%s' % (list_type, item[list_type]['ids'].get('slug'))
            entry.update_using_map(field_maps[list_type], item)
            if entry.isvalid():
                if config.get('strip_dates'):
                    # Remove year from end of name if present
                    entry['title'] = re.sub(r'\s+\(\d{4}\)$', '', entry['title'])
                entries.append(entry)
            else:
                log.debug('Invalid entry created? %s' % entry)

        return entries
예제 #4
0
    def on_task_output(self, task, config):
        """Submits accepted movies or episodes to trakt api."""
        if config.get('account') and not config.get('username'):
            config['username'] = '******'
        found = {'shows': [], 'movies': []}
        for entry in task.accepted:
            if config['type'] in ['auto', 'shows', 'seasons', 'episodes'] and entry.get('series_name') is not None:
                show = {'title': entry['series_name'], 'ids': get_entry_ids(entry)}
                if config['type'] in ['auto', 'seasons', 'episodes'] and entry.get('series_season') is not None:
                    season = {'number': entry['series_season']}
                    if config['type'] in ['auto', 'episodes'] and entry.get('series_episode') is not None:
                        season['episodes'] = [{'number': entry['series_episode']}]
                    show['seasons'] = [season]
                if config['type'] in ['seasons', 'episodes'] and 'seasons' not in show:
                    self.log.debug('Not submitting `%s`, no season found.' % entry['title'])
                    continue
                if config['type'] == 'episodes' and 'episodes' not in show:
                    self.log.debug('Not submitting `%s`, no episode number found.' % entry['title'])
                    continue
                found['shows'].append(show)
            elif config['type'] in ['auto', 'movies']:
                movie = {'ids': get_entry_ids(entry)}
                if not movie['ids']:
                    if entry.get('movie_name') is not None:
                        movie['title'] = entry.get('movie_name') or entry.get('imdb_name')
                        movie['year'] = entry.get('movie_year') or entry.get('imdb_year')
                    else:
                        self.log.debug('Not submitting `%s`, no movie name or id found.' % entry['title'])
                        continue
                found['movies'].append(movie)

        if not (found['shows'] or found['movies']):
            self.log.debug('Nothing to submit to trakt.')
            return

        if config['list'] in ['collection', 'watchlist', 'watched']:
            args = ('sync', 'history' if config['list'] == 'watched' else config['list'])
        else:
            args = ('users', config['username'], 'lists', make_list_slug(config['list']), 'items')
        if self.remove:
            args += ('remove', )
        url = get_api_url(args)

        if task.manager.options.test:
            self.log.info('Not submitting to trakt.tv because of test mode.')
            return
        session = get_session(account=config.get('account'))
        self.log.debug('Submitting data to trakt.tv (%s): %s' % (url, found))
        try:
            result = session.post(url, data=json.dumps(found), raise_status=False)
        except RequestException as e:
            self.log.error('Error submitting data to trakt.tv: %s' % e)
            return
        if 200 <= result.status_code < 300:
            action = 'added'
            if self.remove:
                action = 'deleted'
            res = result.json()
            movies = res[action].get('movies', 0)
            shows = res[action].get('shows', 0)
            eps = res[action].get('episodes', 0)
            self.log.info('Successfully %s to/from list %s: %s movie(s), %s show(s), %s episode(s).',
                          action, config['list'], movies, shows, eps)
            for k, r in res['not_found'].iteritems():
                if r:
                    self.log.debug('not found %s: %s' % (k, r))
            # TODO: Improve messages about existing and unknown results
        elif result.status_code == 404:
            self.log.error('List does not appear to exist on trakt: %s' % config['list'])
        elif result.status_code == 401:
            self.log.error('Authentication error: have you authorized Flexget on Trakt.tv?')
            self.log.debug('trakt response: ' + result.text)
        else:
            self.log.error('Unknown error submitting data to trakt.tv: %s' % result.text)
예제 #5
0
 def on_task_input(self, task, config):
     if config.get('account') and not config.get('username'):
         config['username'] = '******'
     session = get_session(account=config.get('account'))
     listed_series = {}
     if config.get('list'):
         args = ('users', config['username'])
         if config['list'] in ['collection', 'watchlist', 'watched']:
             args += (config['list'], 'shows')
         else:
             args += ('lists', make_list_slug(config['list']), 'items')
         try:
             data = session.get(get_api_url(args)).json()
         except RequestException as e:
             raise plugin.PluginError('Unable to get trakt list `%s`: %s' % (config['list'], e))
         if not data:
             log.warning('The list "%s" is empty.' % config['list'])
             return
         for item in data:
             if item.get('show'):
                 if not item['show']['title']:
                     # Seems we can get entries with a blank show title sometimes
                     log.warning('Found trakt list show with no series name.')
                     continue
                 trakt_id = item['show']['ids']['trakt']
                 listed_series[trakt_id] = {
                     'series_name': '%s (%s)' % (item['show']['title'], item['show']['year']),
                     'trakt_id': trakt_id,
                     'tvdb_id': item['show']['ids']['tvdb'],
                     'trakt_list': config.get('list')}
     context = config['context']
     if context == 'collected':
         context = 'collection'
     entries = []
     for trakt_id, fields in listed_series.items():
         url = get_api_url('shows', trakt_id, 'progress', context)
         try:
             data = session.get(url).json()
         except RequestException as e:
             raise plugin.PluginError('An error has occured looking up: Trakt_id: %s Error: %s' % (trakt_id, e))
         if config['position'] == 'next' and data.get('next_episode'):
             # If the next episode is already in the trakt database, we'll get it here
             eps = data['next_episode']['season']
             epn = data['next_episode']['number']
         else:
             # If we need last ep, or next_episode was not provided, search for last ep
             for seas in reversed(data['seasons']):
                 # Find the first season with collected/watched episodes
                 if seas['completed'] > 0:
                     eps = seas['number']
                     # Pick the highest collected/watched episode
                     epn = max(item['number'] for item in seas['episodes'] if item['completed'])
                     # If we are in next episode mode, we have to increment this number
                     if config['position'] == 'next':
                         if seas['completed'] >= seas['aired']:
                             # TODO: next_episode doesn't count unaired episodes right now, this will skip to next
                             # season too early when there are episodes left to air this season.
                             eps += 1
                             epn = 1
                         else:
                             epn += 1
                     break
             else:
                 if config['position'] == 'next':
                     eps = epn = 1
                 else:
                     # There were no watched/collected episodes, nothing to emit in 'last' mode
                     continue
         if eps and epn:
             if config.get('strip_dates'):
                 # remove year from end of series_name if present
                 fields['series_name'] = re.sub(r'\s+\(\d{4}\)$', '', fields['series_name'])
             entry = self.make_entry(fields, eps, epn)
             entries.append(entry)
     return entries
예제 #6
0
 def on_task_input(self, task, config):
     if config.get('account') and not config.get('username'):
         config['username'] = '******'
     session = get_session(account=config.get('account'))
     listed_series = {}
     if config.get('list'):
         args = ('users', config['username'])
         if config['list'] in ['collection', 'watchlist', 'watched']:
             args += (config['list'], 'shows')
         else:
             args += ('lists', make_list_slug(config['list']), 'items')
         try:
             data = session.get(get_api_url(args)).json()
         except RequestException as e:
             raise plugin.PluginError('Unable to get trakt list `%s`: %s' %
                                      (config['list'], e))
         if not data:
             log.warning('The list "%s" is empty.' % config['list'])
             return
         for item in data:
             if item.get('show'):
                 if not item['show']['title']:
                     # Seems we can get entries with a blank show title sometimes
                     log.warning(
                         'Found trakt list show with no series name.')
                     continue
                 trakt_id = item['show']['ids']['trakt']
                 listed_series[trakt_id] = {
                     'series_name':
                     '%s (%s)' %
                     (item['show']['title'], item['show']['year']),
                     'trakt_id':
                     trakt_id,
                     'tvdb_id':
                     item['show']['ids']['tvdb'],
                     'trakt_list':
                     config.get('list')
                 }
     context = config['context']
     if context == 'collected':
         context = 'collection'
     entries = []
     for trakt_id, fields in listed_series.items():
         url = get_api_url('shows', trakt_id, 'progress', context)
         try:
             data = session.get(url).json()
         except RequestException as e:
             raise plugin.PluginError('TODO: error message')
         if config['position'] == 'next' and data.get('next_episode'):
             # If the next episode is already in the trakt database, we'll get it here
             eps = data['next_episode']['season']
             epn = data['next_episode']['number']
         else:
             # If we need last ep, or next_episode was not provided, search for last ep
             for seas in reversed(data['seasons']):
                 # Find the first season with collected/watched episodes
                 if seas['completed'] > 0:
                     eps = seas['number']
                     # Pick the highest collected/watched episode
                     epn = max(item['number'] for item in seas['episodes']
                               if item['completed'])
                     # If we are in next episode mode, we have to increment this number
                     if config['position'] == 'next':
                         if seas['completed'] >= seas['aired']:
                             # TODO: next_episode doesn't count unaired episodes right now, this will skip to next
                             # season too early when there are episodes left to air this season.
                             eps += 1
                             epn = 1
                         else:
                             epn += 1
                     break
             else:
                 if config['position'] == 'next':
                     eps = epn = 1
                 else:
                     # There were no watched/collected episodes, nothing to emit in 'last' mode
                     continue
         if eps and epn:
             if config.get('strip_dates'):
                 # remove year from end of series_name if present
                 fields['series_name'] = re.sub(r'\s+\(\d{4}\)$', '',
                                                fields['series_name'])
             entry = self.make_entry(fields, eps, epn)
             entries.append(entry)
     return entries
예제 #7
0
    def on_task_output(self, task, config):
        """Submits accepted movies or episodes to trakt api."""
        if config.get('account') and not config.get('username'):
            config['username'] = '******'
        found = {'shows': [], 'movies': []}
        for entry in task.accepted:
            if 'series_name' in entry:
                show = {
                    'title': entry['series_name'],
                    'ids': get_entry_ids(entry)
                }
                if 'series_season' in entry:
                    season = {'number': entry['series_season']}
                    if 'series_episode' in entry:
                        season['episodes'] = [{
                            'number': entry['series_episode']
                        }]
                    show['seasons'] = [season]
                found['shows'].append(show)
            elif any(field in entry
                     for field in ['imdb_id', 'tmdb_id', 'movie_name']):
                movie = {'ids': get_entry_ids(entry)}
                if not movie['ids']:
                    movie['title'] = entry.get('movie_name') or entry.get(
                        'imdb_name')
                    movie['year'] = entry.get('movie_year') or entry.get(
                        'imdb_year')
                found['movies'].append(movie)

        if not (found['shows'] or found['movies']):
            self.log.debug('Nothing to submit to trakt.')
            return

        if config['list'] in ['collection', 'watchlist', 'watched']:
            args = ('sync', 'history'
                    if config['list'] == 'watched' else config['list'])
        else:
            args = ('users', config['username'], 'lists',
                    make_list_slug(config['list']), 'items')
        if self.remove:
            args += ('remove', )
        url = get_api_url(args)

        if task.manager.options.test:
            self.log.info('Not submitting to trakt.tv because of test mode.')
            return
        session = get_session(account=config.get('account'))
        self.log.debug('Submitting data to trakt.tv (%s): %s' % (url, found))
        try:
            result = session.post(url,
                                  data=json.dumps(found),
                                  raise_status=False)
        except RequestException as e:
            self.log.error('Error submitting data to trakt.tv: %s' % e)
            return
        if 200 <= result.status_code < 300:
            action = 'added'
            if self.remove:
                action = 'deleted'
            res = result.json()
            movies = res[action].get('movies', 0)
            eps = res[action].get('episodes', 0)
            self.log.info(
                'Successfully %s to/from list %s: %s movie(s), %s episode(s).'
                % (action, config['list'], movies, eps))
            for k, r in res['not_found'].iteritems():
                if r:
                    self.log.debug('not found %s: %s' % (k, r))
            # TODO: Improve messages about existing and unknown results
        elif result.status_code == 404:
            self.log.error('List does not appear to exist on trakt: %s' %
                           config['list'])
        elif result.status_code == 401:
            self.log.error(
                'Authentication error: have you authorized Flexget on Trakt.tv?'
            )
            self.log.debug('trakt response: ' + result.text)
        else:
            self.log.error('Unknown error submitting data to trakt.tv: %s' %
                           result.text)
예제 #8
0
 def on_task_input(self, task, config):
     if config.get("account") and not config.get("username"):
         config["username"] = "******"
     session = get_session(account=config.get("account"))
     listed_series = {}
     if config.get("list"):
         args = ("users", config["username"])
         if config["list"] in ["collection", "watchlist", "watched"]:
             args += (config["list"], "shows")
         else:
             args += ("lists", make_list_slug(config["list"]), "items")
         try:
             data = session.get(get_api_url(args)).json()
         except RequestException as e:
             raise plugin.PluginError("Unable to get trakt list `%s`: %s" % (config["list"], e))
         if not data:
             log.warning('The list "%s" is empty.' % config["list"])
             return
         for item in data:
             if item.get("show"):
                 if not item["show"]["title"]:
                     # Seems we can get entries with a blank show title sometimes
                     log.warning("Found trakt list show with no series name.")
                     continue
                 trakt_id = item["show"]["ids"]["trakt"]
                 listed_series[trakt_id] = {
                     "series_name": "%s (%s)" % (item["show"]["title"], item["show"]["year"]),
                     "trakt_id": trakt_id,
                     "tvdb_id": item["show"]["ids"]["tvdb"],
                     "trakt_list": config.get("list"),
                 }
     context = config["context"]
     if context == "collected":
         context = "collection"
     entries = []
     for trakt_id, fields in listed_series.iteritems():
         url = get_api_url("shows", trakt_id, "progress", context)
         try:
             data = session.get(url).json()
         except RequestException as e:
             raise plugin.PluginError("TODO: error message")
         if config["position"] == "next" and data.get("next_episode"):
             # If the next episode is already in the trakt database, we'll get it here
             eps = data["next_episode"]["season"]
             epn = data["next_episode"]["number"]
         else:
             # If we need last ep, or next_episode was not provided, search for last ep
             for seas in reversed(data["seasons"]):
                 # Find the first season with collected/watched episodes
                 if seas["completed"] > 0:
                     eps = seas["number"]
                     # Pick the highest collected/watched episode
                     epn = max(item["number"] for item in seas["episodes"] if item["completed"])
                     # If we are in next episode mode, we have to increment this number
                     if config["position"] == "next":
                         if seas["completed"] >= seas["aired"]:
                             # TODO: next_episode doesn't count unaired episodes right now, this will skip to next
                             # season too early when there are episodes left to air this season.
                             eps += 1
                             epn = 1
                         else:
                             epn += 1
                     break
             else:
                 if config["position"] == "next":
                     eps = epn = 1
                 else:
                     # There were no watched/collected episodes, nothing to emit in 'last' mode
                     continue
         if eps and epn:
             entry = self.make_entry(fields, eps, epn)
             entries.append(entry)
     return entries