Beispiel #1
0
def movie_list_add(options):
    with Session() as session:
        try:
            movie_list = get_list_by_exact_name(options.list_name)
        except NoResultFound:
            console('Could not find movie list with name {}, creating'.format(options.list_name))
            movie_list = MovieListList(name=options.list_name)
        session.merge(movie_list)
        title, year = split_title_year(options.movie_title)
        console('Trying to lookup movie %s title' % title)
        entry = lookup_movie(title=title, session=session, identifiers=options.identifiers)
        if not entry:
            console('movie lookup failed for movie %s, aborting')
            return
        title = entry['movie_name']
        movie = get_movie_by_title(list_id=movie_list.id, title=title, session=session)
        if not movie:
            console("Adding movie with title {} to list {}".format(title, movie_list.name))
            movie = MovieListMovie(title=entry['movie_name'], year=year, list_id=movie_list.id)
        else:
            console("Movie with title {} already exist in list {}".format(title, movie_list.name))

        id_list = []
        if options.identifiers:
            id_list = options.identifiers
        else:
            for _id in MovieListBase().supported_ids:
                if entry.get(_id):
                    id_list.append({_id: entry.get(_id)})
        if id_list:
            console('Setting movie identifiers:', id_list)
            movie.ids = get_db_movie_identifiers(identifier_list=id_list, session=session)
        session.merge(movie)

    console('Successfully added movie {} to movie list {} '.format(title, movie_list.name))
Beispiel #2
0
def get_trakt_id_from_title(title, media_type, year=None):
    if not title:
        raise LookupError('No lookup arguments provided.')
    requests_session = get_session()
    # Try finding trakt id based on title and year
    parsed_title, y = split_title_year(title)
    y = year or y
    try:
        params = {'query': parsed_title, 'type': media_type, 'year': y}
        log.debug('Type of title: %s', type(parsed_title))
        log.debug(
            'Searching with params: %s',
            ', '.join('{}={}'.format(k, v) for (k, v) in params.items()),
        )
        results = requests_session.get(get_api_url('search'), params=params).json()
    except requests.RequestException as e:
        raise LookupError('Searching trakt for %s failed with error: %s' % (title, e))
    for result in results:
        if year and result[media_type]['year'] != year:
            continue
        if parsed_title.lower() == result[media_type]['title'].lower():
            return result[media_type]['ids']['trakt']
    # grab the first result if there is no exact match
    if results:
        return results[0][media_type]['ids']['trakt']
Beispiel #3
0
    def post(self, list_id, session=None):
        """ Add movies to list by ID """
        try:
            movie_list = ml.get_list_by_id(list_id=list_id, session=session)
        except NoResultFound:
            return {'status': 'error',
                    'message': 'list_id %d does not exist' % list_id}, 404
        data = request.json

        # Validates ID type based on allowed ID
        # TODO pass this to json schema validation
        for id_name in data.get('movie_identifiers'):
            if set(id_name.keys()) & set(allowed_ids) == set([]):
                return {'status': 'error',
                        'message': 'movie identifier %s is not allowed' % id_name}, 501
        if 'movie_name' in data:
            title, year = data['movie_name'], data.get('movie_year')
        else:
            title, year = split_title_year(data['title'])
        movie = ml.get_movie_by_title(list_id=list_id, title=title, session=session)
        if movie:
            return {'status': 'error',
                    'message': 'movie with name "%s" already exist in list %d' % (title, list_id)}, 500
        movie = ml.MovieListMovie()
        movie.title = title
        movie.year = year
        movie.ids = ml.get_db_movie_identifiers(identifier_list=data.get('movie_identifiers'), session=session)
        movie.list_id = list_id
        session.add(movie)
        session.commit()
        response = jsonify({'movie': movie.to_dict()})
        response.status_code = 201
        return response
Beispiel #4
0
def get_item_from_cache(table, session, title=None, year=None, trakt_ids=None):
    """
    Get the cached info for a given show/movie from the database.
    :param table: Either TraktMovie or TraktShow
    :param title: Title of the show/movie
    :param year: First release year
    :param trakt_ids: instance of TraktShowIds or TraktMovieIds
    :param session: database session object
    :return: query result
    """
    result = None
    if trakt_ids:
        result = (
            session.query(table)
            .filter(
                or_(getattr(table, col) == val for col, val in trakt_ids.to_dict().items() if val)
            )
            .first()
        )
    elif title:
        title, y = split_title_year(title)
        year = year or y
        query = session.query(table).filter(table.title == title)
        if year:
            query = query.filter(table.year == year)
        result = query.first()
    return result
Beispiel #5
0
def prepare_lookup_for_tvmaze(**lookup_params):
    """
    Return a dict of params which is valid with tvmaze API lookups

    :param lookup_params: Search parameters
    :return: Dict of tvmaze recognizable key words
    """
    prepared_params = {}
    title = None
    series_name = (
        lookup_params.get('series_name')
        or lookup_params.get('show_name')
        or lookup_params.get('title')
    )
    if series_name:
        title, _ = split_title_year(series_name)
    # Support for when title is just a number
    if not title:
        title = series_name

    # Ensure we send native types to tvmaze lib as it does not handle new types very well
    prepared_params['tvmaze_id'] = lookup_params.get('tvmaze_id')
    prepared_params['thetvdb_id'] = lookup_params.get('tvdb_id') or lookup_params.get(
        'trakt_series_tvdb_id'
    )
    prepared_params['tvrage_id'] = lookup_params.get('tvrage_id') or lookup_params.get(
        'trakt_series_tvrage_id'
    )
    prepared_params['imdb_id'] = lookup_params.get('imdb_id')
    prepared_params['show_name'] = native(title) if title else None

    return prepared_params
