Skip to content

Commit

Permalink
Merge pull request #17 from hurlenko/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
hurlenko authored Aug 28, 2021
2 parents c656c19 + 4c94f1a commit 1cf3a04
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 90 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ Currently `mloader` supports these commands
```bash
Usage: mloader [OPTIONS] [URLS]...

Command-line tool to download manga from mangaplus

Options:
--version Show the version and exit.
-o, --out <directory> Save directory (not a file) [default:
mloader_downloads]
-r, --raw Save raw images [default: False]
Expand All @@ -48,5 +51,12 @@ Options:
-s, --split Split combined images [default: False]
-c, --chapter INTEGER Chapter id
-t, --title INTEGER Title id
-b, --begin INTEGER RANGE Minimal chapter to try to download
[default: 0;x>=0]
-e, --end INTEGER RANGE Maximal chapter to try to download [x>=1]
-l, --last Download only the last chapter for title
[default: False]
--chapter-title Include chapter titles in filenames
[default: False]
--help Show this message and exit.
```
50 changes: 48 additions & 2 deletions mloader/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import re
import sys
from functools import partial
from typing import Optional, Set

import click
Expand Down Expand Up @@ -145,6 +146,35 @@ def validate_ids(ctx: click.Context, param, value):
expose_value=False,
callback=validate_ids,
)
@click.option(
"--begin",
"-b",
type=click.IntRange(min=0),
default=0,
show_default=True,
help="Minimal chapter to try to download",
)
@click.option(
"--end",
"-e",
type=click.IntRange(min=1),
help="Maximal chapter to try to download",
)
@click.option(
"--last",
"-l",
is_flag=True,
default=False,
show_default=True,
help="Download only the last chapter for title",
)
@click.option(
"--chapter-title",
is_flag=True,
default=False,
show_default=True,
help="Include chapter titles in filenames",
)
@click.argument("urls", nargs=-1, callback=validate_urls, expose_value=False)
@click.pass_context
def main(
Expand All @@ -153,18 +183,34 @@ def main(
raw: bool,
quality: str,
split: bool,
begin: int,
end: int,
last: bool,
chapter_title: bool,
chapters: Optional[Set[int]] = None,
titles: Optional[Set[int]] = None,
):
click.echo(click.style(about.__doc__, fg="blue"))
if not any((chapters, titles)):
click.echo(ctx.get_help())
return
end = end or float("inf")
log.info("Started export")

loader = MangaLoader(RawExporter if raw else CBZExporter, quality, split)
exporter = RawExporter if raw else CBZExporter
exporter = partial(
exporter, destination=out_dir, add_chapter_title=chapter_title
)

loader = MangaLoader(exporter, quality, split)
try:
loader.download(title_ids=titles, chapter_ids=chapters, dst=out_dir)
loader.download(
title_ids=titles,
chapter_ids=chapters,
min_chapter=begin,
max_chapter=end,
last_chapter=last,
)
except Exception:
log.exception("Failed to download manga")
log.info("SUCCESS")
Expand Down
2 changes: 1 addition & 1 deletion mloader/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
__title__ = "mloader"
__description__ = "Command-line tool to download manga from mangaplus"
__url__ = "https://github.com/hurlenko/mloader"
__version__ = "1.1.5"
__version__ = "1.1.6"
__license__ = "GPLv3"
23 changes: 23 additions & 0 deletions mloader/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from enum import Enum


class Language(Enum):
eng = 0
spa = 1
ind = 3
por = 4
rus = 5
tha = 6


class ChapterType(Enum):
latest = 0
sequence = 1
nosequence = 2


class PageType(Enum):
single = 0
left = 1
right = 2
double = 3
65 changes: 16 additions & 49 deletions mloader/exporter.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import re
import string
import zipfile
from abc import ABCMeta, abstractmethod
from enum import Enum
from itertools import chain
from pathlib import Path
from typing import Union, Optional

from mloader.constants import Language
from mloader.response_pb2 import Title, Chapter


class Language(Enum):
eng = 0
spa = 1
from mloader.utils import escape_path, is_oneshot, chapter_name_to_int


class ExporterBase(metaclass=ABCMeta):
Expand All @@ -22,19 +16,21 @@ def __init__(
title: Title,
chapter: Chapter,
next_chapter: Optional[Chapter] = None,
add_chapter_title: bool = False,
):
self.destination = destination
self.title_name = self.escape_path(title.name).title()
self.is_oneshot = self._is_oneshot(chapter.name, chapter.sub_title)
self.add_chapter_title = add_chapter_title
self.title_name = escape_path(title.name).title()
self.is_oneshot = is_oneshot(chapter.name, chapter.sub_title)
self.is_extra = chapter.name == "ex"

self._extra_info = []

if self.is_oneshot:
self._extra_info.append("[Oneshot]")

if self.is_extra:
self._extra_info.append(f"[{self.escape_path(chapter.sub_title)}]")
if self.is_extra or self.add_chapter_title:
self._extra_info.append(f"[{escape_path(chapter.sub_title)}]")

self._chapter_prefix = self._format_chapter_prefix(
self.title_name,
Expand All @@ -47,19 +43,6 @@ def __init__(
(self._chapter_prefix, self._chapter_suffix)
)

def _is_oneshot(self, chapter_name: str, chapter_subtitle: str) -> bool:
for name in (chapter_name, chapter_subtitle):
name = name.lower()
if "one" in name and "shot" in name:
return True
return False

def _chapter_name_to_int(self, name: str) -> Optional[int]:
try:
return int(name.lstrip("#"))
except ValueError:
return None

def _format_chapter_prefix(
self,
title_name: str,
Expand All @@ -78,17 +61,17 @@ def _format_chapter_prefix(
chapter_num = 0
elif self.is_extra and next_chapter_name:
suffix = "x1"
chapter_num = self._chapter_name_to_int(next_chapter_name)
chapter_num = chapter_name_to_int(next_chapter_name)
if chapter_num is not None:
chapter_num -= 1
prefix = "c" if chapter_num < 1000 else "d"
else:
chapter_num = self._chapter_name_to_int(chapter_name)
chapter_num = chapter_name_to_int(chapter_name)
if chapter_num is not None:
prefix = "c" if chapter_num < 1000 else "d"

if chapter_num is None:
chapter_num = self.escape_path(chapter_name)
chapter_num = escape_path(chapter_name)

components.append(f"{prefix}{chapter_num:0>3}{suffix}")
components.append("(web)")
Expand All @@ -103,13 +86,10 @@ def format_page_name(self, page: Union[int, range], ext=".jpg") -> str:
else:
page = f"p{page:0>3}"

ext = ext.lstrip('.')
ext = ext.lstrip(".")

return f"{self._chapter_prefix} - {page} {self._chapter_suffix}.{ext}"

def escape_path(self, path: str) -> str:
return re.sub(r"[^\w]+", " ", path).strip(string.punctuation + " ")

def close(self):
pass

Expand All @@ -119,14 +99,8 @@ def add_image(self, image_data: bytes, index: Union[int, range]):


class RawExporter(ExporterBase):
def __init__(
self,
destination: str,
title: Title,
chapter: Chapter,
next_chapter: Optional[Chapter] = None,
):
super().__init__(destination, title, chapter, next_chapter)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.path = Path(self.destination, self.title_name)
self.path.mkdir(parents=True, exist_ok=True)

Expand All @@ -136,15 +110,8 @@ def add_image(self, image_data: bytes, index: Union[int, range]):


class CBZExporter(ExporterBase):
def __init__(
self,
destination: str,
title: Title,
chapter: Chapter,
next_chapter: Optional[Chapter] = None,
compression=zipfile.ZIP_DEFLATED,
):
super().__init__(destination, title, chapter, next_chapter)
def __init__(self, compression=zipfile.ZIP_DEFLATED, *args, **kwargs):
super().__init__(*args, **kwargs)
self.path = Path(self.destination, self.title_name)
self.path.mkdir(parents=True, exist_ok=True)
self.path = self.path.joinpath(self.chapter_name).with_suffix(".cbz")
Expand Down
Loading

0 comments on commit 1cf3a04

Please sign in to comment.