教程

阅读须知

  1. 本教程以提供大概思路为主,讲的话应该都通俗易懂。
  2. 代码为本人早期所写,想到啥就写啥,顺着往下写,所以存在大量的回调地狱(各位大佬请嘴下留情)
  3. 本教程基于Mirai平台,且无需数据库,NodeJs 等环境,仅需一个浏览器
  4. 本套代码虽然屎山但是经过了本人长时间运行认证,稳定运行
  5. 群友太牛逼,感觉再不发点啥就感觉自己快成 fw 了

案例演示

QQ截图20230430160358.png

开始之前

你首先得需要知道:

  1. Mirai-http-api文档:https://docs.mirai.mamoe.net/mirai-api-http/
  2. MCSManager API文档:https://docs.mcsmanager.com/#/zh-cn/
  3. 一些htmljs知识(至于为啥用 html 你往下看就知道了)

你需要准备以下东西:

  1. 一个干净的html文件
  2. Axios库:https://www.axios-http.cn/docs/intro
  3. 一个 Mirai 机器人,并且已经装好了mirai-http-api插件
  4. 一个 MCSManager 9

准备思路

  1. 我得先连上 mirai 的 websocket(以下简称 ws),用于接收消息
  2. 将接收到的消息加以判断,然后执行相关的代码,做你想做的事
    那,你听懂了吗?

第一步

使用 VSCode 生成一个.html文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
</html>

第二步

引入Axios库,这里我用的是 360CDN

<script src="https://lib.baomitu.com/axios/latest/axios.min.js"></script>

第三步

body标签内创建一个 a 链接,href 属性填上javascript:start()start则是下边启动 bot 的函数名

<a href="javascript:start()" style>启动 MCSM</a>

第四步

</body>前面写<script>标签,并在里面写上以下 js 代码

function start() {}

第五步

重要的来了,这里开始配置 mirai-http-api 插件。

5.1

打开插件配置文件,在第一行你会看见adapters这几个英文字母,你不需要知道这是啥意思,只需要根据下边配置就行:

adapters:
  - http
  - ws

5.2

往下拉,看见这两个选项没?意思是开启认证流程,这一步很重要

enableVerify: true   // 开启认证
verifyKey: lazy666   // 认证密钥

5.3

再往下拉,你就会看见adapterSettings这几个英文字母,同样,根据下边配置就行:

adapterSettings:
  // 开启http监听
  http:
    host: 192.168.1.9  // 服务器ipv4地址
    port: 2345         // http端口
    cors: [*]          // 允许跨域请求
  ws:
    //开启Websocket监听
    host: 192.168.1.9  //这里跟上边http保持一致
    port: 2345
    reservedSyncId: -1

配置好后保存文件,重启 mirai 机器人。如果控制台出现以下字样则说明配置成功

2023-03-28 21:56:27 I/Mirai HTTP API: ********************************************************
2023-03-28 21:56:27 I/MahKtorAdapter[http,ws]: Autoreload is disabled because the development mode is off.
2023-03-28 21:56:28 I/MahKtorAdapter[http,ws]: Application started in 0.447 seconds.
2023-03-28 21:56:28 I/MahKtorAdapter[http,ws]: Responding at http://192.168.1.9:2345
2023-03-28 21:56:28 I/http adapter: >>> [http adapter] is listening at http://192.168.1.9:2345
2023-03-28 21:56:28 I/ws adapter: >>> [ws adapter] is listening at ws://192.168.1.9:2345
2023-03-28 21:56:28 I/Mirai HTTP API: Http api server is running with verifyKey: lazy666
2023-03-28 21:56:28 I/Mirai HTTP API: adaptors: [http,ws]
2023-03-28 21:56:28 I/Mirai HTTP API: ********************************************************

(为了防止有人杠特地说明一下,这是上次服务器炸掉再开启的日志)

第六步

返回到刚才写的 html 文件下边的 js 代码部分,我们现在开始准备连接 mirai 机器人。通过查文档可知,准备连接第一步,那就是认证。然后我们在刚才的start函数里面写上以下内容:

// 认证
axios
  .post("http://192.168.1.9:2345/verify", {
    verifyKey: "lazy666", // 这里是你刚才设置的 verifyKey
  })
  .then(function (res) {
    console.log(res);
  })
  .catch(function (err) {
    // 如果有错误就控制台打印
    console.log(err);
  });

