Ejemplo n.º 1
0
 def send_location_msg(self):
     slave = coordinator.slaves['tests.mocks.slave']
     alice = slave.get_chat('alice')
     msg = EFBMsg()
     msg.deliver_to = slave
     msg.chat = alice
     msg.author = EFBChat(self).self()
     msg.type = MsgType.Location
     msg.text = "I'm not here."
     msg.attributes = EFBMsgLocationAttribute(latitude=0.1, longitude=1.0)
     return coordinator.send_message(msg)
Ejemplo n.º 2
0
 def build_efb_chat_as_anonymous_user(self, context):
     efb_chat = EFBChat(self.channel)
     anonymous_data = context['anonymous']
     efb_chat.chat_uid = 'anonymous' + '_' + anonymous_data['flag']
     efb_chat.chat_name = '[Anonymous] ' + anonymous_data['name']
     efb_chat.chat_type = ChatType.User
     efb_chat.is_chat = False
     efb_chat.vendor_specific = {
         'is_anonymous': True,
         'anonymous_id': anonymous_data['id']
     }
     efb_chat.group = self.build_efb_chat_as_group(context)
     return efb_chat
Ejemplo n.º 3
0
 def send_link_msg(self):
     slave = next(iter(coordinator.slaves.values()))
     alice = slave.get_chat('alice')
     msg = EFBMsg()
     msg.deliver_to = slave
     msg.chat = alice
     msg.author = EFBChat(self).self()
     msg.type = MsgType.Link
     msg.text = "Check it out."
     msg.attributes = EFBMsgLinkAttribute(title="Example",
                                          url="https://example.com")
     return coordinator.send_message(msg)
Ejemplo n.º 4
0
 def test_copy(self):
     channel = MockMasterChannel()
     chat = EFBChat(channel)
     chat.chat_uid = "00001"
     chat.chat_name = "Chat"
     chat.chat_alias = "chaT"
     chat.chat_type = ChatType.User
     copy = chat.copy()
     assert chat == copy
     assert chat is not copy
Ejemplo n.º 5
0
 def test_copy(self):
     channel = MockMasterChannel()
     chat = EFBChat(channel)
     chat.chat_uid = "00001"
     chat.chat_name = "Chat"
     chat.chat_alias = "chaT"
     chat.chat_type = ChatType.User
     copy = chat.copy()
     self.assertEqual(chat, copy)
     self.assertIsNot(chat, copy)
Ejemplo n.º 6
0
 def build_efb_chat_as_group(self, context):
     efb_chat = EFBChat(self.channel)
     efb_chat.chat_type = ChatType.Group
     is_discuss = False if context['message_type'] == 'group' else True
     chat_uid = context['discuss_id'] if is_discuss else context['group_id']
     if not is_discuss:
         efb_chat.chat_uid = 'group' + '_' + str(chat_uid)
         i = self.channel.QQClient.get_group_info(chat_uid)
         if i is not None:
             efb_chat.chat_name = i[
                 'group_name'] if 'group_name' not in context else context[
                     'group_name']
         else:
             efb_chat.chat_name = chat_uid
         efb_chat.vendor_specific = {'is_discuss': False}
         # todo Add user to efb_chat.member
     else:
         efb_chat.chat_uid = 'discuss' + '_' + str(chat_uid)
         efb_chat.chat_name = 'Discuss Group' + '_' + str(chat_uid)
         # todo Find a way to distinguish from different discuss group
         efb_chat.vendor_specific = {'is_discuss': True}
     return efb_chat
Ejemplo n.º 7
0
 def build_efb_chat_as_user(self, context, is_chat):
     efb_chat = EFBChat(self.channel)
     uid = context['user_id']
     efb_chat.chat_uid = 'private' + '_' + str(uid)
     chat_name = ''
     if 'nickname' not in context:
         i: dict = self.channel.QQClient.get_stranger_info(uid)
         chat_name = i['nickname']
     else:
         chat_name = context['nickname']
     efb_chat.chat_name = chat_name
     efb_chat.chat_alias = None if 'alias' not in context else context[
         'alias']
     efb_chat.chat_type = ChatType.User
     efb_chat.is_chat = is_chat
     efb_chat.vendor_specific = {'is_anonymous': False}
     if not is_chat and context['message_type'] != 'private':
         efb_chat.group = self.build_efb_chat_as_group(context)
     return efb_chat
