Botkit is designed to ease the process of designing and running useful, creative bots that live inside Cisco Jabber. Botkit features a comprehensive set of tools to deal with Cisco Jabber, and allows developers to build interactive bots and applications that send and receive messages just like real humans. This document covers the Cisco Jabber-specific implementation details only.

Cisco Jabber bot uses node-xmpp to connect to Cisco Unified IM & Presence server or Cisco WebEx Messenger and can only use the password authentication methods. The bot is relying on starndard XMPP protocol to send/receive messages. You can refer to RFC6120 and RFC6121 to learn more about how to connect to XMPP server and how to create the XMPP message stanza.

Cisco Jabber bot can take part in 1-1 chat or group chat conversations and can provide information or other services for the conversations. It's better to use persist store for the Botkit controller, otherwise when restart the bot, it will lose the group information and cannot received the message from a group chat.

The full code for a simple Cisco Jabber bot is as below and you can find it in ../examples/jabber_bot.js:

const Botkit = require('./lib/JabberBot.js');
var controller = Botkit({
    json_file_store: './bot_store/'
});
var bot = controller.spawn({
client: {
    jid: 'xx@domain.com',
    password: *,
    host: "hostname.domain.com",
    port: 5222
}
});
controller.hears(['hello'], ['direct_mention', 'direct_message'], function (bot, message) {
    bot.reply(message, 'Hi');
});
controller.on('direct_mention', function (bot, message) {
    bot.reply(message, 'You mentioned me in a group and said, "' + message.text + '"');
});
controller.on('direct_message', function (bot, message) {
    bot.reply(message, 'I got your direct message. You said, "' + message.text + '"');
});

When spawn bot from the Botkit controller, there are several options available.

Argument Description
jid Jid of the jabber bot
password Password of the jabber bot
host Host of the Cisco Unified IM & Presence server, not neccessary for bot of Cisco WebEx Messenger
port Port of the Cisco Unified IM & Presence server, not neccessary for bot of Cisco WebEx Messenger

Jabber support the following events

Event Description
direct_message Bot has received a direct message from a 1-1 chat
direct_mention Bot has received a message from a group chat and is mentioned by the message sender
self_message Bot has received a message it sent

Cisco Jabber bot supports both plain text message and rich text message. Below is an example for plain text message.

bot.reply(message, 'Hello');

Below is an example for rich text message. Jabber Bots Developer needs to compose the whole stanza for the message. He can create his own UI element to replace the UI part inside the body element in this example. Notes: Below example just for show element clearly. It's better to remove all empty space in the stanza.

let reply_message = {};
let to = message.user;
let type = message.group ? 'groupchat' : 'chat';
let body = 'html demo(only for Jabber Windows now)';
reply_message.text = body;
reply_message.stanza = xml`<message to="${to}" type="${type}"><body>${body}</body>
<html xmlns="http://jabber.org/protocol/xhtml-im">
<body xmlns="http://www.w3.org/1999/xhtml">
<span style="font-family:Segoe UI;color:#1a1a1a;font-size:10pt;font-weight:normal;font-style:normal;text-decoration:none;">
<div>
<span style="font-family:Comic Sans MS;color:#a61770;font-weight:normal;font-style:normal;text-decoration:none;">${body}
<form onsubmit="return false;">
<input type="text" name="mailer"></input>
<button robot-type="robot-submit" type="button" value="Submit">Submit</button>
</form>
</span>
</div>
</span>
</body>
</html></message>`;
bot.reply(message, reply_message);

Cisco Jabber can support all HTML5 elements and bootstrap 3.2 CSS style. However, Bot developer cannot inject any java-script code into the rich text message because of the security reason. In addition, Cisco Jabber introduces a new attribute robot-type for the button element to enhance the interaction between Jabber and the bot. Below is a short summary of the allow value and description. More detail and example usage can be found in later section.

