Files
romm/backend/endpoints/assets.py
2024-01-12 23:44:27 +01:00

171 lines
5.6 KiB
Python

from pathlib import Path
from config.config_loader import config
from decorators.oauth import protected_route
from endpoints.responses.assets import (
SaveSchema,
StateSchema,
UploadedSavesResponse,
UploadedStatesResponse,
)
from fastapi import APIRouter, File, HTTPException, Request, UploadFile, status
from handler import dbh
from logger.logger import log
from handler.scan_handler import scan_save, scan_state
router = APIRouter()
def write_file(file: UploadFile, path: str) -> None:
log.info(f" - Uploading {file.filename}")
file_location = f"{path}/{file.filename}"
Path(path).mkdir(parents=True, exist_ok=True)
with open(file_location, "wb+") as f:
while True:
chunk = file.file.read(1024)
if not chunk:
break
f.write(chunk)
@protected_route(router.put, "/saves/upload", ["assets.write"])
def upload_saves(
request: Request, rom_id: str, saves: list[UploadFile] = File(...)
) -> UploadedSavesResponse:
rom = dbh.get_rom(rom_id)
log.info(f"Uploading saves to {rom.name}")
if saves is None:
log.error("No saves were uploaded")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="No saves were uploaded",
)
saves_path = fsh.build_upload_file_path(
rom.platform.fs_slug, folder=config.SAVES_FOLDER_NAME
)
for save in saves:
write_file(file=save, path=saves_path)
# Scan or update save
scanned_save = scan_save(rom.platform, save.filename)
db_save = dbh.get_save_by_filename(rom.platform_slug, save.filename)
if db_save:
dbh.update_save(
db_save.id, {"file_size_bytes": scanned_save.file_size_bytes}
)
continue
scanned_save.rom_id = rom.id
scanned_save.platform_slug = rom.platform_slug
dbh.add_save(scanned_save)
rom = dbh.get_rom(rom_id)
return {"uploaded": len(saves), "saves": rom.saves}
@protected_route(router.post, "/saves/delete", ["assets.write"])
async def delete_saves(request: Request) -> list[SaveSchema]:
data: dict = await request.json()
save_ids: list = data["saves"]
delete_from_fs: bool = data["delete_from_fs"]
if not save_ids:
error = "No saves were provided"
log.error(error)
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error)
for save_id in save_ids:
save = dbh.get_save(save_id)
if not save:
error = f"Save with ID {save_id} not found"
log.error(error)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
dbh.delete_save(save_id)
if delete_from_fs:
log.info(f"Deleting {save.file_name} from filesystem")
try:
fsh.remove_file(file_name=save.file_name, file_path=save.file_path)
except FileNotFoundError:
error = f"Save file {save.file_name} not found for platform {save.platform_slug}"
log.error(error)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
rom = dbh.get_rom(save.rom_id)
return rom.saves
@protected_route(router.put, "/states/upload", ["assets.write"])
def upload_states(
request: Request, rom_id: str, states: list[UploadFile] = File(...)
) -> UploadedStatesResponse:
rom = dbh.get_rom(rom_id)
log.info(f"Uploading states to {rom.name}")
if states is None:
log.error("No states were uploaded")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="No states were uploaded",
)
states_path = fsh.build_upload_file_path(
rom.platform.fs_slug, folder=config.STATES_FOLDER_NAME
)
for state in states:
write_file(file=state, path=states_path)
# Scan or update state
scanned_state = scan_state(rom.platform, state.filename)
db_state = dbh.get_state_by_filename(rom.platform_slug, state.filename)
if db_state:
dbh.update_state(
db_state.id, {"file_size_bytes": scanned_state.file_size_bytes}
)
continue
scanned_state.rom_id = rom.id
scanned_state.platform_slug = rom.platform_slug
dbh.add_state(scanned_state)
rom = dbh.get_rom(rom_id)
return {"uploaded": len(states), "states": rom.states}
@protected_route(router.post, "/states/delete", ["assets.write"])
async def delete_states(request: Request) -> list[StateSchema]:
data: dict = await request.json()
state_ids: list = data["states"]
delete_from_fs: bool = data["delete_from_fs"]
if not state_ids:
error = "No states were provided"
log.error(error)
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error)
for state_id in state_ids:
state = dbh.get_state(state_id)
if not state:
error = f"Save with ID {state_id} not found"
log.error(error)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
dbh.delete_state(state_id)
if delete_from_fs:
log.info(f"Deleting {state.file_name} from filesystem")
try:
fsh.remove_file(file_name=state.file_name, file_path=state.file_path)
except FileNotFoundError:
error = f"Save file {state.file_name} not found for platform {state.platform_slug}"
log.error(error)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
rom = dbh.get_rom(state.rom_id)
return rom.states