Esempio n. 1
0
 async def handle_matrix_message(self, sender: 'u.User',
                                 message: MessageEventContent,
                                 event_id: EventID) -> None:
     puppet = p.Puppet.get_by_custom_mxid(sender.mxid)
     if puppet and message.get("net.maunium.hangouts.puppet", False):
         self.log.debug(
             f"Ignoring puppet-sent message by confirmed puppet user {sender.mxid}"
         )
         return
     # TODO this probably isn't nice for bridging images, it really only needs to lock the
     #      actual message send call and dedup queue append.
     async with self.require_send_lock(sender.gid):
         if message.msgtype == MessageType.TEXT or message.msgtype == MessageType.NOTICE:
             gid = await self._handle_matrix_text(sender, message)
         elif message.msgtype == MessageType.EMOTE:
             gid = await self._handle_matrix_emote(sender, message)
         elif message.msgtype == MessageType.IMAGE:
             gid = await self._handle_matrix_image(sender, message)
         # elif message.msgtype == MessageType.LOCATION:
         #     gid = await self._handle_matrix_location(sender, message)
         else:
             self.log.warning(f"Unsupported msgtype in {message}")
             return
         if not gid:
             return
         self._dedup.appendleft(gid)
         DBMessage(mxid=event_id,
                   mx_room=self.mxid,
                   gid=gid,
                   receiver=self.receiver,
                   index=0).insert()
         self._last_bridged_mxid = event_id
     await self._send_delivery_receipt(event_id)
Esempio n. 2
0
 async def apply_relay_message_format(
     self, sender: br.BaseUser, content: MessageEventContent
 ) -> None:
     if self.relay_formatted_body and content.get("format", None) != Format.HTML:
         content["format"] = Format.HTML
         content["formatted_body"] = html.escape(content.body).replace("\n", "<br/>")
     tpl = self.bridge.config["bridge.relay.message_formats"].get(
         content.msgtype.value, "$sender_displayname: $message"
     )
     displayname = await self.get_displayname(sender)
     username, _ = self.az.intent.parse_user_id(sender.mxid)
     tpl_args = {
         "sender_mxid": sender.mxid,
         "sender_username": username,
         "sender_displayname": html.escape(displayname),
         "formatted_body": content["formatted_body"],
         "body": content.body,
         "message": content.body,
     }
     content.body = Template(tpl).safe_substitute(tpl_args)
     if self.relay_formatted_body and "formatted_body" in content:
         tpl_args["message"] = content["formatted_body"]
         content["formatted_body"] = Template(tpl).safe_substitute(tpl_args)
     if self.relay_emote_to_text and content.msgtype == MessageType.EMOTE:
         content.msgtype = MessageType.TEXT
Esempio n. 3
0
    async def handle_matrix_message(self, sender: 'u.User',
                                    message: MessageEventContent,
                                    event_id: EventID) -> None:
        if ((message.get(self.bridge.real_user_content_key, False)
             and await p.Puppet.get_by_custom_mxid(sender.mxid))):
            self.log.debug(
                f"Ignoring puppet-sent message by confirmed puppet user {sender.mxid}"
            )
            return
        request_id = int(time.time() * 1000)
        self._msgts_dedup.appendleft((sender.uuid, request_id))

        quote = None
        if message.get_reply_to():
            reply = await DBMessage.get_by_mxid(message.get_reply_to(),
                                                self.mxid)
            # TODO include actual text? either store in db or fetch event from homeserver
            quote = Quote(id=reply.timestamp,
                          author=Address(uuid=reply.sender),
                          text="")

        text = message.body
        attachments: Optional[List[Attachment]] = None
        attachment_path: Optional[str] = None
        if message.msgtype == MessageType.EMOTE:
            text = f"/me {text}"
        elif message.msgtype.is_media:
            attachment_path = await self._download_matrix_media(message)
            attachment = self._make_attachment(message, attachment_path)
            attachments = [attachment]
            text = None
            self.log.trace("Formed outgoing attachment %s", attachment)
        await self.signal.send(username=sender.username,
                               recipient=self.recipient,
                               body=text,
                               quote=quote,
                               attachments=attachments,
                               timestamp=request_id)
        msg = DBMessage(mxid=event_id,
                        mx_room=self.mxid,
                        sender=sender.uuid,
                        timestamp=request_id,
                        signal_chat_id=self.chat_id,
                        signal_receiver=self.receiver)
        await msg.insert()
        await self._send_delivery_receipt(event_id)
        self.log.debug(f"Handled Matrix message {event_id} -> {request_id}")
        if attachment_path and self.config["signal.remove_file_after_handling"]:
            try:
                os.remove(attachment_path)
            except FileNotFoundError:
                pass
