def wechat_raw_link_msg(self,
                            msg: wxpy.Message,
                            title: str,
                            description: str,
                            image: str,
                            url: str,
                            suffix: str = "") -> Message:

        if url:
            efb_msg = Message(type=MsgType.Link,
                              text=suffix,
                              attributes=LinkAttribute(title=title,
                                                       description=description,
                                                       image=image,
                                                       url=url))
        else:
            efb_msg = Message(
                type=MsgType.Text,
                text=f"{title}\n{description}",
            )
            if suffix:
                efb_msg.text += f"\n{suffix}"
            if image:
                efb_msg.text += f"\n\n{image}"
        return efb_msg
示例#2
0
 def qq_location_wrapper(self, data, chat: Chat = None):
     efb_msg = Message(text=data['content'],
                       type=MsgType.Location,
                       attributes=LocationAttribute(
                           longitude=float(data['lon']),
                           latitude=float(data['lat'])))
     return [efb_msg]
示例#3
0
    def send_text_message(self,
                          chat: Chat,
                          author: Optional[ChatMember] = None,
                          target: Optional[Message] = None,
                          reactions: bool = False,
                          commands: bool = False,
                          substitution: bool = False,
                          unsupported: bool = False) -> Message:
        """Send a text message to master channel.
        Leave author blank to use “self” of the chat.

        Returns the message sent.
        """
        author = author or chat.self
        uid = f"__msg_id_{uuid4()}__"
        msg_type = MsgType.Unsupported if unsupported else MsgType.Text
        message = Message(
            chat=chat,
            author=author,
            type=msg_type,
            target=target,
            uid=uid,
            text=f"Content of {msg_type.name} message with ID {uid}",
            deliver_to=coordinator.master)
        message = self.attach_message_properties(message, reactions, commands,
                                                 substitution)

        coordinator.send_message(message)
        self.messages_sent[uid] = message

        return message
示例#4
0
 def send_file_like_message(self,
                            msg_type: MsgType,
                            file_path: Path,
                            mime: str,
                            chat: Chat,
                            author: Optional[ChatMember] = None,
                            target: Optional[Message] = None,
                            reactions: bool = False,
                            commands: bool = False,
                            substitution: bool = False) -> Message:
     author = author or chat.self
     uid = f"__msg_id_{uuid4()}__"
     message = Message(
         chat=chat,
         author=author,
         type=msg_type,
         target=target,
         uid=uid,
         file=file_path.open('rb'),
         filename=file_path.name,
         path=file_path,
         mime=mime,
         text=f"Content of {msg_type.name} message with ID {uid}",
         deliver_to=coordinator.master)
     message = self.attach_message_properties(message, reactions, commands,
                                              substitution)
     self.messages_sent[uid] = message
     coordinator.send_message(message)
     return message
