コード例 #1
0
    def getMovieData(self, movieId):
        """From a given TVDBPy movie object, return a graph containing its information."""
        m = self.tmdb.Movies(movieId)
        resp = m.info({'language': self.tmdb.lang})

        result = MemoryObjectGraph()
        movie = result.Movie(title=unicode(resp['title']))
        movie.original_title = resp['original_title']

        if resp.get('release_date'):
            movie.set(
                'year',
                datetime.datetime.strptime(resp['release_date'],
                                           '%Y-%m-%d').year)
        movie.set('genres', [unicode(g['name']) for g in resp['genres']])
        movie.set('rating', resp['vote_average'])
        movie.set('plot', [unicode(resp['overview'])])
        resp = m.credits()
        movie.set('director', [
            unicode(c['name']) for c in resp['crew'] if c['job'] == 'Director'
        ])
        movie.set(
            'writer',
            [unicode(c['name']) for c in resp['crew'] if c['job'] == 'Author'])

        try:
            movie.cast = [
                unicode(actor['name']) + ' -- ' + unicode(actor['character'])
                for actor in resp['cast']
            ]
        except KeyError:
            movie.cast = []

        return result
コード例 #2
0
ファイル: media.py プロジェクト: EQ4/smewt
def foundMetadata(query, result, link = True):
    """Return a graph that contains:
     - the only Media object found in the query graph
     - the result object linked as metadata to the previous media object

    WARNING: this functions messes with the data in the query graph, do not reuse it after
    calling this function.
    """
    # TODO: check that result is valid
    solved = MemoryObjectGraph()

    # remove the stale 'matches' link before adding the media to the resulting graph
    #query.display_graph()
    media = query.find_one(Media)
    media.matches = []
    media.metadata = []
    m = solved.add_object(media)

    if result is None:
        return solved

    if isinstance(result, list):
        result = [ solved.add_object(n, recurse = Equal.OnLiterals) for n in result ]
    else:
        result = solved.add_object(result, recurse = Equal.OnLiterals)

    #solved.display_graph()
    if link:
        m.metadata = result

    return solved
コード例 #3
0
def foundMetadata(query, result, link=True):
    """Return a graph that contains:
     - the only Media object found in the query graph
     - the result object linked as metadata to the previous media object

    WARNING: this functions messes with the data in the query graph, do not reuse it after
    calling this function.
    """
    # TODO: check that result is valid
    solved = MemoryObjectGraph()

    # remove the stale 'matches' link before adding the media to the resulting graph
    #query.display_graph()
    media = query.find_one(Media)
    media.matches = []
    media.metadata = []
    m = solved.add_object(media)

    if result is None:
        return solved

    if isinstance(result, list):
        result = [
            solved.add_object(n, recurse=Equal.OnLiterals) for n in result
        ]
    else:
        result = solved.add_object(result, recurse=Equal.OnLiterals)

    #solved.display_graph()
    if link:
        m.metadata = result

    return solved
コード例 #4
0
    def perform(self):
        query = MemoryObjectGraph()
        query.Media(filename=self.filename)
        result = self.taggerType().perform(query)

        # TODO: check that we actually found something useful
        #result.display_graph()

        # import the data into our collection
        self.collection.add_object(result.find_one(Media),
                                   recurse=Equal.OnUnique)
コード例 #5
0
    def perform(self, query):
        self.checkValid(query)

        log.debug('MovieTvdb: finding more info on %s' % u(query.find_one(Movie)))
        movie = query.find_one(Movie)

        try:
            mdprovider = TVDBMetadataProvider()
            result = mdprovider.startMovie(movie.title)
        except SmewtException:
            # movie could not be found, return a dummy Unknown movie instead so we can group them somewhere
            log.warning('Could not find info for movie: %s' % u(query.find_one(Media).filename))
            noposter = '/static/images/noposter.png'
            result = MemoryObjectGraph()
            result.Movie(title = 'Unknown', loresImage = noposter, hiresImage = noposter)

        result = foundMetadata(query, result.find_one(Movie))
        return result
