Beispiel #1
0
class TMDBMovie(TMDBContainer, Base):

    __tablename__ = 'tmdb_movies'

    id = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
    updated = Column(DateTime, default=datetime.now, nullable=False)
    popularity = Column(Integer)
    translated = Column(Boolean)
    adult = Column(Boolean)
    language = Column(String)
    original_name = Column(Unicode)
    name = Column(Unicode)
    alternative_name = Column(Unicode)
    movie_type = Column(String)
    imdb_id = Column(String)
    url = Column(String)
    votes = Column(Integer)
    rating = Column(Float)
    certification = Column(String)
    overview = Column(Unicode)
    runtime = Column(Integer)
    tagline = Column(Unicode)
    budget = Column(Integer)
    revenue = Column(Integer)
    homepage = Column(String)
    trailer = Column(String)
    _released = Column('released', DateTime)
    released = text_date_synonym('_released')
    year = year_property('released')
    posters = relation('TMDBPoster',
                       backref='movie',
                       cascade='all, delete, delete-orphan')
    genres = relation('TMDBGenre', secondary=genres_table, backref='movies')
Beispiel #2
0
class TMDBMovie(TMDBContainer, Base):
    __tablename__ = 'tmdb_movies'

    id = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
    updated = Column(DateTime, default=datetime.now, nullable=False)
    popularity = Column(Integer)
    translated = Column(Boolean)
    adult = Column(Boolean)
    language = Column(String)
    original_name = Column(Unicode)
    name = Column(Unicode)
    alternative_name = Column(Unicode)
    movie_type = Column(String)
    imdb_id = Column(String)
    url = Column(String)
    votes = Column(Integer)
    rating = Column(Float)
    certification = Column(String)
    overview = Column(Unicode)
    runtime = Column(Integer)
    tagline = Column(Unicode)
    budget = Column(Integer)
    revenue = Column(Integer)
    homepage = Column(String)
    trailer = Column(String)
    _released = Column('released', DateTime)
    released = text_date_synonym('_released')
    year = year_property('released')
    posters = relation('TMDBPoster', backref='movie', cascade='all, delete, delete-orphan')
    genres = relation('TMDBGenre', secondary=genres_table, backref='movies')

    def update_from_object(self, update_object):
        try:
            TMDBContainer.update_from_object(self, update_object)
            self.translated = len(update_object.translations) > 0
            if len(update_object.languages) > 0:
                self.language = update_object.languages[0].code # .code or .name ?
            self.original_name = update_object.originaltitle
            self.name = update_object.title
            try:
                if len(update_object.alternate_titles) > 0:
                    # maybe we could choose alternate title from movie country only
                    self.alternative_name = update_object.alternate_titles[0].title
            except UnicodeEncodeError:
                # Bug in tmdb3 library, see #2437. Just don't set alternate_name when it fails
                pass
            self.imdb_id = update_object.imdb
            self.url = update_object.homepage
            self.rating = update_object.userrating
            if len(update_object.youtube_trailers) > 0:
                self.trailer = update_object.youtube_trailers[0].source # unicode: ooNSm6Uug3g
            elif len(update_object.apple_trailers) > 0:
                self.trailer = update_object.apple_trailers[0].source
            self.released = update_object.releasedate
        except tmdb3.TMDBError as e:
            raise LookupError('Error updating data from tmdb: %s' % e)
Beispiel #3
0
class ReleaseDate(Base):
    __tablename__ = 'rottentomatoes_releasedates'

    db_id = Column(Integer, primary_key=True)
    movie_id = Column(Integer, ForeignKey('rottentomatoes_movies.id'))
    name = Column(String)
    date = text_date_synonym('_date')
    _date = Column('date', DateTime)

    def __init__(self, name, date):
        self.name = name
        self.date = date
