matrix-alertbot/matrix_alertbot/chat_functions.py

136 lines
3.4 KiB
Python
Raw Normal View History

2019-09-25 14:26:29 +02:00
import logging
2022-07-09 15:25:16 +02:00
from typing import Dict, Optional, TypedDict, Union
2020-08-10 00:02:07 +02:00
from nio import (
AsyncClient,
ErrorResponse,
Response,
RoomSendError,
RoomSendResponse,
SendRetryError,
)
2022-07-09 15:25:16 +02:00
from typing_extensions import NotRequired
2019-09-25 14:26:29 +02:00
logger = logging.getLogger(__name__)
2022-07-09 15:25:16 +02:00
ContentEventDict = TypedDict(
"ContentEventDict",
{
"msgtype": str,
"format": str,
"body": str,
"formatted_body": NotRequired[str],
"m.relates_to": NotRequired[Dict],
},
)
2019-10-04 15:46:51 +02:00
async def send_text_to_room(
2022-08-08 12:38:09 +02:00
matrix_client: AsyncClient,
room_id: str,
plaintext: str,
html: str = None,
notice: bool = True,
reply_to_event_id: Optional[str] = None,
) -> RoomSendResponse:
"""Send text to a matrix room.
2019-09-25 14:26:29 +02:00
Args:
client: The client to communicate to matrix with.
2019-09-25 14:26:29 +02:00
room_id: The ID of the room to send the message to.
2019-09-25 14:26:29 +02:00
plaintext: The message content.
html: The message content in HTML format.
2019-09-25 14:26:29 +02:00
notice: Whether the message should be sent with an "m.notice" message type
(will not ping users).
2019-10-04 15:46:51 +02:00
reply_to_event_id: Whether this message is a reply to another event. The event
ID this is message is a reply to.
2021-01-10 04:30:07 +01:00
Returns:
A RoomSendResponse if the request was successful, else an ErrorResponse.
2019-09-25 14:26:29 +02:00
"""
2019-10-04 15:46:51 +02:00
# Determine whether to ping room members or not
msgtype = "m.notice" if notice else "m.text"
2022-07-09 15:25:16 +02:00
content: ContentEventDict = {
2019-10-04 15:46:51 +02:00
"msgtype": msgtype,
"format": "org.matrix.custom.html",
"body": plaintext,
2019-10-04 15:46:51 +02:00
}
if html is not None:
content["formatted_body"] = html
2019-09-25 14:26:29 +02:00
if reply_to_event_id:
content["m.relates_to"] = {"m.in_reply_to": {"event_id": reply_to_event_id}}
response_event = await matrix_client.room_send(
2022-08-08 12:38:09 +02:00
room_id,
"m.room.message",
content,
ignore_unverified_devices=True,
)
if isinstance(response_event, RoomSendError):
raise SendRetryError(f"{response_event.status_code} - {response_event.message}")
return response_event
async def react_to_event(
client: AsyncClient,
room_id: str,
event_id: str,
reaction_text: str,
) -> Union[Response, ErrorResponse]:
"""Reacts to a given event in a room with the given reaction text
Args:
client: The client to communicate to matrix with.
room_id: The ID of the room to send the message to.
event_id: The ID of the event to react to.
reaction_text: The string to react with. Can also be (one or more) emoji characters.
Returns:
A nio.Response or nio.ErrorResponse if an error occurred.
Raises:
SendRetryError: If the reaction was unable to be sent.
"""
content = {
"m.relates_to": {
"rel_type": "m.annotation",
"event_id": event_id,
"key": reaction_text,
}
}
response_event = await client.room_send(
room_id,
"m.reaction",
content,
ignore_unverified_devices=True,
)
2021-01-10 03:58:39 +01:00
if isinstance(response_event, RoomSendError):
raise SendRetryError(f"{response_event.status_code} - {response_event.message}")
return response_event
2021-01-10 03:58:39 +01:00
def strip_fallback(content: str) -> str:
index = 0
for line in content.splitlines(keepends=True):
if not line.startswith("> "):
break
if index == 0:
index += 1
index += len(line)
return content[index:]