Пример #1
0
    def download_episodes(self, signal):
        self.signal = signal
        animes, anime_title = self.get_animes()
        self.progressBar.setMaximum(len(animes._episode_urls))
        download_dir = self.get_download_dir()

        for count, episode in enumerate(animes, 1):

            ep_no = episode.ep_no
            external = Config["dl"]["external_downloader"]

            if external:
                util.external_download(
                    Config["dl"]["external_downloader"],
                    episode,
                    Config["dl"]["file_format"],
                    Config["dl"]["speed_limit"],
                    path=download_dir
                )

            else:
                episode.download(force=Config["dl"]["force_download"],
                                 path=download_dir,
                                 format=Config["dl"]["file_format"],
                                 range_size=Config["dl"]["chunk_size"]
                                 )

            self.signal.emit(count)
            time.sleep(1)
Пример #2
0
def dl(ctx, anime_url, episode_range, url, player, skip_download, quality,
       force_download, log_level, download_dir, file_format, provider,
       external_downloader):
    """ Download the anime using the url or search for it.
    """

    util.setup_logger(log_level)
    util.print_info(__version__)

    cls = get_anime_class(anime_url)

    if not cls:
        anime_url = util.search(anime_url, provider)
        cls = get_anime_class(anime_url)

    try:
        anime = cls(anime_url, quality=quality)
    except Exception as e:
        echo(click.style(str(e), fg='red'))
        return

    # TODO: Refractor this somewhere else. (util?)
    if episode_range is None:
        episode_range = '1:'
    if episode_range.endswith(':'):
        episode_range += str(len(anime) + 1)
    if episode_range.startswith(':'):
        episode_range = '1' + episode_range

    logging.info('Found anime: {}'.format(anime.title))

    anime = util.split_anime(anime, episode_range)

    if url or player:
        skip_download = True

    if download_dir and not skip_download:
        logging.info('Downloading to {}'.format(os.path.abspath(download_dir)))

    for episode in anime:
        if url:
            util.print_episodeurl(episode)

        if player:
            util.play_episode(episode, player=player)

        if not skip_download:
            if external_downloader:
                logging.info('Downloading episode {} of {}'.format(
                    episode.ep_no, anime.title))
                util.external_download(external_downloader,
                                       episode,
                                       file_format,
                                       path=download_dir)
                continue

            episode.download(force=force_download,
                             path=download_dir,
                             format=file_format)
            print()
Пример #3
0
def command(ctx, anime_url, episode_range, url, player, skip_download, quality,
            force_download, download_dir, file_format, provider,
            external_downloader, chunk_size, disable_ssl, fallback_qualities,
            choice):
    """ Download the anime using the url or search for it.
    """
    util.print_info(__version__)
    # TODO: Replace by factory
    cls = get_anime_class(anime_url)

    disable_ssl = cls and cls.__name__ == 'Masterani' or disable_ssl
    session.get_session().verify = not disable_ssl

    if not cls:
        anime_url = util.search(anime_url, provider, choice)
        cls = get_anime_class(anime_url)

    anime = cls(anime_url,
                quality=quality,
                fallback_qualities=fallback_qualities)
    logger.info('Found anime: {}'.format(anime.title))

    animes = util.parse_ep_str(anime, episode_range)

    # TODO:
    # Two types of plugins:
    #   - Aime plugin: Pass the whole anime
    #   - Ep plugin: Pass each episode
    if url or player:
        skip_download = True

    if download_dir and not skip_download:
        logger.info('Downloading to {}'.format(os.path.abspath(download_dir)))

    for episode in animes:
        if url:
            util.print_episodeurl(episode)

        if player:
            util.play_episode(episode, player=player)

        if not skip_download:
            if external_downloader:
                logging.info('Downloading episode {} of {}'.format(
                    episode.ep_no, anime.title))
                util.external_download(external_downloader,
                                       episode,
                                       file_format,
                                       path=download_dir)
                continue
            if chunk_size is not None:
                chunk_size *= 1e6
                chunk_size = int(chunk_size)
            with requests_cache.disabled():
                episode.download(force=force_download,
                                 path=download_dir,
                                 format=file_format,
                                 range_size=chunk_size)
            print()
