All Projects → CiscoDevNet → Node Sparkbot

CiscoDevNet / Node Sparkbot

Licence: mit
Build Webex ChatBots in JavaScript

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Node Sparkbot

Deeppavlov
An open source library for deep learning end-to-end dialog systems and chatbots.
Stars: ✭ 5,525 (+30594.44%)
Mutual labels:  chatbot
Chatui
The UI design language and React library for Conversational UI
Stars: ✭ 684 (+3700%)
Mutual labels:  chatbot
Groupme Giphy Bot
A bot that adds the /giphy command to Groupme.
Stars: ✭ 5 (-72.22%)
Mutual labels:  chatbot
Botman
A framework agnostic PHP library to build chat bots
Stars: ✭ 5,538 (+30666.67%)
Mutual labels:  chatbot
Yoda
Wise and powerful personal assistant, available in your nearest terminal
Stars: ✭ 674 (+3644.44%)
Mutual labels:  chatbot
Integrations
Connect your App to Multiple Messaging Channels with the W3C Open standard.
Stars: ✭ 721 (+3905.56%)
Mutual labels:  chatbot
Hangoutsbot
Google Hangouts bot
Stars: ✭ 578 (+3111.11%)
Mutual labels:  chatbot
Viber
Viber messaging/chatbot for Go/Golang
Stars: ✭ 17 (-5.56%)
Mutual labels:  chatbot
Chatito
🎯🗯 Generate datasets for AI chatbots, NLP tasks, named entity recognition or text classification models using a simple DSL!
Stars: ✭ 678 (+3666.67%)
Mutual labels:  chatbot
Insuranceqa Corpus Zh
🚁 保险行业语料库,聊天机器人
Stars: ✭ 821 (+4461.11%)
Mutual labels:  chatbot
Me bot
Build a bot that speaks like you!
Stars: ✭ 641 (+3461.11%)
Mutual labels:  chatbot
Awesome Chatops
🤖 A collection of awesome things about ChatOps – managing operations through a chat
Stars: ✭ 648 (+3500%)
Mutual labels:  chatbot
Seq2seq Chatbot
Chatbot in 200 lines of code using TensorLayer
Stars: ✭ 777 (+4216.67%)
Mutual labels:  chatbot
Facebook Messenger Bot
Facebook chatbot that I trained to talk like me using Seq2Seq
Stars: ✭ 602 (+3244.44%)
Mutual labels:  chatbot
Tensorlayer
Deep Learning and Reinforcement Learning Library for Scientists and Engineers 🔥
Stars: ✭ 6,796 (+37655.56%)
Mutual labels:  chatbot
Pymessager
Python API to develop chatbot on Facebook Messenger Platform
Stars: ✭ 580 (+3122.22%)
Mutual labels:  chatbot
Program O
PHP MySQL AIML Chatbot - One click installation. Fully loaded admin area to admin your chatbot. Set up multiple chatbots. Foreign language support. XML/JSON responses or just plain HTML. Massive community of users. Twitter Plugins and lots and lots more. Please feel free to fork the DEV branch and contribute. :)
Stars: ✭ 712 (+3855.56%)
Mutual labels:  chatbot
Line Account Link
LINE account link tutorial with sample code
Stars: ✭ 18 (+0%)
Mutual labels:  chatbot
Nadekobot
Open source, general-purpose Discord chat bot written in C#
Stars: ✭ 892 (+4855.56%)
Mutual labels:  chatbot
Botkube
An app that helps you monitor your Kubernetes cluster, debug critical deployments & gives recommendations for standard practices
Stars: ✭ 804 (+4366.67%)
Mutual labels:  chatbot

Build Webex ChatBots in JavaScript

Yet another opiniated framework to build Webex Teams Bots in Node.js:

This project focusses on the framework itself and its testing companions.

If you're looking for ready-to-run Chatbots built with the library, jump to the node-sparkbot-samples repo.

Quickstart

Copy a sample from Quickstart.

For Mac, Linux and bash users, open a terminal and type:

git clone https://github.com/CiscoDevNet/node-sparkbot
cd node-sparkbot
npm install
DEBUG=sparkbot* node tests/onEvent-all-all.js

For Windows users, open a command shell and type:

git clone https://github.com/CiscoDevNet/node-sparkbot
cd node-sparkbot
npm install
set DEBUG=sparkbot*
node tests/onEvent-all-all.js

Done, your bot is live

Let's check it's live by hitting its healthcheck endpoint:

