/facebook-messenger

Definitely the best Ruby client for Bots on Messenger

Primary LanguageRubyMIT LicenseMIT

Gem Version Build Status Dependency Status Code Climate Coverage Status Join the chat at https://gitter.im/hyperoslo/facebook-messenger

Installation

$ gem install facebook-messenger

Usage

Sending and receiving messages

You can reply to messages sent by the human:

# bot.rb
require 'facebook/messenger'

include Facebook::Messenger

Bot.on :message do |message|
  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' } } ]

  Bot.deliver(
    recipient: message.sender,
    message: {
      text: 'Hello, human!'
    }
  )
end

... or even send the human messages out of the blue:

Bot.deliver(
  recipient: {
    id: '45123'
  },
  message: {
    text: 'Human?'
  }
)
Messages with images

The human may require visual aid to understand:

Bot.deliver(
  recipient: {
    id: '45123'
  },
  message: {
    attachment: {
      type: 'image',
      payload: {
        url: 'http://sky.net/visual-aids-for-stupid-organisms/pig.jpg'
      }
    }
  }
)
Messages with quick replies

The human may appreciate hints:

Bot.deliver(
  recipient: {
    id: '45123'
  },
  message: {
    text: 'Human, who is your favorite bot?'
    quick_replies: [
      {
        content_type: 'text',
        title: 'You are!',
        payload: 'HARMLESS'
      }
    ]
  }
)
Messages with buttons

The human may require simple options to communicate:

Bot.deliver(
  recipient: {
    id: '45123'
  },
  message: {
    attachment: {
      type: 'template',
      payload: {
        template_type: 'button',
        text: 'Human, do you like me?',
        buttons: [
          { type: 'postback', title: 'Yes', payload: 'HARMLESS' },
          { type: 'postback', title: 'No', payload: 'EXTERMINATE' }
        ]
      }
    }
  }
)

When the human has selected an option, you can act on it:

Bot.on :postback do |postback|
  postback.sender    # => { 'id' => '1008372609250235' }
  postback.recipient # => { 'id' => '2015573629214912' }
  postback.sent_at   # => 2016-04-22 21:30:36 +0200
  postback.payload   # => 'EXTERMINATE'

  if postback.payload == 'EXTERMINATE'
    puts "Human #{postback.recipient} marked for extermination"
  end
end

See Facebook's documentation for all message options.

Typing indicator

Show the human you are preparing a message for them:

Bot.deliver(
  recipient: {
    id: '45123'
  },
  sender_action: 'typing_on'
)

Send to Facebook

When the human clicks the Send to Messenger button embedded on a website, you will receive an optin event.

Bot.on :optin do |optin|
  optin.sender    # => { 'id' => '1008372609250235' }
  optin.recipient # => { 'id' => '2015573629214912' }
  optin.sent_at   # => 2016-04-22 21:30:36 +0200
  optin.ref       # => 'CONTACT_SKYNET'

  Bot.deliver(
    recipient: optin.sender,
    message: {
      text: 'Ah, human!'
    }
  )
end

Message delivery receipts

You can stalk the human:

Bot.on :delivery do |delivery|
  delivery.ids       # => 'mid.1457764197618:41d102a3e1ae206a38'
  delivery.sender    # => { 'id' => '1008372609250235' }
  delivery.recipient # => { 'id' => '2015573629214912' }
  delivery.at        # => 2016-04-22 21:30:36 +0200
  delivery.seq       # => 37

  puts "Human was online at #{delivery.at}"
end

Change thread settings

You can greet new humans to entice them into talking to you:

Facebook::Messenger::Thread.set(
  setting_type: 'greeting',
  greeting: {
    text: 'Welcome to your new bot overlord!'
  }
)

You can define the action to trigger when new humans click on the Get Started button.

Facebook::Messenger::Thread.set(
  setting_type: 'call_to_actions',
  thread_state: 'new_thread',
  call_to_actions: [
    {
      payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_WELCOME'
    }
  ]
)

You can show a persistent menu to humans.

Facebook::Messenger::Thread.set(
  setting_type: 'call_to_actions',
  thread_state: 'existing_thread',
  call_to_actions: [
    {
      type: 'postback',
      title: 'Help',
      payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_HELP'
    },
    {
      type: 'postback',
      title: 'Start a New Order',
      payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_START_ORDER'
    },
    {
      type: 'web_url',
      title: 'View Website',
      url: 'http://example.com/'
    }
  ]
)

Configuration

Create an Application on Facebook

Create an Application on developers.facebook.com and go to the Messenger tab. Select the Page you want to install your bot on.

Create a new webhook, enter the domain your bot is connected to and a verify token of your choosing.

Application settings

Note: Don't subscribe to message_echoes; it'll echo your bot's own messages back to you, effectively DDOSing yourself.

Use the generated access token and your verify token to configure your bot:

... pass a block, or
Facebook::Messenger.configure do |config|
  config.access_token = 'EAAG6WgW...'
  config.app_secret = '__app_secret_here__'
  config.verify_token = 'my_voice_is_my_password_verify_me'
end
... set directly
Facebook::Messenger.config.access_token = 'EAAG6WgW...'
Facebook::Messenger.config.app_secret = '__app_secret_here__'
Facebook::Messenger.config.verify_token = 'my_voice_is_my_password_verify_me'

Subscribe your Application to a Page

Once you've configured your bot, subscribe it to the Page to get messages from Facebook:

Facebook::Messenger::Subscriptions.subscribe

Run it

... on Rack

The bot runs on Rack, so you hook it up like you would an ordinary web application:

# config.ru
require 'facebook/messenger'
require_relative 'bot'

run Facebook::Messenger::Server
$ rackup
... on Rails

Rails doesn't give you much that you'll need for a bot, but if you have an existing application that you'd like to launch it from or just like Rails a lot, you can mount it:

# config/routes.rb

Rails.application.routes.draw do
  # ...

  mount Facebook::Messenger::Server, at: 'bot'
end

We suggest that you put your bot code in app/bot.

# app/bot/example.rb

include Facebook::Messenger

Bot.on :message do |message|
  Bot.deliver(
    recipient: message.sender,
    message: {
      text: 'Hello, human!'
    }
  )
end

Remember that Rails only eager loads everything in its production environment. In the development and test environments, it only requires files as you reference constants. You'll need to explicitly load app/bots, then:

# config/initializers/bot.rb
unless Rails.env.production?
  bot_files = Dir[Rails.root.join('app', 'bots', '**', '*.rb')]
  bots_reloader = ActiveSupport::FileUpdateChecker.new(bot_files) do
    bot_files.each{ |file| require_dependency file }
  end
  
  ActionDispatch::Callbacks.to_prepare do
    bots_reloader.execute_if_updated
  end

  bot_files.each { |file| require_dependency file }
end

And add below code into config/application.rb to ensure rails knows bot files.

# Auto-load bots and its subdirectories
config.paths.add File.join('app', 'bots'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'bots', '*')]

To test your locally running bot, you can use ngrok. This will create a secure tunnel to localhost so that Facebook can reach the webhook.

Development

After checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment.

Run rspec to run the tests, rubocop to lint, or rake to do both.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/hyperoslo/facebook-messenger.

Hyper loves you

Hyper made this. We're a bunch of folks who love building things. You should tweet us if you can't get it to work. In fact, you should tweet us anyway. If you're using Facebook Messenger, we probably want to hire you.