Beispiel #6
0
def prepare_lookup_for_pytvmaze(**lookup_params):
    """
    Return a dict of params which is valid with pytvmaze get_show method
    :param lookup_params: Search parameters
    :return: Dict of pytvmaze recognizable key words
    """
    prepared_params = {}
    title = None
    year_match = None
    series_name = lookup_params.get('series_name') or lookup_params.get('show_name') or lookup_params.get('title')
    if series_name:
        title, year_match = split_title_year(series_name)
    # Support for when title is just a number
    if not title:
        title = series_name

    prepared_params['maze_id'] = lookup_params.get('tvmaze_id')
    prepared_params['tvdb_id'] = lookup_params.get('tvdb_id') or lookup_params.get('trakt_series_tvdb_id')
    prepared_params['tvrage_id'] = lookup_params.get('tvrage_id') or lookup_params.get('trakt_series_tvrage_id')
    prepared_params['imdb_id'] = lookup_params.get('imdb_id')
    prepared_params['show_name'] = title or None
    prepared_params['show_year'] = lookup_params.get('trakt_series_year') or lookup_params.get(
        'year') or lookup_params.get('imdb_year') or year_match
    prepared_params['show_network'] = lookup_params.get('network') or lookup_params.get('trakt_series_network')
    prepared_params['show_country'] = lookup_params.get('country') or lookup_params.get('trakt_series_country')
    prepared_params['show_language'] = lookup_params.get('language')

    # Include cast information by default
    prepared_params['embed'] = 'cast'

    return prepared_params
Beispiel #7
0
def movie_list_del(options):
    with Session() as session:
        try:
            movie_list = db.get_list_by_exact_name(options.list_name)
        except NoResultFound:
            console('Could not find movie list with name {}'.format(options.list_name))
            return

        try:
            movie_exist = db.get_movie_by_id(
                list_id=movie_list.id, movie_id=int(options.movie), session=session
            )
        except NoResultFound:
            console(
                'Could not find movie with ID {} in list `{}`'.format(
                    int(options.movie), options.list_name
                )
            )
            return
        except ValueError:
            title, year = split_title_year(options.movie)
            movie_exist = db.get_movie_by_title_and_year(
                list_id=movie_list.id, title=title, year=year, session=session
            )
        if not movie_exist:
            console(
                'Could not find movie with title {} in list {}'.format(
                    options.movie, options.list_name
                )
            )
            return
        else:
            console('Removing movie {} from list {}'.format(movie_exist.title, options.list_name))
            session.delete(movie_exist)
Beispiel #8
0
 def items(self):
     if self._items is None:
         try:
             req = TVDBRequest(username=self.config['username'], account_id=self.config['account_id']).get(
                 'user/favorites')
             series_ids = [int(f_id) for f_id in req['favorites'] if f_id != '']
         except RequestException as e:
             raise PluginError('Error retrieving favorites from thetvdb: %s' % str(e))
         self._items = []
         for series_id in series_ids:
             # Lookup the series name from the id
             try:
                 series = lookup_series(tvdb_id=series_id)
             except LookupError as e:
                 log.error('Error looking up %s from thetvdb: %s' % (series_id, e.args[0]))
             else:
                 series_name = series.name
                 if self.config.get('strip_dates'):
                     # Remove year from end of series name if present
                     series_name, _ = split_title_year(series_name)
                 entry = Entry()
                 entry['title'] = entry['series_name'] = series_name
                 entry['url'] = 'http://thetvdb.com/index.php?tab=series&id={}'.format(str(series.id))
                 entry['tvdb_id'] = str(series.id)
                 self._items.append(entry)
     return self._items
Beispiel #9
0
def movie_list_add(options):
    with Session() as session:
        try:
            movie_list = get_list_by_exact_name(options.list_name)
        except NoResultFound:
            console('Could not find movie list with name {}, creating'.format(options.list_name))
            movie_list = MovieListList(name=options.list_name)
            session.add(movie_list)
        session.merge(movie_list)
        title, year = split_title_year(options.movie_title)
        movie_exist = get_movie_by_title(list_id=movie_list.id, title=title, session=session)
        if movie_exist:
            console("Movie with the title {} already exist with list {}. Will replace identifiers if given".format(
                title, movie_list.name))
            output = 'Successfully updated movie {} to movie list {} '.format(title, movie_list.name)
        else:
            console("Adding movie with title {} to list {}".format(title, movie_list.name))
            movie_exist = MovieListMovie(title=title, year=year, list_id=movie_list.id)
            session.add(movie_exist)
            output = 'Successfully added movie {} to movie list {} '.format(title, movie_list.name)
        if options.identifiers:
            identifiers = [parse_identifier(identifier) for identifier in options.identifiers if options.identifiers]
            console('Adding identifiers {} to movie {}'.format(identifiers, title))
            movie_exist.ids = get_db_movie_identifiers(identifier_list=identifiers, session=session)
        console(output)
Beispiel #10
0
def prepare_lookup_for_pytvmaze(**lookup_params):
    """
    Return a dict of params which is valid with pytvmaze get_show method
    :param lookup_params: Search parameters
    :return: Dict of pytvmaze recognizable key words
    """
    prepared_params = {}
    series_name = lookup_params.get("series_name") or lookup_params.get("show_name") or lookup_params.get("title")
    title, year_match = split_title_year(series_name)
    # Support for when title is just a number
    if not title:
        title = series_name

    prepared_params["maze_id"] = lookup_params.get("tvmaze_id")
    prepared_params["tvdb_id"] = lookup_params.get("tvdb_id") or lookup_params.get("trakt_series_tvdb_id")
    prepared_params["tvrage_id"] = lookup_params.get("tvrage_id") or lookup_params.get("trakt_series_tvrage_id")
    prepared_params["show_name"] = title
    prepared_params["show_year"] = (
        lookup_params.get("trakt_series_year")
        or lookup_params.get("year")
        or lookup_params.get("imdb_year")
        or year_match
    )
    prepared_params["show_network"] = lookup_params.get("network") or lookup_params.get("trakt_series_network")
    prepared_params["show_country"] = lookup_params.get("country") or lookup_params.get("trakt_series_country")
    prepared_params["show_language"] = lookup_params.get("language")

    # Include cast information by default
    prepared_params["embed"] = "cast"

    return prepared_params
Beispiel #11
0
 def _find_entry(self, entry, session=None):
     """Finds `MovieListMovie` corresponding to this entry, if it exists."""
     for id_name in SUPPORTED_IDS:
         if entry.get(id_name):
             log.debug('trying to match movie based off id %s: %s', id_name, entry[id_name])
             res = (self._db_list(session).movies.join(MovieListMovie.ids).filter(
                 and_(
                     MovieListID.id_name == id_name,
                     MovieListID.id_value == entry[id_name]))
                    .first())
             if res:
                 log.debug('found movie %s', res)
                 return res
     # Fall back to title/year match
     if entry.get('movie_name') and entry.get('movie_year'):
         name, year = entry['movie_name'], entry['movie_year']
     else:
         name, year = split_title_year(entry['title'])
     if not name:
         log.verbose('no movie name to match, skipping')
         return
     log.debug('trying to match movie based of name: %s and year: %d', name, year)
     res = (self._db_list(session).movies.filter(func.lower(MovieListMovie.title) == name.lower())
            .filter(MovieListMovie.year == year).first())
     if res:
         log.debug('found movie %s', res)
     return res
