TweetFace: A BrightWork RESTBot Tutorial

BrightWork comes with a lot of power right out of the box, but maybe you're interested in writing your own custom routes and operations on the back-end. You can do this by building a RESTful BrightBot! This tutorial will show you the basic implementation and structure of a RESTful BrightBot, give a couple working examples, and include a front-end demo application making use of the new endpoints.

Twitter Logo

RESTful BrightBot Basics

BrightWork RESTBots give you the ability to run your custom code by simply sending a request to a specified endpoint. To begin building a BrightBot, you'll need to create a new JavaScript file in the root directory of your Brightwork application (the same folder as your 'manifest.yml').

In the new file, you'll want to require the RestBot class and extend it using a new ES6 class. In the below example we extend the RestBot class and call the new class 'HelloBot'. This class creates an instance of a 'HelloBot' with a trigger that generates a new endpoint for your application and an action that executes when that trigger is hit.

const RestBot = require('bw-brightbot').RestBot;

class HelloBot extends RestBot {

    constructor() {
        super()
    }

    get trigger() {
      return 'get /sayHelloTo/:name';
    }

    action(context) {
        return `Hello ${context.name}!`;
    }
}

module.exports = HelloBot;  

The above code would create a new endpoint on your application which you could access with a 'GET' request to http://YOURAPPNAME.bwapps.io/sayHelloTo/Rob
and would return a string "Hello Rob". When you finish adding your logic or internal functions, you can then run bw push and all your bot code will be bundled with your manifest and sent to the BrightWork API for deployment.

Example Twitter BrightBot

For our example application, TweetFace, you can probably guess that we're going to be interacting with the Twitter API.

'use strict';

const RestBot = require('bw-brightbot').RestBot;

class TwitterBot extends RestBot {

    constructor() {
        super()
    }

To build a TwitterBot, you will have to create a Twitter Developer account and get your Consumer Key and Secret. These are required to authenticate with the API before you can request any data. In the TwitterBot you'll then have to add two additional functions to the Basic RESTBot Template. The first makes the call to Twitter to authenticate and get a token.

    authenticate() {

      let consumer_key = 'TWITTER_CONSUMER_KEY';
      let consumer_secret = 'TWITTER_CONSUMER_SECRET';
      let consumerStr = `${consumer_key}:${consumer_secret}`;
      let encodedStr = new Buffer(consumerStr).toString('base64');

      let options = {
        method: 'POST',
        uri: 'https://api.twitter.com/oauth2/token',
        body: 'grant_type=client_credentials',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            'Authorization': `Basic ${encodedStr}`,
            'Accept-Encoding': 'json'
        }
      };

      return request(options).then((response)=> {
          return JSON.parse(response).access_token;
      });

    }

The second, getTweets, attaches that token to a request to get the tweets from a specific user.

    getTweets(token, id) {

      let options = {
        method: 'GET',
        uri: `https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=${id}`,
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
          'Authorization': `Bearer ${token}`
        },
        json: true
      };

      return request(options).then((response)=> {
          return { tweets: response };
        });

    }

Lastly, every BrightBot needs a trigger and an action. In this case, the new endpoint takes the twitter handle in through the path at the parameter 'id'. The action calls 'authenticate' and then 'getTweets' getting the id from the context object.

    get trigger() {
        return 'get /tweets/:id';
    }

    action(context) {
        return this.authenticate().then((token)=>{
          return this.getTweets(token, context.id);
        });
    }
}

module.exports = TwitterBot;

Once both requests are completed the action returns the response object containing the tweets.

Example Alchemy BrightBot

Next we'll take a look at how to build a RESTBot to interact with IBM's Alchemy API. First, we'll need to get an API key by setting up an account on IBM Bluemix. Once we have the api key, the process is slightly easier and we just have to attach it to each request we make. We setup our AlchemyBot the same as before.

'use strict';

const RestBot = require('bw-brightbot').RestBot;

class AlchemyBot extends RestBot {

    constructor() {
        super()
    }

Then we setup a response object that will return two separate calls to Alchemy. We've also included a filter to remove all urls from the tweets.

    analyzeTweets(text) {

        var alchemyResponses = {
            sentimentAnalysis: {},
            entitiesAnalysis: {}
        };
        var apiKey = IBM_ALCHEMY_API_KEY;
        var noUrls = text.replace(/(?:https?|ftp):\/\/[\n\S]+/g, '')

One call will get the sentiment of the tweets

        var sentimentAnalysis = {
            method: 'POST',
            uri: 'https://gateway-a.watsonplatform.net/calls/text/TextGetTextSentiment',
            qs: {
                'apikey': apiKey,
                'outputMode': 'json',
                'text': noUrls,
                'showSourceText': 1
            }
        };

and the other will get the sentiment and emotion of frequently found entities in the tweets.

        var entitiesAnalysis = {
            method: 'POST',
            uri: 'https://gateway-a.watsonplatform.net/calls/text/TextGetRankedNamedEntities',
            qs: {
                'apikey': apiKey,
                'outputMode': 'json',
                'text': noUrls,
                'showSourceText': 1,
                'sentiment': 1,
                'emotion': 1
            }
        };

After setting up the options we can make both calls. (In every BrightBot you have access to common npm modules like 'request-promise' and 'lodash')

        return request(sentimentAnalysis).then((response)=> {

            alchemyResponses.sentimentAnalysis = JSON.parse(response);

            return request(entitiesAnalysis).then((response)=> {

                alchemyResponses.entitiesAnalysis = JSON.parse(response);

                return alchemyResponses;

            });

        });

    }

The alchemy endpoint will call 'analyzeTweets' and return the object containing both responses.

    get trigger() {
      return 'post /alchemy';
    }

    action(context) {
        return this.analyzeTweets(context.body.text);
    }
}

module.exports = AlchemyBot;

TweetFace Demo

Once we've pushed up our BrightBots we can write them into our client application. Using some Emoji Sentiment Research, the BrightWork Angular SDK, and a quick matching algorithm, we can build TweetFace. Which returns an emoji based on your mood.
Tweet Face Form Displays the results of the TweetFaces with the most followers,
Leader Board And generates an report telling you how you feel about certain entities.
Mood Report

BrightBots allow you create even more features for your application. Check out the live version of TweetFace and get out there and build something...faster!