Value Description
robot-button Send back a message
robot-openlink Open URL
robot-executecommand Execute predefined command in Jabber, like start group chat, start conf call and start instant meeting
robot-submit Send back a json message with all input name and value in a HTML form.
let reply_message = {};
let to = message.user;
let type = message.group ? 'groupchat' : 'chat';
let body = 'robot-button demo(only for Jabber Windows)';
reply_message.text = body;
reply_message.stanza = xml`<message to="${to}" type="${type}"><body>${body}</body><html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml">
<div class="container"><h6>${body}</h6><button class="btn btn-primary btn-sm center-block" style="margin-top:8px;" robot-type="robot-button" type="button" robot-message="help">Send back help message</button></div></body></html></message>`;
bot.reply(message, reply_message);

All the below buttons needs to be putted in a form.

let reply_message = {};
let to = message.user;
let type = message.group ? 'groupchat' : 'chat';
let body = 'robot-openlink demo(only for Jabber Windows)';
reply_message.text = body;
reply_message.stanza = xml`<message to="${to}" type="${type}"><body>${body}</body><html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml">
<div class="container">
<h6>${body}</h6>
<form class="form-horizontal">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" class="form-control" name="openlink" value="https://help.webex.com/community/jabber"/>
<button class="btn btn-primary btn-sm center-block" style="margin-top:8px" robot-type="robot-openlink" type="button">Open Jabber help page</button>
</div>
</form>
</div>
</body></html></message>`;
bot.reply(message, reply_message);
function extractMentionJids(message) {
let direct_mention_reg = /href="xmpp:\s?(\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+)\s?"/ig;
let email_reg = /\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+/i;
let match = message.stanza.toString().match(direct_mention_reg);
let mention_jids = [];
if (match) {
for (let i = 0; i < match.length; i++) {
let jid_match = match[i].match(email_reg);
if (jid_match) {
let jid = jid_match[0];
if (jid != bot.client_jid) {
mention_jids.push(jid);
}
}
}
}
return mention_jids;
}

let reply_message = {};
let to = message.user;
let type = message.group ? 'groupchat' : 'chat';
let mention_jids = extractMentionJids(message);
let mentionJids = "";
for (let i = 0; i < mention_jids.length; i++) {
mentionJids += mention_jids[i];
mentionJids += ";";
}

let body = 'robot-executecommand demo(only for Jabber Windows)';
reply_message.text = body;
reply_message.stanza = xml`<message to="${to}" type="${type}"><body>${body}</body><html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml">
<div class="container">
<h6>${body}</h6>
<form class="form-horizontal">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" class="form-control" name="command" value="startgroupchat:${mentionJids}"/>
<button class="btn btn-primary btn-sm center-block" style="margin-top:8px" robot-type="robot-executecommand" type="button">Start Group Chat</button>
</div>
</form>
</div>
<div class="container">
<form class="form-horizontal">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" class="form-control" name="command" value="startconference:${mentionJids}"/>
<button class="btn btn-primary btn-sm center-block" style="margin-top:8px" robot-type="robot-executecommand" type="button">Start Conference</button>
</div>
</form>
</div>
<div class="container">
<form class="form-horizontal">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" class="form-control" name="command" value="startmeeting:${mentionJids}"/>
<button class="btn btn-primary btn-sm center-block" style="margin-top:8px" robot-type="robot-executecommand" type="button">Start Meeting</button>
</div>
</form>
</div>
</body></html></message>`;
bot.reply(message, reply_message);
let reply_message = {};
let to = message.user;
let type = message.group ? 'groupchat' : 'chat';

