Files
g0v0-server/app/database/beatmap_playcounts.py
chenjintang-shrimp 50375c7b12 feat(event): 添加百次播放事件记录功能
- 在 beatmap_playcounts 模块中增加了事件记录功能
- 当用户播放次数达到百的倍数时,创建并记录 Event 对象
- 事件类型为 EventType.BEATMAP_PLAYCOUNT
2025-08-13 06:48:54 +00:00

96 lines
2.9 KiB
Python

from datetime import UTC, datetime
from typing import TYPE_CHECKING
from app.database.events import Event, EventType
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlmodel import (
BigInteger,
Column,
Field,
ForeignKey,
Relationship,
SQLModel,
select,
)
from sqlmodel.ext.asyncio.session import AsyncSession
if TYPE_CHECKING:
from .beatmap import Beatmap, BeatmapResp
from .beatmapset import BeatmapsetResp
from .lazer_user import User
class BeatmapPlaycounts(AsyncAttrs, SQLModel, table=True):
__tablename__ = "beatmap_playcounts" # pyright: ignore[reportAssignmentType]
id: int | None = Field(
default=None,
sa_column=Column(BigInteger, primary_key=True, autoincrement=True),
)
user_id: int = Field(
sa_column=Column(BigInteger, ForeignKey("lazer_users.id"), index=True)
)
beatmap_id: int = Field(foreign_key="beatmaps.id", index=True)
playcount: int = Field(default=0)
user: "User" = Relationship()
beatmap: "Beatmap" = Relationship()
class BeatmapPlaycountsResp(BaseModel):
beatmap_id: int
beatmap: "BeatmapResp | None" = None
beatmapset: "BeatmapsetResp | None" = None
count: int
@classmethod
async def from_db(cls, db_model: BeatmapPlaycounts) -> "BeatmapPlaycountsResp":
from .beatmap import BeatmapResp
from .beatmapset import BeatmapsetResp
await db_model.awaitable_attrs.beatmap
return cls(
beatmap_id=db_model.beatmap_id,
count=db_model.playcount,
beatmap=await BeatmapResp.from_db(db_model.beatmap),
beatmapset=await BeatmapsetResp.from_db(db_model.beatmap.beatmapset),
)
async def process_beatmap_playcount(
session: AsyncSession, user_id: int, beatmap_id: int
) -> None:
existing_playcount = (
await session.exec(
select(BeatmapPlaycounts).where(
BeatmapPlaycounts.user_id == user_id,
BeatmapPlaycounts.beatmap_id == beatmap_id,
)
)
).first()
if existing_playcount:
existing_playcount.playcount += 1
if existing_playcount.playcount % 100 == 0:
playcount_event = Event(
created_at=datetime.now(UTC),
type=EventType.BEATMAP_PLAYCOUNT,
user_id=user_id,
)
await existing_playcount.awaitable_attrs.beatmap
playcount_event.event_payload = {
"count": existing_playcount.playcount,
"beatmap": {
"title": existing_playcount.beatmap.version,
"url": existing_playcount.beatmap.url,
},
}
session.add(playcount_event)
else:
new_playcount = BeatmapPlaycounts(
user_id=user_id, beatmap_id=beatmap_id, playcount=1
)
session.add(new_playcount)