Exemplo n.º 1
0
def save_episode(lookup, path, genres, source_type):
    try:
        tvshow = TVShow.get(media_id=lookup.media_id)
    except TVShow.DoesNotExist:
        tvshow = TVShow.create(media_id=lookup.media_id, title=lookup.title, year=lookup.year, type=source_type)
        if genres:
            tvshow.add_genres(genres)
    else:
        tvshow.watched = False
        if tvshow.is_dirty():
            tvshow.save()

    TVShowEpisode.create(season=lookup.season, episode=lookup.episode, path=path, show=tvshow)
Exemplo n.º 2
0
    def ws_play_season(self, id, season, append=False):
        # FIXME: would be great if it was configurable to play the whole season or only unwatched
        query = (
            TVShowEpisode.select(TVShowEpisode.path)
            .join(TVShow)
            .where(TVShow.media_id == id, TVShowEpisode.season == season)
            .order_by(TVShowEpisode.episode)
        )
        paths = [tv.path for tv in query]

        first = True
        for path in paths:
            log.debug("queuing {}", path)
            if first:
                self.player.play(path, append=append)
                append = True
                first = False
            else:
                self.player.play(path, append=append)
Exemplo n.º 3
0
def get_movie_or_tv_show(path):
    try:
        media = TVShowEpisode.select().where(TVShowEpisode.path == path).get()
    except TVShowEpisode.DoesNotExist:
        media = Movie.select().where(Movie.path == path).get()
    return media
Exemplo n.º 4
0
def catalog_videos(database, source, max_lookups):
    from aesop.processor.movie import MovieLookup
    from aesop.processor.episode import AnimeLookup, TVShowLookup

    model, lookup_model = {
        'movies': (Movie, MovieLookup),
        'tv': (TVShow, TVShowLookup),
        'anime': (TVShow, AnimeLookup),
    }[source.type]

    log.info("Cataloguing {} videos for {}", source.type, source.path)

    if model == Movie:
        query = model.select(model.path)
        known_paths = set(itertools.chain.from_iterable(m.path.split('|') for m in query))
    else:
        query = TVShowEpisode.select(TVShowEpisode.path).where(TVShowEpisode.path.startswith(source.path))
        known_paths = {m.path for m in query}

    known_video_types = set(Config.get('processor', 'video types', default='avi, mp4, mkv, ogm').replace(' ', '').split(','))

    lookups = []
    paths = []

    log.debug("Known paths {}", known_paths)

    removed = 0

    for path in set(known_paths):
        if not os.path.exists(path):
            known_paths.remove(path)
            log.info("{} does not exist, removing from database.", path)
            if model == Movie:
                Movie.delete().where(
                    (Movie.path == path) |
                    Movie.path.contains(path+'|') |
                    Movie.path.contains('|'+path)
                ).execute()
            else:
                ep = TVShowEpisode.select().where(TVShowEpisode.path == path).get()

                show = ep.show

                removed += 1

                with database_proxy.transaction():
                    ep.delete_instance()

                    if not list(show.episodes):
                        show.delete_instance()
                    else:
                        if all([episode.watched for episode in show.episodes]):
                            show.watched = True
                            if show.is_dirty():
                                show.save()

    start_time = time.time()
    successes = 0
    lookup_failures = 0

    for root, dirs, files in os.walk(source.path):
        for path in (os.path.join(root, p) for p in files):
            if '/.AppleDouble/' in path:
                log.debug('Skipping {} as it looks like an Apple double.', path)
                continue

            if os.path.basename(path).startswith('.'):
                continue

            if os.path.splitext(path)[1][1:] not in known_video_types:
                continue

            if '/sample/' in path.lower() or os.path.splitext(path)[0].lower().endswith('-sample'):
                log.debug('Skipping {} as it looks like a sample.', path)
                continue

            if path in known_paths:
                continue

            with FingersCrossedHandler(default_handler):
                try:
                    path_lookups = lookup_model.from_path(path)
                except SkipIt as e:
                    log.error("Skipping path: {} {}", path, str(e))
                except Exception as e:
                    lookup_failures += 1
                    exception = ''.join(traceback.format_exception(e.__class__, e, e.__traceback__))
                    log.error("Error retrieving information for {}: {}", path, exception)
                else:
                    lookups.extend(path_lookups)
                    paths.extend([path]*len(path_lookups))

    loop = asyncio.get_event_loop()

    log.info("{} lookups to do", len(lookups))

    for i in range(0, len(lookups), max_lookups):
        chunk = lookups[i:i+max_lookups]
        f = asyncio.gather(
                *[asyncio.async(c, loop=loop) for c in chunk],
                loop=loop, return_exceptions=True)
        completed = loop.run_until_complete(f)

        with database.transaction():
            for path, lookup in zip(paths[i:i+max_lookups], completed):
                if isinstance(lookup, SkipIt):
                    # logged earlier, no need to log now
                    lookup_failures += 1
                elif isinstance(lookup, Exception):
                    lookup_failures += 1
                    exception = ''.join(traceback.format_exception(lookup.__class__, lookup, lookup.__traceback__))

                    log.error("Error retrieving information for {}: {}", path, exception)
                else:
                    genres = [Genre.get_or_create(text=g) for g in lookup.genres]
                    if source.type == 'movies':
                        save_movie(lookup, path, genres)
                    else:
                        save_episode(lookup, path, genres, source.type)

                    successes += 1
    end_time = time.time()

    log.info("Took {:.2f} seconds to do {} lookups", end_time - start_time, len(lookups))
    log.info("{} lookups failed", lookup_failures)

    return successes, lookup_failures, removed