Beispiel #4
0
class TVDBSeries(TVDBContainer, Base):

    __tablename__ = "tvdb_series"

    id = Column(Integer, primary_key=True, autoincrement=False)
    lastupdated = Column(Integer)
    expired = Column(Boolean)
    seriesname = Column(Unicode)
    language = Column(Unicode)
    rating = Column(Float)
    status = Column(Unicode)
    runtime = Column(Integer)
    airs_time = Column(Unicode)
    airs_dayofweek = Column(Unicode)
    contentrating = Column(Unicode)
    network = Column(Unicode)
    imdb_id = Column(String)
    zap2it_id = Column(String)
    banner = Column(String)
    fanart = Column(String)
    poster = Column(String)
    poster_file = Column(Unicode)
    _genre = Column('genre', Unicode)
    genre = pipe_list_synonym('_genre')
    _firstaired = Column('firstaired', DateTime)
    firstaired = text_date_synonym('_firstaired')

    episodes = relation('TVDBEpisode',
                        backref='series',
                        cascade='all, delete, delete-orphan')

    def update(self):
        if not self.id:
            raise LookupError('Cannot update a series without a tvdb id.')
        url = get_mirror() + api_key + '/series/%s/%s.xml' % (self.id,
                                                              language)
        try:
            data = requests.get(url).content
        except RequestException, e:
            raise LookupError('Request failed %s' % url)
        result = BeautifulStoneSoup(
            data,
            convertEntities=BeautifulStoneSoup.HTML_ENTITIES).find('series')
        if result:
            self.update_from_bss(result)
        else:
            raise LookupError('Could not retrieve information from thetvdb')
Beispiel #5
0
class TVDBEpisode(TVDBContainer, Base):
    __tablename__ = 'tvdb_episodes'

    id = Column(Integer, primary_key=True, autoincrement=False)
    expired = Column(Boolean)
    lastupdated = Column(Integer)
    seasonnumber = Column(Integer)
    episodenumber = Column(Integer)
    absolute_number = Column(Integer)
    episodename = Column(Unicode)
    overview = Column(Unicode)
    _director = Column('director', Unicode)
    director = pipe_list_synonym('_director')
    _writer = Column('writer', Unicode)
    writer = pipe_list_synonym('_writer')
    _gueststars = Column('gueststars', Unicode)
    gueststars = pipe_list_synonym('_gueststars')
    rating = Column(Float)
    filename = Column(Unicode)
    _firstaired = Column('firstaired', DateTime)
    firstaired = text_date_synonym('_firstaired')

    series_id = Column(Integer, ForeignKey('tvdb_series.id'), nullable=False)

    def update(self):
        if not self.id:
            raise LookupError(
                'Cannot update an episode without an episode id.')
        url = get_mirror() + api_key + '/episodes/%s/%s.xml' % (self.id,
                                                                language)
        try:
            data = requests.get(url).content
        except RequestException as e:
            raise LookupError('Request failed %s' % url)
        result = BeautifulStoneSoup(
            data,
            convertEntities=BeautifulStoneSoup.HTML_ENTITIES).find('episode')
        if result:
            self.update_from_bss(result)
        else:
            raise LookupError('Could not retrieve information from thetvdb')

    def __repr__(self):
        return '<TVDBEpisode series=%s,season=%s,episode=%s>' %\
               (self.series.seriesname, self.seasonnumber, self.episodenumber)
Beispiel #6
0
class TVDBEpisode(Base):
    __tablename__ = 'tvdb_episodes'

    id = Column(Integer, primary_key=True, autoincrement=False)
    expired = Column(Boolean)
    last_updated = Column(Integer)
    season_number = Column(Integer)
    episode_number = Column(Integer)
    absolute_number = Column(Integer)
    name = Column(Unicode)
    overview = Column(Unicode)
    rating = Column(Float)
    director = Column(Unicode)
    _image = Column(Unicode)
    _first_aired = Column('firstaired', DateTime)
    first_aired = text_date_synonym('_first_aired')

    series_id = Column(Integer, ForeignKey('tvdb_series.id'), nullable=False)

    def __init__(self, id):
        """
        Looks up movie on tvdb and creates a new database model for it.
        These instances should only be added to a session via `session.merge`.
        """
        self.id = id
        try:
            episode = TVDBRequest().get('episodes/%s' % self.id)
        except requests.RequestException as e:
            raise LookupError('Error updating data from tvdb: %s' % e)

        self.id = episode['id']
        self.last_updated = episode['lastUpdated']
        self.season_number = episode['airedSeason']
        self.episode_number = episode['airedEpisodeNumber']
        self.absolute_number = episode['absoluteNumber']
        self.name = episode['episodeName']
        self.overview = episode['overview']
        self.director = episode['director']
        self._image = episode['filename']
        self.rating = episode['siteRating']
        self.first_aired = episode['firstAired']

    def __repr__(self):
        return '<TVDBEpisode series=%s,season=%s,episode=%s>' % \
               (self.series.name, self.season_number, self.episode_number)

    def to_dict(self):
        return {
            'id': self.id,
            'expired': self.expired,
            'last_update': self.last_updated,
            'season_number': self.season_number,
            'episode_number': self.episode_number,
            'absolute_number': self.absolute_number,
            'episode_name': self.name,
            'overview': self.overview,
            'director': self.director,
            'rating': self.rating,
            'image': self.image,
            'first_aired': self.first_aired,
            'series_id': self.series_id
        }

    @property
    def image(self):
        if self._image:
            return TVDBRequest.BANNER_URL + self._image
