Example #1
0
    def get_list_endpoint(self, remove=False, submit=False):
        if not submit and self.config['list'] == 'collection' and self.config[
                'type'] == 'episodes':
            # API restriction as they don't have an endpoint for collected episodes yet
            if self.config['list'] == 'collection':
                raise plugin.PluginError(
                    '`type` cannot be `episodes` for collection list.')
            if self.config.get('account'):
                return ('sync', 'history', 'episodes')
            else:
                raise plugin.PluginError(
                    'A trakt `account` needs to be configured to get the episode history.'
                )

        if self.config['list'] in [
                'collection', 'watchlist', 'watched', 'ratings'
        ]:
            if self.config.get('account'):
                endpoint = ('sync', 'history' if self.config['list']
                            == 'watched' else self.config['list'])
                if not submit:
                    endpoint += (self.config['type'], )
            else:
                endpoint = ('users', self.config['username'],
                            self.config['list'], self.config['type'])
        else:
            endpoint = ('users', self.config['username'], 'lists',
                        plugin_api_trakt.make_list_slug(self.config['list']),
                        'items')

        if remove:
            endpoint += ('remove', )
        return endpoint
Example #2
0
    def get_list_endpoint(self, remove=False, submit=False):
        # Api restriction, but we could easily extract season and episode info from the 'shows' type
        if not submit and self.config['list'] in [
                'collection', 'watched'
        ] and self.config['type'] == 'episodes':
            raise plugin.PluginError(
                '`type` cannot be `%s` for %s list.' %
                (self.config['type'], self.config['list']))

        if self.config['list'] in [
                'collection', 'watchlist', 'watched', 'ratings'
        ]:
            if self.config.get('account'):
                if self.config['list'] == 'watched':
                    endpoint = ('sync', 'history')
                else:
                    endpoint = ('sync', self.config['list'])
                    if not submit:
                        endpoint += (self.config['type'], )
            else:
                endpoint = ('users', self.config['username'],
                            self.config['list'], self.config['type'])
        else:
            endpoint = ('users', self.config['username'], 'lists',
                        make_list_slug(self.config['list']), 'items')

        if remove:
            endpoint += ('remove', )
        return endpoint
Example #3
0
 def get_list_endpoint(self):
     endpoint = ['users', self.config['username']]
     if isinstance(self.config['list'], dict):
         if self.config['type'] == 'auto':
             raise plugin.PluginError('`type` cannot be `auto` for ratings lists.')
         endpoint += ('ratings', self.config['type'], self.config['list']['rating'])
     elif self.config['list'] in ['collection', 'watchlist', 'watched', 'ratings']:
         if self.config['type'] == 'auto':
             raise plugin.PluginError('`type` cannot be `auto` for %s list.' % self.config['list'])
         endpoint += (self.config['list'], self.config['type'])
     else:
         endpoint += ('lists', make_list_slug(self.config['list']), 'items')
     return endpoint
Example #4
0
    def get_list_endpoint(self, remove=False):
        # Api restriction, but we could easily extract season and episode info from the 'shows' type
        if self.config['list'] in ['collection', 'watched'] and self.config['type'] == 'episodes':
            raise plugin.PluginError('`type` cannot be `%s` for %s list.' % (self.config['type'], self.config['list']))

        if self.config['list'] in ['collection', 'watchlist', 'watched', 'ratings']:
            if self.config.get('account'):
                endpoint = ('sync', 'history' if self.config['list'] == 'watched' else self.config['list'])
            else:
                endpoint = ('users', self.config['username'], self.config['list'], self.config['type'])
        else:
            endpoint = ('users', self.config['username'], 'lists', make_list_slug(self.config['list']), 'items')

        if remove:
            endpoint += ('remove', )
        return endpoint
Example #5
0
    def get_list_endpoint(self, remove=False, submit=False):
        if not submit and self.config['list'] == 'collection' and self.config['type'] == 'episodes':
            # API restriction as they don't have an endpoint for collected episodes yet
            if self.config['list'] == 'collection':
                raise plugin.PluginError('`type` cannot be `episodes` for collection list.')
            if self.config.get('account'):
                return ('sync', 'history', 'episodes')
            else:
                raise plugin.PluginError('A trakt `account` needs to be configured to get the episode history.')

        if self.config['list'] in ['collection', 'watchlist', 'watched', 'ratings']:
            if self.config.get('account'):
                endpoint = ('sync', 'history' if self.config['list'] == 'watched' else self.config['list'])
                if not submit:
                    endpoint += (self.config['type'], )
            else:
                endpoint = ('users', self.config['username'], self.config['list'], self.config['type'])
        else:
            endpoint = ('users', self.config['username'], 'lists', make_list_slug(self.config['list']), 'items')

        if remove:
            endpoint += ('remove', )
        return endpoint
