feat(beatmap): implement get beatmap arrtibutes

This commit is contained in:
MingxuanGame
2025-07-26 17:31:23 +00:00
parent ef977d1c2d
commit 900a17f815
16 changed files with 425 additions and 171 deletions

View File

@@ -1,12 +1,14 @@
from datetime import datetime
from app.fetcher import Fetcher
from app.models.beatmap import BeatmapRankStatus
from app.models.score import MODE_TO_INT, GameMode
from .beatmapset import Beatmapset, BeatmapsetResp
from sqlalchemy import DECIMAL, Column, DateTime
from sqlmodel import VARCHAR, Field, Relationship, SQLModel
from sqlalchemy.orm import joinedload
from sqlmodel import VARCHAR, Field, Relationship, SQLModel, select
from sqlmodel.ext.asyncio.session import AsyncSession
@@ -77,6 +79,7 @@ class Beatmap(BeatmapBase, table=True):
)
session.add(beatmap)
await session.commit()
await session.refresh(beatmap)
return beatmap
@classmethod
@@ -102,6 +105,30 @@ class Beatmap(BeatmapBase, table=True):
await session.commit()
return beatmaps
@classmethod
async def get_or_fetch(
cls, session: AsyncSession, bid: int, fetcher: Fetcher
) -> "Beatmap":
beatmap = (
await session.exec(
select(Beatmap)
.where(Beatmap.id == bid)
.options(
joinedload(Beatmap.beatmapset).selectinload(Beatmapset.beatmaps) # pyright: ignore[reportArgumentType]
)
)
).first()
if not beatmap:
resp = await fetcher.get_beatmap(bid)
r = await session.exec(
select(Beatmapset.id).where(Beatmapset.id == resp.beatmapset_id)
)
if not r.first():
set_resp = await fetcher.get_beatmapset(resp.beatmapset_id)
await Beatmapset.from_resp(session, set_resp, from_=resp.id)
return await Beatmap.from_resp(session, resp)
return beatmap
class BeatmapResp(BeatmapBase):
id: int

View File

@@ -2,7 +2,6 @@ from datetime import datetime
from typing import TYPE_CHECKING, TypedDict, cast
from app.models.beatmap import BeatmapRankStatus, Genre, Language
from app.models.score import GameMode
from pydantic import BaseModel, model_serializer
from sqlalchemy import DECIMAL, JSON, Column, DateTime, Text
@@ -69,7 +68,7 @@ class BeatmapNomination(TypedDict):
beatmapset_id: int
reset: bool
user_id: int
rulesets: dict[str, GameMode] | None
rulesets: list[str] | None
class BeatmapDescription(SQLModel):

View File

@@ -2,7 +2,8 @@ from datetime import datetime
import math
from app.database.user import User
from app.models.score import MODE_TO_INT, APIMod, GameMode, Rank
from app.models.mods import APIMod
from app.models.score import MODE_TO_INT, GameMode, Rank
from .beatmap import Beatmap, BeatmapResp
from .beatmapset import BeatmapsetResp