Пример #4
0
def command(ctx, anime_url, episode_range, url, player, skip_download, quality,
            force_download, download_dir, file_format, provider,
            external_downloader, chunk_size, disable_ssl, fallback_qualities, choice, skip_fillers, speed_limit):
    """ Download the anime using the url or search for it.
    """
    query = anime_url[:]

    util.print_info(__version__)
    # TODO: Replace by factory
    cls = get_anime_class(anime_url)

    disable_ssl = cls and cls.__name__ == 'Masterani' or disable_ssl
    session.get_session().verify = not disable_ssl

    if not cls:
        anime_url, _ = util.search(anime_url, provider, choice)
        cls = get_anime_class(anime_url)

    anime = cls(anime_url, quality=quality,
                fallback_qualities=fallback_qualities)
    logger.info('Found anime: {}'.format(anime.title))

    animes = util.parse_ep_str(anime, episode_range)
    if not animes:
        # Issue #508.
        raise exceptions.NotFoundError('No episodes found within index.')

    # TODO:
    # Two types of plugins:
    #   - Aime plugin: Pass the whole anime
    #   - Ep plugin: Pass each episode
    if url or player:
        skip_download = True

    if download_dir and not skip_download:
        logger.info('Downloading to {}'.format(os.path.abspath(download_dir)))
    if skip_fillers:
        fillers = util.get_filler_episodes(query)
    if speed_limit:
        logger.info("Speed is being limited to {}".format(speed_limit))
    for episode in animes:
        if skip_fillers and fillers:
            if episode.ep_no in fillers:
                logger.info("Skipping episode {} because it is a filler.".format(episode.ep_no))
                continue

        if url:
            util.print_episodeurl(episode)

        if player:
            util.play_episode(episode, player=player, title=f'{anime.title} - Episode {episode.ep_no}')

        if not skip_download:
            if external_downloader:
                logging.info('Downloading episode {} of {}'.format(
                    episode.ep_no, anime.title)
                )
                util.external_download(external_downloader, episode,
                                       file_format, speed_limit, path=download_dir)
                continue
            if chunk_size is not None:
                chunk_size *= 1e6
                chunk_size = int(chunk_size)
            with requests_cache.disabled():
                episode.download(force=force_download,
                                 path=download_dir,
                                 format=file_format,
                                 range_size=chunk_size)
            print()
