Skip to content

feat: Auto Export Game List on scan#2987

Merged
gantoine merged 9 commits intorommapp:masterfrom
ItzCobaltboy:feat_auto_export_gamelist
Feb 5, 2026
Merged

feat: Auto Export Game List on scan#2987
gantoine merged 9 commits intorommapp:masterfrom
ItzCobaltboy:feat_auto_export_gamelist

Conversation

@ItzCobaltboy
Copy link
Contributor

Implementation for #2975

Description
Implements the Feature of automatic export of gamelist for each platform on Library scan. Adds a new config feature to enable it (Disabled by default)

Implementation details

  • Parses a configuration gamelist.auto_export_on_scan on boot, default set to false
  • If set to true, at the end of scan_platforms, calls GameListExporter for exporting gamelist.xml locally
  • Modifies GameListExporter to accept None if local_export=True is set, throws value error if request is not passed for non local export

Files changed

  • backend/config/config_manager.py
  • backend/endpoints/sockets/scan.py
  • backend/utils/gamelist_exporter.py

This pull request introduces a new configuration option to automatically export gamelist.xml files for all platforms after a scan completes. The changes include updates to configuration management, validation, and the scan completion workflow, as well as improvements to the gamelist exporter utility to support optional request objects for local exports.

Configuration management and validation:

  • Added the GAMELIST_AUTO_EXPORT_ON_SCAN boolean option to the Config class, parsing, and validation logic to control auto-export behavior.

Scan workflow enhancements:

  • Updated the scan completion handler to check the new config option and, if enabled, automatically export gamelist.xml for all scanned platforms using the GamelistExporter. Errors during export are logged per platform.

Gamelist exporter improvements:

  • Modified GamelistExporter methods (_create_game_element, export_platform_to_xml, and export_platform_to_file) to accept an optional request argument, raising an error if a non-local export is attempted without a request. This supports the new local auto-export workflow.

AI Disclosure

The PR and Code is authored by me. ChatGPT was used for codebase comprehension and to sanity-check the implementation for potential misbehavior.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Copilot AI review requested due to automatic review settings February 4, 2026 06:38
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ItzCobaltboy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new feature that allows for the automatic export of gamelist.xml files for all scanned platforms immediately after a library scan completes. This enhancement streamlines the workflow for users who rely on these XML files, providing an opt-in configuration to enable this convenience. The changes involve updating the configuration management to include and validate the new setting, integrating the export process into the scan completion handler, and refining the GamelistExporter to support this new local export mechanism.

Highlights

  • New Configuration Option: Introduced a new boolean configuration option, gamelist.auto_export_on_scan, which is disabled by default. This option controls whether gamelist.xml files are automatically exported after a library scan.
  • Automatic Gamelist Export: Implemented functionality to automatically export gamelist.xml for each platform after a successful library scan, provided the new configuration option is enabled. This process includes logging for success and error handling for individual platform exports.
  • Gamelist Exporter Enhancements: Modified the GamelistExporter utility to gracefully handle local exports without requiring a request object. For non-local exports, a ValueError is now raised if the request object is not provided, ensuring proper context for URL generation.
Changelog
  • backend/config/config_manager.py
    • Added GAMELIST_AUTO_EXPORT_ON_SCAN as a new attribute to the Config class.
    • Implemented parsing logic for gamelist.auto_export_on_scan from the raw configuration, defaulting to False.
    • Added validation to ensure gamelist.auto_export_on_scan is a boolean type.
    • Included gamelist.auto_export_on_scan in the configuration file update mechanism.
  • backend/endpoints/sockets/scan.py
    • Imported the GamelistExporter utility.
    • Integrated a conditional block within the scan completion handler to check GAMELIST_AUTO_EXPORT_ON_SCAN.
    • If enabled, an instance of GamelistExporter is created for local export, and gamelist.xml is exported for each scanned platform.
    • Added logging for the auto-export process, including success messages and error handling for failed exports per platform.
  • backend/utils/gamelist_exporter.py
    • Modified the _create_game_element method to accept request: Request | None, allowing it to be optional for local exports.
    • Added a ValueError check in _create_game_element to ensure a request object is provided for non-local exports.
    • Updated the export_platform_to_xml method signature to accept request: Request | None.
    • Updated the export_platform_to_file method signature to accept request: Request | None.
Activity
  • The author, ItzCobaltboy, created this pull request to implement automatic gamelist export on scan.
  • The author has tested the changes locally and updated relevant comments.
  • The author used ChatGPT for codebase comprehension and to sanity-check the implementation.
  • No human review comments or approvals have been recorded yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new feature to automatically export gamelist.xml after a library scan, controlled by a new configuration option. The implementation is well-structured, covering configuration management, the scan workflow, and modifications to the gamelist exporter to support local exports without a request context. I have one suggestion to improve performance by refactoring a loop to avoid multiple database queries.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in configuration flag to automatically export ES-DE gamelist.xml files for scanned platforms after a library scan completes.

Changes:

  • Introduces gamelist.auto_export_on_scan config option (default false) with parsing + validation.
  • Hooks scan completion to optionally trigger local gamelist.xml export per platform.
  • Updates GamelistExporter APIs to accept request=None for local exports.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
