feat(matrix): show typing while processing messages
This commit is contained in:
@@ -11,6 +11,7 @@ from nio import (
|
|||||||
MatrixRoom,
|
MatrixRoom,
|
||||||
RoomMessageText,
|
RoomMessageText,
|
||||||
RoomSendError,
|
RoomSendError,
|
||||||
|
RoomTypingError,
|
||||||
SyncError,
|
SyncError,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ from nanobot.channels.base import BaseChannel
|
|||||||
from nanobot.config.loader import get_data_dir
|
from nanobot.config.loader import get_data_dir
|
||||||
|
|
||||||
LOGGING_STACK_BASE_DEPTH = 2
|
LOGGING_STACK_BASE_DEPTH = 2
|
||||||
|
TYPING_NOTICE_TIMEOUT_MS = 30_000
|
||||||
|
|
||||||
|
|
||||||
class _NioLoguruHandler(logging.Handler):
|
class _NioLoguruHandler(logging.Handler):
|
||||||
@@ -135,12 +137,15 @@ class MatrixChannel(BaseChannel):
|
|||||||
if not self.client:
|
if not self.client:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
await self.client.room_send(
|
await self.client.room_send(
|
||||||
room_id=msg.chat_id,
|
room_id=msg.chat_id,
|
||||||
message_type="m.room.message",
|
message_type="m.room.message",
|
||||||
content={"msgtype": "m.text", "body": msg.content},
|
content={"msgtype": "m.text", "body": msg.content},
|
||||||
ignore_unverified_devices=True,
|
ignore_unverified_devices=True,
|
||||||
)
|
)
|
||||||
|
finally:
|
||||||
|
await self._set_typing(msg.chat_id, False)
|
||||||
|
|
||||||
def _register_event_callbacks(self) -> None:
|
def _register_event_callbacks(self) -> None:
|
||||||
"""Register Matrix event callbacks used by this channel."""
|
"""Register Matrix event callbacks used by this channel."""
|
||||||
@@ -179,6 +184,28 @@ class MatrixChannel(BaseChannel):
|
|||||||
return
|
return
|
||||||
logger.warning("Matrix send warning: {}", response)
|
logger.warning("Matrix send warning: {}", response)
|
||||||
|
|
||||||
|
async def _set_typing(self, room_id: str, typing: bool) -> None:
|
||||||
|
"""Best-effort typing indicator update that never blocks message flow."""
|
||||||
|
if not self.client:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = await self.client.room_typing(
|
||||||
|
room_id=room_id,
|
||||||
|
typing_state=typing,
|
||||||
|
timeout=TYPING_NOTICE_TIMEOUT_MS,
|
||||||
|
)
|
||||||
|
if isinstance(response, RoomTypingError):
|
||||||
|
logger.debug("Matrix typing update failed for room {}: {}", room_id, response)
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(
|
||||||
|
"Matrix typing update failed for room {} (typing={}): {}: {}",
|
||||||
|
room_id,
|
||||||
|
typing,
|
||||||
|
type(e).__name__,
|
||||||
|
str(e),
|
||||||
|
)
|
||||||
|
|
||||||
async def _sync_loop(self) -> None:
|
async def _sync_loop(self) -> None:
|
||||||
while self._running:
|
while self._running:
|
||||||
try:
|
try:
|
||||||
@@ -202,9 +229,23 @@ class MatrixChannel(BaseChannel):
|
|||||||
if event.sender == self.config.user_id:
|
if event.sender == self.config.user_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not self.is_allowed(event.sender):
|
||||||
await self._handle_message(
|
await self._handle_message(
|
||||||
sender_id=event.sender,
|
sender_id=event.sender,
|
||||||
chat_id=room.room_id,
|
chat_id=room.room_id,
|
||||||
content=event.body,
|
content=event.body,
|
||||||
metadata={"room": room.display_name},
|
metadata={"room": room.display_name},
|
||||||
)
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
await self._set_typing(room.room_id, True)
|
||||||
|
try:
|
||||||
|
await self._handle_message(
|
||||||
|
sender_id=event.sender,
|
||||||
|
chat_id=room.room_id,
|
||||||
|
content=event.body,
|
||||||
|
metadata={"room": room.display_name},
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
await self._set_typing(room.room_id, False)
|
||||||
|
raise
|
||||||
|
|||||||
Reference in New Issue
Block a user