Nodejs微信与Bot framework通过Direct Line连接
背景
最近开发了一个Bot Framework的小工具,能够通过Luis分析出用户输入的文本,对文本中的StyleNo/FabricNo/TrimNo提取出来,并传入另一个小系统进行查询出结果,包括文本与图片,用户可以通过skype/teams/wechat……gi还有微信,可以与Bot进行交互(现时只是查询)
关于Bot Framework的开发,开始的时候已经开发了一个C#版本,后来因项目都需要改成Nodejs,我就借这个小项目来熟悉一下Nodejs的开发
关于微信Nodejs开发,前人还是提代了很丰富的NPM库的,推荐两个库wechat(https://www.npmjs.com/package/wechat)和wechat-api(https://www.npmjs.com/package/wechat-api),这两个库的配合,能够帮助我们完成绝大部分的开发要求,
架构
开发
在完成了Bot Framework的开发后,现时的功能能够使用skype/teams/邮件进行交互,因为现时公司就是使用Office365来办公的,那么使用skype也是相当方便,这里提一点,skype business这个版本暂时还不支持加入Bot的功能,还需要等待一阵才有可能使用到Bot功能。
因为微信的普及,我们也希望加入微信来对功能进行拓展,所以才有了现在这个微信的开发,现时只是对Bot的功能进行延展,只要求微信能够使用到这个功能就可以了
微信
var wechat = require('wechat'); var wechatAPI = require('wechat-api'); //wechat config var config = { token: 'weixin', appid: 'wx1434eed5268660c4', encodingAESKey: 'ZEtViedarf49EUOCDeu45pqhkZhKPFBjSHI2DynP4vq', checkSignature: true // 可选,默认为true。由于微信公众平台接口调试工具在明文模式下不发送签名,所以如要使用该测试工具,请将其设置为false }; var api = new wechatAPI(config.appid, '30a5f51682755652e6e02879757a0fb1'); app.use('/wechat', wechat(config, wechat.text(function (message, req, res, next) { //------------------------------------------------------------------------ //get message from wechat client var message = req.weixin; logger.log("2.1:get message from wechat client", message); //========================================================================================================= var touserid = message.FromUserName; //send message entity var messageBody = { "type": "message", "from": { "id": message.FromUserName, "FromUserName": 'WeChatUser' }, "text": message.Content }; //send message to botframework sendMessageToBotframework(_tokenObject, messageBody, touserid); //response for wechat client res.reply('message send successfully, waiting for response'); //========================================================================================================= }).image(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).voice(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).video(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).location(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).link(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).event(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('感谢你的关注,你也可以在github中查看,https://github.com/ChenWes/esquel-LPD-Bot-Node-WeChat'); }).device_text(function (message, req, res, next) { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); }).device_event(function (message, req, res, next) { if (message.Event === 'subscribe' || message.Event === 'unsubscribe') { var message = req.weixin; logger.log("info", message); res.reply("功能开发中"); } else { var message = req.weixin; logger.log("info", message); res.reply('功能开发中'); } })));
Bot framework Direct line
var client = require('./directline-api-v3'); var secret = 'JmQLHOoxqeg.cwA.UqE.ZeXqmfJ5ncjzD9ZcoOe4tvOW7VDhVHZCMjfEEyZsNDo'; var _tokenObject; var _conversationWss; var _watermark = 0; client.getTokenObject(secret).subscribe( (tokenObject) => { _tokenObject = tokenObject; logger.log('1.1:get token', _tokenObject); client.initConversationStream(_tokenObject).subscribe( (message) => { _conversationWss = message; logger.log('1.2:info', _conversationWss); }, (err) => console.log(err), () => console.log("1.2:get conversation successfully") ) //maybe need refresh token here setTimeout(function () { refreshToken() }, (_tokenObject.expires_in - 30) * 1000); }, (err) => console.log(err), () => console.log('1.1:get token successfully') ) //========================================================================================================= function refreshToken() { console.log('------------------------refreshToken-----------------------------') client.refTokenObject(secret).subscribe( (tokenObject) => { _tokenObject = tokenObject; logger.log('1.3:refresh token', _tokenObject); }, (err) => console.log(err), () => console.log('1.3:refresh token successfully') ) } //send message to bot framework function sendMessageToBotframework(_tokenObject, messageBody, touserid) { client.sendMessage(_tokenObject, messageBody).subscribe( (data) => { var sendMessageid = data.id; //time out function get message from botframework setTimeout(function () { getmessagefrombotframework(touserid, _tokenObject, sendMessageid, _watermark) }, 10000); }, (err) => { logger.log('2.2:send message to BotFramework error', err); }, () => { console.log("2.2:send message to bot botframework successfully"); } ); } //get message from bot framework function function getmessagefrombotframework(senduserid, tokenobject, sendmsgid, sendwatermark) { client.getMessage(tokenobject, sendwatermark).subscribe( (result) => { _watermark = result.watermark; //filter activities var getResponseMessages = _.where(result.activities, { replyToId: sendmsgid }); //send message to wechat client sendMessageToClient(senduserid, getResponseMessages); }, (err) => { logger.log('3.1:get message from botframework error', err); }, () => console.log("3.1:get message from botframework successfully") ) } //send to message to wechat client function sendMessageToClient(senduserid, getResponseMessages) { if (getResponseMessages) { //forEach message getResponseMessages.forEach(function (getResponseMessageItem) { //process message from botframework api.sendText(senduserid, getResponseMessageItem.text, function (err, result) { if (err) { logger.log('3.2:reply wechat client (' + senduserid + ') message error', err); } }); //process attachment if (getResponseMessageItem.attachments) { getResponseMessageItem.attachments.forEach(function (getResponseMessageAttachmentItem) { if (getResponseMessageAttachmentItem.contentType == 'application/vnd.microsoft.card.thumbnail' || getResponseMessageAttachmentItem.contentType == 'application/vnd.microsoft.card.hero') //-------------upload media api.uploadMedia(getResponseMessageAttachmentItem.content.images[0].url, 'image', function (err, result) { // console.log('start upload image' + result); if (err) { logger.log('3.4:upload image error', err); } else { //-------------send image api.sendImage(senduserid, result.media_id, function (err, result) { if (err) { logger.log('3.5:send image wechat client (' + senduserid + ') attachment error', err); } }); //------------- } }); //------------- api.sendText(senduserid, getResponseMessageAttachmentItem.content.title + '\r' + getResponseMessageAttachmentItem.content.subtitle + '\r' + getResponseMessageAttachmentItem.content.text, function (err, result) { if (err) { logger.log('3.3:reply wechat client (' + senduserid + ') attachment error', err); } }); }); } }); } }
最后公开一下github代码:https://github.com/ChenWes/esquel-LPD-Bot-Node-WeChat/tree/dev
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架