Ejemplo n.º 8
0
 def wechat_text_msg(self, msg: wxpy.Message) -> EFBMsg:
     if msg.chat.user_name == "newsapp" and msg.text.startswith("<mmreader>"):
         return self.wechat_newsapp_msg(msg)
     if msg.text.startswith("http://weixin.qq.com/cgi-bin/redirectforward?args="):
         return self.wechat_location_msg(msg)
     efb_msg = EFBMsg()
     efb_msg.text = ews_utils.wechat_string_unescape(msg.text)
     efb_msg.type = MsgType.Text
     if msg.is_at:
         found = False
         for i in re.finditer("@([^@]*)(?=\u2005|$)", msg.text):
             if i.groups()[0] in (self.bot.self.name, msg.chat.self.display_name):
                 found = True
                 efb_msg.substitutions = EFBMsgSubstitutions({
                     i.span(): EFBChat(self.channel).self()
                 })
         if not found:
             append = "@" + self.bot.self.name
             efb_msg.substitutions = EFBMsgSubstitutions({
                 (len(msg.text) + 1, len(msg.text) + 1 + len(append)): EFBChat(self.channel).self()
             })
             efb_msg.text += " " + append
     return efb_msg
Ejemplo n.º 9
0
    def exit_callback(self):
        # Don't send prompt if there's nowhere to send.
        if not getattr(coordinator, 'master', default=None):
            raise Exception(
                self.
                _("Web WeChat logged your account out before master channel is ready."
                  ))
        self.logger.debug('Calling exit callback...')
        if self._stop_polling_event.is_set():
            return
        msg = EFBMsg()
        chat = EFBChat(self).system()
        chat.chat_type = ChatType.System
        chat.chat_name = self._("EWS User Auth")
        msg.chat = msg.author = chat
        msg.deliver_to = coordinator.master
        msg.text = self._(
            "WeChat server has logged you out. Please log in again when you are ready."
        )
        msg.uid = "__reauth__.%s" % int(time.time())
        msg.type = MsgType.Text
        on_log_out = self.flag("on_log_out")
        on_log_out = on_log_out if on_log_out in ("command", "idle",
                                                  "reauth") else "command"
        if on_log_out == "command":
            msg.type = MsgType.Text
            msg.commands = EFBMsgCommands([
                EFBMsgCommand(name=self._("Log in again"),
                              callable_name="reauth",
                              kwargs={"command": True})
            ])
        elif on_log_out == "reauth":
            if self.flag("qr_reload") == "console_qr_code":
                msg.text += "\n" + self._("Please check your log to continue.")
            self.reauth()

        coordinator.send_message(msg)
Ejemplo n.º 10
0
 def wechat_system_msg(self, msg: wxpy.Message) -> Optional[EFBMsg]:
     if msg.recalled_message_id:
         efb_msg = EFBMsg()
         efb_msg.chat = self.channel.chats.wxpy_chat_to_efb_chat(msg.chat)
         efb_msg.author = self.channel.chats.wxpy_chat_to_efb_chat(msg.sender)
         efb_msg.uid = str(msg.recalled_message_id)
         coordinator.send_status(EFBMessageRemoval(source_channel=self.channel,
                                                   destination_channel=coordinator.master,
                                                   message=efb_msg))
         return None
     efb_msg = EFBMsg()
     efb_msg.text = msg.text
     efb_msg.type = MsgType.Text
     efb_msg.author = EFBChat(self.channel).system()
     return efb_msg
Ejemplo n.º 11
0
def test_pickle(slave_channel):
    chat = EFBChat(slave_channel)
    chat.chat_uid = "00001"
    chat.chat_name = "Chat"
    chat.chat_alias = "chaT"
    chat.chat_type = ChatType.User
    chat_dup = pickle.loads(pickle.dumps(chat))
    for attr in ("module_name", "module_id", "channel_emoji", "chat_name",
                 "chat_type", "chat_alias", "chat_uid", "is_chat"):
        assert getattr(chat, attr) == getattr(chat_dup, attr)
Ejemplo n.º 12
0
 def get_chat_from_db(self, channel_id: str,
                      chat_id: str) -> Optional[EFBChat]:
     d = self.db.get_slave_chat_info(slave_channel_id=channel_id,
                                     slave_chat_uid=chat_id)
     if d:
         chat = EFBChat(coordinator.slaves[channel_id])
         chat.chat_name = d.slave_chat_name
         chat.chat_alias = d.slave_chat_alias
         chat.chat_uid = d.slave_chat_uid
         chat.chat_type = ChatType(d.slave_chat_type)
         return chat
     else:
         chat = coordinator.slaves[channel_id].get_chat(chat_id)
         if chat:
             self._db_update_slave_chats_cache([chat])
             return chat