コード例 #6
0
ファイル: movietmdb.py プロジェクト: EQ4/smewt
    def perform(self, query):
        self.checkValid(query)

        log.debug("MovieTvdb: finding more info on %s" % u(query.find_one(Movie)))
        movie = query.find_one(Movie)

        try:
            mdprovider = TVDBMetadataProvider()
            result = mdprovider.startMovie(movie.title)
        except SmewtException:
            # movie could not be found, return a dummy Unknown movie instead so we can group them somewhere
            log.warning("Could not find info for movie: %s" % u(query.find_one(Media).filename))
            noposter = "/static/images/noposter.png"
            result = MemoryObjectGraph()
            result.Movie(title="Unknown", loresImage=noposter, hiresImage=noposter)

        result = foundMetadata(query, result.find_one(Movie))
        return result
コード例 #7
0
ファイル: episodetvdb.py プロジェクト: cantikhuna68/smewt
    def perform(self, query):
        self.checkValid(query)
        self.query = query

        ep = query.find_one(Episode)

        log.debug('EpisodeTvdb: finding more info on %s' % ep)
        if ep.get('series') is None:
            raise SmewtException(
                "EpisodeTVDB: Episode doesn't contain 'series' field: %s" % ep)

        # little hack: if we have no season number, add 1 as default season number
        # (helps for series which have only 1 season)
        if ep.get('season') is None:
            ep.season = 1

        try:
            mdprovider = TVDBMetadataProvider()
            result = mdprovider.startEpisode(ep)

        except SmewtException:
            # series could not be found, return a dummy Unknown series instead
            # so we can group them somewhere
            log.warning('Could not find series for file: %s' %
                        query.find_one(Media).filename)
            noposter = '/static/images/noposter.png'
            result = MemoryObjectGraph()
            result.Series(title='Unknown',
                          loresImage=noposter,
                          hiresImage=noposter)

        # update the series
        query.delete_node(ep.series.node)
        ep.series = query.add_object(
            result.find_one(Series))  # this add_object should be unnecessary

        series = ep.series
        # and add all the potential episodes
        for found_ep in result.find_all(Episode):
            data = {'series': series}
            data.update(found_ep.literal_items())
            ep = query.Episode(**data)

        return query
コード例 #8
0
    def getEpisodes(self, series, language):
        """From a given TVDBPy series object, return a graph containing its information
        as well as its episodes nodes."""
        show, episodes = self.tvdb.get_show_and_episodes(series,
                                                         language=language)

        # TODO: debug to see if this is the correct way to access the series' title
        result = MemoryObjectGraph()
        smewtSeries = result.Series(title=show.name)

        for episode in episodes:
            ep = result.Episode(series=smewtSeries,
                                season=episode.season_number,
                                episodeNumber=episode.episode_number)
            ep.set('title', episode.name)
            ep.set('synopsis', episode.overview)
            ep.set('originalAirDate', str(episode.first_aired))

        return result
コード例 #9
0
ファイル: episodetvdb.py プロジェクト: EQ4/smewt
    def perform(self, query):
        self.checkValid(query)
        self.query = query

        ep = query.find_one(Episode)

        log.debug('EpisodeTvdb: finding more info on %s' % ep)
        if ep.get('series') is None:
            raise SmewtException("EpisodeTVDB: Episode doesn't contain 'series' field: %s" % ep)

        # little hack: if we have no season number, add 1 as default season number
        # (helps for series which have only 1 season)
        if ep.get('season') is None:
            ep.season = 1

        try:
            mdprovider = TVDBMetadataProvider()
            result = mdprovider.startEpisode(ep)

        except SmewtException:
            # series could not be found, return a dummy Unknown series instead
            # so we can group them somewhere
            log.warning('Could not find series for file: %s' % query.find_one(Media).filename)
            noposter = '/static/images/noposter.png'
            result = MemoryObjectGraph()
            result.Series(title = 'Unknown', loresImage=noposter, hiresImage=noposter)

        # update the series
        query.delete_node(ep.series.node)
        ep.series = query.add_object(result.find_one(Series)) # this add_object should be unnecessary

        series = ep.series
        # and add all the potential episodes
        for found_ep in result.find_all(Episode):
            data = { 'series': series }
            data.update(found_ep.literal_items())
            ep = query.Episode(**data)


        return query