Example #6
0
    def submit(self, entries, remove=False):
        """Submits movies or episodes to trakt api."""
        found = {}
        for entry in entries:
            if self.config['type'] in ['auto', 'shows', 'seasons', 'episodes'
                                       ] and entry.get('series_name'):
                show_name, show_year = split_title_year(entry['series_name'])
                show = {'title': show_name, 'ids': get_entry_ids(entry)}
                if show_year:
                    show['year'] = show_year
                if self.config['type'] in [
                        'auto', 'seasons', 'episodes'
                ] and entry.get('series_season') is not None:
                    season = {'number': entry['series_season']}
                    if self.config['type'] in [
                            'auto', 'episodes'
                    ] and entry.get('series_episode') is not None:
                        season['episodes'] = [{
                            'number': entry['series_episode']
                        }]
                    show['seasons'] = [season]
                if self.config['type'] in ['seasons', 'episodes'
                                           ] and 'seasons' not in show:
                    log.debug('Not submitting `%s`, no season found.' %
                              entry['title'])
                    continue
                if self.config['type'] == 'episodes' and 'episodes' not in show[
                        'seasons'][0]:
                    log.debug('Not submitting `%s`, no episode number found.' %
                              entry['title'])
                    continue
                found.setdefault('shows', []).append(show)
            elif self.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:
                        log.debug(
                            'Not submitting `%s`, no movie name or id found.' %
                            entry['title'])
                        continue
                found.setdefault('movies', []).append(movie)

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

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

        log.debug('Submitting data to trakt.tv (%s): %s' % (url, found))
        try:
            result = self.session.post(url,
                                       data=json.dumps(found),
                                       raise_status=False)
        except RequestException as e:
            log.error('Error submitting data to trakt.tv: %s' % e)
            return
        if 200 <= result.status_code < 300:
            action = 'deleted' if remove else 'added'
            res = result.json()
            # Default to 0 for all categories, even if trakt response didn't include them
            for cat in ('movies', 'shows', 'episodes', 'seasons'):
                res[action].setdefault(cat, 0)
            log.info(
                'Successfully {0} to/from list {1}: {movies} movie(s), {shows} show(s), {episodes} episode(s), '
                '{seasons} season(s).'.format(action, self.config['list'],
                                              **res[action]))
            for k, r in res['not_found'].items():
                if r:
                    log.debug('not found %s: %s' % (k, r))
            # TODO: Improve messages about existing and unknown results
            # Mark the results expired if we added or removed anything
            if sum(res[action].values()) > 0:
                self.invalidate_cache()
        elif result.status_code == 404:
            log.error('List does not appear to exist on trakt: %s' %
                      self.config['list'])
        elif result.status_code == 401:
            log.error(
                'Authentication error: have you authorized Flexget on Trakt.tv?'
            )
            log.debug('trakt response: ' + result.text)
        else:
            log.error('Unknown error submitting data to trakt.tv: %s' %
                      result.text)
 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,
                     'trakt_series_name':
                     item['show']['title'],
                     'trakt_series_year':
                     item['show']['year'],
                     'trakt_list':
                     config.get('list')
                 }
                 if item['show']['ids'].get('tvdb'):
                     listed_series[trakt_id]['tvdb_id'] = item['show'][
                         'ids']['tvdb']
                 if item['show']['ids'].get('tvrage'):
                     listed_series[trakt_id]['tvrage_id'] = item['show'][
                         'ids']['tvrage']
                 if item['show']['ids'].get('imdb'):
                     listed_series[trakt_id]['imdb_id'] = item['show'][
                         'ids']['imdb']
                 if item['show']['ids'].get('tmdb'):
                     listed_series[trakt_id]['tmdb_id'] = item['show'][
                         'ids']['tmdb']
                 if item['show']['ids'].get('slug'):
                     listed_series[trakt_id]['trakt_slug'] = item['show'][
                         'ids']['slug']
     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 occurred 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