Пример #5
0
def command(ctx, anime_url, episode_range, player, force_download, provider,
            skip_fillers, ratio, url, choice, download_metadata):
    """
    dl with fallback providers\n
    Will use another provider even if the chosen one fails.\n
    """

    # Borrows some config from the original dl command.
    # This can all be flags, but ezdl is made to be easy.
    fallback_qualities = Config['dl']['fallback_qualities']
    download_dir = Config['dl']['download_dir']
    quality = Config['dl']['quality']
    url = Config['dl']['url'] if not url else url
    skip_download = Config['dl']['skip_download']
    chunk_size = Config['dl']['chunk_size']
    speed_limit = Config['dl']['speed_limit']

    external_downloader = Config['dl']['external_downloader']
    file_format = Config['ezdl']['file_format']
    fallback_providers = Config['ezdl']['fallback_providers']

    query = anime_url[:]
    util.print_info(__version__)

    fallback_providers.insert(0, provider)
    # Eliminates duplicates while keeping order
    providers = sorted(set(fallback_providers), key=fallback_providers.index)

    info = animeinfo.search_anilist(query, choice)

    logger.info('Selected "{}" '.format(info.title))
    episode_count = info.episodes - 1
    # Interprets the episode range for use in a for loop.
    # 1:3 -> for _episode in range(1, 4):
    episode_range = util.parse_episode_range(episode_count, episode_range)
    episode_range_split = episode_range.split(':')
    # Issue #508.
    if episode_range_split[0] > episode_range_split[-1]:
        raise exceptions.NotFoundError('No episodes found within index.')

    # Stores the choices for each provider, to prevent re-prompting search.
    # As the current setup runs episode wise without this a 12 episode series would give 12+ prompts.
    choice_dict = {}

    # Doesn't work on nyaa since it only returns one episode.
    for episode_range in range(int(episode_range_split[0]),
                               int(episode_range_split[-1]) + 1):
        # Exits if all providers are skipped.
        if [choice_dict[i] for i in choice_dict] == [0] * len(providers):
            logger.info('All providers skipped, exiting')
            exit()

        for provider in providers:
            if not get_anime_class(provider):
                logger.info('"{}" is an invalid provider'.format(provider))
                continue

            logger.debug('Current provider: {}'.format(provider))
            # TODO: Replace by factory
            cls = get_anime_class(anime_url)

            # To make the downloads use the correct name if URL:s are used.
            real_provider = cls.sitename if cls else provider
            # This will allow for animeinfo metadata in filename and one filename for multiple providers.
            rep_dict = {
                'animeinfo_anime_title': util.slugify(info.title),
                'provider': util.slugify(real_provider),
                'anime_title': '{anime_title}',
                'ep_no': '{ep_no}'
            }
            fixed_file_format = file_format.format(**rep_dict)
            # Keeping this as I don't know the impact of removing it.
            # It's False by default in normal dl.
            disable_ssl = False
            session.get_session().verify = not disable_ssl

            # This is just to make choices in providers presistent between searches.
            choice_provider = choice_dict.get(provider)

            if not cls:
                _anime_url, choice_provider = util.search(anime_url,
                                                          provider,
                                                          val=choice_provider,
                                                          season_info=info,
                                                          ratio=ratio)
                choice_dict[provider] = choice_provider
                if choice_provider == 0 or not _anime_url:
                    logger.info('Skipped')
                    continue

                cls = get_anime_class(_anime_url)

            try:
                anime = cls(_anime_url,
                            quality=quality,
                            fallback_qualities=fallback_qualities)
            # I have yet to investigate all errors this can output
            # No sources found gives error which exits the script
            except:
                continue

            logger.debug('Found anime: {}'.format(anime.title))

            try:
                animes = util.parse_ep_str(anime, str(episode_range))
            except RuntimeError:
                logger.error(
                    'No episode found with index {}'.format(episode_range))
                continue
            except:
                logger.error('Unknown provider error')
                continue

            # TODO:
            # Two types of plugins:
            #   - Aime plugin: Pass the whole anime
            #   - Ep plugin: Pass each episode
            if url or player:
                skip_download = True

            if download_dir and not skip_download:
                logger.info('Downloading to {}'.format(
                    os.path.abspath(download_dir)))
            if skip_fillers:
                fillers = util.get_filler_episodes(query)
            for episode in animes:
                if skip_fillers and fillers:
                    if episode.ep_no in fillers:
                        logger.info(
                            "Skipping episode {} because it is a filler.".
                            format(episode.ep_no))
                        continue

                if download_metadata:
                    util.download_metadata(fixed_file_format, info.metadata,
                                           episode)

                if url:
                    util.print_episodeurl(episode)

                if player:
                    util.play_episode(
                        episode,
                        player=player,
                        title=f'{anime.title} - Episode {episode.ep_no}')

                if not skip_download:
                    if external_downloader:
                        logging.info('Downloading episode {} of {}'.format(
                            episode.ep_no, anime.title))
                        util.external_download(external_downloader,
                                               episode,
                                               fixed_file_format,
                                               path=download_dir,
                                               speed_limit=speed_limit)
                        continue
                    if chunk_size is not None:
                        chunk_size = int(chunk_size)
                        chunk_size *= 1e6
                    with requests_cache.disabled():
                        episode.download(force=force_download,
                                         path=download_dir,
                                         format=fixed_file_format,
                                         range_size=chunk_size)
                    print()

            # If it's all successfull proceeds to next ep instead of looping.
            break
