2.5.1 • Published 3 months ago

webex-node-bot-framework v2.5.1

Weekly downloads
108
License
MIT
Repository
github
Last release
3 months ago

webex-node-bot-framework

Node JS Bot Framework for Cisco Webex

This project is inspired by, and provides an alternate implementation of, the awesome node-flint framework by Nick Marus. The framework makes it easy to quickly develop a Webex messaging bot, abstracting away some of the complexity of Webex For Developers interfaces, such as registering for events and calling REST APIs. A bot developer can use the framework to focus primarily on how the bot will interact with users in Webex, by writing "handlers" for various message or membership events in spaces where the bot has been added.

The primary change in this implementation is that it is based on the webex-jssdk which continues to be supported as new features and functionality are added to Webex.

For developers who are familiar with flint, or who wish to port existing bots built on node-flint to the webex-node-bot-framework, this implementation is NOT backwards compatible. Please see Migrating from the original flint framework

Feel free to join the "Webex Node Bot Framework" space on Webex to ask questions and share tips on how to leverage this framework. This project is community supported so contributions are welcome. If you are interested in making the framework better please see the Contribution Guidelines.

News

  • May, 2023 - Version 2.5.0 introduces two new elments of the Trigger object
    • trigger.command will now contain the component of the user message that matched the framework.hears phrase.
    • trigger.prompt will contain all of the user message that was NOT part of the command or the bot mention.

This should simplify logic that uses part of the user message, for example:

// echo user input
framework.hears('echo', (bot, trigger) => {
  bot.say('markdown', `You said: ${trigger.prompt}`);
}, '**echo** - I\'ll echo back the rest of your message');

This release also includes updated Contribution Guidelines including details on running the tests

  • May, 2020 - Version 2 introduces a some new configuration options designed to help developers restrict access to their bot. This can be helpful during the development phase (guideEmails parameter) or for production bots that should be restricted for use to users that have certain email domains (restrictedToEmailDomains parameter). See Membership-Rules README

  • October 31, 2020 - Earlier this year, a series of blog posts were published to help developers get started building bots with the framework:

    For first timers, I strongly recommend following these, running the sample app, stepping through it in the debugger, and getting a sense of how the framework works. Once you have done the detailed documentation here will make a lot more sense!

Full Version History

Contents

Installation

Via Git

mkdir myproj
cd myproj
git clone https://github.com/WebexCommunity/webex-node-bot-framework
npm install ./webex-node-bot-framework

Via NPM

mkdir myproj
cd myproj
npm install webex-node-bot-framework

Example Template Using Express

var Framework = require('webex-node-bot-framework'); 
var webhook = require('webex-node-bot-framework/webhook');

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());

// framework options
var config = {
  webhookUrl: 'http://myserver.com/framework',
  token: 'Tm90aGluZyB0byBzZWUgaGVyZS4uLiBNb3ZlIGFsb25nLi4u',
  port: 80
};

// init framework
var framework = new Framework(config);
framework.start();

// An initialized event means your webhooks are all registered and the 
// framework has created a bot object for all the spaces your bot is in
framework.on("initialized", () => {
  framework.debug("Framework initialized successfully! [Press CTRL-C to quit]");
});

// A spawn event is generated when the framework finds a space with your bot in it
// You can use the bot object to send messages to that space
// The id field is the id of the framework
// If addedBy is set, it means that a user has added your bot to a new space
// Otherwise, this bot was in the space before this server instance started
framework.on('spawn', (bot, id, addedBy) => {
  if (!addedBy) {
    // don't say anything here or your bot's spaces will get 
    // spammed every time your server is restarted
    framework.debug(`Framework created an object for an existing bot in a space called: ${bot.room.title}`);
  } else {
    // addedBy is the ID of the user who just added our bot to a new space, 
    // Say hello, and tell users what you do!
    bot.say('Hi there, you can say hello to me.  Don\'t forget you need to mention me in a group space!');
  }
});

// say hello
framework.hears('hello', (bot, trigger) => {
  bot.say('Hello %s!', trigger.person.displayName);
}, '**hello** - say hello and I\'ll say hello back');

// echo user input
framework.hears('echo', (bot, trigger) => {
  bot.say('markdown', `You said: ${trigger.prompt}`);
}, '**echo** - I\'ll echo back the rest of your message');

// get help
framework.hears('help', (bot, trigger) => {
  bot.say('markdown', framework.showHelp());
}, '**help** - get a list of my commands', 0); // zero is default priorty

// Its a good practice to handle unexpected input
// Setting a priority > 0 means this will be called only if nothing else matches
framework.hears(/.*/gim, (bot, trigger) => {
    bot.say('Sorry, I don\'t know how to respond to "%s"', trigger.message.text);
    bot.say('markdown', framework.showHelp());
}, 99999); 

// define express path for incoming webhooks
app.post('/framework', webhook(framework));

// start express server
var server = app.listen(config.port, () => {
  framework.debug('Framework listening on port %s', config.port);
});

// gracefully shutdown (ctrl-c)
process.on('SIGINT', () => {
  framework.debug('stoppping...');
  server.close();
  framework.stop().then(() => {
    process.exit();
  });
});

Websocket Example

Buttons and Cards Example

Restify Example

Overview

