node.js結合wechaty實現微信機器人[進階篇]


360截圖16530709434750.png

需求

自己一直想做一個個人的微信機器人,曾經目睹一位大佬用自己個人微信實現語音控制機器人搭建后台系統,羡慕不已的同時,自己也暗自下定決心做一個自己的微信機器人,發現wechaty的時候,似乎看到了希望,並不是超越誰而是實現目前所可以做到的。

搭建自己的微信公眾號,jd轉鏈接,圖文翻譯,智能對話,個人收藏夾目前就是這幾個,可是我發現對於小程序是不可以發送到自己的訂閱號的,還有就是jd鏈接我每次都會重復的打開微信公眾號,找到自己訂閱號后發送似乎繁瑣,所以我決定自己搞一個個人機器人解決以上的痛點。

介紹

Wechaty

Wechaty是一款適用於Chatbot Makers的現代會話 RPA SDK,可以用幾行代碼創建一個bot。

Wechaty提供了開箱即用的支持,可以將您的IM帳戶轉變為聊天機器人,從而為您提供期望的通用功能,開發人員可以輕松地對其進行自定義和擴展,以創建滿足其確切需求的聊天機器人。

世界上最短的聊天機器人

我們可以使用Wechaty用最少6行代碼構建一個聊天機器人

const { Wechaty } = require('wechaty')

async function main () {
  conswt bot = new Wechaty()
  bot
    .on('scan', (qrcode, status) => console.log(`Scan QR Code to login: ${status}\nhttps://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`))
    .on('login',            user => console.log(`User ${user} logged in`))
    .on('message',       message => console.log(`Message: ${message}`))
  await bot.start()
}

main()
  .catch(console.error)

運行代碼之前

准備好可運行Wechaty的微信號,已經申請前綴為puppet_padlocal的token

  • wechaty-puppet-padlocal:wechaty的ipad協議實現

(每個人申請的token是不同的所以使用的協議也不同,需要在入口做處理)

目前實現功能

  • 自動通過好友驗證
    • 當有人添加機器人時,判斷驗證消息關鍵字后通過或直接通過
    • 通過驗證后自動回復並介紹機器人功能
  • 私聊關鍵字回復
    • 例如回復 加群 推送群聊邀請
    • 例如回復 群聊名稱 自動拉群
  • 自動聊天
    • 群聊中配置和自己的機器人聊天
    • 私聊發送消息即可聊天
  • 解析小程序信息
  • 加入群聊自動歡迎
    • 當新的小伙伴加入群聊后自動 @[新的小伙伴] 發一個文字歡迎
    • 關鍵字觸發,發送個人卡片鏈接
    • 群內發送小程序可獲取小程序相關信息
    • 群內發送英文開啟翻譯功能,最多不可超多2000字

api接口

有道翻譯
百度翻譯

天行api

核心代碼

入口文件

bot.js

const { Wechaty } = require("wechaty");
const { PuppetPadlocal } = require("wechaty-puppet-padlocal");  // 引入協議包
const QrcodeTerminal = require("qrcode-terminal");  // 控制台二維碼
const onMessage = require("./onMessage"); // 消息監聽回調
const config = require("./config"); // 配置文件


// 實例化機器人
const bot = new Wechaty({
  puppet: new PuppetPadlocal({
    token: config.token,
  }),
});

// 添加監聽事件
bot
  // 掃碼登錄
  .on("scan", (qrcode, status) => {
    console.log(
      `Scan QR Code to login: ${status}\nhttps://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(
        qrcode
      )}`
    );
    QrcodeTerminal.generate(qrcode);
  })
  // 登錄監聽
  .on("login", (user) => {
    console.log(user, "logined");
  })
  // 退出監聽
  .on("logout", (user) => {
    console.log(user, "logout");
  })
  // 消息監聽
  .on("message", onMessage(bot))
  .start();

onMessage.js

監聽消息事件觸發,這里只判斷了接收的主要類型,文字type7,小程序type9,卡片鏈接type14,使用群聊@的時候你可能會遇到發送不成功,你可以使用另外的一種方法如果你也遇到room.say失效,然后我在獲取文本信息處理的時候加了一層判斷,因為消息監聽默認也會監聽到你所有群聊的消息,我測試的時候就遇到機器人主動和群里的人聊天,很尷尬所以拉了幾個好友組了一個測試群方便測試

 // 獲取@你的群友
 let member = msg.talker();
 // 群聊@群友回復
 let response = ‘回復給群友的內容’;
 msg.room().say(response,member);
const { UrlLink } = require("wechaty");
const request = require("request");
const urlencode = require("urlencode");
const config = require("./config");
const miniProrReply = require("../utils/miniProReply");  // 小程序參數
const translate = require("../utils/translate"); // 百度翻譯
const { rainbowFart, circle ,drugInstruction} = require("../utils/txAPI");  // 天行api
const name = config.name;
const roomList = config.room.roomList;

// 消息監聽回調
module.exports = (bot) => {
  return async function onMessage(msg) {
    // 判斷消息來自自己,直接return
    if (msg.self()) return;
    // 消息類型判斷
    switch (msg.type()) {
      case 7:
        var reg = /^[\u4e00-\u9fa5]+$/; // 文字正則
        console.log("獲取到文本");
        // 回復信息是關鍵字 “加群”     測試成功
        if (await isAddRoom(msg)) return;
        // 回復信息是所管理的群聊名    測試成功
        if (await isRoomName(bot, msg)) return;
          // 開啟機器人
          if (msg.payload.roomId) {
            // 添加判斷 不是指定群聊的信息不觸發  [不加判斷機器人,機器人會回復任意所在群聊內容。。。]
            console.log("獲取到群聊消息");
            if (msg.payload.roomId === "20856899751@chatroom") {
            // 判斷群內回復內容不為文字
              if(!reg.test(msg.text())){
                translate(msg);
                return;
              } else{
                roomMessageReply(msg);
                return;
              }
            }
          }
        break;
      case 9:
        console.log("獲取到小程序"); // 測試成功
        miniProrReply(msg);
        break;
      case 14:
        console.log("獲取到卡片鏈接"); // 測試成功
        break;
      default:
        console.log("暫時不支持該類型的接收!");
        break;
    }
  };
};