# simply run: curl http://localhost:8080 
# or if you like formatting, install jq and run:
$ curl http://localhost:8080 | jq -C
{
  "message": "Congrats, your Webex Teams webhook is up and running",
  "since": "2016-09-23T07:46:52.397Z",
  "tip": "Register your bot as a WebHook to start receiving events: https://developer.webex.com/endpoint-webhooks-post.html",
  "listeners": [
    "messages/created"
  ],
  "token": false,
  "account": {},
  "interpreter": {},
  "commands": [],
}

Congrats, your bot is now up and running

Now, let's make Webex post events to our bot.

Note that if you want your bot to respond to commands, add a Webex Teams API token on the command line (see below).

Finally, we suggest you take a look at the tests as they provide a great way to discover the framework features.

Respond to commands

At startup, the library looks for the ACCESS_TOKEN environment variable.

Note that ACCESS_TOKEN is still accepted but deprecated as of v1.x of the framework

If present, the library will leverage the token to retreive new message contents, and automatically detect the Webex Teams account associated to the token and take initialization options to fit common scenarios, see Account detection.

As messages flow in, the library automatically removes bot mentions when relevant, so that you can focus on the command itself.

DEBUG=sparkbot*  ACCCESS_TOKEN=Very_Secret  node tests/onCommand.js

...
  sparkbot webhook instantiated with default configuration +0ms
  sparkbot addMessagesCreatedListener: listener registered +89ms
  sparkbot bot started on port: 8080 +8ms
  sparkbot:interpreter bot account detected, name: CiscoDevNet (bot) +1s

Capture inputs submitted via Cards

We'll use a sample card that proposes a single name entry field.

To create the card, create a Webex Teams space and place the following requests with the roomId of your space, typically via Postman. Note: you can use this postman collection to experiment with Cards. After importing the collection, make sure to add a BOT_TOKEN variable to your Postman environment.

POST https://api.ciscospark.com/v1/messages
Authorization: Bearer YOUR_BOT_TOKEN
{{
    "roomId": "{{_room}}",
    "markdown": "[Learn more](https://adaptivecards.io) about Adaptive Cards.",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "content": {
                "type": "AdaptiveCard",
                "version": "1.0",
                "body": [
                    {
                        "type": "TextBlock",
                        "text": "Please enter your name:"
                    },
                    {
                        "type": "Input.Text",
                        "id": "name",
                        "title": "New Input.Toggle",
                        "placeholder": "name"
                    }
                ],
                "actions": [
                    {
                        "type": "Action.Submit",
                        "title": "Submit"
                    }
                ]
            }
        }
    ]
}

As cards are submitted, the onCardSubmission() function invokes your custom code logic. Note: if a PUBLIC_URL environment variable is present, the example will automatically create a Webhook.

 DEBUG=sparkbot ACCESS_TOKEN=Y2QzMz_typically_a_bot_token_JlODAzZmItYTVm PUBLIC_URL="https://d3fc85fe.ngrok.io" node tests/onCardSubmission-webhook.js

...
 sparkbot webhook instantiated with default configuration +0ms
  sparkbot bot started on port: 8080 +37ms
  sparkbot webhook already exists with same properties, no creation needed +664ms
webhook successfully checked, with id: Y2lzY29zcGFyazovL3VzL1dFQkhPT0svYTkyYWU5NjMtOTNmYS00YTE0LWEwOGItYTMzMjQ5MzA3MGQ4
  sparkbot webhook invoked +9s
  sparkbot calling listener for resource/event: attachmentActions/created, with data context: Y2lzY29zcGFyazovL3VzL0FUVEFDSE1FTlRfQUNUSU9OLzkyNmEzNDYwLWMzMjktMTFlOS05OGQyLTg5ZDBlNGQyZDU1Mg +6ms
new attachmentActions from personId: Y2lzY29zcGFyazovL3VzL1BFT1BMRS85MmIzZGQ5YS02NzVkLTRhNDEtOGM0MS0yYWJkZjg5ZjQ0ZjQ , with inputs
   name: CiscoDevNet

Here is the code used by the sample, hou can check the full code sample here:

// Starts your Webhook with a default configuration where the Webex API access token is read from ACCESS_TOKEN
const SparkBot = require("../sparkbot/webhook");
const bot = new SparkBot();

// Create webhook
const publicURL = process.env.PUBLIC_URL || "https://d3fc85fe.ngrok.io";
bot.secret = process.env.WEBHOOK_SECRET || "not THAT secret";
bot.createOrUpdateWebhook("register-bot", publicURL, "attachmentActions", "created", null, bot.secret);
 