Beispiel #7
0
class TVDBSeries(Base):
    __tablename__ = "tvdb_series"

    id = Column(Integer, primary_key=True, autoincrement=False)
    last_updated = Column(Integer)
    expired = Column(Boolean)
    name = Column(Unicode)
    language = Column(Unicode)
    rating = Column(Float)
    status = Column(Unicode)
    runtime = Column(Integer)
    airs_time = Column(Unicode)
    airs_dayofweek = Column(Unicode)
    content_rating = Column(Unicode)
    network = Column(Unicode)
    overview = Column(Unicode)
    imdb_id = Column(Unicode)
    zap2it_id = Column(Unicode)
    _banner = Column('banner', Unicode)

    _first_aired = Column('first_aired', DateTime)
    first_aired = text_date_synonym('_first_aired')
    _aliases = Column('aliases', Unicode)
    aliases = json_synonym('_aliases')
    _actors = Column('actors', Unicode)
    actors_list = json_synonym('_actors')
    _posters = Column('posters', Unicode)
    posters_list = json_synonym('_posters')

    _genres = relation('TVDBGenre', secondary=genres_table)
    genres = association_proxy('_genres', 'name')

    episodes = relation('TVDBEpisode',
                        backref='series',
                        cascade='all, delete, delete-orphan')

    def __init__(self, tvdb_id):
        """
        Looks up movie on tvdb and creates a new database model for it.
        These instances should only be added to a session via `session.merge`.
        """
        self.id = tvdb_id

        try:
            series = TVDBRequest().get('series/%s' % self.id)
        except requests.RequestException as e:
            raise LookupError('Error updating data from tvdb: %s' % e)

        self.id = series['id']
        self.language = 'en'
        self.last_updated = series['lastUpdated']
        self.name = series['seriesName']
        self.rating = float(
            series['siteRating']) if series['siteRating'] else 0.0
        self.status = series['status']
        self.runtime = int(series['runtime']) if series['runtime'] else 0
        self.airs_time = series['airsTime']
        self.airs_dayofweek = series['airsDayOfWeek']
        self.content_rating = series['rating']
        self.network = series['network']
        self.overview = series['overview']
        self.imdb_id = series['imdbId']
        self.zap2it_id = series['zap2itId']
        self.first_aired = series['firstAired']
        self.expired = False
        self.aliases = series['aliases']
        self._banner = series['banner']
        self._genres = [TVDBGenre(
            id=name) for name in series['genre']] if series['genre'] else []

        # Actors and Posters are lazy populated
        self._actors = None
        self._posters = None

    def __repr__(self):
        return '<TVDBSeries name=%s,tvdb_id=%s>' % (self.name, self.id)

    @property
    def banner(self):
        if self._banner:
            return TVDBRequest.BANNER_URL + self._banner

    @property
    def actors(self):
        return self.get_actors()

    @property
    def posters(self):
        return self.get_posters()

    def get_actors(self):
        if not self._actors:
            log.debug('Looking up actors for series %s' % self.name)
            try:
                actors_query = TVDBRequest().get('series/%s/actors' % self.id)
                self.actors_list = [a['name'] for a in actors_query
                                    ] if actors_query else []
            except requests.RequestException as e:
                if None is not e.response and e.response.status_code == 404:
                    self.actors_list = []
                else:
                    raise LookupError('Error updating actors from tvdb: %s' %
                                      e)

        return self.actors_list

    def get_posters(self):
        if not self._posters:
            log.debug('Getting top 5 posters for series %s' % self.name)
            try:
                poster_query = TVDBRequest().get('series/%s/images/query' %
                                                 self.id,
                                                 keyType='poster')
                self.posters_list = [p['fileName'] for p in poster_query[:5]
                                     ] if poster_query else []
            except requests.RequestException as e:
                if None is not e.response and e.response.status_code == 404:
                    self.posters_list = []
                else:
                    raise LookupError('Error updating posters from tvdb: %s' %
                                      e)

        return [TVDBRequest.BANNER_URL + p for p in self.posters_list]

    def to_dict(self):
        return {
            'tvdb_id':
            self.id,
            'last_updated':
            datetime.fromtimestamp(
                self.last_updated).strftime('%Y-%m-%d %H:%M:%S'),
            'expired':
            self.expired,
            'series_name':
            self.name,
            'language':
            self.language,
            'rating':
            self.rating,
            'status':
            self.status,
            'runtime':
            self.runtime,
            'airs_time':
            self.airs_time,
            'airs_dayofweek':
            self.airs_dayofweek,
            'content_rating':
            self.content_rating,
            'network':
            self.network,
            'overview':
            self.overview,
            'imdb_id':
            self.imdb_id,
            'zap2it_id':
            self.zap2it_id,
            'banner':
            self.banner,
            'posters':
            self.posters,
            'genres': [g for g in self.genres],
            'actors':
            self.actors,
            'first_aired':
            self.first_aired,
        }
