需求背景
目前所在企業是一家創新型汽車後市場網際網路科技有限公司,拓展汽車後市場B2C、B2B和O2O業務。
前期打造連結線下6家自營大型汽車專業維修中心,12家自營汽車配件、汽保設備銷售中心,3000餘家加盟汽修、汽配企業及10餘萬個人客戶的服務平臺;
由於客戶維繫和供應商諮詢等都是基於微信群聊的。每天要在成百上千的群聊中提供服務。需要實時在群內產品報價,車架號識別,圖片識別,關鍵字反饋。數據推送等等功能。這樣的需求情況下,人力成本是巨大的。
而我作為一名前端開發工程師,平時也喜歡寫技術博客和交朋友,為此我也創建了微信技術交流群和微信公眾號,一般我都會在文章下面貼出公眾號和我的個人二維碼,給有興趣的小夥伴們添加微信然後我再拉他們進群這些,但是不停的同意微信好友驗證,再發送群邀請真的是太痛苦了,相信很多做公眾號的小夥伴都和我一樣,作為一名開發,這種重複勞動是絕對不能忍受的基於這種情況和公司業務情況,調研發現了並了解到了wechaty,發現其提供的功能能夠覆蓋到企業和個人微信,並且能夠自己定製化開發符合自己需求的功能。
介紹
Wechaty 是什麼
微信個人號功能非常強大和靈活,是一個非常適合用來做ChatBot的載體。它可以靈活不受限制的發送語音簡訊、視頻、圖片和文字,支持多人群聊。但是使用微信個人微信號作為ChatBot,需要通過非官方的第三方庫接入微信。因為截至2018年底,微信尚無任何官方的ChatBot API發布。
Wechaty 是一個開源的的對話機器人 SDK,支持 個人號 微信。它是一個使用Typescript 構建的Node.js 應用。支持多種微信接入方案,包括網頁,ipad,ios,windows, android 等。同時支持Linux, Windows, Darwin(OSX/Mac) 和 Docker 多個平臺。
在GitHub上可以找到很多支持微信個人號接入的第三方類庫,其中大多都是基於Web Wechat的API來實現的,如基於Python的WeixinBot,基於Node.js的Wechaty等。少數支持非Web協議的庫,大多是商業私有閉源的,Wechaty是少有的開源項目支持非Web協議的類庫。
只需要6行代碼,你就可以 通過個人號 搭建一個 微信機器人功能 ,用來自動管理微信消息。
import { Wechaty } from'wechaty'Wechaty.instance().on('scan', qrcode => console.log('掃碼登錄:' + qrcode)).on('login', user => console.log('登錄成功:' + user)).on('message', message => console.log('收到消息:' + message)).on('friendship', friendship => console.log('收到好友請求:' + friendship)).on('room-invite', invitation => console.log('收到入群邀請:' + invitation)).start()更多功能包括
消息處理:關鍵詞回復群管理:自動入群,拉人,踢人自動處理好友請求智能對話:通過簡單配置,即可加入智能對話系統,完成指定任務... 請自行開腦洞所有你能想到的交互模式。在微信上都有實現的可能。每日定時拉取天氣預報。
每天給你心愛的人發送早安和晚安信息。
什麼成語接龍啦。快問快答等等功能
當然wechaty的功能服務並不是免費的
200/月的費用,如果你是個人開發可能會斟酌一二。但是你可以通過社區申請一個長達15天的免費token來嘗試使用和開發一個小型機器人,從而決定你是否需要購買使用。
關於申請的地址我放在了這裡Wechaty Token 申請及使用文檔和常見問題
基於wechaty-puppet-hostie開發企業級微信機器人
目錄結構
├── config│ └── index.js // 配置文件├── package.json├── service│ ├── bot-service│ │ ├── error-service.js│ │ ├── friendship-service.js│ │ ├── heartbeat-service.js│ │ ├── login-service│ │ │ ├── function-service.js│ │ │ └── index.js│ │ ├── logout-service.js│ │ ├── message-service│ │ │ ├── function-service.js│ │ │ └── index.js│ │ ├── ready-service│ │ │ ├── function-service.js│ │ │ └── index.js│ │ ├── room-invite-service.js│ │ ├── room-join-service.js│ │ ├── room-leave-service.js│ │ ├── room-topic-service.js│ │ └── scan-service│ │ └── index.js│ ├── common-service│ │ ├── chatbot-service.js│ │ ├── ding-service.js│ │ └── oss-service.js│ └── redis-service│ └── index.js├── src│ └── main.js // 入口├── store│ └── index.js // 全局存儲對象├── utils│ ├── oss.js // 阿里雲oss認證│ └── redis.js // redis認證登錄└── yarn.locksrc/main.js
const { Wechaty } = require('wechaty') // 機器人木偶const { onScan } = require("../service/bot-service/scan-service") // 當機器人需要掃碼登陸的時候會觸發這個事件。const { onLogin } = require("../service/bot-service/login-service") // 當機器人成功登陸後,會觸發事件,並會在事件中傳遞當前登陸機器人的信息const { onLogout } = require("../service/bot-service/logout-service") // 當機器人檢測到登出的時候,會觸發事件,並會在事件中傳遞機器人的信息。const { onReady } = require("../service/bot-service/ready-service") // 當所有數據加載完成後,會觸發這個事件。在wechaty-puppet-padchat 中,它意味著已經加載完成Contact 和Room 的信息。const { onMessage } = require("../service/bot-service/message-service") // 當機器人收到消息的時候會觸發這個事件。const { onRoomInvite } = require("../service/bot-service/room-invite-service") // 當收到群邀請的時候,會觸發這個事件。const { onRoomTopic } = require("../service/bot-service/room-topic-service") // 當有人修改群名稱的時候會觸發這個事件。const { onRoomJoin } = require("../service/bot-service/room-join-service") // 當有人進入微信群的時候會觸發這個事件。機器人主動進入某個微信群,那個樣會觸發這個事件。const { onRoomleave } = require("../service/bot-service/room-leave-service") // 當機器人把群裡某個用戶移出群聊的時候會觸發這個時間。用戶主動退群是無法檢測到的。const { onFriendship } = require("../service/bot-service/friendship-service") // 當有人給機器人發好友請求的時候會觸發這個事件。const { onHeartbeat } = require('../service/bot-service/heartbeat-service') // 獲取機器人的心跳。const { onError } = require('../service/bot-service/error-service') // 當機器人內部出錯的時候會觸發error 事件。const { wechatyToken } = require('../config/index') // 機器人tokenconst { globalData } = require('../store/index') // 全局對象globalData.bot = new Wechaty({puppet: 'wechaty-puppet-hostie',puppetOptions: {token: wechatyToken }});globalData.bot .on('scan', onScan) .on('login', onLogin) .on('logout', onLogout) .on('ready', onReady) .on('message', onMessage) .on('room-invite', onRoomInvite) .on('room-topic', onRoomTopic) .on('room-join', onRoomJoin) .on('room-leave', onRoomleave) .on('friendship', onFriendship) .on('heartbeat', onHeartbeat) .on('error', onError) .start()具體功能實現及代碼
掃碼登錄通過node啟動後,觸發onScan事件,將登錄二維碼列印在控制臺,掃碼登錄const QrcodeTerminal = require('qrcode-terminal');const { ScanStatus } = require('wechaty-puppet')/** * @method onScan 當機器人需要掃碼登陸的時候會觸發這個事件。 建議你安裝 qrcode-terminal(運行 npm install qrcode-terminal) 這個包,這樣你可以在命令行中直接看到二維碼。 * @param {*}qrcode * @param {*}status */const onScan = async (qrcode, status) => {try {if (status === ScanStatus.Waiting) {console.log(`========================二維碼狀態:${status}========================\n\n`) QrcodeTerminal.generate(qrcode, {small: true }) } } catch (error) {console.log('onScan', error) }}module.exports = { onScan }登錄成功掃碼登錄成功後會觸發onLogin事件,通過事件接收到登錄信息和機器人信息,通過釘釘接口將登錄通知發送至釘釘群內const { notificationLoginInformation } = require('../../common-service/ding-service')const { updateBotInfo } = require('./function-service')const { globalData } = require('../../../store/index')/** * @method onLogin 當機器人成功登陸後,會觸發事件,並會在事件中傳遞當前登陸機器人的信息 * @param {*}botInfo */const onLogin = async botInfo => {try {console.log('======================== onLogin ========================\n\n')console.log(`機器人信息:${JSON.stringify(botInfo)}\n\n`)console.log(` // \\ // \\ // ##DDDDDDDDDDDDDDDDDDDDDD## ## DDDDDDDDDDDDDDDDDDDD ## ## DDDDDDDDDDDDDDDDDDDD ## ## hh hh ## ## ## ## ## ## ## ## ## ### ## #### ## ## hh // \\ hh ## ## ## ## ## ## ## ## ## ## hh // \\ hh ## ## ## ## ## ## ## ## ## ## hh hh ## ## ## ## ## ## ## ## ## ## ## hh wwww hh ## ## ## ## ## ## ## ## #### ## hh hh ## ## ## ## ## ## ## ## ## ## ## ### ## ## ### ## MMMMMMMMMMMMMMMMMMMM ## ##MMMMMMMMMMMMMMMMMMMMMM## 微信機器人名為: [${botInfo.payload.name}] 已經掃碼登錄成功了。\n\n `)// 全局存儲機器人信息 globalData.botPayload = botInfo.payload// 更新機器人列表 updateBotInfo()// 機器人登錄登出提醒/通知釘釘接口 notificationLoginInformation(true) } catch (error) {console.log(`onLogin: ${error}`) }}module.exports = { onLogin }— 機器人異常退出當node服務異常終端,或者手機上退出機器人登錄後會觸發onLogout事件,同樣釘釘群內通知信息,並且銷毀程序中運行的一些定時器等
const { notificationLoginInformation } = require('../common-service//ding-service')const { globalData } = require('../../store/index')/** * @method onLogout 當機器人檢測到登出的時候,會觸發事件,並會在事件中傳遞機器人的信息。 * @param {*}botInfo */const onLogout = async botInfo => {try {console.log('======================== onLogout ========================')console.log(`當bot檢測到註銷時,將與當前登錄用戶的聯繫人發出註銷。`)// 全局存儲機器人信息 globalData.botPayload = botInfo.payloadconst { updateRoomInfoTimer, chatbotSayQueueTimer } = globalData// 機器人退出清空定時器if (updateRoomInfoTimer) { clearTimeout(updateRoomInfoTimer) }if (chatbotSayQueueTimer) { clearInterval(chatbotSayQueueTimer) }// 機器人登錄登出提醒/通知釘釘接口 notificationLoginInformation(false) } catch (error) {console.log(`error in onLogout:${error}`) }}module.exports = { onLogout }消息接收處理當微信接收到新的消息時候會觸發onMessage事件,通過事件內對消息的判斷,群內消息還是私聊消息等做出不同的邏輯處理。從而實現業務需求。部分代碼如下const dayjs = require('dayjs');const { say } = require('../../common-service/chatbot-service')const { isCanSay, roomIdentifyVin, rooImageIdentifyVin, contactIdentifyVin, contactImageIdentifyVin, messageProcessing, storageRoomMessage, storageContactMessage,} = require('./function-service')const { roomMessageFeedback, contactMessageFeedback} = require('../../common-service/ding-service')const { globalData } = require('../../../store/index');const { Message } = require('wechaty');/** * @method onMessage 當機器人收到消息的時候會觸發這個事件。 * @param {*} message */const onMessage = async message => {try {console.log('======================== onMessage ========================\n\n')// 機器人信息const { botPayload } = globalData// 獲取發送消息的聯繫人const contact = message.from()// 獲取消息所在的微信群,如果這條消息不在微信群中,會返回null const room = message.room()// 查看這條消息是否為機器人發送的const isSelf = message.self()// 處理消息內容const text = await messageProcessing(message)// console.log(`======================== 處理消息後內容為:${text} ========================\n\n`)// 消息為空不處理if (!text) return// 消息詳情const messagePayload = message.payload// console.log(`======================== 消息詳情:${JSON.stringify(messagePayload)} ========================\n\n`)// 消息聯繫人詳情const contactPayload = contact.payload// console.log(`======================== 消息聯繫人詳情:${JSON.stringify(contactPayload)} ========================\n\n`)// 群消息if (room) {console.log(`======================== 群聊消息 ========================\n\n`)// 房間詳情const roomPayload = room.payload// console.log(`======================== 房間詳情:${JSON.stringify(roomPayload)} ========================\n\n`)console.log(`消息時間:${dayjs(messagePayload.timestamp).format('YYYY-MM-DD HH:mm:ss')}\n\n群聊名稱:${roomPayload.topic}\n\n微信名稱:${contactPayload.name}\n\n微信類型:${contactPayload.type}\n\n備註暱稱:${contactPayload.alias}\n\n消息內容:${text}\n\n消息類型:${messagePayload.type}\n\n`);// 存儲消息內容const storeMessage = {category: 'room', // 消息類別,room為群聊消息, contact為個人消息。isSelf: isSelf, // 是否自己發送的消息messageId: messagePayload.id, // 消息idmessageToId: messagePayload.toId, // 消息接收者idmessageType: messagePayload.type, // 消息類型messageText: text, // 消息內容messageTimestamp: messagePayload.timestamp, // 消息時間戳messageTime: dayjs(messagePayload.timestamp).format('YYYY-MM-DD HH:mm:ss'), // 消息時間roomOwnerId: roomPayload.ownerId, // 群聊群主idroomTopic: roomPayload.topic, // 群聊名稱roomId: roomPayload.id, // 群聊名稱contactId: contactPayload.id, // 消息發送者idcontactName: contactPayload.name, // 消息發送者暱稱contactType: contactPayload.type, // 消息發送者類型contactAvatar: contactPayload.avatar, // 消息發送者頭像contactAlias: contactPayload.alias, // 消息發送者備註 }// redis中存儲群聊消息內容 storageRoomMessage(roomPayload, storeMessage)// 消息是機器人自己發的 或者 消息發送到wechaty接收間隔大於半個小時if (isSelf || message.age() > 1800) return// 判斷當前機器人在群中是否可以說話 if (!await isCanSay(roomPayload)) return// 有人@我const isMentionSelf = await message.mentionSelf()// 如果有人@我if (isMentionSelf) {console.log('this message were mentioned me! [You were mentioned] tip ([有人@我]的提示)')// 獲取消息內容,拿到整個消息文本,去掉 @名字const sendText = text.replace("@" + botPayload.name, "")if (sendText == '圖片') {// 通過不同的關鍵字進行業務處理邏輯 say({messageType: 6,sender: room,messageInfo: {fromUrl: 'https://wework.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDqfABIxIv4ic0FyQRxgQVpUIaqlePxrDW8L2qPB3WnHSZclgQ1D1QhDs/0' } })return }if (sendText == '分享') {// 通過不同的關鍵字進行業務處理邏輯 say({messageType: 14,sender: room,messageInfo: {urlLink: {description: 'WeChat Bot SDK for Individual Account, Powered by TypeScript, Docker, and Love',thumbnailUrl: 'https://avatars0.githubusercontent.com/u/25162437?s=200&v=4',title: 'Welcome to Wechaty',url: 'https://github.com/wechaty/wechaty', } } })return }if (sendText == '名片') { say({messageType: 3,sender: room,messageInfo: {contactCard: 'contactId' } })return }if (sendText == '小程序') { say({messageType: 9,sender: room,messageInfo: {miniProgram: {appid: 'xxxxx',title: '我正在使用Authing認證身份,你也來試試吧',pagePath: 'pages/home/home.html',description: '身份管家',thumbUrl: '30590201000452305002010002041092541302033d0af802040b30feb602045df0c2c5042b777875706c6f61645f31373533353339353230344063686174726f6f6d3131355f313537363035393538390204010400030201000400',thumbKey: '42f8609e62817ae45cf7d8fefb532e83', } } })return }// 群裡正常說話 } else {// 重構機器人功能測試群if (roomPayload.id !== 'R:10696051737544800') {console.log(`======================== 不是測試群消息,不處理群內業務邏輯 ========================\n\n`)return }if (/^[a-zA-Z0-9]{17}$/.test(text)) {// 群聊識別vin反饋 roomIdentifyVin(room, contact, message, text)return }// 群內消息以[弱]開頭的信息為反饋信息。反饋給後臺if (text.indexOf('[弱]') === 0) {// 群消息反饋 roomMessageFeedback(room, contact, text)return }// 如果是圖片,則圖片解析vinif (messagePayload.type === Message.Type.Image) {// 群聊圖片識別vin反饋 rooImageIdentifyVin(room, contact, message) } }// 私聊消息 } else {console.log(`======================== 私聊消息 ========================\n\n`)console.log(`消息時間:${dayjs(messagePayload.timestamp).format('YYYY-MM-DD HH:mm:ss')}\n\n微信名稱:${contactPayload.name}\n\n微信類型:${contactPayload.type}\n\n備註暱稱:${contactPayload.alias}\n\n消息內容:${text}\n\n消息類型:${messagePayload.type}\n\n`);// 存儲消息內容const storeMessage = {category: 'contact', // 消息類別,room為群聊消息, contact為個人消息。isSelf: isSelf, // 是否自己發送的消息messageId: messagePayload.id, // 消息idmessageToId: messagePayload.toId, // 消息接收者idmessageType: messagePayload.type, // 消息類型messageText: text, // 消息內容messageTimestamp: messagePayload.timestamp, // 消息時間戳messageTime: dayjs(messagePayload.timestamp).format('YYYY-MM-DD HH:mm:ss'), // 消息時間contactId: contactPayload.id, // 消息發送者idcontactName: contactPayload.name, // 消息發送者暱稱contactType: contactPayload.type, // 消息發送者類型contactAvatar: contactPayload.avatar, // 消息發送者頭像contactAlias: contactPayload.alias, // 消息發送者備註 }// redis中存儲私聊消息內容 storageContactMessage(contact, storeMessage)// 消息是機器人自己發的 或者 消息發送到wechaty接收間隔大於半個小時if (isSelf || message.age() > 1800) returnif (/^[a-zA-Z0-9]{17}$/.test(text)) {// 私聊識別vin反饋 contactIdentifyVin(contact, message, text)return }// 私聊消息以[弱]開頭的信息為反饋信息。反饋給後臺if (text.indexOf('[弱]') === 0) {// 私聊消息反饋 contactMessageFeedback(contact, text)return }// 如果是圖片,則圖片解析vinif (messagePayload.type === Message.Type.Image) {// 私聊圖片解析vin反饋 contactImageIdentifyVin(contact, message) } } } catch (error) {console.log(`onMessage:${error}`) }}module.exports = { onMessage }至於其他的一些生命周期以及鉤子函數。大家可以參考文檔做出屬於自己的應用機器人
封裝say方法
因為say()方法會在多處調用,並且要根據不同的消息類型發送的內容做出不同的數據處理。大家以後也會遇到,因此這裡將我封裝的一個say方法展示給大家用於參考
const { MiniProgram, UrlLink, FileBox } = require('wechaty')const dayjs = require('dayjs');const { DelayQueueExector } = require('rx-queue');const { redisHexists, redisHset, redisHget, redisSet, redisLpush } = require('../redis-service/index')const { globalData } = require('../../store/index')const delay = new DelayQueueExector(10000);/** * @method say 機器人發送消息 * @param {*} messageType 消息類型 7文本,1文件,6圖片,3個人名片,14卡片連結 9小程序 * @param {*} sender 來源 房間 || 個人 實例對象 * @param {*} messageInfo 內容 *//** * messageInfo 數據結構 * tetx: string 文本消息必傳 * fileUrl: string 文件消息必傳 * imageUr: string 圖片消息必傳 * cardId: string 個人名片消息必傳 * linkInfo: object 卡片消息必傳 * description: string 描述 * thumbnailUrl: string 縮略圖地址 * title: string 標題 * url: string 跳轉地址 */asyncfunctionsay({ messageType, sender, messageInfo }) {// console.log(messageType);// console.log(sender);// console.log(messageInfo);try {returnnewPromise(async (resolve, reject) => {// 機器人信息const { bot } = globalData// 枚舉消息類型const MessageType = {text: 7, // 文本fromFile: 1, // 文件fromUrl: 6, // 圖片contactCard: 3, // 個人名片urlLink: 14, // 卡片連結miniProgram: 9, // 小程序 }// 內容不存在if (!messageInfo) {return }// 要發送的消息內容let contentswitch (messageType) {// 文本 7case MessageType.text: content = messageInfo.textbreak;// 文件 1case MessageType.fromFile: content = FileBox.fromFile(messageInfo.fromFile)break;// 圖片 6case MessageType.fromUrl: content = FileBox.fromUrl(messageInfo.fromUrl)break;// 個人名片 3case MessageType.contactCard: content = await bot.Contact.load('1688853777824721')break;// 連結 14case MessageType.urlLink: content = new UrlLink({description: 'WeChat Bot SDK for Individual Account, Powered by TypeScript, Docker, and Love',thumbnailUrl: 'https://avatars0.githubusercontent.com/u/25162437?s=200&v=4',title: 'Welcome to Wechaty',url: 'https://github.com/wechaty/wechaty', })break;// 小程序 9case MessageType.miniProgram: content = new MiniProgram({appid: 'wx60090841b63b6250',title: '我正在使用Authing認證身份,你也來試試吧',pagePath: 'pages/home/home.html',description: '身份管家',thumbUrl: '30590201000452305002010002041092541302033d0af802040b30feb602045df0c2c5042b777875706c6f61645f31373533353339353230344063686174726f6f6d3131355f313537363035393538390204010400030201000400',thumbKey: '42f8609e62817ae45cf7d8fefb532e83', });break;default:break; } delay.execute(async () => { sender.say(content) .then(value => {console.log(`======================== 機器人回復 ========================\n\n`) resolve() }) .catch(reason => {console.log(`======================== 機器人發送消息失敗 ========================\n\n`, reason) }) }) }) } catch (error) {console.log('error in say', error); }}module.exports = { say}對了,對於onMessage事件中消息格式的判斷我也做了一層封裝,這裡給大家提供參考。
/** * @method messageProcessing 處理消息內容 * @param {*}message */asyncfunctionmessageProcessing(message) {try {returnnewPromise(async (resolve, reject) => {console.log(`======================== messageProcessing ========================\n\n`)// 消息詳情const messagePayload = message.payload// 獲取消息的文本內容。 let text = message.text()/** * Unknown: 0, Attachment: 1, Audio: 2, Contact: 3, ChatHistory: 4, Emoticon: 5, Image: 6, Text: 7, Location: 8, MiniProgram: 9, GroupNote: 10, Transfer: 11, RedEnvelope: 12, Recalled: 13, Url: 14, Video: 15 */// 消息類型switch (messagePayload.type) {// 附件 0case Message.Type.Unknown:console.log(`======================== 消息類型為未知消息:${messagePayload.type} ========================\n\n`) text = '[你收到一個未知消息,請在手機上查看]'break;// 附件 1case Message.Type.Attachment:console.log(`======================== 消息類型為附件:${messagePayload.type} ========================\n\n`)// 暫時不知道怎麼處理 text = '[你收到一個附件,請在手機上查看]'break;// 音頻 2case Message.Type.Audio:console.log(`======================== 消息類型為音頻:${messagePayload.type} ========================\n\n`) text = '[你收到一條語音消息,請在手機上查看]'break;// 個人名片 3case Message.Type.Contact:console.log(`======================== 消息類型為個人名片:${messagePayload.type} ========================\n\n`) text = '[你收到一張個人名片,請在手機上查看]'break;// 聊天記錄 4case Message.Type.ChatHistory:console.log(`======================== 消息類型為聊天記錄:${messagePayload.type} ========================\n\n`) text = '[你收到聊天記錄,請在手機上查看]'break;// 表情符號 5case Message.Type.Emoticon:console.log(`======================== 消息類型為表情符號:${messagePayload.type} ========================\n\n`) text = '[你收到表情符號,請在手機上查看]'// 暫時不知道怎麼處理break;// 圖片 6case Message.Type.Image:console.log(`======================== 消息類型為圖片:${messagePayload.type} ========================\n\n`)// 上傳圖片至阿里雲獲取圖片地址 text = await addImageOss(message)break;// 文本 7case Message.Type.Text:console.log(`======================== 消息類型為文本:${messagePayload.type} ========================\n\n`)// 去空格換行 text = text.replace(/\s+/g, '')break;// 位置 8case Message.Type.Location:console.log(`======================== 消息類型為位置:${messagePayload.type} ========================\n\n`) text = '[你收到一條圖片消息,請在手機上查看]'break;// 小程序 9case Message.Type.MiniProgram:console.log(`======================== 消息類型為小程序:${messagePayload.type} ========================\n\n`) text = '[你收到一個小程序消息,請在手機上查看]'break;// GroupNote 10case Message.Type.GroupNote:console.log(`======================== 消息類型為GroupNote:${messagePayload.type} ========================\n\n`) text = '[你收到一個GroupNote,請在手機上查看]'break;// Transfer 11case Message.Type.Transfer:console.log(`======================== 消息類型為Transfer:${messagePayload.type} ========================\n\n`) text = '[你收到一個Transfer,請在手機上查看]'break;// 紅包 12case Message.Type.RedEnvelope:console.log(`======================== 消息類型為紅包:${messagePayload.type} ========================\n\n`) text = '[你收到一個紅包,請在手機上查看]'break;// Recalled 13case Message.Type.Recalled:console.log(`======================== 消息類型為Recalled:${messagePayload.type} ========================\n\n`) text = '[你收到一個Recalled,請在手機上查看]'break;// 連結地址 14case Message.Type.Url:console.log(`======================== 消息類型為連結地址:${messagePayload.type} ========================\n\n`)// 暫時不知道怎麼處理 text = '[你收到一條連結消息,請在手機上查看]'break;// 視頻 15case Message.Type.Video:console.log(`======================== 消息類型為視頻:${messagePayload.type} ========================\n\n`) text = '[你收到一個視頻消息,請在手機上查看]'break;default: text = ''break; } resolve(text) }) } catch (error) {console.log('error in messageProcessing', error); }}為什麼這樣做一層封裝處理,是因為我們的業務需求要將聊天內容進行redis和mysql數據存儲。方便以後數據訂正和查詢使用。
實現的功能
基於wechaty我們實現的功能有那些呢?
— 根據關鍵詞,輸入車輛 VIN 對應反饋出車型配件信息,並且將公司所在群區域的店鋪配件庫存信息反饋出來
根據圖片識別車輛 VIN,然後識別 VIN 對應反饋出車型配件信息,並且將公司所在群區域的店鋪配件庫存信息反饋出來,圖片解釋接口採用的百度的接口關鍵詞指令綁定群信息。根據不同指令進行群配置。redis 存儲機器人信息。將群信息存儲並同步在 redis 和 mysql 中。後臺配置對應群是否開啟某些功能等等。每月月初定時發送每個群的採購信息。銷量信息等等。機器人登錄調用釘釘接口,在釘釘群內發布機器人登錄或者退出的提醒信息群邀請自動通過,入群以後做出相應數據存儲邏輯判斷功能設置等好友申請自動通過,關鍵字申請自動邀請入不同的群,功能覆蓋等等等等功能。以上功能支持還在不斷開發和摸索中。但已經滿足目前我們的業務需求。最後
你如果想用我這些東西,拉下代碼config.js裡換下token和一些配置信息就可以,當然我在不停更新,功能會越來越多,所以倉庫中代碼和文中會有些不一樣,使用時簡單看下代碼,都寫了詳細注釋,也很簡單,但是因為代碼中很多地方涉及到來企業敏感信息。我只好重新寫來一份最小可執行的demo,大家僅供參考。
看完幫個忙
如果你覺得這篇內容對你挺有啟發,我想邀請你幫我個小忙:
點讚,讓更多的人也能看到這篇內容(收藏不點讚,都是耍流氓 -_-)關注公眾號「番茄學前端」,我會定時更新和發布前端相關信息和項目案例經驗供你參考。加個好友, 雖然幫不上你大忙,但是一些業務問題大家可以探討交流。