Skip to content

Commit

Permalink
added collection cover management
Browse files Browse the repository at this point in the history
  • Loading branch information
zurdi15 committed Jul 3, 2024
1 parent 39708ff commit 665dade
Show file tree
Hide file tree
Showing 38 changed files with 406 additions and 529 deletions.
12 changes: 7 additions & 5 deletions backend/alembic/versions/0019_resources_refactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ def upgrade() -> None:

old_folder_path = f"{RESOURCES_BASE_PATH}/{platform_slug}/{rom.name}"
new_folder_path = (
f"{RESOURCES_BASE_PATH}/{platform_folder_name}/{rom_folder_name}"
f"{RESOURCES_BASE_PATH}/roms/{platform_folder_name}/{rom_folder_name}"
)

print("INFO:\t [Resources migration] Renaming folder:")
print(f"INFO:\t [Resources migration] - old: {old_folder_path}")
print(f"INFO:\t [Resources migration] - new: {new_folder_path}")

try:
os.makedirs(f"{RESOURCES_BASE_PATH}/{platform_folder_name}", exist_ok=True)
os.makedirs(
f"{RESOURCES_BASE_PATH}/roms/{platform_folder_name}", exist_ok=True
)
except OSError as error:
print(error)

Expand Down Expand Up @@ -94,9 +96,9 @@ def upgrade() -> None:
),
{
"id": rom.id,
"path_cover_s": updated_path_cover_s,
"path_cover_l": updated_path_cover_l,
"path_screenshots": updated_path_screenshots,
"path_cover_s": f"roms/{updated_path_cover_s}",
"path_cover_l": f"roms/{updated_path_cover_l}",
"path_screenshots": f"roms/{updated_path_screenshots}",
},
)

Expand Down
109 changes: 100 additions & 9 deletions backend/endpoints/collections.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json
from shutil import rmtree

from config import RESOURCES_BASE_PATH
from decorators.auth import protected_route
from endpoints.responses import MessageResponse
from endpoints.responses.collection import CollectionSchema
Expand All @@ -8,16 +10,21 @@
CollectionNotFoundInDatabaseException,
CollectionPermissionError,
)
from fastapi import APIRouter, Request
from fastapi import APIRouter, Request, UploadFile
from handler.database import db_collection_handler
from handler.filesystem import fs_resource_handler
from logger.logger import log
from models.collection import Collection
from sqlalchemy.inspection import inspect

router = APIRouter()


@protected_route(router.post, "/collections", ["collections.write"])
async def add_collection(request: Request) -> CollectionSchema:
async def add_collection(
request: Request,
artwork: UploadFile | None = None,
) -> CollectionSchema:
"""Create collection endpoint
Args:
Expand All @@ -27,19 +34,57 @@ async def add_collection(request: Request) -> CollectionSchema:
CollectionSchema: Just created collection
"""

data = await request.json()
data = await request.form()
cleaned_data = {
"name": data["name"],
"description": data["description"],
"name": data.get("name", ""),
"description": data.get("description", ""),
"url_cover": data.get("url_cover", ""),
"is_public": data.get("is_public", False),
"user_id": request.user.id,
}
collection_db = db_collection_handler.get_collection_by_name(
cleaned_data["name"], request.user.id
)

if collection_db:
raise CollectionAlreadyExistsException(cleaned_data["name"])
collection = Collection(**cleaned_data)
return db_collection_handler.add_collection(collection)

_added_collection = db_collection_handler.add_collection(Collection(**cleaned_data))

if artwork is not None:
file_ext = artwork.filename.split(".")[-1]
(
path_cover_l,
path_cover_s,
artwork_path,
) = fs_resource_handler.build_artwork_path(_added_collection, file_ext)

artwork_file = artwork.file.read()
file_location_s = f"{artwork_path}/small.{file_ext}"
with open(file_location_s, "wb+") as artwork_s:
artwork_s.write(artwork_file)
fs_resource_handler.resize_cover_to_small(file_location_s)

file_location_l = f"{artwork_path}/big.{file_ext}"
with open(file_location_l, "wb+") as artwork_l:
artwork_l.write(artwork_file)
else:
path_cover_s, path_cover_l = fs_resource_handler.get_cover(
overwrite=True,
entity=_added_collection,
url_cover=_added_collection.url_cover,
)

