mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
saves endpoint refactor as RESTful
This commit is contained in:
@@ -3,7 +3,7 @@ from decorators.auth import protected_route
|
||||
from endpoints.responses import MessageResponse
|
||||
from endpoints.responses.assets import UploadedSavesResponse
|
||||
from fastapi import APIRouter, File, HTTPException, Request, UploadFile, status
|
||||
from handler import dbh, fsasseth, fsromh
|
||||
from handler import dbsaveh, fsasseth, dbromh
|
||||
from handler.scan_handler import scan_save
|
||||
from logger.logger import log
|
||||
|
||||
@@ -14,7 +14,7 @@ router = APIRouter()
|
||||
def add_saves(
|
||||
request: Request, rom_id: int, saves: list[UploadFile] = File(...)
|
||||
) -> UploadedSavesResponse:
|
||||
rom = dbh.get_rom(rom_id)
|
||||
rom = dbromh.get_roms(id=rom_id)
|
||||
log.info(f"Uploading saves to {rom.name}")
|
||||
if saves is None:
|
||||
log.error("No saves were uploaded")
|
||||
@@ -23,7 +23,7 @@ def add_saves(
|
||||
detail="No saves were uploaded",
|
||||
)
|
||||
|
||||
saves_path = fsromh.build_upload_file_path(
|
||||
saves_path = fsasseth.build_upload_file_path(
|
||||
rom.platform.fs_slug, folder=cm.config.SAVES_FOLDER_NAME
|
||||
)
|
||||
|
||||
@@ -32,18 +32,16 @@ def add_saves(
|
||||
|
||||
# Scan or update save
|
||||
scanned_save = scan_save(rom.platform, save.filename)
|
||||
db_save = dbh.get_save_by_filename(rom.platform_slug, save.filename)
|
||||
db_save = dbsaveh.get_save(rom.id, save.filename)
|
||||
if db_save:
|
||||
dbh.update_save(
|
||||
dbsaveh.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)
|
||||
dbsaveh.add_save(scanned_save)
|
||||
|
||||
rom = dbh.get_rom(rom_id)
|
||||
return {"uploaded": len(saves), "saves": rom.saves}
|
||||
|
||||
|
||||
@@ -74,19 +72,19 @@ async def delete_saves(request: Request) -> MessageResponse:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error)
|
||||
|
||||
for save_id in save_ids:
|
||||
save = dbh.get_save(save_id)
|
||||
save = dbsaveh.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)
|
||||
dbsaveh.delete_save(save_id)
|
||||
|
||||
if delete_from_fs:
|
||||
log.info(f"Deleting {save.file_name} from filesystem")
|
||||
|
||||
try:
|
||||
fsromh.remove_file(file_name=save.file_name, file_path=save.file_path)
|
||||
fsasseth.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)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from handler.auth_handler.auth_handler import AuthHandler, OAuthHandler
|
||||
from handler.db_handler.db_platforms_handler import DBPlatformsHandler
|
||||
from handler.db_handler.db_roms_handler import DBRomsHandler
|
||||
from handler.db_handler.db_saves_handler import DBSavesHandler
|
||||
from handler.fs_handler.fs_assets_handler import FSAssetsHandler
|
||||
from handler.fs_handler.fs_platforms_handler import FSPlatformsHandler
|
||||
from handler.fs_handler.fs_resources_handler import FSResourceHandler
|
||||
@@ -18,11 +19,13 @@ oauthh = OAuthHandler()
|
||||
socketh = SocketHandler()
|
||||
dbplatformh = DBPlatformsHandler()
|
||||
dbromh = DBRomsHandler()
|
||||
dbsaveh = DBSavesHandler()
|
||||
fsplatformh = FSPlatformsHandler()
|
||||
fsromh = FSRomsHandler()
|
||||
fsasseth = FSAssetsHandler()
|
||||
fsresourceh = FSResourceHandler()
|
||||
|
||||
|
||||
from handler.db_handler.db_handler import DBHandler
|
||||
from handler.db_handler.db_handler import DBHandler
|
||||
|
||||
dbh = DBHandler()
|
||||
|
||||
@@ -10,51 +10,6 @@ class DBHandler:
|
||||
self.engine = create_engine(ConfigManager.get_db_engine(), pool_pre_ping=True)
|
||||
self.session = sessionmaker(bind=self.engine, expire_on_commit=False)
|
||||
|
||||
# ========= Roms =========
|
||||
@begin_session
|
||||
def add_rom(self, rom: Rom, session: Session = None):
|
||||
return session.merge(rom)
|
||||
|
||||
def get_roms(self, platform_slug: str):
|
||||
return (
|
||||
select(Rom)
|
||||
.filter_by(platform_slug=platform_slug)
|
||||
.order_by(func.lower(Rom.name).asc())
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def get_rom(self, id: int, session: Session = None):
|
||||
return session.get(Rom, id)
|
||||
|
||||
@begin_session
|
||||
def get_recent_roms(self, session: Session = None):
|
||||
return session.scalars(select(Rom).order_by(Rom.id.desc()).limit(15)).all()
|
||||
|
||||
@begin_session
|
||||
def update_rom(self, id: int, data: dict, session: Session = None):
|
||||
return session.execute(
|
||||
update(Rom)
|
||||
.where(Rom.id == id)
|
||||
.values(**data)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def delete_rom(self, id: int, session: Session = None):
|
||||
return session.execute(
|
||||
delete(Rom)
|
||||
.where(Rom.id == id)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def purge_roms(self, platform_id: int, roms: list[str], session: Session = None):
|
||||
return session.execute(
|
||||
delete(Rom)
|
||||
.where(and_(Rom.platform_id == platform_id, Rom.file_name.not_in(roms)))
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
# ==== Utils ======
|
||||
@begin_session
|
||||
def get_rom_by_filename(
|
||||
@@ -73,48 +28,7 @@ class DBHandler:
|
||||
).first()
|
||||
|
||||
# ========= Saves =========
|
||||
@begin_session
|
||||
def add_save(self, save: Save, session: Session = None):
|
||||
return session.merge(save)
|
||||
|
||||
@begin_session
|
||||
def get_save(self, id, session: Session = None):
|
||||
return session.get(Save, id)
|
||||
|
||||
@begin_session
|
||||
def get_save_by_filename(
|
||||
self, platform_slug: str, file_name: str, session: Session = None
|
||||
):
|
||||
return session.scalars(
|
||||
select(Save)
|
||||
.filter_by(platform_slug=platform_slug, file_name=file_name)
|
||||
.limit(1)
|
||||
).first()
|
||||
|
||||
@begin_session
|
||||
def update_save(self, id: int, data: dict, session: Session = None):
|
||||
session.execute(
|
||||
update(Save)
|
||||
.where(Save.id == id)
|
||||
.values(**data)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def delete_save(self, id: int, session: Session = None):
|
||||
return session.execute(
|
||||
delete(Save)
|
||||
.where(Save.id == id)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def purge_saves(self, platform_id: int, saves: list[str], session: Session = None):
|
||||
return session.execute(
|
||||
delete(Save)
|
||||
.where(and_(Save.platform_id == platform_id, Save.file_name.not_in(saves)))
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
|
||||
# ========= States =========
|
||||
@begin_session
|
||||
|
||||
64
backend/handler/db_handler/db_saves_handler.py
Normal file
64
backend/handler/db_handler/db_saves_handler.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from decorators.database import begin_session
|
||||
from handler.db_handler.db_handler import DBHandler
|
||||
from models import Save, Rom
|
||||
from sqlalchemy import and_, delete, func, select, update
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
||||
class DBSavesHandler(DBHandler):
|
||||
# @staticmethod
|
||||
# def _filter(data, platform_id, search_term):
|
||||
# if platform_id:
|
||||
# data = data.filter_by(platform_id=platform_id)
|
||||
# if search_term:
|
||||
# data = data.filter(Rom.file_name.ilike(f"%{search_term}%"))
|
||||
# return data
|
||||
|
||||
# @staticmethod
|
||||
# def _order(data, order_by, order_dir):
|
||||
# if order_by == "name":
|
||||
# _column = func.lower(Rom.name)
|
||||
# elif order_by == "id":
|
||||
# _column = Rom.id
|
||||
# else:
|
||||
# _column = func.lower(Rom.name)
|
||||
|
||||
# if order_dir == "asc":
|
||||
# return data.order_by(_column.asc())
|
||||
# elif order_dir == "desc":
|
||||
# return data.order_by(_column.desc())
|
||||
# else:
|
||||
# return data.order_by(_column.asc())
|
||||
|
||||
@begin_session
|
||||
def add_save(self, save: Save, session: Session = None):
|
||||
return session.merge(save)
|
||||
|
||||
@begin_session
|
||||
def get_save(self, id: int, session: Session = None):
|
||||
return session.get(Save, id)
|
||||
|
||||
@begin_session
|
||||
def update_save(self, id: int, data: dict, session: Session = None):
|
||||
session.execute(
|
||||
update(Save)
|
||||
.where(Save.id == id)
|
||||
.values(**data)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def delete_save(self, id: int, session: Session = None):
|
||||
return session.execute(
|
||||
delete(Save)
|
||||
.where(Save.id == id)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def purge_saves(self, platform_id: int, saves: list[str], session: Session = None):
|
||||
return session.execute(
|
||||
delete(Save)
|
||||
.where(and_(Save.platform_id == platform_id, Save.file_name.not_in(saves)))
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
76
backend/handler/db_handler/db_states_handler.py
Normal file
76
backend/handler/db_handler/db_states_handler.py
Normal file
@@ -0,0 +1,76 @@
|
||||
from decorators.database import begin_session
|
||||
from handler.db_handler.db_handler import DBHandler
|
||||
from models import Rom
|
||||
from sqlalchemy import and_, delete, func, select, update
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
||||
class DBRomsHandler(DBHandler):
|
||||
@staticmethod
|
||||
def _filter(data, platform_id, search_term):
|
||||
if platform_id:
|
||||
data = data.filter_by(platform_id=platform_id)
|
||||
if search_term:
|
||||
data = data.filter(Rom.file_name.ilike(f"%{search_term}%"))
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def _order(data, order_by, order_dir):
|
||||
if order_by == "name":
|
||||
_column = func.lower(Rom.name)
|
||||
elif order_by == "id":
|
||||
_column = Rom.id
|
||||
else:
|
||||
_column = func.lower(Rom.name)
|
||||
|
||||
if order_dir == "asc":
|
||||
return data.order_by(_column.asc())
|
||||
elif order_dir == "desc":
|
||||
return data.order_by(_column.desc())
|
||||
else:
|
||||
return data.order_by(_column.asc())
|
||||
|
||||
@begin_session
|
||||
def get_roms(
|
||||
self,
|
||||
id: int = None,
|
||||
platform_id: int = None,
|
||||
search_term: str = "",
|
||||
order_by: str = "name",
|
||||
order_dir: str = "asc",
|
||||
session: Session = None,
|
||||
):
|
||||
return (
|
||||
session.get(Rom, id)
|
||||
if id
|
||||
else self._order(
|
||||
self._filter(select(Rom), platform_id, search_term),
|
||||
order_by,
|
||||
order_dir,
|
||||
)
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def update_rom(self, id: int, data: dict, session: Session = None):
|
||||
return session.execute(
|
||||
update(Rom)
|
||||
.where(Rom.id == id)
|
||||
.values(**data)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def delete_rom(self, id: int, session: Session = None):
|
||||
return session.execute(
|
||||
delete(Rom)
|
||||
.where(Rom.id == id)
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
|
||||
@begin_session
|
||||
def purge_roms(self, platform_id: int, roms: list[str], session: Session = None):
|
||||
return session.execute(
|
||||
delete(Rom)
|
||||
.where(and_(Rom.platform_id == platform_id, Rom.file_name.not_in(roms)))
|
||||
.execution_options(synchronize_session="evaluate")
|
||||
)
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from abc import ABC
|
||||
|
||||
from config import LIBRARY_BASE_PATH
|
||||
@@ -38,3 +39,10 @@ class FSHandler(ABC):
|
||||
):
|
||||
rom_path = self.get_fs_structure(fs_slug, folder=folder)
|
||||
return f"{LIBRARY_BASE_PATH}/{rom_path}"
|
||||
|
||||
@staticmethod
|
||||
def remove_file(file_name: str, file_path: str):
|
||||
try:
|
||||
os.remove(f"{LIBRARY_BASE_PATH}/{file_path}/{file_name}")
|
||||
except IsADirectoryError:
|
||||
shutil.rmtree(f"{LIBRARY_BASE_PATH}/{file_path}/{file_name}")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from models.platform import Platform
|
||||
|
||||
@@ -191,10 +190,3 @@ class FSRomsHandler(FSHandler):
|
||||
f"{LIBRARY_BASE_PATH}/{file_path}/{old_name}",
|
||||
f"{LIBRARY_BASE_PATH}/{file_path}/{new_name}",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def remove_file(file_name: str, file_path: str):
|
||||
try:
|
||||
os.remove(f"{LIBRARY_BASE_PATH}/{file_path}/{file_name}")
|
||||
except IsADirectoryError:
|
||||
shutil.rmtree(f"{LIBRARY_BASE_PATH}/{file_path}/{file_name}")
|
||||
|
||||
Reference in New Issue
Block a user