保存后运行 html 文件,点击 启动 MCSM ,按 F12 打开浏览器控制台,不出意外你就会看见以下内容:
QQ截图20230430034459.png
里面的data就是我们需要的东西。至此,认证环节结束。

第七步

这一步将要进行 绑定 环节(这里我默认你的 mirai 上有且仅有一个 QQ 号),并且从这里开始将会是回调地狱的开始,请注意关闭编辑器的代码自动换行功能!。
将上边第六步 认证 的代码复制一份,粘贴到第六步代码的.then里面,然后稍作修改,大概像下边这样

// 认证
axios
  .post("http://192.168.1.9:2345/bind", {
    sessionKey: res.data.session, // 第六步获取到的 sessionKey
    qq: 123456789, // mirai上登陆的QQ号
  })
  .then(function () {
    // 绑定成功
  })
  .catch(function (err) {
    console.log(err);
  });

第八步

既然前边的认证和绑定工作都做完了,下边开始就需要进行连接了。
注意:从现在开始我们都在 绑定 的.then里面开工。

8.1

新建一个 Websocket 连接(里面的参数根据自己的配置来调整):

let ws = new WebSocket(
  "ws://192.168.1.9:2345/all?verifyKey=lazy666&qq=123456789&sessionKey=" +
    res.data.session
);

8.2

使用ws.onmessage来获取服务器端返回的数据,并使用JSON.parse()方法将接收到的数据转换为 JavaScript 对象。

ws.onmessage = function (evt) {
  let msg = JSON.parse(evt.data);
  console.log(msg);
};

此时,刷新网页再次运行,你应该可以顺利地在控制台看到输出了:
QQ截图20230430142246.png

第九步

这时我们的连接工作就已经全部做完了,下边开始就可以按照你的兴趣进行发挥了。
这里先进行一个简单的判断,看看是好友消息还是群消息(注意是在ws.onmessage里面写)

// 判断好友,群聊
if (msg.data.type === "GroupMessage") {
  // 如果是群聊消息
  // 这里还可以再加一层if判断,可以做到黑/白名单的效果
  // 这里我加的是:判断群里说话的那个人的QQ号是不是2211717435,如果是就执行相应的代码(白名单效果)
  if (msg.data.sender.id === 2211717435) {
    // 示例代码:如果他在群里说了个 6,则机器人对他说牛逼
    if (msg.data.messageChain[1].text === "6") {
      axios.post("http://192.168.1.9:2345/sendGroupMessage", {
        sessionKey: res.data.session, // 前面获取到的 sessionKey
        target: msg.data.sender.group.id, // 要把消息发送到哪个群?
        messageChain: [
          {
            type: "Plain",
            text: "牛逼",
          },
        ],
      });
    }
  }
} else if (msg.data.type === "FriendMessage") {
  //好友消息
  // 道理同上
  if (msg.data.sender.id === 2211717435) {
    // 一些代码
  }
}

写完后保存,运行一下,点开 QQ 试下效果:
QQ截图20230430150822.png

第十步

通过上面的代码我们可以发现,axios.post('http://192.168.1.9:2345/sendGroupMessage', {})这段代码的重复使用率是极高的,所以我们可以将它封装成一个函数来进行调用,以减少屎山高度。
在上边的 if 判断外边,定义一个发送消息的函数:

function send() {}

然后仔细观察上面那端代码,不难看出,只有sendGroupMessagetarget是变化的,所以我们可以将它看作两个参数。然后则可以写成下面的形式(这里不知道怎么说更好)

function send(sApi, sender) {
  if (msg.data.messageChain[1].text === "6") {
    axios.post("http://192.168.1.9:2345/" + sApi, {
      sessionKey: res.data.session,
      target: sender, // 要把消息发送到哪个群?
      messageChain: [
        {
          type: "Plain",
          text: "牛逼",
        },
      ],
    });
  }
}

则上面第九步的 if 判断就可以写成:

