80 lines
2.1 KiB
Python
80 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Matrix Helper Utilities
|
|
|
|
Shared utilities for Matrix client operations, reducing code duplication
|
|
across matrix_mcp.py and matrix_integration.py.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
from pathlib import Path
|
|
from typing import AsyncIterator
|
|
|
|
try:
|
|
from nio import AsyncClient
|
|
except ImportError:
|
|
raise ImportError(
|
|
"matrix-nio not installed. Install with: pip3 install matrix-nio\n"
|
|
"Note: Without [e2e] extra, only unencrypted rooms are supported"
|
|
)
|
|
|
|
# Configuration
|
|
CREDENTIALS_FILE = Path.home() / ".matrix-credentials.json"
|
|
MATRIX_DATA_DIR = Path.home() / ".matrix-data"
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def load_credentials() -> dict:
|
|
"""Load Matrix credentials from JSON file"""
|
|
if not CREDENTIALS_FILE.exists():
|
|
raise FileNotFoundError(
|
|
f"Credentials file not found: {CREDENTIALS_FILE}\n"
|
|
f"Run setup_matrix.sh to create credentials"
|
|
)
|
|
|
|
try:
|
|
with open(CREDENTIALS_FILE, 'r') as f:
|
|
return json.load(f)
|
|
except Exception as e:
|
|
logger.error(f"Failed to load credentials: {e}")
|
|
raise
|
|
|
|
|
|
@asynccontextmanager
|
|
async def matrix_client() -> AsyncIterator[AsyncClient]:
|
|
"""
|
|
Async context manager for Matrix client operations.
|
|
|
|
Handles client setup, session restoration, and cleanup automatically.
|
|
Ensures client.close() is always called, preventing resource leaks.
|
|
|
|
Usage:
|
|
async with matrix_client() as client:
|
|
response = await client.room_send(...)
|
|
|
|
Yields:
|
|
AsyncClient: Configured and authenticated Matrix client
|
|
"""
|
|
creds = load_credentials()
|
|
|
|
# Create data directory for E2EE store
|
|
MATRIX_DATA_DIR.mkdir(exist_ok=True)
|
|
|
|
client = AsyncClient(
|
|
homeserver=creds['homeserver'],
|
|
user=creds['user_id'],
|
|
store_path=str(MATRIX_DATA_DIR),
|
|
)
|
|
|
|
# Restore session from credentials
|
|
client.access_token = creds['access_token']
|
|
client.device_id = creds['device_id']
|
|
|
|
try:
|
|
yield client
|
|
finally:
|
|
await client.close()
|