153 lines
3.9 KiB
Python
153 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from enum import IntEnum
|
|
from typing import Any, Literal
|
|
|
|
from app.models.signalr import UserState
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
|
|
class _UserActivity(BaseModel):
|
|
model_config = ConfigDict(serialize_by_alias=True)
|
|
type: Literal[
|
|
"ChoosingBeatmap",
|
|
"InSoloGame",
|
|
"WatchingReplay",
|
|
"SpectatingUser",
|
|
"SearchingForLobby",
|
|
"InLobby",
|
|
"InMultiplayerGame",
|
|
"SpectatingMultiplayerGame",
|
|
"InPlaylistGame",
|
|
"EditingBeatmap",
|
|
"ModdingBeatmap",
|
|
"TestingBeatmap",
|
|
"InDailyChallengeLobby",
|
|
"PlayingDailyChallenge",
|
|
] = Field(alias="$dtype")
|
|
value: Any | None = Field(alias="$value")
|
|
|
|
|
|
class ChoosingBeatmap(_UserActivity):
|
|
type: Literal["ChoosingBeatmap"] = Field(alias="$dtype")
|
|
|
|
|
|
class InGameValue(BaseModel):
|
|
beatmap_id: int = Field(alias="BeatmapID")
|
|
beatmap_display_title: str = Field(alias="BeatmapDisplayTitle")
|
|
ruleset_id: int = Field(alias="RulesetID")
|
|
ruleset_playing_verb: str = Field(alias="RulesetPlayingVerb")
|
|
|
|
|
|
class _InGame(_UserActivity):
|
|
value: InGameValue = Field(alias="$value")
|
|
|
|
|
|
class InSoloGame(_InGame):
|
|
type: Literal["InSoloGame"] = Field(alias="$dtype")
|
|
|
|
|
|
class InMultiplayerGame(_InGame):
|
|
type: Literal["InMultiplayerGame"] = Field(alias="$dtype")
|
|
|
|
|
|
class SpectatingMultiplayerGame(_InGame):
|
|
type: Literal["SpectatingMultiplayerGame"] = Field(alias="$dtype")
|
|
|
|
|
|
class InPlaylistGame(_InGame):
|
|
type: Literal["InPlaylistGame"] = Field(alias="$dtype")
|
|
|
|
|
|
class EditingBeatmapValue(BaseModel):
|
|
beatmap_id: int = Field(alias="BeatmapID")
|
|
beatmap_display_title: str = Field(alias="BeatmapDisplayTitle")
|
|
|
|
|
|
class EditingBeatmap(_UserActivity):
|
|
type: Literal["EditingBeatmap"] = Field(alias="$dtype")
|
|
value: EditingBeatmapValue = Field(alias="$value")
|
|
|
|
|
|
class TestingBeatmap(_UserActivity):
|
|
type: Literal["TestingBeatmap"] = Field(alias="$dtype")
|
|
|
|
|
|
class ModdingBeatmap(_UserActivity):
|
|
type: Literal["ModdingBeatmap"] = Field(alias="$dtype")
|
|
|
|
|
|
class WatchingReplayValue(BaseModel):
|
|
score_id: int = Field(alias="ScoreID")
|
|
player_name: str = Field(alias="PlayerName")
|
|
beatmap_id: int = Field(alias="BeatmapID")
|
|
beatmap_display_title: str = Field(alias="BeatmapDisplayTitle")
|
|
|
|
|
|
class WatchingReplay(_UserActivity):
|
|
type: Literal["WatchingReplay"] = Field(alias="$dtype")
|
|
value: int | None = Field(alias="$value") # Replay ID
|
|
|
|
|
|
class SpectatingUser(WatchingReplay):
|
|
type: Literal["SpectatingUser"] = Field(alias="$dtype")
|
|
|
|
|
|
class SearchingForLobby(_UserActivity):
|
|
type: Literal["SearchingForLobby"] = Field(alias="$dtype")
|
|
|
|
|
|
class InLobbyValue(BaseModel):
|
|
room_id: int = Field(alias="RoomID")
|
|
room_name: str = Field(alias="RoomName")
|
|
|
|
|
|
class InLobby(_UserActivity):
|
|
type: Literal["InLobby"] = "InLobby"
|
|
|
|
|
|
class InDailyChallengeLobby(_UserActivity):
|
|
type: Literal["InDailyChallengeLobby"] = Field(alias="$dtype")
|
|
|
|
|
|
UserActivity = (
|
|
ChoosingBeatmap
|
|
| InSoloGame
|
|
| WatchingReplay
|
|
| SpectatingUser
|
|
| SearchingForLobby
|
|
| InLobby
|
|
| InMultiplayerGame
|
|
| SpectatingMultiplayerGame
|
|
| InPlaylistGame
|
|
| EditingBeatmap
|
|
| ModdingBeatmap
|
|
| TestingBeatmap
|
|
| InDailyChallengeLobby
|
|
)
|
|
|
|
|
|
class MetadataClientState(UserState):
|
|
user_activity: UserActivity | None = None
|
|
status: OnlineStatus | None = None
|
|
|
|
def to_dict(self) -> dict[str, Any] | None:
|
|
if self.status is None or self.status == OnlineStatus.OFFLINE:
|
|
return None
|
|
dumped = self.model_dump(by_alias=True, exclude_none=True)
|
|
return {
|
|
"Activity": dumped.get("user_activity"),
|
|
"Status": dumped.get("status"),
|
|
}
|
|
|
|
@property
|
|
def pushable(self) -> bool:
|
|
return self.status is not None and self.status != OnlineStatus.OFFLINE
|
|
|
|
|
|
class OnlineStatus(IntEnum):
|
|
OFFLINE = 0 # 隐身
|
|
DO_NOT_DISTURB = 1
|
|
ONLINE = 2
|