def test_verify_message_command(): msg = EFBMsg() msg.deliver_to = coordinator.master msg.author = patch_chat_0 msg.chat = patch_chat_1 msg.text = "Message" msg.verify() msg.type = MsgType.Text msg.attributes = None msg.commands = EFBMsgCommands([ EFBMsgCommand(name="Command 1", callable_name="command_1") ]) msg.commands.commands[0].verify = mock.Mock() msg.verify() msg.commands.commands[0].verify.assert_called_once()
def test_pickle_media_message(media_type): with NamedTemporaryFile() as f: msg = EFBMsg() msg.deliver_to = coordinator.master msg.author = chat msg.chat = chat msg.type = media_type msg.file = f msg.filename = "test.bin" msg.path = f.name msg.mime = "application/octet-stream" msg.uid = "message_id" msg.verify() msg_dup = pickle.loads(pickle.dumps(msg)) for attr in ("deliver_to", "author", "chat", "type", "chat", "filename", "path", "mime", "text", "uid"): assert getattr(msg, attr) == getattr(msg_dup, attr)
def test_verify_status_message(): msg = EFBMsg() msg.deliver_to = coordinator.master msg.author = patch_chat_0 msg.chat = patch_chat_1 msg.text = "Message" msg.verify() msg.type = MsgType.Status msg.attributes = EFBMsgStatusAttribute(status_type=EFBMsgStatusAttribute.Types.TYPING) msg.attributes.verify = mock.Mock() msg.verify() msg.attributes.verify.assert_called_once()
def test_verify_location_message(): msg = EFBMsg() msg.deliver_to = coordinator.master msg.author = patch_chat_0 msg.chat = patch_chat_1 msg.text = "Message" msg.verify() msg.type = MsgType.Location msg.attributes = EFBMsgLocationAttribute(latitude=0.0, longitude=0.0) msg.attributes.verify = mock.Mock() msg.verify() msg.attributes.verify.assert_called_once()
def test_verify_link_message(): msg = EFBMsg() msg.deliver_to = coordinator.master msg.author = patch_chat_0 msg.chat = patch_chat_1 msg.text = "Message" msg.verify() msg.type = MsgType.Link msg.attributes = EFBMsgLinkAttribute(title='Title', url='URL') msg.attributes.verify = mock.Mock() msg.verify() msg.attributes.verify.assert_called_once()
def send_message(self, msg: EFBMsg) -> EFBMsg: """Send a message to WeChat. Supports text, image, sticker, and file. Args: msg (channel.EFBMsg): Message Object to be sent. Returns: This method returns nothing. Raises: EFBMessageTypeNotSupported: Raised when message type is not supported by the channel. """ chat: wxpy.Chat = self.chats.get_wxpy_chat_by_uid(msg.chat.chat_uid) r = None self.logger.info( "[%s] Sending message to WeChat:\n" "uid: %s\n" "UserName: %s\n" "NickName: %s\n" "Type: %s\n" "Text: %s", msg.uid, msg.chat.chat_uid, chat.user_name, chat.name, msg.type, msg.text) self.logger.debug('[%s] Is edited: %s', msg.uid, msg.edit) if msg.edit: if self.flag('delete_on_edit'): try: ews_utils.message_to_dummy_message(msg.uid, self).recall() except wxpy.ResponseError as e: self.logger.error( "[%s] Trying to recall message but failed: %s", msg.uid, e) raise EFBMessageError( self. _('Failed to recall message, edited message was not sent.' )) else: raise EFBOperationNotSupported() if msg.type in [MsgType.Text, MsgType.Link]: if isinstance(msg.target, EFBMsg): max_length = self.flag("max_quote_length") qt_txt = "%s" % msg.target.text if max_length > 0: tgt_text = qt_txt[:max_length] if len(qt_txt) >= max_length: tgt_text += "…" tgt_text = "「%s」" % tgt_text elif max_length < 0: tgt_text = "「%s」" % qt_txt else: tgt_text = "" if isinstance(chat, wxpy.Group) and not msg.target.author.is_self: tgt_alias = "@%s\u2005 " % msg.target.author.chat_alias else: tgt_alias = "" msg.text = "%s%s\n\n%s" % (tgt_alias, tgt_text, msg.text) r: wxpy.SentMessage = self._bot_send_msg(chat, msg.text) self.logger.debug('[%s] Sent as a text message. %s', msg.uid, msg.text) elif msg.type in (MsgType.Image, MsgType.Sticker): self.logger.info("[%s] Image/Sticker %s", msg.uid, msg.type) if msg.type != MsgType.Sticker: if os.fstat(msg.file.fileno()).st_size > self.MAX_FILE_SIZE: raise EFBMessageError( self._("Image size is too large. (IS01)")) self.logger.debug("[%s] Sending %s (image) to WeChat.", msg.uid, msg.path) r: wxpy.SentMessage = self._bot_send_image( chat, msg.path, msg.file) msg.file.close() else: # Convert Image format with NamedTemporaryFile(suffix=".gif") as f: img = Image.open(msg.file) try: alpha = img.split()[3] mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0) except IndexError: mask = Image.eval(img.split()[0], lambda a: 0) img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255) img.paste(255, mask) img.save(f, transparency=255) msg.path = f.name self.logger.debug('[%s] Image converted from %s to GIF', msg.uid, msg.mime) msg.file.close() f.seek(0) if os.fstat(f.fileno()).st_size > self.MAX_FILE_SIZE: raise EFBMessageError( self._("Image size is too large. (IS02)")) r: wxpy.SentMessage = self._bot_send_image(chat, f.name, f) if msg.text: self._bot_send_msg(chat, msg.text) elif msg.type in (MsgType.File, MsgType.Audio): self.logger.info( "[%s] Sending %s to WeChat\nFileName: %s\nPath: %s\nFilename: %s", msg.uid, msg.type, msg.text, msg.path, msg.filename) r = self._bot_send_file(chat, msg.filename, file=msg.file) if msg.text: self._bot_send_msg(chat, msg.text) msg.file.close() elif msg.type == MsgType.Video: self.logger.info( "[%s] Sending video to WeChat\nFileName: %s\nPath: %s", msg.uid, msg.text, msg.path) r = self._bot_send_video(chat, msg.path, file=msg.file) if msg.text: self._bot_send_msg(chat, msg.text) msg.file.close() else: raise EFBMessageTypeNotSupported() msg.uid = ews_utils.generate_message_uid(r) self.logger.debug('WeChat message is assigned with unique ID: %s', msg.uid) return msg
def master_qr_code(self, uuid, status, qrcode=None): status = int(status) msg = EFBMsg() msg.type = MsgType.Text msg.chat = EFBChat(self).system() msg.chat.chat_name = self._("EWS User Auth") msg.author = msg.chat msg.deliver_to = coordinator.master if status == 201: msg.type = MsgType.Text msg.text = self._('Confirm on your phone.') elif status == 200: msg.type = MsgType.Text msg.text = self._("Successfully logged in.") elif uuid != self.qr_uuid: msg.type = MsgType.Image # path = os.path.join("storage", self.channel_id) # if not os.path.exists(path): # os.makedirs(path) # path = os.path.join(path, 'QR-%s.jpg' % int(time.time())) # self.logger.debug("master_qr_code file path: %s", path) file = NamedTemporaryFile(suffix=".png") qr_url = "https://login.weixin.qq.com/l/" + uuid QRCode(qr_url).png(file, scale=10) msg.text = self._("QR code expired, please scan the new one.") msg.path = file.name msg.file = file msg.mime = 'image/png' if status in (200, 201) or uuid != self.qr_uuid: coordinator.send_message(msg) self.qr_uuid = uuid