diff --git a/cbz/comic.py b/cbz/comic.py index 8a4d02c..7e395f4 100644 --- a/cbz/comic.py +++ b/cbz/comic.py @@ -10,7 +10,7 @@ from langcodes import Language from pathlib import Path from cbz import utils -from cbz.constants import YesNo, Manga, AgeRating, Format +from cbz.constants import YesNo, Manga, AgeRating, Format, xml_name from cbz.page import PageInfo @@ -30,50 +30,50 @@ class ComicInfo: def __init__(self, pages: [PageInfo], **kwargs): self.__pages = pages self.__info = { - 'Title': str(kwargs.get('title', '')), - 'Series': str(kwargs.get('series', '')), - 'Number': str(kwargs.get('number', '')), - 'Count': int(kwargs.get('count', -1)), - 'Volume': int(kwargs.get('volume', -1)), - 'AlternateSeries': str(kwargs.get('alternate_series', '')), - 'AlternateNumber': str(kwargs.get('alternate_number', '')), - 'AlternateCount': int(kwargs.get('alternate_count', -1)), - 'Summary': str(kwargs.get('summary', '')), - 'Notes': str(kwargs.get('notes', '')), - 'Year': int(kwargs.get('year', -1)), - 'Month': int(kwargs.get('month', -1)), - 'Day': int(kwargs.get('day', -1)), - 'Writer': str(kwargs.get('writer', '')), - 'Penciller': str(kwargs.get('penciller', '')), - 'Inker': str(kwargs.get('inker', '')), - 'Colorist': str(kwargs.get('colorist', '')), - 'Letterer': str(kwargs.get('letterer', '')), - 'CoverArtist': str(kwargs.get('cover_artist', '')), - 'Editor': str(kwargs.get('editor', '')), - 'Translator': str(kwargs.get('translator', '')), - 'Publisher': str(kwargs.get('publisher', '')), - 'Imprint': str(kwargs.get('imprint', '')), - 'Genre': str(kwargs.get('genre', '')), - 'Tags': str(kwargs.get('tags', '')), - 'Web': str(kwargs.get('web', '')), + 'Title': str(kwargs.get('title', kwargs.get('Title', ''))), + 'Series': str(kwargs.get('series', kwargs.get('Series', ''))), + 'Number': str(kwargs.get('number', kwargs.get('Number', ''))), + 'Count': int(kwargs.get('count', kwargs.get('Count', -1))), + 'Volume': int(kwargs.get('volume', kwargs.get('Volume', -1))), + 'AlternateSeries': str(kwargs.get('alternate_series', kwargs.get('AlternateSeries', ''))), + 'AlternateNumber': str(kwargs.get('alternate_number', kwargs.get('AlternateNumber', ''))), + 'AlternateCount': int(kwargs.get('alternate_count', kwargs.get('AlternateCount', -1))), + 'Summary': str(kwargs.get('summary', kwargs.get('Summary', ''))), + 'Notes': str(kwargs.get('notes', kwargs.get('Notes', ''))), + 'Year': int(kwargs.get('year', kwargs.get('Year', -1))), + 'Month': int(kwargs.get('month', kwargs.get('Month', -1))), + 'Day': int(kwargs.get('day', kwargs.get('Day', -1))), + 'Writer': str(kwargs.get('writer', kwargs.get('Writer', ''))), + 'Penciller': str(kwargs.get('penciller', kwargs.get('Penciller', ''))), + 'Inker': str(kwargs.get('inker', kwargs.get('Inker', ''))), + 'Colorist': str(kwargs.get('colorist', kwargs.get('Colorist', ''))), + 'Letterer': str(kwargs.get('letterer', kwargs.get('Letterer', ''))), + 'CoverArtist': str(kwargs.get('cover_artist', kwargs.get('CoverArtist', ''))), + 'Editor': str(kwargs.get('editor', kwargs.get('Editor', ''))), + 'Translator': str(kwargs.get('translator', kwargs.get('Translator', ''))), + 'Publisher': str(kwargs.get('publisher', kwargs.get('Publisher', ''))), + 'Imprint': str(kwargs.get('imprint', kwargs.get('imprint', 'Imprint'))), + 'Genre': str(kwargs.get('genre', kwargs.get('Genre', ''))), + 'Tags': str(kwargs.get('tags', kwargs.get('Tags', ''))), + 'Web': str(kwargs.get('web', kwargs.get('Web', ''))), 'PageCount': len(self.__pages), - 'LanguageISO': language(kwargs.get('language_iso', '')), - 'Format': Format(kwargs.get('format', Format.UNKNOWN)), - 'EAN': str(kwargs.get('ean', '')), - 'BlackAndWhite': YesNo(kwargs.get('black_white', YesNo.UNKNOWN)), - 'Manga': Manga(kwargs.get('manga', Manga.UNKNOWN)), - 'Characters': str(kwargs.get('characters', '')), - 'Teams': str(kwargs.get('teams', '')), - 'Locations': str(kwargs.get('locations', '')), - 'ScanInformation': str(kwargs.get('scan_information', '')), - 'StoryArc': str(kwargs.get('story_arc', '')), - 'StoryArcNumber': str(kwargs.get('story_arc_number', '')), - 'SeriesGroup': str(kwargs.get('series_group', '')), - 'AgeRating': AgeRating(kwargs.get('age_rating', AgeRating.UNKNOWN)), + 'LanguageISO': language(kwargs.get('language_iso', kwargs.get('LanguageISO', ''))), + 'Format': Format(kwargs.get('format', kwargs.get('Format', Format.UNKNOWN))), + 'EAN': str(kwargs.get('ean', kwargs.get('EAN', ''))), + 'BlackAndWhite': YesNo(kwargs.get('black_white', kwargs.get('BlackAndWhite', YesNo.UNKNOWN))), + 'Manga': Manga(kwargs.get('manga', kwargs.get('Manga', Manga.UNKNOWN))), + 'Characters': str(kwargs.get('characters', kwargs.get('Characters', ''))), + 'Teams': str(kwargs.get('teams', kwargs.get('Teams', ''))), + 'Locations': str(kwargs.get('locations', kwargs.get('Locations', ''))), + 'ScanInformation': str(kwargs.get('scan_information', kwargs.get('ScanInformation', ''))), + 'StoryArc': str(kwargs.get('story_arc', kwargs.get('StoryArc', ''))), + 'StoryArcNumber': str(kwargs.get('story_arc_number', kwargs.get('StoryArcNumber', ''))), + 'SeriesGroup': str(kwargs.get('series_group', kwargs.get('series_group', ''))), + 'AgeRating': AgeRating(kwargs.get('age_rating', kwargs.get('AgeRating', AgeRating.UNKNOWN))), 'Pages': [{'Image': i, **page.dumps()} for i, page in enumerate(pages)], - 'CommunityRating': rating(kwargs.get('community_rating', -1)), - 'MainCharacterOrTeam': str(kwargs.get('main_character_or_team', '')), - 'Review': str(kwargs.get('review', '')) + 'CommunityRating': rating(kwargs.get('community_rating', kwargs.get('CommunityRating', -1))), + 'MainCharacterOrTeam': str(kwargs.get('main_character_or_team', kwargs.get('MainCharacterOrTeam', ''))), + 'Review': str(kwargs.get('review', kwargs.get('Review', ''))) } def dumps(self) -> dict: @@ -90,17 +90,29 @@ class ComicInfo: def from_cbz(cls, path: Union[Path, str]) -> ComicInfo: if not isinstance(path, (Path, str)): raise ValueError(f'Expecting Path object or path string, got {path!r}') - with Path(path).open(mode='rb') as f: - return cls(cls.__unpack(f.read())) + return cls(**cls.__unpack(Path(path))) - def __unpack(self, data: bytes) -> tuple[[PageInfo], dict]: - raise NotImplemented + @staticmethod + def __unpack(file_path: Path) -> dict: + with zipfile.ZipFile(file_path, 'r', zipfile.ZIP_STORED) as zip_file: + _files = zip_file.namelist() + assert xml_name in _files, f"{xml_name} not found in: {zip_file.filename}" + xml_file = zip_file.open(xml_name) + info = xmltodict.parse(xml_file.read()).get("ComicInfo") + xml_file.close() + _files.remove(xml_name) + info["pages"] = list() + for filename in _files: + page_file = zip_file.open(filename) + info["pages"].append(PageInfo.loads(page_file.read())) + page_file.close() + return info def pack(self) -> bytes: zip_buffer = BytesIO() with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_STORED) as zip_file: zip_file.writestr( - 'ComicInfo.xml', + xml_name, xmltodict.unparse({'ComicInfo': self.dumps()}, pretty=True).encode('utf-8') ) diff --git a/cbz/constants.py b/cbz/constants.py index 4060b13..91b0991 100644 --- a/cbz/constants.py +++ b/cbz/constants.py @@ -1,5 +1,7 @@ from enum import Enum +xml_name = "ComicInfo.xml" + class YesNo(Enum): UNKNOWN = 'Unknown'