diff --git a/README.md b/README.md index 5064830..c804e96 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,13 @@ pip install -r requirements.txt ## 更新 +- **2023.3.18** + - 更新`robot.py` + - 新增 自动添加好友并发送自定义消息 + - 新增 微信聊天的方式更新配置文件 + - 新增 用chatgpt与好友聊天 + - 新增 用chatgpt与群友聊天 + - 更新 wcfree.py 用法 - **2023.3.18** - 更新`gpt.py` 将一些参数丢到了json文件中,方便修改 - 新建了`job_all.py` 创建了定时类型的任务 diff --git a/main.py b/main.py index 56e3321..13c6378 100644 --- a/main.py +++ b/main.py @@ -42,16 +42,16 @@ def clean_all(): robot.LOG.info("----正在启动机器人----") # 机器人启动后发送测试消息 - robot.sendTextMsg("机器人启动成功!", "filehelper") + robot.send_text_msg("机器人启动成功!", "filehelper") # 接收消息 - robot.action_to_Msg() + robot.enable_receive_message_service() # 每天7点定时发送天气预报 robot.on_every_time('07:00', weather_report, robot=robot) # 让机器人一直跑 - robot.keepRunning_and_block_the_process() + robot.keep_running_and_block_the_process() if __name__ == "__main__": diff --git a/robot.py b/robot.py index c238a5c..2d971fc 100644 --- a/robot.py +++ b/robot.py @@ -28,8 +28,153 @@ def __init__(self, wcf: Wcf) -> None: self.config = Config() self.LOG = logging.getLogger("Robot") self.wxid = self.wcf.get_self_wxid() - self.allPeople = self.getallPeople() + self.allPeople = self.getall_people() self.chat = GptThread(self.config.CHAT_KEY) - def getallPeople(self): - pass + def enable_receive_message_service(self) -> None: + """ + 启动接收消息的服务 + """ + self.wcf.enable_recv_msg(self.action_msg) + + def action_msg(self, msg: Wcf.WxMsg): + """ + 接收到消息的处理 + :param msg: 微信消息体 + """ + try: + self.LOG.info(msg) + self.various_methods(msg) + except Exception as e: + self.LOG.error(f'出现错误,接收消息出粗:{e}') + + def various_methods(self, msg: Wcf.WxMsg) -> None: + """ + 接收到消息的时候会调用这个方法,不调用,打印原始消息 + 群号: msg.roomid 微信ID: msg.sender 消息内容: msg.content + :param msg: 微信消息体 包含以上信息 + """ + + if msg.from_group(): # 群聊消息 + self.from_group_msg(msg) + else: + if msg.type == 37: # 好友请求 + self.from_friend_request(msg) + elif msg.type == 10000: # 系统消息 + self.from_system_info(msg) + elif msg.type == 0x01: # 文本消息 + self.from_text_msg(msg) + + def from_group_msg(self, msg: Wcf.WxMsg) -> None: + """ + 处理群聊消息 + :param msg: 微信消息体 + """ + if msg.roomid not in self.config.GROUPS: # 不在允许的配置里面 + self.LOG.info(f'收到群聊消息,但是{msg.roomid}没有在{self.config.GROUPS}中配置,不处理\n') + return + elif msg.is_at(self.wxid): # 被@ + self.at_me(msg) + else: + return + + def from_friend_request(self, msg: Wcf.WxMsg) -> None: + """ + 处理好友请求 + :param msg: 微信消息体 + """ + self.auto_accept_friend_request(msg) + + def from_system_info(self, msg: Wcf.WxMsg) -> None: + """ + 处理系统消息 + :param msg: 微信消息体 + """ + self.say_hi_to_new_friend(msg) + + def from_text_msg(self, msg: Wcf.WxMsg) -> None: + """ + 处理文本消息 + :param msg: 微信消息体 + """ + if msg.from_self() and msg.content == '更新': + self.config.reload() + self.LOG.info('更新配置成功') + else: + self.get_chat_gpt(msg) + + def at_me(self, msg: Wcf.WxMsg) -> bool: + """ + 处理被@的消息 + :param msg: 微信消息结构体 + :return: 处理状态, True为处理成功, False为处理失败 + """ + return self.get_chat_gpt(msg) + + def get_chat_gpt(self, msg: Wcf.WxMsg) -> bool: + """ + 获取聊天结构体中的gpt模型 + :param msg: 微信消息结构体 + :return: 处理状态, True为处理成功, False为处理失败 + """ + question = re.sub(r"@.*?[\u2005|\s]", "", msg.content) + + def send_text_msg(self, msg: str, receiver: str, at_lists: str = '') -> None: + """ + 发送文本消息 + :param msg: 消息内容 + :param receiver: 接收人的wxid或者群roomid + :param at_lists: 要@的人的wxid列表,@所有人为:nofity@all + """ + # msg 中需要有 @ 名单中一样数量的 @ + ats = "" + if at_lists: + wxids = at_lists.split(",") + for wxid in wxids: + ats = f" @{self.allPeople.get(wxid, '')}" + + self.LOG.info(f"To {receiver}: {msg}{ats}") + self.wcf.send_text(f"{msg}{ats}", receiver, at_lists) + + def getall_people(self) -> dict: + """ + 获取联系人(包括好友、公众号、服务号、群成员……) + 格式: {"wxid": "NickName"} + """ + contacts = self.wcf.query_sql( + "MicroMsg.db", "SELECT UserName, NickName FROM Contact;") + return {contact["UserName"]: contact["NickName"] + for contact in contacts} + + def auto_accept_friend_request(self, msg: Wcf.WxMsg): + """ + 自动接受好友请求 + :param msg: 微信消息结构体 + """ + try: + xml = ET.fromstring(msg.content) + v3 = xml.attrib["encryptusername"] + v4 = xml.attrib["ticket"] + self.wcf.accept_new_friend(v3, v4) + + except Exception as e: + self.LOG.error(f"同意好友出错:{e}") + + def say_hi_to_new_friend(self, msg): + """ + 接收好友请求后自动发送消息 + :param msg: + """ + nick_name = re.findall(r"你已添加了(.*),现在可以开始聊天了。", msg.content) + if nick_name: + # 添加了好友,更新好友列表 + self.allPeople = nick_name[0] + self.send_text_msg(f"Hi {nick_name[0]},我自动通过了你的好友请求。", msg.sender) + + def keep_running_and_block_the_process(self): + """ + 保持机器人运行,不让进程退出 + """ + while True: + self.run_pending_jobs() + time.sleep(1) diff --git a/wcfree.md b/wcfree.md index d4e9c98..38ce292 100644 --- a/wcfree.md +++ b/wcfree.md @@ -1,4 +1,25 @@ # 使用方法 + + + +1. `is_login` 检查登录状态 +2. `get_self_wxid` 获取登陆账号的wxid +3. `get_msg_types` 获取消息类型 +4. `get_contacts` 获取所有联系人 +5. `get_friends` 获取所有好友 +6. `get_dbs` 获取数据库 +7. `get_tables` 获取数据库中的表 +8. `send_text` 发送文本消息,可以@ +9. `send_image` 发送图片消息 +10. `send_xml` 发送xml +11. `send_file` 发送文件消息 +12. `enable_receiving_msg ` 允许接收消息 +13. `disable_recv_msg` 停止接收消息 +14. `query_sql` 执行sql查询 +15. `accept_new_friend` 接收好友申请 +16. `add_chatroom_members` 添加群成员 + +--- 1. **enable_recv_msg()** - 首先判断是否已经在接收消息,如果是,则直接返回`True`。 - 如果回调函数为空,则返回`False`。 @@ -63,4 +84,5 @@ self.LOG.error("退出失败!") return self._is_running = False - ``` \ No newline at end of file + ``` +