RockChinQ / QChatGPT

😎高稳定性、🧩支持扩展、🦄多模态的 ChatGPT QQ / QQ频道 / One Bot 机器人🤖 | 支持 OpenAI GPT、GPT 4o、Claude、Gemini Pro、DeepSeek、Moonshot(Kimi)、gpt4free、One API、Ollama 的 QQ / QQ频道 / OneBot 机器人 / Agent 平台
https://q.rkcn.top
GNU Affero General Public License v3.0
4.14k stars 326 forks source link

[Feature]: 主动消息撤回 #564

Open For-Lin0601 opened 11 months ago

For-Lin0601 commented 11 months ago

这是一个?

新功能

详细描述

我在QChatGPT\pkg\qqbot\sources\yirimirai.py中加入了如下适配器:

    async def recall(self, massage_id):
        return await self.bot.recall(massage_id)

此注册器在python\Lib\site-packages\mirai\bot.pyi中有如下描述(第1009行开始):

    @type_check_only
    class __RecallProxy():
        async def set(self, target: int) -> Response:
            撤回消息。

            Args:
                target (`int`): 需要撤回的消息的 message_id。

    @overload
    @property
    def recall(self) -> __RecallProxy:
        撤回消息。

    @overload
    async def recall(self, target: int) -> Response:
        撤回消息。

        Args:
            target (`int`): 需要撤回的消息的 message_id。

他们的具体实现我在python\Lib\site-packages\miraicle\mirai.py中找到了疑似的方法(第330行开始):

    def recall(self, msg_id: int):
        撤回消息
        :param msg_id: 需要撤回的消息的 messageId
        :return: mirai-api-http 的响应
        content = {'sessionKey': self.session_key,
                   'target': msg_id}
        if self.adapter == 'http':
            response = self.__session.post(url=f'{self.base_url}/recall', json=content).json()
            return response
        elif self.adapter == 'ws':
            response = self.__ws_send(command='recall', content=content)
            return response

但是并不能工作,具体的报错反馈如下

[2023-09-11 21:13:54.992] host.py (373) - [ERROR] : 插件randoming触发事件person_command_sent时发生错误
[2023-09-11 21:13:54.992] host.py (374) - [ERROR] : Traceback (most recent call last):
  File "C:\QChatGPT_file\bot3\QChatGPT\.\pkg\plugin\host.py", line 367, in emit
    hook(plugin['instance'], **kwargs)
  File "C:\QChatGPT_file\bot3\QChatGPT\.\plugins\randomimg\main.py", line 356, in person_normal_message_received
    tmp = asyncio.run(adapter.recall(note_message.message_id))  # massage_id=note_message.message_id))
  File "asyncio\runners.py", line 44, in run
  File "asyncio\base_events.py", line 649, in run_until_complete
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\models\api.py", line 415, in __call__
    return await self.set(*args, **kwargs)
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\models\api.py", line 383, in set
    return await self._call_api(
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\models\api.py", line 373, in _call_api
    return await api.call(self.api_provider, method, response_type)
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\models\api.py", line 304, in call
    raw_response = await api_provider.call_api(
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\bot.py", line 91, in call_api
    return await self._adapter.call_api(api, *args, **kwargs)
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\adapters\websocket.py", line 236, in call_api
    return await self._recv(sync_id)
  File "C:\QChatGPT_file\bot3\python\lib\site-packages\mirai\adapters\websocket.py", line 165, in _recv
    raise exceptions.ApiError(data)
mirai.exceptions.ApiError: (400, '[ERROR 400]参数错误。', '无效参数')

目测为mirai-api-http的问题。

此外,有一些事件并不能监听到。比如:好友头像戳一戳事件。这里我想说明一下,qq的戳一戳有三类,头像戳一戳无法监听(logging.debug也不行),然后才是class Poke,也就是正常的戳一戳动态表情,此类方法能被正常监听。但是戳一戳动态表情里面只有前三个能正常监听,后面的内容不知道是一个什么类,反正不是Poke,也不能被message_chain[1].type in ["Poke"]:这个代码捕捉,日志记录如下,几乎像一个文本了都: 正常戳一戳日志:

2023-09-11 21:23:48 V/Bot.3353064953: 醉饮红尘外(1636708665) -> [mirai:poke:,1,0]
2023-09-11 21:23:48 V/Bot.3353064953: Friend(1636708665) <- [mirai:poke:戳一戳,1,-1]

异常戳一戳日志:

2023-09-11 21:22:46 V/Bot.3353064953: 醉饮红尘外(1636708665) -> [点赞]请使用最新版本手机QQ查看。
> [2023-09-11 21:22:46.799] message.py (26) - [INFO] : [person_1636708665]发送消息:[点赞]请使用最新版本手机QQ查看。

但是除了头像戳一戳事件,别的戳一戳都能够通过Poke类正常发送。

这个戳一戳可能也和撤回消息有关?因为我手动用bot的QQ撤回也得不到返回值,按理说应该有一个Response的返回值,但反正logging.debug也监听不到bot的手动撤回消息事件

RockChinQ commented 11 months ago

YiriMirai使用了比较抽象的元编程方式对mah接口进行映射,目前估计问题是协议兼容性问题,待复现并查明

RockChinQ commented 11 months ago

这个戳一戳问题,是mirai配置导致的,你得用支持接收戳一戳的协议(手机QQ应该可以),具体请到mirai的仓库去找