Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions backend/config/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Config:
EXCLUDED_MULTI_FILES: list[str]
EXCLUDED_MULTI_PARTS_EXT: list[str]
EXCLUDED_MULTI_PARTS_FILES: list[str]
GAMELIST_AUTO_EXPORT_ON_SCAN: bool
PLATFORMS_BINDING: dict[str, str]
PLATFORMS_VERSIONS: dict[str, str]
ROMS_FOLDER_NAME: str
Expand Down Expand Up @@ -223,6 +224,9 @@ def _parse_config(self):
FIRMWARE_FOLDER_NAME=pydash.get(
self._raw_config, "filesystem.firmware_folder", "bios"
),
GAMELIST_AUTO_EXPORT_ON_SCAN=pydash.get(
self._raw_config, "scan.export_gamelist", False
),
SKIP_HASH_CALCULATION=pydash.get(
self._raw_config, "filesystem.skip_hash_calculation", False
),
Expand Down Expand Up @@ -364,6 +368,9 @@ def _validate_config(self):
"Invalid config.yml: exclude.roms.multi_file.parts.names must be a list"
)
sys.exit(3)
if not isinstance(self.config.GAMELIST_AUTO_EXPORT_ON_SCAN, bool):
log.critical("Invalid config.yml: scan.export_gamelist must be a boolean")
sys.exit(3)

if not isinstance(self.config.PLATFORMS_BINDING, dict):
log.critical("Invalid config.yml: system.platforms must be a dictionary")
Expand Down Expand Up @@ -570,6 +577,7 @@ def _update_config_file(self) -> None:
"language": self.config.SCAN_LANGUAGE_PRIORITY,
},
"media": self.config.SCAN_MEDIA,
"export_gamelist": self.config.GAMELIST_AUTO_EXPORT_ON_SCAN,
},
}

Expand Down
27 changes: 27 additions & 0 deletions backend/endpoints/sockets/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from tasks.tasks import update_job_meta
from utils import emoji
from utils.context import initialize_context
from utils.gamelist_exporter import GamelistExporter

STOP_SCAN_FLAG: Final = "scan:stop"

Expand Down Expand Up @@ -683,6 +684,32 @@ async def stop_scan():
log.warning(f" - {p.slug} ({p.fs_slug})")

log.info(f"{emoji.EMOJI_CHECK_MARK} Scan completed")

# Export gamelist.xml if enabled in config
config = cm.get_config()
if config.GAMELIST_AUTO_EXPORT_ON_SCAN:
log.info("Auto-exporting gamelist.xml for all platforms...")
gamelist_exporter = GamelistExporter(local_export=True)
platforms_by_slug = {
p.fs_slug: p for p in db_platform_handler.get_platforms()
}
for platform_slug in platform_list:
platform = platforms_by_slug.get(platform_slug)
if platform:
export_success = await gamelist_exporter.export_platform_to_file(
platform.id,
request=None,
)
if export_success:
log.info(
f"Auto-exported gamelist.xml for platform {platform.name} after scan"
)
else:
log.warning(
f"Failed to auto-export gamelist.xml for platform {platform.name} after scan"
)
log.info("Gamelist.xml auto-export completed.")

await socket_manager.emit("scan:done", scan_stats.to_dict())
except ScanStoppedException:
await stop_scan()
Expand Down
10 changes: 7 additions & 3 deletions backend/utils/gamelist_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ def _format_release_date(self, timestamp: int) -> str:
"""Format release date to YYYYMMDDTHHMMSS format"""
return datetime.fromtimestamp(timestamp / 1000).strftime("%Y%m%dT%H%M%S")

def _create_game_element(self, rom: Rom, request: Request) -> Element:
def _create_game_element(self, rom: Rom, request: Request | None) -> Element:
"""Create a <game> element for a ROM"""
game = Element("game")

# Basic game info
if self.local_export:
SubElement(game, "path").text = f"./{rom.fs_name}"
else:
if request is None:
raise ValueError(
"Request object must be provided for non-local exports"
)
SubElement(game, "path").text = str(
request.url_for(
"get_rom_content",
Expand Down Expand Up @@ -155,7 +159,7 @@ def _create_game_element(self, rom: Rom, request: Request) -> Element:

return game

def export_platform_to_xml(self, platform_id: int, request: Request) -> str:
def export_platform_to_xml(self, platform_id: int, request: Request | None) -> str:
"""Export a platform's ROMs to gamelist.xml format

Args:
Expand Down Expand Up @@ -188,7 +192,7 @@ def export_platform_to_xml(self, platform_id: int, request: Request) -> str:
async def export_platform_to_file(
self,
platform_id: int,
request: Request,
request: Request | None,
) -> bool:
"""Export platform ROMs to gamelist.xml file in the platform's directory

Expand Down
Loading