예제 #1
0
def download_m3u8(url, filepath, replace=False):
    if os.path.exists(filepath) and not replace:
        outputs.warning_info('File already downloaded, skipping.')
        return
    part_file = f'{filepath}.part'
    media = m3u8.load(url)
    total = len(media.segments)
    with open(part_file, 'wb') as writer:
        c = pycurl.Curl()
        curl_header = [f'{k}: {v}' for k, v in config.down_headers.items()]
        c.setopt(pycurl.HTTPHEADER, curl_header)
        c.setopt(pycurl.WRITEDATA, writer)
        try:
            for i, f in enumerate(media.segments):
                uri = f.absolute_uri
                c.setopt(pycurl.URL, uri)
                c.perform()
                outputs.normal_info('\rDownloaded :',
                                    f'{(i+1)*100//total}% ({i+1} of {total})',
                                    end="")
            c.close()
        except (KeyboardInterrupt, pycurl.error) as e:
            c.close()
            raise SystemExit(f"Download Failed {e}")
    outputs.normal_info()
    os.rename(part_file, filepath)
예제 #2
0
def anime_log(args):
    log_args = dict()
    if len(args) == 0:
        pass
    elif args[0].isnumeric():
        log_args["number"] = int(args[0])
    else:
        log_args["pattern"] = re.compile(args[0])
        if len(args) == 2:
            log_args["number"] = int(args[1])
    logs = utils.read_log(**log_args)
    ongoing = utils.read_log(logfile=config.ongoingfile)
    if len(logs) == 0:
        if len(args) == 0:
            outputs.warning_info("No log entries found.")
        else:
            outputs.prompt_val("Log entries not found for arguments", args[0],
                               "error")
        return
    outputs.bold_info("Watched\t\tAnime Name")
    for k, log in logs.items():
        outputs.normal_info(utils.Log(log).show(), end=" ")
        if k in ongoing:
            outputs.warning_tag("TRACKED", end="")
        outputs.normal_info()
예제 #3
0
def download_file(url, filepath, replace=False):
    if os.path.exists(filepath) and not replace:
        outputs.warning_info('File already downloaded, skipping.')
        return
    part_file = f'{filepath}.part'

    c = pycurl.Curl()
    c.setopt(pycurl.URL, url)
    c.setopt(pycurl.NOPROGRESS, 0)

    curl_header = [f'{k}: {v}' for k, v in config.down_headers.items()]

    if os.path.exists(part_file) and not replace:
        outputs.normal_info('Previously Downloaded part found.')
        wmode = 'ab'
        curl_header.append(
            config.resume_t.substitute(size=os.path.getsize(part_file)))
    else:
        wmode = 'wb'
    c.setopt(pycurl.HTTPHEADER, curl_header)
    try:
        with open(part_file, wmode) as writer:
            c.setopt(pycurl.WRITEDATA, writer)
            c.perform()
            c.close()
    except (KeyboardInterrupt, pycurl.error) as e:
        c.close()
        outputs.error_info(f"Download Failed {e}")
        raise SystemExit

    os.rename(part_file, filepath)
예제 #4
0
def save_anime(args):
    """Put the anime into watch later list."""
    anime_name, eps = read_args(args)
    watched = utils.read_log(anime_name)
    if watched:
        watched_eps = utils.extract_range(utils.Log(watched).eps)
    else:
        watched_eps = []
    save_eps = set(eps).difference(set(watched_eps))
    if not save_eps:
        outputs.warning_info('Already watched the provided episodes.')
        return
    utils.write_log(anime_name,
                    utils.compress_range(save_eps),
                    append=True,
                    logfile=config.watchlaterfile)
예제 #5
0
def track_anime(args):
    """Put an anime into the track list"""
    anime_name = read_args(args, episodes=False)
    watched_episodes = utils.read_log(anime_name)
    if watched_episodes is None:
        outputs.warning_info(
            'Log entry not found. Setting only new episodes for tracking.')
        _, episodes = read_args(args)
        episodes = utils.compress_range(episodes)
    else:
        outputs.prompt_val(f'Watched', watched_episodes, 'success')
        episodes = watched_episodes
    utils.write_log(anime_name,
                    episodes,
                    append=False,
                    logfile=config.ongoingfile)
예제 #6
0
def track_anime(args):
    """Put an anime into the track list"""
    anime_name, episodes = read_args(args, episodes=False)
    log = utils.read_log(anime_name)
    if log is None:
        outputs.warning_info(
            "Log entry not found.")
        if not episodes:
            _, episodes = read_args(args)
        episodes = utils.compress_range(episodes)
    else:
        episodes = utils.Log(log).eps
        outputs.prompt_val("Watched", episodes, "success")
    utils.write_log(anime_name,
                    episodes,
                    append=False,
                    logfile=config.ongoingfile)
예제 #7
0
def stream_from_url(url, anime_name=None, episode=None, *, local=False):
    if not anime_name or not episode:
        anime_name, episode = anime_source_module.parse_url(url)
    if local:
        durl = url
        _, ext = os.path.splitext(durl)
    else:
        outputs.normal_info("Getting Streaming Link:", url)
        durl, ext = anime_source_module.get_direct_video_url(url)
        if not durl:
            outputs.error_info("Url for the file not found")
            raise SystemExit
    outputs.prompt_val("Stream link", durl, "success")
    try:
        if config.ext_player_confirm:
            choice = input(f"Open {config.ext_player} Player? <Y/n>")
            if choice == "" or choice.lower() == "y":
                pass
            else:
                raise SystemExit
        else:
            for i in range(11):
                outputs.normal_info(
                    f"\rOpening External Player in: {1-i/10:1.1f} sec.",
                    end="")
                time.sleep(0.1)
            outputs.normal_info()
        retval = player_module.play_media(
            durl, title=f"ANIME:{anime_name}:ep-{episode}{ext}")
        if retval:
            utils.write_log(anime_name, episode)
            utils.update_tracklist(anime_name, episode)
            utils.write_cache(anime_name)
            utils.update_watchlater(anime_name, episode)
            return
    except KeyboardInterrupt:
        outputs.warning_info("\nInturrupted, Exiting...")
        raise SystemExit
    outputs.normal_info()
