from dataclasses import asdict, dataclass from typing import Annotated, Literal from litestar import Controller, Litestar, MediaType, Response, get, put from litestar.params import Parameter from pydantic import UUID4 from secretsanta.domain import Group from secretsanta.repo import S3Repo from secretsanta.service import ( CreateGroupService, GetGroupParticipantsService, GetPairService, ) from secretsanta.settings import get_config @dataclass class CreateGroup: participants: list[str] @dataclass class PairResponse: pair: str class GroupController(Controller): path = "api/v1/groups" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.repo = S3Repo() self.get_participants_service = GetGroupParticipantsService(self.repo) self.create_group_service = CreateGroupService(self.repo) self.get_pair_service = GetPairService(self.repo) @get("/{group_uuid:uuid}") async def get_participants(self, group_uuid: UUID4) -> list[str]: return await self.get_participants_service.run(group_uuid) @put("/{group_uuid:uuid}") async def create_group( self, group_uuid: UUID4, data: CreateGroup, ) -> list[str]: return await self.create_group_service.run( Group(uuid=group_uuid, **asdict(data)), ) @get("/{group_uuid:uuid}/pair/{participant_name:str}") async def get_pair( self, group_uuid: UUID4, participant_name: str, response_type: Annotated[ Literal["json", "plain"], Parameter(query="type"), ] = "plain", ) -> Response[str] | PairResponse: pair = await self.get_pair_service.run( group_uuid=group_uuid, participant=participant_name, ) if response_type == "json": return PairResponse(pair=pair) return Response(content=pair, media_type=MediaType.TEXT) config = get_config() app = Litestar(route_handlers=[GroupController], debug=config.environment == "local")