// Process new card submissions
bot.onCardSubmission(function (trigger, attachmentActions) {

   console.log(`new attachmentActions from personId: ${trigger.data.personId} , with inputs`);
   Object.keys(attachmentActions.inputs).forEach(prop => {
      console.log(`   ${prop}: ${attachmentActions.inputs[prop]}`);
   });
});

Architecture

The library supports the full set of Webex Teams webhooks, see https://developer.webex.com/webhooks-explained.html

As Webex fires Webhook events, the related listener functions are called.

You can register to listen to a WebHook event by calling the function ".on(,)"

Note that the library implements a shortcut that lets you listen to all Webhook events. Check sample code onEvent-all-all.js.

var SparkBot = require("sparkbot");
var bot = new SparkBot();
 
bot.onEvent("all", "all", function(trigger) {
  
    // YOUR CODE HERE
    console.log("EVENT: " + trigger.resource + "/" + trigger.event + ", with data id: " + trigger.data.id + ", triggered by person id:" + trigger.actorId);
});

This other example code onEvent-messages-created.js illustrates how to listen to (Messages/Created) Webhook events.

// Starts your Webhook with default configuration where the Webex Teams API access token is read from the ACCESS_TOKEN env variable 
var SparkBot = require("sparkbot");
var bot = new SparkBot();

bot.onEvent("messages", "created", function(trigger) {
    console.log("new message from: " + trigger.data.personEmail + ", in room: " + trigger.data.roomId);
    bot.decryptMessage(trigger, function (err, message) {
        if (err) {
            console.log("could not fetch message contents, err: " + err.message); 
            return;
        }

        // YOUR CODE HERE
        console.log("processing message contents: " + message.text);
    });
});

New message listener

The library also provides a shortcut easy way to listen to only new messages, via the .onMessage() function.

Note that this function is not only a shorcut to create a ".on('messages', 'created')" listener. It also automatically fetches for you the text of the new message by requesting Webex Teams for the message details. As the message is fetched behind the scene, you should position a ACCESS_TOKEN env variable when starting up your bot.

Check the onMessage.js for an example:

// Starts your Webhook with default configuration where the Webex Teams API access token is read from the ACCESS_TOKEN env variable 
SparkBot = require("node-sparkbot");
var bot = new SparkBot();
 
bot.onMessage(function(trigger, message) {
 
  // ADD YOUR CUSTOM CODE HERE
  console.log("new message from: " + trigger.data.personEmail + ", text: " + message.text);
});

Note that most of the time, you'll want to check for the presence of a keyword to take action. To that purpose, you can check this example: onMessage-asCommand.

// Starts your Webhook with default configuration where the Webex Teams API access token is read from the ACCESS_TOKEN env variable 
var SparkBot = require("node-sparkbot");
var bot = new SparkBot();

bot.onMessage(function (trigger, message) {
    console.log("new message from: " + trigger.data.personEmail + ", text: " + message.text);

    var command = bot.asCommand(message);
    if (command) {
        // // ADD YOUR CUSTOM CODE HERE
        console.log("detected command: " + command.keyword + ", with args: " + JSON.stringify(command.args));
    }
});

Note that The onCommand function below is pretty powerful, as it not only checks for command keywords, but also removes any mention of your bot, as this mention is a Webex pre-requisite for your bot to receive a message in a group space, but it meaningless for your bot to process the message.

Well that said, we're ready to go thru the creation of interactive assistants.

Interactive assistants

To implement an interative assistant, you would typically:

  • respond to commands (keywords) via an onCommand() listener function
    • with an option to trim mention if your bot is mentionned in a group room
    • and an option to specify a fallback command
    • please check onCommand sample
  • respond to attachementActions submissions (cards) via an onCardSubmission() listener function
  • manually create a webhook via a POST /webhooks request against the Webex REST API

Healthcheck

The library automatically exposes an healthcheck endpoint. As such, hitting GET / will respond a 200 OK with an attached JSON payload.

The healcheck JSON payload will give you extra details:

  • token:true // if a token was detected at launch
  • account // detailled info about the Webex Teams account tied to the token
  • listeners // events for which your bot has registered a listener
  • commands // commands for which your bot is ready to be activated
  • interpreter // preferences for the command interpreter
