Files
g0v0-server/app/models/metadata_hub.py
2025-07-28 05:52:48 +00:00

151 lines
3.9 KiB
Python

from __future__ import annotations
from enum import IntEnum
from typing import Any, Literal
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(BaseModel):
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