Пример #6
0
def list_animes(watcher, quality, download_dir, imp=None, _filter=None):

    click.echo('Available Commands: swap, new')
    watcher.list(filt=_filter)
    inp = click.prompt('Select an anime', default="1") if not imp else imp
    provider = Config['watch']['provider']
    # Not a number as input and command
    if not str(inp).isnumeric():
        if ' ' in str(inp).strip():
            args = command_parser(str(inp))
            key = args[0].lower()
            vals = args[1:]
            if key == 'new':
                query = vals[0]
                if '--provider' in vals:
                    if vals.index('--provider') + 1 < len(vals):
                        provider = vals[vals.index('--provider') + 1]
                url, _ = util.search(query, provider)
                watcher.new(url)

            if key == 'swap':
                if vals[0] in [
                        'all', 'watching', 'completed', 'planned', 'dropped',
                        'hold'
                ]:
                    return list_animes(watcher,
                                       quality,
                                       download_dir,
                                       imp=imp,
                                       _filter=vals[0])

            return list_animes(watcher, quality, download_dir, imp=imp)
        else:
            # Exits if neither int or actual command
            sys.exit(0)

    try:
        anime = watcher.get(int(inp) - 1)
    except IndexError:
        sys.exit(0)

    # Make the selected anime first result
    watcher.update(anime)
    while True:
        click.clear()
        click.secho('Title: ' +
                    click.style(anime.title, fg='green', bold=True))
        click.echo('episodes_done: {}'.format(
            click.style(str(anime.episodes_done), bold=True, fg='yellow')))
        click.echo('Length: {}'.format(len(anime)))
        click.echo('Provider: {}'.format(anime.sitename))
        click.echo('Score: {}'.format(anime.score))
        click.echo('Watch Status: {}'.format(anime.watch_status))
        meta = ''
        for k, v in anime.meta.items():
            meta += '{}: {}\n'.format(k, click.style(str(v), bold=True))
        click.echo(meta)

        click.echo('Available Commands: set, remove, update, watch, back,'
                   ' download.\n')

        inp = click.prompt('Press q to exit', default='q').strip()

        # TODO: A better way to handle commands. Use regex. Refractor to class?
        # Decorator?
        if inp == 'q':
            sys.exit(0)
        elif inp == 'back':
            list_animes(watcher, quality, download_dir, imp=imp)
        elif inp == 'remove':
            watcher.remove(anime)
            list_animes(watcher, quality, download_dir, imp=imp)
        elif inp == 'update':
            watcher.update_anime(anime)
        elif inp == 'watch':
            anime.quality = quality
            watch_anime(watcher, anime, quality, download_dir)
        elif inp.startswith('watch '):
            anime.quality = quality
            watch_anime(watcher,
                        anime,
                        quality,
                        download_dir,
                        player_class=inp.split('watch ')[-1])

        elif inp.startswith('download'):
            # You can use download 3:10 for selected episodes
            try:
                inp = inp.split('download ')[1]
            except IndexError:
                inp = ':'
            animes = util.parse_ep_str(anime, inp)

            # Using the config from dl.
            if not download_dir:
                download_dir = Config['dl']['download_dir']
            # These things could be flags.
            external_downloader = Config['dl']['external_downloader']
            file_format = Config['dl']['file_format']
            speed_limit = Config['dl']['speed_limit']

            for episode in animes:
                util.external_download(external_downloader,
                                       episode,
                                       file_format,
                                       speed_limit,
                                       path=download_dir)

        elif inp.startswith('set '):
            inp = inp.split('set ')[-1]
            key, val = [v.strip() for v in inp.split('=')]
            key = key.lower()

            if key == 'title':
                watcher.remove(anime)
                setattr(anime, key, val)
                watcher.add(anime)

            elif key == 'episodes_done':
                # Retries if invalid input.
                if not val.isnumeric():
                    # Uncomment this if you want to let the user know.
                    #logger.error("Invalid integer")
                    # input()
                    continue
                # Prevents setting length above max amount of episodes.
                val = val if int(val) <= len(anime) else len(anime)
                setattr(anime, key, int(val))
                watcher.update(anime)

            elif key == 'provider':
                # Checks if it's an invalid provider preventing errors.
                if not get_anime_class(val):
                    # Probably good to list providers here before looping.
                    continue
                # Watch can quit if no anime is found, not ideal.
                url, _ = util.search(anime.title, val)
                watcher.remove(anime)
                newanime = watcher.new(url)
                newanime.episodes_done = anime.episodes_done
                newanime.score = anime.score
                newanime.watch_status = anime.watch_status
                newanime._timestamp = anime._timestamp
                watcher.update(newanime)
                anime = newanime

            elif key == 'score':
                anime.score = val
                watcher.update(anime)

            elif key == 'watch_status':
                if val in [
                        'watching', 'completed', 'dropped', 'planned', 'all'
                ]:
                    colours = {
                        'watching': 'cyan',
                        'completed': 'green',
                        'dropped': 'red',
                        'planned': 'yellow',
                        'hold': 'white'
                    }
                    anime.watch_status = val
                    anime.colours = colours.get(anime.watch_status, 'yellow')
                    watcher.update(anime)
