Files
manga-mover-and-metadata-co…/src/MediaResolver.py
T

92 lines
3.0 KiB
Python

"""
media_resolver.py
=================
Abstract base class for tracker-specific manga metadata resolvers.
Concrete implementations (MALResolver, AniListResolver) must implement
every abstract method, ensuring a uniform interface regardless of the
underlying data source (Jikan/MAL, AniList GraphQL, …).
"""
from __future__ import annotations
from abc import ABC, abstractmethod
class MediaResolver(ABC):
"""
Abstract base for tracker-specific manga metadata resolvers.
Subclasses connect to a specific tracker API and expose a common
interface for:
- Searching a manga by title → tracker-specific numeric ID
- Fetching summary statistics (score, rank, popularity, …)
- Listing characters and staff (name-only and detailed forms)
- Fetching full details for a single character or person
Methods that accept a tracker ID treat None as "unknown" and return
a safe empty value rather than raising.
"""
@abstractmethod
def find_id(self, title: str) -> "int | None":
"""
Searches the tracker for a manga by title.
Returns the best-matching tracker ID, or None on failure.
"""
@abstractmethod
def get_stats(self, tracker_id: "int | None") -> "dict | None":
"""
Returns a statistics dict for the given tracker ID:
{score, rank, scored_by, popularity, members, favorites,
url, title, as_of (DD-MM-YYYY)}
Returns None if tracker_id is None or on network failure.
"""
@abstractmethod
def get_characters(self, tracker_id: "int | None") -> "list[str]":
"""
Returns a flat list of character name strings for the manga.
Used to populate the ComicInfo <Characters> XML element.
"""
@abstractmethod
def get_characters_detailed(self, tracker_id: "int | None") -> "list[dict]":
"""
Returns detailed character entries for a manga:
[{id, name, image_url, role, about=None, ...}, ...]
'about' is not populated here; call get_character_details() lazily.
"""
@abstractmethod
def get_staff_detailed(self, tracker_id: "int | None") -> "list[dict]":
"""
Returns detailed staff/author entries for a manga:
[{id, name, image_url, positions, about=None, ...}, ...]
'about' is not populated here; call get_person_details() lazily.
"""
@abstractmethod
def get_character_details(self, char_id: "int | None") -> "dict | None":
"""
Returns full details for a single character, including description.
Implementations should cache the result.
"""
@abstractmethod
def get_person_details(self, person_id: "int | None") -> "dict | None":
"""
Returns full details for a single person (staff), including description.
Implementations should cache the result.
"""
@abstractmethod
def clear_cache(self) -> None:
"""Clears all internal caches."""