Chat Robot

此機器人可以登入 xmpp,包含聊天室。然後把

  1. 接收訊息
  2. 聊天室成員變動

資訊轉發給外部 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();
});

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。