Preparation

(1) Create a new App on your Facebook Developers.

(2) Add Product > Messenger

(3) Go to Messenger > Settings > Token Generation and link this App to the Facebook Page that you want to listen to Messages by generating a Token.


(4) You will be prompted with a permission request. Accept to authorize this App and copy the generated token as it will be needed later.

Setup Webhook

(1) Facebook needs to validate your server when setting up the callback webhook). This involves Facebook sending a token to your webhook URL and you respond with a specific challenge string.

(2) First, we will create a Rails app, with a single route. You can use your app id as the route URL. E.g.

Rails.application.routes.draw do
  match 'fb0000111122223333', :via => [:get, :post], :to => 'facebook_requests#create'
end

(3) The controller action will look like this:

class FacebookRequestsController < ApplicationController

  def create

    if params.has_key?('hub.mode') && params['hub.mode'] == 'subscribe'
      if params['hub.verify_token'] == 'your_token'
        response = params['hub.challenge']
      else
        response = 'Error'
      end
      render plain: response, status: :ok and return
    end
    render status: :bad_request
  end
end

(4) Deploy the App.

(5) Go to Messenger > Settings > Webhooks and add a new webhook. Enter the Webhook URL and the token for verification. For subscription fields, we will select "messages", "messaging_postbacks", "messaging_optins" and "message_deliveries".


(6) Click "Verify and Save" and Facebook will fire a verification message to your server. If your server responded correctly, you will see webhook setup is completed. You can set the webhook to the page your select earlier.


Read and Process Webhook Message

(1) You can now add logic to your controller code to handle commands. For this example, we do some simple math calculations based on the inputs.

class FacebookRequestsController < ApplicationController

  def create

    if params.has_key?('hub.mode') && params['hub.mode'] == 'subscribe'
      if params['hub.verify_token'] == 'your_token'
        response = params['hub.challenge']
      else
        response = 'Error'
      end
      render plain: response, status: :ok and return
    end
    
    if params.has_key?(:entry)
      params[:entry].each do |entry|
        entry[:messaging].each do |messaging|
          sender_id = messaging[:sender][:id]
          message_text = messaging[:message][:text]

          matches = /^([0-9.-]{1,})([+\-*\/]{1})([0-9.-]{1,})[=]{0,1}$/.match(message_text)

          if matches.nil?
            FacebookApi.send_message(sender_id, 'Sorry. I do not understand this command.')
          else
            a = BigDecimal(matches[1])
            b = BigDecimal(matches[3])
            case matches[2]
              when '+'
                result = a + b
              when '-'
                result = a - b
              when '*'
                result = a * b
              when '/'
                if b == BigDecimal('0')
                  result = 'Undefined'
                else
                  result = a / b
                end
              else
                result = 'Sorry. I do not understand this command.'
            end
            FacebookApi.send_message(sender_id, "#{result}")
          end
        end
      end
    end

    render status: :ok
  end
end

(2) We also need to use the messenger API to send the result back to the user.

class FacebookApi
  include HTTParty
  base_uri 'https://graph.facebook.com/v2.6/me/messages?access_token=the_access_token'
  debug_output (Rails.env.production? ? Rails.logger : $stdout)
  open_timeout 30
  read_timeout 30

  def self.send_message(recipient, message)
    post('/',
         :headers => {
             'Content-Type' => 'application/json'
         },
         :body => {
             :recipient => {
                 :id => recipient
             },
             :message => {
                 :text => message
             }
         }.to_json
    )
  end

end

(3) Deploy the App and test.

Test It!

That's all. Now you have a messenger bot that can do maths.