Beispiel #12
0
    def lazy_loader(self, entry):
        """Does the lookup for this entry and populates the entry fields."""
        lookup = plugin.get('api_bluray', self).lookup

        try:
            with Session() as session:
                title, year = split_title_year(entry['title'])
                movie = lookup(title=title, year=year, session=session)
                entry.update_using_map(self.field_map, movie)
        except LookupError:
            log_once('Bluray lookup failed for %s' % entry['title'], log, logging.WARN)
Beispiel #13
0
    def estimate(self, entry):
        if not all(field in entry for field in ['series_name', 'series_season']):
            return
        series_name = entry['series_name']
        season = entry['series_season']
        episode_number = entry.get('series_episode')
        title, year_match = split_title_year(series_name)

        # This value should be added to input plugins to trigger a season lookuo
        season_pack = entry.get('season_pack_lookup')

        kwargs = {
            'tvmaze_id': entry.get('tvmaze_id'),
            'tvdb_id': entry.get('tvdb_id') or entry.get('trakt_series_tvdb_id'),
            'tvrage_id': entry.get('tvrage_id') or entry.get('trakt_series_tvrage_id'),
            'imdb_id': entry.get('imdb_id'),
            'show_name': title,
            'show_year': entry.get('trakt_series_year')
            or entry.get('year')
            or entry.get('imdb_year')
            or year_match,
            'show_network': entry.get('network') or entry.get('trakt_series_network'),
            'show_country': entry.get('country') or entry.get('trakt_series_country'),
            'show_language': entry.get('language'),
            'series_season': season,
            'series_episode': episode_number,
            'series_name': series_name,
        }

        api_tvmaze = plugin.get('api_tvmaze', self)
        if season_pack:
            lookup = api_tvmaze.season_lookup
            log.debug('Searching api_tvmaze for season')
        else:
            log.debug('Searching api_tvmaze for episode')
            lookup = api_tvmaze.episode_lookup

        for k, v in list(kwargs.items()):
            if v:
                log.debug('%s: %s', k, v)

        try:
            entity = lookup(**kwargs)
        except LookupError as e:
            log.debug(str(e))
            return
        if entity and entity.airdate:
            log.debug('received air-date: %s', entity.airdate)
            return entity.airdate
        return
Beispiel #14
0
def movie_list_del(options):
    with Session() as session:
        try:
            movie_list = get_list_by_exact_name(options.list_name)
        except NoResultFound:
            console('Could not find movie list with name {}'.format(options.list_name))
            return
        title = split_title_year(options.movie_title)[0]
        movie_exist = get_movie_by_title(list_id=movie_list.id, title=title, session=session)
        if movie_exist:
            console('Removing movie %s from list %s' % (options.movie_title, options.list_name))
            session.delete(movie_exist)
        else:
            console('Could not find movie with title %s in list %s' % (options.movie_title, options.list_name))
            return
Beispiel #15
0
 def _find_entry(self, entry, session=None):
     """Finds `MovieListMovie` corresponding to this entry, if it exists."""
     for id_name in SUPPORTED_IDS:
         if id_name in entry:
             # TODO: Make this real
             res = (self._db_list(session).movies.filter(MovieListID.id_name == id_name)
                    .filter(MovieListID.id_value == entry[id_name]).first())
             if res:
                 return res
     # Fall back to title/year match
     if 'movie_name' in entry and 'movie_year' in entry:
         name, year = entry['movie_name'], entry['movie_year']
     else:
         name, year = split_title_year(entry['title'])
     res = (self._db_list(session).movies.filter(MovieListMovie.title == name)
            .filter(MovieListMovie.year == year).first())
     return res
Beispiel #16
0
def movie_list_add(options):
    with Session() as session:
        try:
            movie_list = db.get_list_by_exact_name(options.list_name, session=session)
        except NoResultFound:
            console('Could not find movie list with name {}, creating'.format(options.list_name))
            movie_list = db.MovieListList(name=options.list_name)
            session.add(movie_list)
            session.commit()

        title, year = split_title_year(options.movie_title)
        console('Trying to lookup movie title: `{}`'.format(title))
        movie_lookup = lookup_movie(title=title, session=session, identifiers=options.identifiers)
        if not movie_lookup:
            console(
                'ERROR: movie lookup failed for movie {}, aborting'.format(options.movie_title)
            )
            return

        title = movie_lookup['movie_name']
        movie = db.get_movie_by_title_and_year(
            list_id=movie_list.id, title=title, year=year, session=session
        )
        if not movie:
            console("Adding movie with title {} to list {}".format(title, movie_list.name))
            movie = db.MovieListMovie(title=title, year=year, list_id=movie_list.id)
        else:
            console("Movie with title {} already exist in list {}".format(title, movie_list.name))

        id_list = []
        if options.identifiers:
            id_list = options.identifiers
        else:
            for _id in db.MovieListBase().supported_ids:
                if movie_lookup.get(_id):
                    id_list.append({_id: movie_lookup.get(_id)})
        if id_list:
            console('Setting movie identifiers:')
            for ident in id_list:
                for key in ident:
                    console('{}: {}'.format(key, ident[key]))
            movie.ids = db.get_db_movie_identifiers(identifier_list=id_list, session=session)
        session.merge(movie)
        console('Successfully added movie {} to movie list {} '.format(title, movie_list.name))
Beispiel #17
0
 def add(self, entry, session=None):
     # Check if this is already in the list, refresh info if so
     db_list = self._db_list(session=session)
     db_movie = self._find_entry(entry, session=session)
     # Just delete and re-create to refresh
     if db_movie:
         session.delete(db_movie)
     db_movie = MovieListMovie()
     if 'movie_name' in entry:
         db_movie.title, db_movie.year = entry['movie_name'], entry.get('movie_year')
     else:
         db_movie.title, db_movie.year = split_title_year(entry['title'])
     for id_name in SUPPORTED_IDS:
         if id_name in entry:
             db_movie.ids.append(MovieListID(id_name=id_name, id_value=entry[id_name]))
     log.debug('adding entry %s', entry)
     db_list.movies.append(db_movie)
     session.commit()
     return db_movie.to_entry()
