Ya tvoy Rubotnik*. Beginner-friendly Ruby boilerplate to build your own Messenger bot

Written by progapanda | Published 2017/04/18
Tech Story Tags: bots | chatbots | messenger-bots | ruby | learning-to-code

TLDRvia the TL;DR App

How to quickly get past ubiquitous «echo bots» tutorials and build an assistant that actually does something. Just clone, tweak and launch. Can it become a «bot-end» framework?

*a reference to Kraftwerk’s single “The Robot” (1978)

It started with a screw up

I have to admit: as a former journalist, I still write faster than I think. Turns out, it applies to code too. I royally screwed up in my “Build your first Messenget bot in Ruby” series. Even though more than 6000 people saw it and some readers used it to create their own projects, no one seemed to have noticed the gaping design flaw. I misused facebook-messenger gem in a way that when several users try talking to the tutorial bot at the same time, their messages get mixed up. When one user is in the middle of the interaction, bot is hung up on the task in progress and any other message from any other user would be treated as the next step in the conversation thread. That sucked and I desperately wanted to make up for it. I had to rethink the architecture to handle requests from different users and remember their place in conversation. A simple refactoring led to more refactoring, and more refactoring, and more… As a result, I created a simple tool that solves a number of design problems with bots, so you don’t have to solve them yourself**.**

Meet Rubotnik — your starting point to mess with Ruby chatbots for Facebook Messenger, the largest messaging platform out there. At this early stage it’s more a proof of concept and I haven’t packaged it as a separate gem yet, so when you download the boilerplate, you can see how its internals are implemented inside the /rubotnik folder. It also contains some example code that you’re free to tweak and replace.