Пример #7
0
def command(ctx, anime_url, episode_range, url, player, skip_download, quality,
            force_download, download_dir, file_format, provider,
            external_downloader, chunk_size, disable_ssl, fallback_qualities,
            choice, skip_fillers, speed_limit, sub, dub):
    """ Download the anime using the url or search for it.
    """
    """if episode_range:
        regexed_range = re.compile("^:?(\d+)?:?(\d+)?$").search(episode_range)
        # Prevent such cases as: :5: and :1:1
        if not regexed_range or (len(regexed_range.groups()) >= episode_range.count(":") and episode_range.count(":") != 1):
            raise click.UsageError(
                "Invalid value for '--episode' / '-e': {} is not a valid range".format(episode_range))
"""
    if sub and dub:
        raise click.UsageError(
            "--dub/-d and --sub/-s flags cannot be used together")

    query = anime_url[:]

    util.print_info(__version__)
    # TODO: Replace by factory
    cls = get_anime_class(anime_url)

    disable_ssl = cls and cls.__name__ == 'Masterani' or disable_ssl
    session.get_session().verify = not disable_ssl

    if not cls:
        anime_url, _ = util.search(anime_url, provider, choice)
        cls = get_anime_class(anime_url)

    subbed = None

    if sub or dub:
        subbed = subbed is not None

    anime = cls(anime_url,
                quality=quality,
                fallback_qualities=fallback_qualities,
                subbed=subbed)
    logger.info('Found anime: {}'.format(anime.title))

    animes = util.parse_ep_str(anime, episode_range)
    if not animes:
        # Issue #508.
        raise exceptions.NotFoundError('No episodes found within index.')

    # TODO:
    # Two types of plugins:
    #   - Aime plugin: Pass the whole anime
    #   - Ep plugin: Pass each episode
    if url or player:
        skip_download = True

    if download_dir and not skip_download:
        logger.info('Downloading to {}'.format(os.path.abspath(download_dir)))
    if skip_fillers:
        fillers = util.get_filler_episodes(query)
    if speed_limit:
        logger.info("Speed is being limited to {}".format(speed_limit))
    for episode in animes:
        if skip_fillers and fillers:
            if episode.ep_no in fillers:
                logger.info(
                    "Skipping episode {} because it is a filler.".format(
                        episode.ep_no))
                continue

        if url:
            util.print_episodeurl(episode)

        if player:
            util.play_episode(episode,
                              player=player,
                              title=f'{anime.title} - Episode {episode.ep_no}')

        if not skip_download:
            if external_downloader:
                logging.info('Downloading episode {} of {}'.format(
                    episode.ep_no, anime.title))
                util.external_download(external_downloader,
                                       episode,
                                       file_format,
                                       speed_limit,
                                       path=download_dir)
                continue
            if chunk_size is not None:
                chunk_size *= 1e6
                chunk_size = int(chunk_size)
            with requests_cache.disabled():
                episode.download(force=force_download,
                                 path=download_dir,
                                 format=file_format,
                                 range_size=chunk_size)
            print()
Пример #8
0
def dl(ctx, anime_url, episode_range, url, player, skip_download, quality,
       force_download, log_level, download_dir, file_format, provider,
       external_downloader, chunk_size, disable_ssl, fallback_qualities):
    """ Download the anime using the url or search for it.
    """

    util.setup_logger(log_level)
    util.print_info(__version__)

    cls = get_anime_class(anime_url)

    disable_ssl = cls and cls.__name__ == 'Masterani' or disable_ssl
    session.get_session().verify = not disable_ssl

    if not cls:
        anime_url = util.search(anime_url, provider)
        cls = get_anime_class(anime_url)

    try:
        anime = cls(anime_url,
                    quality=quality,
                    fallback_qualities=fallback_qualities)
    except Exception as e:
        if log_level != 'DEBUG':
            echo(click.style(str(e), fg='red'))
        else:
            raise
        return

    logging.info('Found anime: {}'.format(anime.title))

    anime = util.parse_ep_str(anime, episode_range)

    if url or player:
        skip_download = True

    if download_dir and not skip_download:
        logging.info('Downloading to {}'.format(os.path.abspath(download_dir)))

    for episode in anime:
        if url:
            util.print_episodeurl(episode)

        if player:
            util.play_episode(episode, player=player)

        if not skip_download:
            if external_downloader:
                logging.info('Downloading episode {} of {}'.format(
                    episode.ep_no, anime.title))
                util.external_download(external_downloader,
                                       episode,
                                       file_format,
                                       path=download_dir)
                continue
            if chunk_size is not None:
                chunk_size *= 1e6
                chunk_size = int(chunk_size)
            episode.download(force=force_download,
                             path=download_dir,
                             format=file_format,
                             range_size=chunk_size)
            print()