/**
 * @description 回復群聊信息 處理函數
 * @param {Object} msg 消息對象
 * @return {Promise} true-是 false-不是
 */
async function roomMessageReply(msg) {
  const room = msg.room();
  const text = msg.text();
  if (await msg.mentionSelf()) {
    // 獲取消息內容,拿到整個消息文本,去掉 @名字
    const sendText = msg.text().replace("@蔚藍", "");
    // 請求機器人接口回復
    let res = await requestRobot(sendText);
    // 返回消息,並@來自人 只可以padplus調用
    // room.say(res, msg.fromId());
    // 此處替換為群內回話
    // padlocal使用 msg函數@指定人
    // 獲取@你的群友 
    // let member = msg.talker();
    // 群聊@群友回復
    // msg.room().say(response,member);
    room.say(res);  
  } else {
    let content = await requestRobot(msg.text());
    room.say(content);
    return 
  }

  // 指定關鍵字觸發
  if (/互動/.test(text)) {
    room.say("互動測試");
    return 
  } else if(/彩虹屁/.test(text)){
    let reply = await rainbowFart(params);
    room.say(reply);
    return 
  } else if(/文案/.test(text)){
    let reply = await circle(params);
    room.say(reply);
    return 
  }else if (/蔚藍工作室/.test(text)) {
    room.say(new UrlLink(config.personal.introUrl));
    return 
  } else if(/葯品/.test(text)){
    params.word = text.substring(2);
    console.log(params);
    let reply = await drugInstruction(params);
    room.say(reply);
    return 
  }
}

/**
 * @description 回復信息是關鍵字 “加群” 處理函數
 * @param {Object} msg 消息對象
 * @return {Promise} true-是 false-不是
 */
async function isAddRoom(msg) {
  // 關鍵字 加群 處理
  if (msg.text() == "加群") {
    let roomListName = Object.keys(roomList);
    let info = `${name}當前管理群聊有${roomListName.length}個,回復群聊名即可加入哦\n\n`;
    roomListName.map((v) => {
      info += "【" + v + "】" + "\n";
    });
    msg.say(info);
    return true;
  }
  return false;
}

/**
 * @description 回復信息是所管理的群聊名 處理函數
 * @param {Object} bot 實例對象
 * @param {Object} msg 消息對象
 * @return {Promise} true-是群聊 false-不是群聊
 */
async function isRoomName(bot, msg) {
  // 回復信息為管理的群聊名
  if (Object.keys(roomList).some((v) => v == msg.text())) {
    // 通過群聊id獲取到該群聊實例
    const room = await bot.Room.find({ id: roomList[msg.text()] });
    // 獲取當前room信息
    console.log(room);
    // 判斷是否在房間中 在-提示並結束
    if (await room.has(msg.from())) {
      await msg.say("您已經在房間中了");
      return true;
    }

    // 發送群邀請
    await room.add(msg.from());
    await msg.say("已發送群邀請");
    return true;
  }
  return false;
}

/**
 * @description 機器人請求接口 處理函數
 * @param {String} info 發送文字
 * @return {Promise} 相應內容
 */
function requestRobot(info) {
  return new Promise((resolve, reject) => {
    let url = `https://open.drea.cc/bbsapi/chat/get?keyWord=${urlencode(info)}`;
    request(url, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        let res = JSON.parse(body);
        if (res.isSuccess) {
          let send = res.data.reply;
          // 免費的接口,所以需要把機器人名字替換成為自己設置的機器人名字
          send = send.replace(/Smile/g, name);
          resolve(send);
        } else {
          if (res.code == 1010) {
            resolve("沒事別老艾特我,我還以為愛情來了");
          } else {
            resolve("你在說什么,我聽不懂");
          }
        }
      } else {
        resolve("你在說什么,我腦子有點短路誒!");
      }
    });
  });
}


utils文件夾

主要存放的是一些onmessage的方法,api請求以及小程序通過xml-js提取參數類的,這部分相對簡單一些,此處不再贅述

百度翻譯 使用請到utils-translate文件替換appid以及key

天行api 使用請到src-config文件更換key保證正常使用

效果

4de6c65e83c4624b6ea90fe791cd3b1.jpg

ad0cf4c464a0ea0e2cbe74c7d6fb1fe.jpg

8e14eaa78b5a28570231048aee0060a.jpg

274fb61aa0bf250fdac31b81acc6922.jpg

常見問題

github wechaty-puppet-padplus升級說明如下:
卸載wechaty-puppet-padplus,安裝wechaty-puppet-hostie
代碼中啟動wechaty的wechaty-puppet-padplus更換成【wechaty-puppet-hostie】

npm官網 Wechaty-Puppet-Hostie模塊已重命名為wechaty-puppet-service,請改用【wechaty-puppet-service】
使用wechaty-puppet-service代替Wechaty-Puppet-Hostie

協議使用服務兼容性

免費token

padlocal 7天免費(推薦)

最后

探索token和對應協議的過程有點痛苦,不過我已經搭建好了,我會給你提供最簡單的搭建個人機器人的方式,一起交流學習

項目github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM