Add Matrix bot Phase 1: core setup + fun commands
Modular bot using matrix-nio[e2e] with E2EE support, deployed as systemd service on Synapse LXC. Includes 10 commands: help, ping, 8ball, fortune, flip, roll, random, rps, poll, champion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
60
callbacks.py
Normal file
60
callbacks.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import logging
|
||||
from functools import wraps
|
||||
|
||||
from nio import AsyncClient, RoomMessageText
|
||||
|
||||
from config import BOT_PREFIX, MATRIX_USER_ID
|
||||
from commands import COMMANDS
|
||||
|
||||
logger = logging.getLogger("matrixbot")
|
||||
|
||||
|
||||
def handle_command_errors(func):
|
||||
@wraps(func)
|
||||
async def wrapper(client, room_id, sender, args):
|
||||
try:
|
||||
return await func(client, room_id, sender, args)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in command {func.__name__}: {e}", exc_info=True)
|
||||
try:
|
||||
from utils import send_text
|
||||
await send_text(client, room_id, "An unexpected error occurred. Please try again later.")
|
||||
except Exception as e2:
|
||||
logger.error(f"Failed to send error message: {e2}", exc_info=True)
|
||||
return wrapper
|
||||
|
||||
|
||||
class Callbacks:
|
||||
def __init__(self, client: AsyncClient):
|
||||
self.client = client
|
||||
# Track the sync token so we ignore old messages on startup
|
||||
self.startup_sync_token = None
|
||||
|
||||
async def message(self, room, event):
|
||||
# Ignore messages from before the bot started
|
||||
if self.startup_sync_token is None:
|
||||
return
|
||||
|
||||
# Ignore our own messages
|
||||
if event.sender == MATRIX_USER_ID:
|
||||
return
|
||||
|
||||
body = event.body.strip() if event.body else ""
|
||||
if not body.startswith(BOT_PREFIX):
|
||||
return
|
||||
|
||||
# Parse command and args
|
||||
without_prefix = body[len(BOT_PREFIX):]
|
||||
parts = without_prefix.split(None, 1)
|
||||
cmd_name = parts[0].lower() if parts else ""
|
||||
args = parts[1] if len(parts) > 1 else ""
|
||||
|
||||
logger.info(f"Command '{cmd_name}' from {event.sender} in {room.room_id}")
|
||||
|
||||
handler_entry = COMMANDS.get(cmd_name)
|
||||
if handler_entry is None:
|
||||
return
|
||||
|
||||
handler, _ = handler_entry
|
||||
wrapped = handle_command_errors(handler)
|
||||
await wrapped(self.client, room.room_id, event.sender, args)
|
||||
Reference in New Issue
Block a user