The framework provides developers with some basic scaffolding to quickly get a bot up and running. Once a framework object is created with a configuration that includes a bot token, calling the framework.start() method kicks of the setup of this scaffolding. The framework registers for all Webex Teams events, and may discover existing Webex Teams spaces that the bot is already a member of.

A bot object is created for each space, and the framework generates a spawn event each time it finds a new one. When all existing bot objects are created the framework generates an initialized event signalling that it is ready to begin "listening" for user input.

// init framework
var framework = new Framework(config);
framework.start();

// An initialized event means your webhooks are all registered and the 
// framework has created bot objects for the spaces your bot was found in
framework.on("initialized", () => {
  framework.debug("Framework initialized successfully! [Press CTRL-C to quit]");
});

// A spawn event is generated when the framework finds a space with your bot in it
// You can use the bot object to send messages to that space
// The id field is the id of the framework
// If addedBy is set, it means that a user has added your bot to a new space
// Otherwise, this bot was in the space before this server instance started
framework.on('spawn', (bot, id, addedBy) => {
  if (!addedBy) {
    // don't say anything here or your bot's spaces will get 
    // spammed every time your server is restarted
    framework.debug(`Framework created an object for an existing bot in a space called: ${bot.room.title}`);
  } else {
    // addedBy is the ID of the user who just added our bot to a new space, 
    // Say hello, and tell users what you do!
    bot.say('Hi there, you can say hello to me.  Don\'t forget you need to mention me in a group space!');
  }
});

Most of the framework's functionality is based around the framework.hears() function. This defines the phrase or pattern the bot is listening for and what actions to take when that phrase or pattern is matched. The framework.hears() function gets a callback that includes three objects: the bot object, and the trigger object, and the id of the framework.

The bot object is a specific instance of the bot class associated with the Webex Teams space that triggered the framework.hears() call.
The trigger object provides details about the message that was sent, and the person who sent it, which caused the framework.hears() function to be triggered.

A simple example of a framework.hears() function setup:

let priority = 0;
framework.hears(phrase, (bot, trigger, id) => {
  bot.<command>
    .then((returnedValue) => {
      // do something with returned value
    })
    .catch((err) => {
      // handle errors
    });
},'This is text that describes what happens when user sends phrase to bot', priority);
  • phrase : This can be either a regex pattern or a string. If a regex pattern is used, it is matched against the entire message text. If a string, the phrase is matched if it is a substring of the room message. (This behavior differs slightly when run with a user token, see Differences between Bot Accounts and User Accounts).
  • bot : The bot object that is used to execute commands when the phrase is triggered.
  • bot.<command> : The Bot method to execute.
  • then : Node JS Promise keyword that invokes additional logic once the previous command is executed.
  • catch : handle errors that happen at either the original command or in any of the chained 'then' functions.
  • trigger : The object that describes the details around what triggered the phrase.
  • commands : The commands that are ran when the phrase is heard.
  • help text : Optional help text can be supplied after the function. This enables the framework.showHelp() method to automatically generate help messages for the bot.
  • priority : Optional priority can be supplied after the function (or help text) to specify which function should be called when multiple phrases match. The hears() method(s) with the lowest priorities are called if priorities are set.

Authentication

The token used to authenticate the Framework with the Webex API is passed as part of the options used when instantiating the Framework class. To change or update the token, use the Framework#setWebexToken() method.

Example:

var newToken = 'Tm90aGluZyB0byBzZWUgaGVyZS4uLiBNb3ZlIGFsb25nLi4u';

framework.setWebexToken(newToken)
.then((token) => {
  console.log('token updated to: ' + token);
});

Storage

The storage system used in the framework is a simple key/value store and resolves around these 3 methods:

  • bot.store(key, value) - Store a value to a bot instance where 'key' is a string and 'value' is a boolean, number, string, array, or object. This does not not support functions or any non serializable data. Returns the a promise with the value.
  • bot.recall(key) - Recall a value by 'key' from a bot instance. Returns a resolved promise with the value or a rejected promise if not found.
  • bot.forget([key]) - Forget (remove) value(s) from a bot instance where 'key' is an optional property that when defined, removes the specific key, and when undefined, removes all keys. Returns a resolved promise if deleted or not found.

When a bot is first spawned, the framework calls the bot.initStorage method which attepts to load any previously existing bot storage elements (if using a persistent storage driver such as MongoStore), or will create an optional initial set of key/value pairs that were specified in the framework's configuration options initBotStorageData element. If this is not set, new bots start off with no key/value pairs until bot.store() is called.

When a bot despawns (is removed from a space), the key/value store for that bot instance will automatically be removed from the store. Framework currently has an in-memory store and a mongo based store. By default, the in-memory store is used. Other backend stores are possible by replicating any one of the built-in storage modules and passing it to the framework.storeageDriver() method.

The MongoStore (and potentially other stores that use a persistent storage mechanism), also support the following methods:

  • initialize() -- this must be called before framework.storageDriver() and framework.start() are called, and will validate that the configuration is correct
  • writeMetrics() -- is a new, optional, method for persistent storage adaptors that can be called to write breadcrumbs into the database that can be used to build reports on the bot's usage

See MongoStore, for details on how to configure this storage adaptor.

The redis adaptor is likely broken and needs to be updated to support the new functions. It would be great if a flint user of redis wanted to contribute!

Bot Accounts vs. User Accounts.

