Re-implementing watch (#461)

* It should be fully functional now 👌 

Co-authored-by: Blatzar <46196380+Blatzar@users.noreply.github.com>
master
Michael Johnson 2020-08-03 15:40:47 +01:00 committed by GitHub
parent d35994bd0a
commit e4865980f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 51 deletions

View File

@ -35,6 +35,7 @@ Yeah. Me too! That's why this tool exists.
## Features ## Features
- Download or stream any episode or episode range of any anime. - 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. - Specify the quality you want to stream or download.
- Search and download. - Search and download.
- Save yourselves from those malicious ads. - Save yourselves from those malicious ads.

View File

@ -7,11 +7,11 @@ from anime_downloader.__version__ import __version__
from anime_downloader.players.mpv import mpv from anime_downloader.players.mpv import mpv
from anime_downloader import watch as _watch from anime_downloader import watch as _watch
from anime_downloader.config import Config from anime_downloader.config import Config
from anime_downloader.sites import get_anime_class, ALL_ANIME_SITES
logger = logging.Logger(__name__) logger = logging.Logger(__name__)
echo = click.echo echo = click.echo
sitenames = [v[1] for v in ALL_ANIME_SITES]
@click.command() @click.command()
@click.argument('anime_name', required=False) @click.argument('anime_name', required=False)
@ -36,13 +36,12 @@ echo = click.echo
@click.option( @click.option(
'--provider', '--provider',
help='The anime provider (website) for search.', 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, def command(anime_name, new, update_all, _list, quality, remove,
download_dir, provider): download_dir, provider):
""" """
With watch you can keep track of any anime you watch. With watch you can keep track of any anime you watch.
Available Commands after selection of an anime:\n Available Commands after selection of an anime:\n
set : set episodes_done, provider and title. set : set episodes_done, provider and title.
Ex: set episodes_done=3\n 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 update : Update the episodes of the currrent anime\n
watch : Watch selected anime\n watch : Watch selected anime\n
download : Download episodes of selected anime download : Download episodes of selected anime
back : Returns back to the list
""" """
util.print_info(__version__) 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() watcher = _watch.Watcher()
if new: if new:
@ -87,7 +83,7 @@ def command(anime_name, new, update_all, _list, quality, remove,
watcher.update_anime(anime) watcher.update_anime(anime)
if _list: if _list:
list_animes(watcher, quality, download_dir) list_animes(watcher, quality, download_dir, None)
sys.exit(0) sys.exit(0)
if anime_name: if anime_name:
@ -101,12 +97,13 @@ def command(anime_name, new, update_all, _list, quality, remove,
anime.quality = quality anime.quality = quality
logger.info('Found {}'.format(anime.title)) 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() watcher.list()
inp = click.prompt('Select an anime', default=1) inp = click.prompt('Select an anime', default=1) if not imp else imp
try: try:
anime = watcher.get(int(inp)-1) anime = watcher.get(int(inp)-1)
except IndexError: except IndexError:
@ -129,7 +126,7 @@ def list_animes(watcher, quality, download_dir):
meta += '{}: {}\n'.format(k, click.style(str(v), bold=True)) meta += '{}: {}\n'.format(k, click.style(str(v), bold=True))
click.echo(meta) click.echo(meta)
click.echo('Available Commands: set, remove, update, watch,' click.echo('Available Commands: set, remove, update, watch, back,'
' download.\n') ' download.\n')
inp = click.prompt('Press q to exit', default='q').strip() 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? # TODO: A better way to handle commands. Use regex. Refractor to class?
# Decorator? # Decorator?
if inp == 'q': if inp == 'q':
break sys.exit(0)
elif inp == 'back':
list_animes(watcher, quality, download_dir, imp=imp)
elif inp == 'remove': elif inp == 'remove':
watcher.remove(anime) watcher.remove(anime)
break list_anime(watcher, quality, download_dir, imp=imp)
elif inp == 'update': elif inp == 'update':
watcher.update_anime(anime) watcher.update_anime(anime)
elif inp == 'watch': elif inp == 'watch':
anime.quality = quality anime.quality = quality
watch_anime(watcher, anime) watch_anime(watcher, anime,quality, download_dir)
sys.exit(0)
elif inp.startswith('download'): elif inp.startswith('download'):
# You can use download 3:10 for selected episodes
try: try:
inp = inp.split('download ')[1] inp = inp.split('download ')[1]
except IndexError: except IndexError:
inp = ':' inp = ':'
inp = str(anime.episodes_done+1) + \ animes = util.parse_ep_str(anime, inp)
inp if inp.startswith(':') else inp
inp = inp+str(len(anime)) if inp.endswith(':') else inp
anime = util.split_anime(anime, inp)
# Using the config from dl.
if not download_dir: if not download_dir:
download_dir = Config['dl']['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 '): elif inp.startswith('set '):
inp = inp.split('set ')[-1] inp = inp.split('set ')[-1]
key, val = [v.strip() for v in inp.split('=')] key, val = [v.strip() for v in inp.split('=')]
@ -174,10 +175,25 @@ def list_animes(watcher, quality, download_dir):
watcher.remove(anime) watcher.remove(anime)
setattr(anime, key, val) setattr(anime, key, val)
watcher.add(anime) watcher.add(anime)
elif key == 'episodes_done': 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)) setattr(anime, key, int(val))
watcher.update(anime) watcher.update(anime)
elif key == 'provider': 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) url = util.search(anime.title, val)
watcher.remove(anime) watcher.remove(anime)
newanime = watcher.new(url) newanime = watcher.new(url)
@ -187,9 +203,10 @@ def list_animes(watcher, quality, download_dir):
anime = newanime 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:] 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): while anime.episodes_done < len(anime):
episode = anime[anime.episodes_done] episode = anime[anime.episodes_done]
@ -208,16 +225,22 @@ def watch_anime(watcher, anime):
sys.exit(1) sys.exit(1)
returncode = player.play() returncode = player.play()
if returncode == player.STOP: if returncode == player.STOP:
sys.exit(0) # Returns to watch.
return
elif returncode == player.CONNECT_ERR: elif returncode == player.CONNECT_ERR:
logger.warning("Couldn't connect. Retrying. " logger.warning("Couldn't connect. Retrying. "
"Attempt #{}".format(tries+1)) "Attempt #{}".format(tries+1))
continue continue
elif returncode == player.PREV: elif returncode == player.PREV:
anime.episodes_done -= 2 anime.episodes_done -= 2
watcher.update(anime) watcher.update(anime)
break break
else: # If no other return codes, basically when the player finishes.
# Can't find the returncode for success.
elif autoplay:
break break
else:
return

