from datetime import datetime from typing import Optional from ninja import Schema class GameOut(Schema): id: int steam_app_id: Optional[int] = None name: str path: str custom_path: bool image: Optional[str] = None description: str @staticmethod def resolve_description(obj) -> str: # The admin one wins, Steam games fall back to their store blurb return obj.description or obj.steam_short_description class SteamGameOut(Schema): id: int name: str steam_app_id: int store_url: str header_image: str library_image: str short_description: str is_free: bool currency: str price_initial: Optional[int] = None price_final: Optional[int] = None discount_percent: int updated_at: Optional[datetime] = None @staticmethod def resolve_store_url(obj) -> str: return obj.store_url @staticmethod def resolve_header_image(obj) -> str: return ( obj.steam_header_image or f"https://cdn.akamai.steamstatic.com/steam/apps/{obj.steam_app_id}/header.jpg" ) @staticmethod def resolve_library_image(obj) -> str: return obj.library_image_url @staticmethod def resolve_short_description(obj) -> str: return obj.steam_short_description @staticmethod def resolve_is_free(obj) -> bool: return obj.steam_is_free @staticmethod def resolve_currency(obj) -> str: return obj.steam_currency @staticmethod def resolve_price_initial(obj) -> Optional[int]: return obj.steam_price_initial @staticmethod def resolve_price_final(obj) -> Optional[int]: return obj.steam_price_final @staticmethod def resolve_discount_percent(obj) -> int: return obj.steam_discount_percent @staticmethod def resolve_updated_at(obj) -> Optional[datetime]: return obj.steam_info_updated_at class PlanningGameOut(Schema): name: str # Empty when the name didn't match any of our games library_image: str = "" store_url: str = "" steam_app_id: Optional[int] = None class PlanningSlotOut(Schema): id: int title: str begin: datetime end: datetime column: int color: str is_multi_anims: bool # Single slot: the slot's game. Multi-anims: each of their games. games: list[PlanningGameOut]