// 判断好友,群聊
if (msg.data.type == "GroupMessage") {
  // 如果是群聊消息
  if (msg.data.sender.id === 2211717435) {
    sender = msg.data.sender.group.id;
    sApi = "sendGroupMessage";

    // 调用刚才写的 send() 函数,注意位置不要搞反了
    send(sender, sApi);
  }
} else if (msg.data.type === "FriendMessage") {
  //好友消息
  // 道理同上
  if (msg.data.sender.id === 2211717435) {
    sender = msg.data.sender.id;
    sApi = "sendFriendMessage";
    send(sender, sApi);
  }
}

第十一步

从现在开始我们要在 send() 函数里面再做点文章。首先要将收到的消息进行拆分,这里我按空格进行拆分

let temp = msg.data.messageChain[1].text.split(" ");

比如说我在群里 bb 了一句/mcsm info,则会是下面的效果:

let temp = "/mcsm info".split(" ");
// 输出 => ['/mcsm', 'info']

你是不是发现了什么?输出的是一个数组诶!那我们现在就可以判断temp[下标]来执行相应的指令了。

第十二步

停!在这之前咱们先看看文章标题,mcsm 机器人,所以咱的 mcsm api 还没整呢。
所以现在先定义一下 mcsm api 地址(在上边let temp下边写就行):

let mcsmurl = "http://192.168.1.9:23333";
let apikey = "114514191810";

然后进行口令判断

// 首先必须判断是不是 /mcsm 开头
if (temp[0] == "/mcsm") {
  // 然后?接着判断啊。看看 /mcsm 后面跟的是啥
  switch (temp[1]) {
    // 这里只演示 info (获取面板信息),剩下的都大差不差
    // 因篇幅有限,仅展示部分内容
    case "info":
      axios
        // 请求mcsm对应的api
        .get(mcsmurl + "/api/overview?apikey=" + apikey)
        .then(function (overview) {
          axios
            .post("http://192.168.1.9:2345/" + sApi, {
              sessionKey: res.data.session,
              target: sender,
              messageChain: [
                {
                  type: "Plain",
                  text:
                    "系统信息:\n- 系统平台:" +
                    overview.data.data.system.platform +
                    "\n",
                },
                {
                  type: "Plain",
                  text:
                    "- 系统版本:" + overview.data.data.system.version + "\n",
                },
                {
                  type: "Plain",
                  text: "- Node版本:" + overview.data.data.system.node + "\n",
                },
                {
                  type: "Plain",
                  text: "- 面板版本:" + overview.data.data.version + "\n",
                },
              ],
            })
            .catch(function (error) {
              console.log(error);
            });
        })
        .catch(function (error) {
          console.log(error);
        });
      break;
  }
}

保存并刷新浏览器再次运行,向群里或者机器人 bb 一句/mcsm info,不出意外就可以看见效果了。

第十三步

至此,你已经学会了如何获取面板信息。你是不是还发现差了点什么?(啊对,菜单)。
返回刚才的 switch 代码段,往下添加以下内容

default:
  axios.post("http://192.168.1.9:2345/" + sApi, {
    sessionKey: res.data.session,
    target: sender,
    messageChain: [
      {
        type: "Plain",
        text: "MCSManager 菜单\n",
      },
      {
        type: "Plain",
        text: "====面板相关====\n",
      },
      {
        type: "Plain",
        text: "info 查看面板信息\n",
      },
      {
        type: "Plain",
        text: "===============\n",
      },
      {
        type: "Plain",
        text: "*开发中页面,可能是最终品质",
      },
    ],
  });

这样,人家如果只说 /mcsm ,则就会返回菜单,/mcsm info 则可以返回面板信息了

完结撒花

恭喜你,你已经学会了如何创建一个 MCSM QQ 机器人,可以去朋友面前或者群里面装逼了。实际上从第十二步开始,你完全可以自由发挥制作一个属于自己的独一无二的机器人了。

源码下载

本教程源码成品:/usr/uploads/2023/04/mcsm-bot.html
访问后直接Ctrl + S即可保存到本地

最后的最后

版权所有,转载请注明出处。如果你觉得我写的不好或者有什么意见,欢迎在评论区指出~
顺便求赞赏

微信支付

微信支付

支付宝支付

支付宝支付

评论

  1. windpop windpop
    Chrome 114

    测试进行评论

This is just a placeholder img.