Esempio n. 4
0
    async def handle_matrix_message(self, sender: 'u.User', content: MessageEventContent,
                                    event_id: EventID) -> None:
        if not content.body or not content.msgtype:
            self.log.debug(f"Ignoring message {event_id} in {self.mxid} without body or msgtype")
            return

        puppet = p.Puppet.get_by_custom_mxid(sender.mxid)
        if puppet and content.get("net.maunium.telegram.puppet", False):
            self.log.debug("Ignoring puppet-sent message by confirmed puppet user %s", sender.mxid)
            return

        logged_in = not await sender.needs_relaybot(self)
        client = sender.client if logged_in else self.bot.client
        sender_id = sender.tgid if logged_in else self.bot.tgid
        space = (self.tgid if self.peer_type == "channel"  # Channels have their own ID space
                 else (sender.tgid if logged_in else self.bot.tgid))
        reply_to = formatter.matrix_reply_to_telegram(content, space, room_id=self.mxid)

        media = (MessageType.STICKER, MessageType.IMAGE, MessageType.FILE, MessageType.AUDIO,
                 MessageType.VIDEO)

        if content.msgtype == MessageType.NOTICE:
            bridge_notices = self.get_config("bridge_notices.default")
            excepted = sender.mxid in self.get_config("bridge_notices.exceptions")
            if not bridge_notices and not excepted:
                return

        if content.msgtype in (MessageType.TEXT, MessageType.EMOTE, MessageType.NOTICE):
            await self._pre_process_matrix_message(sender, not logged_in, content)
            await self._handle_matrix_text(sender_id, event_id, space, client, content, reply_to)
        elif content.msgtype == MessageType.LOCATION:
            await self._pre_process_matrix_message(sender, not logged_in, content)
            await self._handle_matrix_location(sender_id, event_id, space, client, content,
                                               reply_to)
        elif content.msgtype in media:
            content["net.maunium.telegram.internal.filename"] = content.body
            try:
                caption_content: MessageEventContent = sender.command_status["caption"]
                reply_to = reply_to or formatter.matrix_reply_to_telegram(caption_content, space,
                                                                          room_id=self.mxid)
                sender.command_status = None
            except (KeyError, TypeError):
                caption_content = None if logged_in else TextMessageEventContent(body=content.body)
            if caption_content:
                caption_content.msgtype = content.msgtype
                await self._pre_process_matrix_message(sender, not logged_in, caption_content)
            await self._handle_matrix_file(sender_id, event_id, space, client, content, reply_to,
                                           caption_content)
        else:
            self.log.debug(f"Unhandled Matrix event: {content}")
Esempio n. 5
0
 async def handle_matrix_message(self, sender: 'u.User',
                                 message: MessageEventContent,
                                 event_id: EventID) -> None:
     if not sender.client:
         self.log.debug(
             f"Ignoring message {event_id} as user is not connected")
         return
     elif ((message.get(self.bridge.real_user_content_key, False)
            and await p.Puppet.get_by_custom_mxid(sender.mxid))):
         self.log.debug(
             f"Ignoring puppet-sent message by confirmed puppet user {sender.mxid}"
         )
         return
     request_id = str(sender.client.new_request_id())
     self._reqid_dedup.add(request_id)
     text = message.body
     media_id = None
     if message.msgtype == MessageType.EMOTE:
         text = f"/me {text}"
     elif message.msgtype.is_media:
         if message.file and decrypt_attachment:
             data = await self.main_intent.download_media(message.file.url)
             data = decrypt_attachment(data, message.file.key.key,
                                       message.file.hashes.get("sha256"),
                                       message.file.iv)
         else:
             data = await self.main_intent.download_media(message.url)
         mime_type = message.info.mimetype or magic.from_buffer(data,
                                                                mime=True)
         # TODO this will throw errors if the mime type is not supported
         #      those errors should be sent back to the client
         upload_resp = await sender.client.upload(data, mime_type=mime_type)
         media_id = upload_resp.media_id
         text = ""
     resp = await sender.client.conversation(self.twid
                                             ).send(text,
                                                    media_id=media_id,
                                                    request_id=request_id)
     resp_msg_id = int(resp.entries[0].message.id)
     self._msgid_dedup.appendleft(resp_msg_id)
     msg = DBMessage(mxid=event_id,
                     mx_room=self.mxid,
                     twid=resp_msg_id,
                     receiver=self.receiver)
     await msg.insert()
     self._reqid_dedup.remove(request_id)
     await self._send_delivery_receipt(event_id)
     self.log.debug(f"Handled Matrix message {event_id} -> {resp_msg_id}")
