big upgrade UwU
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Download settings and file-type handling."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from sticker_downloader.errors import InvalidFileType
|
||||
|
||||
STATIC = "webp"
|
||||
ANIMATED = "tgs"
|
||||
VIDEO = "webm"
|
||||
THUMBNAIL = "png"
|
||||
|
||||
#: Every type the downloader knows how to save, in a stable display order.
|
||||
ALL_FILE_TYPES: tuple[str, ...] = (STATIC, ANIMATED, VIDEO, THUMBNAIL)
|
||||
|
||||
FILE_TYPE_HELP: dict[str, str] = {
|
||||
STATIC: "static stickers",
|
||||
ANIMATED: "animated stickers (Lottie)",
|
||||
VIDEO: "video stickers",
|
||||
THUMBNAIL: "PNG thumbnails",
|
||||
}
|
||||
|
||||
DEFAULT_OUTPUT_DIR = Path("downloads")
|
||||
DEFAULT_URL_FILE = Path("urls.txt")
|
||||
DEFAULT_CONCURRENCY = 8
|
||||
DEFAULT_RETRIES = 3
|
||||
METADATA_FILE_NAME = "pack.json"
|
||||
PACK_THUMBNAIL_STEM = "_pack_thumbnail"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DownloadConfig:
|
||||
"""Everything that shapes a download run."""
|
||||
|
||||
file_types: frozenset[str] = field(default_factory=lambda: frozenset(ALL_FILE_TYPES))
|
||||
output_dir: Path = DEFAULT_OUTPUT_DIR
|
||||
concurrency: int = DEFAULT_CONCURRENCY
|
||||
retries: int = DEFAULT_RETRIES
|
||||
overwrite: bool = False
|
||||
write_metadata: bool = True
|
||||
pack_thumbnail: bool = True
|
||||
emoji_names: bool = False
|
||||
dry_run: bool = False
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
unknown = sorted(self.file_types - set(ALL_FILE_TYPES))
|
||||
if unknown:
|
||||
raise InvalidFileType(f"unknown file type(s): {', '.join(unknown)}")
|
||||
if not self.file_types:
|
||||
raise InvalidFileType("at least one file type is required")
|
||||
if self.concurrency < 1:
|
||||
raise ValueError("concurrency must be at least 1")
|
||||
if self.retries < 1:
|
||||
raise ValueError("retries must be at least 1")
|
||||
|
||||
@property
|
||||
def sorted_file_types(self) -> list[str]:
|
||||
"""The requested types in canonical order, for stable output."""
|
||||
return [file_type for file_type in ALL_FILE_TYPES if file_type in self.file_types]
|
||||
|
||||
def wants(self, file_type: str) -> bool:
|
||||
return file_type in self.file_types
|
||||
|
||||
|
||||
def parse_file_types(raw: str | None) -> frozenset[str]:
|
||||
"""Turn user input such as ``"webp, png"``, ``"all"`` or ``""`` into a type set.
|
||||
|
||||
Empty input and ``"all"`` both mean "every supported type", matching what the
|
||||
interactive prompt advertises.
|
||||
"""
|
||||
text = (raw or "").strip().lower()
|
||||
if not text or text == "all":
|
||||
return frozenset(ALL_FILE_TYPES)
|
||||
|
||||
requested = [part.strip().lstrip(".") for part in text.replace(" ", ",").split(",")]
|
||||
selected = {part for part in requested if part}
|
||||
if not selected:
|
||||
raise InvalidFileType("no file types given")
|
||||
|
||||
unknown = sorted(selected - set(ALL_FILE_TYPES))
|
||||
if unknown:
|
||||
raise InvalidFileType(
|
||||
f"unknown file type(s): {', '.join(unknown)}. "
|
||||
f"Supported: {', '.join(ALL_FILE_TYPES)}, or 'all'."
|
||||
)
|
||||
return frozenset(selected)
|
||||
Reference in New Issue
Block a user