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
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
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
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
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
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
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