From 6b39df5b9bbbad732e72245efc4fe762cfec5348 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Sat, 22 Apr 2023 21:50:41 +0800 Subject: [PATCH 01/23] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4NoneBot2?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-template.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config-template.py b/config-template.py index 7568f7d3..3ba73d8c 100644 --- a/config-template.py +++ b/config-template.py @@ -4,7 +4,6 @@ import logging # 消息处理协议适配器 # 目前支持以下适配器: # - "yirimirai": YiriMirai框架适配器, 请填写mirai_http_api_config -# - "nonebot2": NoneBot2框架适配器, 请填写nonebot2_config msg_source_adapter = "yirimirai" # [必需] Mirai的配置 @@ -24,9 +23,6 @@ mirai_http_api_config = { "qq": 1234567890 } -# NoneBot2的配置 -nonebot2_config = {} - # [必需] OpenAI的配置 # api_key: OpenAI的API Key # http_proxy: 请求OpenAI时使用的代理,None为不使用,https和socks5暂不能使用 From 640afdc49c6e366f5dc225469f3f33f2aed843a4 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sat, 22 Apr 2023 13:51:02 +0000 Subject: [PATCH 02/23] Update override-all.json --- override-all.json | 1 - 1 file changed, 1 deletion(-) diff --git a/override-all.json b/override-all.json index c3f6f1c8..985a0bf3 100644 --- a/override-all.json +++ b/override-all.json @@ -8,7 +8,6 @@ "verifyKey": "yirimirai", "qq": 1234567890 }, - "nonebot2_config": {}, "openai_config": { "api_key": { "default": "openai_api_key" From e74df0b37d8de010c001cded3878c852a3a39e9e Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Sun, 23 Apr 2023 09:31:35 +0800 Subject: [PATCH 03/23] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0nakuru?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE;=20=E4=BD=BF=E7=94=A8nakur?= =?UTF-8?q?u-project-test=E4=B8=B4=E6=97=B6=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- config-template.py | 12 +++++++++++- requirements.txt | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5da69533..6d5de378 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ cookies.json res/announcement_saved res/announcement_saved.json cmdpriv.json -tips.py \ No newline at end of file +tips.py +.venv \ No newline at end of file diff --git a/config-template.py b/config-template.py index 3ba73d8c..dbb9283e 100644 --- a/config-template.py +++ b/config-template.py @@ -4,9 +4,10 @@ import logging # 消息处理协议适配器 # 目前支持以下适配器: # - "yirimirai": YiriMirai框架适配器, 请填写mirai_http_api_config +# - "nakuru": 通过nakuru-project框架连接go-cqhttp,请填写nakuru_config msg_source_adapter = "yirimirai" -# [必需] Mirai的配置 +# [必需(与nakuru二选一,取决于msg_source_adapter)] Mirai的配置 # 请到配置mirai的步骤中的教程查看每个字段的信息 # adapter: 选择适配器,目前支持HTTPAdapter和WebSocketAdapter # host: 运行mirai的主机地址 @@ -23,6 +24,15 @@ mirai_http_api_config = { "qq": 1234567890 } +# [必需(与mirai二选一,取决于msg_source_adapter)] +# 使用nakuru-project框架连接go-cqhttp的配置 +nakuru_config = { + "host": "localhost", # go-cqhttp的地址 + "port": 6700, # go-cqhttp的正向websocket端口 + "http_port": 5700, # go-cqhttp的正向http端口 + "token": "" # 若在go-cqhttp的config.yml设置了access_token, 则填写此处 +} + # [必需] OpenAI的配置 # api_key: OpenAI的API Key # http_proxy: 请求OpenAI时使用的代理,None为不使用,https和socks5暂不能使用 diff --git a/requirements.txt b/requirements.txt index ac56cf0d..7ef00a46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ yiri-mirai~=0.2.6.1 websockets urllib3~=1.26.10 func_timeout~=4.3.5 -Pillow \ No newline at end of file +Pillow +nakuru-project-test \ No newline at end of file From 48ee940d8eccb6902edd4a4ee574cfda292de766 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 23 Apr 2023 01:32:36 +0000 Subject: [PATCH 04/23] Update override-all.json --- override-all.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/override-all.json b/override-all.json index 985a0bf3..737afb34 100644 --- a/override-all.json +++ b/override-all.json @@ -8,6 +8,12 @@ "verifyKey": "yirimirai", "qq": 1234567890 }, + "nakuru_config": { + "host": "localhost", + "port": 6700, + "http_port": 5700, + "token": "" + }, "openai_config": { "api_key": { "default": "openai_api_key" From 612033f478f5b7cdff570a5ef63357c483105358 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Sun, 23 Apr 2023 15:58:37 +0800 Subject: [PATCH 05/23] =?UTF-8?q?feat:=20nakuru=E9=80=82=E9=85=8D=E5=99=A8?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/adapter.py | 56 +++++++++++++++++++- pkg/qqbot/manager.py | 2 +- pkg/qqbot/sources/nakuru.py | 96 ++++++++++++++++++++++++++++++++++ pkg/qqbot/sources/yirimirai.py | 1 + 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 pkg/qqbot/sources/nakuru.py diff --git a/pkg/qqbot/adapter.py b/pkg/qqbot/adapter.py index 5d4faa00..0d00915d 100644 --- a/pkg/qqbot/adapter.py +++ b/pkg/qqbot/adapter.py @@ -79,4 +79,58 @@ class MessageSourceAdapter: bool: 是否成功关闭,热重载时若此函数返回False则不会重载MessageSource底层 """ raise NotImplementedError - \ No newline at end of file + + +class MessageConverter: + """消息链转换器基类""" + @staticmethod + def yiri2target(message_chain: mirai.MessageChain): + """将YiriMirai消息链转换为目标消息链 + + Args: + message_chain (mirai.MessageChain): YiriMirai消息链 + + Returns: + typing.Any: 目标消息链 + """ + raise NotImplementedError + + @staticmethod + def target2yiri(message_chain: typing.Any) -> mirai.MessageChain: + """将目标消息链转换为YiriMirai消息链 + + Args: + message_chain (typing.Any): 目标消息链 + + Returns: + mirai.MessageChain: YiriMirai消息链 + """ + raise NotImplementedError + + +class EventConverter: + """事件转换器基类""" + + @staticmethod + def yiri2target(event: typing.Type[mirai.Event]): + """将YiriMirai事件转换为目标事件 + + Args: + event (typing.Type[mirai.Event]): YiriMirai事件 + + Returns: + typing.Any: 目标事件 + """ + raise NotImplementedError + + @staticmethod + def target2yiri(event: typing.Any) -> mirai.Event: + """将目标事件的调用参数转换为YiriMirai的事件参数对象 + + Args: + event (typing.Any): 目标事件 + + Returns: + typing.Type[mirai.Event]: YiriMirai事件 + """ + raise NotImplementedError diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index 747854cb..ce5b1c90 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -92,7 +92,7 @@ class QQBotManager: from pkg.qqbot.sources.yirimirai import YiriMiraiAdapter self.bot_account_id = config.mirai_http_api_config['qq'] self.adapter = YiriMiraiAdapter(mirai_http_api_config) - elif config.msg_source_adapter == 'nonebot2': + elif config.msg_source_adapter == 'nakuru': pass else: self.adapter = pkg.utils.context.get_qqbot_manager().adapter diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py new file mode 100644 index 00000000..addc2ed4 --- /dev/null +++ b/pkg/qqbot/sources/nakuru.py @@ -0,0 +1,96 @@ +import mirai + +from ..adapter import MessageSourceAdapter, MessageConverter, EventConverter +import nakuru + +import asyncio +import typing + + +class NakuruProjectMessageConverter(MessageConverter): + @staticmethod + def yiri2target(message_chain: mirai.MessageChain) -> list: + pass + + @staticmethod + def target2yiri(message_chain: typing.Any) -> mirai.MessageChain: + pass + + +class NakuruProjectEventConverter(EventConverter): + @staticmethod + def yiri2target(event: typing.Type[mirai.Event]): + if event is mirai.GroupMessage: + return "GroupMessage" + elif event is mirai.FriendMessage: + return "FriendMessage" + elif event is mirai.StrangerMessage: + return "FriendMessage" + else: + raise Exception("Unknown event type: " + str(event)) + + @staticmethod + def target2yiri(event: typing.Any) -> mirai.Event: + pass + + +class NakuruProjectAdapter(MessageSourceAdapter): + """nakuru-project适配器""" + bot: nakuru.CQHTTP + + message_converter: NakuruProjectMessageConverter + event_converter: NakuruProjectEventConverter + + def __init__(self, config: dict): + """初始化nakuru-project的对象""" + self.bot = nakuru.CQHTTP(**config) + + def send_message( + self, + target_type: str, + target_id: str, + message: mirai.MessageChain + ): + task = None + if target_type == "group": + task = self.bot.sendGroupMessage(int(target_id), self.message_converter.yiri2target(message)) + elif target_type == "person": + task = self.bot.sendFriendMessage(int(target_id), self.message_converter.yiri2target(message)) + else: + raise Exception("Unknown target type: " + target_type) + + asyncio.run(task) + + def reply_message( + self, + message_source: mirai.MessageEvent, + message: mirai.MessageChain, + quote_origin: bool = False + ): + pass + + def is_muted(self, group_id: int) -> bool: + pass + + def register_listener( + self, + event_type: typing.Type[mirai.Event], + callback: typing.Callable[[mirai.Event], None] + ): + def listener_wrapper(app: nakuru.CQHTTP, source: nakuru.GroupMessage): + callback(self.event_converter.target2yiri(source)) + + self.bot.receiver(self.event_converter.yiri2target(event_type))(listener_wrapper) + + def unregister_listener( + self, + event_type: typing.Type[mirai.Event], + callback: typing.Callable[[mirai.Event], None] + ): + pass + + def run_sync(self): + self.bot.run() + + def kill(self) -> bool: + return False diff --git a/pkg/qqbot/sources/yirimirai.py b/pkg/qqbot/sources/yirimirai.py index 0026ba94..8aa14ba4 100644 --- a/pkg/qqbot/sources/yirimirai.py +++ b/pkg/qqbot/sources/yirimirai.py @@ -68,6 +68,7 @@ class YiriMiraiAdapter(MessageSourceAdapter): Args: message_source (mirai.MessageEvent): YiriMirai消息源事件 message (mirai.MessageChain): YiriMirai库的消息链 + quote_origin (bool, optional): 是否引用原消息. Defaults to False. """ asyncio.run(self.bot.send(message_source, message, quote_origin)) From 5b96ac122f1967d075d970cf0f3a3c545e08504d Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Sun, 23 Apr 2023 23:40:08 +0800 Subject: [PATCH 06/23] =?UTF-8?q?feat:=20=E9=80=82=E9=85=8Dnakuru=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- main.py | 10 ++- pkg/qqbot/manager.py | 28 ++++-- pkg/qqbot/sources/nakuru.py | 175 ++++++++++++++++++++++++++++++++---- 4 files changed, 189 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 6d5de378..42034518 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,6 @@ res/announcement_saved res/announcement_saved.json cmdpriv.json tips.py -.venv \ No newline at end of file +.venv +bin/ +.vscode \ No newline at end of file diff --git a/main.py b/main.py index fbdd961a..4980c096 100644 --- a/main.py +++ b/main.py @@ -243,6 +243,8 @@ def start(first_time_init=False): "mirai-api-http端口无法使用:{}, 解决方案: https://github.com/RockChinQ/QChatGPT/issues/22".format( e)) else: + import traceback + traceback.print_exc() logging.error( "捕捉到未知异常:{}, 请前往 https://github.com/RockChinQ/QChatGPT/issues 查找或提issue".format(e)) known_exception_caught = True @@ -262,9 +264,11 @@ def start(first_time_init=False): if first_time_init: if not known_exception_caught: - logging.info("QQ: {}, MAH: {}".format(config.mirai_http_api_config['qq'], config.mirai_http_api_config['host']+":"+str(config.mirai_http_api_config['port']))) - logging.info('程序启动完成,如长时间未显示 ”成功登录到账号xxxxx“ ,并且不回复消息,请查看 ' - 'https://github.com/RockChinQ/QChatGPT/issues/37') + import config + if config.msg_source_adapter == "yirimirai": + logging.info("QQ: {}, MAH: {}".format(config.mirai_http_api_config['qq'], config.mirai_http_api_config['host']+":"+str(config.mirai_http_api_config['port']))) + logging.info('程序启动完成,如长时间未显示 ”成功登录到账号xxxxx“ ,并且不回复消息,请查看 ' + 'https://github.com/RockChinQ/QChatGPT/issues/37') else: sys.exit(1) else: diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index ce5b1c90..2a160c95 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -80,7 +80,6 @@ class QQBotManager: def __init__(self, first_time_init=True): import config - mirai_http_api_config = config.mirai_http_api_config self.timeout = config.process_message_timeout self.retry = config.retry_times @@ -88,12 +87,26 @@ class QQBotManager: # 故只在第一次初始化时创建bot对象,重载之后使用原bot对象 # 因此,bot的配置不支持热重载 if first_time_init: + logging.info("Use adapter:" + config.msg_source_adapter) if config.msg_source_adapter == 'yirimirai': from pkg.qqbot.sources.yirimirai import YiriMiraiAdapter + + mirai_http_api_config = config.mirai_http_api_config self.bot_account_id = config.mirai_http_api_config['qq'] self.adapter = YiriMiraiAdapter(mirai_http_api_config) elif config.msg_source_adapter == 'nakuru': - pass + from pkg.qqbot.sources.nakuru import NakuruProjectAdapter + self.adapter = NakuruProjectAdapter(config.nakuru_config) + # nakuru库有bug,这个接口没法带access_token,会失败 + # 所以目前自行发请求 + import requests + resp = requests.get( + url="http://{}:{}/get_login_info".format(config.nakuru_config['host'], config.nakuru_config['http_port']), + headers={ + 'Authorization': "Bearer " + config.nakuru_config['token'] if 'token' in config.nakuru_config else "" + } + ) + self.bot_account_id = int(resp.json()['data']['user_id']) else: self.adapter = pkg.utils.context.get_qqbot_manager().adapter @@ -146,10 +159,12 @@ class QQBotManager: pkg.utils.context.get_thread_ctl().submit_user_task( stranger_message_handler, ) - self.adapter.register_listener( - StrangerMessage, - on_stranger_message - ) + # nakuru不区分好友和陌生人,故仅为yirimirai注册陌生人事件 + if config.msg_source_adapter == 'yirimirai': + self.adapter.register_listener( + StrangerMessage, + on_stranger_message + ) def on_group_message(event: GroupMessage): @@ -272,7 +287,6 @@ class QQBotManager: def on_group_message(self, event: GroupMessage): import config reply = '' - def process(text=None) -> str: replys = "" if At(self.bot_account_id) in event.message_chain: diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index addc2ed4..46e17c79 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -2,48 +2,141 @@ import mirai from ..adapter import MessageSourceAdapter, MessageConverter, EventConverter import nakuru +import nakuru.entities.components as nkc import asyncio import typing +import traceback +import logging +import json class NakuruProjectMessageConverter(MessageConverter): @staticmethod def yiri2target(message_chain: mirai.MessageChain) -> list: - pass + msg_list = [] + if type(message_chain) is mirai.MessageChain: + msg_list = message_chain.__root__ + elif type(message_chain) is list: + msg_list = message_chain + else: + raise Exception("Unknown message type: " + str(message_chain) + type(message_chain)) + + nakuru_msg_list = [] + + # 遍历并转换 + for component in msg_list: + if type(component) is mirai.Plain: + nakuru_msg_list.append(nkc.Plain(component.text)) + elif type(component) is mirai.Image: + if component.url is not None: + nakuru_msg_list.append(nkc.Image.fromURL(component.url)) + elif component.base64 is not None: + nakuru_msg_list.append(nkc.Image.fromBase64(component.base64)) + elif component.path is not None: + nakuru_msg_list.append(nkc.Image.fromFileSystem(component.path)) + elif type(component) is mirai.Face: + nakuru_msg_list.append(nkc.Face(id=component.face_id)) + elif type(component) is mirai.At: + nakuru_msg_list.append(nkc.At(qq=component.target)) + elif type(component) is mirai.AtAll: + nakuru_msg_list.append(nkc.AtAll()) + elif type(component) is mirai.Voice: + pass + else: + pass + + return nakuru_msg_list @staticmethod def target2yiri(message_chain: typing.Any) -> mirai.MessageChain: - pass + assert type(message_chain) is list + + yiri_msg_list = [] + for component in message_chain: + if type(component) is nkc.Plain: + yiri_msg_list.append(mirai.Plain(text=component.text)) + elif type(component) is nkc.Image: + yiri_msg_list.append(mirai.Image(url=component.url)) + elif type(component) is nkc.Face: + yiri_msg_list.append(mirai.Face(face_id=component.id)) + elif type(component) is nkc.At: + yiri_msg_list.append(mirai.At(target=component.qq)) + elif type(component) is nkc.AtAll: + yiri_msg_list.append(mirai.AtAll()) + else: + pass + logging.debug("转换后的消息链: " + str(yiri_msg_list)) + return mirai.MessageChain(yiri_msg_list) class NakuruProjectEventConverter(EventConverter): @staticmethod def yiri2target(event: typing.Type[mirai.Event]): if event is mirai.GroupMessage: - return "GroupMessage" + return nakuru.GroupMessage elif event is mirai.FriendMessage: - return "FriendMessage" - elif event is mirai.StrangerMessage: - return "FriendMessage" + return nakuru.FriendMessage else: - raise Exception("Unknown event type: " + str(event)) + raise Exception("未支持转换的事件类型: " + str(event)) @staticmethod def target2yiri(event: typing.Any) -> mirai.Event: - pass + if type(event) is nakuru.FriendMessage: + return mirai.FriendMessage( + sender=mirai.models.entities.Friend( + id=event.sender.user_id, + nickname=event.sender.nickname, + remark=event.sender.nickname + ), + message_chain=NakuruProjectMessageConverter.target2yiri(event.message), + time=event.time + ) + elif type(event) is nakuru.GroupMessage: + permission = "MEMBER" + + if event.sender.role == "admin": + permission = "ADMINISTRATOR" + elif event.sender.role == "owner": + permission = "OWNER" + + import mirai.models.entities as entities + return mirai.GroupMessage( + sender=mirai.models.entities.GroupMember( + id=event.sender.user_id, + member_name=event.sender.nickname, + permission=permission, + group=mirai.models.entities.Group( + id=event.group_id, + name=event.sender.nickname, + permission=entities.Permission.Member + ), + special_title=event.sender.title, + join_timestamp=0, + last_speak_timestamp=0, + mute_time_remaining=0, + ), + message_chain=NakuruProjectMessageConverter.target2yiri(event.message), + time=event.time + ) + else: + raise Exception("未支持转换的事件类型: " + str(event)) + class NakuruProjectAdapter(MessageSourceAdapter): """nakuru-project适配器""" bot: nakuru.CQHTTP - message_converter: NakuruProjectMessageConverter - event_converter: NakuruProjectEventConverter + message_converter: NakuruProjectMessageConverter = NakuruProjectMessageConverter() + event_converter: NakuruProjectEventConverter = NakuruProjectEventConverter() + + listener_list: list[dict] def __init__(self, config: dict): """初始化nakuru-project的对象""" self.bot = nakuru.CQHTTP(**config) + self.listener_list = [] def send_message( self, @@ -67,29 +160,77 @@ class NakuruProjectAdapter(MessageSourceAdapter): message: mirai.MessageChain, quote_origin: bool = False ): - pass + if type(message_source) is mirai.GroupMessage: + task = self.bot.sendGroupMessage( + message_source.sender.group.id, + self.message_converter.yiri2target(message), + # quote=message_source.message_id if quote_origin else None + ) + elif type(message_source) is mirai.FriendMessage: + task = self.bot.sendFriendMessage( + message_source.sender.id, + self.message_converter.yiri2target(message), + # quote=message_source.message_id if quote_origin else None + ) + else: + raise Exception("Unknown message source type: " + str(type(message_source))) + + asyncio.run(task) def is_muted(self, group_id: int) -> bool: - pass + return False def register_listener( self, event_type: typing.Type[mirai.Event], callback: typing.Callable[[mirai.Event], None] ): - def listener_wrapper(app: nakuru.CQHTTP, source: nakuru.GroupMessage): - callback(self.event_converter.target2yiri(source)) - - self.bot.receiver(self.event_converter.yiri2target(event_type))(listener_wrapper) + try: + logging.debug("注册监听器: " + str(event_type) + " -> " + str(callback)) + async def listener_wrapper(app: nakuru.CQHTTP, source: self.event_converter.yiri2target(event_type)): + callback(self.event_converter.target2yiri(source)) + self.listener_list.append( + { + "event_type": event_type, + "callable": callback, + "wrapper": listener_wrapper, + } + ) + self.bot.receiver(self.event_converter.yiri2target(event_type).__name__)(listener_wrapper) + logging.debug("注册完成") + except Exception as e: + traceback.print_exc() + raise e def unregister_listener( self, event_type: typing.Type[mirai.Event], callback: typing.Callable[[mirai.Event], None] ): - pass + nakuru_event_name = self.event_converter.yiri2target(event_type) + + new_event_list = [] + + # 从本对象的监听器列表中查找并删除 + target_wrapper = None + for listener in self.listener_list: + if listener["event_type"] == event_type and listener["callable"] == callback: + target_wrapper = listener["wrapper"] + self.listener_list.remove(listener) + break + + if target_wrapper is None: + raise Exception("未找到对应的监听器") + + for func in self.bot.event[nakuru_event_name]: + if func.callable != target_wrapper: + new_event_list.append(func) + + self.bot.event[nakuru_event_name] = new_event_list def run_sync(self): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) self.bot.run() def kill(self) -> bool: From 3cb49fe2d8bd609429fe44703c154b1fe6f06e20 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 10:34:51 +0800 Subject: [PATCH 07/23] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E7=BE=A4=E5=86=85=E7=A6=81=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/manager.py | 11 +---------- pkg/qqbot/process.py | 3 ++- pkg/qqbot/sources/nakuru.py | 24 +++++++++++++++++++++--- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index 2a160c95..78429202 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -97,16 +97,7 @@ class QQBotManager: elif config.msg_source_adapter == 'nakuru': from pkg.qqbot.sources.nakuru import NakuruProjectAdapter self.adapter = NakuruProjectAdapter(config.nakuru_config) - # nakuru库有bug,这个接口没法带access_token,会失败 - # 所以目前自行发请求 - import requests - resp = requests.get( - url="http://{}:{}/get_login_info".format(config.nakuru_config['host'], config.nakuru_config['http_port']), - headers={ - 'Authorization': "Bearer " + config.nakuru_config['token'] if 'token' in config.nakuru_config else "" - } - ) - self.bot_account_id = int(resp.json()['data']['user_id']) + self.bot_account_id = self.adapter.bot_account_id else: self.adapter = pkg.utils.context.get_qqbot_manager().adapter diff --git a/pkg/qqbot/process.py b/pkg/qqbot/process.py index ff85126c..545886d1 100644 --- a/pkg/qqbot/process.py +++ b/pkg/qqbot/process.py @@ -66,7 +66,8 @@ def process_message(launcher_type: str, launcher_id: int, text_message: str, mes # 检查是否被禁言 if launcher_type == 'group': - if mgr.adapter.is_muted(launcher_id): + is_muted = mgr.adapter.is_muted(launcher_id) + if is_muted: logging.info("机器人被禁言,跳过消息处理(group_{})".format(launcher_id)) return reply diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index 46e17c79..d7fae727 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -12,6 +12,7 @@ import json class NakuruProjectMessageConverter(MessageConverter): + """消息转换器""" @staticmethod def yiri2target(message_chain: mirai.MessageChain) -> list: msg_list = [] @@ -50,6 +51,7 @@ class NakuruProjectMessageConverter(MessageConverter): @staticmethod def target2yiri(message_chain: typing.Any) -> mirai.MessageChain: + """将Yiri的消息链转换为YiriMirai的消息链""" assert type(message_chain) is list yiri_msg_list = [] @@ -71,6 +73,7 @@ class NakuruProjectMessageConverter(MessageConverter): class NakuruProjectEventConverter(EventConverter): + """事件转换器""" @staticmethod def yiri2target(event: typing.Type[mirai.Event]): if event is mirai.GroupMessage: @@ -127,16 +130,29 @@ class NakuruProjectEventConverter(EventConverter): class NakuruProjectAdapter(MessageSourceAdapter): """nakuru-project适配器""" bot: nakuru.CQHTTP + bot_account_id: int message_converter: NakuruProjectMessageConverter = NakuruProjectMessageConverter() event_converter: NakuruProjectEventConverter = NakuruProjectEventConverter() listener_list: list[dict] - def __init__(self, config: dict): + def __init__(self, cfg: dict): """初始化nakuru-project的对象""" - self.bot = nakuru.CQHTTP(**config) + self.bot = nakuru.CQHTTP(**cfg) self.listener_list = [] + # nakuru库有bug,这个接口没法带access_token,会失败 + # 所以目前自行发请求 + import config + import requests + resp = requests.get( + url="http://{}:{}/get_login_info".format(config.nakuru_config['host'], config.nakuru_config['http_port']), + headers={ + 'Authorization': "Bearer " + config.nakuru_config['token'] if 'token' in config.nakuru_config else "" + }, + timeout=5 + ) + self.bot_account_id = int(resp.json()['data']['user_id']) def send_message( self, @@ -178,7 +194,9 @@ class NakuruProjectAdapter(MessageSourceAdapter): asyncio.run(task) def is_muted(self, group_id: int) -> bool: - return False + import time + group_member_info = asyncio.run(self.bot.getGroupMemberInfo(group_id, self.bot_account_id)) + return group_member_info.shut_up_timestamp > int(time.time()) def register_listener( self, From a2bc25c08b76e7e5719619ad80f204bffcda5442 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 10:57:43 +0800 Subject: [PATCH 08/23] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E5=8E=9F=E6=B6=88=E6=81=AF=E5=9B=9E=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/sources/nakuru.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index d7fae727..1525e421 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -50,11 +50,13 @@ class NakuruProjectMessageConverter(MessageConverter): return nakuru_msg_list @staticmethod - def target2yiri(message_chain: typing.Any) -> mirai.MessageChain: + def target2yiri(message_chain: typing.Any, message_id: int = -1) -> mirai.MessageChain: """将Yiri的消息链转换为YiriMirai的消息链""" assert type(message_chain) is list yiri_msg_list = [] + import datetime + yiri_msg_list.append(mirai.models.message.Source(id=message_id, time=datetime.datetime.now())) for component in message_chain: if type(component) is nkc.Plain: yiri_msg_list.append(mirai.Plain(text=component.text)) @@ -69,7 +71,8 @@ class NakuruProjectMessageConverter(MessageConverter): else: pass logging.debug("转换后的消息链: " + str(yiri_msg_list)) - return mirai.MessageChain(yiri_msg_list) + chain = mirai.MessageChain(yiri_msg_list) + return chain class NakuruProjectEventConverter(EventConverter): @@ -85,6 +88,7 @@ class NakuruProjectEventConverter(EventConverter): @staticmethod def target2yiri(event: typing.Any) -> mirai.Event: + yiri_chain = NakuruProjectMessageConverter.target2yiri(event.message, event.message_id) if type(event) is nakuru.FriendMessage: return mirai.FriendMessage( sender=mirai.models.entities.Friend( @@ -92,7 +96,7 @@ class NakuruProjectEventConverter(EventConverter): nickname=event.sender.nickname, remark=event.sender.nickname ), - message_chain=NakuruProjectMessageConverter.target2yiri(event.message), + message_chain=yiri_chain, time=event.time ) elif type(event) is nakuru.GroupMessage: @@ -119,7 +123,7 @@ class NakuruProjectEventConverter(EventConverter): last_speak_timestamp=0, mute_time_remaining=0, ), - message_chain=NakuruProjectMessageConverter.target2yiri(event.message), + message_chain=yiri_chain, time=event.time ) else: @@ -176,16 +180,23 @@ class NakuruProjectAdapter(MessageSourceAdapter): message: mirai.MessageChain, quote_origin: bool = False ): + message = self.message_converter.yiri2target(message) + if quote_origin: + # 在前方添加引用组件 + message.insert(0, nkc.Reply( + id=message_source.message_chain.message_id, + ) + ) if type(message_source) is mirai.GroupMessage: task = self.bot.sendGroupMessage( message_source.sender.group.id, - self.message_converter.yiri2target(message), + message, # quote=message_source.message_id if quote_origin else None ) elif type(message_source) is mirai.FriendMessage: task = self.bot.sendFriendMessage( message_source.sender.id, - self.message_converter.yiri2target(message), + message, # quote=message_source.message_id if quote_origin else None ) else: From 7d10d0398e1350c56ddb8533891745a0a84d8423 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 11:21:51 +0800 Subject: [PATCH 09/23] =?UTF-8?q?fix:=20nakuru=E7=83=AD=E9=87=8D=E8=BD=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/manager.py | 10 ++++++---- pkg/qqbot/sources/nakuru.py | 14 +++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index 78429202..4a1b8c78 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -188,14 +188,16 @@ class QQBotManager: 用于在热重载流程中卸载所有事件处理器 """ + import config self.adapter.unregister_listener( FriendMessage, on_friend_message ) - self.adapter.unregister_listener( - StrangerMessage, - on_stranger_message - ) + if config.msg_source_adapter == 'yirimirai': + self.adapter.unregister_listener( + StrangerMessage, + on_stranger_message + ) self.adapter.unregister_listener( GroupMessage, on_group_message diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index 1525e421..4f770115 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -56,6 +56,7 @@ class NakuruProjectMessageConverter(MessageConverter): yiri_msg_list = [] import datetime + # 添加Source组件以标记message_id等信息 yiri_msg_list.append(mirai.models.message.Source(id=message_id, time=datetime.datetime.now())) for component in message_chain: if type(component) is nkc.Plain: @@ -89,7 +90,7 @@ class NakuruProjectEventConverter(EventConverter): @staticmethod def target2yiri(event: typing.Any) -> mirai.Event: yiri_chain = NakuruProjectMessageConverter.target2yiri(event.message, event.message_id) - if type(event) is nakuru.FriendMessage: + if type(event) is nakuru.FriendMessage: # 私聊消息事件 return mirai.FriendMessage( sender=mirai.models.entities.Friend( id=event.sender.user_id, @@ -99,7 +100,7 @@ class NakuruProjectEventConverter(EventConverter): message_chain=yiri_chain, time=event.time ) - elif type(event) is nakuru.GroupMessage: + elif type(event) is nakuru.GroupMessage: # 群聊消息事件 permission = "MEMBER" if event.sender.role == "admin": @@ -206,6 +207,7 @@ class NakuruProjectAdapter(MessageSourceAdapter): def is_muted(self, group_id: int) -> bool: import time + # 检查是否被禁言 group_member_info = asyncio.run(self.bot.getGroupMemberInfo(group_id, self.bot_account_id)) return group_member_info.shut_up_timestamp > int(time.time()) @@ -216,8 +218,12 @@ class NakuruProjectAdapter(MessageSourceAdapter): ): try: logging.debug("注册监听器: " + str(event_type) + " -> " + str(callback)) + + # 包装函数 async def listener_wrapper(app: nakuru.CQHTTP, source: self.event_converter.yiri2target(event_type)): callback(self.event_converter.target2yiri(source)) + + # 将包装函数和原函数的对应关系存入列表 self.listener_list.append( { "event_type": event_type, @@ -225,6 +231,8 @@ class NakuruProjectAdapter(MessageSourceAdapter): "wrapper": listener_wrapper, } ) + + # 注册监听器 self.bot.receiver(self.event_converter.yiri2target(event_type).__name__)(listener_wrapper) logging.debug("注册完成") except Exception as e: @@ -236,7 +244,7 @@ class NakuruProjectAdapter(MessageSourceAdapter): event_type: typing.Type[mirai.Event], callback: typing.Callable[[mirai.Event], None] ): - nakuru_event_name = self.event_converter.yiri2target(event_type) + nakuru_event_name = self.event_converter.yiri2target(event_type).__name__ new_event_list = [] From c7517d31a40de662d8bf393a4da15ed299d93ffd Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 11:37:01 +0800 Subject: [PATCH 10/23] =?UTF-8?q?chore:=20=E6=9B=B4=E6=8D=A2=E4=BD=BF?= =?UTF-8?q?=E7=94=A8nakuru-project-idk=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7ef00a46..1c17a401 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,4 @@ websockets urllib3~=1.26.10 func_timeout~=4.3.5 Pillow -nakuru-project-test \ No newline at end of file +nakuru-project-idk \ No newline at end of file From 471768e760ba9719d1fb3b5991dd5a2aeb3a4bf6 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 12:46:33 +0800 Subject: [PATCH 11/23] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=8F=91?= =?UTF-8?q?=E9=80=81=E8=BD=AC=E5=8F=91=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/sources/nakuru.py | 70 +++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index 4f770115..25363371 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -10,6 +10,8 @@ import traceback import logging import json +from pkg.qqbot.blob import Forward, ForwardMessageNode, ForwardMessageDiaplay + class NakuruProjectMessageConverter(MessageConverter): """消息转换器""" @@ -28,7 +30,7 @@ class NakuruProjectMessageConverter(MessageConverter): # 遍历并转换 for component in msg_list: if type(component) is mirai.Plain: - nakuru_msg_list.append(nkc.Plain(component.text)) + nakuru_msg_list.append(nkc.Plain(component.text, False)) elif type(component) is mirai.Image: if component.url is not None: nakuru_msg_list.append(nkc.Image.fromURL(component.url)) @@ -44,8 +46,29 @@ class NakuruProjectMessageConverter(MessageConverter): nakuru_msg_list.append(nkc.AtAll()) elif type(component) is mirai.Voice: pass + elif type(component) is Forward: + # 转发消息 + yiri_forward_node_list = component.node_list + nakuru_forward_node_list = [] + + # 遍历并转换 + for yiri_forward_node in yiri_forward_node_list: + try: + content_list = NakuruProjectMessageConverter.yiri2target(yiri_forward_node.message_chain) + nakuru_forward_node = nkc.Node( + name=yiri_forward_node.sender_name, + uin=yiri_forward_node.sender_id, + time=int(yiri_forward_node.time.timestamp()) if yiri_forward_node.time is not None else None, + content=content_list + ) + nakuru_forward_node_list.append(nakuru_forward_node) + except Exception as e: + import traceback + traceback.print_exc() + + nakuru_msg_list.append(nakuru_forward_node_list) else: - pass + nakuru_msg_list.append(nkc.Plain(str(component))) return nakuru_msg_list @@ -163,15 +186,34 @@ class NakuruProjectAdapter(MessageSourceAdapter): self, target_type: str, target_id: str, - message: mirai.MessageChain + message: typing.Union[mirai.MessageChain, list], + converted: bool = False ): task = None - if target_type == "group": - task = self.bot.sendGroupMessage(int(target_id), self.message_converter.yiri2target(message)) - elif target_type == "person": - task = self.bot.sendFriendMessage(int(target_id), self.message_converter.yiri2target(message)) + + converted_msg = self.message_converter.yiri2target(message) if not converted else message + + # 检查是否有转发消息 + has_forward = False + for msg in converted_msg: + if type(msg) is list: # 转发消息,仅回复此消息组件 + has_forward = True + converted_msg = msg + break + if has_forward: + if target_type == "group": + task = self.bot.sendGroupForwardMessage(int(target_id), converted_msg) + elif target_type == "person": + task = self.bot.sendPrivateForwardMessage(int(target_id), converted_msg) + else: + raise Exception("Unknown target type: " + target_type) else: - raise Exception("Unknown target type: " + target_type) + if target_type == "group": + task = self.bot.sendGroupMessage(int(target_id), converted_msg) + elif target_type == "person": + task = self.bot.sendFriendMessage(int(target_id), converted_msg) + else: + raise Exception("Unknown target type: " + target_type) asyncio.run(task) @@ -189,22 +231,22 @@ class NakuruProjectAdapter(MessageSourceAdapter): ) ) if type(message_source) is mirai.GroupMessage: - task = self.bot.sendGroupMessage( + self.send_message( + "group", message_source.sender.group.id, message, - # quote=message_source.message_id if quote_origin else None + converted=True ) elif type(message_source) is mirai.FriendMessage: - task = self.bot.sendFriendMessage( + self.send_message( + "person", message_source.sender.id, message, - # quote=message_source.message_id if quote_origin else None + converted=True ) else: raise Exception("Unknown message source type: " + str(type(message_source))) - asyncio.run(task) - def is_muted(self, group_id: int) -> bool: import time # 检查是否被禁言 From 7b7cdd8adb2575f08bd8f10c1abea6d970cc3829 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 13:52:22 +0800 Subject: [PATCH 12/23] =?UTF-8?q?perf:=20=E5=9C=A8=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=8C=85=E5=90=AB=E8=BE=93=E5=87=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/utils/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/utils/log.py b/pkg/utils/log.py index 2666616e..b976583b 100644 --- a/pkg/utils/log.py +++ b/pkg/utils/log.py @@ -48,7 +48,7 @@ def reset_logging(): logging.basicConfig(level=config.logging_level, # 设置日志输出格式 filename=log_file_name, # log日志输出的文件位置和文件名 - format="[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s", + format="[%(asctime)s.%(msecs)03d] %(pathname)s (%(lineno)d) - [%(levelname)s] :\n%(message)s", # 日志输出的格式 # -8表示占位符,让输出左对齐,输出长度都为8位 datefmt="%Y-%m-%d %H:%M:%S" # 时间输出的格式 From 950ef4a181dee3be455352ae9e01d139405bf78c Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 14:57:28 +0800 Subject: [PATCH 13/23] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- README_en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f2cb90de..d4ffc9ff 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ cd QChatGPT 2. 安装依赖 ```bash -pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow +pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow nakuru-project-idk ``` 3. 运行一次主程序,生成配置文件 diff --git a/README_en.md b/README_en.md index 068eee40..ffffab53 100644 --- a/README_en.md +++ b/README_en.md @@ -124,7 +124,7 @@ cd QChatGPT 2. Install dependencies ```bash -pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow +pip3 install requests yiri-mirai openai colorlog func_timeout dulwich Pillow nakuru-project-idk ``` 3. Generate `config.py` From 0a02ee8c04bbc34e156128613780498d377a49ed Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:04:07 +0800 Subject: [PATCH 14/23] =?UTF-8?q?feat:=20=E5=90=AF=E5=8A=A8=E6=97=B6?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0nakuru=E7=9A=84=E6=8F=90=E7=A4=BA=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 4980c096..c60aca82 100644 --- a/main.py +++ b/main.py @@ -267,8 +267,11 @@ def start(first_time_init=False): import config if config.msg_source_adapter == "yirimirai": logging.info("QQ: {}, MAH: {}".format(config.mirai_http_api_config['qq'], config.mirai_http_api_config['host']+":"+str(config.mirai_http_api_config['port']))) - logging.info('程序启动完成,如长时间未显示 ”成功登录到账号xxxxx“ ,并且不回复消息,请查看 ' + logging.critical('程序启动完成,如长时间未显示 "成功登录到账号xxxxx" ,并且不回复消息,请查看 ' 'https://github.com/RockChinQ/QChatGPT/issues/37') + elif config.msg_source_adapter == 'nakuru': + logging.info("host: {}, port: {}, http_port: {}".format(config.nakuru_config['host'], config.nakuru_config['port'], config.nakuru_config['http_port'])) + logging.critical('程序启动完成,如长时间未显示 "Protocol: connected" ,并且不回复消息,请检查config.py中的nakuru_config是否正确') else: sys.exit(1) else: From 58ee204a759091bc2fdf50551c789b421d33a29e Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:41:28 +0800 Subject: [PATCH 15/23] =?UTF-8?q?doc:=20wiki=E6=B7=BB=E5=8A=A0go-cqhttp?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- res/wiki/go-cqhttp配置.md | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 res/wiki/go-cqhttp配置.md diff --git a/res/wiki/go-cqhttp配置.md b/res/wiki/go-cqhttp配置.md new file mode 100644 index 00000000..c7a496c1 --- /dev/null +++ b/res/wiki/go-cqhttp配置.md @@ -0,0 +1,65 @@ +# 配置go-cqhttp用于登录QQ + +## 步骤 + +1. 从[go-cqhttp的Release](https://github.com/Mrs4s/go-cqhttp/releases/latest)下载最新的go-cqhttp可执行文件(建议直接下载可执行文件压缩包,而不是安装器) +2. 解压并运行,首次运行会询问需要开放的网络协议,请填入`02`并回车 + + ``` + C:\Softwares\go-cqhttp.old> .\go-cqhttp.exe + 未找到配置文件,正在为您生成配置文件中! + 请选择你需要的通信方式: + > 0: HTTP通信 + > 1: 云函数服务 + > 2: 正向 Websocket 通信 + > 3: 反向 Websocket 通信 + 请输入你需要的编号(0-9),可输入多个,同一编号也可输入多个(如: 233) + 您的选择是:02 + ``` + 提示已生成`config.yml`文件,关闭go-cqhttp。 + +3. 打开go-cqhttp同目录的`config.yml` + + 1. 编辑账号登录信息(可选) + + 只需要修改下方`uin`和`password`为你要登录的机器人账号的QQ号和密码即可。 + **若您不填写,将会在启动时请求扫码登录。** + + ```yaml + account: # 账号相关 + uin: 1233456 # QQ账号 + password: '' # 密码为空时使用扫码登录 + encrypt: false # 是否开启密码加密 + status: 0 # 在线状态 请参考 https://docs.go-cqhttp.org/guide/config.html#在线状态 + relogin: # 重连设置 + delay: 3 # 首次重连延迟, 单位秒 + interval: 3 # 重连间隔 + max-times: 0 # 最大重连次数, 0为无限制 + ``` + + 2. 修改websocket端口(必需) + + 在`config.yml`下方找到以下内容 + + ```yaml + - ws: + # 正向WS服务器监听地址 + address: 0.0.0.0:8080 + middlewares: + <<: *default # 引用默认中间件 + ``` + + **将`0.0.0.0:8080`改为`0.0.0.0:6700`**,保存并关闭`config.yml`。 + + 3. 若您的服务器位于公网,强烈建议您填写`access-token` (可选) + + ```yaml + # 默认中间件锚点 + default-middlewares: &default + # 访问密钥, 强烈推荐在公网的服务器设置 + access-token: '' + ``` + +4. 配置完成,重新启动go-cqhttp + +> 若启动后登录不成功,请尝试根据[此文档](https://docs.go-cqhttp.org/guide/config.html#%E8%AE%BE%E5%A4%87%E4%BF%A1%E6%81%AF)修改`device.json`的协议编号。 \ No newline at end of file From 052b834151e23a7eeb2b61b9682c14631351d554 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:46:26 +0800 Subject: [PATCH 16/23] =?UTF-8?q?doc:=20=E5=AE=8C=E5=96=84config-template.?= =?UTF-8?q?py=E7=9A=84=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-template.py b/config-template.py index dbb9283e..3ade6830 100644 --- a/config-template.py +++ b/config-template.py @@ -3,8 +3,8 @@ import logging # 消息处理协议适配器 # 目前支持以下适配器: -# - "yirimirai": YiriMirai框架适配器, 请填写mirai_http_api_config -# - "nakuru": 通过nakuru-project框架连接go-cqhttp,请填写nakuru_config +# - "yirimirai": mirai的通信框架,YiriMirai框架适配器, 请同时填写下方mirai_http_api_config +# - "nakuru": go-cqhttp通信框架,请同时填写下方nakuru_config msg_source_adapter = "yirimirai" # [必需(与nakuru二选一,取决于msg_source_adapter)] Mirai的配置 From 418bb05b4cca96487f325182b5555cdffc2a4796 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:46:58 +0800 Subject: [PATCH 17/23] =?UTF-8?q?doc:=20=E6=B7=BB=E5=8A=A0go-cqhttp?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ++++++++++++++++++++--- README_en.md | 17 ++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d4ffc9ff..4f47a1db 100644 --- a/README.md +++ b/README.md @@ -192,10 +192,27 @@ - 请使用Python 3.9.x以上版本 -#### 配置Mirai +#### 配置QQ登录框架 -按照[此教程](https://yiri-mirai.wybxc.cc/tutorials/01/configuration)配置Mirai及YiriMirai -启动mirai-console后,使用`login`命令登录QQ账号,保持mirai-console运行状态 +目前支持mirai和go-cqhttp,配置任意一个即可 + +
+mirai + +1. 按照[此教程](https://yiri-mirai.wybxc.cc/tutorials/01/configuration)配置Mirai及mirai-api-http +2. 启动mirai-console后,使用`login`命令登录QQ账号,保持mirai-console运行状态 +3. 在下一步配置主程序时请在config.py中将`msg_source_adapter`设为`yirimirai` + +
+ +
+go-cqhttp + +1. 按照[此文档](https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE)配置go-cqhttp +2. 启动go-cqhttp,确保登录成功,保持运行 +3. 在下一步配置主程序时请在config.py中将`msg_source_adapter`设为`nakuru` + +
#### 配置主程序 diff --git a/README_en.md b/README_en.md index ffffab53..92ca57b8 100644 --- a/README_en.md +++ b/README_en.md @@ -107,11 +107,26 @@ Use [this installer](https://github.com/RockChinQ/qcg-installer) to deploy. - Python 3.9.x or higher -#### Configure Mirai +#### 配置QQ登录框架 + +Currently supports mirai and go-cqhttp, configure either one + +
+mirai Follow [this tutorial(cn)](https://yiri-mirai.wybxc.cc/tutorials/01/configuration) to configure Mirai and YiriMirai. After starting mirai-console, use the `login` command to log in to the QQ account, and keep the mirai-console running. +
+ +
+go-cqhttp + +1. Follow [this tutorial(cn)](https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE) to configure go-cqhttp. +2. Start go-cqhttp, make sure it is logged in and running. + +
+ #### Configure QChatGPT 1. Clone the repository From 270a632789932599b317614774af620a98276aca Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:48:28 +0800 Subject: [PATCH 18/23] =?UTF-8?q?doc:=20=E4=BF=AE=E6=94=B9=E6=A0=87?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f47a1db..400d66f6 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ - 请使用Python 3.9.x以上版本 -#### 配置QQ登录框架 +#### ① 配置QQ登录框架 目前支持mirai和go-cqhttp,配置任意一个即可 @@ -214,7 +214,7 @@ -#### 配置主程序 +#### ② 配置主程序 1. 克隆此项目 From 1bee7a146bf9fbca509a29f9715b022bff4ae717 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:55:21 +0800 Subject: [PATCH 19/23] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=AF=AD?= =?UTF-8?q?=E9=9F=B3=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/sources/nakuru.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/qqbot/sources/nakuru.py b/pkg/qqbot/sources/nakuru.py index 25363371..6ce36c6e 100644 --- a/pkg/qqbot/sources/nakuru.py +++ b/pkg/qqbot/sources/nakuru.py @@ -45,7 +45,10 @@ class NakuruProjectMessageConverter(MessageConverter): elif type(component) is mirai.AtAll: nakuru_msg_list.append(nkc.AtAll()) elif type(component) is mirai.Voice: - pass + if component.url is not None: + nakuru_msg_list.append(nkc.Record.fromURL(component.url)) + elif component.path is not None: + nakuru_msg_list.append(nkc.Record.fromFileSystem(component.path)) elif type(component) is Forward: # 转发消息 yiri_forward_node_list = component.node_list From 449e0247715ca1980a8125b5e939d871ae841b4e Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 15:59:07 +0800 Subject: [PATCH 20/23] =?UTF-8?q?doc:=20=E6=B7=BB=E5=8A=A0=E9=92=88?= =?UTF-8?q?=E5=AF=B9=E8=80=81=E7=94=A8=E6=88=B7=E7=9A=84=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- res/wiki/go-cqhttp配置.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/wiki/go-cqhttp配置.md b/res/wiki/go-cqhttp配置.md index c7a496c1..0868d64c 100644 --- a/res/wiki/go-cqhttp配置.md +++ b/res/wiki/go-cqhttp配置.md @@ -1,5 +1,7 @@ # 配置go-cqhttp用于登录QQ +> 若您是从旧版本升级到此版本以使用go-cqhttp的用户,请您按照`config-template.py`的内容修改`config.py`,添加`msg_source_adapter`配置项并将其设为`nakuru`,同时添加`nakuru_config`字段按照说明配置。 + ## 步骤 1. 从[go-cqhttp的Release](https://github.com/Mrs4s/go-cqhttp/releases/latest)下载最新的go-cqhttp可执行文件(建议直接下载可执行文件压缩包,而不是安装器) From b5fa2ea8b898186e1ac05ab4acb165a161d9d71e Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 16:01:43 +0800 Subject: [PATCH 21/23] =?UTF-8?q?feat(main.py):=20=E6=B7=BB=E5=8A=A0nakuru?= =?UTF-8?q?-project-idk=E7=9A=84=E4=BE=9D=E8=B5=96=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index c60aca82..725e6578 100644 --- a/main.py +++ b/main.py @@ -47,7 +47,7 @@ def init_db(): def ensure_dependencies(): import pkg.utils.pkgmgr as pkgmgr - pkgmgr.run_pip(["install", "openai", "Pillow", "--upgrade", + pkgmgr.run_pip(["install", "openai", "Pillow", "nakuru-project-idk", "--upgrade", "-i", "https://pypi.douban.com/simple/", "--trusted-host", "pypi.douban.com"]) From 15a1f00b7390ff8110fba59bc4292ee7489314f0 Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 16:04:25 +0800 Subject: [PATCH 22/23] =?UTF-8?q?doc(README.md):=20=E6=B7=BB=E5=8A=A0go-cq?= =?UTF-8?q?http=E5=85=AC=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 400d66f6..1fbdcd6b 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/QChatGPT?style=flat-square)](https://github.com/RockChinQ/QChatGPT/releases/latest) +> 2023/4/24 支持使用go-cqhttp登录QQ,请查看[此文档](https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE) > 2023/3/18 现已支持GPT-4 API(内测),请查看`config-template.py`中的`completion_api_params` > 2023/3/15 逆向库已支持New Bing,使用方法查看[插件文档](https://github.com/RockChinQ/revLibs) From 253ef44d1737f7afd291a0465464c5cf98f6eb6b Mon Sep 17 00:00:00 2001 From: Rock Chin <1010553892@qq.com> Date: Mon, 24 Apr 2023 16:05:47 +0800 Subject: [PATCH 23/23] =?UTF-8?q?chore:=20=E5=85=AC=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- res/announcement.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/res/announcement.json b/res/announcement.json index 0637a088..3c475860 100644 --- a/res/announcement.json +++ b/res/announcement.json @@ -1 +1,8 @@ -[] \ No newline at end of file +[ + { + "id": 0, + "time": "2023-04-24 16:05:20", + "timestamp": 1682323520, + "content": "现已支持使用go-cqhttp替换mirai作为QQ登录框架, 请更新并查看 https://github.com/RockChinQ/QChatGPT/wiki/go-cqhttp%E9%85%8D%E7%BD%AE" + } +] \ No newline at end of file