Skip to content

Commit 8e8360a

Browse files
committed
portal/matrix: report message send checkpoint on all message types
1 parent a1f389c commit 8e8360a

File tree

1 file changed

+124
-45
lines changed

1 file changed

+124
-45
lines changed

mautrix_telegram/portal/matrix.py

+124-45
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@
3333
UpdateNewMessage, InputMediaUploadedDocument,
3434
InputMediaUploadedPhoto)
3535

36-
from mautrix.types import (EventID, RoomID, UserID, ContentURI, MessageType, MessageEventContent,
37-
TextMessageEventContent, MediaMessageEventContent, Format,
38-
LocationMessageEventContent, ImageInfo, VideoInfo)
36+
from mautrix.types import (EventID, EventType, RoomID, UserID, ContentURI, MessageType,
37+
MessageEventContent, TextMessageEventContent, MediaMessageEventContent,
38+
Format, LocationMessageEventContent, ImageInfo, VideoInfo)
39+
from mautrix.util.message_send_checkpoint import MessageSendCheckpointStatus
3940

4041
from ..types import TelegramID
4142
from ..db import Message as DBMessage
@@ -225,11 +226,13 @@ async def _pre_process_matrix_message(self, sender: 'u.User', use_relaybot: bool
225226
elif content.msgtype == MessageType.EMOTE:
226227
await self._apply_emote_format(sender, content)
227228

228-
async def _handle_matrix_text(self, sender_id: TelegramID, event_id: EventID,
229+
async def _handle_matrix_text(self, sender: 'u.User', logged_in: bool, event_id: EventID,
229230
space: TelegramID, client: 'MautrixTelegramClient',
230-
content: TextMessageEventContent, reply_to: TelegramID) -> None:
231+
content: TextMessageEventContent, reply_to: Optional[TelegramID]
232+
) -> None:
231233
message, entities = await formatter.matrix_to_telegram(client, text=content.body,
232234
html=content.formatted(Format.HTML))
235+
sender_id = sender.tgid if logged_in else self.bot.tgid
233236
async with self.send_lock(sender_id):
234237
lp = self.get_config("telegram_link_preview")
235238
if content.get_edit():
@@ -240,16 +243,28 @@ async def _handle_matrix_text(self, sender_id: TelegramID, event_id: EventID,
240243
link_preview=lp)
241244
self._add_telegram_message_to_db(event_id, space, -1, response)
242245
return
243-
response = await client.send_message(self.peer, message, reply_to=reply_to,
244-
formatting_entities=entities,
245-
link_preview=lp)
246-
self._add_telegram_message_to_db(event_id, space, 0, response)
247-
await self._send_delivery_receipt(event_id)
246+
try:
247+
response = await client.send_message(self.peer, message, reply_to=reply_to,
248+
formatting_entities=entities,
249+
link_preview=lp)
250+
except Exception:
251+
raise
252+
else:
253+
sender.send_remote_checkpoint(
254+
MessageSendCheckpointStatus.SUCCESS,
255+
event_id,
256+
self.mxid,
257+
EventType.ROOM_MESSAGE,
258+
message_type=content.msgtype,
259+
)
260+
self._add_telegram_message_to_db(event_id, space, 0, response)
261+
await self._send_delivery_receipt(event_id)
248262

249-
async def _handle_matrix_file(self, sender_id: TelegramID, event_id: EventID,
263+
async def _handle_matrix_file(self, sender: 'u.User', logged_in: bool, event_id: EventID,
250264
space: TelegramID, client: 'MautrixTelegramClient',
251265
content: MediaMessageEventContent, reply_to: TelegramID,
252266
caption: TextMessageEventContent = None) -> None:
267+
sender_id = sender.tgid if logged_in else self.bot.tgid
253268
mime = content.info.mimetype
254269
if isinstance(content.info, (ImageInfo, VideoInfo)):
255270
w, h = content.info.width, content.info.height
@@ -264,9 +279,8 @@ async def _handle_matrix_file(self, sender_id: TelegramID, event_id: EventID,
264279
else:
265280
if content.file:
266281
if not decrypt_attachment:
267-
self.log.warning(f"Can't bridge encrypted media event {event_id}:"
268-
" matrix-nio not installed")
269-
return
282+
raise Exception(f"Can't bridge encrypted media event {event_id}: matrix-nio "
283+
"is not installed")
270284
file = await self.main_intent.download_media(content.file.url)
271285
file = decrypt_attachment(file, content.file.key.key,
272286
content.file.hashes.get("sha256"), content.file.iv)
@@ -304,15 +318,26 @@ async def _handle_matrix_file(self, sender_id: TelegramID, event_id: EventID,
304318
if await self._matrix_document_edit(client, content, space, capt, media, event_id):
305319
return
306320
try:
307-
response = await client.send_media(self.peer, media, reply_to=reply_to,
308-
caption=capt, entities=entities)
309-
except (PhotoInvalidDimensionsError, PhotoSaveFileInvalidError, PhotoExtInvalidError):
310-
media = InputMediaUploadedDocument(file=media.file, mime_type=mime,
311-
attributes=attributes)
312-
response = await client.send_media(self.peer, media, reply_to=reply_to,
313-
caption=capt, entities=entities)
314-
self._add_telegram_message_to_db(event_id, space, 0, response)
315-
await self._send_delivery_receipt(event_id)
321+
try:
322+
response = await client.send_media(self.peer, media, reply_to=reply_to,
323+
caption=capt, entities=entities)
324+
except (PhotoInvalidDimensionsError, PhotoSaveFileInvalidError, PhotoExtInvalidError):
325+
media = InputMediaUploadedDocument(file=media.file, mime_type=mime,
326+
attributes=attributes)
327+
response = await client.send_media(self.peer, media, reply_to=reply_to,
328+
caption=capt, entities=entities)
329+
except Exception:
330+
raise
331+
else:
332+
sender.send_remote_checkpoint(
333+
MessageSendCheckpointStatus.SUCCESS,
334+
event_id,
335+
self.mxid,
336+
EventType.ROOM_MESSAGE,
337+
message_type=content.msgtype,
338+
)
339+
self._add_telegram_message_to_db(event_id, space, 0, response)
340+
await self._send_delivery_receipt(event_id)
316341

317342
async def _matrix_document_edit(self, client: 'MautrixTelegramClient',
318343
content: MessageEventContent, space: TelegramID,
@@ -327,10 +352,11 @@ async def _matrix_document_edit(self, client: 'MautrixTelegramClient',
327352
return True
328353
return False
329354

330-
async def _handle_matrix_location(self, sender_id: TelegramID, event_id: EventID,
355+
async def _handle_matrix_location(self, sender: 'u.User', logged_in: bool, event_id: EventID,
331356
space: TelegramID, client: 'MautrixTelegramClient',
332357
content: LocationMessageEventContent, reply_to: TelegramID
333358
) -> None:
359+
sender_id = sender.tgid if logged_in else self.bot.tgid
334360
try:
335361
lat, long = content.geo_uri[len("geo:"):].split(";")[0].split(",")
336362
lat, long = float(lat), float(long)
@@ -343,10 +369,21 @@ async def _handle_matrix_location(self, sender_id: TelegramID, event_id: EventID
343369
async with self.send_lock(sender_id):
344370
if await self._matrix_document_edit(client, content, space, caption, media, event_id):
345371
return
346-
response = await client.send_media(self.peer, media, reply_to=reply_to,
347-
caption=caption, entities=entities)
348-
self._add_telegram_message_to_db(event_id, space, 0, response)
349-
await self._send_delivery_receipt(event_id)
372+
try:
373+
response = await client.send_media(self.peer, media, reply_to=reply_to,
374+
caption=caption, entities=entities)
375+
except Exception:
376+
raise
377+
else:
378+
self._add_telegram_message_to_db(event_id, space, 0, response)
379+
sender.send_remote_checkpoint(
380+
MessageSendCheckpointStatus.SUCCESS,
381+
event_id,
382+
self.mxid,
383+
EventType.ROOM_MESSAGE,
384+
message_type=content.msgtype,
385+
)
386+
await self._send_delivery_receipt(event_id)
350387

351388
def _add_telegram_message_to_db(self, event_id: EventID, space: TelegramID,
352389
edit_index: int, response: TypeMessage) -> None:
@@ -362,7 +399,19 @@ def _add_telegram_message_to_db(self, event_id: EventID, space: TelegramID,
362399
mxid=event_id,
363400
edit_index=edit_index).insert()
364401

365-
async def _send_bridge_error(self, msg: str) -> None:
402+
async def _send_bridge_error(self, sender: 'u.User', err: Exception, event_id: EventID,
403+
event_type: EventType,
404+
message_type: Optional[MessageType] = None,
405+
msg: Optional[str] = None, confirmed: bool = False) -> None:
406+
sender.send_remote_checkpoint(
407+
MessageSendCheckpointStatus.PERM_FAILURE,
408+
event_id,
409+
self.mxid,
410+
event_type,
411+
message_type=message_type,
412+
error=err,
413+
)
414+
366415
if config["bridge.delivery_error_reports"]:
367416
await self._send_message(self.main_intent,
368417
TextMessageEventContent(msgtype=MessageType.NOTICE, body=msg))
@@ -372,10 +421,25 @@ async def handle_matrix_message(self, sender: 'u.User', content: MessageEventCon
372421
try:
373422
await self._handle_matrix_message(sender, content, event_id)
374423
except RPCError as e:
375-
if config["bridge.delivery_error_reports"]:
376-
await self._send_bridge_error(
377-
f"\u26a0 Your message may not have been bridged: {e}")
424+
self.log.exception(f"RPCError while bridging {event_id}: {e}")
425+
await self._send_bridge_error(
426+
sender,
427+
e,
428+
event_id,
429+
EventType.ROOM_MESSAGE,
430+
message_type=content.msgtype,
431+
msg=f"\u26a0 Your message may not have been bridged: {e}",
432+
)
378433
raise
434+
except Exception as e:
435+
self.log.exception(f"Failed to bridge {event_id}: {e}")
436+
await self._send_bridge_error(
437+
sender,
438+
e,
439+
event_id,
440+
EventType.ROOM_MESSAGE,
441+
message_type=content.msgtype,
442+
)
379443

380444
async def _handle_matrix_message(self, sender: 'u.User', content: MessageEventContent,
381445
event_id: EventID) -> None:
@@ -385,7 +449,6 @@ async def _handle_matrix_message(self, sender: 'u.User', content: MessageEventCo
385449

386450
logged_in = not await sender.needs_relaybot(self)
387451
client = sender.client if logged_in else self.bot.client
388-
sender_id = sender.tgid if logged_in else self.bot.tgid
389452
space = (self.tgid if self.peer_type == "channel" # Channels have their own ID space
390453
else (sender.tgid if logged_in else self.bot.tgid))
391454
reply_to = formatter.matrix_reply_to_telegram(content, space, room_id=self.mxid)
@@ -397,14 +460,15 @@ async def _handle_matrix_message(self, sender: 'u.User', content: MessageEventCo
397460
bridge_notices = self.get_config("bridge_notices.default")
398461
excepted = sender.mxid in self.get_config("bridge_notices.exceptions")
399462
if not bridge_notices and not excepted:
400-
return
463+
raise Exception("Notices are not configured to be bridged.")
401464

402465
if content.msgtype in (MessageType.TEXT, MessageType.EMOTE, MessageType.NOTICE):
403466
await self._pre_process_matrix_message(sender, not logged_in, content)
404-
await self._handle_matrix_text(sender_id, event_id, space, client, content, reply_to)
467+
await self._handle_matrix_text(sender, logged_in, event_id, space, client, content,
468+
reply_to)
405469
elif content.msgtype == MessageType.LOCATION:
406470
await self._pre_process_matrix_message(sender, not logged_in, content)
407-
await self._handle_matrix_location(sender_id, event_id, space, client, content,
471+
await self._handle_matrix_location(sender, logged_in, event_id, space, client, content,
408472
reply_to)
409473
elif content.msgtype in media:
410474
content["net.maunium.telegram.internal.filename"] = content.body
@@ -418,11 +482,12 @@ async def _handle_matrix_message(self, sender: 'u.User', content: MessageEventCo
418482
if caption_content:
419483
caption_content.msgtype = content.msgtype
420484
await self._pre_process_matrix_message(sender, not logged_in, caption_content)
421-
await self._handle_matrix_file(sender_id, event_id, space, client, content, reply_to,
422-
caption_content)
485+
await self._handle_matrix_file(sender, logged_in, event_id, space, client, content,
486+
reply_to, caption_content)
423487
else:
424-
self.log.debug("Didn't handle Matrix event {event_id} due to unknown msgtype {content.msgtype}")
488+
self.log.debug(f"Didn't handle Matrix event {event_id} due to unknown msgtype {content.msgtype}")
425489
self.log.trace("Unhandled Matrix event content: %s", content)
490+
raise Exception(f"Unhandled msgtype {content.msgtype}")
426491

427492
async def handle_matrix_unpin_all(self, sender: 'u.User', pin_event_id: EventID) -> None:
428493
await sender.client(UnpinAllMessagesRequest(peer=self.peer))
@@ -444,22 +509,36 @@ async def handle_matrix_pin(self, sender: 'u.User', changes: Dict[EventID, bool]
444509

445510
async def handle_matrix_deletion(self, deleter: 'u.User', event_id: EventID,
446511
redaction_event_id: EventID) -> None:
512+
try:
513+
await self._handle_matrix_deletion(deleter, event_id, redaction_event_id)
514+
except Exception as e:
515+
await self._send_bridge_error(deleter, e, event_id, EventType.ROOM_REDACTION)
516+
else:
517+
deleter.send_remote_checkpoint(
518+
MessageSendCheckpointStatus.SUCCESS,
519+
event_id,
520+
self.mxid,
521+
EventType.ROOM_REDACTION,
522+
)
523+
await self._send_delivery_receipt(redaction_event_id)
524+
525+
async def _handle_matrix_deletion(self, deleter: 'u.User', event_id: EventID,
526+
redaction_event_id: EventID) -> None:
447527
real_deleter = deleter if not await deleter.needs_relaybot(self) else self.bot
448528
space = self.tgid if self.peer_type == "channel" else real_deleter.tgid
449529
message = DBMessage.get_by_mxid(event_id, self.mxid, space)
450530
if not message:
451-
self.log.trace(f"Ignoring Matrix redaction of unknown event {event_id}")
531+
raise Exception(f"Ignoring Matrix redaction of unknown event {event_id}")
452532
elif message.redacted:
453-
self.log.debug("Ignoring Matrix redaction of already redacted event "
454-
f"{message.mxid} in {message.mx_room}")
533+
raise Exception("Ignoring Matrix redaction of already redacted event "
534+
f"{message.mxid} in {message.mx_room}")
455535
elif message.edit_index != 0:
456536
message.edit(redacted=True)
457-
self.log.debug("Ignoring Matrix redaction of edit event "
458-
f"{message.mxid} in {message.mx_room}")
537+
raise Exception("Ignoring Matrix redaction of edit event "
538+
f"{message.mxid} in {message.mx_room}")
459539
else:
460540
message.edit(redacted=True)
461541
await real_deleter.client.delete_messages(self.peer, [message.tgid])
462-
await self._send_delivery_receipt(redaction_event_id)
463542

464543
async def _update_telegram_power_level(self, sender: 'u.User', user_id: TelegramID,
465544
level: int) -> None:

0 commit comments

Comments
 (0)