Esempio n. 6
0
 async def _handle_matrix_message(self, sender: 'u.User', message: MessageEventContent,
                                  event_id: EventID) -> None:
     if ((message.get(self.bridge.real_user_content_key, False)
          and await p.Puppet.get_by_custom_mxid(sender.mxid))):
         self.log.debug(f"Ignoring puppet-sent message by confirmed puppet user {sender.mxid}")
         return
     elif not sender.is_connected:
         await self._send_bridge_error("You're not connected to Instagram", confirmed=True)
         return
     else:
         self.log.debug(f"Handling Matrix message {event_id} from {sender.mxid}/{sender.igpk}")
     request_id = str(uuid4())
     self._reqid_dedup.add(request_id)
     if message.msgtype in (MessageType.EMOTE, MessageType.TEXT):
         text = message.body
         if message.msgtype == MessageType.EMOTE:
             text = f"/me {text}"
         self.log.trace(f"Sending Matrix text from {event_id} with request ID {request_id}")
         resp = await sender.mqtt.send_text(self.thread_id, text=text,
                                            client_context=request_id)
     elif message.msgtype.is_media:
         if message.file and decrypt_attachment:
             data = await self.main_intent.download_media(message.file.url)
             data = decrypt_attachment(data, message.file.key.key,
                                       message.file.hashes.get("sha256"), message.file.iv)
         else:
             data = await self.main_intent.download_media(message.url)
         mime_type = message.info.mimetype or magic.from_buffer(data, mime=True)
         if mime_type != "image/jpeg" and mime_type.startswith("image/"):
             with BytesIO(data) as inp:
                 img = Image.open(inp)
                 with BytesIO() as out:
                     img.convert("RGB").save(out, format="JPEG", quality=80)
                     data = out.getvalue()
             mime_type = "image/jpeg"
         if mime_type == "image/jpeg":
             self.log.trace(f"Uploading photo from {event_id}")
             upload_resp = await sender.client.upload_jpeg_photo(data)
             self.log.trace(f"Broadcasting uploaded photo with request ID {request_id}")
             # TODO is it possible to do this with MQTT?
             resp = await sender.client.broadcast(self.thread_id,
                                                  ThreadItemType.CONFIGURE_PHOTO,
                                                  client_context=request_id,
                                                  upload_id=upload_resp.upload_id,
                                                  allow_full_aspect_ratio="1")
         else:
             await self._send_bridge_error("Non-image files are currently not supported",
                                           confirmed=True)
             return
     else:
         self.log.debug(f"Unhandled Matrix message {event_id}: "
                        f"unknown msgtype {message.msgtype}")
         return
     self.log.trace(f"Got response to message send {request_id}: {resp}")
     if resp.status != "ok":
         self.log.warning(f"Failed to handle {event_id}: {resp}")
         await self._send_bridge_error(resp.payload.message)
     else:
         self._msgid_dedup.appendleft(resp.payload.item_id)
         await DBMessage(mxid=event_id, mx_room=self.mxid, item_id=resp.payload.item_id,
                         receiver=self.receiver, sender=sender.igpk).insert()
         self._reqid_dedup.remove(request_id)
         await self._send_delivery_receipt(event_id)
         self.log.debug(f"Handled Matrix message {event_id} -> {resp.payload.item_id}")