Пример #1
0
def efb_image_wrapper(file: IO,
                      filename: str = None,
                      text: str = None) -> Message:
    """
    A EFB message wrapper for images.

    :param file: The file handle
    :param filename: The actual filename
    :param text: The attached text
    :return: EFB Message
    """
    efb_msg = Message()
    efb_msg.file = file
    mime = magic.from_file(file.name, mime=True)
    if isinstance(mime, bytes):
        mime = mime.decode()

    if "gif" in mime:
        efb_msg.type = MsgType.Animation
    else:
        efb_msg.type = MsgType.Image

    if filename:
        efb_msg.filename = filename
    else:
        efb_msg.filename = file.name
        efb_msg.filename += '.' + str(mime).split('/')[
            1]  # Add extension suffix

    if text:
        efb_msg.text = text

    efb_msg.path = efb_msg.file.name
    efb_msg.mime = mime
    return efb_msg
Пример #2
0
def efb_text_simple_wrapper(
    text: str,
    ats: Union[Mapping[Tuple[int, int], Union[Chat, ChatMember]], None] = None
) -> Message:
    """
    A simple EFB message wrapper for plain text. Emojis are presented as is (plain text).

    :param text: The content of the message
    :param ats: The substitutions of at messages, must follow the Substitution format when not None
                [[begin_index, end_index], {Chat or ChatMember}]
    :return: EFB Message
    """
    efb_msg = Message(type=MsgType.Text, text=text)
    if ats:
        efb_msg.substitutions = Substitutions(ats)
    return efb_msg
Пример #3
0
    async def handle_new_telegram_message(self, event: NewMessage):
        msg: TgMsg = event.message
        chat_id = get_chat_id(msg.peer_id)
        chat = await self.async_get_chat(chat_id)
        self.logger.debug(msg)

        file = None
        path = None
        filename = None
        mime = None
        msg_type = MsgType.Text
        tempfile_suffix = ''
        if getattr(msg, 'media', None):
            media = msg.media
            tempfile_suffix = get_extension(media)
            if isinstance(media, MessageMediaPhoto):
                msg_type = MsgType.Image
            if isinstance(media, MessageMediaDocument):
                document = media.document
                mime = document.mime_type
                msg_type = MsgType.File
                for attr in document.attributes:
                    if isinstance(attr, DocumentAttributeFilename):
                        tempfile_suffix = attr.file_name
                        filename = attr.file_name
                    if isinstance(attr, DocumentAttributeSticker):
                        msg_type = MsgType.Sticker
                    if isinstance(attr, DocumentAttributeVideo):
                        msg_type = MsgType.Video
                    if isinstance(attr, DocumentAttributeAudio):
                        msg_type = MsgType.Audio
        if msg_type != MsgType.Text:
            file = tempfile.NamedTemporaryFile(suffix=tempfile_suffix)
            path = file.name
            await self.client.download_media(msg, file)

        msg_peer = await self.client.get_entity(
            get_chat_id(msg.from_id or msg.peer_id))
        self.logger.debug(msg_peer)

        chat_member = ChatMember(
            chat=chat,
            name=format_entity_name(msg_peer),
            uid=str(chat_id),
        )
        efb_msg = Message(
            deliver_to=coordinator.master,
            author=chat_member,
            chat=chat,
            text=msg.message,
            type=msg_type,
            uid=f'{chat_id}_{msg.id}',
            file=file,
            filename=filename,
            mime=mime,
            path=path,
        )
        coordinator.send_message(efb_msg)
Пример #4
0
def efb_unsupported_wrapper(text: str) -> Message:
    """
    A simple EFB message wrapper for unsupported message

    :param text: The content of the message
    :return: EFB Message
    """
    efb_msg = Message(type=MsgType.Unsupported, text=text)
    return efb_msg
 def send_message(self, msg: Message) -> Message:
     if msg.type == MsgType.Text:
         coordinator.send_message(Message(
             uid=MessageID(f'echo_{uuid4()}'),
             type=MsgType.Text,
             chat=self.chat,
             author=self.chat.other,
             deliver_to=coordinator.master,
             text=msg.text,
         ))
     return msg
