mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
221 lines
6.9 KiB
Python
221 lines
6.9 KiB
Python
from datetime import datetime, timezone
|
|
from typing import Annotated
|
|
|
|
from fastapi import Body
|
|
from fastapi import Path as PathVar
|
|
from fastapi import Request, status
|
|
|
|
from decorators.auth import protected_route
|
|
from endpoints.responses.platform import PlatformSchema
|
|
from exceptions.endpoint_exceptions import PlatformNotFoundInDatabaseException
|
|
from exceptions.fs_exceptions import PlatformAlreadyExistsException
|
|
from handler.auth.constants import Scope
|
|
from handler.database import db_platform_handler
|
|
from handler.filesystem import fs_platform_handler
|
|
from handler.metadata import (
|
|
meta_flashpoint_handler,
|
|
meta_hasheous_handler,
|
|
meta_igdb_handler,
|
|
meta_launchbox_handler,
|
|
meta_moby_handler,
|
|
meta_ra_handler,
|
|
meta_ss_handler,
|
|
meta_tgdb_handler,
|
|
)
|
|
from handler.metadata.base_handler import UniversalPlatformSlug as UPS
|
|
from handler.scan_handler import scan_platform
|
|
from logger.formatter import BLUE
|
|
from logger.formatter import highlight as hl
|
|
from logger.logger import log
|
|
from models.platform import DEFAULT_COVER_ASPECT_RATIO, Platform
|
|
from utils.router import APIRouter
|
|
|
|
router = APIRouter(
|
|
prefix="/platforms",
|
|
tags=["platforms"],
|
|
)
|
|
|
|
|
|
@protected_route(
|
|
router.post,
|
|
"",
|
|
[Scope.PLATFORMS_WRITE],
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def add_platform(
|
|
request: Request,
|
|
fs_slug: Annotated[str, Body(description="Platform slug.", embed=True)],
|
|
) -> PlatformSchema:
|
|
"""Create a platform."""
|
|
|
|
try:
|
|
await fs_platform_handler.add_platform(fs_slug=fs_slug)
|
|
except PlatformAlreadyExistsException:
|
|
log.info(f"Detected platform: {hl(fs_slug)}")
|
|
|
|
scanned_platform = await scan_platform(fs_slug, [fs_slug])
|
|
return PlatformSchema.model_validate(
|
|
db_platform_handler.add_platform(scanned_platform)
|
|
)
|
|
|
|
|
|
@protected_route(router.get, "", [Scope.PLATFORMS_READ])
|
|
def get_platforms(request: Request) -> list[PlatformSchema]:
|
|
"""Retrieve platforms."""
|
|
|
|
return [
|
|
PlatformSchema.model_validate(p) for p in db_platform_handler.get_platforms()
|
|
]
|
|
|
|
|
|
@protected_route(router.get, "/supported", [Scope.PLATFORMS_READ])
|
|
def get_supported_platforms(request: Request) -> list[PlatformSchema]:
|
|
"""Retrieve the list of supported platforms."""
|
|
|
|
db_platforms = db_platform_handler.get_platforms()
|
|
db_platforms_map = {p.slug: p for p in db_platforms}
|
|
|
|
now = datetime.now(timezone.utc)
|
|
supported_platforms = []
|
|
|
|
for upslug in UPS:
|
|
slug = upslug.value
|
|
|
|
db_platform = db_platforms_map.get(slug, None)
|
|
if db_platform:
|
|
supported_platforms.append(
|
|
PlatformSchema.model_validate(db_platform).model_dump()
|
|
)
|
|
continue
|
|
|
|
igdb_platform = meta_igdb_handler.get_platform(slug)
|
|
moby_platform = meta_moby_handler.get_platform(slug)
|
|
ss_platform = meta_ss_handler.get_platform(slug)
|
|
ra_platform = meta_ra_handler.get_platform(slug)
|
|
launchbox_platform = meta_launchbox_handler.get_platform(slug)
|
|
hasheous_platform = meta_hasheous_handler.get_platform(slug)
|
|
tgdb_platform = meta_tgdb_handler.get_platform(slug)
|
|
flashpoint_platform = meta_flashpoint_handler.get_platform(slug)
|
|
|
|
platform_attrs = {
|
|
"id": -1,
|
|
"name": slug.replace("-", " ").title(),
|
|
"fs_slug": slug,
|
|
"slug": slug,
|
|
"roms": [],
|
|
"rom_count": 0,
|
|
"created_at": now,
|
|
"updated_at": now,
|
|
"fs_size_bytes": 0,
|
|
"missing_from_fs": False,
|
|
"aspect_ratio": DEFAULT_COVER_ASPECT_RATIO,
|
|
}
|
|
|
|
platform_attrs.update(
|
|
{
|
|
**flashpoint_platform,
|
|
**hasheous_platform,
|
|
**tgdb_platform,
|
|
**launchbox_platform,
|
|
**ra_platform,
|
|
**moby_platform,
|
|
**ss_platform,
|
|
**igdb_platform,
|
|
"igdb_id": igdb_platform.get("igdb_id")
|
|
or hasheous_platform.get("igdb_id")
|
|
or None,
|
|
"ra_id": ra_platform.get("ra_id")
|
|
or hasheous_platform.get("ra_id")
|
|
or None,
|
|
"tgdb_id": moby_platform.get("tgdb_id")
|
|
or hasheous_platform.get("tgdb_id")
|
|
or None,
|
|
"name": igdb_platform.get("name")
|
|
or ss_platform.get("name")
|
|
or moby_platform.get("name")
|
|
or ra_platform.get("name")
|
|
or launchbox_platform.get("name")
|
|
or hasheous_platform.get("name")
|
|
or tgdb_platform.get("name")
|
|
or flashpoint_platform.get("name")
|
|
or slug.replace("-", " ").title(),
|
|
"url_logo": igdb_platform.get("url_logo")
|
|
or tgdb_platform.get("url_logo")
|
|
or "",
|
|
}
|
|
)
|
|
|
|
platform = Platform(**platform_attrs)
|
|
supported_platforms.append(PlatformSchema.model_validate(platform).model_dump())
|
|
|
|
return supported_platforms
|
|
|
|
|
|
@protected_route(
|
|
router.get,
|
|
"/{id}",
|
|
[Scope.PLATFORMS_READ],
|
|
responses={status.HTTP_404_NOT_FOUND: {}},
|
|
)
|
|
def get_platform(
|
|
request: Request,
|
|
id: Annotated[int, PathVar(description="Platform id.", ge=1)],
|
|
) -> PlatformSchema:
|
|
"""Retrieve a platform by ID."""
|
|
|
|
platform = db_platform_handler.get_platform(id)
|
|
if not platform:
|
|
raise PlatformNotFoundInDatabaseException(id)
|
|
return PlatformSchema.model_validate(platform)
|
|
|
|
|
|
@protected_route(
|
|
router.put,
|
|
"/{id}",
|
|
[Scope.PLATFORMS_WRITE],
|
|
responses={status.HTTP_404_NOT_FOUND: {}},
|
|
)
|
|
async def update_platform(
|
|
request: Request,
|
|
id: Annotated[int, PathVar(description="Platform id.", ge=1)],
|
|
aspect_ratio: Annotated[str | None, Body(description="Cover aspect ratio.")] = None,
|
|
custom_name: Annotated[
|
|
str | None, Body(description="Custom platform name.")
|
|
] = None,
|
|
) -> PlatformSchema:
|
|
"""Update a platform."""
|
|
|
|
platform_db = db_platform_handler.get_platform(id)
|
|
if not platform_db:
|
|
raise PlatformNotFoundInDatabaseException(id)
|
|
|
|
if aspect_ratio is not None:
|
|
platform_db.aspect_ratio = aspect_ratio
|
|
if custom_name is not None:
|
|
platform_db.custom_name = custom_name
|
|
platform_db = db_platform_handler.add_platform(platform_db)
|
|
|
|
return PlatformSchema.model_validate(platform_db)
|
|
|
|
|
|
@protected_route(
|
|
router.delete,
|
|
"/{id}",
|
|
[Scope.PLATFORMS_WRITE],
|
|
responses={status.HTTP_404_NOT_FOUND: {}},
|
|
)
|
|
async def delete_platform(
|
|
request: Request,
|
|
id: Annotated[int, PathVar(description="Platform id.", ge=1)],
|
|
) -> None:
|
|
"""Delete a platform by ID."""
|
|
|
|
platform = db_platform_handler.get_platform(id)
|
|
if not platform:
|
|
raise PlatformNotFoundInDatabaseException(id)
|
|
|
|
log.info(
|
|
f"Deleting {hl(platform.name, color=BLUE)} [{hl(platform.fs_slug)}] from database"
|
|
)
|
|
db_platform_handler.delete_platform(id)
|