Merge branch '4-handle-roomsenderror-response-event-after-sending-a-message-to-matrix' into 'master'
Resolve "Handle RoomSendError response event after sending a message to Matrix" Closes #4 See merge request Neutrinet/matrix-alertbot!4
This commit is contained in:
commit
21c568312b
3 changed files with 115 additions and 30 deletions
|
@ -1,7 +1,14 @@
|
|||
import logging
|
||||
from typing import Dict, Optional, TypedDict, Union
|
||||
|
||||
from nio import AsyncClient, ErrorResponse, Response, RoomSendResponse
|
||||
from nio import (
|
||||
AsyncClient,
|
||||
ErrorResponse,
|
||||
Response,
|
||||
RoomSendError,
|
||||
RoomSendResponse,
|
||||
SendRetryError,
|
||||
)
|
||||
from typing_extensions import NotRequired
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -62,32 +69,16 @@ async def send_text_to_room(
|
|||
if reply_to_event_id:
|
||||
content["m.relates_to"] = {"m.in_reply_to": {"event_id": reply_to_event_id}}
|
||||
|
||||
return await matrix_client.room_send(
|
||||
response_event = await matrix_client.room_send(
|
||||
room_id,
|
||||
"m.room.message",
|
||||
content,
|
||||
ignore_unverified_devices=True,
|
||||
)
|
||||
|
||||
|
||||
def make_pill(user_id: str, displayname: str = None) -> str:
|
||||
"""Convert a user ID (and optionally a display name) to a formatted user 'pill'
|
||||
|
||||
Args:
|
||||
user_id: The MXID of the user.
|
||||
|
||||
displayname: An optional displayname. Clients like Element will figure out the
|
||||
correct display name no matter what, but other clients may not. If not
|
||||
provided, the MXID will be used instead.
|
||||
|
||||
Returns:
|
||||
The formatted user pill.
|
||||
"""
|
||||
if not displayname:
|
||||
# Use the user ID as the displayname if not provided
|
||||
displayname = user_id
|
||||
|
||||
return f'<a href="https://matrix.to/#/{user_id}">{displayname}</a>'
|
||||
if isinstance(response_event, RoomSendError):
|
||||
raise SendRetryError(response_event.error)
|
||||
return response_event
|
||||
|
||||
|
||||
async def react_to_event(
|
||||
|
@ -121,13 +112,17 @@ async def react_to_event(
|
|||
}
|
||||
}
|
||||
|
||||
return await client.room_send(
|
||||
response_event = await client.room_send(
|
||||
room_id,
|
||||
"m.reaction",
|
||||
content,
|
||||
ignore_unverified_devices=True,
|
||||
)
|
||||
|
||||
if isinstance(response_event, RoomSendError):
|
||||
raise SendRetryError(response_event.error)
|
||||
return response_event
|
||||
|
||||
|
||||
def strip_fallback(content: str) -> str:
|
||||
index = 0
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
# This file holds custom error types that you can define for your application.
|
||||
|
||||
|
||||
class ConfigError(Exception):
|
||||
class MatrixAlertbotError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigError(MatrixAlertbotError):
|
||||
"""An error encountered during reading the config file."""
|
||||
|
||||
pass
|
||||
|
@ -25,7 +29,7 @@ class RequiredConfigKeyError(ConfigError):
|
|||
pass
|
||||
|
||||
|
||||
class AlertmanagerError(Exception):
|
||||
class AlertmanagerError(MatrixAlertbotError):
|
||||
"""An error encountered with Alertmanager."""
|
||||
|
||||
pass
|
||||
|
|
|
@ -4,7 +4,11 @@ from unittest.mock import Mock
|
|||
|
||||
import nio
|
||||
|
||||
from matrix_alertbot.chat_functions import send_text_to_room, strip_fallback
|
||||
from matrix_alertbot.chat_functions import (
|
||||
react_to_event,
|
||||
send_text_to_room,
|
||||
strip_fallback,
|
||||
)
|
||||
|
||||
from tests.utils import make_awaitable
|
||||
|
||||
|
@ -32,6 +36,59 @@ class ChatFunctionsTestCase(unittest.IsolatedAsyncioTestCase):
|
|||
message = strip_fallback(fake_body)
|
||||
self.assertEqual(fake_body, message)
|
||||
|
||||
async def test_react_to_event(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendResponse)
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send = Mock(return_value=make_awaitable(fake_response))
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_event_id = "some event id"
|
||||
fake_reaction_text = "some reaction"
|
||||
|
||||
response = await react_to_event(
|
||||
fake_matrix_client, fake_room_id, fake_event_id, fake_reaction_text
|
||||
)
|
||||
|
||||
fake_matrix_client.room_send.assert_called_once_with(
|
||||
fake_room_id,
|
||||
"m.reaction",
|
||||
{
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.annotation",
|
||||
"event_id": fake_event_id,
|
||||
"key": fake_reaction_text,
|
||||
}
|
||||
},
|
||||
ignore_unverified_devices=True,
|
||||
)
|
||||
self.assertEqual(fake_response, response)
|
||||
|
||||
async def test_react_to_event_return_room_send_error(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendError)
|
||||
fake_response.error = "some error"
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send.return_value = make_awaitable(fake_response)
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_event_id = "some event id"
|
||||
fake_reaction_text = "some reaction"
|
||||
|
||||
with self.assertRaises(nio.SendRetryError):
|
||||
await react_to_event(
|
||||
fake_matrix_client, fake_room_id, fake_event_id, fake_reaction_text
|
||||
)
|
||||
|
||||
fake_matrix_client.room_send.assert_called_once_with(
|
||||
fake_room_id,
|
||||
"m.reaction",
|
||||
{
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.annotation",
|
||||
"event_id": fake_event_id,
|
||||
"key": fake_reaction_text,
|
||||
}
|
||||
},
|
||||
ignore_unverified_devices=True,
|
||||
)
|
||||
|
||||
async def test_send_text_to_room_as_notice(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendResponse)
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
|
@ -60,7 +117,7 @@ class ChatFunctionsTestCase(unittest.IsolatedAsyncioTestCase):
|
|||
async def test_send_text_to_room_as_message(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendResponse)
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send = Mock(return_value=make_awaitable(fake_response))
|
||||
fake_matrix_client.room_send.return_value = make_awaitable(fake_response)
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_plaintext_body = "some plaintext message"
|
||||
fake_html_body = "some html message"
|
||||
|
@ -89,7 +146,7 @@ class ChatFunctionsTestCase(unittest.IsolatedAsyncioTestCase):
|
|||
async def test_send_text_to_room_in_reply_to_event(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendResponse)
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send = Mock(return_value=make_awaitable(fake_response))
|
||||
fake_matrix_client.room_send.return_value = make_awaitable(fake_response)
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_plaintext_body = "some plaintext message"
|
||||
fake_html_body = "some html message"
|
||||
|
@ -119,9 +176,8 @@ class ChatFunctionsTestCase(unittest.IsolatedAsyncioTestCase):
|
|||
|
||||
async def test_send_text_to_room_raise_send_retry_error(self) -> None:
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send = Mock(
|
||||
side_effect=send_room_raise_send_retry_error
|
||||
)
|
||||
fake_matrix_client.room_send.side_effect = send_room_raise_send_retry_error
|
||||
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_plaintext_body = "some plaintext message"
|
||||
fake_html_body = "some html message"
|
||||
|
@ -133,6 +189,36 @@ class ChatFunctionsTestCase(unittest.IsolatedAsyncioTestCase):
|
|||
fake_plaintext_body,
|
||||
fake_html_body,
|
||||
)
|
||||
|
||||
fake_matrix_client.room_send.assert_called_once_with(
|
||||
fake_room_id,
|
||||
"m.room.message",
|
||||
{
|
||||
"msgtype": "m.notice",
|
||||
"format": "org.matrix.custom.html",
|
||||
"body": fake_plaintext_body,
|
||||
"formatted_body": fake_html_body,
|
||||
},
|
||||
ignore_unverified_devices=True,
|
||||
)
|
||||
|
||||
async def test_send_text_to_room_return_room_send_error(self) -> None:
|
||||
fake_response = Mock(spec=nio.RoomSendError)
|
||||
fake_response.error = "some error"
|
||||
fake_matrix_client = Mock(spec=nio.AsyncClient)
|
||||
fake_matrix_client.room_send.return_value = make_awaitable(fake_response)
|
||||
fake_room_id = "!abcdefgh:example.com"
|
||||
fake_plaintext_body = "some plaintext message"
|
||||
fake_html_body = "some html message"
|
||||
|
||||
with self.assertRaises(nio.SendRetryError):
|
||||
await send_text_to_room(
|
||||
fake_matrix_client,
|
||||
fake_room_id,
|
||||
fake_plaintext_body,
|
||||
fake_html_body,
|
||||
)
|
||||
|
||||
fake_matrix_client.room_send.assert_called_once_with(
|
||||
fake_room_id,
|
||||
"m.room.message",
|
||||
|
|
Loading…
Reference in a new issue