Source code for trackmania.club

import logging
from contextlib import suppress
from datetime import datetime

from typing_extensions import Self

from ._util import _regex_it
from .api import _APIClient
from .base import ClubObject
from .config import get_from_cache, set_in_cache
from .constants import _TMIO
from .errors import TMIOException
from .player import Player

_log = logging.getLogger(__name__)

__all__ = (
    "ClubMember",
    "ClubActivity",
    "Club",
)


[docs]class ClubMember(ClubObject): """ .. versionadded :: 0.5 Represents a member of a club. Parameters ---------- name : str The name of the player. tag : str | None The club tab of the player. player_id : str The ID of the player. join_time : datetime When the player joined the club. role : str The role of the player inside the club vip : bool Whether the player is a VIP. """ def __init__( self, name: str, tag: str | None, player_id: str, join_time: datetime, role: str, vip: bool, ): self.name = name self.tag = tag self.player_id = player_id self.join_time = join_time self.role = role self.vip = vip @classmethod def _from_dict(cls: Self, raw_data: dict) -> Self: _log.debug("Creating a ClubMember class from the given dictionary") name = _regex_it(raw_data["player"].get("name")) tag = _regex_it(raw_data["player"].get("tag", None)) player_id = raw_data["player"].get("id") join_time = datetime.utcfromtimestamp(raw_data.get("joinTime")) role = raw_data.get("role") vip = raw_data.get("vip") args = [ name, tag, player_id, join_time, role, vip, ] return cls(*args)
[docs] async def player(self) -> Player: """ .. versionadded :: 0.5 Gets the player who is this specific club member. (IDK wtf to put here xD) Returns ------- :class:`Player` The player who is the club member. Raises ------ :class:`TMIOException` If there is a problem with the TMIO API. """ return await Player.get_player(self.player_id)
[docs]class ClubActivity(ClubObject): """ .. versionadded :: 0.5 Represents an activity of the club. Parameters ---------- name : str The name of the activity. type : str What type of activity it is. activity_id : int The activity's ID. target_activity_id : int The activity's target ID. position : int The position of the activity within the club. public : bool Whether the activity is public or club-member only. media : str The media of the activity. password : bool Whether the activity is password-protected. """ def __init__( self, name: str, type: str, activity_id: int, target_activity_id: int, position: int, public: bool, media: str, password: bool, ): self.name = name self.type = type self.activity_id = activity_id self.target_activity_id = target_activity_id self.position = position self.public = public self.media = media self.password = password @classmethod def _from_dict(cls: Self, raw_data: dict) -> Self: _log.debug("Creating a ClubActivity class from the given dictionary") name = _regex_it(raw_data.get("name")) type = raw_data.get("type") activity_id = raw_data.get("activityid") target_activity_id = raw_data.get("targetactivityid", 0) position = raw_data.get("position") public = raw_data.get("public") media = raw_data.get("media") password = raw_data.get("password") args = [ name, type, activity_id, target_activity_id, position, public, media, password, ] return cls(*args)
[docs]class Club(ClubObject): """ Represents a Club in Trackmania 2020. Parameters ---------- background : str The club's background url. created_at : datetime The club's created date. decal : str The club decal URL description : str The club's description featured : bool Whether the club is featured or not. club_id : int The club's ID. logo : str The club's logo URL. member_count : int The club's member count. name : str The club's name. popularity : int The club popularity level state : str The club's state. Is either Private or Public. tag : str The club tag """ def __init__( self, background: str, created_at: datetime, decal: str, description: str, featured: bool, club_id: int, logo: str, member_count: int, name: str, popularity: int, state: str, tag: str | None, creator_id: str, ): self.background = background self.created_at = created_at self.decal = decal self.description = description self.featured = featured self.club_id = club_id self.logo = logo self.member_count = member_count self.name = name self.popularity = popularity self.state = state self.tag = tag self.creator_id = creator_id @classmethod def _from_dict(cls: Self, raw_data: dict) -> Self: _log.debug("Creating a Club class from the given dictionary.") background = raw_data.get("backgroundUrl", "") created_at = datetime.utcfromtimestamp(raw_data.get("creationTimestamp", 0)) decal = raw_data.get("decalUrl") description = raw_data.get("description") featured = raw_data.get("featured") club_id = raw_data.get("id", 0) logo = raw_data.get("logoUrl") member_count = raw_data.get("membercount", 0) name = _regex_it(raw_data.get("name")) popularity = raw_data.get("popularityLevel") state = raw_data.get("state") tag = _regex_it(raw_data.get("tag", None)) creator_id = raw_data["creatorplayer"]["id"] args = [ background, created_at, decal, description, featured, club_id, logo, member_count, name, popularity, state, tag, creator_id, ] return cls(*args)
[docs] @classmethod async def get_club(cls: Self, club_id: int) -> Self | None: """ .. versionadded :: 0.5 Gets a club based on its club id. Returns None if the `club_id` is 0 Parameters ---------- club_id : int The club's id. Returns ------- :class:`Club` | None Returns a `Club` class if a club exists with the given class id. Otherwise returns None. Raises ------ :class:`TMIOException` If the club doesn't exist or if an unexpected error occurs on TMIO's side. """ if club_id == 0: return None club_data = get_from_cache(f"club:{club_id}") if club_data is not None: return cls._from_dict(club_data) api_client = _APIClient() club_data = await api_client.get(_TMIO.build([_TMIO.TABS.CLUB, club_id])) await api_client.close() with suppress(KeyError, TypeError): raise TMIOException(club_data["error"]) return cls._from_dict(club_data)
[docs] @classmethod async def list_clubs(cls: Self, page: int = 0) -> list[Self]: """ .. versionadded :: 0.5 Lists all the popular clubs. Parameters ---------- page : int, optional The page bumber, by default 0 Returns ------- :class:`list[Club]` The list of clubs on that specific page. """ clubs = [] club_data = get_from_cache(f"clubs:{page}") if club_data is not None: for club in club_data.get("clubs", []): clubs.append(cls._from_dict(club)) return clubs api_client = _APIClient() club_data = await api_client.get( _TMIO.build([_TMIO.TABS.CLUBS, page]) + "?sort=popularity" ) await api_client.close() set_in_cache(f"clubs:{page}", club_data, ex=43200) for club in club_data.get("clubs", []): clubs.append(cls._from_dict(club)) return clubs
[docs] async def get_activities(self: Self, page: int = 0) -> list[ClubActivity]: """ .. versionadded :: 0.5 Gets the activities of the club. Parameters ---------- page : int The page number, by default 0 Returns ------- :class:`list[ClubActivity]` The list of activities of the club. """ club_activities = [] all_activities = get_from_cache(f"club_activities:{self.club_id}:{page}") if all_activities is not None: for activity in all_activities: club_activities.append(ClubActivity._from_dict(activity)) return club_activities api_client = _APIClient() all_activities = await api_client.get( _TMIO.build([_TMIO.TABS.CLUB, self.club_id, _TMIO.TABS.ACTIVITIES, page]) ) await api_client.close() with suppress(KeyError, TypeError): raise TMIOException(all_activities["error"]) for activity in all_activities.get("activities", []): club_activities.append(ClubActivity._from_dict(activity)) return club_activities
[docs] async def get_members(self: Self, page: int = 0) -> list[ClubMember]: """ .. versionadded :: 0.5 Gets the members of the club. Parameters ---------- page : int, optional The page number, by default 0 Returns ------- :class:`list[Player]` The list of members of the club. """ player_list = [] club_members = get_from_cache(f"club_members:{self.club_id}:{page}") if club_members is not None: for member in club_members.get("members", []): player_list.append(ClubMember._from_dict(member)) return player_list api_client = _APIClient() club_members = await api_client.get( _TMIO.build([_TMIO.TABS.CLUB, self.club_id, _TMIO.TABS.MEMBERS, page]) ) await api_client.close() for member in club_members.get("members", []): player_list.append(ClubMember._from_dict(member)) return player_list
[docs] async def creator(self) -> Player: """ .. versionadded :: 0.5 Gets the creator of the club. Returns ------- :class:`Player` The creator of the club. """ return await Player.get_player(self.creator_id)