Skip to content

Types

Base

Bases: Struct

Base class for AniList data structures.

from_dict classmethod

from_dict(data: dict[str, Any]) -> Self

Create an instance of this class from a dictionary.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary representing the instance of this class.

required

Returns:

Type Description
Self

An instance of this class.

Source code in src/seadex/_types.py
@classmethod
def from_dict(cls, data: dict[str, Any], /) -> Self:
    """
    Create an instance of this class from a dictionary.

    Parameters
    ----------
    data : dict[str, Any]
        Dictionary representing the instance of this class.

    Returns
    -------
    Self
        An instance of this class.

    """
    return msgspec.convert(data, type=cls)

from_json classmethod

from_json(data: str | bytes) -> Self

Create an instance of this class from JSON data.

Parameters:

Name Type Description Default
data str | bytes

JSON data representing the instance of this class.

required

Returns:

Type Description
Self

An instance of this class.

Source code in src/seadex/_types.py
@classmethod
def from_json(cls, data: str | bytes, /) -> Self:
    """
    Create an instance of this class from JSON data.

    Parameters
    ----------
    data : str | bytes
        JSON data representing the instance of this class.

    Returns
    -------
    Self
        An instance of this class.

    """
    return msgspec.json.decode(data, type=cls)

to_dict

to_dict() -> dict[str, Any]

Serialize the instance of this class into a dictionary.

Returns:

Type Description
dict[str, Any]

Dictionary representing the instance of this class.

Source code in src/seadex/_types.py
def to_dict(self) -> dict[str, Any]:
    """
    Serialize the instance of this class into a dictionary.

    Returns
    -------
    dict[str, Any]
        Dictionary representing the instance of this class.

    """
    return msgspec.to_builtins(self)  # type: ignore[no-any-return]

to_json

to_json(*, indent: int = 2) -> str

Serialize the instance of this class into a JSON string.

Parameters:

Name Type Description Default
indent int

Number of spaces for indentation. Set to 0 for a single line with spacing, or negative to minimize size by removing extra whitespace.

2

Returns:

Type Description
str

JSON string representing this class.

Source code in src/seadex/_types.py
def to_json(self, *, indent: int = 2) -> str:
    """
    Serialize the instance of this class into a JSON string.

    Parameters
    ----------
    indent : int, optional
        Number of spaces for indentation.
        Set to 0 for a single line with spacing,
        or negative to minimize size by removing extra whitespace.

    Returns
    -------
    str
        JSON string representing this class.

    """
    jsonified = msgspec.json.encode(self)
    return msgspec.json.format(jsonified, indent=indent).decode()

BackupFile

Bases: Base

Represents a backup file.

modified_time instance-attribute

modified_time: datetime

The last modified time of the backup file.

name instance-attribute

name: str

The name of the backup file.

size instance-attribute

size: int

The size of the backup file in bytes.

from_dict classmethod

from_dict(data: dict[str, Any]) -> Self

Create an instance of this class from a dictionary.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary representing the instance of this class.

required

Returns:

Type Description
Self

An instance of this class.

Source code in src/seadex/_backup.py
@classmethod
def from_dict(cls, data: dict[str, Any], /) -> Self:
    """
    Create an instance of this class from a dictionary.

    Parameters
    ----------
    data : dict[str, Any]
        Dictionary representing the instance of this class.

    Returns
    -------
    Self
        An instance of this class.

    """
    try:
        # Attempt a strict conversion, assuming data
        # comes from TorrentRecord.to_dict()
        return msgspec.convert(data, type=cls)
    except msgspec.ValidationError:
        # Failed, let's attempt a laxer conversion,
        # assuming the data comes from the SeaDex API.
        kwargs = {
            "name": data["key"],
            "modified_time": data["modified"],
            "size": data["size"],
        }
        return msgspec.convert(kwargs, type=cls, strict=False)

EntryRecord

Bases: Base

Represents a single anime entry in SeaDex.

anilist_id instance-attribute

anilist_id: int

The AniList ID of the anime.

collection_id instance-attribute

collection_id: str

The ID of the collection the entry belongs to.

collection_name instance-attribute

collection_name: str

The name of the collection the entry belongs to.

comparisons instance-attribute

comparisons: tuple[str, ...]

A tuple of comparison urls.

created_at instance-attribute

created_at: datetime

The timestamp of when the entry was created.

id instance-attribute

id: str

The ID of the entry.

is_incomplete instance-attribute

is_incomplete: bool

Whether the entry is considered incomplete.

notes instance-attribute

notes: str

Additional notes about the entry.

size instance-attribute

size: int

The total size of the entry, calculated by summing the sizes of all files in all torrents.

theoretical_best instance-attribute

theoretical_best: str | None

The theoretical best release for the entry, if known.

torrents instance-attribute

torrents: tuple[TorrentRecord, ...]

A tuple of TorrentRecord objects associated with the entry.

updated_at instance-attribute

updated_at: datetime

The timestamp of when the entry was last updated.

url instance-attribute

url: str

The URL of the entry.

from_dict classmethod

from_dict(data: dict[str, Any]) -> Self

Create an instance of this class from a dictionary.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary representing the instance of this class.

required

Returns:

Type Description
Self

