This commit is contained in:
夜坂雅 2022-09-08 15:52:09 +08:00
parent 04f2372ac3
commit b28e72f383
4 changed files with 76 additions and 20 deletions

View file

@ -19,6 +19,7 @@ class Command:
room: MatrixRoom,
event: RoomMessageText,
reply_to: str,
replace_map: dict,
):
"""A command made by a user.
@ -43,6 +44,7 @@ class Command:
self.event = event
self.args = self.command.split()[1:]
self.reply_to = reply_to
self.replace_map = replace_map
async def process(self):
"""Process the command"""
@ -56,7 +58,9 @@ class Command:
await self._unknown_command()
async def _quote(self):
await send_quote_image(self.client, self.room, self.event, self.reply_to)
await send_quote_image(
self.client, self.room, self.event, self.reply_to, self.replace_map
)
async def _send_avatar(self):
await send_user_image(self.client, self.room, self.event, self.reply_to)

View file

@ -34,6 +34,7 @@ class Callbacks:
self.store = store
self.config = config
self.command_prefix = config.command_prefix
self.replace_map = {}
async def message(self, room: MatrixRoom, event: RoomMessageText) -> None:
"""Callback for when a message event is received
@ -43,6 +44,20 @@ class Callbacks:
event: The event defining the message.
"""
# Ignore too old messages
current_time = int(time.time() * 1000)
if current_time - event.server_timestamp > 60000:
return
# Check if we should replace things.
content = event.source.get("content")
relates_to = content.get("m.relates_to") or {}
rel_type = relates_to.get("rel_type")
if rel_type == "m.replace":
event_id = relates_to.get("event_id")
self.replace_map[event_id] = event.event_id
logger.debug(f"Replace {event_id} with {event.event_id}")
# Extract the message text
msg = event.body
@ -50,17 +65,11 @@ class Callbacks:
if event.sender == self.client.user:
return
# Ignore too old messages
current_time = int(time.time() * 1000)
if current_time - event.server_timestamp > 60000:
return
logger.debug(
f"Bot message received for room {room.display_name} | "
f"{room.user_name(event.sender)}: {msg}"
)
content = event.source.get("content")
reply_to = ((content.get("m.relates_to") or {}).get("m.in_reply_to") or {}).get(
"event_id"
)
@ -98,7 +107,14 @@ class Callbacks:
msg = msg[len(self.command_prefix) :]
command = Command(
self.client, self.store, self.config, msg, room, event, reply_to
self.client,
self.store,
self.config,
msg,
room,
event,
reply_to,
self.replace_map,
)
try:
await command.process()

View file

@ -17,6 +17,7 @@ from nio import (
from wand.image import Image
from nyx_bot.quote_image import make_quote_image
from nyx_bot.utils import get_body, user_name
logger = logging.getLogger(__name__)
@ -183,6 +184,7 @@ async def send_quote_image(
room: MatrixRoom,
event: RoomMessageText,
reply_to: str,
replace_map: dict,
):
if not reply_to:
await send_text_to_room(
@ -199,8 +201,8 @@ async def send_quote_image(
target_event = target_response.event
if isinstance(target_event, RoomMessageText):
sender = target_event.sender
body = target_event.body
sender_name = room.user_name(sender)
body = await get_body(client, room, target_event.event_id, replace_map)
sender_name = user_name(room, sender)
sender_avatar = room.avatar_url(sender)
image = None
if sender_avatar:
@ -214,7 +216,7 @@ async def send_quote_image(
else:
image = Image(width=64, height=64, background="#FFFF00")
quote_image = await make_quote_image(sender_name, body, image)
await send_sticker_image(client, room.room_id, quote_image, reply_to)
await send_sticker_image(client, room.room_id, quote_image, body, event.event_id)
else:
await send_text_to_room(
@ -232,6 +234,7 @@ async def send_sticker_image(
client: AsyncClient,
room_id: str,
image: Image,
body: str,
reply_to: Optional[str] = None,
):
"""Send sticker to toom. Hardcodes to WebP.
@ -285,7 +288,7 @@ async def send_sticker_image(
print(f"Failed to upload image. Failure response: {resp}")
content = {
"body": "[Image]",
"body": body,
"info": {
"size": length,
"mimetype": "image/webp",
@ -357,8 +360,20 @@ async def send_user_image(
bytesio = BytesIO(data)
length = bytesio.getbuffer().nbytes
image = Image(file=bytesio)
else:
await send_text_to_room(
client,
room.room_id,
"This user has no avatar.",
True,
False,
event.event_id,
True,
)
return
(width, height) = (image.width, image.height)
with image:
(width, height) = (image.width, image.height)
content = {
"body": f"[Avatar of {sender_name}]",
@ -382,10 +397,4 @@ async def send_user_image(
if reply_to:
content["m.relates_to"] = {"m.in_reply_to": {"event_id": reply_to}}
try:
await client.room_send(
room.room_id, message_type="m.room.message", content=content
)
print("Image was sent successfully")
except Exception:
print(f"Image send of file {image} failed.")
await client.room_send(room.room_id, message_type="m.room.message", content=content)

27
nyx_bot/utils.py Normal file
View file

@ -0,0 +1,27 @@
from typing import Optional
from nio import AsyncClient, MatrixRoom
def user_name(room: MatrixRoom, user_id: str) -> Optional[str]:
"""Get display name for a user."""
if user_id not in room.users:
return None
user = room.users[user_id]
return user.name
async def get_body(
client: AsyncClient, room: MatrixRoom, event_id: str, replace_map: str
) -> str:
if event_id not in replace_map:
target_response = await client.room_get_event(room.room_id, event_id)
target_event = target_response.event
return target_event.body
else:
new_evid = replace_map.get(event_id)
target_response = await client.room_get_event(room.room_id, new_evid)
target_event = target_response.event
content = target_event.source.get("content")
new_content = content.get("m.new_content")
return new_content.get("body")