예제 #1
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()
예제 #2
0
def set_geometry(value):
    if re.match(r'^([0-9]+-?)+$', value):
        config.geometry = value
        config.compile_ext_player_command()
    else:
        outputs.prompt_val('Incorrect Argument', value, 'error')
    outputs.prompt_val('External Player command',
                       " ".join(config.ext_player_command))
예제 #3
0
def play_local_anime(args):
    name, episodes = read_args(args)
    for e in episodes:
        path = utils.get_episode_path(name, e, check=True)
        if not path:
            outputs.prompt_val("File not found locally", f"{name}:ep-{e}",
                               "error")
            continue
        stream_from_url(path, name, e, local=True)
예제 #4
0
def set_quality(quality):
    if quality.isnumeric():
        config.video_quality = int(quality)
    elif quality.isalnum():
        if re.match(r"[0-9]+p", quality):
            config.video_quality = int(quality[:-1])
        else:
            outputs.prompt_val("Invalid quality format", quality, "error")
    else:
        outputs.normal_info(f"Current quality: {quality}")
예제 #5
0
def set_quality(quality):
    if quality.isnumeric():
        config.QUALITY_PREFERENCE = int(quality)
    elif quality.isalnum():
        if re.match(r'[0-9]+p', quality):
            config.QUALITY_PREFERENCE = int(quality[:-1])
        else:
            outputs.prompt_val('Invalid quality format', quality, 'error')
    else:
        outputs.normal_info(f'Current quality: {quality}')
예제 #6
0
def toggle_fullscreen(value):
    if value.lower() in ['on', 'yes']:
        config.fullscreen = True
        config.compile_ext_player_command()
    elif value.lower() in ['off', 'no']:
        config.fullscreen = False
        config.compile_ext_player_command()
    else:
        outputs.prompt_val('Incorrect Argument', value, 'error')
    outputs.prompt_val('External Player command',
                       " ".join(config.ext_player_command))
예제 #7
0
def set_geometry(value):
    if re.match(r"^([0-9]+-?)+$", value):
        player_module.geometry = value
        player_module.compile_command(
            flags=config.ext_player_flags,
            fullscreen=config.ext_player_fullscreen
        )
    else:
        outputs.prompt_val("Incorrect Argument", value, "error")
    outputs.prompt_val("External Player command",
                       " ".join(player_module.player_command))
예제 #8
0
def continue_play(args):
    name, episodes = read_args(args)
    watched = utils.read_log().get(name)
    outputs.prompt_val('Watched', watched, 'success')
    if not watched:
        last = 0
    else:
        last = int(watched.split('-')[-1])
    play_anime(
        [name,
         utils.compress_range(filter(lambda e: e > last, episodes))])
예제 #9
0
def list_episodes(args):
    name = read_args(args, episodes=False)
    available_rng = gogoanime.get_episodes_range(gogoanime.get_anime_url(name))
    if len(args) == 2:
        _, episodes = read_args(args)
        eps = set(episodes)
        avl_eps = set(utils.extract_range(available_rng))
        res = eps.intersection(avl_eps)
        available_rng = utils.compress_range(res)
    outputs.prompt_val(f'Available episodes', available_rng)
    outputs.prompt_val(f'Watched episodes', utils.read_log(name), 'success')
    utils.write_cache(name)
예제 #10
0
def list_episodes(args):
    name, _ = read_args(args, episodes=False)
    available_rng = anime_source_module.get_episodes_range(anime_source_module.get_anime_url(name))
    if len(args) == 2:
        _, episodes = read_args(args)
        eps = set(episodes)
        avl_eps = set(utils.extract_range(available_rng))
        res = eps.intersection(avl_eps)
        available_rng = utils.compress_range(res)
    outputs.prompt_val("Available episodes", available_rng)
    log = utils.Log(utils.read_log(name))
    outputs.prompt_val("Watched episodes", log.eps, "success", end=' ')
    outputs.normal_info(log.last_updated_fmt)
    utils.write_cache(name)
예제 #11
0
def read_cache(num=1, complete=False):
    if not os.path.exists(config.cachefile):
        return list() if complete else None
    else:
        with open(config.cachefile, 'r') as r:
            lines = r.readlines()
        if complete:
            return list(map(lambda l: l.strip(), lines))
        else:
            try:
                return lines[num - 1].strip()
            except IndexError:
                outputs.error_info("The choice number is too large.")
                outputs.prompt_val("Total items in cache", len(lines), 'error')
                raise SystemExit
예제 #12
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)
예제 #13
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)
예제 #14
0
def toggle_fullscreen(value):
    if value.lower() in ["on", "yes", "true"]:
        config.ext_player_fullscreen = True
        anime_source_module.compile_command(
            flags=config.ext_player_flags,
            fullscreen=True
        )
    elif value.lower() in ["off", "no", "false"]:
        config.ext_player_fullscreen = False
        anime_source_module.compile_command(
            flags=config.ext_player_flags,
            fullscreen=False
        )
    else:
        outputs.prompt_val("Incorrect Argument", value, "error")
    outputs.prompt_val("External Player command",
                       " ".join(config.ext_player_command))
