refactor(api): use Annotated-style dependency injection

This commit is contained in:
MingxuanGame
2025-10-03 05:41:31 +00:00
parent 37b4eadf79
commit 346c2557cf
45 changed files with 623 additions and 577 deletions

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
from datetime import UTC, date
import time
from typing import Annotated
from app.calculator import clamp
from app.config import settings
@@ -34,11 +35,10 @@ from app.database.score import (
process_user,
)
from app.dependencies.api_version import APIVersion
from app.dependencies.database import Database, get_redis, with_db
from app.dependencies.fetcher import get_fetcher
from app.dependencies.storage import get_storage_service
from app.dependencies.user import get_client_user, get_current_user
from app.fetcher import Fetcher
from app.dependencies.database import Database, Redis, get_redis, with_db
from app.dependencies.fetcher import Fetcher, get_fetcher
from app.dependencies.storage import StorageService
from app.dependencies.user import ClientUser, get_current_user
from app.log import logger
from app.models.beatmap import BeatmapRankStatus
from app.models.room import RoomCategory
@@ -50,7 +50,6 @@ from app.models.score import (
)
from app.service.beatmap_cache_service import get_beatmap_cache_service
from app.service.user_cache_service import refresh_user_cache_background
from app.storage.base import StorageService
from app.utils import utcnow
from .router import router
@@ -69,7 +68,6 @@ from fastapi.responses import RedirectResponse
from fastapi_limiter.depends import RateLimiter
from httpx import HTTPError
from pydantic import BaseModel
from redis.asyncio import Redis
from sqlalchemy.orm import joinedload
from sqlmodel import col, exists, func, select
from sqlmodel.ext.asyncio.session import AsyncSession
@@ -245,16 +243,18 @@ class BeatmapScores[T: ScoreResp | LegacyScoreResp](BaseModel):
async def get_beatmap_scores(
db: Database,
api_version: APIVersion,
beatmap_id: int = Path(description="谱面 ID"),
mode: GameMode = Query(description="指定 auleset"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
mods: list[str] = Query(default_factory=set, alias="mods[]", description="筛选使用的 Mods (可选,多值)"),
type: LeaderboardType = Query(
LeaderboardType.GLOBAL,
description=("排行榜类型GLOBAL 全局 / COUNTRY 国家 / FRIENDS 好友 / TEAM 战队"),
),
current_user: User = Security(get_current_user, scopes=["public"]),
limit: int = Query(50, ge=1, le=200, description="返回条数 (1-200)"),
beatmap_id: Annotated[int, Path(description="谱面 ID")],
mode: Annotated[GameMode, Query(description="指定 auleset")],
mods: Annotated[list[str], Query(default_factory=set, alias="mods[]", description="筛选使用的 Mods (可选,多值)")],
current_user: Annotated[User, Security(get_current_user, scopes=["public"])],
legacy_only: Annotated[bool | None, Query(description="是否只查询 Stable 分数")] = None,
type: Annotated[
LeaderboardType,
Query(
description=("排行榜类型GLOBAL 全局 / COUNTRY 国家 / FRIENDS 好友 / TEAM 战队"),
),
] = LeaderboardType.GLOBAL,
limit: Annotated[int, Query(ge=1, le=200, description="返回条数 (1-200)")] = 50,
):
if legacy_only:
raise HTTPException(status_code=404, detail="this server only contains lazer scores")
@@ -294,12 +294,12 @@ async def get_beatmap_scores(
async def get_user_beatmap_score(
db: Database,
api_version: APIVersion,
beatmap_id: int = Path(description="谱面 ID"),
user_id: int = Path(description="用户 ID"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
mode: GameMode | None = Query(None, description="指定 ruleset (可选)"),
mods: str = Query(None, description="筛选使用的 Mods (暂未实现)"),
current_user: User = Security(get_current_user, scopes=["public"]),
beatmap_id: Annotated[int, Path(description="谱面 ID")],
user_id: Annotated[int, Path(description="用户 ID")],
current_user: Annotated[User, Security(get_current_user, scopes=["public"])],
legacy_only: Annotated[bool | None, Query(description="是否只查询 Stable 分数")] = None,
mode: Annotated[GameMode | None, Query(description="指定 ruleset (可选)")] = None,
mods: Annotated[str | None, Query(description="筛选使用的 Mods (暂未实现)")] = None,
):
user_score = (
await db.exec(
@@ -342,11 +342,11 @@ async def get_user_beatmap_score(
async def get_user_all_beatmap_scores(
db: Database,
api_version: APIVersion,
beatmap_id: int = Path(description="谱面 ID"),
user_id: int = Path(description="用户 ID"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
ruleset: GameMode | None = Query(None, description="指定 ruleset (可选)"),
current_user: User = Security(get_current_user, scopes=["public"]),
beatmap_id: Annotated[int, Path(description="谱面 ID")],
user_id: Annotated[int, Path(description="用户 ID")],
current_user: Annotated[User, Security(get_current_user, scopes=["public"])],
legacy_only: Annotated[bool | None, Query(description="是否只查询 Stable 分数")] = None,
ruleset: Annotated[GameMode | None, Query(description="指定 ruleset (可选)")] = None,
):
all_user_scores = (
await db.exec(
@@ -374,11 +374,11 @@ async def get_user_all_beatmap_scores(
async def create_solo_score(
background_task: BackgroundTasks,
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
version_hash: str = Form("", description="游戏版本哈希"),
beatmap_hash: str = Form(description="谱面文件哈希"),
ruleset_id: int = Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)"),
current_user: User = Security(get_client_user),
beatmap_id: Annotated[int, Path(description="谱面 ID")],
beatmap_hash: Annotated[str, Form(description="谱面文件哈希")],
ruleset_id: Annotated[int, Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)")],
current_user: ClientUser,
version_hash: Annotated[str, Form(description="游戏版本哈希")] = "",
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -406,12 +406,12 @@ async def create_solo_score(
async def submit_solo_score(
background_task: BackgroundTasks,
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
token: int = Path(description="成绩令牌 ID"),
info: SoloScoreSubmissionInfo = Body(description="成绩提交信息"),
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
fetcher=Depends(get_fetcher),
beatmap_id: Annotated[int, Path(description="谱面 ID")],
token: Annotated[int, Path(description="成绩令牌 ID")],
info: Annotated[SoloScoreSubmissionInfo, Body(description="成绩提交信息")],
current_user: ClientUser,
redis: Redis,
fetcher: Fetcher,
):
return await submit_score(background_task, info, beatmap_id, token, current_user, db, redis, fetcher)
@@ -428,11 +428,11 @@ async def create_playlist_score(
background_task: BackgroundTasks,
room_id: int,
playlist_id: int,
beatmap_id: int = Form(description="谱面 ID"),
beatmap_hash: str = Form(description="游戏版本哈希"),
ruleset_id: int = Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)"),
version_hash: str = Form("", description="谱面版本哈希"),
current_user: User = Security(get_client_user),
beatmap_id: Annotated[int, Form(description="谱面 ID")],
beatmap_hash: Annotated[str, Form(description="游戏版本哈希")],
ruleset_id: Annotated[int, Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)")],
current_user: ClientUser,
version_hash: Annotated[str, Form(description="谱面版本哈希")] = "",
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -496,9 +496,9 @@ async def submit_playlist_score(
playlist_id: int,
token: int,
info: SoloScoreSubmissionInfo,
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
fetcher: Fetcher = Depends(get_fetcher),
current_user: ClientUser,
redis: Redis,
fetcher: Fetcher,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -555,9 +555,9 @@ async def index_playlist_scores(
session: Database,
room_id: int,
playlist_id: int,
limit: int = Query(50, ge=1, le=50, description="返回条数 (1-50)"),
cursor: int = Query(2000000, alias="cursor[total_score]", description="分页游标(上一页最低分)"),
current_user: User = Security(get_current_user, scopes=["public"]),
current_user: Annotated[User, Security(get_current_user, scopes=["public"])],
limit: Annotated[int, Query(ge=1, le=50, description="返回条数 (1-50)")] = 50,
cursor: Annotated[int, Query(alias="cursor[total_score]", description="分页游标(上一页最低分)")] = 2000000,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -623,8 +623,8 @@ async def show_playlist_score(
room_id: int,
playlist_id: int,
score_id: int,
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
current_user: ClientUser,
redis: Redis,
):
room = await session.get(Room, room_id)
if not room:
@@ -692,7 +692,7 @@ async def get_user_playlist_score(
room_id: int,
playlist_id: int,
user_id: int,
current_user: User = Security(get_client_user),
current_user: ClientUser,
):
score_record = None
start_time = time.time()
@@ -725,8 +725,8 @@ async def get_user_playlist_score(
)
async def pin_score(
db: Database,
score_id: int = Path(description="成绩 ID"),
current_user: User = Security(get_client_user),
score_id: Annotated[int, Path(description="成绩 ID")],
current_user: ClientUser,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -770,8 +770,8 @@ async def pin_score(
)
async def unpin_score(
db: Database,
score_id: int = Path(description="成绩 ID"),
current_user: User = Security(get_client_user),
score_id: Annotated[int, Path(description="成绩 ID")],
current_user: ClientUser,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -805,10 +805,10 @@ async def unpin_score(
)
async def reorder_score_pin(
db: Database,
score_id: int = Path(description="成绩 ID"),
after_score_id: int | None = Body(default=None, description="放在该成绩之后"),
before_score_id: int | None = Body(default=None, description="放在该成绩之"),
current_user: User = Security(get_client_user),
score_id: Annotated[int, Path(description="成绩 ID")],
current_user: ClientUser,
after_score_id: Annotated[int | None, Body(description="放在该成绩之")] = None,
before_score_id: Annotated[int | None, Body(description="放在该成绩之前")] = None,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id
@@ -893,8 +893,8 @@ async def reorder_score_pin(
async def download_score_replay(
score_id: int,
db: Database,
current_user: User = Security(get_current_user, scopes=["public"]),
storage_service: StorageService = Depends(get_storage_service),
current_user: Annotated[User, Security(get_current_user, scopes=["public"])],
storage_service: StorageService,
):
# 立即获取用户ID避免懒加载问题
user_id = current_user.id