92 lines
3.0 KiB
Python
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."""
|