Files
Narasimha-sc 5339978553 core, ui: auto-accept group invitations per user profile
Add a per-profile "Group invitations / Auto-accept" toggle in Privacy &
Security, mirroring the existing "Contact requests from groups" setting.

The join is fully async. processGroupInvitation already had an async accept
path, used when the invitation matches a group link the user opened:
prepareAgentJoin + createMemberConnectionAsync + joinAgentConnectionAsync,
with the outcome reported later against the CFJoinConn command id. Auto-accept
takes that same path instead of going through APIJoinGroup, so it works while
the app is closed and never blocks message processing.

An auto-accepted invitation still records a CIRcvGroupInvitation item in the
chat with the inviting contact, so there is a record of who added the user to
which group.

Two details worth noting for review:

hostContact is reported to clients only for group links. Clients respond to it
by replacing the transient host connection view with the group and removing
that chat - correct for a group link, where the contact is a placeholder, but
wrong for a plain invitation, where it is a real contact.

A resent invitation returns the existing group, because createGroupInvitation
is idempotent on inv_queue_info. The join therefore only runs while the
membership is still GSMemInvited, so a resend cannot open a second connection.
2026-08-14 20:00:34 +00:00
..

SimpleX Chat Python library

Python 3.11+ client for SimpleX Chat bots. Equivalent to the Node.js library.

Install

pip install simplex-chat

The native libsimplex is downloaded lazily on first use. To pre-fetch:

python -m simplex_chat install                     # sqlite (default)
python -m simplex_chat install --backend postgres  # linux-x86_64 only

Quick start

import re
from simplex_chat import Bot, BotProfile, Message, SqliteDb, TextMessage

bot = Bot(
    profile=BotProfile(display_name="Squaring bot"),
    db=SqliteDb(file_prefix="./squaring_bot"),
    welcome="Send me a number, I'll square it.",
)

@bot.on_message(content_type="text", text=re.compile(r"^-?\d+(\.\d+)?$"))
async def square(msg: TextMessage) -> None:
    n = float(msg.text or "0")
    await msg.reply(f"{n} * {n} = {n * n}")

@bot.on_message(content_type="text")
async def fallback(msg: Message) -> None:
    await msg.reply("Send me a number, like 7 or 3.14.")

if __name__ == "__main__":
    bot.run()

bot.run() blocks. The connection address is logged on startup — paste it into a SimpleX client to talk to the bot. Ctrl+C to stop.

Three decorators: @bot.on_message(...), @bot.on_command(name), @bot.on_event(tag). Message handlers are first-match-wins in registration order, so register specific filters first and catch-alls last.

See examples/squaring_bot.py for the full example.

Development

uv venv && source .venv/bin/activate
uv pip install -e '.[dev]'
ruff check && pyright && pytest tests/

Wire types under src/simplex_chat/types/_*.py are generated. Regenerate with cabal test simplex-chat-test --test-options='--match Python'.

Release

Manual for now. Bump _version.py:__version__, build a wheel, upload to PyPI:

uv build --wheel
uv publish --token "$PYPI_TOKEN"

License

AGPL-3.0