Added manga-py source

This commit is contained in:
2019-12-14 22:33:14 -05:00
parent 9a4dd4b09b
commit 45067caea6
420 changed files with 18054 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
import sys
from argparse import ArgumentParser
from getpass import getpass
from os import name as os_name
from progressbar import ProgressBar
from manga_py.fs import check_free_space, get_temp_path
from manga_py.parser import Parser
class Cli: # pragma: no cover
args = None
parser = None
_info = None
__progress_bar = None
def __init__(self, args: ArgumentParser, info=None):
self.args = args.parse_args()
self.parser = Parser(args)
self._info = info
space = self.args.min_free_space
if not check_free_space(get_temp_path(), space) or not check_free_space(self.args.destination, space):
raise OSError('No space left on device')
def start(self):
try:
self.parser.init_provider(
progress=self.progress,
log=self.print,
quest=self.quest,
quest_password=self.quest_password,
info=self._info,
)
except AttributeError as e:
print(e, file=sys.stderr)
print('Please check if your inputed domain is supported by manga-py: ', file=sys.stderr)
print('- https://manga-py.com/manga-py/#resources-list', file=sys.stderr)
print('- https://manga-py.github.io/manga-py/#resources-list (alternative)', file=sys.stderr)
print('- https://yuru-yuri.github.io/manga-py/ (deprecated)', file=sys.stderr)
print('Make sure that your inputed URL is correct\n\nTrace:', file=sys.stderr)
raise e
self.parser.start()
self.__progress_bar and self.__progress_bar.value > 0 and self.__progress_bar.finish()
self.args.quiet or self.print(' ')
def __init_progress(self, items_count: int, re_init: bool):
if re_init or not self.__progress_bar:
if re_init:
self.__progress_bar.finish()
bar = ProgressBar()
self.__progress_bar = bar(range(items_count))
self.__progress_bar.init()
def progress(self, items_count: int, current_item: int, re_init: bool = False):
if not items_count:
return
if not self.args.no_progress and not self.args.print_json:
current_val = 0
if self.__progress_bar:
current_val = self.__progress_bar.value
self.__init_progress(items_count, re_init and current_val > 0)
self.__progress_bar.update(current_item)
def print(self, text, **kwargs):
if os_name == 'nt':
text = str(text).encode().decode(sys.stdout.encoding, 'ignore')
self.args.quiet or print(text, **kwargs)
def _single_quest(self, variants, title):
self.print(title)
for v in variants:
self.print(v)
return input()
def _multiple_quest(self, variants, title):
self.print('Accept - blank line + enter')
self.print(title)
for v in variants:
self.print(v)
result = []
while True:
_ = input().strip()
if not len(_):
return result
result.append(_)
def quest(self, variants: enumerate, title: str, select_type=0): # 0 = single, 1 = multiple
if select_type:
return self._multiple_quest(variants, title)
return self._single_quest(variants, title)
def quest_password(self, title):
return getpass(title)

View File

