feat(score): store replay to storage service

This commit is contained in:
MingxuanGame
2025-08-12 03:58:30 +00:00
parent cf3a6bbd21
commit ac54603acb
3 changed files with 27 additions and 17 deletions

View File

@@ -3,6 +3,3 @@ from __future__ import annotations
from pathlib import Path
STATIC_DIR = Path(__file__).parent.parent / "static"
REPLAY_DIR = Path(__file__).parent.parent / "replays"
REPLAY_DIR.mkdir(exist_ok=True)

View File

@@ -32,6 +32,7 @@ from app.database.score import (
)
from app.dependencies.database import get_db, get_redis
from app.dependencies.fetcher import get_fetcher
from app.dependencies.storage import get_storage_service
from app.dependencies.user import get_current_user
from app.fetcher import Fetcher
from app.models.room import RoomCategory
@@ -42,12 +43,13 @@ from app.models.score import (
Rank,
SoloScoreSubmissionInfo,
)
from app.path import REPLAY_DIR
from app.storage.base import StorageService
from app.storage.local import LocalStorageService
from .router import router
from fastapi import Body, Depends, Form, HTTPException, Query, Security
from fastapi.responses import FileResponse
from fastapi.responses import FileResponse, RedirectResponse
from httpx import HTTPError
from pydantic import BaseModel
from redis.asyncio import Redis
@@ -715,15 +717,15 @@ async def download_score_replay(
score_id: int,
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
storage_service: StorageService = Depends(get_storage_service),
):
score = (await db.exec(select(Score).where(Score.id == score_id))).first()
if not score:
raise HTTPException(status_code=404, detail="Score not found")
filename = f"{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
path = REPLAY_DIR / filename
filepath = f"replays/{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
if not path.exists():
if not await storage_service.is_exists(filepath):
raise HTTPException(status_code=404, detail="Replay file not found")
is_friend = (
@@ -755,7 +757,14 @@ async def download_score_replay(
db.add(replay_watched_count)
replay_watched_count.count += 1
await db.commit()
return FileResponse(
path=path, filename=filename, media_type="application/x-osu-replay"
)
if isinstance(storage_service, LocalStorageService):
return FileResponse(
path=await storage_service.get_file_url(filepath),
filename=filepath,
media_type="application/x-osu-replay",
)
else:
return RedirectResponse(
await storage_service.get_file_url(filepath),
301,
)

View File

@@ -13,6 +13,7 @@ from app.database.score import Score
from app.database.score_token import ScoreToken
from app.dependencies.database import engine
from app.dependencies.fetcher import get_fetcher
from app.dependencies.storage import get_storage_service
from app.models.mods import mods_to_int
from app.models.score import LegacyReplaySoloScoreInfo, ScoreStatistics
from app.models.spectator_hub import (
@@ -25,7 +26,6 @@ from app.models.spectator_hub import (
StoreClientState,
StoreScore,
)
from app.path import REPLAY_DIR
from app.utils import unix_timestamp_to_windows
from .hub import Client, Hub
@@ -64,7 +64,7 @@ def encode_string(s: str) -> bytes:
return ret
def save_replay(
async def save_replay(
ruleset_id: int,
md5: str,
username: str,
@@ -136,10 +136,14 @@ def save_replay(
data.extend(struct.pack("<i", len(compressed)))
data.extend(compressed)
storage_service = get_storage_service()
replay_path = (
REPLAY_DIR / f"{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
f"replays/{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
)
await storage_service.write_file(
replay_path,
bytes(data),
)
replay_path.write_bytes(data)
class SpectatorHub(Hub[StoreClientState]):
@@ -298,7 +302,7 @@ class SpectatorHub(Hub[StoreClientState]):
score_record.has_replay = True
await session.commit()
await session.refresh(score_record)
save_replay(
await save_replay(
ruleset_id=store.ruleset_id,
md5=store.checksum,
username=store.score.score_info.user.name,