Beispiel #8
0
class TVDBSeries(TVDBContainer, Base):

    __tablename__ = "tvdb_series"

    id = Column(Integer, primary_key=True, autoincrement=False)
    lastupdated = Column(Integer)
    expired = Column(Boolean)
    seriesname = Column(Unicode)
    language = Column(Unicode)
    rating = Column(Float)
    status = Column(Unicode)
    runtime = Column(Integer)
    airs_time = Column(Unicode)
    airs_dayofweek = Column(Unicode)
    contentrating = Column(Unicode)
    network = Column(Unicode)
    imdb_id = Column(String)
    zap2it_id = Column(String)
    banner = Column(String)
    fanart = Column(String)
    poster = Column(String)
    poster_file = Column(Unicode)
    _genre = Column('genre', Unicode)
    genre = pipe_list_synonym('_genre')
    _firstaired = Column('firstaired', DateTime)
    firstaired = text_date_synonym('_firstaired')

    episodes = relation('TVDBEpisode',
                        backref='series',
                        cascade='all, delete, delete-orphan')

    def update(self):
        if not self.id:
            raise LookupError('Cannot update a series without a tvdb id.')
        url = get_mirror() + api_key + '/series/%s/%s.xml' % (self.id,
                                                              language)
        try:
            data = requests.get(url).content
        except RequestException as e:
            raise LookupError('Request failed %s' % url)
        result = BeautifulStoneSoup(
            data,
            convertEntities=BeautifulStoneSoup.HTML_ENTITIES).find('series')
        if result:
            self.update_from_bss(result)
        else:
            raise LookupError('Could not retrieve information from thetvdb')

    def get_poster(self, only_cached=False):
        """Downloads this poster to a local cache and returns the path"""
        from flexget.manager import manager
        base_dir = os.path.join(manager.config_base, 'userstatic')
        if os.path.isfile(os.path.join(base_dir, self.poster_file or '')):
            return self.poster_file
        elif only_cached:
            return
        # If we don't already have a local copy, download one.
        url = get_mirror('banner') + self.poster
        log.debug('Downloading poster %s' % url)
        dirname = os.path.join('tvdb', 'posters')
        # Create folders if the don't exist
        fullpath = os.path.join(base_dir, dirname)
        if not os.path.isdir(fullpath):
            os.makedirs(fullpath)
        filename = os.path.join(dirname, posixpath.basename(self.poster))
        thefile = file(os.path.join(base_dir, filename), 'wb')
        thefile.write(requests.get(url).content)
        self.poster_file = filename
        # If we are detached from a session, update the db
        if not Session.object_session(self):
            session = Session()
            session.query(TVDBSeries).filter(TVDBSeries.id == self.id).update(
                values={'poster_file': filename})
            session.close()
        return filename

    def __repr__(self):
        return '<TVDBSeries name=%s,tvdb_id=%s>' % (self.seriesname, self.id)
