From f8f42678d1abcc410f030f4daaf8c69a090cb17e Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Mon, 1 Jan 2024 11:34:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20=E6=B6=88=E6=81=AF?= =?UTF-8?q?=20send()=20=E4=B8=8D=E8=83=BD=E5=A4=9F=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cores/qqbot/core.py | 10 ------- model/platform/_platfrom.py | 22 ++++++++++++++- model/platform/qq_gocq.py | 52 +++++++++++++++++++++++------------ model/platform/qq_official.py | 45 ++++++++++++++++++------------ 4 files changed, 83 insertions(+), 46 deletions(-) diff --git a/cores/qqbot/core.py b/cores/qqbot/core.py index b8983c32a..57c8e4d21 100644 --- a/cores/qqbot/core.py +++ b/cores/qqbot/core.py @@ -68,16 +68,6 @@ init_astrbot_config_items() # 全局对象 _global_object: GlobalObject = None -# def new_sub_thread(func, args=()): -# thread = threading.Thread(target=_runner, args=(func, args), daemon=True) -# thread.start() - -# def _runner(func: Callable, args: tuple): -# loop = asyncio.new_event_loop() -# asyncio.set_event_loop(loop) -# loop.run_until_complete(func(*args)) -# loop.close() - # 统计消息数据 def upload(): global version diff --git a/model/platform/_platfrom.py b/model/platform/_platfrom.py index 4afca9c70..7dc65678b 100644 --- a/model/platform/_platfrom.py +++ b/model/platform/_platfrom.py @@ -1,4 +1,7 @@ import abc +import threading +import asyncio +from typing import Callable class Platform(): def __init__(self, message_handler: callable) -> None: @@ -27,4 +30,21 @@ class Platform(): ''' 发送消息(主动发送) ''' - pass \ No newline at end of file + pass + + @abc.abstractmethod + def send(): + ''' + 发送消息(主动发送)同 send_msg() + ''' + pass + + def new_sub_thread(self, func, args=()): + thread = threading.Thread(target=self._runner, args=(func, args), daemon=True) + thread.start() + + def _runner(self, func: Callable, args: tuple): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + loop.run_until_complete(func(*args)) + loop.close() diff --git a/model/platform/qq_gocq.py b/model/platform/qq_gocq.py index 60b6ca843..0a4d58e63 100644 --- a/model/platform/qq_gocq.py +++ b/model/platform/qq_gocq.py @@ -25,7 +25,9 @@ class FakeSource: class QQGOCQ(Platform): def __init__(self, cfg: dict, message_handler: callable) -> None: super().__init__(message_handler) - asyncio.set_event_loop(asyncio.new_event_loop()) + + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) self.waiting = {} self.gocq_cnt = 0 @@ -57,10 +59,12 @@ class QQGOCQ(Platform): async def _(app: CQHTTP, source: GroupMessage): if self.cc.get("gocq_react_group", True): if isinstance(source.message[0], Plain): - await self.handle_msg(source, True) + # await self.handle_msg(source, True) + self.new_sub_thread(self.handle_msg, (source, True)) elif isinstance(source.message[0], At): if source.message[0].qq == source.self_id: - await self.handle_msg(source, True) + # await self.handle_msg(source, True) + self.new_sub_thread(self.handle_msg, (source, True)) else: return @@ -68,7 +72,8 @@ class QQGOCQ(Platform): async def _(app: CQHTTP, source: FriendMessage): if self.cc.get("gocq_react_friend", True): if isinstance(source.message[0], Plain): - await self.handle_msg(source, False) + # await self.handle_msg(source, False) + self.new_sub_thread(self.handle_msg, (source, False)) else: return @@ -84,16 +89,19 @@ class QQGOCQ(Platform): async def _(app: CQHTTP, source: Notify): print(source) if source.sub_type == "poke" and source.target_id == source.self_id: - await self.handle_msg(source, False) + # await self.handle_msg(source, False) + self.new_sub_thread(self.handle_msg, (source, False)) @gocq_app.receiver("GuildMessage") async def _(app: CQHTTP, source: GuildMessage): if self.cc.get("gocq_react_guild", True): if isinstance(source.message[0], Plain): - await self.handle_msg(source, True) + # await self.handle_msg(source, True) + self.new_sub_thread(self.handle_msg, (source, True)) elif isinstance(source.message[0], At): if source.message[0].qq == source.self_tiny_id: - await self.handle_msg(source, True) + # await self.handle_msg(source, True) + self.new_sub_thread(self.handle_msg, (source, True)) else: return @@ -149,7 +157,7 @@ class QQGOCQ(Platform): if message_result is None: return - await self.reply_msg(message, message_result.result_message) + self.reply_msg(message, message_result.result_message) if message_result.callback is not None: message_result.callback() @@ -157,7 +165,7 @@ class QQGOCQ(Platform): if session_id in self.waiting and self.waiting[session_id] == '': self.waiting[session_id] = message - async def reply_msg(self, + def reply_msg(self, message: Union[GroupMessage, FriendMessage, GuildMessage, Notify], result_message: list): """ @@ -199,10 +207,12 @@ class QQGOCQ(Platform): # 回复消息链 if isinstance(res, list) and len(res) > 0: if source.type == "GuildMessage": - await self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, res) + # await self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, res) + asyncio.run_coroutine_threadsafe(self.client.sendGuildChannelMessage(source.guild_id, source.channel_id, res), self.loop).result() return elif source.type == "FriendMessage": - await self.client.sendFriendMessage(source.user_id, res) + # await self.client.sendFriendMessage(source.user_id, res) + asyncio.run_coroutine_threadsafe(self.client.sendFriendMessage(source.user_id, res), self.loop).result() return elif source.type == "GroupMessage": # 过长时forward发送 @@ -225,29 +235,35 @@ class QQGOCQ(Platform): node.time = int(time.time()) # print(node) nodes=[node] - await self.client.sendGroupForwardMessage(source.group_id, nodes) + # await self.client.sendGroupForwardMessage(source.group_id, nodes) + asyncio.run_coroutine_threadsafe(self.client.sendGroupForwardMessage(source.group_id, nodes), self.loop).result() return - await self.client.sendGroupMessage(source.group_id, res) + # await self.client.sendGroupMessage(source.group_id, res) + asyncio.run_coroutine_threadsafe(self.client.sendGroupMessage(source.group_id, res), self.loop).result() return - async def send_msg(self, message: Union[GroupMessage, FriendMessage, GuildMessage, Notify], result_message: list): + def send_msg(self, message: Union[GroupMessage, FriendMessage, GuildMessage, Notify], result_message: list): ''' 提供给插件的发送QQ消息接口。 参数说明:第一个参数可以是消息对象,也可以是QQ群号。第二个参数是消息内容(消息内容可以是消息链列表,也可以是纯文字信息)。 + 非异步 ''' try: - await self.reply_msg(message, result_message) + # await self.reply_msg(message, result_message) + self.reply_msg(message, result_message) except BaseException as e: raise e - async def send(self, + def send(self, to, res): ''' 同 send_msg() + 非异步 ''' try: - await self.send_msg(to, res) + # await self.send_msg(to, res) + self.reply_msg(to, res) except BaseException as e: raise e @@ -293,7 +309,7 @@ class QQGOCQ(Platform): 返回一个方法调用器,可以用来立即调用nakuru的方法。 """ try: - ret = asyncio.run_coroutine_threadsafe(func(*args, **kwargs), self.gocq_loop).result() + ret = asyncio.run_coroutine_threadsafe(func(*args, **kwargs), self.loop).result() return ret except BaseException as e: raise e diff --git a/model/platform/qq_official.py b/model/platform/qq_official.py index e7d0338eb..40b965bb7 100644 --- a/model/platform/qq_official.py +++ b/model/platform/qq_official.py @@ -29,14 +29,16 @@ class botClient(Client): # 转换层 nakuru_guild_message = gocq_compatible_receive(message) gu.log(f"转换后: {str(nakuru_guild_message)}", gu.LEVEL_DEBUG, max_len=9999) - await self.platform.handle_msg(nakuru_guild_message, is_group=True) + # await self.platform.handle_msg(nakuru_guild_message, is_group=True) + self.platform.new_sub_thread(self.platform.handle_msg, (nakuru_guild_message, True)) # 收到私聊消息 async def on_direct_message_create(self, message: DirectMessage): # 转换层 nakuru_guild_message = gocq_compatible_receive(message) gu.log(f"转换后: {str(nakuru_guild_message)}", gu.LEVEL_DEBUG, max_len=9999) - await self.platform.handle_msg(nakuru_guild_message, is_group=False) + # await self.platform.handle_msg(nakuru_guild_message, is_group=False) + self.platform.new_sub_thread(self.platform.handle_msg, (nakuru_guild_message, False)) class QQOfficial(Platform): @@ -109,7 +111,7 @@ class QQOfficial(Platform): if message_result is None: return - await self.reply_msg(message, message_result.result_message) + self.reply_msg(message, message_result.result_message) if message_result.callback is not None: message_result.callback() @@ -117,7 +119,7 @@ class QQOfficial(Platform): if session_id in self.waiting and self.waiting[session_id] == '': self.waiting[session_id] = message - async def reply_msg(self, + def reply_msg(self, message: NakuruGuildMessage, res: list): ''' @@ -158,7 +160,8 @@ class QQOfficial(Platform): data['file_image'] = image_path try: - await self._send_wrapper(**data) + # await self._send_wrapper(**data) + self._send_wrapper(**data) except BaseException as e: print(e) # 分割过长的消息 @@ -168,40 +171,48 @@ class QQOfficial(Platform): split_res.append(plain_text[len(plain_text)//2:]) for i in split_res: data['content'] = i - await self._send_wrapper(**data) + # await self._send_wrapper(**data) + self._send_wrapper(**data) else: # 发送qq信息 try: # 防止被qq频道过滤消息 plain_text = plain_text.replace(".", " . ") - await self._send_wrapper(**data) + # await self._send_wrapper(**data) + self._send_wrapper(**data) + except BaseException as e: try: data['content'] = str.join(" ", plain_text) - await self._send_wrapper(**data) + # await self._send_wrapper(**data) + self._send_wrapper(**data) except BaseException as e: plain_text = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '[被隐藏的链接]', str(e), flags=re.MULTILINE) plain_text = plain_text.replace(".", "·") data['content'] = plain_text - await self._send_wrapper(**data) + # await self._send_wrapper(**data) + self._send_wrapper(**data) - async def _send_wrapper(self, **kwargs): - await self.client.api.post_message(**kwargs) + def _send_wrapper(self, **kwargs): + # await self.client.api.post_message(**kwargs) + asyncio.run_coroutine_threadsafe(self.client.api.post_message(**kwargs), self.loop).result() - async def send_msg(self, channel_id: int, message_chain: list, message_id: int = None): + def send_msg(self, channel_id: int, message_chain: list, message_id: int = None): ''' - 推送消息, 如果有 message_id,那么就是回复消息。 + 推送消息, 如果有 message_id,那么就是回复消息。非异步。 ''' _n = NakuruGuildMessage() _n.channel_id = channel_id _n.message_id = message_id - await self.reply_msg(_n, message_chain) + # await self.reply_msg(_n, message_chain) + self.reply_msg(_n, message_chain) - async def send(self, message_obj, message_chain: list): + def send(self, message_obj, message_chain: list): ''' - 发送信息。内容同 reply_msg + 发送信息。内容同 reply_msg。非异步。 ''' - await self.reply_msg(message_obj, message_chain) + # await self.reply_msg(message_obj, message_chain) + self.reply_msg(message_obj, message_chain) def wait_for_message(self, channel_id: int) -> NakuruGuildMessage: '''