此機器人可以登入 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();
});