Example #8
0
    def submit(self, entries, remove=False):
        """Submits movies or episodes to trakt api."""
        found = {}
        for entry in entries:
            if self.config['type'] in ['auto', 'shows', 'seasons', 'episodes'] and entry.get('series_name'):
                show_name, show_year = split_title_year(entry['series_name'])
                show = {'title': show_name, 'ids': get_entry_ids(entry)}
                if show_year:
                    show['year'] = show_year
                if self.config['type'] in ['auto', 'seasons', 'episodes'] and entry.get('series_season') is not None:
                    season = {'number': entry['series_season']}
                    if self.config['type'] in ['auto', 'episodes'] and entry.get('series_episode') is not None:
                        season['episodes'] = [{'number': entry['series_episode']}]
                    show['seasons'] = [season]
                if self.config['type'] in ['seasons', 'episodes'] and 'seasons' not in show:
                    log.debug('Not submitting `%s`, no season found.' % entry['title'])
                    continue
                if self.config['type'] == 'episodes' and 'episodes' not in show['seasons'][0]:
                    log.debug('Not submitting `%s`, no episode number found.' % entry['title'])
                    continue
                found.setdefault('shows', []).append(show)
            elif self.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:
                        log.debug('Not submitting `%s`, no movie name or id found.' % entry['title'])
                        continue
                found.setdefault('movies', []).append(movie)

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

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

        log.debug('Submitting data to trakt.tv (%s): %s' % (url, found))
        try:
            result = self.session.post(url, data=json.dumps(found), raise_status=False)
        except RequestException as e:
            log.error('Error submitting data to trakt.tv: %s' % e)
            return
        if 200 <= result.status_code < 300:
            action = 'deleted' if remove else 'added'
            res = result.json()
            # Default to 0 for all categories, even if trakt response didn't include them
            for cat in ('movies', 'shows', 'episodes', 'seasons'):
                res[action].setdefault(cat, 0)
            log.info('Successfully {0} to/from list {1}: {movies} movie(s), {shows} show(s), {episodes} episode(s), '
                     '{seasons} season(s).'.format(action, self.config['list'], **res[action]))
            for k, r in res['not_found'].items():
                if r:
                    log.debug('not found %s: %s' % (k, r))
            # TODO: Improve messages about existing and unknown results
            # Mark the results expired if we added or removed anything
            if sum(res[action].values()) > 0:
                self.invalidate_cache()
        elif result.status_code == 404:
            log.error('List does not appear to exist on trakt: %s' % self.config['list'])
        elif result.status_code == 401:
            log.error('Authentication error: have you authorized Flexget on Trakt.tv?')
            log.debug('trakt response: ' + result.text)
        else:
            log.error('Unknown error submitting data to trakt.tv: %s' % result.text)
    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 = {}
        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
                ids = item['show']['ids']
                trakt_id = ids['trakt']
                listed_series[trakt_id] = {
                    'series_name': '%s (%s)' % (item['show']['title'], item['show']['year']),
                    'trakt_id': trakt_id,
                    'trakt_series_name': item['show']['title'],
                    'trakt_series_year': item['show']['year'],
                    'trakt_list': config.get('list')
                }
                for id_name, id_value in ids.items():
                    entry_field_name = 'trakt_slug' if id_name == 'slug' else id_name  # rename slug to trakt_slug
                    listed_series[trakt_id][entry_field_name] = id_value
        context = 'collection' if config['context'] == 'collected' else config['context']
        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 occurred 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
                season_number = data['next_episode']['season']
                episode_number = data['next_episode']['number']
            else:
                # If we need last ep, or next_episode was not provided, search for last ep
                for season in reversed(data['seasons']):
                    # Find the first season with collected/watched episodes
                    if not season['completed']:
                        continue
                    season_number = season['number']
                    # Pick the highest collected/watched episode
                    episode_number = max(item['number'] for item in season['episodes'] if item['completed'])
                    # If we are in next episode mode, we have to increment this number
                    if config['position'] == 'next':
                        if season['completed'] >= season['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.
                            season_number += 1
                        episode_number = 1
                    break
                else:
                    if config['position'] != 'next':
                        # There were no watched/collected episodes, nothing to emit in 'last' mode
                        continue
                    season_number = episode_number = 1

            if season_number and episode_number:
                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, season_number, episode_number)
                entries.append(entry)
        return entries