Beispiel #9
0
class TVDBSeriesSearchResult(Base):
    """
    This table will hold a single result that results from the /search/series endpoint,
    which return a series with a minimal set of parameters.
    """

    __tablename__ = 'tvdb_series_search_results'

    id = Column(Integer, primary_key=True, autoincrement=False)
    lookup_term = Column(Unicode)

    name = Column(Unicode)
    status = Column(Unicode)
    network = Column(Unicode)
    overview = Column(Unicode)

    _banner = Column('banner', Unicode)

    _first_aired = Column('first_aired', DateTime)
    first_aired = text_date_synonym('_first_aired')

    _aliases = Column('aliases', Unicode)
    aliases = json_synonym('_aliases')

    created_at = Column(DateTime)
    search_name = Column(Unicode)

    def __init__(self, series, lookup_term=None):
        self.lookup_term = lookup_term
        self.id = series['id']
        self.name = series['seriesName']
        self.first_aired = series['firstAired']
        self.network = series['network']
        self.overview = series['overview']
        self.status = series['status']
        self._banner = series['banner']
        self.aliases = series['aliases']
        self.created_at = datetime.now()

    @property
    def banner(self):
        if self._banner:
            return TVDBRequest.BANNER_URL + self._banner

    def to_dict(self):
        return {
            'aliases': [a for a in self.aliases],
            'banner': self.banner,
            'first_aired': self.first_aired,
            'tvdb_id': self.id,
            'network': self.network,
            'overview': self.overview,
            'series_name': self.name,
            'status': self.status,
        }

    @property
    def expired(self):
        logger.debug('checking series {} for expiration', self.original_name)
        if datetime.now() - self.created_at >= timedelta(
                days=SEARCH_RESULT_EXPIRATION_DAYS):
            logger.debug('series {} is expires, should re-fetch',
                         self.original_name)
            return True
        logger.debug('series {} is not expired', self.original_name)
        return False
Beispiel #10
0
class TMDBMovie(Base):
    __tablename__ = 'tmdb_movies'

    id = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
    imdb_id = Column(Unicode)
    url = Column(Unicode)
    name = Column(Unicode)
    original_name = Column(Unicode)
    alternative_name = Column(Unicode)
    _released = Column('released', DateTime)
    released = text_date_synonym('_released')
    year = year_property('released')
    certification = Column(Unicode)
    runtime = Column(Integer)
    language = Column(Unicode)
    overview = Column(Unicode)
    tagline = Column(Unicode)
    rating = Column(Float)
    votes = Column(Integer)
    popularity = Column(Integer)
    adult = Column(Boolean)
    budget = Column(Integer)
    revenue = Column(Integer)
    homepage = Column(Unicode)
    posters = relation('TMDBPoster',
                       backref='movie',
                       cascade='all, delete, delete-orphan')
    _genres = relation('TMDBGenre', secondary=genres_table, backref='movies')
    genres = association_proxy('_genres', 'name')
    updated = Column(DateTime, default=datetime.now, nullable=False)

    def __init__(self, id):
        """
        Looks up movie on tmdb and creates a new database model for it.
        These instances should only be added to a session via `session.merge`.
        """
        self.id = id
        try:
            movie = tmdb_request(
                'movie/{}'.format(self.id),
                append_to_response='alternative_titles,images')
        except requests.RequestException as e:
            raise LookupError('Error updating data from tmdb: %s' % e)
        self.imdb_id = movie['imdb_id']
        self.name = movie['title']
        self.original_name = movie['original_title']
        self.released = movie['release_date']
        self.runtime = movie['runtime']
        self.language = movie['original_language']
        self.overview = movie['overview']
        self.tagline = movie['tagline']
        self.rating = movie['vote_average']
        self.votes = movie['vote_count']
        self.popularity = movie['popularity']
        self.adult = movie['adult']
        self.budget = movie['budget']
        self.revenue = movie['revenue']
        self.homepage = movie['homepage']
        self.alternative_name = None
        try:
            self.alternative_name = movie['alternative_titles']['titles'][0][
                'title']
        except (KeyError, IndexError):
            pass  # No alternate titles
        self._genres = [TMDBGenre(**g) for g in movie['genres']]
        # Just grab the top 5 posters
        self.posters = [
            TMDBPoster(**p) for p in movie['images']['posters'][:5]
        ]
        self.updated = datetime.now()
