Skip to content
Closed
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
36 changes: 25 additions & 11 deletions gateway/platforms/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
from pathlib import Path
from typing import Any, Dict, Optional, Set

try:
import fresholm.import_hook # noqa: F401 — intercepts ``import olm`` for mautrix E2EE
except ImportError:
pass

try:
from mautrix.types import (
ContentURI,
Expand Down Expand Up @@ -138,8 +143,7 @@ def __init__(self, session_key: str, chat_id: str, message_id: str, resolved: bo
)

_E2EE_INSTALL_HINT = (
"Install with: pip install 'mautrix[encryption]' asyncpg aiosqlite "
"(requires libolm C library)"
"Install with: pip install 'mautrix>=0.20' fresholm unpaddedbase64 pycryptodome base58 asyncpg aiosqlite"
)

_MATRIX_IMAGE_FILENAME_EXTS = frozenset({
Expand Down Expand Up @@ -217,24 +221,34 @@ def _create_matrix_session(proxy_url: str | None):
def _check_e2ee_deps() -> bool:
"""Return True if mautrix E2EE dependencies are available.

Verifies python-olm (via mautrix.crypto.OlmMachine), the SQLite crypto
store backend (mautrix.crypto.store.asyncpg.PgCryptoStore — yes, the
PgCryptoStore class also drives the sqlite backend in mautrix 0.21),
and the database drivers actually used at connect time (``asyncpg`` for
the underlying upgrade_table machinery, ``aiosqlite`` for the
``sqlite:///`` URL we pass to ``Database.create``). Without all four,
encrypted rooms fail at connect time with a confusing
``No module named 'asyncpg'`` (#31116).
Checks for fresholm (Rust/vodozemac, preferred) or python-olm (legacy),
plus the non-olm encryption deps that ``mautrix[encryption]`` would install
(unpaddedbase64, pycryptodome, base58). Without these,
``mautrix.crypto.signature`` blows up at import time with
``ModuleNotFoundError: No module named 'unpaddedbase64'``.

Also verifies the SQLite crypto store backend and database drivers.
"""
try:
import unpaddedbase64 # noqa: F401
import Crypto # pycryptodome # noqa: F401
import base58 # noqa: F401
from mautrix.crypto import OlmMachine # noqa: F401
from mautrix.crypto.store.asyncpg import PgCryptoStore # noqa: F401
import asyncpg # noqa: F401
import aiosqlite # noqa: F401

return True
except (ImportError, AttributeError):
return False
# Fresholm import hook may not have run yet (e.g. early startup).
# Try activating it explicitly and retrying.
try:
import fresholm.import_hook # noqa: F401
from mautrix.crypto import OlmMachine # noqa: F401

return True
except (ImportError, AttributeError):
return False


def check_matrix_requirements() -> bool:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ dev = ["debugpy==1.8.20", "pytest==9.0.2", "pytest-asyncio==1.3.0", "pytest-time
messaging = ["python-telegram-bot[webhooks]==22.6", "discord.py[voice]==2.7.1", "aiohttp==3.13.3", "brotlicffi==1.2.0.1", "slack-bolt==1.27.0", "slack-sdk==3.40.1", "qrcode==7.4.2"]
cron = [] # croniter is now a core dependency; this extra kept for back-compat
slack = ["slack-bolt==1.27.0", "slack-sdk==3.40.1", "aiohttp==3.13.3"]
matrix = ["mautrix[encryption]==0.21.0", "Markdown==3.10.2", "aiosqlite==0.22.1", "asyncpg==0.31.0", "aiohttp-socks==0.11.0"]
matrix = ["mautrix>=0.20,<1", "fresholm>=0.2.4", "unpaddedbase64>=1.0.0", "pycryptodome>=3.0", "base58>=2.0.0", "Markdown==3.10.2", "aiosqlite==0.22.1", "asyncpg==0.31.0", "aiohttp-socks==0.11.0"]
# WeCom callback-mode adapter — parses untrusted XML POST bodies from
# WeCom-controlled callback endpoints, so we use defusedxml (drop-in
# replacement for stdlib xml.etree.ElementTree) to block billion-laughs
Expand Down