コード例 #10
0
ファイル: smewtdaemon.py プロジェクト: EQ4/smewt
 def clear_keep_config(self):
     # we want to keep our config object untouched
     tmp = MemoryObjectGraph()
     tmp.add_object(self.config)
     super(VersionedMediaGraph, self).clear()
     self.add_object(tmp.find_one(Config))
コード例 #11
0
class TVDBMetadataProvider(object):
    def __init__(self):
        super(TVDBMetadataProvider, self).__init__()

        self.tvdb = thetvdbapi.TheTVDB("65D91F0290476F3E")
        self.tmdb = tmdbsimple.TMDB('a8b9f96dde091408a03cb4c78477bd14')
        self.tmdb.server_config = self.tmdb.Configuration()
        self.tmdb.server_config.info()
        self.tmdb.lang = 'en'

    @cachedmethod
    def getSeries(self, name):
        """Get the TVDBPy series object given its name."""
        results = self.tvdb.get_matching_shows(name)
        '''
        for id, name, lang in results:
            # FIXME: that doesn't look correct: either yield or no for
            return id
        raise SmewtException("EpisodeTVDB: Could not find series '%s'" % name)
        '''
        if len(results) == 0:
            raise SmewtException("EpisodeTVDB: Could not find series '%s'" %
                                 name)

        return results

    @cachedmethod
    def getEpisodes(self, series, language):
        """From a given TVDBPy series object, return a graph containing its information
        as well as its episodes nodes."""
        show, episodes = self.tvdb.get_show_and_episodes(series,
                                                         language=language)

        # TODO: debug to see if this is the correct way to access the series' title
        result = MemoryObjectGraph()
        smewtSeries = result.Series(title=show.name)

        for episode in episodes:
            ep = result.Episode(series=smewtSeries,
                                season=episode.season_number,
                                episodeNumber=episode.episode_number)
            ep.set('title', episode.name)
            ep.set('synopsis', episode.overview)
            ep.set('originalAirDate', str(episode.first_aired))

        return result

    @cachedmethod
    def getMovie(self, name):
        """Get the IMDBPy movie object given its name."""
        if not name:
            raise SmewtException(
                'You need to specify at least a probable name for the movie...'
            )
        log.debug('MovieTMDB: looking for movie %s', name)
        results = self.tmdb.Search().movie({'query': name})['results']
        for r in results:
            return r['id']

        raise SmewtException("MovieTMDB: Could not find movie '%s'" % name)

    @cachedmethod
    def getMovieData(self, movieId):
        """From a given TVDBPy movie object, return a graph containing its information."""
        m = self.tmdb.Movies(movieId)
        resp = m.info({'language': self.tmdb.lang})

        result = MemoryObjectGraph()
        movie = result.Movie(title=unicode(resp['title']))
        movie.original_title = resp['original_title']

        if resp.get('release_date'):
            movie.set(
                'year',
                datetime.datetime.strptime(resp['release_date'],
                                           '%Y-%m-%d').year)
        movie.set('genres', [unicode(g['name']) for g in resp['genres']])
        movie.set('rating', resp['vote_average'])
        movie.set('plot', [unicode(resp['overview'])])
        resp = m.credits()
        movie.set('director', [
            unicode(c['name']) for c in resp['crew'] if c['job'] == 'Director'
        ])
        movie.set(
            'writer',
            [unicode(c['name']) for c in resp['crew'] if c['job'] == 'Author'])

        try:
            movie.cast = [
                unicode(actor['name']) + ' -- ' + unicode(actor['character'])
                for actor in resp['cast']
            ]
        except KeyError:
            movie.cast = []

        return result

    def savePoster(self, posterUrl, localId):
        hiresFilename = path(smewt.dirs.user_data_dir,
                             'images',
                             '%s_hires.jpg' % localId,
                             createdir=True)

        loresFilename = path(smewt.dirs.user_data_dir, 'images',
                             '%s_lores.jpg' % localId)

        # TODO: use requests instead of urlopen
        open(hiresFilename, 'wb').write(urlopen(posterUrl).read())

        # NOTE: we do the resizing here because if we leave it to the browser,
        #       it will use a fast resampling algorithm, which will be of lower
        #       quality than what we achieve here
        # lores = 80px high
        width, height = 60, 80
        header_msg = 'Creating %dx%d screenshot' % (width, height)
        log.info('%s for %s...', header_msg, hiresFilename)
        im = Image.open(hiresFilename)
        log.debug('%s: resizing...', header_msg)
        im.thumbnail((width, height), Image.ANTIALIAS)
        log.debug('%s: saving to png...', header_msg)
        im.save(loresFilename, "PNG")
        log.debug('%s: done!', header_msg)

        return ('/user/images/%s_lores.jpg' % localId,
                '/user/images/%s_hires.jpg' % localId)

    @cachedmethod
    def getSeriesPoster(self, tvdbID):
        """Return the low- and high-resolution posters of a tvdb object."""
        noposter = '/static/images/noposter.png'

        urls = self.tvdb.get_show_image_choices(tvdbID)
        posters = [url for url in urls if url[1] == 'poster']
        if posters:
            return self.savePoster(posters[0][0], 'series_%s' % tvdbID)

        else:
            log.warning('Could not find poster for tvdb ID %s' % tvdbID)
            return (noposter, noposter)

    @cachedmethod
    def getMoviePoster(self, movieId):
        """Return the low- and high-resolution posters (if available) of an tvdb object."""
        noposter = '/static/images/noposter.png'
        resp = self.tmdb.Movies(movieId).info({'language': self.tmdb.lang})
        image_size = 'original'
        image_base = self.tmdb.server_config.images[
            'base_url'] + '/' + image_size + '/'

        if resp['poster_path']:
            return self.savePoster(image_base + resp['poster_path'],
                                   'movie_%s' % movieId)

        else:
            log.warning('Could not find poster for tmdb ID %s' % movieId)
            return (noposter, noposter)

    def startEpisode(self, episode):
        self.tmdb.lang = guiLanguage().alpha2

        if episode.get('series') is None:
            raise SmewtException(
                "TVDBMetadataProvider: Episode doesn't contain 'series' field: %s",
                episode)

        name = episode.series.title
        name = name.replace(',', ' ')

        matching_series = self.getSeries(name)

        # Try first with the languages from guessit, and then with english
        languages = tolist(episode.get('language', [])) + ['en']

        # Sort the series by id (stupid heuristic about most popular series
        #                        might have been added sooner to the db and the db id
        #                        follows the insertion order)
        # TODO: we should do something smarter like comparing series name distance,
        #       episodes count and/or episodes names
        #print '\n'.join(['%s %s --> %f [%s] %s' % (x[1], name, textutils.levenshtein(x[1], name), x[2], x[0]) for x in matching_series])
        matching_series.sort(
            key=lambda x: (textutils.levenshtein(x[1], name), int(x[0])))

        series = None
        language = 'en'
        for lang in languages:
            try:
                language = lang
                ind = zip(*matching_series)[2].index(lang)
                series = matching_series[ind][0]
                break
            except ValueError, e:
                language = matching_series[0][2]
                series = matching_series[0][0]

        # TODO: at the moment, overwrite the detected language with the one
        #       from the settings. It would be better to use the detected
        #       language if it was more reliable (see previous TODO)...
        language = guiLanguage().alpha2

        eps = self.getEpisodes(series, language)

        try:
            lores, hires = self.getSeriesPoster(series)
            eps.find_one(Series).update({
                'loresImage': lores,
                'hiresImage': hires
            })
            return eps

        except Exception, e:
            log.warning(str(e) + ' -- ' + str(textutils.toUtf8(episode)))
            return MemoryObjectGraph()