GOG Galaxy Integrations Python API

repository·master·Indexed 23 days ago

https://github.com/gogcom/galaxy-integrations-python-api

A Python library (v0.71) for building community integrations for GOG GALAXY 2.1. It enables developers to implement features such as game importing, achievement syncing, and chat by inheriting from the Plugin class. The API provides tools for JSON-RPC communication, data synchronization via Importer classes, and a set of enums for platforms, license types, and user presence states.

Tokens
8.8K
Snippets
14
Records
39
Agent score
80%

What's inside galaxy.plugin.api

  1. Implement a GOG GALAXY 2.1 integration plugin

    master

    To create an integration, inherit from the galaxy.api.plugin.Plugin class. The GOG GALAXY client calls specific methods on your plugin at appropriate times.

    Minimum Requirements: You must override the following two asynchronous methods:

    1. authenticate(self, stored_credentials=None): Returns an Authentication object.
    2. get_owned_games(self): Returns a list of Game objects.

    Error Handling: Methods can raise exceptions that inherit from galaxy.api.jsonrpc.ApplicationError.

    Communication: You can send notifications back to the client, for example using galaxy.api.plugin.Plugin.update_local_game_status.

    import sys
    from galaxy.api.plugin import Plugin, create_and_run_plugin
    from galaxy.api.consts import Platform
    from galaxy.api.types import Authentication, Game, LicenseInfo, LicenseType
    
    
    class PluginExample(Plugin):
        def __init__(self, reader, writer, token):
            super().__init__(
                Platform.Test,  # choose platform from available list
                "0.1",  # version
                reader,
                writer,
                token
            )
    
        # required
        async def authenticate(self, stored_credentials=None):
            return Authentication('test_user_id', 'Test User Name')
    
        # required
        async def get_owned_games(self):
            return [
                Game('test', 'The Test', None, LicenseInfo(LicenseType.SinglePurchase))
            ]
    
    
    def main():
        create_and_run_plugin(PluginExample, sys.argv)
    
    
    # run plugin event loop
    if __name__ == "__main__":
        main()
  2. Deploy a GOG GALAXY integration plugin

    master

    Integrations are delivered as Python modules and must be placed in the GOG GALAXY lookup directory. Each integration folder must contain the plugin files, a manifest.json file, and all third-party dependencies.

    Lookup Directories

    • Windows: %localappdata%\GOG.com\Galaxy\plugins\installed
    • macOS: ~/Library/Application Support/GOG.com/Galaxy/plugins/installed

    Installing Dependencies

    Since the client uses a built-in Python 3.13 interpreter, you must install third-party packages directly into your integration folder using the --target flag. Use the following command structure:

    pip install DEP --target DIR --implementation cp --python-version 313
    pip install DEP --target DIR --implementation cp --python-version 313
  3. Handle plugin lifecycle: handshake, tick, and shutdown

    master

    The Plugin lifecycle is managed through several key hooks:

    • handshake_complete(): Called immediately after the handshake with the client is finished. Use this for plugin-specific initialization. The persistent_cache is available here.
    • tick(): Called periodically. Use for non-blocking background tasks.
    • shutdown(): Called when the integration is shutting down. Use this to perform teardown logic.
    • close() / wait_closed(): Used to stop the connection and wait for all internal and external tasks to finish.
  4. How to represent local game states using LocalGameState

    master

    The LocalGameState is a Flag used to represent the current state of a game on a user's machine. Because it is a bitwise flag, you can combine states using the bitwise OR operator (|).

    For example, to represent a game that is both installed and currently running, use: local_game_state = LocalGameState.Running | LocalGameState.Installed

  5. Implement a new platform integration by inheriting from Plugin

    master
    To create a GOG GALAXY integration, you must create a class that inherits from Plugin. The base class handles the connection, task management, and feature detection. You are responsible for overriding specific methods to provide platform-specific logic for authentication, game management, and data importing.
  6. Import game data using Importers

    master

    The Plugin class uses specialized Importer objects to handle batch data imports (achievements, game times, etc.). To implement these, you should follow a pattern of preparing context and then fetching data:

    1. prepare_{feature}_context(game_ids): (Optional) Override this to perform optimizations, such as fetching a batch of data from your API to use as context for individual requests.
    2. get_{feature}(game_id, context): Override this to return the specific data for a single game using the provided context.
    3. {feature}_import_complete(): (Optional) Override this to perform cleanup or cache updates after the entire batch import finishes.
  7. Run a Plugin with create_and_run_plugin

    master

    Use create_and_run_plugin as the entry point for your integration. It handles the connection to the GOG Galaxy Client via a local port and manages the plugin lifecycle.

    Arguments:

    • plugin_class: Your custom class that inherits from Plugin.
    • argv: The command line arguments (sys.argv).

    Required CLI Arguments: The script expects at least two arguments after the script name:

    1. token: An authentication token.
    2. port: A valid port number (1-65535).

    Exit Codes:

    • 1: Missing required parameters (token, port).
    • 2: Port is not a valid integer.
    • 3: Port is out of range (1-65535).
    • 4: plugin_class is not a subclass of Plugin.
    • 5: An unhandled exception occurred during execution.
    def main():
        create_and_run_plugin(PlatformPlugin, sys.argv)
    
    if __name__ == "__main__":
        main()
  8. Debug plugin logs in GOG GALAXY

    master

    GOG GALAXY sets up a root logger that stores rotated log files. Plugin-specific logs follow the naming convention plugin-<platform>-<guid>.log.

    Log Locations:

    • Windows: %programdata%\GOG.com\Galaxy\logs
    • macOS: /Users/Shared/GOG.com/Galaxy/Logs

    Tip: When debugging communication issues between the plugin and the client, inspect GalaxyClient.log in the same directory.

  9. Configure the manifest.json for your plugin

    master

    The manifest.json is an obligatory file located in the root of your integration folder. It defines the plugin's identity and entry point.

    Required Fields:

    • guid: A custom Globally Unique Identifier.
    • version: Must match the version string provided in the Plugin constructor.
    • script: The path to the entry point module, relative to the integration folder.

    Other Fields:

    • name: Display name of the plugin.
    • platform: The platform ID (e.g., test).
    • description: A brief description.
    • author: Author name.
    • email: Author email.
    • url: Project URL.
    {
        "name": "Example plugin",
        "platform": "test",
        "guid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "version": "0.1",
        "description": "Example plugin",
        "author": "Name",
        "email": "author@email.com",
        "url": "https://github.com/user/galaxy-plugin-example",
        "script": "plugin.py"
    }
  10. Reference: Core Data Models

    master

    The following dataclasses are used to represent core entities within the GOG Galaxy integration API.

    @dataclass
    class Authentication:
        user_id: str
        user_name: str
    
    @dataclass
    class Cookie:
        name: str
        value: str
        domain: Optional[str] = None
        path: Optional[str] = None
    
    @dataclass
    class LicenseInfo:
        license_type: LicenseType
        owner: Optional[str] = None
    
    @dataclass
    class UserInfo:
        user_id: str
        user_name: str
        avatar_url: Optional[str] = None
        profile_url: Optional[str] = None
    
    @dataclass
    class GameTime:
        game_id: str
        time_played: Optional[int]
        last_played_time: Optional[int]
    
    @dataclass
    class GameLibrarySettings:
        game_id: str
        tags: Optional[List[str]]
        hidden: Optional[bool]
    
    @dataclass
    class LocalGame:
        game_id: str
        local_game_state: LocalGameState
  11. Manage Subscriptions and Subscription Games

    master

    Subscriptions allow users to access games via a service.

    Subscription fields:

    • subscription_name (str): The name/identifier of the subscription.
    • owned (Optional[bool]): Whether the user owns the subscription.
    • end_time (Optional[int]): Unix timestamp of expiration.
    • subscription_discovery (SubscriptionDiscovery): Determines how the integration handles subscription behavior. Valid values are AUTOMATIC, USER_ENABLED, or a combination of both.

    SubscriptionGame fields:

    • game_title (str): Title of the game.
    • game_id (str): ID of the game.
    • start_time (Optional[int]): Unix timestamp when the game was added to the subscription.
    • end_time (Optional[int]): Unix timestamp when the game will be removed.