Beispiel #18
0
 def _find_entry(self, entry, session=None):
     """Finds `MovieListMovie` corresponding to this entry, if it exists."""
     for id_name in SUPPORTED_IDS:
         if id_name in entry:
             log.debug('finding movie based off id %s:%s', id_name, entry[id_name])
             res = (self._db_list(session).movies.join(MovieListMovie.ids).filter(
                 and_(
                     MovieListID.id_name == id_name,
                     MovieListID.id_value == entry[id_name]))
                    .first())
             if res:
                 log.debug('found movie %s', res)
                 return res
     # Fall back to title/year match
     if 'movie_name' in entry and 'movie_year' in entry:
         name, year = entry['movie_name'], entry['movie_year']
     else:
         name, year = split_title_year(entry['title'])
     res = (self._db_list(session).movies.filter(MovieListMovie.title == name)
            .filter(MovieListMovie.year == year).first())
     return res
Beispiel #19
0
def find_series_id(name):
    """Looks up the tvdb id for a series"""
    try:
        series = TVDBRequest().get('search/series', name=name)
    except requests.RequestException as e:
        raise LookupError('Unable to get search results for %s: %s' % (name, e))

    name = name.lower()

    if not series:
        raise LookupError('No results found for %s' % name)

    # Cleanup results for sorting
    for s in series:
        if s['firstAired']:
            s['firstAired'] = datetime.strptime(s['firstAired'], "%Y-%m-%d")
        else:
            s['firstAired'] = datetime(1970, 1, 1)

        s['names'] = [a.lower() for a in s.get('aliases')] if s.get('aliases') else []
        if s.get('seriesName'):
            s['names'].append(s.get('seriesName').lower())
        s['running'] = True if s['status'] == 'Continuing' else False

        for n in s['names']:
            # Exact matching by stripping our the year
            title, year = split_title_year(n)
            if title not in s['names']:
                s['names'].append(title)

    # Sort by status, aired_date
    series = sorted(series, key=lambda x: (x['running'], x['firstAired']), reverse=True)

    for s in series:
        # Exact match
        if name in s['names']:
            return s['id']

    # If there is no exact match, pick the first result
    return series[0]['id']
Beispiel #20
0
 def add(self, entry):
     with Session() as session:
         # Check if this is already in the list, refresh info if so
         db_list = self._db_list(session=session)
         db_movie = self._find_entry(entry, session=session)
         # Just delete and re-create to refresh
         if db_movie:
             session.delete(db_movie)
         db_movie = MovieListMovie()
         if 'movie_name' in entry:
             db_movie.title, db_movie.year = entry['movie_name'], entry.get(
                 'movie_year')
         else:
             db_movie.title, db_movie.year = split_title_year(
                 entry['title'])
         for id_name in MovieListBase().supported_ids:
             if id_name in entry:
                 db_movie.ids.append(
                     MovieListID(id_name=id_name, id_value=entry[id_name]))
         log.debug('adding entry %s', entry)
         db_list.movies.append(db_movie)
         session.commit()
         return db_movie.to_entry()
Beispiel #21
0
 def items(self):
     if self._items is None:
         try:
             req = plugin_api_tvdb.TVDBRequest(
                 username=self.config['username'],
                 account_id=self.config['account_id'],
                 api_key=self.config['api_key'],
             ).get('user/favorites')
             series_ids = [
                 int(f_id) for f_id in req['favorites'] if f_id != ''
             ]
         except RequestException as e:
             raise PluginError(
                 'Error retrieving favorites from thetvdb: %s' % str(e))
         self._items = []
         for series_id in series_ids:
             # Lookup the series name from the id
             try:
                 series = plugin_api_tvdb.lookup_series(
                     tvdb_id=series_id,
                     language=self.config.get('language'))
             except LookupError as e:
                 logger.error('Error looking up {} from thetvdb: {}',
                              series_id, e.args[0])
             else:
                 series_name = series.name
                 if self.config.get('strip_dates'):
                     # Remove year from end of series name if present
                     series_name, _ = split_title_year(series_name)
                 entry = Entry()
                 entry['title'] = entry['series_name'] = series_name
                 entry[
                     'url'] = 'http://thetvdb.com/index.php?tab=series&id={}'.format(
                         str(series.id))
                 entry['tvdb_id'] = str(series.id)
                 self._items.append(entry)
     return self._items
Beispiel #22
0
def prepare_lookup_for_pytvmaze(**lookup_params):
    """
    Return a dict of params which is valid with pytvmaze get_show method
    :param lookup_params: Search parameters
    :return: Dict of pytvmaze recognizable key words
    """
    prepared_params = {}
    title = None
    year_match = None
    series_name = lookup_params.get('series_name') or lookup_params.get(
        'show_name') or lookup_params.get('title')
    if series_name:
        title, year_match = split_title_year(series_name)
    # Support for when title is just a number
    if not title:
        title = series_name

    prepared_params['maze_id'] = lookup_params.get('tvmaze_id')
    prepared_params['tvdb_id'] = lookup_params.get(
        'tvdb_id') or lookup_params.get('trakt_series_tvdb_id')
    prepared_params['tvrage_id'] = lookup_params.get(
        'tvrage_id') or lookup_params.get('trakt_series_tvrage_id')
    prepared_params['imdb_id'] = lookup_params.get('imdb_id')
    prepared_params['show_name'] = title or None
    prepared_params['show_year'] = lookup_params.get(
        'trakt_series_year') or lookup_params.get('year') or lookup_params.get(
            'imdb_year') or year_match
    prepared_params['show_network'] = lookup_params.get(
        'network') or lookup_params.get('trakt_series_network')
    prepared_params['show_country'] = lookup_params.get(
        'country') or lookup_params.get('trakt_series_country')
    prepared_params['show_language'] = lookup_params.get('language')

    # Include cast information by default
    prepared_params['embed'] = 'cast'

    return prepared_params
    def estimate(self, entry):
        if not all(field in entry for field in ['series_name', 'series_season', 'series_episode']):
            return
        series_name = entry['series_name']
        season = entry['series_season']
        episode_number = entry['series_episode']
        title, year_match = split_title_year(series_name)

        kwargs = {}
        kwargs['tvmaze_id'] = entry.get('tvmaze_id')
        kwargs['tvdb_id'] = entry.get('tvdb_id') or entry.get('trakt_series_tvdb_id')
        kwargs['tvrage_id'] = entry.get('tvrage_id') or entry.get('trakt_series_tvrage_id')
        kwargs['imdb_id'] = entry.get('imdb_id')
        kwargs['show_name'] = title
        kwargs['show_year'] = entry.get('trakt_series_year') or entry.get('year') or entry.get(
            'imdb_year') or year_match
        kwargs['show_network'] = entry.get('network') or entry.get('trakt_series_network')
        kwargs['show_country'] = entry.get('country') or entry.get('trakt_series_country')
        kwargs['show_language'] = entry.get('language')
        kwargs['series_season'] = season
        kwargs['series_episode'] = episode_number
        kwargs['series_name'] = series_name

        log.debug(
            'Searching TVMaze for airdate of {0} season {1} episode {2}'.format(series_name, season, episode_number))
        for k, v in list(kwargs.items()):
            if v:
                log.debug('{0}: {1}'.format(k, v))
        try:
            episode = lookup(**kwargs)
        except LookupError as e:
            log.debug(e)
            return
        if episode and episode.airdate:
            log.debug('received airdate: {0}'.format(episode.airdate))
            return episode.airdate
        return
