From da3b964a8c47b18a07f1db654022b2333dc7da91 Mon Sep 17 00:00:00 2001 From: Rock Chin Date: Wed, 7 Dec 2022 23:37:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20qqbot=E6=B6=88=E6=81=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=9F=BA=E6=9C=AC=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-template.py | 4 ++ pkg/qqbot/manager.py | 142 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/config-template.py b/config-template.py index 8d13d4d..7740158 100644 --- a/config-template.py +++ b/config-template.py @@ -25,4 +25,8 @@ completion_api_params = { "presence_penalty": 0.3, } +process_message_timeout = 45 + +retry_times = 3 + session_expire_time = 60 * 60 * 24 * 7 diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index e69de29..2074d01 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -0,0 +1,142 @@ +from mirai import At, GroupMessage, MessageEvent, Mirai, Plain, StrangerMessage, WebSocketAdapter, FriendMessage, Image +import pkg.openai.session +from func_timeout import func_set_timeout, FunctionTimedOut + +help_text = """ +!help - 显示帮助 +!reset - 重置会话 +!last - 切换到上一次的对话 +!next - 切换到下一次的对话 +""" + +inst = None + +processing = [] + +class QQBotManager: + timeout = 60 + retry = 3 + + bot = None + + def __init__(self, mirai_http_api_config: dict, timeout: int = 60, retry: int = 3): + + self.timeout = timeout + self.retry = retry + + bot = Mirai( + qq=mirai_http_api_config['qq'], + adapter=WebSocketAdapter( + verify_key=mirai_http_api_config['verifyKey'], + host=mirai_http_api_config['host'], + port=8080 + ) + ) + + @bot.on(FriendMessage) + async def on_friend_message(event: FriendMessage): + return await self.on_person_message(event) + + @bot.on(StrangerMessage) + async def on_stranger_message(event: StrangerMessage): + return await self.on_person_message(event) + + @bot.on(GroupMessage) + async def on_group_message(event: GroupMessage): + return await self.on_group_message(event) + + self.bot = bot + + global inst + inst = self + + # 统一的消息处理函数 + @func_set_timeout(timeout) + def process_message(self, launcher_type: str, launcher_id: int, text_message: str) -> str: + reply = '' + session_name = "{}_{}".format(launcher_type, launcher_id) + + if text_message.startswith('!'): # 指令 + cmd = text_message + + if cmd == '!help': + reply = help_text + elif cmd == '!reset': + pass + elif cmd == '!last': + pass + elif cmd == '!next': + pass + else: # 消息 + session = pkg.openai.session.get_session(session_name) + reply = session.append(text_message) + + return reply + + async def on_person_message(self, event: MessageEvent): + if "person_{}".format(event.sender.id) in processing: + return + + reply = '' + + if event.sender.id == self.bot.qq: + pass + else: + if Image in event.message_chain: + pass + else: + processing.append("person_{}".format(event.sender.id)) + + # 超时则重试,重试超过次数则放弃 + failed = 0 + for i in range(self.retry): + try: + reply = self.process_message('person', event.sender.id, str(event.message_chain)) + break + except FunctionTimedOut: + failed += 1 + continue + + if failed == self.retry: + reply = "err:请求超时" + + processing.remove("person_{}".format(event.sender.id)) + + if reply != '': + return await self.bot.send(event, reply) + + async def on_group_message(self, event: GroupMessage): + if "group_{}".format(event.group.id) in processing: + return + + reply = '' + + if Image in event.message_chain: + pass + elif At(self.bot.qq) not in event.message_chain: + pass + else: + processing.append("group_{}".format(event.sender.id)) + + # 超时则重试,重试超过次数则放弃 + failed = 0 + for i in range(self.retry): + try: + reply = self.process_message('group', event.group.id, str(event.message_chain)) + break + except FunctionTimedOut: + failed += 1 + continue + + if failed == self.retry: + reply = "err:请求超时" + + processing.remove("group_{}".format(event.sender.id)) + + if reply != '': + return await self.bot.send(event, reply) + + +def get_inst() -> QQBotManager: + global inst + return inst