예제 #15
0
def download_from_url(url, anime_name=None, episode=None):
    if not anime_name or not episode:
        anime_name, episode = anime_source_module.parse_url(url)
    os.makedirs(os.path.join(config.anime_dir, f"./{anime_name}"),
                exist_ok=True)
    outputs.prompt_val("Downloading", 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
    if ext == ".m3u8":
        utils.download_m3u8(
            durl, utils.get_episode_path(anime_name, episode, make=True))
    else:
        utils.download_file(
            durl,
            utils.get_episode_path(anime_name, episode, ext=ext, make=True))
예제 #16
0
def check_anime(args):
    name, episodes = read_args(args)
    unavail_eps = []
    for e in episodes:
        url = anime_source_module.get_episode_url(name, e)
        outputs.normal_info("Testing:", url)
        durl, ext = anime_source_module.get_direct_video_url(url)
        if not durl:
            raise SystemExit("Url for the file not found")
        if not os.path.exists(
                os.path.join(config.anime_dir, f"./{name}/ep{e:02d}.{ext}")):
            unavail_eps.append(e)
    if len(unavail_eps) == 0:
        outputs.success_info(
            "All episodes in given range are locally available")
    else:
        outputs.prompt_val("Missing episodes",
                           utils.compress_range(unavail_eps), "warning")
예제 #17
0
def get_updates(anime_name=''):
    """Check and display the updates on the tracked anime list."""
    updates = anime_updates(anime_name)
    if len(updates) == 0:
        outputs.normal_info("No new episodes released.")
        return
    if anime_name == '':
        outputs.prompt_val(f'anime(s) has new episodes.',
                           len(updates),
                           'success',
                           sep=" ",
                           reverse=True)
        outputs.normal_info('-' * 50)
    for anime, episodes in updates.items():
        outputs.normal_info(anime, end='\n\t')
        outputs.success_tag(len(episodes), end=' ')
        outputs.prompt_val('new episodes', utils.compress_range(episodes),
                           'success')
예제 #18
0
def check_anime(args):
    name, episodes = read_args(args)
    unavail_eps = []
    for e in episodes:
        url = gogoanime.get_episode_url(name, e)
        outputs.normal_info('Testing:', url)
        durl, ext = gogoanime.get_direct_video_url(url)
        if not durl:
            raise SystemExit('Url for the file not found')
        if not os.path.exists(
                os.path.join(config.anime_dir, f'./{name}/ep{e:02d}.{ext}')):
            unavail_eps.append(e)
    if len(unavail_eps) == 0:
        outputs.success_info(
            'All episodes in given range are locally available')
    else:
        outputs.prompt_val('Missing episodes',
                           utils.compress_range(unavail_eps), 'warning')
예제 #19
0
def extract_range(range_str):
    if range_str is None or range_str.strip() == '':
        return iter()
    ranges = range_str.split(',')
    try:
        for r in ranges:
            if '-' in r:
                rng = r.split('-')
                if len(rng) > 2:
                    outputs.prompt_val('Incorrect formatting', r, 'error')
                    raise SystemExit
                yield from range(int(rng[0]), int(rng[1]) + 1)
            else:
                yield int(r)
    except ValueError as e:
        outputs.error_info(f'Incorrect formatting: use integers for episodes')
        outputs.error_tag(e)
        raise SystemExit
예제 #20
0
def continue_play(args, play_func=play_anime):
    name, _ = read_args(args, episodes=False)
    log = utils.Log(utils.read_log().get(name))
    watch_later = utils.read_log(name, logfile=config.watchlaterfile)
    if watch_later:
        episodes = utils.extract_range(utils.Log(watch_later).eps)
    else:
        _, episodes = read_args(args)
    outputs.prompt_val("Watched",
                       log._eps, "success", end='\t')
    outputs.normal_info(log.last_updated_fmt)
    if not log.eps:
        last = 0
    else:
        last = int(re.split('-|,', log.eps)[-1])
    to_play = utils.compress_range(filter(lambda e: e > last, episodes))
    if to_play.strip():
        play_func([name, to_play])
    else:
        unsave_anime(name)
예제 #21
0
def get_updates(anime_name=""):
    """Check and display the updates on the tracked anime list."""
    updates = anime_updates(anime_name)
    if len(updates) == 0:
        outputs.normal_info("No new episodes released.")
        return
    if anime_name == "":
        outputs.prompt_val(
            "anime(s) has new episodes.",
            len(updates),
            "success",
            sep=" ",
            reverse=True,
        )
        outputs.normal_info("-" * 50)
    for anime, episodes in updates.items():
        outputs.normal_info(anime, end="\n\t")
        outputs.success_tag(len(episodes), end=" ")
        outputs.prompt_val("new episodes", utils.compress_range(episodes),
                           "success")
예제 #22
0
def download_from_url(gogo_url, anime_name=None, episode=None):
    if not anime_name or not episode:
        anime_name, episode = gogoanime.parse_gogo_url(gogo_url)
    os.makedirs(os.path.join(config.anime_dir, f'./{anime_name}'),
                exist_ok=True)
    outputs.prompt_val('Downloading', gogo_url)
    durl, ext = gogoanime.get_direct_video_url(gogo_url)
    if not durl:
        outputs.error_info('Url for the file not found')
        raise SystemExit
    if ext == 'm3u8':
        m3u8_url = utils.get_m3u8_stream(durl)
        utils.download_m3u8(
            m3u8_url,
            os.path.join(config.anime_dir,
                         f'./{anime_name}/ep{episode:02d}.{ext}'))
    else:
        utils.download_file(
            durl,
            os.path.join(config.anime_dir,
                         f'./{anime_name}/ep{episode:02d}.{ext}'))
예제 #23
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()
예제 #24
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
예제 #25
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
예제 #26
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