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
2 changes: 2 additions & 0 deletions gateway/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,8 @@ def _apply_env_overrides(config: GatewayConfig) -> None:
config.platforms[Platform.MATRIX].extra["password"] = matrix_password
matrix_e2ee = os.getenv("MATRIX_ENCRYPTION", "").lower() in ("true", "1", "yes")
config.platforms[Platform.MATRIX].extra["encryption"] = matrix_e2ee
config.platforms[Platform.MATRIX].extra["device_id"] = os.getenv("MATRIX_DEVICE_ID", "")
config.platforms[Platform.MATRIX].extra["allowed_users"] = os.getenv("MATRIX_ALLOWED_USERS", "")
matrix_home = os.getenv("MATRIX_HOME_ROOM")
if matrix_home:
config.platforms[Platform.MATRIX].home_channel = HomeChannel(
Expand Down
51 changes: 48 additions & 3 deletions gateway/platforms/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ def __init__(self, config: PlatformConfig):
"encryption",
os.getenv("MATRIX_ENCRYPTION", "").lower() in ("true", "1", "yes"),
)
self._device_id: str = (
config.extra.get("device_id", "")
or os.getenv("MATRIX_DEVICE_ID", "")
)
allowed_users_str = config.extra.get("allowed_users", "") or os.getenv("MATRIX_ALLOWED_USERS", "")
self._allowed_users: list[str] = [u.strip() for u in allowed_users_str.split(",") if u.strip()]

self._client: Any = None # nio.AsyncClient
self._sync_task: Optional[asyncio.Task] = None
Expand Down Expand Up @@ -142,6 +148,7 @@ async def connect(self) -> bool:
client = nio.AsyncClient(
self._homeserver,
self._user_id or "",
device_id=self._device_id or None,
store_path=store_path,
)
logger.info("Matrix: E2EE enabled (store: %s)", store_path)
Expand All @@ -152,10 +159,10 @@ async def connect(self) -> bool:
"pip install 'matrix-nio[e2e]'",
exc,
)
client = nio.AsyncClient(self._homeserver, self._user_id or "")
client = nio.AsyncClient(self._homeserver, self._user_id or "", device_id=self._device_id or None)
else:
client = nio.AsyncClient(self._homeserver, self._user_id or "")

client = nio.AsyncClient(self._homeserver, self._user_id or "", device_id=self._device_id or None)
self._client = client

# Authenticate.
Expand All @@ -181,6 +188,7 @@ async def connect(self) -> bool:
resp = await client.login(
self._password,
device_name="Hermes Agent",
device_id=self._device_id or None,
)
if isinstance(resp, nio.LoginResponse):
logger.info("Matrix: logged in as %s", self._user_id)
Expand Down Expand Up @@ -215,6 +223,11 @@ async def connect(self) -> bool:
client.add_event_callback(
self._on_room_message, nio.MegolmEvent
)
client.add_to_device_callback(
self._on_key_verification,
(nio.KeyVerificationStart, nio.KeyVerificationCancel,
nio.KeyVerificationKey, nio.KeyVerificationMac)
)

# Initial sync to catch up, then start background sync.
self._startup_ts = time.time()
Expand Down Expand Up @@ -802,6 +815,38 @@ async def _on_invite(self, room: Any, event: Any) -> None:
except Exception as exc:
logger.warning("Matrix: error joining %s: %s", room.room_id, exc)

async def _on_key_verification(self, event: Any) -> None:
"""Auto-accept device verification from allowed users."""
import nio

if not self._client:
return

# Sadece izin verilen kullanicilarin cihazlarini dogrula
if self._allowed_users and event.sender not in self._allowed_users and "*" not in self._allowed_users:
logger.warning("Matrix: ignoring verification from unauthorized user %s", event.sender)
return

if isinstance(event, nio.KeyVerificationStart):
logger.info("Matrix: auto-accepting verification from %s", event.sender)
try:
await self._client.accept_key_verification(event.transaction_id)
except Exception as e:
logger.error("Matrix: failed to accept verification: %s", e)

elif isinstance(event, nio.KeyVerificationCancel):
logger.warning("Matrix: verification cancelled by %s", event.sender)

elif isinstance(event, nio.KeyVerificationKey):
logger.info("Matrix: received verification key from %s, confirming...", event.sender)
try:
await self._client.confirm_short_auth_string(event.transaction_id)
except Exception as e:
logger.error("Matrix: failed to confirm SAS: %s", e)

elif isinstance(event, nio.KeyVerificationMac):
logger.info("Matrix: verification MAC received from %s", event.sender)

# ------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------
Expand Down
Loading