Beispiel #24
0
def prepare_lookup_for_tvmaze(**lookup_params):
    """
    Return a dict of params which is valid with tvmaze API lookups

    :param lookup_params: Search parameters
    :return: Dict of tvmaze recognizable key words
    """
    prepared_params = {}
    title = None
    series_name = lookup_params.get('series_name') or lookup_params.get('show_name') or lookup_params.get('title')
    if series_name:
        title, _ = split_title_year(series_name)
    # Support for when title is just a number
    if not title:
        title = series_name

    # Ensure we send native types to tvmaze lib as it does not handle new types very well
    prepared_params['tvmaze_id'] = lookup_params.get('tvmaze_id')
    prepared_params['thetvdb_id'] = lookup_params.get('tvdb_id') or lookup_params.get('trakt_series_tvdb_id')
    prepared_params['tvrage_id'] = lookup_params.get('tvrage_id') or lookup_params.get('trakt_series_tvrage_id')
    prepared_params['imdb_id'] = lookup_params.get('imdb_id')
    prepared_params['show_name'] = native(title) if title else None

    return prepared_params
Beispiel #25
0
def movie_list_add(options, session=None):
    try:
        movie_list = get_list_by_exact_name(options.list_name)
    except NoResultFound:
        console('Could not find movie list with name {}, creating'.format(options.list_name))
        movie_list = MovieListList(name=options.list_name)
        session.add(movie_list)
        session.commit()
    title, year = split_title_year(options.movie_title)
    movie_exist = get_movie_by_title(list_id=movie_list.id, title=title, session=session)
    if movie_exist:
        console("Movie with the title {} already exist with list {}. Will replace identifiers if given".format(
            title, movie_list.name))
        output = 'Successfully updated movie {} to movie list {} '.format(title, movie_list.name)
    else:
        console("Adding movie with title {} to list {}".format(title, movie_list.name))
        movie_exist = MovieListMovie(title=title, year=year, list_id=movie_list.id)
        session.add(movie_exist)
        output = 'Successfully added movie {} to movie list {} '.format(title, movie_list.name)
    if options.identifiers:
        identifiers = [parse_identifier(identifier) for identifier in options.identifiers if options.identifiers]
        console('Adding identifiers {} to movie {}'.format(identifiers, title))
        movie_exist.ids = get_db_movie_identifiers(identifier_list=identifiers, session=session)
    console(output)
Beispiel #26
0
def get_item_from_cache(table, session, title=None, year=None, trakt_ids=None):
    """
    Get the cached info for a given show/movie from the database.
    :param table: Either TraktMovie or TraktShow
    :param title: Title of the show/movie
    :param year: First release year
    :param trakt_ids: instance of TraktShowIds or TraktMovieIds
    :param session: database session object
    :return: query result
    """
    result = None
    if trakt_ids:
        result = (session.query(table).filter(
            or_(
                getattr(table, col) == val
                for col, val in trakt_ids.to_dict().items() if val)).first())
    elif title:
        title, y = split_title_year(title)
        year = year or y
        query = session.query(table).filter(table.title == title)
        if year:
            query = query.filter(table.year == year)
        result = query.first()
    return result
Beispiel #27
0
 def test_split_year_title(self, title, expected_title, expected_year):
     assert split_title_year(title) == (expected_title, expected_year)
Beispiel #28
0
    def items(self):
        if self._items is None:
            if self.config['list'] in ['collection', 'watched'] and self.config['type'] == 'auto':
                raise plugin.PluginError('`type` cannot be `auto` for %s list.' % self.config['list'])

            endpoint = self.get_list_endpoint()

            log.verbose('Retrieving `%s` list `%s`', self.config['type'], self.config['list'])
            try:
                result = self.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)

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

            entries = []
            list_type = (self.config['type']).rstrip('s')
            for item in data:
                if self.config['type'] == 'auto':
                    list_type = item['type']
                # 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 list_type != 'episode' and not item[list_type]['title']:
                    # Skip shows/movies with no title
                    log.warning('Item in trakt list does not appear to have a title, skipping.')
                    continue
                entry = Entry()
                if list_type == 'episode':
                    entry['url'] = 'https://trakt.tv/shows/%s/seasons/%s/episodes/%s' % (
                        item['show']['ids']['slug'], item['episode']['season'], item['episode']['number'])
                else:
                    entry['url'] = 'https://trakt.tv/%ss/%s' % (list_type, item[list_type]['ids'].get('slug'))

                entry.update_using_map(field_maps[list_type], item)

                # get movie name translation
                language = self.config.get('language')
                if list_type == 'movie' and language:
                    endpoint = ['movies', entry['trakt_movie_id'], 'translations', language]
                    try:
                        result = self.session.get(get_api_url(endpoint))
                        try:
                            translation = result.json()
                        except ValueError:
                            raise plugin.PluginError('Error decoding movie translation from trakt: %s.' % result.text)
                    except RequestException as e:
                        raise plugin.PluginError('Could not retrieve movie translation from trakt: %s' % str(e))
                    if not translation:
                        log.warning('No translation data returned from trakt for movie %s.', entry['title'])
                    else:
                        log.verbose('Found `%s` translation for movie `%s`: %s',
                                    language, entry['movie_name'], translation[0]['title'])
                        entry['title'] = translation[0]['title']
                        if entry.get('movie_year'):
                            entry['title'] += ' (' + str(entry['movie_year']) + ')'
                        entry['movie_name'] = translation[0]['title']

                # Override the title if strip_dates is on. TODO: a better way?
                if self.config.get('strip_dates'):
                    if list_type in ['show', 'movie']:
                        entry['title'] = item[list_type]['title']
                    elif list_type == 'episode':
                        entry['title'] = '{show[title]} S{episode[season]:02}E{episode[number]:02}'.format(**item)
                        if item['episode']['title']:
                            entry['title'] += ' {episode[title]}'.format(**item)
                if entry.isvalid():
                    if self.config.get('strip_dates'):
                        # Remove year from end of name if present
                        entry['title'] = split_title_year(entry['title'])[0]
                    entries.append(entry)
                else:
                    log.debug('Invalid entry created? %s', entry)

            self._items = entries
        return self._items
