mirror of
https://github.com/jo1gi/grawlix.git
synced 2025-12-16 04:09:10 +00:00
Merge branch 'logging'
This commit is contained in:
commit
4da73a73e1
@ -1,6 +1,6 @@
|
||||
from .book import Book, Series
|
||||
from .config import load_config, Config, SourceConfig
|
||||
from .exceptions import SourceNotAuthenticated
|
||||
from .exceptions import SourceNotAuthenticated, GrawlixError
|
||||
from .sources import load_source, Source
|
||||
from .output import download_book
|
||||
from . import arguments, logging
|
||||
@ -68,23 +68,27 @@ async def authenticate(source: Source, config: Config, options):
|
||||
async def main() -> None:
|
||||
args = arguments.parse_arguments()
|
||||
config = load_config()
|
||||
logging.debug_mode = args.debug
|
||||
urls = get_urls(args)
|
||||
for url in urls:
|
||||
source: Source = load_source(url)
|
||||
if not source.authenticated and source.requires_authentication:
|
||||
await authenticate(source, config, args)
|
||||
result = await source.download(url)
|
||||
if isinstance(result, Book):
|
||||
with logging.progress(result.metadata.title, source.name) as progress:
|
||||
template: str = args.output or "{title}.{ext}"
|
||||
await download_with_progress(result, progress, template)
|
||||
elif isinstance(result, Series):
|
||||
with logging.progress(result.title, source.name, len(result.book_ids)) as progress:
|
||||
for book_id in result.book_ids:
|
||||
book: Book = await source.download_book_from_id(book_id)
|
||||
template: str = args.output or "{series}/{title}.{ext}"
|
||||
await download_with_progress(book, progress, template)
|
||||
logging.info("")
|
||||
try:
|
||||
source: Source = load_source(url)
|
||||
if not source.authenticated and source.requires_authentication:
|
||||
await authenticate(source, config, args)
|
||||
result = await source.download(url)
|
||||
if isinstance(result, Book):
|
||||
with logging.progress(result.metadata.title, source.name) as progress:
|
||||
template: str = args.output or "{title}.{ext}"
|
||||
await download_with_progress(result, progress, template)
|
||||
elif isinstance(result, Series):
|
||||
with logging.progress(result.title, source.name, len(result.book_ids)) as progress:
|
||||
for book_id in result.book_ids:
|
||||
book: Book = await source.download_book_from_id(book_id)
|
||||
template: str = args.output or "{series}/{title}.{ext}"
|
||||
await download_with_progress(book, progress, template)
|
||||
logging.info("")
|
||||
except GrawlixError as error:
|
||||
error.print_error()
|
||||
|
||||
|
||||
async def download_with_progress(book: Book, progress: Progress, template: str):
|
||||
|
||||
@ -51,4 +51,10 @@ def parse_arguments() -> argparse.Namespace:
|
||||
help = "Output destination",
|
||||
dest = "output"
|
||||
)
|
||||
# Logging
|
||||
parser.add_argument(
|
||||
'--debug',
|
||||
help = "Enable debug messages",
|
||||
dest = "debug"
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
9
grawlix/assets/errors/data_not_found.txt
Normal file
9
grawlix/assets/errors/data_not_found.txt
Normal file
@ -0,0 +1,9 @@
|
||||
[red]ERROR: Missing data from source[/red]
|
||||
|
||||
grawlix is missing data from source. This can happen when you try to
|
||||
download ebooks you don't have access too (not logged in or your profile
|
||||
doesn't have the right permissions), the site has been updated and grawlix
|
||||
hasn't implemented the new version, or it could be a bug in grawlix.
|
||||
|
||||
If you think it is a problem with grawlix please create an issue at
|
||||
https://github.com/jo1gi/grawlix/issues
|
||||
6
grawlix/assets/errors/invalid_url.txt
Normal file
6
grawlix/assets/errors/invalid_url.txt
Normal file
@ -0,0 +1,6 @@
|
||||
[red]ERROR: The given url does not match any sources[/red]
|
||||
|
||||
Please make sure the link goes to the ebook you want to download and the site is
|
||||
supported by grawlix. Try the link to the reader page if available.
|
||||
|
||||
If nothing works please create an issue at {issue}
|
||||
8
grawlix/assets/errors/source_not_authenticated.txt
Normal file
8
grawlix/assets/errors/source_not_authenticated.txt
Normal file
@ -0,0 +1,8 @@
|
||||
[red]ERROR: Source has not been authenticated[/red]
|
||||
|
||||
You need to login to use this site. You can either use
|
||||
* [green]--username[/] and [green]--password[/]
|
||||
* Write username and password in the config file
|
||||
* Use a cookie file with [green]--cookies[/]
|
||||
|
||||
See the README for more information: {repo}
|
||||
4
grawlix/assets/errors/throttle.txt
Normal file
4
grawlix/assets/errors/throttle.txt
Normal file
@ -0,0 +1,4 @@
|
||||
[red]ERROR: Your connection has been throttled[/]
|
||||
|
||||
The site you are downloading from has temporarily blocked you.
|
||||
Please wait a bit before downloading again or try another site or account.
|
||||
@ -1,23 +1,30 @@
|
||||
from grawlix.logging import print_error_file
|
||||
|
||||
ISSUE_URL = "https://github.com/jo1gi/grawlix/issues"
|
||||
REPO_URL = "https://github.com/jo1gi/grawlix"
|
||||
|
||||
class GrawlixError(Exception):
|
||||
pass
|
||||
error_file: str
|
||||
|
||||
def print_error(self) -> None:
|
||||
print_error_file(
|
||||
self.error_file,
|
||||
repo = REPO_URL,
|
||||
issue = ISSUE_URL,
|
||||
)
|
||||
|
||||
|
||||
class DataNotFound(GrawlixError):
|
||||
pass
|
||||
error_file = "data_not_found"
|
||||
|
||||
class InvalidUrl(GrawlixError):
|
||||
pass
|
||||
error_file = "invalid_url"
|
||||
|
||||
class UnsupportedOutputFormat(GrawlixError):
|
||||
pass
|
||||
|
||||
class NoSourceFound(GrawlixError):
|
||||
pass
|
||||
error_file = "unsupported_output_format"
|
||||
|
||||
class SourceNotAuthenticated(GrawlixError):
|
||||
pass
|
||||
|
||||
class MissingArgument(GrawlixError):
|
||||
pass
|
||||
error_file = "source_not_authenticated"
|
||||
|
||||
class ThrottleError(GrawlixError):
|
||||
pass
|
||||
error_file = "throttle"
|
||||
|
||||
@ -1,22 +1,63 @@
|
||||
from grawlix.book import Book
|
||||
|
||||
from rich.console import Console
|
||||
from rich.progress import Progress, BarColumn, ProgressColumn, TaskID, SpinnerColumn
|
||||
import rich
|
||||
from rich.console import Console
|
||||
from rich.markup import render
|
||||
from rich.progress import Progress, BarColumn, ProgressColumn, TaskID, SpinnerColumn
|
||||
from rich.style import Style
|
||||
|
||||
from typing import Union
|
||||
from dataclasses import dataclass
|
||||
import importlib.resources
|
||||
|
||||
console = Console(stderr=True)
|
||||
|
||||
debug_mode = False
|
||||
DEBUG_PREFIX = render("[yellow bold]DEBUG[/]")
|
||||
|
||||
|
||||
def debug(msg: str, remove_styling=False) -> None:
|
||||
"""
|
||||
Print debug message in console
|
||||
|
||||
:param msg: Message to print
|
||||
:param remove_styling: Remove automated styling from message
|
||||
"""
|
||||
if debug_mode:
|
||||
if remove_styling:
|
||||
rendered_msg = render(msg, style=Style(bold=False, color="white"))
|
||||
console.print(DEBUG_PREFIX, rendered_msg)
|
||||
else:
|
||||
console.print(DEBUG_PREFIX, msg)
|
||||
|
||||
|
||||
def info(msg: str) -> None:
|
||||
"""
|
||||
Print message in log
|
||||
Print message in console
|
||||
|
||||
:param msg: Message to print
|
||||
"""
|
||||
console.print(msg)
|
||||
|
||||
|
||||
def error(msg: str) -> None:
|
||||
console.print(msg)
|
||||
|
||||
|
||||
def print_error_file(name: str, **kwargs) -> None:
|
||||
"""
|
||||
Print predefined error message
|
||||
|
||||
:param name: Name of error file
|
||||
"""
|
||||
message = importlib.resources.files("grawlix") \
|
||||
.joinpath(f"assets/errors/{name}.txt") \
|
||||
.read_text("utf8") \
|
||||
.format(**kwargs) \
|
||||
.strip()
|
||||
error(message)
|
||||
|
||||
|
||||
def progress(category_name: str, source_name: str, count=1) -> Progress:
|
||||
if count > 1:
|
||||
console.print(f"Downloading [yellow not bold]{count}[/] books in [blue]{category_name}[/] from [magenta]{source_name}[/]")
|
||||
@ -31,6 +72,7 @@ def progress(category_name: str, source_name: str, count=1) -> Progress:
|
||||
)
|
||||
return progress
|
||||
|
||||
|
||||
def add_book(progress: Progress, book: Book) -> TaskID:
|
||||
task = progress.add_task(
|
||||
f"[blue]{book.metadata.title}[/]",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from grawlix.exceptions import NoSourceFound
|
||||
from grawlix.exceptions import InvalidUrl
|
||||
|
||||
from .source import Source
|
||||
from .ereolen import Ereolen
|
||||
@ -42,7 +42,7 @@ def find_source(url: str) -> type[Source]:
|
||||
for num, match in enumerate(cls.match):
|
||||
if re.match(match, url):
|
||||
return cls
|
||||
raise NoSourceFound
|
||||
raise InvalidUrl
|
||||
|
||||
|
||||
def get_source_classes() -> list[type[Source]]:
|
||||
|
||||
@ -2,6 +2,7 @@ from grawlix.exceptions import DataNotFound
|
||||
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
from functools import lru_cache
|
||||
import importlib.resources
|
||||
|
||||
def get_arg_from_url(url: str, key: str) -> str:
|
||||
parsed_url = urlparse(url)
|
||||
@ -38,3 +39,14 @@ def nearest_string(input: str, list: list[str]) -> str:
|
||||
Finds the nearest string in `list` to `input` based on levenstein distance
|
||||
"""
|
||||
return sorted(list, key = lambda x: levenstein_distance(input, x))[0]
|
||||
|
||||
|
||||
def read_asset_file(path: str) -> str:
|
||||
"""
|
||||
Read asset file from the grawlix module
|
||||
|
||||
:param path: Path relative to root of grawlix module
|
||||
"""
|
||||
return importlib.resources.files("grawlix") \
|
||||
.joinpath(path) \
|
||||
.read_text(encoding="utf8")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user