View File

@ -30,6 +30,7 @@ DEFAULT_CONFIG = {
'fallback_qualities': ['720p', '480p', '360p'], 'fallback_qualities': ['720p', '480p', '360p'],
'log_level': 'INFO', 'log_level': 'INFO',
'provider': 'twist.moe', 'provider': 'twist.moe',
'autoplay_next':True
}, },
"siteconfig": { "siteconfig": {
'animefrenzy': { 'animefrenzy': {

View File

@ -34,7 +34,7 @@ class BasePlayer(metaclass=ABCMeta):
def __init__(self, episode): def __init__(self, episode):
# TODO: Stream urls is a list of urls for now # TODO: Stream urls is a list of urls for now
# It should be a list of seperate class with title and other metadata # It should be a list of seperate class with title and other metadata
self.episdoe = episode self.episode = episode
def _get_executable(self): def _get_executable(self):
if os.name == 'nt': if os.name == 'nt':

View File

@ -1,18 +1,16 @@
``watch - DEPRECIATED`` ``watch``
========= =========
.. note:: .. 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 .. figure:: https://thumbs.gfycat.com/FrailSmallGosling-size_restricted.gif
:alt: gif :alt: gif
anime watch in action anime watch in action
``anime watch`` can be a all in one solution for your anime needs. ``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!
Currently only supports 9anime.
``watch`` will track your progress through an anime and thus make your ``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)
life easier.
:: ::
@ -29,20 +27,21 @@ life easier.
With watch you can keep track of any anime you watch. With watch you can keep track of any anime you watch.
Available Commands after selection of an anime: Available Commands after selection of an anime:
set : set episodes_done and title. Ex: set episodes_done=3 set : Set episodes_done, provider and title. Ex: set episodes_done=3
remove : remove selected anime from watch list remove : Remove selected anime from watch list.
update : Update the episodes of the currrent anime update : Update the episodes of the currrent anime, brilliant for currently airing series.
watch : Watch selected anime watch : Watch selected anime.
download : Download episodes of selected anime download : Download episodes of selected anime.
back : Return back to the list.
Options: Options:
-n, --new Create a new anime to watch -n, --new Add a new entry to the list.
-l, --list List all animes in watch list -l, --list List all animes in watch list.
-r, --remove Remove the specified anime -r, --remove Remove a specified anime from the list.
-q, --quality [360p|480p|720p|1080p] -q, --quality [360p|480p|720p|1080p]
Specify the quality of episode. Specify the quality of episodes.
-ll, --log-level [DEBUG|INFO|WARNING|ERROR] -ll, --log-level [DEBUG|INFO|WARNING|ERROR]
Sets the level of logger Sets the level of logger.
--help Show this message and exit. --help Show this message and exit.
``anime watch --new`` ``anime watch --new``
@ -55,6 +54,7 @@ term. If you already know what to search for, use
``anime watch <search term> --new``. You can then select an anime to be ``anime watch <search term> --new``. You can then select an anime to be
added to the watch list. 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 $ 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 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. 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/ .. _mpv: https://mpv.io/