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 .book import Book, Series
|
||||||
from .config import load_config, Config, SourceConfig
|
from .config import load_config, Config, SourceConfig
|
||||||
from .exceptions import SourceNotAuthenticated
|
from .exceptions import SourceNotAuthenticated, GrawlixError
|
||||||
from .sources import load_source, Source
|
from .sources import load_source, Source
|
||||||
from .output import download_book
|
from .output import download_book
|
||||||
from . import arguments, logging
|
from . import arguments, logging
|
||||||
@ -68,23 +68,27 @@ async def authenticate(source: Source, config: Config, options):
|
|||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
args = arguments.parse_arguments()
|
args = arguments.parse_arguments()
|
||||||
config = load_config()
|
config = load_config()
|
||||||
|
logging.debug_mode = args.debug
|
||||||
urls = get_urls(args)
|
urls = get_urls(args)
|
||||||
for url in urls:
|
for url in urls:
|
||||||
source: Source = load_source(url)
|
try:
|
||||||
if not source.authenticated and source.requires_authentication:
|
source: Source = load_source(url)
|
||||||
await authenticate(source, config, args)
|
if not source.authenticated and source.requires_authentication:
|
||||||
result = await source.download(url)
|
await authenticate(source, config, args)
|
||||||
if isinstance(result, Book):
|
result = await source.download(url)
|
||||||
with logging.progress(result.metadata.title, source.name) as progress:
|
if isinstance(result, Book):
|
||||||
template: str = args.output or "{title}.{ext}"
|
with logging.progress(result.metadata.title, source.name) as progress:
|
||||||
await download_with_progress(result, progress, template)
|
template: str = args.output or "{title}.{ext}"
|
||||||
elif isinstance(result, Series):
|
await download_with_progress(result, progress, template)
|
||||||
with logging.progress(result.title, source.name, len(result.book_ids)) as progress:
|
elif isinstance(result, Series):
|
||||||
for book_id in result.book_ids:
|
with logging.progress(result.title, source.name, len(result.book_ids)) as progress:
|
||||||
book: Book = await source.download_book_from_id(book_id)
|
for book_id in result.book_ids:
|
||||||
template: str = args.output or "{series}/{title}.{ext}"
|
book: Book = await source.download_book_from_id(book_id)
|
||||||
await download_with_progress(book, progress, template)
|
template: str = args.output or "{series}/{title}.{ext}"
|
||||||
logging.info("")
|
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):
|
async def download_with_progress(book: Book, progress: Progress, template: str):
|
||||||
|
|||||||
@ -51,4 +51,10 @@ def parse_arguments() -> argparse.Namespace:
|
|||||||
help = "Output destination",
|
help = "Output destination",
|
||||||
dest = "output"
|
dest = "output"
|
||||||
)
|
)
|
||||||
|
# Logging
|
||||||
|
parser.add_argument(
|
||||||
|
'--debug',
|
||||||
|
help = "Enable debug messages",
|
||||||
|
dest = "debug"
|
||||||
|
)
|
||||||
return parser.parse_args()
|
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):
|
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):
|
class DataNotFound(GrawlixError):
|
||||||
pass
|
error_file = "data_not_found"
|
||||||
|
|
||||||
class InvalidUrl(GrawlixError):
|
class InvalidUrl(GrawlixError):
|
||||||
pass
|
error_file = "invalid_url"
|
||||||
|
|
||||||
class UnsupportedOutputFormat(GrawlixError):
|
class UnsupportedOutputFormat(GrawlixError):
|
||||||
pass
|
error_file = "unsupported_output_format"
|
||||||
|
|
||||||
class NoSourceFound(GrawlixError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SourceNotAuthenticated(GrawlixError):
|
class SourceNotAuthenticated(GrawlixError):
|
||||||
pass
|
error_file = "source_not_authenticated"
|
||||||
|
|
||||||
class MissingArgument(GrawlixError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ThrottleError(GrawlixError):
|
class ThrottleError(GrawlixError):
|
||||||
pass
|
error_file = "throttle"
|
||||||
|
|||||||
@ -1,22 +1,63 @@
|
|||||||
from grawlix.book import Book
|
from grawlix.book import Book
|
||||||
|
|
||||||
from rich.console import Console
|
|
||||||
from rich.progress import Progress, BarColumn, ProgressColumn, TaskID, SpinnerColumn
|
|
||||||
import rich
|
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 typing import Union
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
import importlib.resources
|
||||||
|
|
||||||
console = Console(stderr=True)
|
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:
|
def info(msg: str) -> None:
|
||||||
"""
|
"""
|
||||||
Print message in log
|
Print message in console
|
||||||
|
|
||||||
:param msg: Message to print
|
:param msg: Message to print
|
||||||
"""
|
"""
|
||||||
console.print(msg)
|
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:
|
def progress(category_name: str, source_name: str, count=1) -> Progress:
|
||||||
if count > 1:
|
if count > 1:
|
||||||
console.print(f"Downloading [yellow not bold]{count}[/] books in [blue]{category_name}[/] from [magenta]{source_name}[/]")
|
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
|
return progress
|
||||||
|
|
||||||
|
|
||||||
def add_book(progress: Progress, book: Book) -> TaskID:
|
def add_book(progress: Progress, book: Book) -> TaskID:
|
||||||
task = progress.add_task(
|
task = progress.add_task(
|
||||||
f"[blue]{book.metadata.title}[/]",
|
f"[blue]{book.metadata.title}[/]",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from grawlix.exceptions import NoSourceFound
|
from grawlix.exceptions import InvalidUrl
|
||||||
|
|
||||||
from .source import Source
|
from .source import Source
|
||||||
from .ereolen import Ereolen
|
from .ereolen import Ereolen
|
||||||
@ -42,7 +42,7 @@ def find_source(url: str) -> type[Source]:
|
|||||||
for num, match in enumerate(cls.match):
|
for num, match in enumerate(cls.match):
|
||||||
if re.match(match, url):
|
if re.match(match, url):
|
||||||
return cls
|
return cls
|
||||||
raise NoSourceFound
|
raise InvalidUrl
|
||||||
|
|
||||||
|
|
||||||
def get_source_classes() -> list[type[Source]]:
|
def get_source_classes() -> list[type[Source]]:
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from grawlix.exceptions import DataNotFound
|
|||||||
|
|
||||||
from urllib.parse import urlparse, parse_qs
|
from urllib.parse import urlparse, parse_qs
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
import importlib.resources
|
||||||
|
|
||||||
def get_arg_from_url(url: str, key: str) -> str:
|
def get_arg_from_url(url: str, key: str) -> str:
|
||||||
parsed_url = urlparse(url)
|
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
|
Finds the nearest string in `list` to `input` based on levenstein distance
|
||||||
"""
|
"""
|
||||||
return sorted(list, key = lambda x: levenstein_distance(input, x))[0]
|
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