Ejemplo n.º 1
0
    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'] = [
                dictfilter(season.to_dict(), pop=['number', 'ids'])
                for season in self.hidden_seasons.values()
            ]

        if self.next_episode:
            result['next_episode'] = dictfilter(self.next_episode.to_dict(), pop=['season', 'number', 'title', 'ids'])
            result['next_episode']['season'] = self.next_episode.keys[0][0]

        if self.last_episode:
            result['last_episode'] = dictfilter(self.last_episode.to_dict(), pop=['season', 'number', 'title', 'ids'])
            result['last_episode']['season'] = self.last_episode.keys[0][0]

        return result
Ejemplo n.º 2
0
    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,
                                 **dictfilter(
                                     kwargs,
                                     pop=['authenticated', 'validate_token']))

        item = self.get_data(response, **kwargs)

        if isinstance(item, requests.Response):
            return item

        return ProgressMapper.progress(self.client, progress_type, item)
Ejemplo n.º 3
0
    def likes(self, type=None, page=None, per_page=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', [type],
            query={
                'page': page,
                'limit': per_page
            },
            **dictfilter(kwargs,
                         get=['exceptions'],
                         pop=['authenticated', 'pagination',
                              'validate_token']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(self._map_items)

        if isinstance(items, requests.Response):
            return items

        return self._map_items(items)
Ejemplo n.º 4
0
    def delete(self, username, id, **kwargs):
        # Send request
        response = self.http.delete(
            '/users/%s/lists/%s' % (clean_username(username), id),
            **dictfilter(kwargs, pop=['authenticated', 'validate_token']))

        return 200 <= response.status_code < 300
Ejemplo n.º 5
0
    def items(self,
              username,
              id,
              media=None,
              extended=None,
              page=None,
              per_page=None,
              **kwargs):
        response = self.http.get(
            '/users/%s/lists/%s/items' % (clean_username(username), id),
            query={
                'type': media,
                'extended': extended,
                'page': page,
                'limit': per_page
            },
            **dictfilter(kwargs,
                         get=['exceptions'],
                         pop=['authenticated', 'pagination',
                              'validate_token']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: ListItemMapper.process_many(self.client, items))

        if isinstance(items, requests.Response):
            return items

        return ListItemMapper.process_many(self.client, items)
Ejemplo n.º 6
0
    def __get_list(self,
                   list_type,
                   period=None,
                   extended=None,
                   page=None,
                   per_page=None,
                   **kwargs):
        # Build parameters
        params = [period] if period else None

        # Build query
        query = {'extended': extended, 'page': page, 'limit': per_page}

        # Send request
        response = self.http.get(list_type,
                                 params=params,
                                 query=query,
                                 **dictfilter(kwargs,
                                              get=['exceptions'],
                                              pop=['pagination']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: SummaryMapper.movies(self.client, items))

        if isinstance(items, requests.Response):
            return items

        return SummaryMapper.movies(self.client, items)
Ejemplo n.º 7
0
    def add(self, items, **kwargs):
        response = self.http.post(data=items,
                                  **dictfilter(
                                      kwargs,
                                      pop=['authenticated', 'validate_token']))

        return self.get_data(response, **kwargs)
Ejemplo n.º 8
0
    def add(self, username, id, items, **kwargs):
        # Send request
        response = self.http.post(
            '/users/%s/lists/%s/items' % (clean_username(username), id),
            data=items,
            **dictfilter(kwargs, pop=['authenticated', 'validate_token']))

        # Parse response
        return self.get_data(response, **kwargs)
Ejemplo n.º 9
0
    def get(self, username, media=None, sort=None, store=None, extended=None,
            page=None, per_page=None, **kwargs):

        # Build parameters
        params = []

        if media:
            params.append(media)

        if sort:
            params.append(sort)

        # Build query
        query = {
            'extended': extended,
            'page': page,
            'limit': per_page
        }

        # Send request
        response = self.http.get(
            '/users/%s/watchlist' % (clean_username(username)),
            params=params,
            query=query,
            **dictfilter(kwargs, get=[
                'exceptions'
            ], pop=[
                'authenticated',
                'pagination',
                'validate_token'
            ])
        )

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(lambda items: SyncMapper.process(
                self.client, store, items,
                media=media,
                flat=True,
                **self.flags
            ))

        if isinstance(items, requests.Response):
            return items

        if type(items) is not list:
            return None

        # Map items
        return SyncMapper.process(
            self.client, store, items,
            media=media,
            flat=True,
            **self.flags
        )
Ejemplo n.º 10
0
    def get(self,
            username,
            media=None,
            store=None,
            extended=None,
            page=None,
            per_page=None,
            **kwargs):

        if not media or media not in ['shows', 'movies']:
            raise ValueError(
                'The "media" have to be  one of ["shows", "media"]')

        # Build parameters
        params = []

        if media:
            params.append(media)

        # Build query
        query = {'extended': extended, 'page': page, 'limit': per_page}

        # Send request
        response = self.http.get(
            '/users/%s/watched' % (clean_username(username)),
            params=params,
            query=query,
            **dictfilter(kwargs,
                         get=['exceptions'],
                         pop=['authenticated', 'pagination',
                              'validate_token']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: SyncMapper.process(self.client,
                                                 store,
                                                 items,
                                                 media=media,
                                                 flat=True,
                                                 **self.flags))

        if isinstance(items, requests.Response):
            return items

        if type(items) is not list:
            return None

        return SyncMapper.process(self.client,
                                  store,
                                  items,
                                  media=media,
                                  flat=True,
                                  **self.flags)
Ejemplo n.º 11
0
    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,
            **dictfilter(kwargs,
                         get=['exceptions'],
                         pop=['authenticated', 'pagination',
                              'validate_token']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            if not flat:
                raise ValueError(
                    'Pagination is only supported with `flat=True`')

            return items.with_mapper(
                lambda items: SyncMapper.process(self.client,
                                                 store,
                                                 items,
                                                 media=media,
                                                 flat=flat,
                                                 **self.flags))

        if isinstance(items, requests.Response):
            return items

        if type(items) is not list:
            return None

        # Map items
        return SyncMapper.process(self.client,
                                  store,
                                  items,
                                  media=media,
                                  flat=flat,
                                  **self.flags)
Ejemplo n.º 12
0
    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,
            **dictfilter(kwargs, pop=['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)
Ejemplo n.º 13
0
    def get(self, username, extended=None, **kwargs):
        response = self.http.get(
            '/users/%s/following' % (clean_username(username)),
            query={'extended': extended},
            **dictfilter(kwargs,
                         get=['exceptions'],
                         pop=['authenticated', 'validate_token']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, requests.Response):
            return items

        if type(items) is not list:
            return None

        return UserMapper.users(self.client, items)
Ejemplo n.º 14
0
    def trending(self, page=None, per_page=None, **kwargs):
        response = self.http.get('trending',
                                 query={
                                     'page': page,
                                     'limit': per_page
                                 },
                                 **dictfilter(kwargs,
                                              get=['exceptions'],
                                              pop=['pagination']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: ListMapper.public_lists(self.client, items))

        if isinstance(items, requests.Response):
            return items

        return ListMapper.public_lists(self.client, items)
Ejemplo n.º 15
0
    def lookup(self,
               id,
               service=None,
               media=None,
               extended=None,
               page=None,
               per_page=None,
               **kwargs):
        """Lookup items by their Trakt, IMDB, TMDB, TVDB, or TVRage ID.

        **Note:** If you lookup an identifier without a :code:`media` type specified it
        might return multiple items if the :code:`service` is not globally unique.

        :param id: Identifier value to lookup
        :type id: :class:`~python:str` or :class:`~python:int`

        :param service: Identifier service

            **Possible values:**
             - :code:`trakt`
             - :code:`imdb`
             - :code:`tmdb`
             - :code:`tvdb`
             - :code:`tvrage`

        :type service: :class:`~python:str`

        :param media: Desired media type (or :code:`None` to return all matching items)

            **Possible values:**
             - :code:`movie`
             - :code:`show`
             - :code:`episode`
             - :code:`person`
             - :code:`list`

        :type media: :class:`~python:str` or :class:`~python:list` of :class:`~python:str`

        :param extended: Level of information to include in response

            **Possible values:**
             - :code:`None`: Minimal (e.g. title, year, ids) **(default)**
             - :code:`full`: Complete

        :type extended: :class:`~python:str`

        :param kwargs: Extra request options
        :type kwargs: :class:`~python:dict`

        :return: Results
        :rtype: :class:`~python:list` of :class:`trakt.objects.media.Media`
        """
        # Expand tuple `id`
        if type(id) is tuple:
            if len(id) != 2:
                raise ValueError()

            id, service = id

        # Validate parameters
        if not service:
            raise ValueError(
                'Invalid value provided for the "service" parameter')

        # Build query
        query = {'extended': extended, 'page': page, 'limit': per_page}

        if isinstance(media, six.string_types):
            query['type'] = media
        elif isinstance(media, list):
            query['type'] = ','.join(media)

        # Send request
        response = self.http.get(params=[service, id],
                                 query=query,
                                 **dictfilter(kwargs,
                                              get=['exceptions'],
                                              pop=['pagination']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: SearchMapper.process_many(self.client, items))

        if isinstance(items, requests.Response):
            return items

        return SearchMapper.process_many(self.client, items)
Ejemplo n.º 16
0
    def query(self,
              query,
              media=None,
              year=None,
              fields=None,
              extended=None,
              page=None,
              per_page=None,
              **kwargs):
        """Search by titles, descriptions, translated titles, aliases, and people.

        **Note:** Results are ordered by the most relevant score.

        :param query: Search title or description
        :type query: :class:`~python:str`

        :param media: Desired media type (or :code:`None` to return all matching items)

            **Possible values:**
             - :code:`movie`
             - :code:`show`
             - :code:`episode`
             - :code:`person`
             - :code:`list`

        :type media: :class:`~python:str` or :class:`~python:list` of :class:`~python:str`

        :param year: Desired media year (or :code:`None` to return all matching items)
        :type year: :class:`~python:str` or :class:`~python:int`

        :param fields: Fields to search for :code:`query` (or :code:`None` to search all fields)
        :type fields: :class:`~python:str` or :class:`~python:list`

        :param extended: Level of information to include in response

            **Possible values:**
             - :code:`None`: Minimal (e.g. title, year, ids) **(default)**
             - :code:`full`: Complete

        :type extended: :class:`~python:str`

        :param kwargs: Extra request options
        :type kwargs: :class:`~python:dict`

        :return: Results
        :rtype: :class:`~python:list` of :class:`trakt.objects.media.Media`
        """
        # Validate parameters
        if not media:
            warnings.warn(
                "\"media\" parameter is now required on the Trakt['search'].query() method",
                DeprecationWarning,
                stacklevel=2)

        if fields and not media:
            raise ValueError(
                '"fields" can only be used when the "media" parameter is defined'
            )

        # Build query
        query = {
            'query': query,
            'year': year,
            'fields': fields,
            'extended': extended,
            'page': page,
            'limit': per_page
        }

        # Serialize media items
        if isinstance(media, list):
            media = ','.join(media)

        # Send request
        response = self.http.get(params=[media],
                                 query=query,
                                 **dictfilter(kwargs,
                                              get=['exceptions'],
                                              pop=['pagination']))

        # Parse response
        items = self.get_data(response, **kwargs)

        if isinstance(items, PaginationIterator):
            return items.with_mapper(
                lambda items: SearchMapper.process_many(self.client, items))

        if isinstance(items, requests.Response):
            return items

        return SearchMapper.process_many(self.client, items)
Ejemplo n.º 17
0
    def delete(self, playbackid, **kwargs):
        response = self.http.delete(
            path=str(playbackid),
            **dictfilter(kwargs, pop=['authenticated', 'validate_token']))

        return 200 <= response.status_code < 300
Ejemplo n.º 18
0
    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
            },
            **dictfilter(kwargs, pop=['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)
Ejemplo n.º 19
0
    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,
                                  **dictfilter(
                                      kwargs,
                                      pop=['authenticated', 'validate_token']))

        return self.get_data(response, **kwargs)
Ejemplo n.º 20
0
 def last_activities(self, **kwargs):
     return self.get_data(
         self.http.get(
             'last_activities',
             **dictfilter(kwargs, pop=['authenticated', 'validate_token'])),
         **kwargs)
Ejemplo n.º 21
0
    def get(self, **kwargs):
        response = self.http.get(
            **dictfilter(kwargs, pop=['authenticated', 'validate_token']))

        return self.get_data(response, **kwargs)