2018-02-04 15:21:15 -08:00
|
|
|
import click
|
2018-02-05 07:01:37 -08:00
|
|
|
import subprocess
|
2018-05-29 13:28:23 -07:00
|
|
|
import sys
|
2018-06-02 11:18:05 -07:00
|
|
|
import os
|
2018-05-27 10:01:49 -07:00
|
|
|
|
|
|
|
import logging
|
|
|
|
|
2018-06-01 05:37:41 -07:00
|
|
|
from anime_downloader.sites import get_anime_class
|
2018-05-27 10:01:49 -07:00
|
|
|
from anime_downloader.sites.exceptions import NotFoundError
|
2018-06-01 01:13:44 -07:00
|
|
|
from anime_downloader.players.mpv import mpv
|
2018-05-27 10:01:49 -07:00
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
|
2018-06-02 11:18:05 -07:00
|
|
|
from anime_downloader import util
|
|
|
|
from anime_downloader.config import Config
|
2018-05-31 04:04:47 -07:00
|
|
|
from anime_downloader import watch as _watch
|
2018-02-04 15:21:15 -08:00
|
|
|
|
|
|
|
echo = click.echo
|
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
|
2018-06-02 11:18:05 -07:00
|
|
|
@click.group(context_settings=Config.CONTEXT_SETTINGS)
|
2018-05-30 03:56:27 -07:00
|
|
|
def cli():
|
2018-05-30 04:29:23 -07:00
|
|
|
"""Anime Downloader
|
|
|
|
|
|
|
|
Download or watch your favourite anime
|
|
|
|
"""
|
2018-05-30 03:56:27 -07:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
# NOTE: Don't put defaults here. Add them to the dict in config
|
2018-05-30 03:56:27 -07:00
|
|
|
@cli.command()
|
2018-02-04 15:21:15 -08:00
|
|
|
@click.argument('anime_url')
|
2018-05-27 10:01:49 -07:00
|
|
|
@click.option('--episodes', '-e', 'episode_range', metavar='<int>:<int>',
|
2018-02-05 08:54:30 -08:00
|
|
|
help="Range of anime you want to download in the form <start>:<end>")
|
2018-06-02 11:18:05 -07:00
|
|
|
@click.option('--save-playlist', '-p', 'save_playlist', type=bool, is_flag=True,
|
2018-05-27 10:01:49 -07:00
|
|
|
help="If flag is set, saves the stream urls in an m3u file instead of downloading")
|
2018-05-31 04:04:47 -07:00
|
|
|
@click.option('--url', '-u', type=bool, is_flag=True,
|
2018-05-27 10:01:49 -07:00
|
|
|
help="If flag is set, prints the stream url instead of downloading")
|
2018-02-05 07:01:37 -08:00
|
|
|
@click.option('--play', 'player', metavar='PLAYER',
|
|
|
|
help="Streams in the specified player")
|
2018-06-02 11:18:05 -07:00
|
|
|
@click.option('--skip-download', is_flag=True,
|
2018-02-05 08:54:30 -08:00
|
|
|
help="Retrieve without downloading")
|
2018-05-31 04:04:47 -07:00
|
|
|
@click.option('--download-dir', help="Specifiy the directory to download to")
|
2018-05-27 10:01:49 -07:00
|
|
|
@click.option('--quality', '-q', type=click.Choice(['360p', '480p', '720p']),
|
2018-02-05 08:54:30 -08:00
|
|
|
help='Specify the quality of episode. Default-720p')
|
2018-06-02 11:18:05 -07:00
|
|
|
@click.option('--force-download', '-f', is_flag=True,
|
2018-02-08 15:07:11 -08:00
|
|
|
help='Force downloads even if file exists')
|
2018-05-27 10:01:49 -07:00
|
|
|
@click.option('--log-level', '-ll', 'log_level',
|
|
|
|
type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR']),
|
|
|
|
help='Sets the level of logger')
|
2018-05-31 04:04:47 -07:00
|
|
|
@click.pass_context
|
2018-06-02 11:18:05 -07:00
|
|
|
def dl(ctx, anime_url, episode_range, save_playlist, url, player, skip_download, quality,
|
|
|
|
force_download, log_level, download_dir):
|
2018-05-30 04:29:23 -07:00
|
|
|
""" Download the anime using the url or search for it.
|
2018-02-04 15:21:15 -08:00
|
|
|
"""
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-05-27 10:01:49 -07:00
|
|
|
util.setup_logger(log_level)
|
2018-06-02 11:18:05 -07:00
|
|
|
|
|
|
|
if url or player:
|
|
|
|
skip_download = True
|
2018-05-27 10:01:49 -07:00
|
|
|
|
2018-06-01 05:37:41 -07:00
|
|
|
cls = get_anime_class(anime_url)
|
|
|
|
|
|
|
|
if not cls:
|
|
|
|
anime_url = util.search_and_get_url(anime_url)
|
|
|
|
cls = get_anime_class(anime_url)
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-02-04 15:57:10 -08:00
|
|
|
try:
|
2018-06-01 05:37:41 -07:00
|
|
|
anime = cls(anime_url, quality=quality, path=download_dir)
|
2018-02-04 15:57:10 -08:00
|
|
|
except NotFoundError as e:
|
|
|
|
echo(e.args[0])
|
|
|
|
return
|
2018-05-27 10:01:49 -07:00
|
|
|
if episode_range is None:
|
|
|
|
episode_range = '1:'+str(len(anime)+1)
|
2018-02-04 15:21:15 -08:00
|
|
|
|
2018-06-02 11:18:05 -07:00
|
|
|
if download_dir:
|
|
|
|
logging.info('Downloading to {}'.format(os.path.abspath(download_dir)))
|
|
|
|
|
|
|
|
logging.info('Found anime: {}'.format(anime.title))
|
|
|
|
|
2018-02-04 15:21:15 -08:00
|
|
|
try:
|
2018-05-27 10:01:49 -07:00
|
|
|
start, end = [int(x) for x in episode_range.split(':')]
|
2018-02-04 15:21:15 -08:00
|
|
|
anime._episodeIds = anime._episodeIds[start-1:end-1]
|
|
|
|
except ValueError:
|
|
|
|
# Only one episode specified
|
2018-05-27 10:01:49 -07:00
|
|
|
anime = [anime[int(episode_range)-1]]
|
2018-02-04 15:21:15 -08:00
|
|
|
|
|
|
|
for episode in anime:
|
|
|
|
if url:
|
|
|
|
print(episode.stream_url)
|
|
|
|
continue
|
|
|
|
|
2018-02-05 07:01:37 -08:00
|
|
|
if player:
|
|
|
|
p = subprocess.Popen([player, episode.stream_url])
|
|
|
|
p.wait()
|
|
|
|
|
2018-06-02 11:18:05 -07:00
|
|
|
if not skip_download:
|
|
|
|
episode.download(force_download)
|
2018-02-05 07:01:37 -08:00
|
|
|
print()
|
2018-05-28 12:36:40 -07:00
|
|
|
|
|
|
|
|
2018-05-30 03:56:27 -07:00
|
|
|
@cli.command()
|
2018-05-31 04:04:47 -07:00
|
|
|
@click.argument('anime_name', required=False)
|
|
|
|
@click.option('--new', '-n', type=bool, is_flag=True,
|
|
|
|
help="Create a new anime to watch")
|
|
|
|
@click.option('--list', '-l', '_list', type=bool, is_flag=True,
|
|
|
|
help="List all animes in watch list")
|
2018-06-02 12:11:43 -07:00
|
|
|
@click.option('--quality', '-q', type=click.Choice(['360p', '480p', '720p']),
|
|
|
|
help='Specify the quality of episode.')
|
2018-06-01 01:13:44 -07:00
|
|
|
@click.option('--log-level', '-ll', 'log_level',
|
|
|
|
type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR']),
|
|
|
|
help='Sets the level of logger', default='INFO')
|
2018-06-02 12:11:43 -07:00
|
|
|
def watch(anime_name, new, _list, quality, log_level):
|
2018-06-01 12:14:57 -07:00
|
|
|
"""
|
2018-06-02 12:11:43 -07:00
|
|
|
With watch you can keep track of any anime you watch.
|
2018-06-01 12:14:57 -07:00
|
|
|
"""
|
2018-06-01 01:13:44 -07:00
|
|
|
util.setup_logger(log_level)
|
2018-05-31 04:04:47 -07:00
|
|
|
watcher = _watch.Watcher()
|
2018-05-30 03:56:27 -07:00
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
if new:
|
|
|
|
if anime_name:
|
|
|
|
query = anime_name
|
|
|
|
else:
|
|
|
|
query = click.prompt('Enter a anime name or url', type=str)
|
2018-05-30 03:56:27 -07:00
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
url = util.search_and_get_url(query)
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
watcher.new(url)
|
|
|
|
sys.exit(0)
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-05-31 04:04:47 -07:00
|
|
|
if _list:
|
|
|
|
watcher.list()
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if anime_name:
|
|
|
|
anime = watcher.get(anime_name)
|
2018-06-02 12:11:43 -07:00
|
|
|
anime.quality = quality
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-06-02 12:11:43 -07:00
|
|
|
logging.info('Found {}'.format(anime.title))
|
|
|
|
to_watch = anime[anime.episodes_done:]
|
2018-06-01 01:13:44 -07:00
|
|
|
|
2018-06-02 12:11:43 -07:00
|
|
|
for idx, episode in enumerate(to_watch):
|
2018-06-01 01:13:44 -07:00
|
|
|
|
2018-06-02 12:11:43 -07:00
|
|
|
for tries in range(5):
|
|
|
|
logging.info('Playing episode {}'.format(anime.episodes_done+1))
|
|
|
|
player = mpv(episode.stream_url)
|
|
|
|
returncode = player.play()
|
2018-05-28 12:36:40 -07:00
|
|
|
|
2018-06-02 12:11:43 -07:00
|
|
|
if returncode == mpv.STOP:
|
|
|
|
sys.exit(0)
|
|
|
|
elif returncode == mpv.CONNECT_ERR:
|
|
|
|
logging.warning("Couldn't connect. Retrying.")
|
|
|
|
continue
|
|
|
|
anime.episodes_done += 1
|
|
|
|
watcher.update(anime)
|
|
|
|
break
|