cyanray / mirai-cpp

本项目为 mirai-api-http 的 C++ 封装,方便使用 C++ 开发基于 mirai-api-http 插件。
GNU Affero General Public License v3.0
148 stars 38 forks source link

mirai-api-http注册成功,但是执行失败 #113

Closed NessajHu closed 2 years ago

NessajHu commented 2 years ago

mirai-cpp,mirai-http-api为2.0.2 注册命令成功,执行失败。 代码用的是examples/Command.cpp 这里我打印出了content和data.dump 输出。 Active code page: 65001 Bot working... {"alias":["hi"],"description":"指令描述描述描述","name":"hello","sessionKey":"QLVadWkQ","usage":"/hello 你想说的话"} application/json;charset=UTF-8 {"command":[{"text":"hello","type":"Plain"},{"text":"arg1","type":"Plain"},{"text":"arg2","type":"Plain"}],"sessionKey":"QLVadWkQ"} application/json;charset=UTF-8 mirai-api-http 错误: Execute command error 错误码400,错误文本见mirai-api-http/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/adapter/internal/action/command.kt 请问有解决思路吗?

cyanray commented 2 years ago

没有😂,因为我也没成功过。 本来想到mah提issues的,结果忘了。最近比较忙,我更加没时间整理资料去提issues了。 我分享下当时我遇到的一些问题,你可以复现后拿去提issues:

  1. 通过mah注册指令成功,在mirai-console执行help有显示刚注册的指令。
  2. 通过mah执行注册的指令失败。(没有提示原因)
  3. 通过mah执行内建指令失败。(这个我记不清了,印象中没成功)
  4. 通过mirai-console执行注册的指令失败。(好像是提示没有权限)

你可以再试一下在mirai-console能不能看到,以及能不能执行你注册的指令,如果不行,那我想有可能是mah方面有问题?或者我们没弄清楚指令系统的用法。

NessajHu commented 2 years ago

试了下,134是成功的。我不熟http就没试。估计是mirai-cpp某处代码有问题吧。

GekkaSaori commented 2 years ago

问题在于 mirai-cpp 的 mirai_bot 没有正确处理执行命令的流程,json 文件的第一条消息代表的不是一条指令。

错误码 400 经查 mirai-http-api 的文档得知为「错误的访问,如参数错误等」。可知 mirai-cpp 发送的指令不被 mirai-http-api 理解。

mirai-http-api 的 Command 实现是基于 mirai-console 的,在 mirai-console 文档 Command 部分中提到「指令目前通常是 "/commandName arg1 arg2 arg3" 格式的消息。」

通过 mirai-http-api 文档所给的例子可以发现执行命令时「若执行纯文本的命令, 构建多个 Plain 格式的消息 console 会将第一个消息作为指令名」。尝试将第一条消息前面加上 ‘/’,问题得以解决。

临时的 Patch(mirai_bot.cpp 第 958 行,SendCommand 函数):

void MiraiBot::SendCommand(const vector<string>& command)
{
    MessageChain mc;
    vector<string> commandCopy = command;
    commandCopy[0] = '/' + commandCopy[0];
    for (const auto& val : commandCopy)
    {
        mc.Plain(val);
    }
    json data =
    {
        { "sessionKey", pmem->sessionKey },
        { "command", mc.ToJson() }
    };

    auto res = pmem->httpClient->Post("/cmd/execute", data.dump(), CONTENT_TYPE.c_str());
    ParseOrThrowException(res);
}

图片

另外可以看到消息的发送者信息为 null,考虑消息是由 mirai console 发出的。

cyanray commented 2 years ago

问题在于 mirai-cpp 的 mirai_bot 没有正确处理执行命令的流程,json 文件的第一条消息代表的不是一条指令。

错误码 400 经查 mirai-http-api 的文档得知为「错误的访问,如参数错误等」。可知 mirai-cpp 发送的指令不被 mirai-http-api 理解。

mirai-http-api 的 Command 实现是基于 mirai-console 的,在 mirai-console 文档 Command 部分中提到「指令目前通常是 "/commandName arg1 arg2 arg3" 格式的消息。」

通过 mirai-http-api 文档所给的例子可以发现执行命令时「若执行纯文本的命令, 构建多个 Plain 格式的消息 console 会将第一个消息作为指令名」。尝试将第一条消息前面加上 ‘/’,问题得以解决。

临时的 Patch(mirai_bot.cpp 第 958 行,SendCommand 函数):

void MiraiBot::SendCommand(const vector<string>& command)
{
  MessageChain mc;
  vector<string> commandCopy = command;
  commandCopy[0] = '/' + commandCopy[0];
  for (const auto& val : commandCopy)
  {
      mc.Plain(val);
  }
  json data =
  {
      { "sessionKey", pmem->sessionKey },
      { "command", mc.ToJson() }
  };

  auto res = pmem->httpClient->Post("/cmd/execute", data.dump(), CONTENT_TYPE.c_str());
  ParseOrThrowException(res);
}

图片

另外可以看到消息的发送者信息为 null,考虑消息是由 mirai console 发出的。

原来是这样!感谢反馈!😂头大 现在应该可以通过手动补充 "/" 的方式临时补救: bot.SendCommand({ "/hello", "arg1", "arg2" }); 后续更新这个函数会兼容两种方式(有“/”和没有“/”)