Beispiel #29
0
    def estimate(self, entry):
        if not all(field in entry
                   for field in ['series_name', 'series_season']):
            return
        series_name = entry['series_name']
        season = entry['series_season']
        episode_number = entry.get('series_episode')
        title, year_match = split_title_year(series_name)

        # This value should be added to input plugins to trigger a season lookuo
        season_pack = entry.get('season_pack_lookup')

        kwargs = {
            'tvmaze_id':
            entry.get('tvmaze_id'),
            'tvdb_id':
            entry.get('tvdb_id') or entry.get('trakt_series_tvdb_id'),
            'tvrage_id':
            entry.get('tvrage_id') or entry.get('trakt_series_tvrage_id'),
            'imdb_id':
            entry.get('imdb_id'),
            'show_name':
            title,
            'show_year':
            entry.get('trakt_series_year') or entry.get('year')
            or entry.get('imdb_year') or year_match,
            'show_network':
            entry.get('network') or entry.get('trakt_series_network'),
            'show_country':
            entry.get('country') or entry.get('trakt_series_country'),
            'show_language':
            entry.get('language'),
            'series_season':
            season,
            'series_episode':
            episode_number,
            'series_name':
            series_name,
        }

        api_tvmaze = plugin.get('api_tvmaze', self)
        if season_pack:
            lookup = api_tvmaze.season_lookup
            logger.debug('Searching api_tvmaze for season')
        else:
            logger.debug('Searching api_tvmaze for episode')
            lookup = api_tvmaze.episode_lookup

        for k, v in list(kwargs.items()):
            if v:
                logger.debug('{}: {}', k, v)

        entity_data = {'data_exists': True, 'entity_date': None}
        entity = {}
        try:
            entity = lookup(**kwargs)
        except LookupError as e:
            logger.debug(str(e))
            entity_data['data_exists'] = False
        if entity and entity.airdate:
            logger.debug('received air-date: {}', entity.airdate)
            entity_data['entity_date'] = entity.airdate

        if entity_data['data_exists'] == False:
            # Make Lookup to series to see if failed because of no episode or no data
            lookup = api_tvmaze.series_lookup
            series = {}
            try:
                series = lookup(**kwargs)
            except LookupError as e:
                entity_data['data_exists'] = False

            if not series:
                logger.debug('No data in tvmaze for series: {}', series_name)
                entity_data['data_exists'] = False
            else:
                logger.debug(
                    'No information to episode, but series {} exists in tvmaze',
                    series_name)
                entity_data['data_exists'] = True

        return entity_data
Beispiel #30
0
 def test_split_year_title(self, title, expected_title, expected_year):
     assert split_title_year(title) == (expected_title, expected_year)
Beispiel #31
0
def filter_strip_year(name: str) -> str:
    return split_title_year(name).title
Beispiel #32
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') is not None:
                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:
                    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)
Beispiel #33
0
def filter_get_year(name: str) -> str:
    return split_title_year(name).year
Beispiel #34
0
 def test_split_year_title_parenthesis_and_year(self):
     movie = 'The Human Centipede III (Final Sequence) (2015)'
     expected = 'The Human Centipede III (Final Sequence)', 2015
     assert split_title_year(movie) == expected
Beispiel #35
0
 def test_split_year_title_year_scene(self):
     movie = 'The.Matrix.1999'
     expected = 'The.Matrix.', 1999
     assert split_title_year(movie) == expected
Beispiel #36
0
 def test_split_year_title_year_parenthesis(self):
     movie = 'The Matrix (1999)'
     expected = 'The Matrix', 1999
     assert split_title_year(movie) == expected
