feat(score): store replay to storage service
This commit is contained in:
@@ -3,6 +3,3 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
STATIC_DIR = Path(__file__).parent.parent / "static"
|
STATIC_DIR = Path(__file__).parent.parent / "static"
|
||||||
|
|
||||||
REPLAY_DIR = Path(__file__).parent.parent / "replays"
|
|
||||||
REPLAY_DIR.mkdir(exist_ok=True)
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ from app.database.score import (
|
|||||||
)
|
)
|
||||||
from app.dependencies.database import get_db, get_redis
|
from app.dependencies.database import get_db, get_redis
|
||||||
from app.dependencies.fetcher import get_fetcher
|
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.dependencies.user import get_current_user
|
||||||
from app.fetcher import Fetcher
|
from app.fetcher import Fetcher
|
||||||
from app.models.room import RoomCategory
|
from app.models.room import RoomCategory
|
||||||
@@ -42,12 +43,13 @@ from app.models.score import (
|
|||||||
Rank,
|
Rank,
|
||||||
SoloScoreSubmissionInfo,
|
SoloScoreSubmissionInfo,
|
||||||
)
|
)
|
||||||
from app.path import REPLAY_DIR
|
from app.storage.base import StorageService
|
||||||
|
from app.storage.local import LocalStorageService
|
||||||
|
|
||||||
from .router import router
|
from .router import router
|
||||||
|
|
||||||
from fastapi import Body, Depends, Form, HTTPException, Query, Security
|
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 httpx import HTTPError
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from redis.asyncio import Redis
|
from redis.asyncio import Redis
|
||||||
@@ -715,15 +717,15 @@ async def download_score_replay(
|
|||||||
score_id: int,
|
score_id: int,
|
||||||
current_user: User = Security(get_current_user, scopes=["public"]),
|
current_user: User = Security(get_current_user, scopes=["public"]),
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
|
storage_service: StorageService = Depends(get_storage_service),
|
||||||
):
|
):
|
||||||
score = (await db.exec(select(Score).where(Score.id == score_id))).first()
|
score = (await db.exec(select(Score).where(Score.id == score_id))).first()
|
||||||
if not score:
|
if not score:
|
||||||
raise HTTPException(status_code=404, detail="Score not found")
|
raise HTTPException(status_code=404, detail="Score not found")
|
||||||
|
|
||||||
filename = f"{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
|
filepath = f"replays/{score.id}_{score.beatmap_id}_{score.user_id}_lazer_replay.osr"
|
||||||
path = REPLAY_DIR / filename
|
|
||||||
|
|
||||||
if not path.exists():
|
if not await storage_service.is_exists(filepath):
|
||||||
raise HTTPException(status_code=404, detail="Replay file not found")
|
raise HTTPException(status_code=404, detail="Replay file not found")
|
||||||
|
|
||||||
is_friend = (
|
is_friend = (
|
||||||
@@ -755,7 +757,14 @@ async def download_score_replay(
|
|||||||
db.add(replay_watched_count)
|
db.add(replay_watched_count)
|
||||||
replay_watched_count.count += 1
|
replay_watched_count.count += 1
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
if isinstance(storage_service, LocalStorageService):
|
||||||
return FileResponse(
|
return FileResponse(
|
||||||
path=path, filename=filename, media_type="application/x-osu-replay"
|
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,
|
||||||
|
)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from app.database.score import Score
|
|||||||
from app.database.score_token import ScoreToken
|
from app.database.score_token import ScoreToken
|
||||||
from app.dependencies.database import engine
|
from app.dependencies.database import engine
|
||||||
from app.dependencies.fetcher import get_fetcher
|
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.mods import mods_to_int
|
||||||
from app.models.score import LegacyReplaySoloScoreInfo, ScoreStatistics
|
from app.models.score import LegacyReplaySoloScoreInfo, ScoreStatistics
|
||||||
from app.models.spectator_hub import (
|
from app.models.spectator_hub import (
|
||||||
@@ -25,7 +26,6 @@ from app.models.spectator_hub import (
|
|||||||
StoreClientState,
|
StoreClientState,
|
||||||
StoreScore,
|
StoreScore,
|
||||||
)
|
)
|
||||||
from app.path import REPLAY_DIR
|
|
||||||
from app.utils import unix_timestamp_to_windows
|
from app.utils import unix_timestamp_to_windows
|
||||||
|
|
||||||
from .hub import Client, Hub
|
from .hub import Client, Hub
|
||||||
@@ -64,7 +64,7 @@ def encode_string(s: str) -> bytes:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def save_replay(
|
async def save_replay(
|
||||||
ruleset_id: int,
|
ruleset_id: int,
|
||||||
md5: str,
|
md5: str,
|
||||||
username: str,
|
username: str,
|
||||||
@@ -136,10 +136,14 @@ def save_replay(
|
|||||||
data.extend(struct.pack("<i", len(compressed)))
|
data.extend(struct.pack("<i", len(compressed)))
|
||||||
data.extend(compressed)
|
data.extend(compressed)
|
||||||
|
|
||||||
|
storage_service = get_storage_service()
|
||||||
replay_path = (
|
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]):
|
class SpectatorHub(Hub[StoreClientState]):
|
||||||
@@ -298,7 +302,7 @@ class SpectatorHub(Hub[StoreClientState]):
|
|||||||
score_record.has_replay = True
|
score_record.has_replay = True
|
||||||
await session.commit()
|
await session.commit()
|
||||||
await session.refresh(score_record)
|
await session.refresh(score_record)
|
||||||
save_replay(
|
await save_replay(
|
||||||
ruleset_id=store.ruleset_id,
|
ruleset_id=store.ruleset_id,
|
||||||
md5=store.checksum,
|
md5=store.checksum,
|
||||||
username=store.score.score_info.user.name,
|
username=store.score.score_info.user.name,
|
||||||
|
|||||||
Reference in New Issue
Block a user