mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Merge pull request #1064 from rommapp/misc/improve-feed-schemas
misc: Improve typing for feed schemas
This commit is contained in:
@@ -9,7 +9,6 @@ load_dotenv()
|
||||
# GUNICORN
|
||||
DEV_PORT: Final = int(os.environ.get("VITE_BACKEND_DEV_PORT", "5000"))
|
||||
DEV_HOST: Final = "127.0.0.1"
|
||||
ROMM_HOST: Final = os.environ.get("ROMM_HOST", DEV_HOST)
|
||||
GUNICORN_WORKERS: Final = int(os.environ.get("GUNICORN_WORKERS", 2))
|
||||
|
||||
# PATHS
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
from config import DISABLE_DOWNLOAD_ENDPOINT_AUTH, ROMM_HOST
|
||||
from config import DISABLE_DOWNLOAD_ENDPOINT_AUTH
|
||||
from decorators.auth import protected_route
|
||||
from endpoints.responses.feeds import (
|
||||
WEBRCADE_SLUG_TO_TYPE_MAP,
|
||||
WEBRCADE_SUPPORTED_PLATFORM_SLUGS,
|
||||
TinfoilFeedFileSchema,
|
||||
TinfoilFeedSchema,
|
||||
WebrcadeFeedCategorySchema,
|
||||
WebrcadeFeedItemPropsSchema,
|
||||
WebrcadeFeedItemSchema,
|
||||
WebrcadeFeedSchema,
|
||||
)
|
||||
from fastapi import Request
|
||||
from handler.database import db_platform_handler, db_rom_handler
|
||||
from models.rom import Rom
|
||||
from starlette.datastructures import URLPath
|
||||
from utils.router import APIRouter
|
||||
|
||||
router = APIRouter()
|
||||
@@ -21,6 +26,7 @@ router = APIRouter()
|
||||
)
|
||||
def platforms_webrcade_feed(request: Request) -> WebrcadeFeedSchema:
|
||||
"""Get webrcade feed endpoint
|
||||
https://docs.webrcade.com/feeds/format/
|
||||
|
||||
Args:
|
||||
request (Request): Fastapi Request object
|
||||
@@ -31,37 +37,67 @@ def platforms_webrcade_feed(request: Request) -> WebrcadeFeedSchema:
|
||||
|
||||
platforms = db_platform_handler.get_platforms()
|
||||
|
||||
return {
|
||||
"title": "RomM Feed",
|
||||
"longTitle": "Custom RomM Feed",
|
||||
"description": "Custom feed from your RomM library",
|
||||
"thumbnail": "https://raw.githubusercontent.com/rommapp/romm/f2dd425d87ad8e21bf47f8258ae5dcf90f56fbc2/frontend/assets/isotipo.svg",
|
||||
"background": "https://raw.githubusercontent.com/rommapp/romm/release/.github/screenshots/gallery.png",
|
||||
"categories": [
|
||||
{
|
||||
"title": p.name,
|
||||
"longTitle": f"{p.name} Games",
|
||||
"background": f"{ROMM_HOST}/assets/webrcade/feed/{p.slug.lower()}-background.png",
|
||||
"thumbnail": f"{ROMM_HOST}/assets/webrcade/feed/{p.slug.lower()}-thumb.png",
|
||||
"description": "",
|
||||
"items": [
|
||||
{
|
||||
"title": rom.name,
|
||||
"description": rom.summary,
|
||||
"type": WEBRCADE_SLUG_TO_TYPE_MAP.get(p.slug, p.slug),
|
||||
"thumbnail": f"{ROMM_HOST}/assets/romm/resources/{rom.path_cover_s}",
|
||||
"background": f"{ROMM_HOST}/assets/romm/resources/{rom.path_cover_l}",
|
||||
"props": {
|
||||
"rom": f"{ROMM_HOST}/api/roms/{rom.id}/content/{rom.file_name}"
|
||||
},
|
||||
}
|
||||
for rom in db_rom_handler.get_roms(platform_id=p.id)
|
||||
],
|
||||
}
|
||||
for p in platforms
|
||||
if p.slug in WEBRCADE_SUPPORTED_PLATFORM_SLUGS
|
||||
],
|
||||
}
|
||||
categories = []
|
||||
for p in platforms:
|
||||
if p.slug not in WEBRCADE_SUPPORTED_PLATFORM_SLUGS:
|
||||
continue
|
||||
|
||||
category_items = []
|
||||
for rom in db_rom_handler.get_roms(platform_id=p.id):
|
||||
category_item = WebrcadeFeedItemSchema(
|
||||
title=rom.name or "",
|
||||
description=rom.summary or "",
|
||||
type=WEBRCADE_SLUG_TO_TYPE_MAP.get(p.slug, p.slug),
|
||||
props=WebrcadeFeedItemPropsSchema(
|
||||
rom=str(
|
||||
request.url_for(
|
||||
"get_rom_content",
|
||||
id=rom.id,
|
||||
file_name=rom.file_name,
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
if rom.path_cover_s:
|
||||
category_item["thumbnail"] = str(
|
||||
URLPath(
|
||||
f"/assets/romm/resources/{rom.path_cover_s}"
|
||||
).make_absolute_url(request.base_url)
|
||||
)
|
||||
if rom.path_cover_l:
|
||||
category_item["background"] = str(
|
||||
URLPath(
|
||||
f"/assets/romm/resources/{rom.path_cover_l}"
|
||||
).make_absolute_url(request.base_url)
|
||||
)
|
||||
category_items.append(category_item)
|
||||
|
||||
categories.append(
|
||||
WebrcadeFeedCategorySchema(
|
||||
title=p.name,
|
||||
longTitle=f"{p.name} Games",
|
||||
background=str(
|
||||
URLPath(
|
||||
f"/assets/webrcade/feed/{p.slug.lower()}-background.png"
|
||||
).make_absolute_url(request.base_url)
|
||||
),
|
||||
thumbnail=str(
|
||||
URLPath(
|
||||
f"/assets/webrcade/feed/{p.slug.lower()}-thumb.png"
|
||||
).make_absolute_url(request.base_url)
|
||||
),
|
||||
items=category_items,
|
||||
)
|
||||
)
|
||||
|
||||
return WebrcadeFeedSchema(
|
||||
title="RomM Feed",
|
||||
longTitle="Custom RomM Feed",
|
||||
description="Custom feed from your RomM library",
|
||||
thumbnail="https://raw.githubusercontent.com/rommapp/romm/f2dd425d87ad8e21bf47f8258ae5dcf90f56fbc2/frontend/assets/isotipo.svg",
|
||||
background="https://raw.githubusercontent.com/rommapp/romm/release/.github/resources/screenshots/gallery.png",
|
||||
categories=categories,
|
||||
)
|
||||
|
||||
|
||||
@protected_route(router.get, "/tinfoil/feed", ["roms.read"])
|
||||
@@ -77,16 +113,27 @@ def tinfoil_index_feed(request: Request, slug: str = "switch") -> TinfoilFeedSch
|
||||
TinfoilFeedSchema: Tinfoil feed object schema
|
||||
"""
|
||||
switch = db_platform_handler.get_platform_by_fs_slug(slug)
|
||||
if not switch:
|
||||
return TinfoilFeedSchema(
|
||||
files=[],
|
||||
directories=[],
|
||||
error="Nintendo Switch platform not found",
|
||||
)
|
||||
|
||||
files: list[Rom] = db_rom_handler.get_roms(platform_id=switch.id)
|
||||
|
||||
return {
|
||||
"files": [
|
||||
{
|
||||
"url": f"{ROMM_HOST}/api/roms/{file.id}/content/{file.file_name}",
|
||||
"size": file.file_size_bytes,
|
||||
}
|
||||
return TinfoilFeedSchema(
|
||||
files=[
|
||||
TinfoilFeedFileSchema(
|
||||
url=str(
|
||||
request.url_for(
|
||||
"get_rom_content", id=file.id, file_name=file.file_name
|
||||
)
|
||||
),
|
||||
size=file.file_size_bytes,
|
||||
)
|
||||
for file in files
|
||||
],
|
||||
"directories": [],
|
||||
"success": "RomM Switch Library",
|
||||
}
|
||||
directories=[],
|
||||
success="RomM Switch Library",
|
||||
)
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
from typing import NotRequired
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
WEBRCADE_SUPPORTED_PLATFORM_SLUGS = [
|
||||
"3do",
|
||||
"arcade",
|
||||
"atari2600",
|
||||
"atari5200",
|
||||
"atari7800",
|
||||
"lynx",
|
||||
"wonderswan",
|
||||
"wonderswan-color",
|
||||
"colecovision",
|
||||
"turbografx16--1",
|
||||
"turbografx-16-slash-pc-engine-cd",
|
||||
"supergrafx",
|
||||
"pc-fx",
|
||||
"nes",
|
||||
"n64",
|
||||
"snes",
|
||||
"gb",
|
||||
"gba",
|
||||
"gbc",
|
||||
"virtualboy",
|
||||
"sg1000",
|
||||
"sms",
|
||||
"genesis-slash-megadrive",
|
||||
"segacd",
|
||||
"gamegear",
|
||||
"neo-geo-cd",
|
||||
"neogeoaes",
|
||||
"neogeomvs",
|
||||
"neo-geo-pocket",
|
||||
"neo-geo-pocket-color",
|
||||
"ps",
|
||||
]
|
||||
WEBRCADE_SUPPORTED_PLATFORM_SLUGS = frozenset(
|
||||
(
|
||||
"3do",
|
||||
"arcade",
|
||||
"atari2600",
|
||||
"atari5200",
|
||||
"atari7800",
|
||||
"colecovision",
|
||||
"gamegear",
|
||||
"gb",
|
||||
"gba",
|
||||
"gbc",
|
||||
"genesis-slash-megadrive",
|
||||
"lynx",
|
||||
"n64",
|
||||
"neo-geo-cd",
|
||||
"neo-geo-pocket",
|
||||
"neo-geo-pocket-color",
|
||||
"neogeoaes",
|
||||
"neogeomvs",
|
||||
"nes",
|
||||
"pc-fx",
|
||||
"ps",
|
||||
"segacd",
|
||||
"sg1000",
|
||||
"sms",
|
||||
"snes",
|
||||
"supergrafx",
|
||||
"turbografx-16-slash-pc-engine-cd",
|
||||
"turbografx16--1",
|
||||
"virtualboy",
|
||||
"wonderswan",
|
||||
"wonderswan-color",
|
||||
)
|
||||
)
|
||||
|
||||
WEBRCADE_SLUG_TO_TYPE_MAP = {
|
||||
"atari2600": "2600",
|
||||
@@ -55,16 +59,53 @@ WEBRCADE_SLUG_TO_TYPE_MAP = {
|
||||
}
|
||||
|
||||
|
||||
# Webrcade feed format
|
||||
# Source: https://docs.webrcade.com/feeds/format/
|
||||
|
||||
|
||||
class WebrcadeFeedItemPropsSchema(TypedDict):
|
||||
rom: str
|
||||
|
||||
|
||||
class WebrcadeFeedItemSchema(TypedDict):
|
||||
title: str
|
||||
longTitle: NotRequired[str]
|
||||
description: NotRequired[str]
|
||||
type: str
|
||||
thumbnail: NotRequired[str]
|
||||
background: NotRequired[str]
|
||||
props: WebrcadeFeedItemPropsSchema
|
||||
|
||||
|
||||
class WebrcadeFeedCategorySchema(TypedDict):
|
||||
title: str
|
||||
longTitle: NotRequired[str]
|
||||
background: NotRequired[str]
|
||||
thumbnail: NotRequired[str]
|
||||
description: NotRequired[str]
|
||||
items: list[WebrcadeFeedItemSchema]
|
||||
|
||||
|
||||
class WebrcadeFeedSchema(TypedDict):
|
||||
title: str
|
||||
longTitle: str
|
||||
description: str
|
||||
thumbnail: str
|
||||
background: str
|
||||
categories: list[dict]
|
||||
longTitle: NotRequired[str]
|
||||
description: NotRequired[str]
|
||||
thumbnail: NotRequired[str]
|
||||
background: NotRequired[str]
|
||||
categories: list[WebrcadeFeedCategorySchema]
|
||||
|
||||
|
||||
# Tinfoil feed format
|
||||
# Source: https://blawar.github.io/tinfoil/custom_index/
|
||||
|
||||
|
||||
class TinfoilFeedFileSchema(TypedDict):
|
||||
url: str
|
||||
size: int
|
||||
|
||||
|
||||
class TinfoilFeedSchema(TypedDict):
|
||||
files: list[dict]
|
||||
files: list[TinfoilFeedFileSchema]
|
||||
directories: list[str]
|
||||
success: str
|
||||
success: NotRequired[str]
|
||||
error: NotRequired[str]
|
||||
|
||||
@@ -29,7 +29,9 @@ class APIRouter(FastAPIRouter):
|
||||
)
|
||||
|
||||
def decorator(func: DecoratedCallable) -> DecoratedCallable:
|
||||
# Path without trailing slash is registered first, for router's `url_path_for` to prefer it.
|
||||
result = add_path(func)
|
||||
add_alternate_path(func)
|
||||
return add_path(func)
|
||||
return result
|
||||
|
||||
return decorator
|
||||
|
||||
@@ -2,7 +2,6 @@ ROMM_BASE_PATH=/path/to/romm_mock
|
||||
VITE_BACKEND_DEV_PORT=5000
|
||||
|
||||
# Gunicorn (optional)
|
||||
ROMM_HOST=localhost
|
||||
GUNICORN_WORKERS=4 # (2 × CPU cores) + 1
|
||||
|
||||
# IGDB credentials
|
||||
|
||||
Reference in New Issue
Block a user