@@ -0,0 +1,338 @@
'''
manga-py module for CLI and its options.
'''
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter
from manga_py.meta import __version__
class DescriptionDefaultsHelpFormatter(ArgumentDefaultsHelpFormatter,
RawDescriptionHelpFormatter):
'''
Class to format --help cli option with 2 features to output:
programm's description in a raw mode,
options default values.
'''
def _image_args(args_parser): # pragma: no cover
args = args_parser.add_argument_group('Image options')
args.add_argument(
'-E',
'--not-change-files-extension',
action='store_true',
help=(
'Save downloaded files to archive "as is".'
)
)
args.add_argument(
'-W',
'--no-webp',
action='store_true',
help=(
'Convert `*.webp` images to `*.jpg` format.'
)
)
def _debug_args(args_parser): # pragma: no cover
args = args_parser.add_argument_group('Debug / Simulation options')
args.add_argument(
'-h',
'--help',
action='help',
help=(
'Show this help and exit.'
)
)
args.add_argument(
'-j',
'--print-json',
action='store_true',
help=(
'Print information about the results in the JSON format (after completion).'
)
)
args.add_argument(
'-l',
'--simulate',
action='store_true',
help=(
'Simulate running %(prog)s, where: '
'1) do not download files and, '
'2) do not write anything on disk.'
)
)
args.add_argument(
'-i',
'--show-current-chapter-info',
action='store_true',
help=(
'Show current processing chapter info.'
)
)
args.add_argument(
'-b',
'--debug',
action='store_true',
help=(
'Debug %(prog)s.'
)
)
args.add_argument(
'-q',
'--quiet',
action='store_true',
help=(
'Dont show any messages.'
)
)
def _downloading_args(args_parser): # pragma: no cover
args = args_parser.add_argument_group('Downloading options')
args.add_argument(
'-s',
'--skip-volumes',
metavar='COUNT',
type=int,
help=(
'Skip a total number, i.e. %(metavar)s, of volumes.'
),
default=0
)
args.add_argument(
'-m',
'--max-volumes',
metavar='COUNT',
type=int,
default=0,
help=(
'Download a maximum number, i.e. %(metavar)s, of volumes. '
'E.g.: `--max-volumes 2` will download at most 2 volumes. '
'If %(metavar)s is `0` (zero) then it will download all available volumes.'
)
)
args.add_argument(
'-a',
'--user-agent',
type=str,
help=(
'Set an user-agent. '
'Don\'t work from protected sites.'
)
)
args.add_argument(
'-x',
'--proxy',
type=str,
help=(
'Set a http proxy.'
)
)
args.add_argument(
'-e',
'--reverse-downloading',
action='store_true',
help=(
'Download manga volumes in a reverse order. '
'By default, manga is downloaded in ascendent order '
'(i.e. volume 00, volume 01, volume 02...). '
'If `--reverse-downloading` is actived, then manga is downloaded in descendent order '
'(i.e. volume 99, volume 98, volume 97...).'
)
)
args.add_argument(
'-w',
'--rewrite-exists-archives',
action='store_true',
help=(
'(Re)Download manga volume if it already exists locally in the directory destination. '
'Your manga files can be overwrited, so be careful.'
)
)
args.add_argument(
'-t',
'--max-threads',
type=int,
default=None,
help=(
'Set the maximum number of threads, i.e. MAX_THREADS, to be avaliable to manga-py. '
'Threads run in pseudo-parallel when execute the process to download the manga images.'
)
)
args.add_argument(
'-f',
'--zero-fill',
action='store_true',
help=(
'Pad a `-0` (dash-and-zero) at right for all downloaded manga volume filenames. '
'E.g. from `vol_001.zip` to `vol_001-0.zip`. '
'It is useful to standardize the filenames between: '
'1) normal manga volumes (e.g. vol_006.zip) and, '
'2) abnormal manga volumes (e.g. vol_006-5.zip). '
'An abnormal manga volume is a released volume like: '
'extra chapters, '
'bonuses, '
'updated, '
'typos corrected, '
'spelling errors corrected; '
'and so on.'
)
)
args.add_argument(
'-g',
'--with-manga-name',
action='store_true',
help=(
'Pad the manga name at left for all downloaded manga volumes filenames. '
'E.g. from `vol_001.zip` to `manga_name-vol_001.zip`.'
)
)
args.add_argument(
'-o',
'--override-archive-name',
metavar='ARCHIVE_NAME',
type=str,
default='',
dest='override_archive_name',
help=(
'Pad %(metavar)s at left for all downloaded manga volumes filename. '
'E.g from `vol_001.zip` to `%(metavar)s-vol_001.zip`.'
)
)
args.add_argument(
'-c',
'--min-free-space',
metavar='MB',
type=int,
default=100,
help=(
'Alert when the minimum free disc space, i.e. MB, is reached. '
'Insert it in order of megabytes (Mb).'
)
)
def _reader_args(args_parser): # pragma: no cover
args = args_parser.add_argument_group('Archive options')
args.add_argument(
'-z',
'--cbz',
action='store_true',
help=(
'Make `*.cbz` archives (for reader).'
)
)
args.add_argument(
'-r',
'--rename-pages',
action='store_true',
help=(
'Normalize image filenames. '
'E.g. from `0_page_1.jpg` to `0001.jpg`.'
)
)
def get_cli_arguments() -> ArgumentParser: # pragma: no cover
'''
Method to generate manga-py CLI with its options.
'''
args_parser = ArgumentParser(
add_help=False,
formatter_class=DescriptionDefaultsHelpFormatter,
prog="manga-py",
description=(
'%(prog)s is the universal manga downloader (for your offline reading).\n '
'Site: https://manga-py.com/manga-py/\n '
'Source-code: https://github.com/manga-py/manga-py\n '
'Version: ' + __version__
),
epilog=(
'So, that is how %(prog)s can be executed to download yours favourite mangas.\n'
'Enjoy! 😉'
)
)
args = args_parser.add_argument_group('General options')
args.add_argument(
'url',
metavar='URL',
type=str,
help=(
'%(metavar)s, i.e. link from manga, to be downloaded.'
)
)
args.add_argument(
'-v',
'--version',
action='version',
version=__version__,
help=(
'Show %(prog)s\'s version number and exit.'
)
)
args.add_argument(
'-n',
'--name',
metavar='NAME',
type=str,
default='',
help=(
'Rename manga, i.e. by %(metavar)s, and its folder to where it will be saved locally.'
)
)
args.add_argument(
'-d',
'--destination',
metavar='PATH',
type=str,
default='Manga',
help=(
'Destination folder to where the manga will be saved locally. '
'The path will be `./%(metavar)s/manga_name/`.'
)
)
args.add_argument(
'-P',
'--no-progress',
action='store_true',
help=(
'Don\'t show progress bar.'
)
)
_image_args(args_parser)
_reader_args(args_parser)
_downloading_args(args_parser)
_debug_args(args_parser)
return args_parser