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
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
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 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 wechat_sticker_msg(self, msg: wxpy.Message) -> Message: efb_msg = Message(type=MsgType.Sticker) try: if msg.raw['MsgType'] == 47 and not msg.raw['Content']: raise EOFError 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 # ^ Also throws EOFError if 'gif' in efb_msg.mime and Image.open(efb_msg.path).is_animated: efb_msg.type = MsgType.Animation efb_msg.text = "" except EOFError: efb_msg.text += self._("[Failed to download the sticker, please check your phone.]") efb_msg.type = MsgType.Unsupported return efb_msg
def qq_record_wrapper(self, data, chat: Chat = None): # Experimental! efb_msg = Message() try: transformed_file = self.inst.coolq_api_query("get_record", file=data['file'], out_format='mp3') efb_msg.type = MsgType.Audio efb_msg.file = download_voice(transformed_file['file'], self.inst.client_config['api_root'].rstrip("/"), self.inst.client_config['access_token']) 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 except Exception: efb_msg.type = MsgType.Unsupported efb_msg.text = self._('[Voice Message] Please check it on your QQ') logging.getLogger(__name__).exception("Failed to download voice") return [efb_msg]
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
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
def master_qr_code(self, uuid, status, qrcode=None): status = int(status) if self.qr_uuid == (uuid, status): return self.qr_uuid = (uuid, status) msg = Message( uid=f"ews_auth_{uuid}_{status}_{uuid4()}", type=MsgType.Text, chat=self.user_auth_chat, author=self.user_auth_chat.other, deliver_to=coordinator.master, ) if status == 201: msg.type = MsgType.Text msg.text = self._('Confirm on your phone.') self.master_qr_picture_id = None elif status == 200: msg.type = MsgType.Text msg.text = self._("Successfully logged in.") self.master_qr_picture_id = None elif uuid != self.qr_uuid: msg.type = MsgType.Image 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 = Path(file.name) msg.file = file msg.mime = 'image/png' if self.master_qr_picture_id is not None: msg.edit = True msg.edit_media = True msg.uid = self.master_qr_picture_id else: self.master_qr_picture_id = msg.uid if status in (200, 201) or uuid != self.qr_uuid: coordinator.send_message(msg)
def wechat_file_msg(self, msg: wxpy.Message) -> Message: efb_msg = Message(type=MsgType.File) try: file_name = msg.file_name efb_msg.text = file_name or "" app_name = msg.app_name if app_name: efb_msg.text = self._("{file_name} sent via {app_name}").format(file_name=file_name, app_name=app_name) efb_msg.filename = file_name or "" efb_msg.path, efb_msg.mime, efb_msg.file = self.save_file(msg) except EOFError: efb_msg.type = MsgType.Text efb_msg.text += self._("[Failed to download the file, please check your phone.]") return efb_msg
def qq_image_wrapper(self, data, chat: Chat = None): efb_msg = Message() if 'url' not in data: efb_msg.type = MsgType.Text efb_msg.text = self._('[Image Source missing]') return [efb_msg] efb_msg.file = cq_get_image(data['url']) if efb_msg.file is None: efb_msg.type = MsgType.Text efb_msg.text = self._('[Download image failed, please check on your QQ client]') return [efb_msg] efb_msg.type = MsgType.Image mime = magic.from_file(efb_msg.file.name, mime=True) if isinstance(mime, bytes): mime = mime.decode() efb_msg.filename = data['file'] if 'file' in data else efb_msg.file.name efb_msg.filename += '.' + str(mime).split('/')[1] efb_msg.path = efb_msg.file.name efb_msg.mime = mime if "gif" in mime: efb_msg.type = MsgType.Animation return [efb_msg]
def wechat_picture_msg(self, msg: wxpy.Message) -> Message: efb_msg = Message(type=MsgType.Image) try: if msg.raw['MsgType'] == 47 and not msg.raw['Content']: raise EOFError 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 # ^ Also throws EOFError efb_msg.text = "" except EOFError: efb_msg.text += self._("[Failed to download the picture, please check your phone.]") efb_msg.type = MsgType.Unsupported return efb_msg
def reply_message(self, message: Message, text: str): reply = Message() reply.text = text # reply.chat = coordinator.slaves[message.chat.channel_id].get_chat(message.chat.chat_uid) reply.chat = coordinator.slaves[message.chat.module_id].get_chat( message.chat.uid) reply.author = message.chat.make_system_member( uid=self.middleware_id, name=self.middleware_name, middleware=self) reply.type = MsgType.Text # reply.deliver_to = coordinator.master reply.deliver_to = coordinator.slaves[message.chat.module_id] # reply.target = message reply.uid = str(uuid.uuid4()) r2 = reply coordinator.send_message(reply) r2.deliver_to = coordinator.master coordinator.send_message(r2)
def reply_message_img(self, message: Message, im3: Image.Image): reply = Message() # reply.text = text # reply.chat = coordinator.slaves[message.chat.channel_id].get_chat(message.chat.chat_uid) reply.chat = coordinator.slaves[message.chat.module_id].get_chat( message.chat.uid) reply.author = message.chat.make_system_member( uid=self.middleware_id, name=self.middleware_name, middleware=self) reply.type = MsgType.Image reply.mime = 'image/png' f = tempfile.NamedTemporaryFile(suffix='.png') img_data = io.BytesIO() im3.save(img_data, format='png') f.write(img_data.getvalue()) f.file.seek(0) reply.file = f reply.path = f.name reply.filename = os.path.basename(reply.file.name) # reply.deliver_to = coordinator.master reply.deliver_to = coordinator.slaves[message.chat.module_id] # reply.target = message reply.uid = str(uuid.uuid4()) r2 = reply coordinator.send_message(reply) r2.type = MsgType.Image r2.mime = 'image/png' f = tempfile.NamedTemporaryFile(suffix='.png') img_data = io.BytesIO() im3.save(img_data, format='png') f.write(img_data.getvalue()) f.file.seek(0) r2.file = f r2.path = f.name r2.filename = os.path.basename(r2.file.name) r2.deliver_to = coordinator.master coordinator.send_message(r2)
def process_message(self, message: Message) -> Optional[Message]: """ Process a message with middleware Args: message (:obj:`.Message`): Message object to process Returns: Optional[:obj:`.Message`]: Processed message or None if discarded. """ if not self.sent_by_master(message): return message msg_text = message.text if msg_text.startswith('\\np '): message.text = msg_text[3:] return message # re_url = r'https?:\/\/\S+' # taken from django https://github.com/django/django/blob/master/django/core/validators.py#L68 valid_url = re.compile( r'(https?://)?' # scheme is validated separately r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}(?<!-)\.?)|' # domain... r'localhost|' # localhost... r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4 r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6 r'(?::\d+)?' # optional port r'(?:[/?]\S+|[/?])?', re.IGNORECASE) url = valid_url.search(msg_text) if not url: return message url = url.group(0) try: lp = LinkPreview(url) title = lp.title desc = lp.desc except Exception as e: self.logger.error("Failed to get link preview: {}".format(e)) return message text = msg_text if title or desc: text = '\n'.join([ msg_text, 'preview'.center(23, '='), title.center(23), '-' * 27, str(desc), ]) if lp.type.startswith('image') and lp.image: suffix = os.path.splitext(lp.image_url)[1] message.file = NamedTemporaryFile(suffix=suffix) message.filename = os.path.basename(message.file.name) message.file.write(lp.image) message.file.file.seek(0) message.type = MsgType.Image message.mime = lp.type message.path = message.file.name message.text = text return message
def handle_tg_img_preview(self, message: Message): if not message or not message.file or not message.filename: return if message.author.uid == self.middleware_id: # trysh-middleware # self.lg('self') return if message.type != MsgType.Image: return try: message.file.seek(0) fbs = message.file.read() message.file.seek(0) im: Image.Image = Image.open(io.BytesIO(fbs)) max_size = max(im.size) min_size = min(im.size) img_ratio = max_size / min_size if img_ratio < 10.0: return im2 = im.copy() for _ in range(100): max_size = max(im.size) min_size = min(im.size) img_ratio = max_size / min_size if img_ratio >= 10.0: if im.width == min_size: im = im.resize((im.width * 2, im.height), box=(0, 0, 1, 1)) else: im = im.resize((im.width, im.height * 2), box=(0, 0, 1, 1)) continue else: break im.paste(im2, (0, 0, im2.width, im2.height)) im3 = im.convert('RGB') # im.copy() # reply = Message() # reply.text = text # reply.chat = coordinator.slaves[message.chat.channel_id].get_chat(message.chat.chat_uid) reply.chat = coordinator.slaves[message.chat.module_id].get_chat( message.chat.uid) reply.author = message.chat.make_system_member( uid=self.middleware_id, name=self.middleware_name, middleware=self) reply.type = MsgType.Image reply.mime = 'image/png' f = tempfile.NamedTemporaryFile(suffix='.png') img_data = io.BytesIO() im3.save(img_data, format='png') f.write(img_data.getvalue()) f.file.seek(0) reply.file = f reply.path = f.name reply.filename = os.path.basename(reply.file.name) # reply.deliver_to = coordinator.master reply.deliver_to = coordinator.master # reply.target = message reply.uid = str(uuid.uuid4()) coordinator.send_message(reply) except BaseException as e: self.lg(f'handle_tg_img_preview e:{e}') pass
def wechat_unsupported_msg(self, msg: wxpy.Message) -> Message: efb_msg = Message() efb_msg.type = MsgType.Unsupported efb_msg.text += self._("[Unsupported message, please check your phone.]") return efb_msg