def to_dict(self): """Dump progress to a dictionary. :return: Progress dictionary :rtype: :class:`~python:dict` """ result = super(Progress, self).to_dict() label = LABELS['last_progress_change'][self.progress_type] result[label] = to_iso8601_datetime(self.last_progress_change) if self.progress_type == 'watched': result['reset_at'] = self.reset_at result['seasons'] = [ season.to_dict() for season in self.seasons.values() ] if self.hidden_seasons: result['hidden_seasons'] = [ popitems(season.to_dict(), ['number', 'ids']) for season in self.hidden_seasons.values() ] if self.next_episode: result['next_episode'] = popitems(self.next_episode.to_dict(), ['season', 'number', 'title', 'ids']) result['next_episode']['season'] = self.next_episode.keys[0][0] if self.last_episode: result['last_episode'] = popitems(self.last_episode.to_dict(), ['season', 'number', 'title', 'ids']) result['last_episode']['season'] = self.last_episode.keys[0][0] return result
def get(self, media=None, store=None, params=None, query=None, flat=False, **kwargs): if not params: params = [] params.insert(0, media) # Request resource response = self.http.get( params=params, query=query, **popitems(kwargs, ['authenticated', 'validate_token'])) # Parse response items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items if type(items) is not list and not isinstance(items, PaginationIterator): return None # Map items return SyncMapper.process(self.client, store, items, media=media, flat=flat, **self.flags)
def remove(self, items, **kwargs): response = self.http.post( 'remove', data=items, **popitems(kwargs, ['authenticated', 'validate_token'])) return self.get_data(response, **kwargs)
def get(self, media=None, store=None, params=None, query=None, flat=False, **kwargs): if not params: params = [] params.insert(0, media) # Request resource response = self.http.get( params=params, query=query, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) # Parse response items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items if type(items) is not list and not isinstance(items, PaginationIterator): return None # Map items return SyncMapper.process( self.client, store, items, media=media, flat=flat, **self.flags )
def likes(self, type=None, **kwargs): if type and type not in ['comments', 'lists']: raise ValueError('Unknown type specified: %r' % type) if kwargs.get('parse') is False: raise ValueError('Parse can\'t be disabled on this method') # Send request response = self.http.get( 'likes', params=[type], **popitems(kwargs, ['authenticated', 'validate_token'])) # Parse response items = self.get_data(response, **kwargs) if not items: return # Map items to comment/list objects for item in items: item_type = item.get('type') if item_type == 'comment': yield CommentMapper.comment(self.client, item) elif item_type == 'list': yield ListMapper.custom_list(self.client, item) else: log.warn('Unknown item returned, type: %r', item_type)
def delete(self, username, id, **kwargs): # Send request response = self.http.delete( '/users/%s/lists/%s' % (clean_username(username), id), **popitems(kwargs, ['authenticated', 'validate_token'])) return 200 <= response.status_code < 300
def add(self, username, id, items, **kwargs): # Send request response = self.http.post( '/users/%s/lists/%s/items' % (clean_username(username), id), data=items, **popitems(kwargs, ['authenticated', 'validate_token'])) # Parse response return self.get_data(response, **kwargs)
def get(self, id, **kwargs): response = self.http.get(str(id), query=dict(**popitems(kwargs, ['extended', 'limit']))) item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item return SummaryMapper.show(self.client, item)
def get(self, **kwargs): response = self.http.get( **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) return self.get_data(response, **kwargs)
def trending(self, **kwargs): response = self.http.get('trending', query=dict(**popitems(kwargs, ['extended', 'limit']))) items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items return SummaryMapper.shows(self.client, items)
def trending(self, **kwargs): response = self.http.get( 'trending', query=dict(**popitems(kwargs, ['extended', 'limit']))) items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items return SummaryMapper.shows(self.client, items)
def get(self, id, **kwargs): response = self.http.get( str(id), query=dict(**popitems(kwargs, ['extended', 'limit']))) item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item return SummaryMapper.show(self.client, item)
def add(self, items, **kwargs): response = self.http.post( data=items, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) return self.get_data(response, **kwargs)
def delete(self, playbackid, **kwargs): response = self.http.delete( path=str(playbackid), **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) return 200 <= response.status_code < 300
def delete(self, username, id, **kwargs): # Send request response = self.http.delete( '/users/%s/lists/%s' % (clean_username(username), id), **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) return 200 <= response.status_code < 300
def last_activities(self, **kwargs): return self.get_data( self.http.get( 'last_activities', **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ), **kwargs )
def get(self, start_date: date, days: int, **kwargs): params = ['{:%Y-%m-%d}'.format(start_date), days] response = self.http.get( params=params, **popitems(kwargs, ['authenticated', 'validate_token'])) items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items return SummaryMapper.shows(self.client, items)
def add(self, username, id, items, **kwargs): # Send request response = self.http.post( '/users/%s/lists/%s/items' % (clean_username(username), id), data=items, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) # Parse response return self.get_data(response, **kwargs)
def to_dict(self): """Dump progress to a dictionary. :return: Progress dictionary :rtype: :class:`~python:dict` """ result = super(Progress, self).to_dict() label = LABELS['last_progress_change'][self.progress_type] result[label] = to_iso8601_datetime(self.last_progress_change) if self.progress_type == 'watched': result['reset_at'] = self.reset_at result['seasons'] = [ season.to_dict() for season in self.seasons.values() ] if self.hidden_seasons: result['hidden_seasons'] = [ popitems(season.to_dict(), ['number', 'ids']) for season in self.hidden_seasons.values() ] if self.next_episode: result['next_episode'] = popitems( self.next_episode.to_dict(), ['season', 'number', 'title', 'ids']) result['next_episode']['season'] = self.next_episode.keys[0][0] if self.last_episode: result['last_episode'] = popitems( self.last_episode.to_dict(), ['season', 'number', 'title', 'ids']) result['last_episode']['season'] = self.last_episode.keys[0][0] return result
def update(self, username, id, name=None, description=None, privacy=None, display_numbers=None, allow_comments=None, return_type='object', **kwargs): data = { 'name': name, 'description': description, 'privacy': privacy, 'allow_comments': allow_comments, 'display_numbers': display_numbers } # Remove attributes with `None` values for key in list(data.keys()): if data[key] is not None: continue del data[key] # Send request response = self.http.put( '/users/%s/lists/%s' % (clean_username(username), id), data=data, **popitems(kwargs, ['authenticated', 'validate_token'])) # Parse response item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item if not item: return None if return_type == 'data': return item if return_type == 'object': # Map item to list object return ListMapper.custom_list(self.client, item, username=username) raise ValueError('Unsupported value for "return_type": %r', return_type)
def update(self, username, id, name=None, description=None, privacy=None, display_numbers=None, allow_comments=None, return_type='object', **kwargs): data = { 'name': name, 'description': description, 'privacy': privacy, 'allow_comments': allow_comments, 'display_numbers': display_numbers } # Remove attributes with `None` values for key in list(data.keys()): if data[key] is not None: continue del data[key] # Send request response = self.http.put( '/users/%s/lists/%s' % (clean_username(username), id), data=data, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) # Parse response item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item if not item: return None if return_type == 'data': return item if return_type == 'object': # Map item to list object return ListMapper.custom_list( self.client, item, username=username ) raise ValueError("Unsupported value for \"return_type\": %r", return_type)
def progress(self, progress_type, id, hidden=False, specials=False, count_specials=True, **kwargs): query = { 'hidden': hidden, 'specials': specials, 'count_specials': count_specials } response = self.http.get(str(id), [ 'progress', progress_type ], query=query, **popitems(kwargs, [ 'authenticated', 'validate_token' ])) item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item return ProgressMapper.progress(self.client, progress_type, item)
def likes(self, type=None, **kwargs): if type and type not in ['comments', 'lists']: raise ValueError('Unknown type specified: %r' % type) if kwargs.get('parse') is False: raise ValueError('Parse can\'t be disabled on this method') # Send request response = self.http.get( 'likes', params=[type], **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) # Parse response items = self.get_data(response, **kwargs) if not items: return # Map items to comment/list objects for item in items: item_type = item.get('type') if item_type == 'comment': yield CommentMapper.comment( self.client, item ) elif item_type == 'list': yield ListMapper.custom_list( self.client, item ) else: log.warn('Unknown item returned, type: %r', item_type)
def progress(self, progress_type, id, hidden=False, specials=False, count_specials=True, **kwargs): query = { 'hidden': hidden, 'specials': specials, 'count_specials': count_specials } response = self.http.get( str(id), ['progress', progress_type], query=query, **popitems(kwargs, ['authenticated', 'validate_token'])) item = self.get_data(response, **kwargs) if isinstance(item, requests.Response): return item return ProgressMapper.progress(self.client, progress_type, item)
def get(self, **kwargs): response = self.http.get( **popitems(kwargs, ['authenticated', 'validate_token'])) return self.get_data(response, **kwargs)
def get(self, source, media, collection=None, start_date=None, days=None, query=None, years=None, genres=None, languages=None, countries=None, runtimes=None, ratings=None, certifications=None, networks=None, status=None, **kwargs): """Retrieve calendar items. The `all` calendar displays info for all shows airing during the specified period. The `my` calendar displays episodes for all shows that have been watched, collected, or watchlisted. :param source: Calendar source (`all` or `my`) :type source: str :param media: Media type (`dvd`, `movies` or `shows`) :type media: str :param collection: Collection type (`new`, `premieres`) :type collection: str or None :param start_date: Start date (defaults to today) :type start_date: datetime or None :param days: Number of days to display (defaults to `7`) :type days: int or None :param query: Search title or description. :type query: str or None :param years: Year or range of years (e.g. `2014`, or `2014-2016`) :type years: int or str or tuple or None :param genres: Genre slugs (e.g. `action`) :type genres: str or list of str or None :param languages: Language codes (e.g. `en`) :type languages: str or list of str or None :param countries: Country codes (e.g. `us`) :type countries: str or list of str or None :param runtimes: Runtime range in minutes (e.g. `30-90`) :type runtimes: str or tuple or None :param ratings: Rating range between `0` and `100` (e.g. `75-100`) :type ratings: str or tuple or None :param certifications: US Content Certification (e.g. `pg-13`, `tv-pg`) :type certifications: str or list of str or None :param networks: (TV) Network name (e.g. `HBO`) :type networks: str or list of str or None :param status: (TV) Show status (e.g. `returning series`, `in production`, ended`) :type status: str or list of str or None :return: Items :rtype: list of trakt.objects.video.Video """ if source not in ['all', 'my']: raise ValueError('Unknown collection type: %s' % (source, )) if media not in ['dvd', 'movies', 'shows']: raise ValueError('Unknown media type: %s' % (media, )) # Default `start_date` to today when only `days` is provided if start_date is None and days: start_date = datetime.utcnow() # Request calendar collection response = self.http.get( '/calendars/%s/%s%s' % (source, media, ('/' + collection) if collection else ''), params=[ start_date.strftime('%Y-%m-%d') if start_date else None, days ], query={ 'query': query, 'years': years, 'genres': genres, 'languages': languages, 'countries': countries, 'runtimes': runtimes, 'ratings': ratings, 'certifications': certifications, # TV 'networks': networks, 'status': status }, **popitems(kwargs, ['authenticated', 'validate_token'])) # Parse response items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items # Map items if media == 'shows': return SummaryMapper.episodes(self.client, items, parse_show=True) return SummaryMapper.movies(self.client, items)
def last_activities(self, **kwargs): return self.get_data( self.http.get( 'last_activities', **popitems(kwargs, ['authenticated', 'validate_token'])), **kwargs)
def get(self, source, media, collection=None, start_date=None, days=None, query=None, years=None, genres=None, languages=None, countries=None, runtimes=None, ratings=None, certifications=None, networks=None, status=None, **kwargs): """Retrieve calendar items. The `all` calendar displays info for all shows airing during the specified period. The `my` calendar displays episodes for all shows that have been watched, collected, or watchlisted. :param source: Calendar source (`all` or `my`) :type source: str :param media: Media type (`dvd`, `movies` or `shows`) :type media: str :param collection: Collection type (`new`, `premieres`) :type collection: str or None :param start_date: Start date (defaults to today) :type start_date: datetime or None :param days: Number of days to display (defaults to `7`) :type days: int or None :param query: Search title or description. :type query: str or None :param years: Year or range of years (e.g. `2014`, or `2014-2016`) :type years: int or str or tuple or None :param genres: Genre slugs (e.g. `action`) :type genres: str or list of str or None :param languages: Language codes (e.g. `en`) :type languages: str or list of str or None :param countries: Country codes (e.g. `us`) :type countries: str or list of str or None :param runtimes: Runtime range in minutes (e.g. `30-90`) :type runtimes: str or tuple or None :param ratings: Rating range between `0` and `100` (e.g. `75-100`) :type ratings: str or tuple or None :param certifications: US Content Certification (e.g. `pg-13`, `tv-pg`) :type certifications: str or list of str or None :param networks: (TV) Network name (e.g. `HBO`) :type networks: str or list of str or None :param status: (TV) Show status (e.g. `returning series`, `in production`, ended`) :type status: str or list of str or None :return: Items :rtype: list of trakt.objects.video.Video """ if source not in ['all', 'my']: raise ValueError('Unknown collection type: %s' % (source,)) if media not in ['dvd', 'movies', 'shows']: raise ValueError('Unknown media type: %s' % (media,)) # Default `start_date` to today when only `days` is provided if start_date is None and days: start_date = datetime.utcnow() # Request calendar collection response = self.http.get( '/calendars/%s/%s%s' % ( source, media, ('/' + collection) if collection else '' ), params=[ start_date.strftime('%Y-%m-%d') if start_date else None, days ], query={ 'query': query, 'years': years, 'genres': genres, 'languages': languages, 'countries': countries, 'runtimes': runtimes, 'ratings': ratings, 'certifications': certifications, # TV 'networks': networks, 'status': status }, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) # Parse response items = self.get_data(response, **kwargs) if isinstance(items, requests.Response): return items # Map items if media == 'shows': return SummaryMapper.episodes( self.client, items, parse_show=True ) return SummaryMapper.movies(self.client, items)
def action(self, action, movie=None, show=None, episode=None, progress=0.0, **kwargs): """Perform scrobble action. :param action: Action to perform (either :code:`start`, :code:`pause` or :code:`stop`) :type action: :class:`~python:str` :param movie: Movie definition (or `None`) **Example:** .. code-block:: python { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'tmdb': 118340 } } :type movie: :class:`~python:dict` :param show: Show definition (or `None`) **Example:** .. code-block:: python { 'title': 'Breaking Bad', 'year': 2008, 'ids': { 'tvdb': 81189 } } :type show: :class:`~python:dict` :param episode: Episode definition (or `None`) **Example:** .. code-block:: python { "season": 3, "number": 11 } :type episode: :class:`~python:dict` :param progress: Current movie/episode progress percentage :type progress: :class:`~python:float` :param kwargs: Extra request options :type kwargs: :class:`~python:dict` :return: Response (or `None`) **Example:** .. code-block:: python { 'action': 'start', 'progress': 1.25, 'sharing': { 'facebook': true, 'twitter': true, 'tumblr': false }, 'movie': { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'trakt': 28, 'slug': 'guardians-of-the-galaxy-2014', 'imdb': 'tt2015381', 'tmdb': 118340 } } } :rtype: :class:`~python:dict` """ if movie and (show or episode): raise ValueError('Only one media type should be provided') if not movie and not episode: raise ValueError('Missing media item') data = { 'progress': progress, 'app_version': kwargs.pop('app_version', self.client.version), 'app_date': kwargs.pop('app_date', None) } if movie: # TODO validate data['movie'] = movie elif episode: if show: data['show'] = show # TODO validate data['episode'] = episode response = self.http.post( action, data=data, **popitems(kwargs, [ 'authenticated', 'validate_token' ]) ) return self.get_data(response, **kwargs)
def delete(self, playbackid, **kwargs): response = self.http.delete( path=str(playbackid), **popitems(kwargs, ['authenticated', 'validate_token'])) return 200 <= response.status_code < 300
def action(self, action, movie=None, show=None, episode=None, progress=0.0, **kwargs): """Perform scrobble action. :param action: Action to perform (either :code:`start`, :code:`pause` or :code:`stop`) :type action: :class:`~python:str` :param movie: Movie definition (or `None`) **Example:** .. code-block:: python { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'tmdb': 118340 } } :type movie: :class:`~python:dict` :param show: Show definition (or `None`) **Example:** .. code-block:: python { 'title': 'Breaking Bad', 'year': 2008, 'ids': { 'tvdb': 81189 } } :type show: :class:`~python:dict` :param episode: Episode definition (or `None`) **Example:** .. code-block:: python { "season": 3, "number": 11 } :type episode: :class:`~python:dict` :param progress: Current movie/episode progress percentage :type progress: :class:`~python:float` :param kwargs: Extra request options :type kwargs: :class:`~python:dict` :return: Response (or `None`) **Example:** .. code-block:: python { 'action': 'start', 'progress': 1.25, 'sharing': { 'facebook': true, 'twitter': true, 'tumblr': false }, 'movie': { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'trakt': 28, 'slug': 'guardians-of-the-galaxy-2014', 'imdb': 'tt2015381', 'tmdb': 118340 } } } :rtype: :class:`~python:dict` """ if movie and (show or episode): raise ValueError('Only one media type should be provided') if not movie and not episode: raise ValueError('Missing media item') data = { 'progress': progress, 'app_version': kwargs.pop('app_version', self.client.version), 'app_date': kwargs.pop('app_date', None) } if movie: # TODO validate data['movie'] = movie elif episode: if show: data['show'] = show # TODO validate data['episode'] = episode response = self.http.post( action, data=data, **popitems(kwargs, ['authenticated', 'validate_token'])) return self.get_data(response, **kwargs)