animedex.backends.mangadex.models

Rich MangaDex dataclasses (one per resource type).

MangaDex serves data in a JSON:API-flavoured shape: every resource is wrapped as {id, type, attributes, relationships} and listings come back as {result, response, data: [...], limit, offset, total}.

Every class below inherits from BackendRichModel so MangaDex payloads round-trip losslessly: declared fields are typed, undeclared upstream fields are kept on the instance via extra='allow', aliases are accepted via populate_by_name=True, and the same data is re-emitted by model_dump. The attributes sub-classes only spell out the fields the high-level API touches; upstream may add more without breaking callers.

The MangaDexManga.to_common() and MangaDexChapter.to_common() projections map onto Manga and Chapter so a downstream pipeline can diff MangaDex output against any other manga upstream without needing to know JSON:API.

MangaDexMangaAttributes

class animedex.backends.mangadex.models.MangaDexMangaAttributes(*, title: Any | None = None, altTitles: List[Any] | None = None, description: Any | None = None, isLocked: bool | None = None, links: Any | None = None, originalLanguage: str | None = None, lastVolume: str | None = None, lastChapter: str | None = None, publicationDemographic: str | None = None, status: str | None = None, year: int | None = None, contentRating: str | None = None, tags: List[Dict[str, Any]] | None = None, state: str | None = None, chapterNumbersResetOnNewVolume: bool | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /manga/{id} resource.

title: Any | None
altTitles: List[Any] | None
description: Any | None
isLocked: bool | None
originalLanguage: str | None
lastVolume: str | None
lastChapter: str | None
publicationDemographic: str | None
status: str | None
year: int | None
contentRating: str | None
tags: List[Dict[str, Any]] | None
state: str | None
chapterNumbersResetOnNewVolume: bool | None

MangaDexChapterAttributes

class animedex.backends.mangadex.models.MangaDexChapterAttributes(*, volume: str | None = None, chapter: str | None = None, title: str | None = None, translatedLanguage: str | None = None, externalUrl: str | None = None, isUnavailable: bool | None = None, publishAt: str | None = None, readableAt: str | None = None, pages: int | None = None, uploader: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /chapter/{id} resource.

volume: str | None
chapter: str | None
title: str | None
translatedLanguage: str | None
externalUrl: str | None
isUnavailable: bool | None
publishAt: str | None
readableAt: str | None
pages: int | None
uploader: str | None

MangaDexCoverAttributes

class animedex.backends.mangadex.models.MangaDexCoverAttributes(*, description: str | None = None, volume: str | None = None, fileName: str | None = None, locale: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /cover/{id} resource.

description: str | None
volume: str | None
fileName: str | None
locale: str | None

MangaDexManga

class animedex.backends.mangadex.models.MangaDexManga(*, id: str, type: str = 'manga', attributes: MangaDexMangaAttributes | None = None, relationships: List[Dict[str, Any]] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API manga resource from /manga/{id} or /manga?title=....

Variables:
  • id (str) – MangaDex UUID.

  • type (str) – JSON:API type tag — always "manga".

  • attributes (MangaDexMangaAttributes or None) – Typed manga attributes.

  • relationships (list[dict] or None) – List of {id, type, ...} relationship descriptors (authors, artists, cover_art, tags, etc.).

  • source_tag (SourceTag or None) – Provenance tag.

id: str
type: str
attributes: MangaDexMangaAttributes | None
relationships: List[Dict[str, Any]] | None
source_tag: SourceTag | None
to_common() Manga[source]

Project this resource onto the cross-source Manga shape.

Notes:

  • MangaDex’s title and description are language-keyed maps; we pick en first, ja-ro next, then any value.

  • The cross-source Manga.chapters field models a list of Chapter, not a count; MangaDex does not return the chapter list on /manga/{id} (the /manga/{id}/feed endpoint does), so the projection sets chapters=[].

  • status and contentRating map into the constrained common literal sets via _normalise_status and _normalise_format.

MangaDexChapter

class animedex.backends.mangadex.models.MangaDexChapter(*, id: str, type: str = 'chapter', attributes: MangaDexChapterAttributes | None = None, relationships: List[Dict[str, Any]] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API chapter resource from /chapter/{id} or /manga/{id}/feed.

id: str
type: str
attributes: MangaDexChapterAttributes | None
relationships: List[Dict[str, Any]] | None
source_tag: SourceTag | None
to_common() Chapter[source]

Project this resource onto the cross-source Chapter shape.

The cross-source Chapter carries number and language as strings (MangaDex’s "1" / "1.5" / "1.5a" shapes round-trip directly). MangaDex’s publishAt / readableAt timestamps and volume / externalUrl are preserved on the rich shape but the common Chapter does not carry them — reach for the rich model when those fields matter.

MangaDexCover

class animedex.backends.mangadex.models.MangaDexCover(*, id: str, type: str = 'cover_art', attributes: MangaDexCoverAttributes | None = None, relationships: List[Dict[str, Any]] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API cover resource from /cover/{id}.

The fileName attribute is the path component for the upstream cover URL (resolved against https://uploads.mangadex.org/covers/<manga-id>/<fileName>).

id: str
type: str
attributes: MangaDexCoverAttributes | None
relationships: List[Dict[str, Any]] | None
source_tag: SourceTag | None

MangaDexUserAttributes

class animedex.backends.mangadex.models.MangaDexUserAttributes(*, username: str | None = None, roles: List[str] | None = None, avatarFileName: str | None = None, bannerFileName: str | None = None, version: int | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /user/me (or /user/{id}-when-authenticated) resource.

username: str | None
roles: List[str] | None
avatarFileName: str | None
bannerFileName: str | None
version: int | None

MangaDexUser

class animedex.backends.mangadex.models.MangaDexUser(*, id: str, type: str = 'user', attributes: MangaDexUserAttributes | None = None, relationships: List[Dict[str, Any]] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API user resource from /user/me and /user/{id}.

id: str
type: str
attributes: MangaDexUserAttributes | None
relationships: List[Dict[str, Any]] | None
source_tag: SourceTag | None

MangaDexResource

class animedex.backends.mangadex.models.MangaDexResource(*, id: str | None = None, type: str | None = None, attributes: Dict[str, Any] | None = None, relationships: List[Dict[str, Any]] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

Catch-all JSON:API resource for endpoints we wrap but have not typed individually.

Used for /author/{id} / /group/{id} / /list/{id} / /user/{id} / /manga/tag / /manga/{id}/recommendation / /statistics/manga/{id} / /statistics/chapter/{id} / /statistics/group/{id} / /report/reasons/{category} / /manga/{id}/aggregate. The shape is the same JSON:API resource envelope; attributes is left as a dict because the typed-attribute story for these endpoints would multiply the model count without much downstream benefit. extra='allow' round-trips every upstream key.

id: str | None
type: str | None
attributes: Dict[str, Any] | None
relationships: List[Dict[str, Any]] | None
source_tag: SourceTag | None

selftest

animedex.backends.mangadex.models.selftest() bool[source]

Smoke-test the MangaDex rich models.

Validates a synthetic MangaDexManga round-trips through model_dump_json / model_validate_json and projects to a well-formed Manga.

Returns:

True on success; raises on schema drift.

Return type:

bool