// Example of a JSON healthcheck
{
  "message": "Congrats, your Webex Teams bot is up and running",
  "since": "2016-09-01T13:15:39.425Z",
  "tip": "Register webhooks for your bot to start receiving events: https://developer.webex.com/endpoint-webhooks-post.html"
  "listeners": [
    "messages/created"
  ],
  "token": true,
  "account": {
    "type": "human",
    "person": {
      "id": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS85MmIzZGQ5YS02NzVkLTRhNDEtOGM0MS0yYWJkZjg5ZjQ0ZjQ",
      "emails": [
        "[email protected]"
      ],
      "displayName": "Stève Sfartz",
      "avatar": "https://1efa7a94ed216783e352-c62266528714497a17239ececf39e9e2.ssl.cf1.rackcdn.com/V1~c2582d2fb9d11e359e02b12c17800f09~aqSu09sCTVOOx45HJCbWHg==~1600",
      "created": "2016-02-04T15:46:20.321Z"
    }
  },
  "interpreter": {
    "prefix": "/",
    "trimMention": true,
    "ignoreSelf": false
  },
  "commands": [
    "help"
  ]
}

Account Type Detection

If a Webex teams API access token has been specified at launch, the library will request details about the Webex Teams account. From the person details provided, the library will infer if the token matches a individual (HUMAN) or a bot account (MACHINE). Because of restrictions concerning bots, the library will setup a default behavior from the account type, unless configuration parameters have already been provided at startup.

Note that the automatic account detection procedure is done asynchronously at launch.

Here is the set of extra information and behaviors that relate to the automatic bot detection: - your bot is populated with an account property - your bot is added a nickName property - a type is attached to your bot instance [HUMAN | MACHINE | OTHER]

Authenticating Requests via payload signature

To ensure paylods received by your bots come from Webex, you can supply a secret parameter at Webhook creation. Every payload posted to your bot will then contain an extra HTTP header "X-Spark-Signature" containing an HMAC-SHA1 signature of the payload.

Once you've created the webhook for your bot with a secret parameter, you can either specify a SECRET environment variable on the command line or in your code.

Command line example:

DEBUG=sparkbot*  ACCESS_TOKEN=your_bot_token WEBHOOK_SECRET=your_secret   node tests/onEvent-check-secret.js
...

Code example:

// Starts your Webhook with default configuration where the Webex Teams API access token is read from the ACCESS_TOKEN env variable 
SparkBot = require("node-sparkbot");
var bot = new SparkBot();
bot.secret = "not THAT secret"
...

Note that it is a HIGHLY RECOMMENDED however not mandatory security practice to set up a SECRET. If your bot has been started with a secret, then the processing will abort if the incoming payload signature is not present or do not fit. However, the bot framework defines a flag so that you can ignore signature check failures when a SECRET is defined.

Auto-Register Webhooks

At startup, node-sparkbot can automatically create a Webhook for your bot, or verify if a webhook already exists with the specified name. Here are a few of the options supported:

  • Simplissime registration where defaults apply (all, all, no filter, no secret), and no callback

    bot.createOrUpdateWebhook("register-bot", "https://f6d5d937.ngrok.io");

  • Registration with no filter, no secret, and no callback

    bot.createOrUpdateWebhook("register-bot", "https://f6d5d937.ngrok.io", "all", "all");

  • Registration with a filter, no secret, no callback

    bot.createOrUpdateWebhook("register-bot", "https://f6d5d937.ngrok.io", "all", "all", "roomId=XXXXXXXXXXXXXXX");

  • Registration with no filter, but a secret and a callback

    bot.createOrUpdateWebhook("register-bot", publicURL, "all", "all", null, bot.secret, function (err, webhook) { ... }

You can check onCommand-webhook.js for an example.

bot.createOrUpdateWebhook("register-bot", "https://f6d5d937.ngrok.io", "all", "all", null, bot.secret, function (err, webhook) {
  console.log("webhook successfully created, id: " + webhook.id);
});

Minimal footprint

node-sparkbot makes a minimal use of third party libraries :

  • debug: as we need a customizable logger
  • express & body-parser: as its Web API foundation
  • htmlparser2: to filter out the bot mention from the message contents

Morever, node-sparkbot does not embedd any Webex Teams client SDK, so that you can choose your favorite (ie, among ciscospark, node-sparky or node-sparkclient...) to interact with Webex.

Contribute

Feedback, issues, thoughts... please use github issues.

Interested in contributing code?

  • Check for open issues or create a new one.
  • Submit a pull request. Just make sure to reference the issue.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].