Beispiel #37
0
    def items(self):
        if self._items is None:
            if self.config['list'] in ['collection', 'watched', 'trending', 'popular'] and self.config['type'] == 'auto':
                raise plugin.PluginError(
                    '`type` cannot be `auto` for %s list.' % self.config['list']
                )

            endpoint = self.get_list_endpoint()

            log.verbose('Retrieving `%s` list `%s`', self.config['type'], self.config['list'])
            try:
                result = self.session.get(db.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.')

                current_page = int(result.headers.get('X-Pagination-Page', 1))
                current_page_count = int(result.headers.get('X-Pagination-Page-Count', 1))
                if current_page < current_page_count:
                    # Pagination, gotta get it all, but we'll limit it to 1000 per page
                    # but we'll have to start over from 0
                    data = []

                    limit = 1000
                    pagination_item_count = int(result.headers.get('X-Pagination-Item-Count', 0))
                    number_of_pages = math.ceil(pagination_item_count / limit)
                    log.debug(
                        'Response is paginated. Number of items: %s, number of pages: %s',
                        pagination_item_count,
                        number_of_pages,
                    )
                    page = int(result.headers.get('X-Pagination-Page'))
                    while page <= number_of_pages:
                        paginated_result = self.session.get(
                            db.get_api_url(endpoint), params={'limit': limit, 'page': page}
                        )
                        page += 1
                        try:
                            data.extend(paginated_result.json())
                        except ValueError:
                            log.debug(
                                'Could not decode json from response: %s', paginated_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)

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

            entries = []
            list_type = (self.config['type']).rstrip('s')
            for item in data:
                if self.config['type'] == 'auto':
                    list_type = item['type']
                if self.config['list'] == 'popular':
                    item = {list_type: item}
                # 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 list_type != 'episode' and not item[list_type]['title']:
                    # Skip shows/movies with no title
                    log.warning('Item in trakt list does not appear to have a title, skipping.')
                    continue
                entry = Entry()
                if list_type == 'episode':
                    entry['url'] = 'https://trakt.tv/shows/%s/seasons/%s/episodes/%s' % (
                        item['show']['ids']['slug'],
                        item['episode']['season'],
                        item['episode']['number'],
                    )
                else:
                    entry['url'] = 'https://trakt.tv/%ss/%s' % (
                        list_type,
                        item[list_type]['ids'].get('slug'),
                    )

                entry.update_using_map(field_maps[list_type], item)

                # get movie name translation
                language = self.config.get('language')
                if list_type == 'movie' and language:
                    endpoint = ['movies', entry['trakt_movie_id'], 'translations', language]
                    try:
                        result = self.session.get(db.get_api_url(endpoint))
                        try:
                            translation = result.json()
                        except ValueError:
                            raise plugin.PluginError(
                                'Error decoding movie translation from trakt: %s.' % result.text
                            )
                    except RequestException as e:
                        raise plugin.PluginError(
                            'Could not retrieve movie translation from trakt: %s' % str(e)
                        )
                    if not translation:
                        log.warning(
                            'No translation data returned from trakt for movie %s.', entry['title']
                        )
                    else:
                        log.verbose(
                            'Found `%s` translation for movie `%s`: %s',
                            language,
                            entry['movie_name'],
                            translation[0]['title'],
                        )
                        entry['title'] = translation[0]['title']
                        if entry.get('movie_year'):
                            entry['title'] += ' (' + str(entry['movie_year']) + ')'
                        entry['movie_name'] = translation[0]['title']

                # Override the title if strip_dates is on. TODO: a better way?
                if self.config.get('strip_dates'):
                    if list_type in ['show', 'movie']:
                        entry['title'] = item[list_type]['title']
                    elif list_type == 'episode':
                        entry[
                            'title'
                        ] = '{show[title]} S{episode[season]:02}E{episode[number]:02}'.format(
                            **item
                        )
                        if item['episode']['title']:
                            entry['title'] += ' {episode[title]}'.format(**item)
                if entry.isvalid():
                    if self.config.get('strip_dates'):
                        # Remove year from end of name if present
                        entry['title'] = split_title_year(entry['title'])[0]
                    entries.append(entry)

                    if self.config.get('limit') and len(entries) >= self.config.get('limit'):
                        break
                else:
                    log.debug('Invalid entry created? %s', entry)

            self._items = entries
        return self._items
    def estimate(self, entry):
        if not all(field in entry
                   for field in ['series_name', 'series_season']):
            return
        series_name = entry['series_name']
        season = entry['series_season']
        episode_number = entry.get('series_episode')
        title, year_match = split_title_year(series_name)

        # This value should be added to input plugins to trigger a season lookup
        season_pack = entry.get('season_pack_lookup')

        kwargs = {
            'title':
            title,
            'year':
            entry.get('trakt_series_year') or entry.get('year')
            or entry.get('imdb_year') or year_match,
            'trakt_slug':
            entry.get('trakt_slug'),
            'tmdb_id':
            entry.get('tmdb_id'),
            'tvdb_id':
            entry.get('tvdb_id') or entry.get('trakt_series_tvdb_id'),
            'imdb_id':
            entry.get('imdb_id'),
            'tvrage_id':
            entry.get('tvrage_id') or entry.get('trakt_series_tvrage_id'),
        }

        api_trakt = plugin.get_plugin_by_name('api_trakt').instance
        log.debug('Searching api_trakt for series')
        for k, v in list(kwargs.items()):
            if v:
                log.debug('%s: %s', k, v)

        with Session(expire_on_commit=False) as session:
            try:
                trakt_series = api_trakt.lookup_series(session=session,
                                                       **kwargs)
                if trakt_series is None:
                    return

                trakt_season = trakt_series.get_season(season, session)
                if trakt_season is None:
                    log.debug('%s doesn\'t have a season %s in trakt' %
                              (series_name, season))
                    return datetime.max
                if season_pack:
                    entity = trakt_season
                else:
                    entity = trakt_series.get_episode(season, episode_number,
                                                      session)
                    if entity is None:
                        log.debug(
                            '%s doesn\'t have a season %s episode %s in trakt'
                            % (series_name, season, episode_number))
                        return datetime.max
            except LookupError as e:
                log.debug(str(e))
                return
        if entity and entity.first_aired:
            log.debug('received first-aired: %s', entity.first_aired)
            return entity.first_aired
        return
Beispiel #39
0
    def get_items(self):
        """Iterator over etrieved itesms from the trakt api."""
        if self.config['list'] in ['collection', 'watched', 'trending', 'popular'] and self.config['type'] == 'auto':
            raise plugin.PluginError(
                '`type` cannot be `auto` for %s list.' % self.config['list']
            )

        limit_per_page = 1000

        endpoint = self.get_list_endpoint()

        list_type = (self.config['type']).rstrip('s')

        log.verbose('Retrieving `%s` list `%s`', self.config['type'], self.config['list'])
        try:
            page = 1
            collecting_finished = False
            while not collecting_finished:
                result = self.session.get(
                    db.get_api_url(endpoint), params={'limit': limit_per_page, 'page': page}
                )
                page = int(result.headers.get('X-Pagination-Page', 1))
                number_of_pages = int(result.headers.get('X-Pagination-Page-Count', 1))
                if page == 2:
                    # If there is more than one page (more than 1000 items) warn user they may want to limit
                    log.verbose('There are a large number of items in trakt `%s` list. You may want to enable `limit`'
                                ' plugin to reduce the amount of entries in this task.', self.config['list'])

                collecting_finished = page >= number_of_pages
                page += 1

                try:
                    trakt_items = result.json()
                except ValueError:
                    log.debug(
                        'Could not decode json from response: %s', result.text
                    )
                    raise plugin.PluginError('Error getting list from trakt.')
                if not trakt_items:
                    log.warning(
                        'No data returned from trakt for %s list %s.',
                        self.config['type'],
                        self.config['list'],
                    )
                    return

                for item in trakt_items:
                    if self.config['type'] == 'auto':
                        list_type = item['type']
                    if self.config['list'] == 'popular':
                        item = {list_type: item}
                    # 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 list_type != 'episode' and not item[list_type]['title']:
                        # Skip shows/movies with no title
                        log.warning('Item in trakt list does not appear to have a title, skipping.')
                        continue
                    entry = Entry()
                    if list_type == 'episode':
                        entry['url'] = 'https://trakt.tv/shows/%s/seasons/%s/episodes/%s' % (
                            item['show']['ids']['slug'],
                            item['episode']['season'],
                            item['episode']['number'],
                        )
                    else:
                        entry['url'] = 'https://trakt.tv/%ss/%s' % (
                            list_type,
                            item[list_type]['ids'].get('slug'),
                        )

                    entry.update_using_map(field_maps[list_type], item)

                    # get movie name translation
                    language = self.config.get('language')
                    if list_type == 'movie' and language:
                        endpoint = ['movies', entry['trakt_movie_id'], 'translations', language]
                        try:
                            result = self.session.get(db.get_api_url(endpoint))
                            try:
                                translation = result.json()
                            except ValueError:
                                raise plugin.PluginError(
                                    'Error decoding movie translation from trakt: %s.' % result.text
                                )
                        except RequestException as e:
                            raise plugin.PluginError(
                                'Could not retrieve movie translation from trakt: %s' % str(e)
                            )
                        if not translation:
                            log.warning(
                                'No translation data returned from trakt for movie %s.', entry['title']
                            )
                        else:
                            log.verbose(
                                'Found `%s` translation for movie `%s`: %s',
                                language,
                                entry['movie_name'],
                                translation[0]['title'],
                            )
                            entry['title'] = translation[0]['title']
                            if entry.get('movie_year'):
                                entry['title'] += ' (' + str(entry['movie_year']) + ')'
                            entry['movie_name'] = translation[0]['title']

                    # Override the title if strip_dates is on. TODO: a better way?
                    if self.config.get('strip_dates'):
                        if list_type in ['show', 'movie']:
                            entry['title'] = item[list_type]['title']
                        elif list_type == 'episode':
                            entry[
                                'title'
                            ] = '{show[title]} S{episode[season]:02}E{episode[number]:02}'.format(
                                **item
                            )
                            if item['episode']['title']:
                                entry['title'] += ' {episode[title]}'.format(**item)
                    if entry.isvalid():
                        if self.config.get('strip_dates'):
                            # Remove year from end of name if present
                            entry['title'] = split_title_year(entry['title'])[0]
                        yield entry
                    else:
                        log.debug('Invalid entry created? %s', entry)

        except RequestException as e:
            raise plugin.PluginError('Could not retrieve list from trakt (%s)' % e)
Beispiel #40
0
    def items(self):
        if self._items is None:
            if self.config['list'] in ['collection', 'watched'] and self.config['type'] == 'auto':
                raise plugin.PluginError('`type` cannot be `auto` for %s list.' % self.config['list'])

            endpoint = self.get_list_endpoint()

            log.verbose('Retrieving `%s` list `%s`', self.config['type'], self.config['list'])
            try:
                result = self.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)

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

            entries = []
            list_type = (self.config['type']).rstrip('s')
            for item in data:
                if self.config['type'] == 'auto':
                    list_type = item['type']
                # 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 list_type != 'episode' and not item[list_type]['title']:
                    # Skip shows/movies with no title
                    log.warning('Item in trakt list does not appear to have a title, skipping.')
                    continue
                entry = Entry()
                if list_type == 'episode':
                    entry['url'] = 'https://trakt.tv/shows/%s/seasons/%s/episodes/%s' % (
                        item['show']['ids']['slug'], item['episode']['season'], item['episode']['number'])
                else:
                    entry['url'] = 'https://trakt.tv/%ss/%s' % (list_type, item[list_type]['ids'].get('slug'))
                entry.update_using_map(field_maps[list_type], item)
                # Override the title if strip_dates is on. TODO: a better way?
                if self.config.get('strip_dates'):
                    if list_type in ['show', 'movie']:
                        entry['title'] = item[list_type]['title']
                    elif list_type == 'episode':
                        entry['title'] = '{show[title]} S{episode[season]:02}E{episode[number]:02}'.format(**item)
                        if item['episode']['title']:
                            entry['title'] += ' {episode[title]}'.format(**item)
                if entry.isvalid():
                    if self.config.get('strip_dates'):
                        # Remove year from end of name if present
                        entry['title'] = split_title_year(entry['title'])[0]
                    entries.append(entry)
                else:
                    log.debug('Invalid entry created? %s', entry)

            self._items = entries
        return self._items