Пример #6
0
def efb_file_wrapper(file: IO,
                     filename: str = None,
                     text: str = None) -> Message:
    efb_msg = Message()
    efb_msg.type = MsgType.File
    efb_msg.file = file
    mime = magic.from_file(efb_msg.file.name, mime=True)
    if isinstance(mime, bytes):
        mime = mime.decode()
    if filename:
        efb_msg.filename = filename
    else:
        efb_msg.filename = file.name
        efb_msg.filename += '.' + str(mime).split('/')[
            1]  # Add extension suffix
    efb_msg.path = efb_msg.file.name
    efb_msg.mime = mime
    if text:
        efb_msg.text = text
    return efb_msg
    def build_efb_msg(self, mid: str, thread_id: str, author_id: str, message_object: Message,
                      nested: bool = False) -> EFBMessage:
        efb_msg = EFBMessage(
            uid=MessageID(mid),
            text=message_object.text,
            type=MsgType.Text,
            deliver_to=coordinator.master,
        )

        # Authors
        efb_msg.chat = self.chat_manager.get_thread(thread_id)
        efb_msg.author = efb_msg.chat.get_member(ChatID(author_id))

        if not nested and message_object.replied_to:
            efb_msg.target = self.build_efb_msg(message_object.reply_to_id,
                                                thread_id=thread_id,
                                                author_id=message_object.author,
                                                message_object=message_object.replied_to,
                                                nested=True)

        if message_object.mentions:
            mentions: Dict[Tuple[int, int], ChatMember] = dict()
            for i in message_object.mentions:
                mentions[(i.offset, i.offset + i.length)] = efb_msg.chat.get_member(i.thread_id)
            efb_msg.substitutions = Substitutions(mentions)

        if message_object.emoji_size:
            efb_msg.text += " (%s)" % message_object.emoji_size.name[0]
            # " (S)", " (M)", " (L)"

        if message_object.reactions:
            reactions: DefaultDict[ReactionName, List[ChatMember]] = defaultdict(list)
            for user_id, reaction in message_object.reactions.items():
                reactions[ReactionName(reaction.value)].append(
                    efb_msg.chat.get_member(user_id))
            efb_msg.reactions = reactions
        return efb_msg
    def send_message(self, msg: EFBMessage) -> Message:
        self.logger.debug("Received message from master: %s", msg)

        try:
            target_msg_offset = 0
            prefix = ""

            mentions = []

            # Send message reaction
            # if msg.target and msg.text.startswith('r`') and \
            #         msg.target.uid.startswith("mid.$"):
            #     self.logger.debug("[%s] Message is a reaction to another message: %s", msg.uid, msg.text)
            #     msg_id = ".".join(msg.target.uid.split(".", 2)[:2])
            #     if getattr(MessageReaction, msg.text[2:], None):
            #         self.client.reactToMessage(msg_id, getattr(MessageReaction, msg.text[2:]))
            #     else:
            #         self.client.reactToMessage(msg_id, self.CustomReaction(msg.text[2:]))
            #     msg.uid = "__reaction__"
            #     return msg

            # Message substitutions
            if msg.substitutions:
                self.logger.debug("[%s] Message has substitutions: %s", msg.uid, msg.substitutions)
                for i in msg.substitutions:
                    mentions.append(Mention(msg.substitutions[i].id,
                                            target_msg_offset + i[0], i[1] - i[0]))
                self.logger.debug("[%s] Translated to mentions: %s", msg.uid, mentions)

            fb_msg = Message(text=prefix + msg.text, mentions=mentions)
            thread: Thread = self.client.fetchThreadInfo(msg.chat.uid)[str(msg.chat.uid)]

            if msg.target and msg.target.uid:
                fb_msg.reply_to_id = msg.target.uid

            if msg.type in (MsgType.Text, MsgType.Unsupported):
                # Remove variation selector-16 (force colored emoji) for
                # matching.
                emoji_compare = msg.text.replace("\uFE0F", "")
                if emoji_compare == "👍":
                    fb_msg.sticker = Sticker(uid=EmojiSize.SMALL.value)
                    if not prefix:
                        fb_msg.text = None
                elif emoji_compare[:-1] == "👍" and emoji_compare[-1] in 'SML':
                    if emoji_compare[-1] == 'S':
                        fb_msg.sticker = Sticker(uid=EmojiSize.SMALL.value)
                    elif emoji_compare[-1] == 'M':
                        fb_msg.sticker = Sticker(uid=EmojiSize.MEDIUM.value)
                    elif emoji_compare[-1] == 'L':
                        fb_msg.sticker = Sticker(uid=EmojiSize.LARGE.value)
                    if not prefix:
                        fb_msg.text = None
                elif emoji_compare[:-1] in emoji.UNICODE_EMOJI and emoji_compare[-1] in 'SML':  # type: ignore
                    self.logger.debug("[%s] Message is an Emoji message: %s", msg.uid, emoji_compare)
                    if emoji_compare[-1] == 'S':
                        fb_msg.emoji_size = EmojiSize.SMALL
                    elif emoji_compare[-1] == 'M':
                        fb_msg.emoji_size = EmojiSize.MEDIUM
                    elif emoji_compare[-1] == 'L':
                        fb_msg.emoji_size = EmojiSize.LARGE
                    fb_msg.text = emoji_compare[:-1]
                msg.uid = self.client.send(fb_msg, thread_id=thread.uid, thread_type=thread.type)
            elif msg.type in (MsgType.Image, MsgType.Sticker, MsgType.Animation):
                msg_uid = self.client.send_image_file(msg.filename, msg.file, msg.mime, message=fb_msg,
                                                      thread_id=thread.uid, thread_type=thread.type)
                if msg_uid.startswith('mid.$'):
                    self.client.sent_messages.add(msg_uid)
                    self.logger.debug("Sent message with ID %s", msg_uid)
                msg.uid = msg_uid
            elif msg.type == MsgType.Voice:
                files = self.upload_file(msg, voice_clip=True)
                msg_uid = self.client._sendFiles(files=files, message=fb_msg,
                                                 thread_id=thread.uid, thread_type=thread.type)
                if msg_uid.startswith('mid.$'):
                    self.client.sent_messages.add(msg_uid)
                    self.logger.debug("Sent message with ID %s", msg_uid)
                msg.uid = msg_uid
            elif msg.type in (MsgType.File, MsgType.Video):
                files = self.upload_file(msg)
                msg_uid = self.client._sendFiles(files=files, message=fb_msg,
                                                 thread_id=thread.uid, thread_type=thread.type)
                if msg_uid.startswith('mid.$'):
                    self.client.sent_messages.add(msg_uid)
                    self.logger.debug("Sent message with ID %s", msg_uid)
                msg.uid = msg_uid
            elif msg.type == MsgType.Status:
                assert (isinstance(msg.attributes, StatusAttribute))
                status: StatusAttribute = msg.attributes
                if status.status_type in (StatusAttribute.Types.TYPING,
                                          StatusAttribute.Types.UPLOADING_VOICE,
                                          StatusAttribute.Types.UPLOADING_VIDEO,
                                          StatusAttribute.Types.UPLOADING_IMAGE,
                                          StatusAttribute.Types.UPLOADING_FILE):
                    self.client.setTypingStatus(TypingStatus.TYPING, thread_id=thread.uid, thread_type=thread.type)
                    threading.Timer(status.timeout / 1000, self.stop_typing, args=(thread.uid, thread.type)).start()
            elif msg.type == MsgType.Link:
                assert (isinstance(msg.attributes, LinkAttribute))
                link: LinkAttribute = msg.attributes
                if self.flag('send_link_with_description'):
                    info: Tuple[str, ...] = (link.title,)
                    if link.description:
                        info += (link.description,)
                    info += (link.url,)
                    text = "\n".join(info)
                else:
                    text = link.url
                if fb_msg.text:
                    text = fb_msg.text + "\n" + text
                fb_msg.text = text
                msg.uid = self.client.send(fb_msg, thread_id=thread.uid, thread_type=thread.type)
            elif msg.type == MsgType.Location:
                assert (isinstance(msg.attributes, LocationAttribute))
                location_attr: LocationAttribute = msg.attributes
                location = LocationAttachment(latitude=location_attr.latitude,
                                              longitude=location_attr.longitude)
                self.client.sendPinnedLocation(location, fb_msg, thread_id=thread.uid, thread_type=thread.type)
            else:
                raise EFBMessageTypeNotSupported()
            return msg
        finally:
            if msg.file and not msg.file.closed:
                msg.file.close()
            self.client.markAsSeen()
            self.client.markAsRead(msg.chat.uid)