예제 #8
0
def read_args(args, episodes=True, verbose=True):
    if len(args) == 0:
        name = utils.read_cache()
    elif len(args) == 1 and args[0].isnumeric():
        name = utils.read_cache(int(args[0]))
        if verbose:
            outputs.prompt_val("Name", name)
    elif "/" in args[0]:
        name = args[0].strip("/").split("/")[-1]
    else:
        name = anime_source_module.process_anime_name(args[0].strip('"'))
        if not anime_source_module.verify_anime_exists(name):
            outputs.prompt_val("Anime with the name doesn't exist", args[0],
                               "error")
            raise SystemExit

    if not name:
        outputs.error_info("Numbers choice invalid, or invalid context.")
        raise SystemExit

    if len(args) <= 1:
        if episodes:
            if verbose:
                outputs.warning_info("Episodes range not given defaulting to all")
            available_rng = anime_source_module.get_episodes_range(
                anime_source_module.get_anime_url(name))
            if verbose:
                outputs.prompt_val("Available episodes", available_rng)
            eps = utils.extract_range(available_rng)
        else:
            eps = None
    elif len(args) == 2:
        eps = utils.extract_range(args[1])
    else:
        outputs.error_info("Too many arguments.\n")
        outputs.normal_info(__doc__)
        raise SystemExit
    return name, eps
예제 #9
0
def stream_from_url(url, anime_name=None, episode=None):
    if not anime_name or not episode:
        anime_name, episode = gogoanime.parse_gogo_url(url)
    outputs.normal_info('Getting Streaming Link:', url)
    durl, ext = gogoanime.get_direct_video_url(url)
    if not durl:
        outputs.error_info('Url for the file not found')
        raise SystemExit
    if ext == 'm3u8':
        durl = utils.get_m3u8_stream(durl)
    outputs.prompt_val(f'Stream link', durl, 'success')
    try:
        for i in range(11):
            outputs.normal_info(
                f'\rOpening External Player in: {1-i/10:1.1f} sec.', end='')
            time.sleep(0.1)
    except KeyboardInterrupt:
        outputs.warning_info('\nInturrupted, Exiting...')
        raise SystemExit
    outputs.normal_info()
    while True:
        t1 = time.time()
        ret_val = subprocess.call(" ".join(config.ext_player_command + [durl]),
                                  shell=True)
        if ret_val == 2:  # mpv error code
            outputs.error_info('Couldn\'t open the stream.')
            if input("retry?<Y/n>") == '':
                continue
            else:
                raise SystemExit
        if (time.time() - t1) > (
                5 * 60
        ):  # 5 minutes watchtime at least, otherwise consider it unwatched.
            # TODO: use direct communication with mpv to know if episode was watched.
            utils.write_log(anime_name, episode)
            utils.update_tracklist(anime_name, episode)
            utils.write_cache(anime_name)
        return
예제 #10
0
def read_args(args, episodes=True, verbose=True):
    if len(args) == 0:
        name = utils.read_cache()
    elif args[0].isnumeric():
        name = utils.read_cache(int(args[0]))
        if verbose:
            outputs.prompt_val('Name', name)
    elif '/' in args[0]:
        name = args[0].strip('/').split('/')[-1]
    else:
        name = gogoanime.process_anime_name(args[0])
        if not gogoanime.verify_anime_exists(name):
            outputs.prompt_val(f'Anime with the name doesn\'t exist', args[0],
                               'error')
            raise SystemExit

    if not name:
        outputs.error_info('Numbers choice invalid, or invalid context.')
        raise SystemExit

    if not episodes:
        return name
    if len(args) <= 1:
        if verbose:
            outputs.warning_info('Episodes range not given defaulting to all')
        available_rng = gogoanime.get_episodes_range(
            gogoanime.get_anime_url(name))
        if verbose:
            outputs.prompt_val('Available episodes', available_rng)
        episodes = utils.extract_range(available_rng)
    elif len(args) == 2:
        episodes = utils.extract_range(args[1])
    else:
        outputs.error_info('Too many arguments.\n')
        outputs.normal_info(__doc__)
        raise SystemExit
    return name, episodes
예제 #11
0
def list_local_episodes(args):
    in_dict = utils.get_local_episodes(*args)
    out_dict = dict()
    for anime, eps in in_dict.items():
        new_eps = utils.compress_range(utils.extract_range(eps))
        if new_eps != "":
            out_dict[anime] = new_eps
    empties = set(in_dict).difference(set(out_dict))
    if len(out_dict) == 0:
        outputs.warning_info("No local entries found.")
    else:
        outputs.bold_info("Episodes\tAnime Name")
        for k, v in out_dict.items():
            outputs.normal_info(f"{v}\t\t{k}")
    if len(empties) > 0:
        outputs.warning_info("Directories without Episodes:")
        outputs.warning_info(", ".join(empties))