What it does

  • You can bind keywords (“help”, for instance, as in “help!” or “Would you help me, please” to your bot’s functions (we will call them “commands” from now on) with a straightforward syntax: bind ‘help’, to: :give_help . Forget about case with a dozen of when’s to parse your input.
  • You write all your bot’s logic as separate methods inside boilerplate’s Commands module and you can chain them together to create threads of dialogue with next_command :method_name
  • You can generate UI elements with the help of convenience classes: UI::ImageAttachment.new(‘http://your.image/url’).send(@user) (it also makes those Facebook’s Generic Templates a bit easier to generate)
  • You can set up a nested persistent menu and a greeting screen for your bot. Alter rubotnik/persistent_menu.rb and rubotnik/bot_profile.rb to create your own.
  • Its README will walk you through all the steps necessary to hook up your bot on Facebook and bring it to life.
  • It’s a standalone service that runs on Rack (it uses Puma server with default config). Think of it as “bot-end” framework for your web app, if you have one. It has Sinatra enabled by default so you can create your own webhooks and handle incoming API connections.
  • It’s primed for easy deployment with Heroku. Just do heroku create and heroku push origin master once you’re done testing on localhost.

What it doesn’t do

  • It has no persistence, but can be extended to work with any database. By default, Rubotnik has simple in-memory storage that keeps track of connected users and their state (see rubotnik/user.rb and rubotnik/user_store.rb to see how it’s implemented).
  • It doesn’t work inside of a Rails project (this is one of the features that can be thought about in future). On the other hand, it can talk to your existing Rails app through REST API.

How it works

So how do you build your bot with Rubotnik? First, make sure you have your Heroku CLI and ngrok installed — we will need this for development, as well as for moving your bot to the cloud. Then follow this steps:

git clone git@github.com:progapandist/rubotnik-boilerplate.git

mv rubotnik-boilerplate NAME_OF_YOUR_PROJECT

cd NAME_OF_YOUR_PROJECT

rm -rf .git # remove boilerplate’s git history

git init # track your own project

Open the project in your favorite editor and take a look at the bot.rb file. There’s a bunch of stuff already written, that constitutes logic for a demo bot that you can play with here.

The bot that demoes boilerplate features

It implements an example of a simple API call to Google Geocoding to determine details about your location, a sample questionnaire to demonstrate gathering data from user message by message, and it also renders some of Facebook’s UI elements to get a taste what your own bot can offer in terms of user experience.

If you don’t change anything at this point and just follow instructions for bot setup in the boilerplate’s readme, you’ll get the exact copy of the demo bot. It lets you understand what does what inside the boilerplate, but you probably want to build your own thing, right? Then just take a quick glance at the sample code and replace it with your own.

Note that all the heavy lifting (sending data to Facebook Messenger Platform and handling incoming requests to your bot’s webhook) is done by the facebook-messenger gem (that guy from Norway did a terrific job, and a community around his project is growing steadily). Rubotnik merely piggybacks on its API, like so:

Same logic applies to postbacks, which are events triggered when the user interacts with buttons in your bot’s UI.

Let’s take a closer look, two things are happening in this snippet:

  1. bind ‘string' is an example of Rubotnik’s DSL.
  2. say is a helper function that allows you to send a text message to connected user with a simplicity of say "Hello!"

Take a look at /commands/questionnaire.rb to see how commands can be chained together to form threads.

Check the README and read through comments in boilerplate’s code to learn more about DSL, helper functions and where to apply them.

How it’s done

Rubotnik’s main classes are called MessageDispatch and PostbackDispatch, they can be found inside of /rubotnik folder. Here’s a snippet that shows how message dispatching is implemented:

A @message instance variable is accessible everywhere through common Rubotnik namespace and represents any given incoming message. It’s an instance of facebook-messenger’s Facebook::Messenger::Incoming::Message class and has all its properties (refer to facebook-messenger’s README)

@message.id # => 'mid.1457764197618:41d102a3e1ae206a38'@message.sender # => { 'id' => '1008372609250235' }@message.seq # => 73@message.sent_at # => 2016-04-22 21:30:36 +0200@message.text # => 'Hello, bot!'@message.attachments # => [ { 'type' => 'image', 'payload' => { 'url' => 'https://www.example.com/1.jpg' } } ]

Same goes for @postback that’s an instance of Facebook::Messenger::Incoming::Postback

@user references the connected user and is an instance of User class defined in user.rb. The main point of this class is to hold onto user’s facebook ID and keep track of commands bound for execution. You can add your custom containers for state (as in the case with answers property, used to track user’s answers in questionnaire.rb).

That’s pretty much all the not-so-secret sauce that ensures all users are served independent of each other and the conversation with them continues exactly at the point it stopped, even after a long interruption.

How to go live

Once you’re done building and testing your bot, just create a heroku app from your console and run git push heroku master. Then update your webhook in Facebook developer console and that’s it!

How to say if you ❤️ it or 👺 it

For now Rubotnik is just a bunch of code organised in some folders. It’s raw. It’s a proof of concept. It needs polishing. Some of the code has to do with actual “framework” logic, while other bits just demo example bot’s features. It has require_relative statements sprinkled everywhere. There’s a bunch of debug statements that are designed to help with understanding how bot performs. But they can’t be allowed to stay there for long.

Some of my practices may be frowned upon by seasoned programmers. That’s understandable, I only discovered Ruby magic last year.

That’s exactly why I invite everyone to collaborate. Feel free to fork the boilerplate and make PR’s or just email me and I’ll add you as a collaborator for the main repo.

I’m also looking for ways to test Rubotnik with some real world examples, so if you are planning to integrate your service with Messenger, contact me and I’ll help you out.

What next?

Obviously, Rubotnik should be turned into a gem. But as it’s tightly coupled with facebook-messenger, I don’t know where to start yet. It should also probably have rails new-style generators to create directory structure for new projects.

I’m also looking into wit.ai and api.ai tools to enable easy interactions with NLU engines that would make your bot a better conversationalist.

Recommend 💚 this article on Medium and stay tuned!

🤖 BOT POWER! 🤖


Published by HackerNoon on 2017/04/18