From 804700d5022778899a073f858436e3eca84fa273 Mon Sep 17 00:00:00 2001 From: jimmy-sketch Date: Tue, 29 Jul 2025 14:57:30 +0000 Subject: [PATCH] =?UTF-8?q?feat(room):=20=E6=B7=BB=E5=8A=A0=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=88=BF=E9=97=B4=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=88=BF=E9=97=B4=E8=8E=B7=E5=8F=96=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 room 路由中添加 POST 请求处理,用于创建新房间 - 实现 MultiplayerRoom 和 MultiplayerRoomSettings 的 from_apiRoom 方法 - 优化 get_all_rooms 接口,增加对 status 参数的处理 - 调整 RoomIndex 表结构,将 id 字段类型改为 int --- app/database/room.py | 2 +- app/models/room.py | 24 ++++++++++++++++++ app/router/room.py | 58 +++++++++++++++++++++++++++++++++----------- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/app/database/room.py b/app/database/room.py index 7a1aff8..0b79ee6 100644 --- a/app/database/room.py +++ b/app/database/room.py @@ -3,4 +3,4 @@ from sqlmodel import Field, SQLModel class RoomIndex(SQLModel, table=True): __tablename__ = "mp_room_index" # pyright: ignore[reportAssignmentType] - id: int | None = Field(default=None, primary_key=True, index=True) # pyright: ignore[reportCallIssue] + id: int = Field(default=None, primary_key=True, index=True) # pyright: ignore[reportCallIssue] diff --git a/app/models/room.py b/app/models/room.py index 8b07878..2d01a26 100644 --- a/app/models/room.py +++ b/app/models/room.py @@ -139,6 +139,17 @@ class MultiplayerRoomSettings(BaseModel): AutoStartDuration: timedelta AutoSkip: bool + @classmethod + def from_apiRoom(cls, room: Room): + s = cls.model_validate(room.model_dump()) + s.Name = room.name + s.Password = room.password if room.password is not None else "" + s.MatchType = room.type + s.QueueMode = room.queue_mode + s.AutoStartDuration = timedelta(seconds=room.auto_start_duration) + s.AutoSkip = room.auto_skip + return s + class BeatmapAvailability(BaseModel): State: DownloadState @@ -314,6 +325,19 @@ class MultiplayerRoom(BaseModel): def CanAddPlayistItem(cls, user: MultiplayerRoomUser) -> bool: return user == cls.Host or cls.Settings.QueueMode != QueueMode.HOST_ONLY + @classmethod + async def from_apiRoom(cls, room: Room, db: AsyncSession, fetcher: Fetcher): + s = cls.model_validate(room.model_dump()) + s.RoomId = room.room_id if room.room_id is not None else 0 + s.ChannelID = room.channel_id + s.Settings = MultiplayerRoomSettings.from_apiRoom(room) + s.Host = await MultiplayerRoomUser.from_id(room.host.id if room.host else 0, db) + s.Playlist = [ + await MultiPlayerListItem.from_apiItem(item, db, fetcher) + for item in room.playlist + ] + return s + class Room(BaseModel): room_id: int diff --git a/app/router/room.py b/app/router/room.py index b19b6f9..385e992 100644 --- a/app/router/room.py +++ b/app/router/room.py @@ -14,9 +14,11 @@ from sqlmodel.ext.asyncio.session import AsyncSession @router.get("/rooms", tags=["rooms"], response_model=list[Room]) async def get_all_rooms( - mode: str = Query(None), # TODO: 对房间根据状态进行筛选 - status: str = Query(None), - category: str = Query(None), # TODO: 对房间根据分类进行筛选(真的有人用这功能吗) + mode: str | None = Query(None), # TODO: 对房间根据状态进行筛选 + status: str | None = Query(None), + category: str | None = Query( + None + ), # TODO: 对房间根据分类进行筛选(真的有人用这功能吗) db: AsyncSession = Depends(get_db), fetcher: Fetcher = Depends(get_fetcher), ): @@ -28,18 +30,22 @@ async def get_all_rooms( dumped_room = redis.get(str(id)) validated_room = MultiplayerRoom.model_validate_json(str(dumped_room)) flag: bool = False - if validated_room.State == MultiplayerRoomState.OPEN and status == "idle": - flag = True - elif validated_room != MultiplayerRoomState.CLOSED: - flag = True - if flag: - resp.append( - await Room.from_mpRoom( - MultiplayerRoom.model_validate_json(str(dumped_room)), - db, - fetcher, + if status is not None: + if ( + validated_room.State == MultiplayerRoomState.OPEN + and status == "idle" + ): + flag = True + elif validated_room != MultiplayerRoomState.CLOSED: + flag = True + if flag: + resp.append( + await Room.from_mpRoom( + MultiplayerRoom.model_validate_json(str(dumped_room)), + db, + fetcher, + ) ) - ) return resp else: raise HTTPException(status_code=500, detail="Redis Error") @@ -63,3 +69,27 @@ async def get_room( raise HTTPException(status_code=404, detail="Room Not Found") else: raise HTTPException(status_code=500, detail="Redis error") + + +class APICreatedRoom(Room): + error: str | None + + +@router.post("/rooms", tags=["beatmap"], response_model=APICreatedRoom) +async def create_room( + room: Room, + db: AsyncSession = Depends(get_db), + fetcher: Fetcher = Depends(get_fetcher), +): + redis = get_redis() + if redis: + room_index = RoomIndex() + db.add(room_index) + await db.commit() + await db.refresh(room_index) + server_room = await MultiplayerRoom.from_apiRoom(room, db, fetcher) + redis.set(str(room_index.id), server_room.model_dump_json()) + room.room_id = room_index.id + return APICreatedRoom(**room.model_dump(), error=None) + else: + raise HTTPException(status_code=500, detail="redis error")