Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Integrate with Message Bus

Ben edited this page Apr 3, 2016 · 5 revisions

Creating a web-based chat app is somewhat confusing to figure out (even with wit.ai), which is why I've made a wiki page about it. Yay!

First, you should familiarize yourself both with wit.ai's concepts, and the concepts in wit_bot, including bots and conversations.

If you're on Rails or many other frameworks that work with message_bus, and you want to make your app able to respond to messages, read on! You'll learn a lot about how wit_bot works.

If you don't feel like learning, you can run the generators. The generators below are equivalent.

Generators

To generate the message_bus listener:

$ rails generate wit_bot:message_bus BotName
$ rails generate wit_bot:message_bus BotName User
$ rails generate wit_bot:message_bus BotName User /witbot

Guide

First, create your bot, I recommend placing it in the app/wit_bot directory. You'll probably want to initialize the bot with the user, to be able to access the user's data in your responses. Here's the documentation, read up on it and create a bot.

Dependencies

Now, you'll need the message_bus gem for this tutorial. Add it to your Gemfile, and bundle.

# For messages
gem 'message_bus', '~> 2.0.0.beta.5'

Side Note: With it's default configuration, message_bus requires redis. You should either read up on the docs for message_bus to use a different storage solution, or add the redis gem to your Gemfile.

Model

You'll want to create a model for storing conversations if you haven't already - here's the guide for that.

Message Bus Listener

Now, let's setup a way for the server to send input and output. For this, we'll be using WitBot's WitBot::Bot::Conversation::Participant class, which allows us to create a listener and a speaker that participates (thus the name) in the conversation.

class MessageBusListener < WitBot::Bot::Conversation::Participant
  attr_accessor :conversation_model, :user

  # Initialize the conversation, set the local user, and add the bot to the message
  def initialize(conversation, user)
    # Send the conversation object to the parent class
    super conversation.object

    # Set instance variables (@conversation is the actual conversation object)
    @conversation_model = conversation
    @user = user
    
    # Add the bot to the conversation
    YourBot.new @conversation, @user
  end

  # A method that saves the conversation.
  def save
    @conversation_model.object = @conversation
    @conversation_model.save
  end

  class << self
    # A method to retrieve a listener from a user.
    def from_user(user)
      unless user.conversation # If the user doesn't have a conversation...
        user.conversation = Conversation.new # Create one
        user.save! # Save the user
      end
      MessageBusListener.new user.conversation, user # Create a new listener from the conversation and the user.
    end
  end

  def bot?
    false # Tell wit_bot that this class handles messages for a user.
  end

  # A method that's call on output of a message automatically by wit_bot
  def on_output(message)
    save # Once we output a message, save the user.
    msg_hash = {text: message.text, bot: message.bot?} # Create a hash to send to the user
    MessageBus.publish '/yourbotchannel', msg_hash, user_ids: [@user.id] # Send the message to the user.
  end
end

Controller

Now, let's add a way for a user to send a message to the conversation. For this, we'll use a simple HTTP POST request, with the :text param used for sending the message's text. We'll be using a background job to process the message, so all this controller will do is enqueue the MessageBusJob. Make sure to setup a route that points to this controller.

class MessageBusController < ApplicationController
  before_action(only: [:send_message]){ doorkeeper_authorize! } # Make sure the user is authorized (replace with your own authentication logic)
  def send_message
    MessageBusJob.perform_later current_user.id, params[:text] # Enqueue 
    head :accepted # Respond the with the HTTP Accepted status code.
  end
end

Job

Now, we'll setup the job in your app/jobs folder. The job will retrieve the student from the database, get the MessageBusListener, and send the message as an input. WitBot will work it's magic, and send the user it's message once it's done.

class MessageBusJob < ActiveJob::Base
  queue_as :high

  def perform(user_id, text)
    # Make sure the user still exists
    if (user = User.find_by_id user_id)
      # Get the listener
      listener = MessageBusListener.from_user user
      # And send the message
      listener.send_message text
    end
  end
end

And... boom! Your bot can now accept and respond to messages! Awesome!

You're done. You've made it so that your app can accept a message, create a response, and send it back to the user. Awesome! You should give yourself a pat on the back.

What's next?

  • Setup your client: Send an ajax request to your MessageBusController endpoint with the text of the message in params[:text]. Your message hash will be transmitted back to the client using message_bus. You should go to message_bus, and setup your client based on their guides.
  • You should setup a background job library if you don't already have one, for that purpose, I recommend GitHub's resque.

Getting Started

Here's how to get started with wit_bot in 3 steps:

  1. Learn how to use wit.ai
  2. Learn how to setup the gem
  3. Learn how to send a message

Dive Deeper

Create Bots

Integrate it

Clone this wiki locally