Beispiel #11
0
class TVDBSeries(TVDBContainer, Base):
    __tablename__ = "tvdb_series"

    id = Column(Integer, primary_key=True, autoincrement=False)
    lastupdated = Column(Integer)
    expired = Column(Boolean)
    seriesname = Column(Unicode)
    language = Column(Unicode)
    rating = Column(Float)
    status = Column(Unicode)
    runtime = Column(Integer)
    airs_time = Column(Unicode)
    airs_dayofweek = Column(Unicode)
    contentrating = Column(Unicode)
    network = Column(Unicode)
    overview = Column(Unicode)
    imdb_id = Column(String)
    zap2it_id = Column(String)
    banner = Column(String)
    fanart = Column(String)
    poster = Column(String)
    poster_file = Column(Unicode)
    _genre = Column('genre', Unicode)
    genre = pipe_list_synonym('_genre')
    _firstaired = Column('firstaired', DateTime)
    firstaired = text_date_synonym('_firstaired')
    _actors = Column('actors', Unicode)
    actors = pipe_list_synonym('_actors')

    episodes = relation('TVDBEpisode',
                        backref='series',
                        cascade='all, delete, delete-orphan')

    def update(self, tvdb_id=None):
        tvdb_id = tvdb_id or self.id
        url = get_mirror() + api_key + '/series/%s/%s.xml' % (tvdb_id,
                                                              language)
        try:
            data = requests.get(url).content
        except RequestException as e:
            raise LookupError('Request failed %s' % url)
        result = ElementTree.fromstring(data).find('Series')
        if result is not None:
            self.update_from_xml(result)
        else:
            raise LookupError('Could not retrieve information from thetvdb')

    def get_poster(self, only_cached=False):
        """Downloads this poster to a local cache and returns the path"""
        from flexget.manager import manager
        base_dir = os.path.join(manager.config_base, 'userstatic')
        if os.path.isfile(os.path.join(base_dir, self.poster_file or '')):
            return self.poster_file
        elif only_cached:
            return
        # If we don't already have a local copy, download one.
        url = get_mirror('banner') + self.poster
        log.debug('Downloading poster %s', url)
        dirname = os.path.join('tvdb', 'posters')
        # Create folders if the don't exist
        fullpath = os.path.join(base_dir, dirname)
        if not os.path.isdir(fullpath):
            os.makedirs(fullpath)
        filename = os.path.join(dirname, posixpath.basename(self.poster))
        thefile = file(os.path.join(base_dir, filename), 'wb')
        thefile.write(requests.get(url).content)
        self.poster_file = filename
        # If we are detached from a session, update the db
        if not Session.object_session(self):
            with Session() as session:
                session.query(TVDBSeries).filter(
                    TVDBSeries.id == self.id).update(
                        values={'poster_file': filename})
        return filename

    def __repr__(self):
        return '<TVDBSeries name=%s,tvdb_id=%s>' % (self.seriesname, self.id)

    def to_dict(self):
        return {
            'TVDB_id':
            self.id,
            'last_updated':
            datetime.fromtimestamp(
                self.lastupdated).strftime('%Y-%m-%d %H:%M:%S'),
            'expired':
            self.expired,
            'series_name':
            self.seriesname,
            'language':
            self.language,
            'rating':
            self.rating,
            'status':
            self.status,
            'runtime':
            self.runtime,
            'airs_time':
            self.airs_time,
            'airs_dayofweek':
            self.airs_dayofweek,
            'content_rating':
            self.contentrating,
            'network':
            self.network,
            'overview':
            self.overview,
            'imdb_id':
            self.imdb_id,
            'zap2it_id':
            self.zap2it_id,
            'banner':
            self.banner,
            'fan_art':
            self.fanart,
            'poster':
            self.poster,
            'poster_file':
            self.poster_file,
            'genres':
            self.genre,
            'first_aired':
            self.firstaired,
            'actors':
            self.actors
        }