animedex.backends.anilist.models

Rich AniList dataclasses (one per Query root we surface).

the high-level backend layer: every anonymous Query root field on AniList’s GraphQL schema gets a typed pydantic dataclass here. Core entities (Media, Character, Staff, Studio) carry to_common() projections onto the cross-source types in animedex.models. Long-tail entities (MediaTrend, AiringSchedule, Review, Recommendation, Thread, ThreadComment, Activity, MediaList, MediaListCollection, Following, Follower, SiteStatistics, ExternalLinkSourceCollection, MediaTagCollection, GenreCollection) expose their own typed shape but do not have a common projection — they are AniList-specific concepts.

All models inherit AnimedexModel (immutable, extra='ignore') so unknown upstream fields are dropped silently and round-trip through JSON cleanly.

AnilistAnime

class animedex.backends.anilist.models.AnilistAnime(*, id: int, idMal: int | None = None, title: _AnilistTitle = _AnilistTitle(romaji=None, english=None, native=None), synonyms: List[str] = [], type: str | None = None, format: str | None = None, status: str | None = None, episodes: int | None = None, duration: int | None = None, season: str | None = None, seasonYear: int | None = None, startDate: _AnilistFuzzyDate | None = None, endDate: _AnilistFuzzyDate | None = None, genres: List[str] = [], tags: List[_AnilistTag] = [], averageScore: int | None = None, meanScore: int | None = None, popularity: int | None = None, favourites: int | None = None, trending: int | None = None, isAdult: bool | None = None, countryOfOrigin: str | None = None, description: str | None = None, source: str | None = None, coverImage: _AnilistCoverImage | None = None, bannerImage: str | None = None, trailer: _AnilistTrailer | None = None, studios: _AnilistStudioConnection | None = None, nextAiringEpisode: _AnilistNextAiringEpisode | None = None, externalLinks: List[_AnilistExternalLink] = [], streamingEpisodes: List[_AnilistStreamingEpisode] = [], source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Full AniList Media (anime / manga) record.

Field-for-field projection of the Q_MEDIA_BY_ID response. to_common() projects onto the cross-source Anime.

id: int
idMal: int | None
title: _AnilistTitle
synonyms: List[str]
type: str | None
format: str | None
status: str | None
episodes: int | None
duration: int | None
season: str | None
seasonYear: int | None
startDate: _AnilistFuzzyDate | None
endDate: _AnilistFuzzyDate | None
genres: List[str]
tags: List[_AnilistTag]
averageScore: int | None
meanScore: int | None
popularity: int | None
favourites: int | None
trending: int | None
isAdult: bool | None
countryOfOrigin: str | None
description: str | None
source: str | None
coverImage: _AnilistCoverImage | None
bannerImage: str | None
trailer: _AnilistTrailer | None
studios: _AnilistStudioConnection | None
nextAiringEpisode: _AnilistNextAiringEpisode | None
streamingEpisodes: List[_AnilistStreamingEpisode]
source_tag: SourceTag
to_common() Anime[source]

Project onto the cross-source Anime.

AnilistCharacter

class animedex.backends.anilist.models.AnilistCharacter(*, id: int, name: _AnilistName = _AnilistName(full=None, native=None, alternative=[]), image: _AnilistImage | None = None, description: str | None = None, gender: str | None = None, age: str | None = None, dateOfBirth: _AnilistFuzzyDate | None = None, bloodType: str | None = None, favourites: int | None = None, media: _AnilistMediaCharacterConnection | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Full AniList Character record.

id: int
name: _AnilistName
image: _AnilistImage | None
description: str | None
gender: str | None
age: str | None
dateOfBirth: _AnilistFuzzyDate | None
bloodType: str | None
favourites: int | None
media: _AnilistMediaCharacterConnection | None
source_tag: SourceTag
to_common() Character[source]

AnilistStaff

class animedex.backends.anilist.models.AnilistStaff(*, id: int, name: _AnilistName = _AnilistName(full=None, native=None, alternative=[]), image: _AnilistImage | None = None, description: str | None = None, primaryOccupations: List[str] = [], gender: str | None = None, age: int | None = None, dateOfBirth: _AnilistFuzzyDate | None = None, yearsActive: List[int] = [], homeTown: str | None = None, languageV2: str | None = None, favourites: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Full AniList Staff record.

id: int
name: _AnilistName
image: _AnilistImage | None
description: str | None
primaryOccupations: List[str]
gender: str | None
age: int | None
dateOfBirth: _AnilistFuzzyDate | None
yearsActive: List[int]
homeTown: str | None
languageV2: str | None
favourites: int | None
source_tag: SourceTag
to_common() Staff[source]

AnilistStudio

class animedex.backends.anilist.models.AnilistStudio(*, id: int, name: str, isAnimationStudio: bool | None = None, favourites: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Full AniList Studio record.

id: int
name: str
isAnimationStudio: bool | None
favourites: int | None
source_tag: SourceTag
to_common() Studio[source]

AnilistMediaTrend

class animedex.backends.anilist.models.AnilistMediaTrend(*, mediaId: int | None = None, date: int, trending: int | None = None, averageScore: int | None = None, popularity: int | None = None, inProgress: int | None = None, episode: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_MEDIA_TREND — daily trending stats.

mediaId: int | None
date: int
trending: int | None
averageScore: int | None
popularity: int | None
inProgress: int | None
episode: int | None
source_tag: SourceTag

AnilistAiringSchedule

class animedex.backends.anilist.models.AnilistAiringSchedule(*, id: int, airingAt: int, episode: int, timeUntilAiring: int, media_id: int | None = None, media_title_romaji: str | None = None, raw_payload: ~typing.Dict[str, ~typing.Any] = <factory>, source_tag: ~animedex.models.common.SourceTag, **extra_data: ~typing.Any)[source]

Bases: BackendRichModel

One row from Q_AIRING_SCHEDULE.

id: int
airingAt: int
episode: int
timeUntilAiring: int
media_id: int | None
media_title_romaji: str | None
raw_payload: Dict[str, Any]
source_tag: SourceTag
to_common() AiringScheduleRow[source]

Project onto the common airing schedule row.

AnilistReview

class animedex.backends.anilist.models.AnilistReview(*, id: int, summary: str | None = None, score: int | None = None, rating: int | None = None, ratingAmount: int | None = None, user_name: str | None = None, siteUrl: str | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_REVIEW.

id: int
summary: str | None
score: int | None
rating: int | None
ratingAmount: int | None
user_name: str | None
siteUrl: str | None
source_tag: SourceTag

AnilistRecommendation

class animedex.backends.anilist.models.AnilistRecommendation(*, id: int, rating: int | None = None, media_id: int | None = None, media_title: str | None = None, recommendation_id: int | None = None, recommendation_title: str | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_RECOMMENDATION.

id: int
rating: int | None
media_id: int | None
media_title: str | None
recommendation_id: int | None
recommendation_title: str | None
source_tag: SourceTag

AnilistThread

class animedex.backends.anilist.models.AnilistThread(*, id: int, title: str | None = None, body: str | None = None, user_name: str | None = None, replyCount: int | None = None, viewCount: int | None = None, createdAt: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_THREAD.

id: int
title: str | None
body: str | None
user_name: str | None
replyCount: int | None
viewCount: int | None
createdAt: int | None
source_tag: SourceTag

AnilistThreadComment

class animedex.backends.anilist.models.AnilistThreadComment(*, id: int, comment: str | None = None, user_name: str | None = None, createdAt: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_THREAD_COMMENT.

id: int
comment: str | None
user_name: str | None
createdAt: int | None
source_tag: SourceTag

AnilistActivity

class animedex.backends.anilist.models.AnilistActivity(*, id: int, kind: str, text: str | None = None, status: str | None = None, user_name: str | None = None, media_title: str | None = None, createdAt: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_ACTIVITY (TextActivity / ListActivity).

id: int
kind: str
text: str | None
status: str | None
user_name: str | None
media_title: str | None
createdAt: int | None
source_tag: SourceTag

AnilistActivityReply

class animedex.backends.anilist.models.AnilistActivityReply(*, id: int, text: str | None = None, user_name: str | None = None, createdAt: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_ACTIVITY_REPLY.

id: int
text: str | None
user_name: str | None
createdAt: int | None
source_tag: SourceTag

AnilistFollowEntry

class animedex.backends.anilist.models.AnilistFollowEntry(*, id: int, name: str, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One follower / following entry.

id: int
name: str
source_tag: SourceTag

AnilistMediaListEntry

class animedex.backends.anilist.models.AnilistMediaListEntry(*, id: int, status: str | None = None, score: float | None = None, progress: int | None = None, media_id: int | None = None, media_title: str | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_MEDIA_LIST_PUBLIC.

id: int
status: str | None
score: float | None
progress: int | None
media_id: int | None
media_title: str | None
source_tag: SourceTag

AnilistMediaListGroup

class animedex.backends.anilist.models.AnilistMediaListGroup(*, name: str, status: str | None = None, entry_count: int, **extra_data: Any)[source]

Bases: BackendRichModel

One named list (e.g. Watching) inside a collection.

name: str
status: str | None
entry_count: int

AnilistMediaListCollection

class animedex.backends.anilist.models.AnilistMediaListCollection(*, user_id: int | None = None, user_name: str | None = None, lists: List[AnilistMediaListGroup] = [], source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One MediaListCollection block.

user_id: int | None
user_name: str | None
lists: List[AnilistMediaListGroup]
source_tag: SourceTag

AnilistGenreCollection

class animedex.backends.anilist.models.AnilistGenreCollection(*, genres: List[str] = [], source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

GenreCollection singleton.

genres: List[str]
source_tag: SourceTag

AnilistMediaTag

class animedex.backends.anilist.models.AnilistMediaTag(*, id: int, name: str, description: str | None = None, category: str | None = None, isAdult: bool | None = None, isGeneralSpoiler: bool | None = None, isMediaSpoiler: bool | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from Q_MEDIA_TAG_COLLECTION.

id: int
name: str
description: str | None
category: str | None
isAdult: bool | None
isGeneralSpoiler: bool | None
isMediaSpoiler: bool | None
source_tag: SourceTag

AnilistSiteStatBucket

class animedex.backends.anilist.models.AnilistSiteStatBucket(*, date: int, count: int, change: int, **extra_data: Any)[source]

Bases: BackendRichModel

One date / count / change triple from SiteStatistics.

date: int
count: int
change: int

AnilistSiteStatistics

class animedex.backends.anilist.models.AnilistSiteStatistics(*, users: List[AnilistSiteStatBucket] = [], anime: List[AnilistSiteStatBucket] = [], manga: List[AnilistSiteStatBucket] = [], characters: List[AnilistSiteStatBucket] = [], staff: List[AnilistSiteStatBucket] = [], reviews: List[AnilistSiteStatBucket] = [], source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

SiteStatistics snapshot.

users: List[AnilistSiteStatBucket]
anime: List[AnilistSiteStatBucket]
manga: List[AnilistSiteStatBucket]
characters: List[AnilistSiteStatBucket]
staff: List[AnilistSiteStatBucket]
reviews: List[AnilistSiteStatBucket]
source_tag: SourceTag

AnilistExternalLinkSource

class animedex.backends.anilist.models.AnilistExternalLinkSource(*, id: int, site: str, type: str | None = None, icon: str | None = None, language: str | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One entry from Q_EXTERNAL_LINK_SOURCE_COLLECTION.

id: int
site: str
type: str | None
icon: str | None
language: str | None
source_tag: SourceTag

AnilistUserStatistics

class animedex.backends.anilist.models.AnilistUserStatistics(*, anime_count: int | None = None, anime_mean_score: float | None = None, anime_minutes_watched: int | None = None, manga_count: int | None = None, manga_mean_score: float | None = None, manga_chapters_read: int | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

User profile statistics block.

anime_count: int | None
anime_mean_score: float | None
anime_minutes_watched: int | None
manga_count: int | None
manga_mean_score: float | None
manga_chapters_read: int | None

AnilistUser

class animedex.backends.anilist.models.AnilistUser(*, id: int, name: str, about: str | None = None, avatar_large: str | None = None, siteUrl: str | None = None, statistics: AnilistUserStatistics | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

User record.

id: int
name: str
about: str | None
avatar_large: str | None
siteUrl: str | None
statistics: AnilistUserStatistics | None
source_tag: SourceTag

AnilistNotification

class animedex.backends.anilist.models.AnilistNotification(*, id: int, kind: str, type: str | None = None, contexts: List[str] = [], context: str | None = None, user_name: str | None = None, createdAt: int | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

One row from the authenticated Page.notifications query.

AniList notifications are a polymorphic union (AiringNotification, FollowingNotification, ActivityMessageNotification, etc.). The kind is identified by GraphQL fragment; this model carries the common subset plus a kind discriminator so consumers can branch.

id: int
kind: str
type: str | None
contexts: List[str]
context: str | None
user_name: str | None
createdAt: int | None
source_tag: SourceTag

AnilistMarkdown

class animedex.backends.anilist.models.AnilistMarkdown(*, html: str, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Result of the authenticated Markdown query — rendered HTML.

AniList renders its in-house markdown to HTML server-side. This is the typed wrapper around the html field.

html: str
source_tag: SourceTag

AnilistAniChartUser

class animedex.backends.anilist.models.AnilistAniChartUser(*, user_id: int, user_name: str, settings: dict = {}, highlights: dict = {}, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Authenticated AniChartUser snapshot.

AniChart is a sister project of AniList. settings and highlights are AniList-encoded JSON strings the user’s AniChart profile page reads; we surface them verbatim and let the consumer decode them on demand.

user_id: int
user_name: str
settings: dict
highlights: dict
source_tag: SourceTag

selftest

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

Smoke-test the AniList rich dataclasses by round-tripping a minimally-populated instance of each through pydantic.