UNPKG

recime-bot-runtime

Version:

This runtime is intended to run inside a micro-service container with platform specific integration and module interpreter.

254 lines (253 loc) 10.9 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var path = require("path"); var crypto = require("crypto"); var request = require("request"); var channel_1 = require("./channel"); var logger_1 = require("./logger"); var recime_keyvalue_store_1 = require("recime-keyvalue-store"); var MaxDuration = 15; var WeChat = /** @class */ (function (_super) { __extends(WeChat, _super); function WeChat(bot) { return _super.call(this, { bot: bot, log: new logger_1.WeChatLogger(bot) }) || this; } WeChat.prototype.execute = function (body, parameters, handler) { var _this = this; return new Promise(function (resolve) { _this.context.log.incoming(body); if (body.Event && (body.Event === 'unsubscribe' || body.Event.search(/LOCATION/ig) === 0)) return resolve(); if (body.Event && (body.Event === 'event' || body.Event.search(/VIEW/ig) === 0)) return resolve(); handler(_this.context.bot, body, 'wechat', function (messages) { var response = (messages || []).map(function (message) { return function () { return _this.sendMessage(body.FromUserName, message); }; }); return response .reduce(function (a, b) { return a.then(function (messages) { return b().then(function (message) { return; }); }); }, Promise.resolve()).then(function () { resolve(); }); }, function (err) { resolve(err.message); }); }); }; WeChat.prototype.sendMessage = function (toUser, message) { var _this = this; return new Promise(function (resolve, reject) { var reqData = { touser: toUser, msgtype: message.type, }; switch (message.type) { case "text": { reqData.text = { content: message.content }; break; } case "audio": case "image": case "video": { message.type = message.type === "audio" ? "voice" : message.type; var media = function () { if (message.media_id) { return Promise.resolve({ media_id: message.media_id }); } return _this.uploadMedia(message.url, message.type).then(function (data) { reqData.msgtype = data.type; if (data.media_id) { return { media_id: data.media_id }; } }); }; return media().then(function (file) { reqData[message.type] = file; return _this.postMessage(reqData).then(function () { return resolve(); }); }); } case "news": { reqData.news = { "articles": ((message.news || []).articles || []).map(function (article) { return { title: article.title, picurl: article.picurl, url: article.url, description: article.digest // content : article.content }; }) }; break; } case "typing": { return _this.sendTypingMessage(toUser).then(function () { var duration = parseInt(message.duration); setTimeout(function () { return resolve(); }, (duration === MaxDuration ? duration - 1 : duration) * 1000); }); } default: { reqData.msgtype = "text"; reqData.text = { content: message.text || "Message type not supported." }; } } ; return _this.postMessage(reqData).then(function () { return resolve(); }); }); }; WeChat.prototype.postMessage = function (data) { var _this = this; return new Promise(function (resolve, reject) { _this.accessToken().then(function (accessToken) { var reqData = { url: "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken, json: true, method: "POST", body: data }; request(reqData, function (err, response, body) { if (err) { console.error(err); return resolve(); } if (response.statusCode < 200 && response.statusCode > 299) { console.error(body); return resolve(); } if (body.errcode) { console.error(body); return resolve(); } _this.context.log.outgoing(reqData, body); resolve(); }); }) .catch(function (err) { console.error(err); resolve(); }); }); }; WeChat.prototype.sendTypingMessage = function (toUser) { var _this = this; return new Promise(function (resolve) { _this.accessToken().then(function (accessToken) { var options = { uri: "https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=" + accessToken, method: 'POST', json: { command: 'Typing', touser: toUser } }; request(options, function (err, response, body) { resolve(); }); }).catch(function (err) { console.error(err); resolve(); }); }); }; WeChat.prototype.accessToken = function () { var _this = this; var db = recime_keyvalue_store_1.default.init(this.context.bot.id); return new Promise(function (resolve, reject) { db.get(_this.context.bot.config.RECIME_WECHAT_APP_ID).then(function (value) { if (value && value.expires > new Date().getTime()) resolve(value.token); else { request.get("https://proxy.recime.io/wechat/token?grant_type=client_credential&appid=" + (process.env.RECIME_WECHAT_APP_ID || _this.context.bot.config.RECIME_WECHAT_APP_ID) + "&secret=" + (process.env.RECIME_WECHAT_APP_SECRET || _this.context.bot.config.RECIME_WECHAT_APP_SECRET), { "Accept": "application/json" }, function (err, response, body) { var result = JSON.parse(body); if (response.statusCode < 200 && response.statusCode > 299) return reject(new Error("[Error] Invalid access token")); if (result.errcode) return reject(new Error(result.errmsg)); var accessToken = JSON.parse(response.body).access_token; db.set(_this.context.bot.config.RECIME_WECHAT_APP_ID, { expires: Date.now() + 7200, token: accessToken }).then(function () { return resolve(accessToken); }); resolve(accessToken); }); } }); }); }; WeChat.prototype.uploadMedia = function (mediaUrl, type) { var _this = this; var parsed = require("url").parse(mediaUrl).path; return new Promise(function (resolve) { _this.accessToken().then(function (accessToken) { var readStream = request(mediaUrl); request({ url: "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + accessToken + "&type=" + type, json: true, method: "POST", formData: { media: readStream, filename: path.basename(parsed) } }, function (err, response, body) { if (response.statusCode < 200 && response.statusCode > 299) { return resolve({ msgtype: "text", content: "[Error] Invalid media url." }); } if (body.errcode) { return resolve({ msgtype: "text", content: body.errmsg }); } return resolve(body); }); }, function (err) { return resolve({ msgtype: "text", content: err.message }); }); }); }; WeChat.prototype.verify = function (query) { var accessToken = process.env.RECIME_WECHAT_ACCESS_TOKEN || this.context.bot.config.RECIME_WECHAT_ACCESS_TOKEN; var token = [query['timestamp'], query['nonce'], accessToken].sort().join(""); var hash = crypto.createHash('sha1').update(token).digest('hex'); return hash === query['signature']; }; return WeChat; }(channel_1.Channel)); exports.WeChat = WeChat;