_added_collection.path_cover_s = path_cover_s
_added_collection.path_cover_l = path_cover_l
# Update the collection with the cover path and update database
return db_collection_handler.update_collection(
_added_collection.id,
{
c: getattr(_added_collection, c)
for c in inspect(_added_collection).mapper.column_attrs.keys()
},
)


@protected_route(router.get, "/collections", ["collections.read"])
Expand Down Expand Up @@ -78,7 +123,12 @@ def get_collection(request: Request, id: int) -> CollectionSchema:


@protected_route(router.put, "/collections/{id}", ["collections.write"])
async def update_collection(request: Request, id: int) -> MessageResponse:
async def update_collection(
request: Request,
id: int,
remove_cover: bool = False,
artwork: UploadFile | None = None,
) -> MessageResponse:
"""Update collection endpoint
Args:
Expand Down Expand Up @@ -109,12 +159,48 @@ async def update_collection(request: Request, id: int) -> MessageResponse:
"name": data.get("name", collection.name),
"description": data.get("description", collection.description),
"roms": list(set(roms)),
"url_cover": data.get("url_cover", collection.url_cover),
"is_public": data.get("is_public", collection.is_public),
"user_id": request.user.id,
}

if remove_cover:
cleaned_data.update(fs_resource_handler.remove_cover(collection))
cleaned_data.update({"url_cover": ""})
else:
if artwork is not None:
file_ext = artwork.filename.split(".")[-1]
(
path_cover_l,
path_cover_s,
artwork_path,
) = fs_resource_handler.build_artwork_path(collection, file_ext)

cleaned_data["path_cover_l"] = path_cover_l
cleaned_data["path_cover_s"] = path_cover_s

artwork_file = artwork.file.read()
file_location_s = f"{artwork_path}/small.{file_ext}"
with open(file_location_s, "wb+") as artwork_s:
artwork_s.write(artwork_file)
fs_resource_handler.resize_cover_to_small(file_location_s)

file_location_l = f"{artwork_path}/big.{file_ext}"
with open(file_location_l, "wb+") as artwork_l:
artwork_l.write(artwork_file)
else:
cleaned_data["url_cover"] = data.get("url_cover", collection.url_cover)
path_cover_s, path_cover_l = fs_resource_handler.get_cover(
overwrite=cleaned_data["url_cover"] != collection.url_cover,
entity=collection,
url_cover=cleaned_data.get("url_cover", ""),
)
cleaned_data.update(
{"path_cover_s": path_cover_s, "path_cover_l": path_cover_l}
)

db_collection_handler.update_collection(id, cleaned_data)
return {"msg": "Collection updated successfully!"}
return {"msg": f"Collection {cleaned_data['name']} updated successfully!"}


@protected_route(router.delete, "/collections/{id}", ["collections.write"])
Expand Down Expand Up @@ -142,4 +228,9 @@ async def delete_collections(request: Request, id: int) -> MessageResponse:
log.info(f"Deleting {collection.name} from database")
db_collection_handler.delete_collection(id)

try:
rmtree(f"{RESOURCES_BASE_PATH}/{collection.fs_resources_path}")
except FileNotFoundError:
log.error(f"Couldn't find resources to delete for {collection.name}")

return {"msg": f"{collection.name} deleted successfully!"}
65 changes: 36 additions & 29 deletions backend/endpoints/rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,10 @@ async def update_rom(
if not rom:
raise RomNotFoundInDatabaseException(id)

cleaned_data = {}
cleaned_data["igdb_id"] = data.get("igdb_id", None)
cleaned_data["moby_id"] = data.get("moby_id", None)
cleaned_data = {
"igdb_id": data.get("igdb_id", None),
"moby_id": data.get("moby_id", None),
}

if cleaned_data["moby_id"]:
moby_rom = meta_moby_handler.get_rom_by_id(cleaned_data["moby_id"])
Expand All @@ -311,8 +312,12 @@ async def update_rom(
else:
cleaned_data.update({"igdb_metadata": {}})

cleaned_data["name"] = data.get("name", rom.name)
cleaned_data["summary"] = data.get("summary", rom.summary)
cleaned_data.update(
{
"name": data.get("name", rom.name),
"summary": data.get("summary", rom.summary),
}
)

fs_safe_file_name = data.get("file_name", rom.file_name).strip().replace("/", "-")
fs_safe_name = cleaned_data["name"].strip().replace("/", "-")
Expand All @@ -330,21 +335,25 @@ async def update_rom(
file_path=rom.file_path,
)
except RomAlreadyExistsException as exc:
log.error(str(exc))
log.error(exc)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=exc
) from exc

cleaned_data["file_name"] = fs_safe_file_name
cleaned_data["file_name_no_tags"] = fs_rom_handler.get_file_name_with_no_tags(
fs_safe_file_name
)
cleaned_data["file_name_no_ext"] = fs_rom_handler.get_file_name_with_no_extension(
fs_safe_file_name
cleaned_data.update(
{
"file_name": fs_safe_file_name,
"file_name_no_tags": fs_rom_handler.get_file_name_with_no_tags(
fs_safe_file_name
),
"file_name_no_ext": fs_rom_handler.get_file_name_with_no_extension(
fs_safe_file_name
),
}
)

if remove_cover:
cleaned_data.update(fs_resource_handler.remove_cover(rom=rom))
cleaned_data.update(fs_resource_handler.remove_cover(rom))
cleaned_data.update({"url_cover": ""})
else:
if artwork is not None:
Expand All @@ -355,8 +364,9 @@ async def update_rom(
artwork_path,
) = fs_resource_handler.build_artwork_path(rom, file_ext)

cleaned_data["path_cover_l"] = path_cover_l
cleaned_data["path_cover_s"] = path_cover_s
cleaned_data.update(
{"path_cover_s": path_cover_s, "path_cover_l": path_cover_l}
)

artwork_file = artwork.file.read()
file_location_s = f"{artwork_path}/small.{file_ext}"
Expand All @@ -368,10 +378,10 @@ async def update_rom(
with open(file_location_l, "wb+") as artwork_l:
artwork_l.write(artwork_file)
else:
cleaned_data["url_cover"] = data.get("url_cover", rom.url_cover)
path_cover_s, path_cover_l = fs_resource_handler.get_rom_cover(
cleaned_data.update({"url_cover": data.get("url_cover", rom.url_cover)})
path_cover_s, path_cover_l = fs_resource_handler.get_cover(
overwrite=cleaned_data["url_cover"] != rom.url_cover,
rom=rom,
entity=rom,
url_cover=cleaned_data.get("url_cover", ""),
)
cleaned_data.update(
Expand Down Expand Up @@ -454,15 +464,12 @@ async def update_rom_user(request: Request, id: int) -> RomUserSchema:
id, request.user.id
) or db_rom_handler.add_rom_user(id, request.user.id)

cleaned_data = {}
cleaned_data["note_raw_markdown"] = data.get(
"note_raw_markdown", db_rom_user.note_raw_markdown
)
cleaned_data["note_is_public"] = data.get(
"note_is_public", db_rom_user.note_is_public
)
cleaned_data["is_main_sibling"] = data.get(
"is_main_sibling", db_rom_user.is_main_sibling
)
cleaned_data = {
"note_raw_markdown": data.get(
"note_raw_markdown", db_rom_user.note_raw_markdown
),
"note_is_public": data.get("note_is_public", db_rom_user.note_is_public),
"is_main_sibling": data.get("is_main_sibling", db_rom_user.is_main_sibling),
}

return db_rom_handler.update_rom_user(db_rom_user.id, cleaned_data)
4 changes: 2 additions & 2 deletions backend/endpoints/sockets/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ async def scan_platforms(

_added_rom = db_rom_handler.add_rom(scanned_rom)

path_cover_s, path_cover_l = fs_resource_handler.get_rom_cover(
path_cover_s, path_cover_l = fs_resource_handler.get_cover(
overwrite=True,
rom=_added_rom,
entity=_added_rom,
url_cover=_added_rom.url_cover,
)

Expand Down
3 changes: 2 additions & 1 deletion backend/handler/database/collections_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ def get_collections(
def update_collection(
self, id: int, data: dict, session: Session = None
) -> Collection:
return session.execute(
session.execute(
update(Collection)
.where(Collection.id == id)
.values(**data)
.execution_options(synchronize_session="evaluate")
)
return self.get_collection(id)

@begin_session
def delete_collection(self, id: int, session: Session = None) -> int:
Expand Down
Loading

0 comments on commit 665dade

Please sign in to comment.