Ejemplo n.º 13
0
 def get_chat_from_db(self, channel_id: ModuleID,
                      chat_id: ChatID) -> Optional[EFBChat]:
     if channel_id not in coordinator.slaves:
         return None
     d = self.db.get_slave_chat_info(slave_channel_id=channel_id,
                                     slave_chat_uid=chat_id)
     if d:
         chat = EFBChat(coordinator.slaves[channel_id])
         chat.chat_name = d.slave_chat_name
         chat.chat_alias = d.slave_chat_alias
         chat.chat_uid = d.slave_chat_uid
         chat.chat_type = ChatType(d.slave_chat_type)
         return chat
     else:
         try:
             chat = coordinator.slaves[channel_id].get_chat(chat_id)
             if chat:
                 self._db_update_slave_chats_cache([chat])
                 return chat
             return None
         except EFBChatNotFound:
             return None
Ejemplo n.º 14
0
 def __init__(self):
     alice = EFBChat(self)
     alice.chat_name = "Alice"
     alice.chat_uid = "alice"
     alice.chat_type = ChatType.User
     bob = EFBChat(self)
     bob.chat_name = "Bob"
     bob.chat_alias = "Little bobby"
     bob.chat_uid = "bob"
     bob.chat_type = ChatType.User
     carol = EFBChat(self)
     carol.chat_name = "Carol"
     carol.chat_uid = "carol"
     carol.chat_type = ChatType.User
     dave = EFBChat(self)
     dave.chat_name = "デブ"  # Nah, that's a joke
     dave.chat_uid = "dave"
     dave.chat_type = ChatType.User
     wonderland = EFBChat(self)
     wonderland.chat_name = "Wonderland"
     wonderland.chat_uid = "wonderland001"
     wonderland.chat_type = ChatType.Group
     wonderland.members = [bob.copy(), carol.copy(), dave.copy()]
     for i in wonderland.members:
         i.group = wonderland
         i.is_chat = False
     self.chats: List[EFBChat] = [alice, bob, wonderland]
Ejemplo n.º 15
0
def test_generate_with_channel(slave_channel):
    chat = EFBChat(slave_channel)
    assert chat.module_id == slave_channel.channel_id
    assert chat.module_name == slave_channel.channel_name
    assert chat.channel_emoji == slave_channel.channel_emoji
Ejemplo n.º 16
0
def test_verify_missing_uid(slave_channel):
    chat = EFBChat(slave_channel)
    chat.chat_name = "Chat"
    chat.chat_type = ChatType.User
    with pytest.raises(ValueError):
        chat.verify()
Ejemplo n.º 17
0
def test_normal_chat():
    chat = EFBChat()
    assert not chat.is_self
    assert not chat.is_system
Ejemplo n.º 18
0
def test_is_self():
    chat = EFBChat().self()
    assert chat.is_self
Ejemplo n.º 19
0
def test_is_system():
    chat = EFBChat().system()
    assert chat.is_system
Ejemplo n.º 20
0
def test_generate_with_middleware(middleware):
    chat = EFBChat(middleware=middleware)
    assert chat.module_id == middleware.middleware_id
    assert chat.module_name == middleware.middleware_name
Ejemplo n.º 21
0
 def test_generate_with_channel(self):
     channel = MockMasterChannel()
     chat = EFBChat(channel)
     self.assertEqual(chat.channel_id, channel.channel_id)
     self.assertEqual(chat.channel_name, channel.channel_name)
     self.assertEqual(chat.channel_emoji, channel.channel_emoji)
