feat(room): 添加创建房间功能并优化房间获取接口
- 在 room 路由中添加 POST 请求处理,用于创建新房间 - 实现 MultiplayerRoom 和 MultiplayerRoomSettings 的 from_apiRoom 方法 - 优化 get_all_rooms 接口,增加对 status 参数的处理 - 调整 RoomIndex 表结构,将 id 字段类型改为 int
This commit is contained in:
@@ -3,4 +3,4 @@ from sqlmodel import Field, SQLModel
|
|||||||
|
|
||||||
class RoomIndex(SQLModel, table=True):
|
class RoomIndex(SQLModel, table=True):
|
||||||
__tablename__ = "mp_room_index" # pyright: ignore[reportAssignmentType]
|
__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]
|
||||||
|
|||||||
@@ -139,6 +139,17 @@ class MultiplayerRoomSettings(BaseModel):
|
|||||||
AutoStartDuration: timedelta
|
AutoStartDuration: timedelta
|
||||||
AutoSkip: bool
|
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):
|
class BeatmapAvailability(BaseModel):
|
||||||
State: DownloadState
|
State: DownloadState
|
||||||
@@ -314,6 +325,19 @@ class MultiplayerRoom(BaseModel):
|
|||||||
def CanAddPlayistItem(cls, user: MultiplayerRoomUser) -> bool:
|
def CanAddPlayistItem(cls, user: MultiplayerRoomUser) -> bool:
|
||||||
return user == cls.Host or cls.Settings.QueueMode != QueueMode.HOST_ONLY
|
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):
|
class Room(BaseModel):
|
||||||
room_id: int
|
room_id: int
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ from sqlmodel.ext.asyncio.session import AsyncSession
|
|||||||
|
|
||||||
@router.get("/rooms", tags=["rooms"], response_model=list[Room])
|
@router.get("/rooms", tags=["rooms"], response_model=list[Room])
|
||||||
async def get_all_rooms(
|
async def get_all_rooms(
|
||||||
mode: str = Query(None), # TODO: 对房间根据状态进行筛选
|
mode: str | None = Query(None), # TODO: 对房间根据状态进行筛选
|
||||||
status: str = Query(None),
|
status: str | None = Query(None),
|
||||||
category: str = Query(None), # TODO: 对房间根据分类进行筛选(真的有人用这功能吗)
|
category: str | None = Query(
|
||||||
|
None
|
||||||
|
), # TODO: 对房间根据分类进行筛选(真的有人用这功能吗)
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
fetcher: Fetcher = Depends(get_fetcher),
|
fetcher: Fetcher = Depends(get_fetcher),
|
||||||
):
|
):
|
||||||
@@ -28,18 +30,22 @@ async def get_all_rooms(
|
|||||||
dumped_room = redis.get(str(id))
|
dumped_room = redis.get(str(id))
|
||||||
validated_room = MultiplayerRoom.model_validate_json(str(dumped_room))
|
validated_room = MultiplayerRoom.model_validate_json(str(dumped_room))
|
||||||
flag: bool = False
|
flag: bool = False
|
||||||
if validated_room.State == MultiplayerRoomState.OPEN and status == "idle":
|
if status is not None:
|
||||||
flag = True
|
if (
|
||||||
elif validated_room != MultiplayerRoomState.CLOSED:
|
validated_room.State == MultiplayerRoomState.OPEN
|
||||||
flag = True
|
and status == "idle"
|
||||||
if flag:
|
):
|
||||||
resp.append(
|
flag = True
|
||||||
await Room.from_mpRoom(
|
elif validated_room != MultiplayerRoomState.CLOSED:
|
||||||
MultiplayerRoom.model_validate_json(str(dumped_room)),
|
flag = True
|
||||||
db,
|
if flag:
|
||||||
fetcher,
|
resp.append(
|
||||||
|
await Room.from_mpRoom(
|
||||||
|
MultiplayerRoom.model_validate_json(str(dumped_room)),
|
||||||
|
db,
|
||||||
|
fetcher,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return resp
|
return resp
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=500, detail="Redis Error")
|
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")
|
raise HTTPException(status_code=404, detail="Room Not Found")
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=500, detail="Redis error")
|
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")
|
||||||
|
|||||||
Reference in New Issue
Block a user