let body = 'robot-submit demo(only for Jabber Windows)';
reply_message.text = body;
reply_message.stanza = xml`<message to="${to}" type="${type}"><body>${body}</body><html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml">
<div class="container">
<h5> Please enter the meeting information:</h5>
<form class="form-horizontal" onsubmit="return false;">
<div class="form-group-sm">
<label class="control-label col-sm-2" for="required_attendees">Required Attendees</label>
<div class="col-sm-10">
    <input type="text" class="form-control" id="required_attendees" placeholder="Enter jid of required attendees, like john@cisco.com;mick@cisco.com" name="required_attendees"/>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="subject">Subject:</label>
<div class="col-sm-10">
    <select class="form-control" id="subject" name="subject">
        <option>Botkit</option>
        <option>JabberBot SDK</option>
        <option>Mindmeld</option>
    </select>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="topics">Topics:</label>
<div class="col-sm-10">
    <label class="checkbox-inline">
        <input type="checkbox" value="Deep Learning" name='topics'/>Deep Learning</label>
    <label class="checkbox-inline">
        <input type="checkbox" value="Neural Networks"  name='topics'/>Neural Networks</label>
    <label class="checkbox-inline">
        <input type="checkbox" value="Machine Learning" name='topics'/>Machine Learning</label>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="body">Body:</label>
<div class="col-sm-10">
    <textarea class="form-control" rows="5" placeholder="Enter invitation of this meeting"  id="body" name="body"/>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="location">Location:</label>
<div  class="col-sm-10">
    <label class="radio-inline">
        <input type="radio" name="location" value="Great Wall"/>Great Wall</label>
    <label class="radio-inline">
        <input type="radio" name="location" value="Big Ben"/>Big Ben</label>
    <label class="radio-inline">
        <input type="radio" name="location" value="Grand Canyon"/>Grand Canyon</label>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="start">Start:</label>
<div class="col-sm-10">
    <input name="start" type="datetime-local" value="2018-01-01T14:00:00"/>
</div>
</div>
<div class="form-group-sm">
<label class="control-label col-sm-2" for="end">End:</label>
<div class="col-sm-10">
    <input name="end" type="datetime-local"  value="2018-01-01T13:00:00"/>
</div>
</div>
<div class="form-group-sm">
<div class="col-sm-offset-2 col-sm-10">
    <button class="btn btn-primary btn-sm" style="margin-top:8px"  robot-type="robot-submit" type="button" value="Submit">Submit</button>
</div>
</div>
</form>
</div>
</body></html></message>`;

bot.startConversation(message, function (err, convo) {
if (!err) {
convo.ask(reply_message, function (response, convo) {
try {
if (response.from_jid == bot.client_jid) {
return;
}
let query = JSON.parse(response.text);

let replay_meeting_info = "You submit the following information:";
replay_meeting_info += "Required Attendees:" + query.required_attendees + ";";
replay_meeting_info += "Subject:" + query.subject + ";";
replay_meeting_info += "Body:" + query.body + ";";
replay_meeting_info += "Topics:" + query.topics + ";";
replay_meeting_info += "Location:" + query.location + ";";
replay_meeting_info += "Start:" + query.start + ";";
replay_meeting_info += "End:" + query.end + "";
bot.reply(message, replay_meeting_info);
convo.stop();
}
catch (err) {
console.log(err.message);
convo.stop();
}
});
}
});

Jabber bot uses node-xmpp to connect to Cisco Unified IM & Presence server or Cisco WebEx Messenger and can only use the password authentication methods. The bot is relying on starndard XMPP protocol to send/receive messages. You can refer to RFC6120 and RFC6121 to learn more about how to connect to XMPP server and how to create the XMPP message stanza. Below is an example for an xmpp message stanza with HTML payload. The bot developer can use this kind of message stanza to implement the functions.

<message
       from='juliet@example.com/balcony'
       id='ktx72v49'
       to='romeo@example.net'
       type='chat'
       xml:lang='en'>
     <body>Art thou not Romeo, and a Montague?</body>
<html xmlns="http://jabber.org/protocol/xhtml-im"> <body xmlns="http://www.w3.org/1999/xhtml">
<div class="container">
<h6>
Art thou not Romeo, and a Montague?
</h6>
</div>
</html> </message>

JabberBot uses node-simple-xmpp to build connection and exchange message with Cisco Unified IM & Presence server or Cisco WebEx Messenger. If you would like to have more functions from XMPP, you can integrate more function into jabber_bot.js with the help of node-simple-xmpp and the underlying node-xmpp like what we have done in the JabberGroupManager.js. Just handle stanza and underlying events, the bot can have all the functions that a xmpp client can do.

Is something missing or out of date?

This file is managed on Github. click here to view the source, and send us a pull request with your improvements!