An instance of this class.

Source code in src/seadex/_types.py
@classmethod
def from_dict(cls, data: dict[str, Any], /) -> Self:
    """
    Create an instance of this class from a dictionary.

    Parameters
    ----------
    data : dict[str, Any]
        Dictionary representing the instance of this class.

    Returns
    -------
    Self
        An instance of this class.

    """
    try:
        # Attempt a strict conversion, assuming data
        # comes from EntryRecord.to_dict()
        return msgspec.convert(data, type=cls)
    except msgspec.ValidationError:
        # Failed, let's attempt a laxer conversion,
        # assuming the data comes from the SeaDex API.

        # Grab all the torrents in the entry
        # And caclculate the total size of the entry.
        torrents: list[TorrentRecord] = []
        size = 0

        for torrent in data["expand"]["trs"]:
            tr = TorrentRecord.from_dict(torrent)
            size += tr.size
            torrents.append(tr)

        # "comparison" is a comma seperated string,
        # so we'll transform it into a set
        comparisons = {i.strip() for i in data["comparison"].split(",") if i}

        # "theoreticalBest" is an empty string in the API
        # if there's no theoretical best, we'll replace it with None
        theoretical_best = data["theoreticalBest"] if data["theoreticalBest"] else None

        anilist_id = data["alID"]

        kwargs = {
            "anilist_id": anilist_id,
            "collection_id": data["collectionId"],
            "collection_name": data["collectionName"],
            "comparisons": comparisons,
            "created_at": data["created"],
            "id": data["id"],
            "is_incomplete": data["incomplete"],
            "notes": data["notes"],
            "theoretical_best": theoretical_best,
            "updated_at": data["updated"],
            "torrents": torrents,
            "url": f"https://releases.moe/{anilist_id}/",
            "size": size,
        }
        return msgspec.convert(kwargs, type=cls, strict=False)

TorrentRecord

Bases: Base

Represents a single torrent record within a SeaDex entry.

collection_id instance-attribute

collection_id: str

The ID of the collection the torrent record belongs to.

collection_name instance-attribute

collection_name: str

The name of the collection the torrent record belongs to.

created_at instance-attribute

created_at: datetime

The timestamp of when the torrent record was created.

files instance-attribute

files: tuple[File, ...]

A tuple of File objects representing the files in the torrent.

id instance-attribute

id: str

The ID of the torrent record.

infohash instance-attribute

infohash: str | None

The infohash of the torrent if available, otherwise None (private torrents).

is_best instance-attribute

is_best: bool

Whether this torrent is marked as the "best".

is_dual_audio instance-attribute

is_dual_audio: bool

Whether the torrent contains both Japanese and English audio tracks.

release_group instance-attribute

release_group: str

The name of the group that released the torrent.

size instance-attribute

size: int

The total size of the torrent, calculated by summing the sizes of all files.

tracker instance-attribute

tracker: Tracker

The tracker where the torrent is hosted.

updated_at instance-attribute

updated_at: datetime

The timestamp of when the torrent record was last updated.

url instance-attribute

url: str

The URL of the torrent.

from_dict classmethod

from_dict(data: dict[str, Any]) -> Self

Create an instance of this class from a dictionary.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary representing the instance of this class.

required

Returns:

Type Description
Self

An instance of this class.

Source code in src/seadex/_types.py
@classmethod
def from_dict(cls, data: dict[str, Any], /) -> Self:
    """
    Create an instance of this class from a dictionary.

    Parameters
    ----------
    data : dict[str, Any]
        Dictionary representing the instance of this class.

    Returns
    -------
    Self
        An instance of this class.

    """
    try:
        # Attempt a strict conversion, assuming data
        # comes from TorrentRecord.to_dict()
        return msgspec.convert(data, type=cls)
    except msgspec.ValidationError:
        # Failed, let's attempt a laxer conversion,
        # assuming the data comes from the SeaDex API.
        files = set()
        size = 0

        for file in data["files"]:
            files.add(File(name=file["name"], size=file["length"]))
            size += file["length"]

        # SeaDex API uses "<redacted>" to indicate that the torrent has no infohash (because it's private).
        # This replaces it with None for a more pythonic approach.
        infohash = None if data["infoHash"] == "<redacted>" else data["infoHash"]

        # Private trackers only have a relative URL on SeaDex
        # This will transform said relative URLs into absolute URLs.
        tracker = Tracker(data["tracker"])
        url: str = data["url"]
        if not url.startswith(tracker.url) and tracker.is_private():
            url = urljoin(tracker.url, url)

        kwargs = {
            "collection_id": data["collectionId"],
            "collection_name": data["collectionName"],
            "created_at": data["created"],
            "is_dual_audio": data["dualAudio"],
            "files": natsorted(files, alg=ns.PATH),
            "id": data["id"],
            "infohash": infohash,
            "is_best": data["isBest"],
            "release_group": data["releaseGroup"],
            "tracker": tracker,
            "updated_at": data["updated"],
            "url": url,
            "size": size,
        }
        return msgspec.convert(kwargs, type=cls, strict=False)

File

Bases: Base

Represents a file in the torrent.

name instance-attribute

name: str

The name of the file.

size instance-attribute

size: int

The size of the file in bytes.