Ejemplo n.º 22
0
    def process_telegram_message(self,
                                 bot: telegram.Bot,
                                 update: telegram.Update,
                                 channel_id: Optional[str] = None,
                                 chat_id: Optional[str] = None,
                                 target_msg: Optional[str] = None):
        """
        Process messages came from Telegram.

        Args:
            bot: Telegram bot
            update: Telegram message update
            channel_id: Slave channel ID if specified
            chat_id: Slave chat ID if specified
            target_msg: Target slave message if specified

        Returns:

        """
        target: Optional[str] = None
        target_channel: Optional[str] = None
        target_log: Optional['MsgLog'] = None
        # Message ID for logging
        message_id = utils.message_id_to_str(update=update)

        multi_slaves: bool = False
        destination: Optional[str] = None
        slave_msg: Optional[EFBMsg] = None

        message: telegram.Message = update.effective_message

        edited = bool(update.edited_message or update.edited_channel_post)
        self.logger.debug('[%s] Message is edited: %s, %s', message_id, edited,
                          message.edit_date)

        private_chat = update.effective_chat.type == telegram.Chat.PRIVATE

        if not private_chat:  # from group
            linked_chats = self.db.get_chat_assoc(
                master_uid=utils.chat_id_to_str(self.channel_id,
                                                update.effective_chat.id))
            if len(linked_chats) == 1:
                destination = linked_chats[0]
            elif len(linked_chats) > 1:
                multi_slaves = True

        reply_to = bool(getattr(message, "reply_to_message", None))

        # Process predefined target (slave) chat.
        if channel_id and chat_id:
            destination = utils.chat_id_to_str(channel_id, chat_id)
            if target_msg:
                target_log = self.db.get_msg_log(master_msg_id=target_msg)
                if target_log:
                    target = target_log.slave_origin_uid
                    target_channel, target_uid = utils.chat_id_str_to_id(
                        target)
                else:
                    self.logger.info(
                        "[%s], Predefined chat %d.%d with target msg")
                    return self.bot.reply_error(
                        update,
                        self._("Message is not found in database. "
                               "Please try with another message. (UC07)"))
        elif private_chat:
            if reply_to:
                dest_msg = self.db.get_msg_log(
                    master_msg_id=utils.message_id_to_str(
                        message.reply_to_message.chat.id,
                        message.reply_to_message.message_id))
                if dest_msg:
                    destination = dest_msg.slave_origin_uid
                else:
                    return self.bot.reply_error(
                        update,
                        self._("Message is not found in database. "
                               "Please try with another one. (UC03)"))
            else:
                return self.bot.reply_error(
                    update,
                    self._("Please reply to an incoming message. (UC04)"))
        else:  # group chat
            if multi_slaves:
                if reply_to:
                    dest_msg = self.db.get_msg_log(
                        master_msg_id=utils.message_id_to_str(
                            message.reply_to_message.chat.id,
                            message.reply_to_message.message_id))
                    if dest_msg:
                        destination = dest_msg.slave_origin_uid
                    else:
                        return self.bot.reply_error(
                            update,
                            self._("Message is not found in database. "
                                   "Please try with another one. (UC05)"))
                else:
                    return self.bot.reply_error(
                        update,
                        self.
                        _("This group is linked to multiple remote chats. "
                          "Please reply to an incoming message. "
                          "To unlink all remote chats, please send /unlink_all . (UC06)"
                          ))
            elif destination:
                if reply_to:
                    target_log = \
                        self.db.get_msg_log(master_msg_id=utils.message_id_to_str(
                            message.reply_to_message.chat.id,
                            message.reply_to_message.message_id))
                    if target_log:
                        target = target_log.slave_origin_uid
                        target_channel, target_uid = utils.chat_id_str_to_id(
                            target)
                    else:
                        return self.bot.reply_error(
                            update,
                            self._("Message is not found in database. "
                                   "Please try with another message. (UC07)"))
            else:
                return self.bot.reply_error(
                    update,
                    self._("This group is not linked to any chat. (UC06)"))

        self.logger.debug(
            "[%s] Telegram received. From private chat: %s; Group has multiple linked chats: %s; "
            "Message replied to another message: %s", message_id, private_chat,
            multi_slaves, reply_to)
        self.logger.debug("[%s] Destination chat = %s", message_id,
                          destination)
        channel, uid = utils.chat_id_str_to_id(destination)
        if channel not in coordinator.slaves:
            return self.bot.reply_error(
                update,
                self._("Internal error: Channel \"{0}\" not found.").format(
                    channel))

        m = EFBMsg()
        try:
            m.uid = message_id
            mtype = get_msg_type(message)
            # Chat and author related stuff
            m.author = EFBChat(self.channel).self()
            m.chat = EFBChat(coordinator.slaves[channel])
            m.chat.chat_uid = uid
            chat_info = self.db.get_slave_chat_info(channel, uid)
            if chat_info:
                m.chat.chat_name = chat_info.slave_chat_name
                m.chat.chat_alias = chat_info.slave_chat_alias
                m.chat.chat_type = ChatType(chat_info.slave_chat_type)
            m.deliver_to = coordinator.slaves[channel]
            if target and target_channel == channel:
                trgt_msg = EFBMsg()
                trgt_msg.type = MsgType.Text
                trgt_msg.text = target_log.text
                trgt_msg.uid = target_log.slave_message_id
                trgt_msg.chat = EFBChat(coordinator.slaves[target_channel])
                trgt_msg.chat.chat_name = target_log.slave_origin_display_name
                trgt_msg.chat.chat_alias = target_log.slave_origin_display_name
                trgt_msg.chat.chat_uid = utils.chat_id_str_to_id(
                    target_log.slave_origin_uid)[1]
                if target_log.slave_member_uid:
                    trgt_msg.author = EFBChat(
                        coordinator.slaves[target_channel])
                    trgt_msg.author.chat_name = target_log.slave_member_display_name
                    trgt_msg.author.chat_alias = target_log.slave_member_display_name
                    trgt_msg.author.chat_uid = target_log.slave_member_uid
                elif target_log.sent_to == 'master':
                    trgt_msg.author = trgt_msg.chat
                else:
                    trgt_msg.author = EFBChat(self.channel).self()
                m.target = trgt_msg

                self.logger.debug(
                    "[%s] This message replies to another message of the same channel.\n"
                    "Chat ID: %s; Message ID: %s.", message_id,
                    trgt_msg.chat.chat_uid, trgt_msg.uid)
            # Type specific stuff
            self.logger.debug("[%s] Message type from Telegram: %s",
                              message_id, mtype)

            if self.TYPE_DICT.get(mtype, None):
                m.type = self.TYPE_DICT[mtype]
                self.logger.debug("[%s] EFB message type: %s", message_id,
                                  mtype)
            else:
                self.logger.info(
                    "[%s] Message type %s is not supported by ETM", message_id,
                    mtype)
                raise EFBMessageTypeNotSupported(
                    "Message type %s is not supported by ETM" % mtype)

            if m.type not in coordinator.slaves[
                    channel].supported_message_types:
                self.logger.info(
                    "[%s] Message type %s is not supported by channel %s",
                    message_id, m.type.name, channel)
                raise EFBMessageTypeNotSupported(
                    "Message type %s is not supported by channel %s" %
                    (m.type, coordinator.slaves[channel].channel_name))

            # Parse message text and caption to markdown
            msg_md_text = message.text and message.text_markdown
            if msg_md_text and msg_md_text == escape_markdown(message.text):
                msg_md_text = message.text
            msg_md_text = msg_md_text or ""

            msg_md_caption = message.caption and message.caption_markdown
            if msg_md_caption and msg_md_caption == escape_markdown(
                    message.caption):
                msg_md_caption = message.caption
            msg_md_caption = msg_md_caption or ""

            # Flag for edited message
            if edited:
                m.edit = True
                text = msg_md_text or msg_md_caption
                msg_log = self.db.get_msg_log(
                    master_msg_id=utils.message_id_to_str(update=update))
                if not msg_log or msg_log == self.FAIL_FLAG:
                    raise EFBMessageNotFound()
                m.uid = msg_log.slave_message_id
                if text.startswith(self.DELETE_FLAG):
                    coordinator.send_status(
                        EFBMessageRemoval(
                            source_channel=self.channel,
                            destination_channel=coordinator.slaves[channel],
                            message=m))
                    self.db.delete_msg_log(
                        master_msg_id=utils.message_id_to_str(update=update))
                    m = None
                    return
                self.logger.debug('[%s] Message is edited (%s)', m.uid, m.edit)

            # Enclose message as an EFBMsg object by message type.
            if mtype == TGMsgType.Text:
                m.text = msg_md_text
            elif mtype == TGMsgType.Photo:
                m.text = msg_md_caption
                m.file, m.mime, m.filename, m.path = self._download_file(
                    message.photo[-1])
            elif mtype == TGMsgType.Sticker:
                # Convert WebP to the more common PNG
                m.text = ""
                m.file, m.mime, m.filename, m.path = self._download_file(
                    message.sticker, 'image/webp')
                self.logger.debug(
                    "[%s] Trying to convert WebP sticker (%s) to PNG.",
                    message_id, m.path)
                f = tempfile.NamedTemporaryFile(suffix=".png")
                Image.open(m.file).convert("RGBA").save(f, 'png')
                m.file.close()
                m.file, m.mime, m.filename, m.path = f, 'image/png', os.path.basename(
                    f.name), f.name
                self.logger.debug(
                    "[%s] WebP sticker is converted to PNG (%s).", message_id,
                    f.name)
            elif mtype == TGMsgType.Animation:
                m.text = ""
                self.logger.debug(
                    "[%s] Telegram message is a \"Telegram GIF\".", message_id)
                m.filename = getattr(message.document, "file_name",
                                     None) or None
                m.file, m.mime, m.filename, m.path = self._download_gif(
                    message.document, channel)
                m.mime = message.document.mime_type or m.mime
            elif mtype == TGMsgType.Document:
                m.text = msg_md_caption
                self.logger.debug("[%s] Telegram message type is document.",
                                  message_id)
                m.filename = getattr(message.document, "file_name",
                                     None) or None
                m.file, m.mime, filename, m.path = self._download_file(
                    message.document, message.document.mime_type)
                m.filename = m.filename or filename
                m.mime = message.document.mime_type or m.mime
            elif mtype == TGMsgType.Video:
                m.text = msg_md_caption
                m.file, m.mime, m.filename, m.path = self._download_file(
                    message.video, message.video.mime_type)
            elif mtype == TGMsgType.Audio:
                m.text = "%s - %s\n%s" % (message.audio.title,
                                          message.audio.performer,
                                          msg_md_caption)
                m.file, m.mime, m.filename, m.path = self._download_file(
                    message.audio, message.audio.mime_type)
            elif mtype == TGMsgType.Voice:
                m.text = msg_md_caption
                m.file, m.mime, m.filename, m.path = self._download_file(
                    message.voice, message.voice.mime_type)
            elif mtype == TGMsgType.Location:
                # TRANSLATORS: Message body text for location messages.
                m.text = self._("Location")
                m.attributes = EFBMsgLocationAttribute(
                    message.location.latitude, message.location.longitude)
            elif mtype == TGMsgType.Venue:
                m.text = message.location.title + "\n" + message.location.adderss
                m.attributes = EFBMsgLocationAttribute(
                    message.venue.location.latitude,
                    message.venue.location.longitude)
            elif mtype == TGMsgType.Contact:
                contact: telegram.Contact = message.contact
                m.text = self._(
                    "Shared a contact: {first_name} {last_name}\n{phone_number}"
                ).format(first_name=contact.first_name,
                         last_name=contact.last_name,
                         phone_number=contact.phone_number)
            else:
                raise EFBMessageTypeNotSupported(
                    self._("Message type {0} is not supported.").format(mtype))
                # return self.bot.reply_error(update, "Message type not supported. (MN02)")

            slave_msg = coordinator.send_message(m)
        except EFBChatNotFound as e:
            self.bot.reply_error(update, e.args[0]
                                 or self._("Chat is not found."))
        except EFBMessageTypeNotSupported as e:
            self.bot.reply_error(
                update, e.args[0] or self._("Message type is not supported."))
        except EFBOperationNotSupported as e:
            self.bot.reply_error(
                update,
                self._("Message editing is not supported.\n\n{!s}".format(e)))
        except Exception as e:
            self.bot.reply_error(
                update, self._("Message is not sent.\n\n{!r}".format(e)))
        finally:
            if m:
                msg_log_d = {
                    "master_msg_id":
                    utils.message_id_to_str(update=update),
                    "text":
                    m.text or "Sent a %s" % m.type,
                    "slave_origin_uid":
                    utils.chat_id_to_str(chat=m.chat),
                    "slave_origin_display_name":
                    "__chat__",
                    "msg_type":
                    m.type,
                    "sent_to":
                    "slave",
                    "slave_message_id":
                    None if m.edit else "%s.%s" %
                    (self.FAIL_FLAG, int(time.time())),
                    # Overwritten later if slave message ID exists
                    "update":
                    m.edit
                }

                # Store media related information to local database
                for tg_media_type in ('audio', 'animation', 'document',
                                      'video', 'voice', 'video_note'):
                    attachment = getattr(message, tg_media_type, None)
                    if attachment:
                        msg_log_d.update(media_type=tg_media_type,
                                         file_id=attachment.file_id,
                                         mime=attachment.mime_type)
                        break
                if not msg_log_d.get('media_type', None):
                    if getattr(message, 'sticker', None):
                        msg_log_d.update(media_type='sticker',
                                         file_id=message.sticker.file_id,
                                         mime='image/webp')
                    elif getattr(message, 'photo', None):
                        attachment = message.photo[-1]
                        msg_log_d.update(media_type=tg_media_type,
                                         file_id=attachment.file_id,
                                         mime='image/jpeg')

                if slave_msg:
                    msg_log_d['slave_message_id'] = slave_msg.uid
                self.db.add_msg_log(**msg_log_d)
                if m.file:
                    m.file.close()
