feat(user): support online & last_visit

This commit is contained in:
MingxuanGame
2025-08-01 02:49:49 +00:00
parent c5fc6afc18
commit 86a6fd1b69
4 changed files with 22 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
from datetime import UTC, datetime
from typing import TYPE_CHECKING, NotRequired, TypedDict
from app.dependencies.database import get_redis
from app.models.model import UTCBaseModel
from app.models.score import GameMode
from app.models.user import Country, Page, RankHistory
@@ -157,7 +158,7 @@ class User(AsyncAttrs, UserBase, table=True):
class UserResp(UserBase):
id: int | None = None
is_online: bool = True # TODO
is_online: bool = False
groups: list = [] # TODO
country: Country = Field(default_factory=lambda: Country(code="CN", name="China"))
favourite_beatmapset_count: int = 0 # TODO
@@ -225,6 +226,8 @@ class UserResp(UserBase):
.limit(200)
)
).one()
redis = get_redis()
u.is_online = await redis.exists(f"metadata:online:{obj.id}")
u.cover_url = (
obj.cover.get(
"url", "https://assets.ppy.sh/user-profile-covers/default.jpeg"

View File

@@ -482,7 +482,6 @@ async def process_user(
previous_score_best_mod = await get_user_best_score_with_mod_in_beatmap(
session, score.beatmap_id, user.id, mod_for_save, score.gamemode
)
print(previous_score_best, previous_score_best_mod)
add_to_db = False
mouthly_playcount = (
await session.exec(

View File

@@ -22,7 +22,7 @@ class OsuDotDirectFetcher(BaseFetcher):
async def get_or_fetch_beatmap_raw(
self, redis: redis.Redis, beatmap_id: int
) -> str:
if redis.exists(f"beatmap:{beatmap_id}:raw"):
if await redis.exists(f"beatmap:{beatmap_id}:raw"):
return await redis.get(f"beatmap:{beatmap_id}:raw") # pyright: ignore[reportReturnType]
raw = await self.get_beatmap_raw(beatmap_id)
await redis.set(f"beatmap:{beatmap_id}:raw", raw, ex=60 * 60 * 24)

View File

@@ -2,10 +2,12 @@ from __future__ import annotations
import asyncio
from collections.abc import Coroutine
from datetime import UTC, datetime
from typing import override
from app.database import Relationship, RelationshipType
from app.dependencies.database import engine
from app.database.lazer_user import User
from app.dependencies.database import engine, get_redis
from app.models.metadata_hub import MetadataClientState, OnlineStatus, UserActivity
from .hub import Client, Hub
@@ -54,6 +56,18 @@ class MetadataHub(Hub[MetadataClientState]):
async def _clean_state(self, state: MetadataClientState) -> None:
if state.pushable:
await asyncio.gather(*self.broadcast_tasks(int(state.connection_id), None))
redis = get_redis()
if await redis.exists(f"metadata:online:{state.connection_id}"):
await redis.delete(f"metadata:online:{state.connection_id}")
async with AsyncSession(engine) as session:
async with session.begin():
user = (
await session.exec(
select(User).where(User.id == int(state.connection_id))
)
).one()
user.last_visit = datetime.now(UTC)
await session.commit()
@override
def create_state(self, client: Client) -> MetadataClientState:
@@ -93,6 +107,8 @@ class MetadataHub(Hub[MetadataClientState]):
)
)
await asyncio.gather(*tasks)
redis = get_redis()
await redis.set(f"metadata:online:{user_id}", "")
async def UpdateStatus(self, client: Client, status: int) -> None:
status_ = OnlineStatus(status)