From e4865980f858499e9077e18d2e4622a85900cd68 Mon Sep 17 00:00:00 2001 From: Michael Johnson <44432163+MichaelDavidJohnson@users.noreply.github.com> Date: Mon, 3 Aug 2020 15:40:47 +0100 Subject: [PATCH] Re-implementing watch (#461) * It should be fully functional now :ok_hand: Co-authored-by: Blatzar <46196380+Blatzar@users.noreply.github.com> --- README.md | 1 + anime_downloader/commands/watch.py | 85 ++++++++++++++++---------- anime_downloader/config.py | 1 + anime_downloader/players/baseplayer.py | 2 +- docs/usage/watch.rst | 50 +++++++++------ 5 files changed, 88 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 8d20f16..4d0421c 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Yeah. Me too! That's why this tool exists. ## Features - Download or stream any episode or episode range of any anime. +- Have a locally stored anime list to track your progress and stream anime using the watch command. - Specify the quality you want to stream or download. - Search and download. - Save yourselves from those malicious ads. diff --git a/anime_downloader/commands/watch.py b/anime_downloader/commands/watch.py index d1efdcd..d91651e 100644 --- a/anime_downloader/commands/watch.py +++ b/anime_downloader/commands/watch.py @@ -7,11 +7,11 @@ from anime_downloader.__version__ import __version__ from anime_downloader.players.mpv import mpv from anime_downloader import watch as _watch from anime_downloader.config import Config - +from anime_downloader.sites import get_anime_class, ALL_ANIME_SITES logger = logging.Logger(__name__) echo = click.echo - +sitenames = [v[1] for v in ALL_ANIME_SITES] @click.command() @click.argument('anime_name', required=False) @@ -36,13 +36,12 @@ echo = click.echo @click.option( '--provider', help='The anime provider (website) for search.', - type=click.Choice(['9anime', 'kissanime', 'twist.moe', 'kisscartoon', 'masterani']) + type=click.Choice(sitenames) ) def command(anime_name, new, update_all, _list, quality, remove, download_dir, provider): """ With watch you can keep track of any anime you watch. - Available Commands after selection of an anime:\n set : set episodes_done, provider and title. Ex: set episodes_done=3\n @@ -50,12 +49,9 @@ def command(anime_name, new, update_all, _list, quality, remove, update : Update the episodes of the currrent anime\n watch : Watch selected anime\n download : Download episodes of selected anime + back : Returns back to the list """ util.print_info(__version__) - echo('Watch is deprecated in favour of adl: https://github.com/RaitaroH/adl .') - echo('You can use dl command to stream anime if you do not want anime tracking.') - echo('watch command may come back in the future.') - watcher = _watch.Watcher() if new: @@ -87,7 +83,7 @@ def command(anime_name, new, update_all, _list, quality, remove, watcher.update_anime(anime) if _list: - list_animes(watcher, quality, download_dir) + list_animes(watcher, quality, download_dir, None) sys.exit(0) if anime_name: @@ -101,12 +97,13 @@ def command(anime_name, new, update_all, _list, quality, remove, anime.quality = quality logger.info('Found {}'.format(anime.title)) - watch_anime(watcher, anime) + watch_anime(watcher, anime,quality,download_dir) -def list_animes(watcher, quality, download_dir): +def list_animes(watcher, quality, download_dir, imp=None): watcher.list() - inp = click.prompt('Select an anime', default=1) + inp = click.prompt('Select an anime', default=1) if not imp else imp + try: anime = watcher.get(int(inp)-1) except IndexError: @@ -129,7 +126,7 @@ def list_animes(watcher, quality, download_dir): meta += '{}: {}\n'.format(k, click.style(str(v), bold=True)) click.echo(meta) - click.echo('Available Commands: set, remove, update, watch,' + click.echo('Available Commands: set, remove, update, watch, back,' ' download.\n') inp = click.prompt('Press q to exit', default='q').strip() @@ -137,34 +134,38 @@ def list_animes(watcher, quality, download_dir): # TODO: A better way to handle commands. Use regex. Refractor to class? # Decorator? if inp == 'q': - break + sys.exit(0) + elif inp == 'back': + list_animes(watcher, quality, download_dir, imp=imp) elif inp == 'remove': watcher.remove(anime) - break + list_anime(watcher, quality, download_dir, imp=imp) elif inp == 'update': watcher.update_anime(anime) elif inp == 'watch': anime.quality = quality - watch_anime(watcher, anime) - sys.exit(0) + watch_anime(watcher, anime,quality, download_dir) + elif inp.startswith('download'): + # You can use download 3:10 for selected episodes try: inp = inp.split('download ')[1] except IndexError: inp = ':' - inp = str(anime.episodes_done+1) + \ - inp if inp.startswith(':') else inp - inp = inp+str(len(anime)) if inp.endswith(':') else inp - - anime = util.split_anime(anime, 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) - for episode in anime: - episode.download(force=False, - path=Config['dl']['download_dir'], - format=Config['dl']['file_format']) elif inp.startswith('set '): inp = inp.split('set ')[-1] key, val = [v.strip() for v in inp.split('=')] @@ -174,10 +175,25 @@ def list_animes(watcher, quality, download_dir): 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) @@ -187,9 +203,10 @@ def list_animes(watcher, quality, download_dir): anime = newanime -def watch_anime(watcher, anime): +def watch_anime(watcher, anime, quality, download_dir): + autoplay = Config['watch']['autoplay_next'] to_watch = anime[anime.episodes_done:] - logger.debug('Sliced epiosdes: {}'.format(to_watch._episode_urls)) + logger.debug('Sliced episodes: {}'.format(to_watch._episode_urls)) while anime.episodes_done < len(anime): episode = anime[anime.episodes_done] @@ -208,16 +225,22 @@ def watch_anime(watcher, anime): sys.exit(1) returncode = player.play() - if returncode == player.STOP: - sys.exit(0) + # Returns to watch. + return + elif returncode == player.CONNECT_ERR: logger.warning("Couldn't connect. Retrying. " "Attempt #{}".format(tries+1)) continue + elif returncode == player.PREV: anime.episodes_done -= 2 watcher.update(anime) break - else: + # If no other return codes, basically when the player finishes. + # Can't find the returncode for success. + elif autoplay: break + else: + return diff --git a/anime_downloader/config.py b/anime_downloader/config.py index 5b79776..7c87304 100644 --- a/anime_downloader/config.py +++ b/anime_downloader/config.py @@ -30,6 +30,7 @@ DEFAULT_CONFIG = { 'fallback_qualities': ['720p', '480p', '360p'], 'log_level': 'INFO', 'provider': 'twist.moe', + 'autoplay_next':True }, "siteconfig": { 'animefrenzy': { diff --git a/anime_downloader/players/baseplayer.py b/anime_downloader/players/baseplayer.py index faf112c..a3c6015 100644 --- a/anime_downloader/players/baseplayer.py +++ b/anime_downloader/players/baseplayer.py @@ -34,7 +34,7 @@ class BasePlayer(metaclass=ABCMeta): def __init__(self, episode): # TODO: Stream urls is a list of urls for now # It should be a list of seperate class with title and other metadata - self.episdoe = episode + self.episode = episode def _get_executable(self): if os.name == 'nt': diff --git a/docs/usage/watch.rst b/docs/usage/watch.rst index e1d73f4..2122db7 100644 --- a/docs/usage/watch.rst +++ b/docs/usage/watch.rst @@ -1,18 +1,16 @@ -``watch - DEPRECIATED`` +``watch`` ========= .. note:: - You need `mpv`_ to use this subcommand. + You need `mpv`_ to use this subcommand currently. Work is being done to add VLC as a player also, but will have reduced functionality. .. figure:: https://thumbs.gfycat.com/FrailSmallGosling-size_restricted.gif :alt: gif anime watch in action -``anime watch`` can be a all in one solution for your anime needs. -Currently only supports 9anime. +``anime watch`` can be a all in one solution for your anime needs. Anime watch contains exactly the same providers used in anime dl so you will not be missing anything! -``watch`` will track your progress through an anime and thus make your -life easier. +``watch`` will locally track your progress with an anime list making your time with anime watch easy and enjoyable (Work is being done to try and format the locally stored list in a way that importing / exporting to MAL could be possible) :: @@ -29,20 +27,21 @@ life easier. With watch you can keep track of any anime you watch. Available Commands after selection of an anime: - set : set episodes_done and title. Ex: set episodes_done=3 - remove : remove selected anime from watch list - update : Update the episodes of the currrent anime - watch : Watch selected anime - download : Download episodes of selected anime + set : Set episodes_done, provider and title. Ex: set episodes_done=3 + remove : Remove selected anime from watch list. + update : Update the episodes of the currrent anime, brilliant for currently airing series. + watch : Watch selected anime. + download : Download episodes of selected anime. + back : Return back to the list. Options: - -n, --new Create a new anime to watch - -l, --list List all animes in watch list - -r, --remove Remove the specified anime + -n, --new Add a new entry to the list. + -l, --list List all animes in watch list. + -r, --remove Remove a specified anime from the list. -q, --quality [360p|480p|720p|1080p] - Specify the quality of episode. + Specify the quality of episodes. -ll, --log-level [DEBUG|INFO|WARNING|ERROR] - Sets the level of logger + Sets the level of logger. --help Show this message and exit. ``anime watch --new`` @@ -55,6 +54,7 @@ term. If you already know what to search for, use ``anime watch --new``. You can then select an anime to be added to the watch list. +If you are familiar with the dl side of anime downloader then you can also specify your choice of provider at this point with the ``--provider`` flag. :: $ anime watch 'code geass' --new @@ -87,8 +87,20 @@ This command lists your watch list. 1 | Code Geass: Lelouch of the Rebellio | 0/25 | TV Series You can select an anime from this list and perform an action on it. -\``\` Available Commands after selection of an anime: set : set -episodes_done and title. Ex: set episodes_done=3 remove : remove -selected anime fro +\``\` + +Once you select an anime from the table a new enviroment for you to use appears, this has the following options; + +- set: Update information about the anime on the list. Episodes, title and provider changes go here. + +- remove: Remove an anime from the list. + +- update: Update the episode range of the anime. + +- watch: Watch an episode of the anime and then return back to this enviroment. + +- download: Download an episode of the anime. + +- back: Return back to the list .. _mpv: https://mpv.io/