Ejemplo n.º 23
0
        def handle_msg(context):
            self.logger.debug(repr(context))
            msg_element = context['message']
            main_text: str = ''
            messages = []
            qq_uid = context['user_id']
            at_list = {}
            for i in range(len(msg_element)):
                msg_type = msg_element[i]['type']
                msg_data = msg_element[i]['data']
                if msg_type == 'text':
                    main_text += msg_data['text']
                elif msg_type == 'face':
                    qq_face = int(msg_data['id'])
                    if qq_face in qq_emoji_list:
                        main_text += qq_emoji_list[qq_face]
                    else:
                        main_text += '\u2753'  # ❓
                elif msg_type == 'sface':
                    main_text += '\u2753'  # ❓
                elif msg_type == 'at':
                    # todo Recheck if bug exists
                    g_id = context['group_id']
                    my_uid = self.get_qq_uid()
                    self.logger.debug('My QQ uid: %s\n'
                                      'QQ mentioned: %s\n', my_uid, msg_data['qq'])
                    group_card = ''
                    if str(msg_data['qq']) == 'all':
                        group_card = 'all'
                    else:
                        member_info = self.coolq_api_query('get_group_member_info',
                                                           group_id=g_id,
                                                           user_id=msg_data['qq'])
                        group_card = member_info['card'] if member_info['card'] != '' else member_info['nickname']
                    self.logger.debug('Group card: {}'.format(group_card))
                    substitution_begin = 0
                    substitution_end = 0
                    if main_text == '':
                        substitution_begin = len(main_text)
                        substitution_end = len(main_text) + len(group_card) + 1
                        main_text += '@{} '.format(group_card)
                    else:
                        substitution_begin = len(main_text) + 1
                        substitution_end = len(main_text) + len(group_card) + 2
                        main_text += ' @{} '.format(group_card)
                    if str(my_uid) == str(msg_data['qq']) or str(msg_data['qq']) == 'all':
                        at_list[(substitution_begin, substitution_end)] = EFBChat(self.channel).self()
                else:
                    messages.extend(self.call_msg_decorator(msg_type, msg_data))
            if main_text != "":
                messages.append(self.msg_decorator.qq_text_simple_wrapper(main_text, at_list))
            uid: str = str(uuid.uuid4())
            coolq_msg_id = context['message_id']
            for i in range(len(messages)):
                if not isinstance(messages[i], EFBMsg):
                    continue
                efb_msg = messages[i]
                efb_msg.uid = uid + '_' + str(coolq_msg_id) + '_' + str(i)
                # if qq_uid != '80000000':
                if 'anonymous' not in context or context['anonymous'] is None:
                    remark = self.get_friend_remark(qq_uid)
                    if context['message_type'] == 'group':
                        if context['sub_type'] == 'notice':
                            context['event_description'] = self._("System Notification")
                            efb_msg.author = self.chat_manager.build_efb_chat_as_system_user(context)
                        else:
                            if remark is not None:
                                context['nickname'] = remark
                            g_id = context['group_id']
                            member_info = self.coolq_api_query('get_group_member_info',
                                                               group_id=g_id,
                                                               user_id=qq_uid)
                            if member_info is not None:
                                context['alias'] = member_info['card']
                            efb_msg.author: EFBChat = self.chat_manager.build_efb_chat_as_user(context, False)
                    else:
                        if context['message_type'] == 'private' or context['message_type'] == 'discuss':
                            context['alias'] = remark
                        efb_msg.author: EFBChat = self.chat_manager.build_efb_chat_as_user(context, False)
                else:  # anonymous user in group
                    efb_msg.author: EFBChat = self.chat_manager.build_efb_chat_as_anonymous_user(context)

                if context['message_type'] == 'private':
                    efb_msg.chat: EFBChat = self.chat_manager.build_efb_chat_as_user(context, True)
                else:
                    efb_msg.chat: EFBChat = self.chat_manager.build_efb_chat_as_group(context)

                # Append discuss group into group list
                if context['message_type'] == 'discuss' and efb_msg.chat not in self.discuss_list:
                    self.discuss_list.append(efb_msg.chat)

                efb_msg.deliver_to = coordinator.master

                def send_message_wrapper(*args, **kwargs):
                    threading.Thread(target=async_send_messages_to_master, args=args, kwargs=kwargs).start()

                send_message_wrapper(efb_msg)
    def wxpy_chat_to_efb_chat(self,
                              chat: wxpy.Chat,
                              recursive=True) -> EFBChat:
        # self.logger.debug("Converting WXPY chat %r, %sin recursive mode", chat, '' if recursive else 'not ')
        # self.logger.debug("WXPY chat with ID: %s, name: %s, alias: %s;", chat.puid, chat.nick_name, chat.alias)
        if chat is None:
            return self.MISSING_USER
        if chat.puid in self.efb_chat_objs:
            return self.efb_chat_objs[chat.puid]
        efb_chat = EFBChat(self.channel)
        efb_chat.chat_uid = chat.puid or "__invalid__"
        efb_chat.chat_name = ews_utils.wechat_string_unescape(chat.nick_name)
        efb_chat.chat_alias = None
        efb_chat.chat_type = ChatType.System
        efb_chat.vendor_specific = {'is_mp': False}
        if isinstance(chat, wxpy.Member):
            efb_chat.chat_type = ChatType.User
            efb_chat.is_chat = False
            efb_chat.chat_alias = chat.name
            # self.logger.debug("[WXPY: %s] Display name: %s;", chat.puid, chat.display_name)
            if recursive:
                efb_chat.group = self.wxpy_chat_to_efb_chat(chat.group, False)
        elif isinstance(chat, wxpy.Group):
            efb_chat.chat_type = ChatType.Group
            for i in chat.members:
                efb_chat.members.append(self.wxpy_chat_to_efb_chat(i, False))
                efb_chat.members[-1].group = efb_chat
        elif isinstance(chat, wxpy.MP):
            efb_chat.chat_type = ChatType.User
            efb_chat.vendor_specific['is_mp'] = True
        elif isinstance(chat, wxpy.User):
            efb_chat.chat_type = ChatType.User
            efb_chat.chat_alias = chat.remark_name or efb_chat.chat_alias
            # self.logger.debug("[WXPY: %s] Remark name: %s;", chat.puid, chat.remark_name)
        if chat == chat.bot.self:
            efb_chat.self()

        efb_chat.chat_alias = efb_chat.chat_alias and ews_utils.wechat_string_unescape(
            efb_chat.chat_alias)

        efb_chat.vendor_specific.update(self.generate_vendor_specific(chat))
        if efb_chat.vendor_specific.get('is_muted', False):
            efb_chat.notification = EFBChatNotificationState.MENTIONS

        # self.logger.debug('WXPY chat %s converted to EFBChat %s', chat.puid, efb_chat)

        if chat.puid:
            self.efb_chat_objs[chat.puid] = efb_chat

        return efb_chat