示例#5
0
    def exit_callback(self):
        # Don't send prompt if there's nowhere to send.
        if not getattr(coordinator, 'master', 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 = Message(
            chat=self.user_auth_chat,
            author=self.user_auth_chat.other,
            deliver_to=coordinator.master,
            text=self._(
                "WeChat server has logged you out. Please log in again when you are ready."),
            uid=f"__reauth__.{uuid4()}",
            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 = MessageCommands(
                [MessageCommand(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)
 def wechat_location_msg(self, msg: wxpy.Message) -> Message:
     efb_msg = Message()
     efb_msg.text = msg.text.split('\n')[0][:-1]
     efb_msg.attributes = LocationAttribute(latitude=float(msg.location['x']),
                                            longitude=float(msg.location['y']))
     efb_msg.type = MsgType.Location
     return efb_msg
示例#7
0
    def send_status_message(self,
                            status: StatusAttribute,
                            chat: Chat,
                            author: Optional[ChatMember] = None,
                            target: Optional[Message] = None) -> Message:
        """Send a status message to master channel.
        Leave author blank to use “self” of the chat.

        Returns the message sent.
        """
        author = author or chat.self
        uid = f"__msg_id_{uuid4()}__"
        message = Message(chat=chat,
                          author=author,
                          type=MsgType.Status,
                          target=target,
                          uid=uid,
                          text="",
                          attributes=status,
                          deliver_to=coordinator.master)

        coordinator.send_message(message)
        self.messages_sent[uid] = message

        return message
示例#8
0
 def send_link_message(self,
                       chat: Chat,
                       author: Optional[ChatMember] = None,
                       target: Optional[Message] = None,
                       reactions: bool = False,
                       commands: bool = False,
                       substitution: bool = False) -> Message:
     author = author or chat.self
     uid = f"__msg_id_{uuid4()}__"
     message = Message(chat=chat,
                       author=author,
                       type=MsgType.Link,
                       target=target,
                       uid=uid,
                       text=f"Content of link message with ID {uid}",
                       attributes=LinkAttribute(
                           title="EH Forwarder Bot",
                           description="EH Forwarder Bot project site.",
                           url="https://efb.1a23.studio"),
                       deliver_to=coordinator.master)
     message = self.attach_message_properties(message, reactions, commands,
                                              substitution)
     self.messages_sent[uid] = message
     coordinator.send_message(message)
     return message
 def wechat_text_msg(self, msg: wxpy.Message) -> Optional[Message]:
     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)
     chat, author = self.get_chat_and_author(msg)
     if self.channel.flag("text_post_processing"):
         text = ews_utils.wechat_string_unescape(msg.text)
     else:
         text = msg.text or ""
     efb_msg = Message(
         chat=chat, author=author,
         text=text,
         type=MsgType.Text
     )
     if msg.is_at and chat.self:
         found = False
         for i in re.finditer(r"@([^@\s]*)(?=\u2005|$|\s)", msg.text):
             if i.groups()[0] in (self.bot.self.name, msg.chat.self.display_name):
                 found = True
                 efb_msg.substitutions = Substitutions({
                     i.span(): chat.self
                 })
         if not found:
             append = "@" + self.bot.self.name
             efb_msg.substitutions = Substitutions({
                 (len(msg.text) + 1, len(msg.text) + 1 + len(append)): chat.self
             })
             efb_msg.text += " " + append
     return efb_msg
 def wechat_system_msg(self, msg: wxpy.Message) -> Optional[Message]:
     if msg.recalled_message_id:
         recall_id = str(msg.recalled_message_id)
         # check conversion table first
         if recall_id in self.recall_msg_id_conversion:
             # prevent feedback of messages deleted by master channel.
             del self.recall_msg_id_conversion[recall_id]
             return None
             # val = self.recall_msg_id_conversion.pop(recall_id)
             # val[1] -= 1
             # if val[1] > 0:  # not all associated messages are recalled.
             #     return None
             # else:
             #     efb_msg.uid = val[0]
         else:
             # Format message IDs as JSON of List[List[str]].
             chat, author = self.get_chat_and_author(msg)
             efb_msg = Message(
                 chat=chat, author=author,
                 uid=MessageID(json.dumps([[recall_id]]))
             )
         coordinator.send_status(MessageRemoval(source_channel=self.channel,
                                                destination_channel=coordinator.master,
                                                message=efb_msg))
         return None
     chat, _ = self.get_chat_and_author(msg)
     try:
         author = chat.get_member(SystemChatMember.SYSTEM_ID)
     except KeyError:
         author = chat.add_system_member()
     if any(i in msg.text for i in self.NEW_CHAT_PATTERNS):
         coordinator.send_status(ChatUpdates(
             channel=self.channel,
             new_chats=(chat.uid,)
         ))
     elif any(i in msg.text for i in self.CHAT_AND_MEMBER_UPDATE_PATTERNS):
         # TODO: detect actual member changes from message text
         coordinator.send_status(ChatUpdates(
             channel=self.channel,
             modified_chats=(chat.uid,)
         ))
     return Message(
         text=msg.text,
         type=MsgType.Text,
         chat=chat,
         author=author,
     )
 def wechat_shared_image_msg(self, msg: wxpy.Message, source: str, text: str = "", mode: str = "image") -> Message:
     efb_msg = Message()
     efb_msg.type = MsgType.Image
     efb_msg.text = self._("Via {source}").format(source=source)
     if text:
         efb_msg.text = "%s\n%s" % (text, efb_msg.text)
     efb_msg.path, efb_msg.mime, efb_msg.file = self.save_file(msg, app_message=mode)
     return efb_msg
 def qq_text_simple_wrapper(self, text: str, ats: dict):  # This cute function only accepts string!
     efb_msg = Message()
     efb_msg.type = MsgType.Text
     efb_msg.text = text
     if ats:  # This is used to replace specific text with @blahblah
         # And Milkice really requires a brain check
         efb_msg.substitutions = Substitutions(ats)
     return efb_msg
 def qq_contact_wrapper(self, data, chat: Chat = None):
     uid = data['id']
     contact_type = data['type']
     efb_msg = Message(
         type=MsgType.Text,
         text=self._("Chat Recommendation Received\nID: {}\nType: {}").format(uid, contact_type)
     )
     return [efb_msg]
 def qq_sign_wrapper(self, data, chat: Chat = None):
     location = self._('at {}').format(data['location']) if 'location' in data else self._('at Unknown Place')
     title = '' if 'title' not in data else (self._('with title {}').format(data['title']))
     efb_msg = Message(
         type=MsgType.Text,
         text=self._('signed in {location} {title}').format(title=title,
                                                            location=location)
     )
     return [efb_msg]
示例#15
0
    def make_status_message(self,
                            msg_base: Message = None,
                            mid: MessageID = None) -> Message:
        if mid is not None:
            msg = self.message_cache[mid]
        elif msg_base is not None:
            msg = msg_base
        else:
            raise ValueError

        reply = Message(
            type=MsgType.Text,
            chat=msg.chat,
            author=msg.chat.make_system_member(uid=ChatID("filter_info"),
                                               name="Filter middleware",
                                               middleware=self),
            deliver_to=coordinator.master,
        )

        if mid:
            reply.uid = mid
        else:
            reply.uid = str(uuid.uuid4())

        status = self.filter_reason(msg)
        if not status:
            # Blue circle emoji
            status = "\U0001F535 This chat is not filtered."
        else:
            # Red circle emoji
            status = "\U0001F534 " + status

        reply.text = "Filter status for chat {chat_id} from {module_id}:\n" \
                     "\n" \
                     "{status}\n".format(
            module_id=msg.chat.module_id,
            chat_id=msg.chat.id,
            status=status
        )

        command = MessageCommand(name="%COMMAND_NAME%",
                                 callable_name="toggle_filter_by_chat_id",
                                 kwargs={
                                     "mid": reply.uid,
                                     "module_id": msg.chat.module_id,
                                     "chat_id": msg.chat.id
                                 })

        if self.is_chat_filtered_by_id(msg.chat):
            command.name = "Unfilter by chat ID"
            command.kwargs['value'] = False
        else:
            command.name = "Filter by chat ID"
            command.kwargs['value'] = True
        reply.commands = MessageCommands([command])

        return reply
示例#16
0
def base_message(chat, master_channel):
    msg = Message(
        deliver_to=master_channel,
        author=chat.other,
        chat=chat,
        text="Message",
        uid="0",
    )
    return msg
示例#17
0
def test_verify_missing_chat(chat):
    with pytest.raises(AssertionError):
        msg = Message(
            deliver_to=coordinator.master,
            author=chat.other,
            type=MsgType.Text,
            text="Message",
        )
        msg.verify()
 def wechat_voice_msg(self, msg: wxpy.Message) -> Message:
     efb_msg = Message(type=MsgType.Voice)
     try:
         efb_msg.path, efb_msg.mime, efb_msg.file = self.save_file(msg)
         efb_msg.text = ""
     except EOFError:
         efb_msg.type = MsgType.Text
         efb_msg.text += self._("[Failed to download the voice message, please check your phone.]")
     return efb_msg
 def qq_music_wrapper(self, data, chat: Chat = None):
     efb_msg = Message()
     if data['type'] == '163':  # Netease Cloud Music
         efb_msg.type = MsgType.Text
         efb_msg.text = 'https://music.163.com/#/song?id=' + data['id']
     else:
         efb_msg.type = MsgType.Text
         efb_msg.text = data['text']
     return [efb_msg]  # todo Port for other music platform
示例#20
0
def test_verify_missing_author(chat, master_channel):
    with pytest.raises(AssertionError):
        msg = Message(
            deliver_to=master_channel,
            chat=chat,
            type=MsgType.Text,
            text="Message",
        )
        msg.verify()
示例#21
0
def test_verify_text_msg(chat):
    msg = Message(
        deliver_to=coordinator.master,
        author=chat.other,
        chat=chat,
        type=MsgType.Text,
        text="Message",
    )
    msg.verify()
示例#22
0
def test_verify_missing_deliver_to(chat):
    msg = Message(
        author=chat.other,
        chat=chat,
        type=MsgType.Text,
        text="Message",
    )
    with pytest.raises(AssertionError):
        msg.verify()
 def wechat_system_unsupported_msg(self, msg: wxpy.Message) -> Optional[Message]:
     if msg.raw['MsgType'] in (50, 52, 53):
         text = self._("[Incoming audio/video call, please check your phone.]")
     else:
         return None
     efb_msg = Message(
         text=text,
         type=MsgType.Unsupported,
     )
     return efb_msg
示例#24
0
 def qq_share_wrapper(self, data, chat: Chat = None):
     efb_msg = Message(
         type=MsgType.Link,
         text='',
         attributes=LinkAttribute(
             title='' if 'title' not in data else data['title'],
             description='' if 'content' not in data else data['content'],
             image='' if 'image' not in data else data['image'],
             url=data['url']))
     return [efb_msg]
示例#25
0
 def send_message_recall_status(self):
     slave = next(iter(coordinator.slaves.values()))
     alice = slave.get_chat('alice')
     msg = Message(
         deliver_to=slave,
         chat=alice,
         author=alice.self,
         uid="1"
     )
     status = MessageRemoval(self, slave, msg)
     return coordinator.send_status(status)
 def qq_file_after_wrapper(self, data):
     efb_msg = Message()
     efb_msg.file = data['file']
     efb_msg.type = MsgType.File
     mime = magic.from_file(efb_msg.file.name, mime=True)
     if isinstance(mime, bytes):
         mime = mime.decode()
     efb_msg.path = efb_msg.file.name
     efb_msg.mime = mime
     efb_msg.filename = quote(data['filename'])
     return efb_msg
示例#27
0
 def send_text_msg(self):
     slave = next(iter(coordinator.slaves.values()))
     wonderland = slave.get_chat('wonderland001')
     msg = Message(
         deliver_to=slave,
         chat=wonderland,
         author=wonderland.self,
         type=MsgType.Text,
         text="Hello, world.",
     )
     return coordinator.send_message(msg)
示例#28
0
def test_verify_different_author_and_chat(patch_chat, patch_chat_member, master_channel):
    msg = Message(
        chat=patch_chat,
        author=patch_chat_member,
        text="Message",
        deliver_to=master_channel
    )
    msg.verify()

    patch_chat.verify.assert_called_once()
    patch_chat_member.verify.assert_called_once()
示例#29
0
def test_pickle_message_removal(slave_channel, master_channel):
    msg = Message()
    msg.chat = slave_channel.alice
    msg.uid = "uid"
    msg_removal = MessageRemoval(source_channel=master_channel,
                                 destination_channel=slave_channel,
                                 message=msg)
    msg_removal_dup = pickle.loads(pickle.dumps(msg_removal))

    # Assume Message is picklable
    for i in ("source_channel", "destination_channel"):
        assert getattr(msg_removal, i) == getattr(msg_removal_dup, i)
 def wechat_video_msg(self, msg: wxpy.Message) -> Message:
     efb_msg = Message(type=MsgType.Video)
     try:
         if msg.file_size == 0:
             raise EOFError
         efb_msg.path, efb_msg.mime, efb_msg.file = self.save_file(msg)
         efb_msg.filename = msg.file_name
         efb_msg.text = ""
     except EOFError:
         efb_msg.type = MsgType.Text
         efb_msg.text += self._("[Failed to download the video message, please check your phone.]")
     return efb_msg