Beispiel #41
0
 def test_split_year_title_no_year(self):
     movie = 'The Matrix'
     expected = 'The Matrix', None
     assert split_title_year(movie) == expected
Beispiel #42
0
    def estimate(self, entry):
        if not all(field in entry
                   for field in ['series_name', 'series_season']):
            return
        series_name = entry['series_name']
        season = entry['series_season']
        episode_number = entry.get('series_episode')
        title, year_match = split_title_year(series_name)

        # This value should be added to input plugins to trigger a season lookuo
        season_pack = entry.get('season_pack_lookup')

        kwargs = {
            'tvmaze_id':
            entry.get('tvmaze_id'),
            'tvdb_id':
            entry.get('tvdb_id') or entry.get('trakt_series_tvdb_id'),
            'tvrage_id':
            entry.get('tvrage_id') or entry.get('trakt_series_tvrage_id'),
            'imdb_id':
            entry.get('imdb_id'),
            'show_name':
            title,
            'show_year':
            entry.get('trakt_series_year') or entry.get('year')
            or entry.get('imdb_year') or year_match,
            'show_network':
            entry.get('network') or entry.get('trakt_series_network'),
            'show_country':
            entry.get('country') or entry.get('trakt_series_country'),
            'show_language':
            entry.get('language'),
            'series_season':
            season,
            'series_episode':
            episode_number,
            'series_name':
            series_name,
        }

        api_tvmaze = plugin.get('api_tvmaze', self)
        if season_pack:
            lookup = api_tvmaze.season_lookup
            log.debug('Searching api_tvmaze for season')
        else:
            log.debug('Searching api_tvmaze for episode')
            lookup = api_tvmaze.episode_lookup

        for k, v in list(kwargs.items()):
            if v:
                log.debug('%s: %s', k, v)

        try:
            entity = lookup(**kwargs)
        except LookupError as e:
            log.debug(str(e))
            return
        if entity and entity.airdate:
            log.debug('received air-date: %s', entity.airdate)
            return entity.airdate
        return
Beispiel #43
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)
Beispiel #44
0
 def test_split_year_title_year(self):
     movie = 'The Matrix 1999'
     expected = 'The Matrix', 1999
     assert split_title_year(movie) == expected