Spaces:
Sleeping
Sleeping
| # encoding:utf-8 | |
| """ | |
| wechaty channel | |
| Python Wechaty - https://github.com/wechaty/python-wechaty | |
| """ | |
| import base64 | |
| import os | |
| import time | |
| import asyncio | |
| from bridge.context import Context | |
| from wechaty_puppet import FileBox | |
| from wechaty import Wechaty, Contact | |
| from wechaty.user import Message | |
| from bridge.reply import * | |
| from bridge.context import * | |
| from channel.chat_channel import ChatChannel | |
| from channel.wechat.wechaty_message import WechatyMessage | |
| from common.log import logger | |
| from common.singleton import singleton | |
| from config import conf | |
| try: | |
| from voice.audio_convert import any_to_sil | |
| except Exception as e: | |
| pass | |
| class WechatyChannel(ChatChannel): | |
| NOT_SUPPORT_REPLYTYPE = [] | |
| def __init__(self): | |
| super().__init__() | |
| def startup(self): | |
| config = conf() | |
| token = config.get('wechaty_puppet_service_token') | |
| os.environ['WECHATY_PUPPET_SERVICE_TOKEN'] = token | |
| asyncio.run(self.main()) | |
| async def main(self): | |
| loop = asyncio.get_event_loop() | |
| #将asyncio的loop传入处理线程 | |
| self.handler_pool._initializer= lambda: asyncio.set_event_loop(loop) | |
| self.bot = Wechaty() | |
| self.bot.on('login', self.on_login) | |
| self.bot.on('message', self.on_message) | |
| await self.bot.start() | |
| async def on_login(self, contact: Contact): | |
| self.user_id = contact.contact_id | |
| self.name = contact.name | |
| logger.info('[WX] login user={}'.format(contact)) | |
| # 统一的发送函数,每个Channel自行实现,根据reply的type字段发送不同类型的消息 | |
| def send(self, reply: Reply, context: Context): | |
| receiver_id = context['receiver'] | |
| loop = asyncio.get_event_loop() | |
| if context['isgroup']: | |
| receiver = asyncio.run_coroutine_threadsafe(self.bot.Room.find(receiver_id),loop).result() | |
| else: | |
| receiver = asyncio.run_coroutine_threadsafe(self.bot.Contact.find(receiver_id),loop).result() | |
| msg = None | |
| if reply.type == ReplyType.TEXT: | |
| msg = reply.content | |
| asyncio.run_coroutine_threadsafe(receiver.say(msg),loop).result() | |
| logger.info('[WX] sendMsg={}, receiver={}'.format(reply, receiver)) | |
| elif reply.type == ReplyType.ERROR or reply.type == ReplyType.INFO: | |
| msg = reply.content | |
| asyncio.run_coroutine_threadsafe(receiver.say(msg),loop).result() | |
| logger.info('[WX] sendMsg={}, receiver={}'.format(reply, receiver)) | |
| elif reply.type == ReplyType.VOICE: | |
| voiceLength = None | |
| file_path = reply.content | |
| sil_file = os.path.splitext(file_path)[0] + '.sil' | |
| voiceLength = int(any_to_sil(file_path, sil_file)) | |
| if voiceLength >= 60000: | |
| voiceLength = 60000 | |
| logger.info('[WX] voice too long, length={}, set to 60s'.format(voiceLength)) | |
| # 发送语音 | |
| t = int(time.time()) | |
| msg = FileBox.from_file(sil_file, name=str(t) + '.sil') | |
| if voiceLength is not None: | |
| msg.metadata['voiceLength'] = voiceLength | |
| asyncio.run_coroutine_threadsafe(receiver.say(msg),loop).result() | |
| try: | |
| os.remove(file_path) | |
| if sil_file != file_path: | |
| os.remove(sil_file) | |
| except Exception as e: | |
| pass | |
| logger.info('[WX] sendVoice={}, receiver={}'.format(reply.content, receiver)) | |
| elif reply.type == ReplyType.IMAGE_URL: # 从网络下载图片 | |
| img_url = reply.content | |
| t = int(time.time()) | |
| msg = FileBox.from_url(url=img_url, name=str(t) + '.png') | |
| asyncio.run_coroutine_threadsafe(receiver.say(msg),loop).result() | |
| logger.info('[WX] sendImage url={}, receiver={}'.format(img_url,receiver)) | |
| elif reply.type == ReplyType.IMAGE: # 从文件读取图片 | |
| image_storage = reply.content | |
| image_storage.seek(0) | |
| t = int(time.time()) | |
| msg = FileBox.from_base64(base64.b64encode(image_storage.read()), str(t) + '.png') | |
| asyncio.run_coroutine_threadsafe(receiver.say(msg),loop).result() | |
| logger.info('[WX] sendImage, receiver={}'.format(receiver)) | |
| async def on_message(self, msg: Message): | |
| """ | |
| listen for message event | |
| """ | |
| try: | |
| cmsg = await WechatyMessage(msg) | |
| except NotImplementedError as e: | |
| logger.debug('[WX] {}'.format(e)) | |
| return | |
| except Exception as e: | |
| logger.exception('[WX] {}'.format(e)) | |
| return | |
| logger.debug('[WX] message:{}'.format(cmsg)) | |
| room = msg.room() # 获取消息来自的群聊. 如果消息不是来自群聊, 则返回None | |
| isgroup = room is not None | |
| ctype = cmsg.ctype | |
| context = self._compose_context(ctype, cmsg.content, isgroup=isgroup, msg=cmsg) | |
| if context: | |
| logger.info('[WX] receiveMsg={}, context={}'.format(cmsg, context)) | |
| self.produce(context) |