feat(v1-api): support api v1
This commit is contained in:
100
app/router/v1/replay.py
Normal file
100
app/router/v1/replay.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from datetime import date
|
||||
from typing import Literal
|
||||
|
||||
from app.database.counts import ReplayWatchedCount
|
||||
from app.database.score import Score
|
||||
from app.dependencies.database import get_db
|
||||
from app.dependencies.storage import get_storage_service
|
||||
from app.models.mods import int_to_mods
|
||||
from app.models.score import INT_TO_MODE
|
||||
from app.storage import StorageService
|
||||
|
||||
from .router import router
|
||||
|
||||
from fastapi import Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
|
||||
class ReplayModel(BaseModel):
|
||||
content: str
|
||||
encoding: Literal["base64"] = "base64"
|
||||
|
||||
|
||||
@router.get(
|
||||
"/get_replay",
|
||||
response_model=ReplayModel,
|
||||
name="获取回放文件",
|
||||
description="获取指定谱面的回放文件。",
|
||||
)
|
||||
async def download_replay(
|
||||
beatmap: int = Query(..., alias="b", description="谱面 ID"),
|
||||
user: str = Query(..., alias="u", description="用户"),
|
||||
ruleset_id: int | None = Query(
|
||||
None, alias="m", description="Ruleset ID", ge=0, le=3
|
||||
),
|
||||
score_id: int | None = Query(None, alias="s", description="成绩 ID"),
|
||||
type: Literal["string", "id"] | None = Query(
|
||||
None, description="用户类型:string 用户名称 / id 用户 ID"
|
||||
),
|
||||
mods: int = Query(0, description="成绩的 MOD"),
|
||||
session: AsyncSession = Depends(get_db),
|
||||
storage_service: StorageService = Depends(get_storage_service),
|
||||
):
|
||||
mods_ = int_to_mods(mods)
|
||||
if score_id is not None:
|
||||
score_record = await session.get(Score, score_id)
|
||||
if score_record is None:
|
||||
raise HTTPException(status_code=404, detail="Score not found")
|
||||
else:
|
||||
score_record = (
|
||||
await session.exec(
|
||||
select(Score).where(
|
||||
Score.beatmap_id == beatmap,
|
||||
Score.user_id == user
|
||||
if type == "id" or user.isdigit()
|
||||
else Score.user.username == user,
|
||||
Score.mods == mods_,
|
||||
Score.gamemode == INT_TO_MODE[ruleset_id]
|
||||
if ruleset_id is not None
|
||||
else True,
|
||||
)
|
||||
)
|
||||
).first()
|
||||
if score_record is None:
|
||||
raise HTTPException(status_code=404, detail="Score not found")
|
||||
|
||||
filepath = (
|
||||
f"replays/{score_record.id}_{score_record.beatmap_id}"
|
||||
f"_{score_record.user_id}_lazer_replay.osr"
|
||||
)
|
||||
if not await storage_service.is_exists(filepath):
|
||||
raise HTTPException(status_code=404, detail="Replay file not found")
|
||||
|
||||
replay_watched_count = (
|
||||
await session.exec(
|
||||
select(ReplayWatchedCount).where(
|
||||
ReplayWatchedCount.user_id == score_record.user_id,
|
||||
ReplayWatchedCount.year == date.today().year,
|
||||
ReplayWatchedCount.month == date.today().month,
|
||||
)
|
||||
)
|
||||
).first()
|
||||
if replay_watched_count is None:
|
||||
replay_watched_count = ReplayWatchedCount(
|
||||
user_id=score_record.user_id,
|
||||
year=date.today().year,
|
||||
month=date.today().month,
|
||||
)
|
||||
session.add(replay_watched_count)
|
||||
replay_watched_count.count += 1
|
||||
await session.commit()
|
||||
|
||||
data = await storage_service.read_file(filepath)
|
||||
return ReplayModel(
|
||||
content=base64.b64encode(data).decode("utf-8"), encoding="base64"
|
||||
)
|
||||
Reference in New Issue
Block a user