game_characters

Per-user character persistence for S.N.E.S. game sessions.

Characters are stored per-user (not per-game) and automatically loaded into every game session. The last created character is the default. Character images are persisted to the filesystem at /home/star/large_files/assets/ for permanence.

# 🎭💀 POSSESSED AVATAR REGISTRY

async game_characters.create_character(user_id, name, description, redis, image_data=None, image_url=None)[source]

Create a new character for a user.

Images are saved to the web-accessible game assets directory so img2img can reference them via public URL.

Return type:

dict[str, Any]

Parameters:
  • user_id (str)

  • name (str)

  • description (str)

  • redis (Any)

  • image_data (bytes | None)

  • image_url (str | None)

async game_characters.list_characters(user_id, redis)[source]

List a user’s saved characters, most-recently-used first.

Reads the per-user Redis hash game:characters:<user_id> (field = char_id, value = JSON), decodes every entry (handling both str and bytes from the client), stamps each dict with its char_id, and returns them sorted by the last_used timestamp descending so the active/default character sorts first. Read-only; any decode or connection error is logged and reported as an empty list.

Called by get_active_character() as a fallback (most-recent character) and by game_ui/components.py to render the character roster.

Parameters:
  • user_id (str) – Owner whose character hash to read.

  • redis (Any) – Async Redis client.

Returns:

Character dicts newest-used first, or an empty list when none exist or on error.

Return type:

list[dict[str, Any]]

async game_characters.get_character(user_id, char_id, redis)[source]

Fetch one of a user’s characters by its identifier.

Reads a single field from the per-user Redis hash game:characters:<user_id> keyed by char_id and JSON-decodes it (handling both str and bytes values). Returns None if the field is missing. Read-only; any decode/connection error is logged and surfaced as None.

Called by get_active_character() to resolve the stored active id; no external callers were found via grep.

Parameters:
  • user_id (str) – Owner of the character hash.

  • char_id (str) – Identifier of the character to fetch.

  • redis (Any) – Async Redis client.

Returns:

The decoded character dict, or None if absent or on error.

Return type:

dict[str, Any] | None

async game_characters.get_active_character(user_id, redis)[source]

Resolve a user’s active character, falling back to most-recent.

Reads the active-pointer string game:active_char:<user_id> from Redis; if it is set, resolves the character via get_character(). If no active pointer exists, it falls back to the most-recently-used character returned by list_characters() so a user who never explicitly chose one still gets a sensible default. Read-only; any error is logged and surfaced as None.

This is the most widely used accessor in the module: it is invoked across the message pipeline and platforms – e.g. message_processor/context_injections.py, message_processor/processor.py, message_processor/generate_and_send.py, platforms/discord.py, background_agents/game_art_agent.py, tools/game_controls.py, and openrouter_client/executor.py – to inject the player’s character into prompts and image generation.

Parameters:
  • user_id (str) – Owner whose active character to resolve.

  • redis (Any) – Async Redis client.

Returns:

The active (or most-recent) character dict, or None if the user has none or on error.

Return type:

dict[str, Any] | None

async game_characters.set_active_character(user_id, char_id, redis)[source]

Mark a character active for a user and refresh its last-used time.

Writes the char_id into the active-pointer string game:active_char:<user_id>, then reads that character back from the per-user hash game:characters:<user_id>, updates its last_used timestamp, and persists the modified JSON. Keeping last_used current also influences the most-recent fallback in get_active_character() and the ordering in list_characters(). Errors are logged and swallowed (best-effort write).

Called by create_character() (to auto-activate a freshly created character) and by the UI/platform layers game_ui/modals/lobby.py and platforms/discord.py when a user selects a character.

Parameters:
  • user_id (str) – Owner of the character.

  • char_id (str) – Identifier of the character to make active.

  • redis (Any) – Async Redis client.

Return type:

None

Returns:

None.

async game_characters.delete_character(user_id, char_id, redis)[source]

Delete a user’s character, its image file, and any active pointer.

Reads the character from the per-user hash game:characters:<user_id> to find its persisted image_path and best-effort removes that file from disk, then deletes the character field from the hash with HDEL. If the deleted character was the one recorded in the active-pointer string game:active_char:<user_id>, that pointer is cleared so no dangling active id remains. Touches both Redis and the filesystem; errors are logged and treated as a failed delete.

No external callers were found via grep; this is the public teardown counterpart to create_character().

Parameters:
  • user_id (str) – Owner of the character.

  • char_id (str) – Identifier of the character to delete.

  • redis (Any) – Async Redis client.

Returns:

True if a character field was removed, False if it was absent or on error.

Return type:

bool

async game_characters.get_character_image_data(char)[source]

Read a character’s persisted image bytes from disk, if present.

Pulls the image_path recorded on the character dict (written by create_character() when an image was supplied) and, if that path exists, reads and returns the raw file bytes – e.g. for re-use as an img2img reference. Returns None when the character has no stored image or the file is missing, and logs and swallows any read error. Touches the filesystem only (no Redis).

No callers were found via grep; intended for consumers needing the original image bytes rather than the public URL stored on the character.

Parameters:

char (dict[str, Any]) – A character dict, typically from get_active_character() or get_character(), expected to carry an image_path key.

Returns:

The image file contents, or None if absent/unreadable.

Return type:

bytes | None