backend/config/config_manager.py Adds new config field, parsing, validation, and persistence into config.yml.
backend/endpoints/sockets/scan.py Triggers optional auto-export at end of scan when config is enabled.
backend/utils/gamelist_exporter.py Allows request to be optional to support local export flows.
Comments suppressed due to low confidence (2)

backend/utils/gamelist_exporter.py:176

  • Request validation for non-local exports is only enforced inside _create_game_element(). If a platform has zero ROMs (or all ROMs are filtered out), _create_game_element() is never called, so export_platform_to_xml() / export_platform_to_file() can succeed even when local_export=False and request=None. Add an upfront guard in export_platform_to_xml() (and/or export_platform_to_file()) to raise when request is missing for non-local exports, regardless of ROM count.
    def export_platform_to_xml(self, platform_id: int, request: Request | None) -> str:
        """Export a platform's ROMs to gamelist.xml format

        Args:
            platform_id: Platform ID to export

        Returns:
            XML string in gamelist.xml format
        """
        platform = db_platform_handler.get_platform(platform_id)
        if not platform:
            raise ValueError(f"Platform with ID {platform_id} not found")

        roms = db_rom_handler.get_roms_scalar(platform_ids=[platform_id])

backend/utils/gamelist_exporter.py:205

  • The docstrings don’t reflect that request is now optional: export_platform_to_xml() doesn’t document the request argument at all, and export_platform_to_file() still implies it’s required. Update the docstrings to clarify when request may be None (local exports) and when it’s mandatory (non-local exports).
    def export_platform_to_xml(self, platform_id: int, request: Request | None) -> str:
        """Export a platform's ROMs to gamelist.xml format

        Args:
            platform_id: Platform ID to export

        Returns:
            XML string in gamelist.xml format
        """
        platform = db_platform_handler.get_platform(platform_id)
        if not platform:
            raise ValueError(f"Platform with ID {platform_id} not found")

        roms = db_rom_handler.get_roms_scalar(platform_ids=[platform_id])

        # Create root element
        root = Element("gameList")

        for rom in roms:
            if rom and not rom.missing_from_fs and rom.fs_name != "gamelist.xml":
                game_element = self._create_game_element(rom, request=request)
                root.append(game_element)

        # Convert to XML string
        indent(root, space="  ", level=0)
        xml_str = tostring(root, encoding="unicode", xml_declaration=True)

        log.info(f"Exported {len(roms)} ROMs for platform {platform.name}")
        return xml_str

    async def export_platform_to_file(
        self,
        platform_id: int,
        request: Request | None,
    ) -> bool:
        """Export platform ROMs to gamelist.xml file in the platform's directory

        Args:
            platform_id: Platform ID to export
            request: FastAPI request object for URL generation

        Returns:
            True if successful, False otherwise
        """

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ItzCobaltboy and others added 5 commits February 4, 2026 12:15
Pulls database call out of the loop

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (3)

backend/utils/gamelist_exporter.py:166

  • This module currently contains syntactically invalid f-strings in the rom.ss_metadata block (e.g., rom.ss_metadata["box3d_path"] embedded inside a double-quoted f-string). As written, it will raise a SyntaxError at import time, which would break the /gamelist/export endpoint and the new scan auto-export path. Please fix the quoting/formatting of those f-strings so the file parses correctly.
    def export_platform_to_xml(self, platform_id: int, request: Request | None) -> str:
        """Export a platform's ROMs to gamelist.xml format

        Args:
            platform_id: Platform ID to export

backend/utils/gamelist_exporter.py:205

  • export_platform_to_file's docstring still describes request as required, but the signature now allows None for local exports. Update the docstring to reflect that request is optional only when local_export=True, and ideally raise a clear error (or return False with a specific log) if request is missing for non-local exports.
    async def export_platform_to_file(
        self,
        platform_id: int,
        request: Request | None,
    ) -> bool:
        """Export platform ROMs to gamelist.xml file in the platform's directory

        Args:
            platform_id: Platform ID to export
            request: FastAPI request object for URL generation

        Returns:
            True if successful, False otherwise
        """

backend/utils/gamelist_exporter.py:170

  • export_platform_to_xml now accepts an optional request, but the docstring Args: section does not document the request parameter or when it is required (non-local export) vs optional (local export). Please update the docstring so callers know the contract.
    def export_platform_to_xml(self, platform_id: int, request: Request | None) -> str:
        """Export a platform's ROMs to gamelist.xml format

        Args:
            platform_id: Platform ID to export

        Returns:
            XML string in gamelist.xml format
        """

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gantoine gantoine self-requested a review February 4, 2026 14:43
@ItzCobaltboy ItzCobaltboy requested a review from gantoine February 5, 2026 08:37
@gantoine
Copy link
Member

gantoine commented Feb 5, 2026

@ItzCobaltboy can you ping me when you've addressed he copilot comments? resolve any you don't want/don't think need to be changes.

@ItzCobaltboy
Copy link
Contributor Author

ItzCobaltboy commented Feb 5, 2026

@gantoine
I am done on my part

Edit: I pushed a commit with files formatted, there should be no workflow issues now

@gantoine gantoine merged commit 2d252f2 into rommapp:master Feb 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants