此機器人可以登入 xmpp,包含聊天室。然後把
- 接收訊息
- 聊天室成員變動
資訊轉發給外部 API
首先要透過 npm 安裝相關的套件 (package.json)
參考範例程式如下: (原始程式下載: uim.js)
'use strict'; //////////////////////////////////////////////////////////////////////// // [外部] // 接收訊息 API: // https://example.com/api/receive // 人員異動 API: // https://example.com/api/user var CONFIG_EXT_API = { message: 'https://example.com/api/receive', members: 'https://example.com/api/user' } //////////////////////////////////////////////////////////////////////// // 聊天信息組態 var CONFIG_CHAT = { appID: '12345', apiKey: '1234567890abcdefg', getListApi: 'https://uim.example.com/chatbot/getList', key: 'xxxxxxxxxxxxxxxx', secret: 'yyyyyyyyyyyyyyyyyyyyyy', userID: '12345678', userPW: 'password', dialogID: '0987654321', } ////////////////////////////////////////////////////////////////////////// // 系統組態 var CONFIG = { endpoints: { api: "api.uim", // set custom API endpoint chat: "chat.uim" // set custom Chat endpoint }, chatProtocol: { active: 1 // set 1 to use BOSH, set 2 to use WebSockets (default) }, debug: {mode: 0} // set DEBUG mode }; // required libraries const QB = require('quickblox'); const request = require('request'); var sleep = require('system-sleep'); QB.init(CONFIG_CHAT.appID, CONFIG_CHAT.key, CONFIG_CHAT.secret, CONFIG); // ################################################################################# // Connect to Real-Time Chat QB.chat.connect({ userId: CONFIG_CHAT.userID, password: CONFIG_CHAT.userPW, }, (chatConnectError) => { if (chatConnectError) { console.log('[SYS] chat.connect is failed', JSON.stringify(chatConnectError)); process.exit(1); } console.log('[SYS] Bot is up and running'); // ################################################################################# // join to a group var dialogJid = QB.chat.helpers.getRoomJidFromDialogId(CONFIG_CHAT.dialogID); QB.chat.muc.join(dialogJid, function(resultStanza) { // // var joined = true; // console.log(resultStanza); // for (var i = 0; i < resultStanza.children.length; i++) { // // var elItem = resultStanza.children.item(i); // // if (elItem.tagName === 'error'){ // // joined = false; // // } // } }); // ################################################################################# // Add chat messages listener // onMessageListener QB.chat.onMessageListener = onMessageListener; QB.chat.onSubscribeListener = onSubscribeListener; QB.chat.onSystemMessageListener = onSystemMessageListener; // QB.chat.onMessageTypingListener = onMessageTypingListener; // QB.chat.onReconnectFailedListener = onReconnectFailedListener; // messaage status listeners // QB.chat.onSentMessageCallback = onSentMessageCallback.bind(this); // QB.chat.onDeliveredStatusListener = onDeliveredStatusListener.bind(this); // QB.chat.onReadStatusListener = onReadStatusListener.bind(this); }); // ################################################################################# function sendMsgOpponentId(opponentId, body) { console.log('[SYS] sendMsgOpponentId'); var msg = { type: 'chat', body: body, extension: { save_to_history: 1, uuid: uuid(), type: 'text', date_sent_client: Date.now() + 1000, }, }; QB.chat.send(opponentId, msg); console.log('[SYS] send msg to ' + opponentId); } function sendFile(opponentId, file) { console.log('[SYS] sendFile'); const QB = require('quickblox'); var fs = require('fs'); var UPLOAD_TIMEOUT = 6000; var imgName = "logo.jpg"; var srcIMG = 'spec/' + imgName; fs.stat(srcIMG, function (err, stats) { fs.readFile(srcIMG, function (err, data) { if (err) throw err; var data = {name: imgName, file: data, type: "image/jpg", size: data.length, public: false}; upload(data); }); }); } function queryChatroom( _callback ) { console.log('[SYS] queryChatroom'); var url = CONFIG_CHAT.getListApi, querystring = require('querystring'), form = { "api_key": CONFIG_CHAT.apiKey}, formData = querystring.stringify(form), contentLength = formData.length, ret = {}; request.post({ headers: { 'Content-Length': contentLength, 'Content-Type': 'application/x-www-form-urlencoded' }, url: url, body: formData, method: 'POST', json: true, }, function (error, response, body) { if (error) { console.log('[ERR]'); console.log(error); return; } if (typeof body.data.users === 'undefined') return false; _callback(body.data.users); // console.log(body); }); } function sendExtAPI(userId, msg) { console.log('[SYS] sendExtAPI'); if (userId == CONFIG_CHAT.userID) return; var dialogId = CONFIG_CHAT.dialogID; var encodeMsg = Buffer.from(msg).toString('base64'); // header: var url = CONFIG_EXT_API.message, req = { "GROUP_ID": dialogId, "PLAYER_ID": userId, "MESSAGE_TEXT": encodeMsg}; request.post({ headers: { 'X-UIM-APIKEY': CONFIG_CHAT.apiKey, }, url: url, body: req, json: true }, function (error, response, body) { // console.log('3Party Begin ============================= '); if (error) { console.log('[ERR]'); console.log(error); return; } // console.log(error); console.log('[Forward]: from ' + userId + ' [Msg] ' + msg + ' / ' + encodeMsg + ' > response: ' + response.body); console.log(response.body); // console.log('3Party End ============================= '); }); } function sendChatroomUpdate(dialogId) { console.log('[SYS] sendChatroomUpdate'); console.log('sendChatroomUpdate'); if (dialogId !== CONFIG_CHAT.dialogID) return; queryChatroom( function (users) { var dialogId = CONFIG_CHAT.dialogID; var playerList = []; // console.log(users); Object.keys(users).forEach(function(key) { var val = users[key]; playerList.push({PLAYER_ID: key, NICK_NAME: Buffer.from(val.full_name).toString('base64')}); }); var req = { GROUP_ID: dialogId, playerList: playerList }; // header: var url = CONFIG_EXT_API.members; request.post({ headers: { 'X-UIM-APIKEY': CONFIG_CHAT.apiKey, }, url: url, body: req, json: true }, function (error, response, body) { console.log('sendChatroomUpdate Begin ============================= '); if (error) { console.log('[ERR]'); console.log(error); return; } // console.log(error); console.log(body); console.log('sendChatroomUpdate End ============================= '); }); }); } function onMessageListener(userId, msg) { console.log('[SYS] onMessageListener'); console.log(userId); if (typeof msg == 'undefined') return; if (typeof msg.body == 'undefined') return; if (msg.body == null) return; if (userId == CONFIG_CHAT.userID) { console.log('Robot itself'); return; } console.log('[SYS] from ' + userId + ' onMessage: ' + msg.body); // send read status var params = { messageId: msg.id, userId: userId, dialogId: msg.dialog_id }; QB.chat.sendReadStatus(params); // console.log(params); // 3rd party if (msg.type == 'groupchat') { sendExtAPI(userId, msg.body); return; } // process 1-1 messages if (msg.type == 'chat') { if(msg.body){ if ( parseInt(msg.body) == 'NaN') return; if (parseInt(msg.body) != 0 && parseInt(msg.body) <= 1000) { for (var i=1 ; i <= parseInt(msg.body) ; i++ ){ let answerMessage = { type: 'chat', body: '[' + i + ']' + ' re: ' + msg.body, // echo back original message extension: { save_to_history: 1, uuid: uuid(), type: 'text', date_sent_client: Date.now() + 1000, }, }; QB.chat.send(userId, answerMessage); sleep(3); } return; } let answerMessage = { type: 'chat', body: 're: ' + msg.body, // echo back original message extension: { save_to_history: 1, uuid: uuid(), type: 'text', date_sent_client: Date.now() + 1000, }, }; QB.chat.send(userId, answerMessage); sleep(1); } } } function onSubscribeListener(userId) { console.log('[SYS] onSubscribeListener'); console.log(`[SYS] onSubscribeListener. Subscribe from ${userId}`); QB.chat.roster.confirm(userId, function() { console.log(`[SYS] Confirm subscription from user ${userId}`); }); } function onSystemMessageListener(message) { console.log('[SYS] onSystemMessageListener'); if (!message.delay) { switch (message.extension.notification_type) { case "1": // This is a notification about dialog creation getAndShowNewDialog(message.extension.dialog_id); break; case "2": // This is a notification about dialog update getAndUpdateDialog(message.extension.dialog_id); break; default: break; } } } function onSystemMessageListener(msg) { console.log('[SYS] onSystemMessageListener'); console.log(`[SYS] onSystemMessageListener. Message: `); console.log(msg); if (msg.delay) return; if (msg.extension.dialog_id != CONFIG_CHAT.dialogID) return; switch (msg.extension.notification_type) { case "1": // This is a notification about dialog creation getAndShowNewDialog(msg.extension.dialog_id); break; case "2": // This is a notification about dialog update getAndUpdateDialog(msg.extension.dialog_id); break; default: break; } sendChatroomUpdate(msg.extension.dialog_id); } function uuid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } // ################################################## process.on('exit', function () { console.log('Kill bot'); QB.chat.disconnect(); });