Skip to content

Commit

Permalink
Service order adjustments (#15)
Browse files Browse the repository at this point in the history
- Set service order, fixes #14
- Only process necessary archives
  • Loading branch information
Buried-In-Code authored May 20, 2024
1 parent 95ed2dc commit f42de90
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 22 deletions.
1 change: 1 addition & 0 deletions perdoo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def setup_logging(debug: bool = False) -> None:
console_handler.setLevel(logging.DEBUG if debug else logging.INFO)
console_handler.setFormatter(logging.Formatter("%(message)s"))
file_handler = logging.FileHandler(filename=log_folder / "perdoo.log")
file_handler.setLevel(logging.DEBUG)
logging.basicConfig(
format="[%(asctime)s] [%(levelname)-8s] {%(name)s} | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
Expand Down
67 changes: 50 additions & 17 deletions perdoo/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from perdoo.models.metadata import Format, Meta, Source, Tool
from perdoo.models.metron_info import InformationSource
from perdoo.services import Comicvine, League, Marvel, Metron
from perdoo.settings import OutputFormat, Settings
from perdoo.settings import OutputFormat, Service, Settings
from perdoo.utils import Details, Identifications, get_metadata_id, list_files, sanitize

LOGGER = logging.getLogger("perdoo")
Expand Down Expand Up @@ -47,14 +47,15 @@ def convert_collection(path: Path, output: OutputFormat) -> None:
archive_type.convert(old_archive=archive)


def read_meta(archive: BaseArchive) -> tuple[Meta, Details]:
def read_meta(archive: BaseArchive) -> tuple[Meta | None, Details | None]:
filenames = archive.list_filenames()

def read_meta_file(cls: type[InfoModel], filename: str) -> InfoModel | None:
if filename in filenames:
return cls.from_bytes(content=archive.read_file(filename=filename))
return None

# region Read Metadata
try:
metadata = read_meta_file(cls=Metadata, filename="/Metadata.xml") or read_meta_file(
cls=Metadata, filename="Metadata.xml"
Expand Down Expand Up @@ -97,6 +98,9 @@ def read_meta_file(cls: type[InfoModel], filename: str) -> InfoModel | None:
return meta, details
except ValidationError:
LOGGER.error("%s contains an invalid Metadata file", archive.path.name) # noqa: TRY400
# endregion

# region Read MetronInfo
try:
metron_info = read_meta_file(cls=MetronInfo, filename="/MetronInfo.xml") or read_meta_file(
cls=MetronInfo, filename="MetronInfo.xml"
Expand Down Expand Up @@ -139,6 +143,9 @@ def read_meta_file(cls: type[InfoModel], filename: str) -> InfoModel | None:
return Meta(date_=date.today(), tool=Tool(value="MetronInfo")), details
except ValidationError:
LOGGER.error("%s contains an invalid MetronInfo file", archive.path.name) # noqa: TRY400
# endregion

# region Read ComicInfo
try:
comic_info = read_meta_file(cls=ComicInfo, filename="/ComicInfo.xml") or read_meta_file(
cls=ComicInfo, filename="ComicInfo.xml"
Expand All @@ -151,11 +158,28 @@ def read_meta_file(cls: type[InfoModel], filename: str) -> InfoModel | None:
return Meta(date_=date.today(), tool=Tool(value="ComicInfo")), details
except ValidationError:
LOGGER.error("%s contains an invalid ComicInfo file", archive.path.name) # noqa: TRY400

return Meta(date_=date.today(), tool=Tool(value="Manual")), Details(
series=Identifications(search=Prompt.ask("Series title", console=CONSOLE)),
issue=Identifications(),
)
# endregion

return None, None


def load_archives(
path: Path, output: OutputFormat, force: bool = False
) -> list[tuple[Path, BaseArchive, Details | None]]:
archives = []
with CONSOLE.status(f"Searching for {output} files"):
for file in list_files(path, f".{output}"):
archive = get_archive(path=file)
LOGGER.debug("Reading %s", file.stem)
meta, details = read_meta(archive=archive)
if not meta or not details:
archives.append((file, archive, details))
continue
difference = abs(date.today() - meta.date_)
if force or meta.tool != Tool() or difference.days >= 28:
archives.append((file, archive, details))
continue
return archives


def fetch_from_services(
Expand All @@ -181,7 +205,15 @@ def fetch_from_services(
LOGGER.warning("No external services configured")
return None, None, None

for service in (marvel, metron, comicvine, league):
services = {
Service.COMICVINE: comicvine,
Service.LEAGUE_OF_COMIC_GEEKS: league,
Service.MARVEL: marvel,
Service.METRON: metron,
}

for service_name in settings.service_order:
service = services[service_name]
if not service:
continue
LOGGER.info("Fetching details from %s", type(service).__name__)
Expand Down Expand Up @@ -243,6 +275,7 @@ def process_pages(
from perdoo.models.metadata import Page as MetadataPage
from perdoo.models.metron_info import Page as MetronPage

LOGGER.info("Processing pages")
rename_images(folder=folder, filename=filename)
image_list = list_files(folder, *IMAGE_EXTENSIONS)
metadata_pages = set()
Expand Down Expand Up @@ -272,16 +305,17 @@ def process_pages(
def start(settings: Settings, force: bool = False) -> None:
LOGGER.info("Starting Perdoo")
convert_collection(path=settings.collection_folder, output=settings.output.format)
for file in list_files(settings.collection_folder, f".{settings.output.format}"):
archive = get_archive(path=file)
archives = load_archives(
path=settings.collection_folder, output=settings.output.format, force=force
)

for file, archive, details in archives:
CONSOLE.rule(file.stem)
LOGGER.info("Processing %s", file.stem)
meta, details = read_meta(archive=archive)

if not force:
difference = abs(date.today() - meta.date_)
if meta.tool == Tool() and difference.days < 28:
continue
details = details or Details( # noqa: PLW2901
series=Identifications(search=Prompt.ask("Series title", console=CONSOLE)),
issue=Identifications(),
)

metadata, metron_info, comic_info = fetch_from_services(settings=settings, details=details)
new_file = generate_filename(
Expand All @@ -293,7 +327,6 @@ def start(settings: Settings, force: bool = False) -> None:
temp_folder = Path(temp_str)
if not archive.extract_files(destination=temp_folder):
return
LOGGER.info("Processing %s pages", file.stem)
process_pages(
folder=temp_folder,
metadata=metadata,
Expand Down
4 changes: 3 additions & 1 deletion perdoo/archives/cb7.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ def convert(old_archive: BaseArchive) -> CB7Archive | None:
temp_folder = Path(temp_str)
if not old_archive.extract_files(destination=temp_folder):
return None
archive_file = CB7Archive.archive_files(src=temp_folder, filename=old_archive.path.stem)
archive_file = CB7Archive.archive_files(
src=temp_folder, output_name=old_archive.path.stem
)
if not archive_file:
return None
new_filepath = old_archive.path.parent / f"{old_archive.path.stem}.cb7"
Expand Down
4 changes: 3 additions & 1 deletion perdoo/archives/cbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def convert(old_archive: BaseArchive) -> CBTArchive | None:
temp_folder = Path(temp_str)
if not old_archive.extract_files(destination=temp_folder):
return None
archive_file = CBTArchive.archive_files(src=temp_folder, filename=old_archive.path.stem)
archive_file = CBTArchive.archive_files(
src=temp_folder, output_name=old_archive.path.stem
)
if not archive_file:
return None
new_filepath = old_archive.path.parent / f"{old_archive.path.stem}.cbt"
Expand Down
4 changes: 3 additions & 1 deletion perdoo/archives/cbz.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def convert(old_archive: BaseArchive) -> CBZArchive | None:
temp_folder = Path(temp_str)
if not old_archive.extract_files(destination=temp_folder):
return None
archive_file = CBZArchive.archive_files(src=temp_folder, filename=old_archive.path.stem)
archive_file = CBZArchive.archive_files(
src=temp_folder, output_name=old_archive.path.stem
)
if not archive_file:
return None
new_filepath = old_archive.path.parent / f"{old_archive.path.stem}.cbz"
Expand Down
4 changes: 2 additions & 2 deletions perdoo/services/marvel.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

class Marvel(BaseService[Series, Comic]):
def __init__(self: Marvel, settings: MarvelSettings):
cache = SqliteCache(db_name=str(get_cache_dir() / "mokkari.sqlite"), expire=14)
cache = SqliteCache(db_name=str(get_cache_dir() / "esak.sqlite"), expire=14)
self.session = Esak(
public_key=settings.public_key, private_key=settings.private_key, cache=cache
)
Expand All @@ -40,7 +40,7 @@ def _get_series_id(self: Marvel, title: str | None) -> int | None:
if not options:
LOGGER.warning("Unable to find any Series with the title: '%s'", title)
index = create_menu(
options=[f"{x.id} | {x.title} ({x.start_year})" for x in options],
options=[f"{x.id} | {x.title}" for x in options],
title="Marvel Series",
default="None of the Above",
)
Expand Down
29 changes: 29 additions & 0 deletions perdoo/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ def __str__(self: OutputFormat) -> str:
return self.value


class Service(Enum):
COMICVINE = "Comicvine"
LEAGUE_OF_COMIC_GEEKS = "League of Comic Geeks"
MARVEL = "Marvel"
METRON = "Metron"

@staticmethod
def load(value: str) -> Service:
for entry in Service:
if entry.value.casefold() == value.casefold():
return entry
raise ValueError(f"`{value}` isn't a valid Service")

def __lt__(self: Service, other) -> int: # noqa: ANN001
if not isinstance(other, type(self)):
raise NotImplementedError
return self.value < other.value

def __str__(self: Service) -> str:
return self.value


class Output(SettingsModel):
create_comic_info: bool = True
create_metron_info: bool = True
Expand All @@ -99,6 +121,12 @@ class Settings(SettingsModel):
league_of_comic_geeks: LeagueofComicGeeks = LeagueofComicGeeks()
marvel: Marvel = Marvel()
metron: Metron = Metron()
service_order: list[Service] = [
Service.METRON,
Service.MARVEL,
Service.COMICVINE,
Service.LEAGUE_OF_COMIC_GEEKS,
]
output: Output = Output()

@classmethod
Expand All @@ -113,6 +141,7 @@ def save(self: Settings) -> Settings:
with self._filename.open("wb") as stream:
content = self.dict(by_alias=False)
content["collection_folder"] = str(content["collection_folder"])
content["service_order"] = [str(x) for x in content["service_order"]]
content["output"]["format"] = str(content["output"]["format"])
tomlwriter.dump(content, stream)
return self

0 comments on commit f42de90

Please sign in to comment.