Ejemplo n.º 25
0
 def setUp(self):
     self.channel = MockMasterChannel()
     self.chat = EFBChat(self.channel)
     self.chat.chat_name = "Chat 0"
     self.chat.chat_uid = "0"
     self.chat.chat_type = ChatType.User
Ejemplo n.º 26
0
 def test_normal_chat(self):
     chat = EFBChat()
     self.assertFalse(chat.is_self)
     self.assertFalse(chat.is_system)
Ejemplo n.º 27
0
 def test_is_self(self):
     chat = EFBChat().self()
     self.assertTrue(chat.is_self)
Ejemplo n.º 28
0
 def test_is_system(self):
     chat = EFBChat().system()
     self.assertTrue(chat.is_system)
Ejemplo n.º 29
0
def patch_chat_1(slave_channel):
    mocked_chat = EFBChat(slave_channel).self()
    mocked_chat.verify = mock.Mock()
    return mocked_chat
Ejemplo n.º 30
0
Archivo: chats.py Proyecto: Z0-0Z/chat
    def wxpy_chat_to_efb_chat(self, chat: wxpy.Chat, recursive=True) -> Optional[EFBChat]:
        self.logger.debug("Converting WXPY chat %r, %sin recursive mode", chat, '' if recursive else 'not ')
        self.logger.debug("WXPY chat with ID: %s, name: %s, alias: %s;", chat.puid, chat.nick_name, chat.alias)
        if chat is None:
            return self.MISSING_USER
        efb_chat = EFBChat(self.channel)
        efb_chat.chat_uid = chat.puid or "__invalid__"
        efb_chat.chat_name = ews_utils.wechat_string_unescape(chat.nick_name)
        efb_chat.chat_alias = None
        efb_chat.chat_type = ChatType.System
        efb_chat.vendor_specific = {'is_mp': False,
                                    'wxpy_object': chat}
        if isinstance(chat, wxpy.Member):
            efb_chat.chat_type = ChatType.User
            efb_chat.is_chat = False
            efb_chat.chat_alias = chat.display_name or efb_chat.chat_alias
            self.logger.debug("[WXPY: %s] Display name: %s;", chat.puid, chat.display_name)
            if recursive:
                efb_chat.group = self.wxpy_chat_to_efb_chat(chat.group, False)
        elif isinstance(chat, wxpy.Group):
            efb_chat.chat_type = ChatType.Group
            for i in chat.members:
                efb_chat.members.append(self.wxpy_chat_to_efb_chat(i, False))
                efb_chat.members[-1].group = efb_chat
        elif isinstance(chat, wxpy.MP):
            efb_chat.chat_type = ChatType.User
            efb_chat.vendor_specific['is_mp'] = True
        elif isinstance(chat, wxpy.User):
            efb_chat.chat_type = ChatType.User
            efb_chat.chat_alias = chat.remark_name or efb_chat.chat_alias
            self.logger.debug("[WXPY: %s] Remark name: %s;", chat.puid, chat.remark_name)
        if chat == chat.bot.self:
            efb_chat.self()

        efb_chat.chat_alias = efb_chat.chat_alias and ews_utils.wechat_string_unescape(efb_chat.chat_alias)

        self.logger.debug('WXPY chat %s converted to EFBChat %s', chat.puid, efb_chat)
        return efb_chat