Most Webex bots are built using a "Bot Account" that was created in Webex For Developers - Create A Bot.
It is also possible to build framework based applications using a "User Account" by specifying a user token obtained via a Webex Integration

When using "Bot Accounts" the major differences are:

  • Webhooks and websocket events for message:created only trigger when the Bot is mentioned by name
  • Unable to read all messages in Webex space using the Webex API.
  • May request the details of individual messages via the API by specifying a messageId. In group space the messageID must be for a message where the bot was "mentioned". Bots can request info for any message in 1-1 spaces.

Differences with matching string phrases when using Framework with a "Bot Account":

  • When running as a bot account and a framework.hears() is defined with a string phrase (as opposed to regex) the framework will convert the string to regex, for example: "string" is converted to /(^| )string( |$)/i in order to see if the string exists as a substring of the message.
  • When running as a user account, a string phrase will match only against the first word of the message.
  • Regex phrases behave the same in a `framework.hears() for both Bot and User accounts

Differences with trigger.args using Framework with a "Bot Account":

The trigger.args array is a shortcut in processing the trigger.text string. It consists of an array of the words that are in the trigger.message string split by one or more spaces. Punctation is included if there is no space between the symbol and the word. With bot accounts, this behaves a bit differently.

  • If defining a framework.hears() using a string (not regex), trigger.args is a filtered array of words from the message that begins after the first match of bot mention.
  • If defining a framework.hears() using regex, the trigger.args array is the entire message.

Troubleshooting

A common complaint from new framework developers is "My bot is not responding to messages!". If this is happening to you, here are a few things to check:

  1. Make sure you have configured your app with the token that belongs to the bot you are sending messages to.
  2. Make sure your framework based app is up and running.
  3. If using webhooks, make sure that your Webhook URL is reachable from the public internet. If you aren't sure how to test this, remove the webhookUrl key from your framework config object. This will use websockets which are more likely to work in development configurations.
  4. If interacting with a bot in a group space, make sure to at-mention your bot when you send it a message. Only messages that specifically at-mention a bot by name are sent to the bot logic.

If you are having intermittent problems with your bot failing to respond to messages this may be a problem with the Webex services itself, a problem with the framework, or a problem with the way you have configured your framework.hears(...) methods. One way to isolate the problem is to add a handler for the internal framework log events, as follows

framework.on('log', (msg) => {
  console.log(msg);
});

This will cause your app to include framework logging which provides details about every message received, and every framework.hears() handler that is invoked in response to those messages. If you don't see the message you are sending to your bot, contact Webex developer support. If you do see the message, check the logs to validate that your framework.hears() handler is being called. You may need to modify the phrase. See the framework.hears documentation

Framework Reference

Classes

Objects

Events

Framework

Kind: global class
Properties

NameTypeDescription
idstringFramework UUID
activebooleanFramework active state
initializedbooleanFramework fully initialized
isBotAccountbooleanIs Framework attached to Webex using a bot account?
isUserAccountbooleanIs Framework attached to Webex using a user account?
personobjectFramework person object
emailstringFramework email
webexobjectThe Webex JSSDK instance used by Framework

new Framework(options)

Creates an instance of the Framework.

ParamTypeDescription
optionsObjectConfiguration object containing Framework settings.

Example

var options = {
  webhookUrl: 'http://myserver.com/framework',
  token: 'Tm90aGluZyB0byBzZWUgaGVyZS4uLiBNb3ZlIGFsb25nLi4u'
};
var framework = new Framework(options);

framework.options : object

Options Object

Kind: instance namespace of Framework
Properties

NameTypeDefaultDescription
tokenstringWebex Token.
webhookUrlstringURL that is used for Webex API to send callbacks. If not set events are received via websocket
webhookSecretstringIf specified, inbound webhooks are authorized before being processed. Ignored if webhookUrl is not set.
httpsProxystringIf specified the https proxy to route request to webex through. Ie: "https://proxy.mycompany.com:8090"
maxStartupSpacesnumberIf specified, the maximum number of spaces with our bot that the framework will discover during startup. If not specified the framework will attempt to discover all the spaces the framework's identity is in and "spawn" a bot object for all of them before emitting an "initiatialized" event. For popular bots that belog to hundreds or thousands of spaces, this can result in long startup times. Setting this to a number (ie: 100) will limit the number of bots spawned before initialization. Bots that are driven by external events and rely on logic that checks if an appropriate bot object exists before sending a notification should not modify the default. Bots that are driven primarily by webex user commands to the bot may set this to 0 or any positive number to facilitate a faster startup. After initialization new bot objects are created ("spawned") when the bot is added to a new space or, if the framework receives events in existing spaces that it did not discover during initialization. In the case of these "late discoveries", bots objects are spawned "just in time". This behavior is similar to the way the webex teams clients work. See the Spawn Event docs to discover how to handle the different types of spawn events.
supressDirectSpaceSpawnFailuresbooleantrueWhen a bot has a 1-1 space with a webex user who is no longer active the bot will fail to spawn. By default these error messages are supressed. Set to false to see them.
messageFormatstring"text"Default Webex message format to use with bot.say().
profileMsgProcessingTimestringfalseSet to true to profile time spent in franmework and hears() callbacks per message.
initBotStorageDataobject{}Initial data for new bots to put into storage.
idstring"random"The id this instance of Framework uses.
webhookRequestJSONLocationstring"body"The property under the Request to find the JSON contents.
removeWebhooksOnStartBooleantrueIf you wish to have the bot remove all account webhooks when starting. Ignored if webhookUrl is not set.
removeDeviceRegistrationsOnStartBooleanfalseIf you use websockets and get "excessive device registrations" during iterative development, this will delete ALL device registrations. Use with caution! Ignored if webhookUrl is set.
restrictedToEmailDomainsstringSet to a comma seperated list of email domains the bot may interact with, ie "myco.com,myco2.com". For more details see the Membership-Rules README
guideEmailsstringSet to a comma seperated list of Webex users emails who MUST be in a space in order for the bot to work, ie "user1@myco.com,user2@myco2.com". For more details see the Membership-Rules README
membershipRulesDisallowedResponsestringMessage from bot when it detects it is in a space that does not conform to the membership rules specified by the restrictedToEmailDomains and/or the guideEmails parameters. Default messages is "Sorry, my use is not allowed for all the members in this space. Will ignore any new messages to me.". No message will be sent if this is set to an empty string.
membershipRulesStateMessageResponsestringMessage from bot when it is messaged in a space that does not conform to the membership rules specified by the restrictedToEmailDomains and/or the guideEmails parameters. Default messages is "Sorry, because my use is not allowed for all the members in this space I am ignoring any input.". No message will be sent if this is set to an empty string.
membershipRulesAllowedResponsestringMessage from bot when it detects that an the memberships of a space it is in have changed in in order to conform with the membership rules specified by the The default messages is "I am now allowed to interact with all the members in this space and will no longer ignore any input.". No message will be sent if this is set to an empty string.
fedrampBooleanIf specified, enables the framework to support the Webex FedRAMP environment.

framework.setWebexToken(token) ⇒ Promise.<String>

Tests, and then sets a new Webex Token.

Kind: instance method of Framework

ParamTypeDescription
tokenStringNew Webex Token for Framework to use.

Example

framework.setWebexToken('Tm90aGluZyB0byBzZWUgaGVyZS4uLiBNb3ZlIGFsb25nLi4u')
  .then((token) => {
     console.log('token updated to: ' + token);
  });

framework.getWebexSDK() ⇒ object

Accessor for Webex SDK instance

Access SDK functionality described in SDK Reference

Kind: instance method of Framework
Returns: object - - Framework's Webex SDK instance
Example

let webex = framework.getWebexSDK();
webex.people.get(me)
  .then(person => {
    console.log('SDK instantiated by: ' + person.displayName);
  }).catch(e => {
    console.error('SDK failed to lookup framework user: ' + e.message);
  });

framework.stop() ⇒ Promise.<Boolean>

Stop Framework.

Kind: instance method of Framework
Example

framework.stop();

framework.start() ⇒ Promise.<Boolean>

Start Framework.

Kind: instance method of Framework
Example

framework.start();

framework.restart() ⇒ Promise.<Boolean>

Restart Framework.

Kind: instance method of Framework
Example

framework.restart();

framework.getBotByRoomId(roomId) ⇒ object

Get bot object associated with roomId. Returns null if no object exists

Kind: instance method of Framework
Returns: object - - found bot object or null

ParamTypeDescription
roomIdstringid of room to search for

Example

let bot = framework.getBotByRoomId(roomId);
if (bot) {
  bot.say('Hi, I\'m the bot in this room!');
} else {
  console.log('Could not find bot for room ID: ' + roomId);
}

framework.hears(phrase, action, helpText, preference) ⇒ String

Add action to be performed when bot hears a phrase.

Kind: instance method of Framework

ParamTypeDefaultDescription
phraseRegex | StringThe phrase as either a regex or string. If regex, matches on entire message.If string, matches on first word.
actionfunctionThe function to execute when phrase is matched. Function is executed with 2 variables. Trigger and Bot. The Trigger Object contains information about the person who entered a message that matched the phrase. The Bot Object is an instance of the Bot Class as it relates to the room the message was heard.
helpTextStringThe string of text that describes how this command operates.
preferenceNumber0Specifies preference of phrase action when overlapping phrases are matched. On multiple matches with same preference, all matched actions are excuted. On multiple matches with difference preference values, only the lower preferenced matched action(s) are executed.

Example

// using a string to match first word and defines help text
framework.hears('/say', (bot, trigger) {
  bot.say(trigger.args.slice(1, trigger.args.length - 1));
}, '/say <greeting> - Responds with a greeting');

Example

// using regex to match across entire message
framework.hears(/(^| )beer( |.|$)/i, (bot, trigger) => {
  bot.say('Enjoy a beer, %s! 🍻', trigger.person.displayName);
});

Example

// echo user input using trigger.prompt
framework.hears('echo', (bot, trigger) => {
  if (trigger.command == 'echo') {
    bot.say('markdown', `You said: ${trigger.prompt}`);
  }
}, '**echo** - I\'ll echo back the rest of your message');

Example

// create hears handlers that use the helpText and preference params
// This handler has a lower preference than the catchall
// and inlcudes a built-in message for the showHelp command
framework.hears('help', (bot, trigger) => {
  bot.say('markdown', framework.showHelp());
}, 'help - shows information about commands I understand', 0);

// This catchall handler does not include a help  message, but it
// does set a high preference value so it will not be called if any
// handlers with a lower preference score match
framework.hears(/.*&#8205;/gim, (bot, trigger) => {
  bot.say('I didn\'t quite understand that.');
  bot.say('markdown;, framework.showHelp());
 }, 99999);

framework.clearHears(id) ⇒ null

Remove a "framework.hears()" entry.

Kind: instance method of Framework

ParamTypeDescription
idStringThe "hears" ID.

Example

// using a string to match first word and defines help text
var hearsHello = framework.hears('/framework', (bot, trigger, id) => {
  bot.say('Hello %s!', trigger.person.displayName);
});
framework.clearHears(hearsHello);

framework.showHelp(header, footer) ⇒ String

Display help for registered Framework Commands.

Kind: instance method of Framework

ParamTypeDefaultDescription
headerStringUsage:String to use in header before displaying help message.
footerStringPowered by Webex Node Bot Framework - https://github.com/WebexCommunity/webex-node-bot-frameworkString to use in footer before displaying help message.

Example

framework.hears('/help', (bot, trigger, id) => {
  bot.say('markdown', framework.showHelp());
});

framework.setAuthorizer(Action) ⇒ Boolean

Attaches authorizer function.

Kind: instance method of Framework

ParamTypeDescription
ActionfunctionThe function to execute when phrase is matched to authenticate a user. The function is passed the bot, trigger, and id and expects a return value of true or false.

Example

function myAuthorizer(bot, trigger, id) {
  if(trigger.personEmail === 'john@test.com') {
    return true;
  }
  else if(trigger.personDomain === 'test.com') {
    return true;
  }
  else {
    return false;
  }
}
framework.setAuthorizer(myAuthorizer);

framework.clearAuthorizer() ⇒ null

Removes authorizer function.

Kind: instance method of Framework
Example

framework.clearAuthorizer();

framework.storageDriver(Driver) ⇒ Promise.<Boolean>

Defines storage backend.

Kind: instance method of Framework
Returns: Promise.<Boolean> - - True if driver loaded succesfully

ParamTypeDescription
DriverfunctionThe storage driver.

Example

// define memory store (default if not specified)
framework.storageDriver(new MemStore());

framework.use(path) ⇒ Boolean

Load a Plugin from a external file.

Kind: instance method of Framework

ParamTypeDescription
pathStringLoad a plugin at given path.

Example

framework.use('events.js');

Example

// events.js
module.exports = (framework) => {
  framework.on('spawn', (bot) => {
    console.log('new bot spawned in room: %s', bot.myroom.title);
  });
  framework.on('despawn', (bot) => {
    console.log('bot despawned in room: %s', bot.myroom.title);
  });
  framework.on('messageCreated', (message, bot) => {
    console.log('"%s" said "%s" in room "%s"', message.personEmail, message.text, bot.myroom.title);
  });
};

framework.checkMembershipRules()

Private function to check for memembership rules in config

Kind: instance method of Framework

framework.myEmit()

Private emit functions that check the membership rules before emitting and event

Kind: instance method of Framework

Bot

Creates a Bot instance that is then attached to a Webex Team Room.

Kind: global class
Properties

NameTypeDescription
idstringBot UUID
activebooleanBot active state
personobjectBot's Webex Person Object
emailstringBot email
roomobjectBot's Webex Room object
membershipobjectBot's Webex Membership object
isLockedbooleanIf bot is locked
isModeratorbooleanIf bot is a moderator
isGroupbooleanIf bot is in Group Room
isDirectbooleanIf bot is in 1:1/Direct Room
isTeambooleanIf bot is in a Room associated to a Team
isDirectTostringRecipient Email if bot is in 1:1/Direct Room
lastActivitydateLast bot activity

new Bot(framework, options, webex)

ParamTypeDescription
frameworkObjectThe framework object this Bot spawns under.
optionsObjectThe options of the framework object this Bot spawns under.
webexObjectThe webex sdk of the framework object this Bot spawns under.

bot.exit() ⇒ Promise.<Boolean>

Instructs Bot to exit from room.

Kind: instance method of Bot
Example

bot.exit();

bot.getWebexSDK() ⇒ object

Accessor for Webex SDK instance

This is a convenience and returns the same shared Webex SDK instance that is returned by a call to framework.getWebexSDK()

Access SDK functionality described in SDK Reference

Kind: instance method of Bot
Returns: object - - Bot's Webex SDK instance
Example

let webex = bot.getWebexSDK();
webex.people.get(me)
  .then(person => {
    console.log('SDK instantiated by: ' + person.displayName);
  }).catch(e => {
    console.error('SDK failed to lookup framework user: ' + e.message);
  });

bot.add(email(s), moderator) ⇒ Promise.<Array>

Instructs Bot to add person(s) to room.

Kind: instance method of Bot
Returns: Promise.<Array> - Array of emails added

ParamTypeDescription
email(s)String | ArrayEmail Address (or Array of Email Addresses) of Person(s) to add to room.
moderatorBooleanAdd as moderator.

Example

// add one person to room by email
bot.add('john@test.com');

Example

// add one person as moderator to room by email
bot.add('john@test.com', true)
  .catch((err) => {
    // log error if unsuccessful
    console.log(err.message);
  });

Example

// add 3 people to room by email
bot.add(['john@test.com', 'jane@test.com', 'bill@test.com']);

bot.remove(email(s)) ⇒ Promise.<Array>

Instructs Bot to remove person from room.

Kind: instance method of Bot
Returns: Promise.<Array> - Array of emails removed

ParamTypeDescription
email(s)String | ArrayEmail Address (or Array of Email Addresses) of Person(s) to remove from room.

Example

// remove one person to room by email
bot.remove('john@test.com');

Example

// remove 3 people from room by email
bot.remove(['john@test.com', 'jane@test.com', 'bill@test.com']);

bot.getModerators() ⇒ Promise.<Array>

Get room moderators.

Kind: instance method of Bot
Example

bot.getModerators()
  .then((moderators) => {
    console.log(moderators);
  });

bot.newRoom(name, emails, isTeam) ⇒ Promise.<Bot>

Create new room with people by email

Kind: instance method of Bot

ParamTypeDescription
nameStringName of room.
emailsArrayEmails of people to add to room.
isTeamBoolean- Create a team room (if bot is already in a team space)

bot.newTeamRoom(name, emails) ⇒ Promise.<Bot>

Create new Team Room

This can also be done by passing an optional boolean isTeam param to the newRoom() function, but this function is also kept for compatibility with node-flint

Kind: instance method of Bot

ParamTypeDescription
nameStringName of room.
emailsArrayEmails of people to add to room.

bot.moderateRoom() ⇒ Promise.<Bot>

Enable Room Moderation.

This function will not work when framework was created using a bot token, it requires an authorized user token

Kind: instance method of Bot
Example

bot.moderateRoom()
  .then((err) => {
    console.log(err.message)
  });

bot.unmoderateRoom() ⇒ Promise.<Bot>

Disable Room Moderation.

This function will not work when framework was created using a bot token, it requires an authorized user token

Kind: instance method of Bot
Example

bot.unmoderateRoom()
  .then((err) => {
    console.log(err.message)
  });

bot.moderatorSet(email(s)) ⇒ Promise.<Bot>

Assign Moderator in Room

This function will not work when framework was created using a bot token, it requires an authorized user token

Kind: instance method of Bot

ParamTypeDescription
email(s)String | ArrayEmail Address (or Array of Email Addresses) of Person(s) to assign as moderator.

Example

bot.moderatorSet('john@test.com')
  .then((err) => {
    console.log(err.message)
  });

bot.moderatorClear(email(s)) ⇒ Promise.<Bot>

Unassign Moderator in Room

This function will not work when framework was created using a bot token, it requires an authorized user token

Kind: instance method of Bot

ParamTypeDescription
email(s)String | ArrayEmail Address (or Array of Email Addresses) of Person(s) to unassign as moderator.

Example

bot.moderatorClear('john@test.com')
  .then((err) => {
    console.log(err.message)
  });

bot.implode() ⇒ Promise.<Boolean>

Remove a room and all memberships.

Kind: instance method of Bot
Example

framework.hears('/implode', (bot, trigger) => {
  bot.implode();
});

bot.say(format, message) ⇒ Promise.<Message>

Send text with optional file to room.

Kind: instance method of Bot

ParamTypeDefaultDescription
formatStringtextSet message format. Valid options are 'text' or 'markdown'.
messageString | ObjectMessage to send to room. This can be a simple string, or a object for advanced use.

Example

// Simple example
framework.hears('/hello', (bot, trigger) => {
  bot.say('hello');
});

Example

// Simple example to send message and file
framework.hears('/file', (bot, trigger) => {
  bot.say({text: 'Here is your file!', file: 'http://myurl/file.doc'});
}, '**file** - ask bot to post a file to the space');

Example

// Markdown Method 1 - Define markdown as default
framework.messageFormat = 'markdown';
framework.hears('/hello', (bot, trigger) => {
  bot.say('**hello**, How are you today?');
}, '**hello** - say hello to the bot');

Example

// Markdown Method 2 - Define message format as part of argument string
framework.hears('/hello', (bot, trigger) => {
  bot.say('markdown', '**hello**, How are you today?');
}, '**hello** - say hello to the bot');

Example

// Mardown Method 3 - Use an object (use this method of bot.say() when needing to send a file in the same message as markdown text.
framework.hears('/hello', (bot, trigger) => {
  bot.say({markdown: '*Hello <@personEmail:' + trigger.personEmail + '|' + trigger.personDisplayName + '>*'});
}, '**hello** - say hello to the bot');

Example

// Send an Webex card by providing a fully formed message object.
framework.hears('/card please', (bot, trigger) => {
  bot.say({       
     // Fallback text for clients that don't render cards is required
     markdown: "If you see this message your client cannot render buttons and cards.",
     attachments: [{
       "contentType": "application/vnd.microsoft.card.adaptive",
       "content": myCardsJson
    }]
   });
  }, '**card please** - ask bot to post a card to the space');

bot.sayWithLocalFile(message, filename) ⇒ Promise.<Message>

Send optional text message with a local file to room.

Kind: instance method of Bot

ParamTypeDescription
messageString | ObjectMessage to send to room. If null or empty string is ignored. If set the default messageFormat is used
filenameStringname of local file to send to space

Example

// Simple example
framework.hears('/file', (bot, trigger) => {
  bot.sayWithLocalFile('here is a file', './image.jpg);
}, '**file** - ask bot to send a file to the space');

bot.reply(replyTo, message, format) ⇒ Promise.<Message>

Send a threaded message reply

Kind: instance method of Bot

ParamTypeDefaultDescription
replyToString | ObjectMessageId or message object or attachmentAction object to send to reply to. Passing a message object ensures that the reply will succeed even if the parent message is also a reply in a thread.
messageString | ObjectMessage to send to room. This can be a simple string, or a message object for advanced use.
formatStringtextSet message format. Valid options are 'text' or 'markdown'. Default format is used if not set.

Example

// Simple example
framework.hears('/hello', (bot, trigger) => {
  bot.reply(trigger.message, 'hello back at you');
}, '**hello** - say hello to the bot);

Example

// Reply to a card when a user hits an action.submit button
framework.on('attachmentAction', (bot, trigger) => {
  bot.reply(trigger.attachmentAction, 'Thanks for hitting the button');
});

Example

// Reply to a reply
// The Webex messaging API does not allow a reply to a reply.
// If the replyTo parameter is a message object, the framework
// will look for a parentId in that object and pass it to webex, effectively
// allowing a framework based app to support a reply to a reply.
framework.hears('This is a reply', (bot, trigger) => {
  // This will work even if the parent message is already a reply
  bot.reply(trigger.message, 'and this is a reply to a reply');
  // This only works if replyTo is a message object.  It will fail if
  // replyTo is the messageId of a message that is already a reply.
  // So for example this won't work:
  return bot.reply(trigger.message.id, 'this will fail if the message was already a reply')
    .catch((e) => console.log(e.message));
});

bot.dm(person, format, message) ⇒ Promise.<Message>

Send text with optional file in a direct message. This sends a message to a 1:1 room with the user (creates 1:1, if one does not already exist)

Kind: instance method of Bot

ParamTypeDefaultDescription
personStringEmail or personId of person to send Direct Message.
formatStringtextSet message format. Valid options are 'text' or 'markdown'.
messageString | ObjectMessage to send to room. This can be a simple string, or a object for advanced use.

Example

// Simple example
framework.hears('dm me', (bot, trigger) => {
  bot.dm(trigger.person.id, 'hello');
}, '**dm me** - ask the bot to send a message to you in a 1-1 space');

Example

// Simple example to send message and file
framework.hears('dm me a file', (bot, trigger) => {
  bot.dm(trigger.person.id, {text: 'Here is your file!', file: 'http://myurl/file.doc'});
}, '**dm me a file ** - ask the bot to send a file to you in a 1-1 space');

Example

// Markdown Method 1 - Define markdown as default
framework.messageFormat = 'markdown';
framework.hears('dm me some rich text', (bot, trigger) => {
  bot.dm(trigger.person.id, '**hello**, How are you today?');
}, '**dm me some rich text** - ask the bot to send a rich text message to you in a 1-1 space');

Example

// Markdown Method 2 - Define message format as part of argument string
framework.hears('dm someone', (bot, trigger) => {
  bot.dm('john@doe.com', 'markdown', '**hello**, How are you today?');
}, '**dm someone** - ask the bot to send a message to john@doe.com in a 1-1 space');

Example

// Mardown Method 3 - Use an object (use this method of bot.dm() when needing to send a file in the same message as markdown text.
framework.hears('dm someone', (bot, trigger) => {
  bot.dm('someone@domain.com', {markdown: '*Hello <@personId:' + trigger.person.id + '|' + trigger.person.displayName + '>*'});
}, '**dm someone** - ask the bot to send a message and file to someone@domain.com in a 1-1 space');

bot.sendCard(cardJson, fallbackText) ⇒ Promise.<Message>

Send a Webex Teams Card to room.

Kind: instance method of Bot
See

ParamTypeDescription
cardJsonObjectThe card JSON to render. This can come from the Webex Buttons and Cards Designer.
fallbackTextStringMessage to be displayed on client's that can't render cards.

Example

// Simple example
framework.hears('card please', (bot, trigger) => {
  bot.SendCard(
   {
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "type": "AdaptiveCard",
      "version": "1.0",
      "body": [
          {
              "type": "ColumnSet",
              "columns": [
                  {
                      "type": "Column",
                      "width": 2,
                      "items": [
                          {
                              "type": "TextBlock",
                              "text": "Card Sample",
                              "weight": "Bolder",
                              "size": "Medium"
                          },
                          {
                              "type": "TextBlock",
                              "text": "What is your name?",
                              "wrap": true
                          },
                          {
                              "type": "Input.Text",
                              "id": "myName",
                              "placeholder": "John Doe"
                          }
                      ]
                  }
              ]
          }
      ],
      "actions": [
          {
              "type": "Action.Submit",
              "title": "Submit"
          }
      ]
   },
   "This is the fallback text if the client can't render this card");
 }, '**card please** - ask the bot to post a card to the space');

bot.dmCard(person, cardJson, fallbackText) ⇒ Promise.<Message>

Send a Card to a 1-1 space.

Kind: instance method of Bot

ParamTypeDescription
personStringEmail or ID of the user to 1-1 message.
cardJsonObjectThe card JSON to render. This can come from the Webex Buttons and Cards Designer.
fallbackTextStringMessage to be displayed on client's that can't render cards.

Example

// Simple example
framework.hears('card for joe please', (bot, trigger) => {
  bot.dmCard(
   'joe@email.com',
   {
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "type": "AdaptiveCard",
      "version": "1.0",
      "body": [
          {
            "type": "TextBlock",
            "text": "Joe, here is your card!",
            "weight": "Bolder",
            "size": "Medium"
          }
      ]
   },
   "This is the fallback text if the client can't render this card");
 }, '**card for john please** - ask the bot to send a card to joe@email.com in a 1-1 space');

bot.uploadStream(filename, stream) ⇒ Promise.<Message>

Upload a file to a room using a Readable Stream

Kind: instance method of Bot

ParamTypeDescription
filenameStringFile name used when uploading to room
streamStream.ReadableStream Readable

Example

framework.hears('/file', (bot, trigger) => {

  // define filename used when uploading to room
  var filename = 'test.png';

  // create readable stream
  var stream = fs.createReadStream('/my/file/test.png');

  bot.uploadStream(stream);
}, '**\/file** - ask the bot to post a file to the space via the stream method');

bot.censor(messageId) ⇒ Promise.<null>

Remove Message By Id.

Kind: instance method of Bot
Returns: Promise.<null> - - API returns 204 with no content upon success

ParamType
messageIdString

bot.roomRename(title) ⇒ Promise.<Room>

Set Title of Room.

Kind: instance method of Bot

ParamType
titleString

Example

bot.roomRename('My Renamed Room')
  .then((err) => {
    console.log(err.message)
  });

bot.store(key, value) ⇒ Promise.<String> | Promise.<Number> | Promise.<Boolean> | Promise.<Array> | Promise.<Object>

Store key/value data.

Kind: instance method of Bot

ParamTypeDescription
keyStringKey under id object
valueString | Number | Boolean | Array | ObjectValue of key

bot.recall(key) ⇒ Promise.<String> | Promise.<Number> | Promise.<Boolean> | Promise.<Array> | Promise.<Object>

Recall value of data stored by 'key'.

Kind: instance method of Bot

ParamTypeDescription
keyStringKey under id object (optional). If key is not passed, all keys for id are returned as an object.

bot.forget(key) ⇒ Promise.<String> | Promise.<Number> | Promise.<Boolean> | Promise.<Array> | Promise.<Object>

Forget a key or entire store.

Kind: instance method of Bot

ParamTypeDescription
keyStringKey under id object (optional). If key is not passed, id and all children are removed.

Trigger : object

Trigger Object

Kind: global namespace
Properties

NameTypeDescription
typestringtype of trigger - message or attachmentAction
idstringMessage or attachentAction ID
messageobjectmessage that caused this trigger (if type is 'message')
phrasestring | regexMatched lexicon phrase if any
commandstringPortion of message text that matched phrase.
promptstringPortion of message text that follows the command (excluding any bot mentions)
argsarrayFiltered array of words in message text.
attachmentActionobjectattachmentAction that caused this trigger (if type is 'attachmentAction')
personobjectPerson object associated with user that sent the message or action
personIdstringID of person

"log"

Framework log event.

Applications may implement a framework.on("log") handler to process log messags from the framework, such as details about events that were not sent due to mebership rules. See Membership-Rules README

Kind: event emitted
Properties

NameTypeDescription
messagestringLog Message

"stop"

Framework stop event.

Kind: event emitted
Properties

NameTypeDescription
idstringFramework UUID

"start"

Framework start event.

Kind: event emitted
Properties

NameTypeDescription
idstringFramework UUID

"initialized"

Framework initialized event.

Kind: event emitted
Properties

NameTypeDescription
idstringFramework UUID

"roomLocked"

Room Locked event.

Kind: event emitted
Properties

NameTypeDescription
botobjectBot Object
roomobjectRoom Object
idstringFramework UUID

"roomUnocked"

Room Unocked event.

Kind: event emitted
Properties

NameTypeDescription
botobjectBot Object
roomobjectRoom Object
idstringFramework UUID

"roomRenamed"

Room Renamed event.

Kind: event emitted
Properties

NameTypeDescription
botobjectBot Object
roomobjectRoom Object
idstringFramework UUID

"memberEnters"

Member Enter Room event.

Kind: event emitted
Properties

NameTypeDescription
botobjectBot Object
membershipobjectMembership Object
idstringFramework UUID

"botAddedAsModerator"

Bot Added as Room Moderator.

Kind: event emitted
**Propertie

2.5.1

3 months ago

2.4.1

1 year ago

2.4.0

1 year ago

2.4.2

1 year ago

2.5.0

12 months ago

2.3.13

2 years ago

2.3.12

2 years ago

2.3.15

2 years ago

2.3.14

2 years ago

2.3.11

2 years ago

2.3.10

2 years ago

2.3.8

2 years ago

2.3.9

2 years ago

2.3.7

3 years ago

2.3.6

3 years ago

2.3.5

3 years ago

2.3.4

3 years ago

2.3.3

3 years ago

2.3.2

3 years ago

2.3.1

3 years ago

2.3.0

4 years ago

2.2.0

4 years ago

2.1.1

4 years ago

2.1.0

4 years ago

2.0.0

4 years ago

1.2.2

4 years ago

1.2.1

4 years ago

1.2.0

4 years ago

1.1.0

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

0.7.1

4 years ago

0.7.0

4 years ago

0.6.1

4 years ago

0.6.0

4 years ago

0.5.0

4 years ago

0.4.0

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.2

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago