背景
最近开发了一个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 + ' ' + getResponseMessageAttachmentItem.content.subtitle + ' ' + 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