messenger-bot-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +71 -0
  6. data/LICENSE +21 -0
  7. data/README.md +152 -0
  8. data/Rakefile +2 -0
  9. data/bin/console +6 -0
  10. data/bin/setup +5 -0
  11. data/config.ru +3 -0
  12. data/examples/bot.rb +53 -0
  13. data/lib/messenger/bot.rb +10 -0
  14. data/lib/messenger/bot/api.rb +87 -0
  15. data/lib/messenger/bot/client.rb +66 -0
  16. data/lib/messenger/bot/exceptions.rb +2 -0
  17. data/lib/messenger/bot/exceptions/base.rb +7 -0
  18. data/lib/messenger/bot/exceptions/response_error.rb +32 -0
  19. data/lib/messenger/bot/null_logger.rb +11 -0
  20. data/lib/messenger/bot/types.rb +20 -0
  21. data/lib/messenger/bot/types/address.rb +14 -0
  22. data/lib/messenger/bot/types/adjustment.rb +10 -0
  23. data/lib/messenger/bot/types/attachment.rb +10 -0
  24. data/lib/messenger/bot/types/base.rb +9 -0
  25. data/lib/messenger/bot/types/button.rb +12 -0
  26. data/lib/messenger/bot/types/button_template.rb +12 -0
  27. data/lib/messenger/bot/types/callback.rb +10 -0
  28. data/lib/messenger/bot/types/delivery.rb +11 -0
  29. data/lib/messenger/bot/types/element.rb +11 -0
  30. data/lib/messenger/bot/types/entry.rb +11 -0
  31. data/lib/messenger/bot/types/generic_template.rb +28 -0
  32. data/lib/messenger/bot/types/image.rb +12 -0
  33. data/lib/messenger/bot/types/image_attachment.rb +10 -0
  34. data/lib/messenger/bot/types/message.rb +14 -0
  35. data/lib/messenger/bot/types/messaging.rb +14 -0
  36. data/lib/messenger/bot/types/payload.rb +9 -0
  37. data/lib/messenger/bot/types/postback.rb +9 -0
  38. data/lib/messenger/bot/types/receipt_element.rb +14 -0
  39. data/lib/messenger/bot/types/receipt_template.rb +19 -0
  40. data/lib/messenger/bot/types/recipient.rb +12 -0
  41. data/lib/messenger/bot/types/sender.rb +12 -0
  42. data/lib/messenger/bot/types/summary.rb +12 -0
  43. data/lib/messenger/bot/types/template_attachment.rb +10 -0
  44. data/lib/messenger/bot/version.rb +5 -0
  45. data/messenger-bot-ruby.gemspec +29 -0
  46. metadata +202 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e58554d6934e450aa15901619fbda6209f4daa4
4
+ data.tar.gz: debc4eaa53d54eae3afaaaa30a601b9a03bebf56
5
+ SHA512:
6
+ metadata.gz: 134cac2692eb0ec98fe15e189a9b1704b2910e39ee94d7827a98ce2d3b2fd203c4bb047dae3a4f3b3119190e68cb2a0514a20519037782bccb14cb08a66a63fe
7
+ data.tar.gz: a939e9cb006ce518aec1d7721559bae14984ec2d8b26f0c7d307aab3c88c8a4f17f0c5886aa4e1fa84a821e6c64398dac58b581774d57cf32d8dd4abe5bbfeee
@@ -0,0 +1,36 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ # .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial commit and implementation, really quick and dirty.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,71 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ messenger-bot-ruby (0.1.0)
5
+ httmultiparty (~> 0.3.16)
6
+ persistent_httparty (~> 0.1.2)
7
+ virtus (~> 1.0.5)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ axiom-types (0.1.1)
13
+ descendants_tracker (~> 0.0.4)
14
+ ice_nine (~> 0.11.0)
15
+ thread_safe (~> 0.3, >= 0.3.1)
16
+ coderay (1.1.1)
17
+ coercible (1.0.0)
18
+ descendants_tracker (~> 0.0.1)
19
+ cuba (3.6.0)
20
+ rack (~> 1.6.0)
21
+ descendants_tracker (0.0.4)
22
+ thread_safe (~> 0.3, >= 0.3.1)
23
+ equalizer (0.0.11)
24
+ gene_pool (1.4.1)
25
+ thread_safe
26
+ httmultiparty (0.3.16)
27
+ httparty (>= 0.7.3)
28
+ mimemagic
29
+ multipart-post
30
+ httparty (0.13.7)
31
+ json (~> 1.8)
32
+ multi_xml (>= 0.5.2)
33
+ ice_nine (0.11.2)
34
+ json (1.8.3)
35
+ method_source (0.8.2)
36
+ mimemagic (0.3.1)
37
+ multi_json (1.11.2)
38
+ multi_xml (0.5.5)
39
+ multipart-post (2.0.0)
40
+ persistent_http (1.0.6)
41
+ gene_pool (>= 1.3)
42
+ persistent_httparty (0.1.2)
43
+ httparty (~> 0.9)
44
+ persistent_http (< 2)
45
+ pry (0.10.3)
46
+ coderay (~> 1.1.0)
47
+ method_source (~> 0.8.1)
48
+ slop (~> 3.4)
49
+ rack (1.6.4)
50
+ rake (10.5.0)
51
+ slop (3.6.0)
52
+ thread_safe (0.3.5)
53
+ virtus (1.0.5)
54
+ axiom-types (~> 0.1)
55
+ coercible (~> 1.0)
56
+ descendants_tracker (~> 0.0, >= 0.0.3)
57
+ equalizer (~> 0.0, >= 0.0.9)
58
+
59
+ PLATFORMS
60
+ ruby
61
+
62
+ DEPENDENCIES
63
+ bundler (~> 1.9)
64
+ cuba (~> 3.6.0)
65
+ messenger-bot-ruby!
66
+ multi_json
67
+ pry (~> 0.10.3)
68
+ rake (~> 10.0)
69
+
70
+ BUNDLED WITH
71
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Matteo Gavagnin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,152 @@
1
+ # messenger-bot-ruby
2
+
3
+ Ruby wrapper for [Messenger's Platform Bot API](https://developers.facebook.com/docs/messenger-platform).
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/messenger-bot-ruby.svg)](http://badge.fury.io/rb/messenger-bot-ruby)
6
+
7
+ This library is heavily based on the great [telegram-bot-ruby](https://github.com/atipugin/telegram-bot-ruby) gem written by [Alexander Tipugin](mailto:atipugin@gmail.com) and its main goal is let you easily integrate your (existing?) Telegram Bot with Messenger.
8
+
9
+ ## Prerequisites
10
+
11
+ Messenger platform uses the webhook pattern to send you updates on events, requiring a TLS encrypted connection.
12
+
13
+ ### Development: ngrok
14
+
15
+ To be able to use the bot on your development machine I heavily suggest you to purchase a [ngrok Pro subscription](https://ngrok.com/product#pricing) (billed monthly or yearly). I struggled with [localtunnel](https://localtunnel.me) that's free, but at the moment has a bug (it crashes losing the tunnel and the domain) and you have to reconfigure the webhook on Facebook every few minutes.
16
+
17
+ Remember to [authorize your machine](https://dashboard.ngrok.com/auth) after you purchase the subscription.
18
+
19
+ Whenever you need to develop, start a tunnel following the ngrok instructions, but something like this should suffice:
20
+
21
+ ```shell
22
+ ngrok http 9292
23
+ ```
24
+
25
+ where `http` is the protocol (if authenticated will establish also the encrypted `https` tunnel), `9292` is the default Cuba port.
26
+
27
+ ```shell
28
+ Forwarding http://bf6ab2c6.ngrok.io -> localhost:9292
29
+ Forwarding https://bf6ab2c6.ngrok.io -> localhost:9292
30
+ ```
31
+
32
+ The interesting information is the `https://bf6bb3c6.ngrok.io` forwarded address, you need to use it on Facebook to configure the webhook appending the `/messenger` path.
33
+
34
+ So your webhook should point to something like
35
+
36
+ https://bf6ab2c6.ngrok.io/messenger
37
+
38
+ Please follow the [official guide](https://developers.facebook.com/docs/messenger-platform) and once completed you can proceed.
39
+
40
+ ### Production: Let's Encrypt
41
+
42
+ On the production machine I cannot praise enough [Let's Encrypt](http://letsencrypt.org): free and secure TLS certificates for everyone (I'm using it on many production projects and it rocks!).
43
+
44
+ ## Quick start
45
+
46
+ Clone this repository and start a terminal session inside the folder and execute the following commands to fetch the necessary dependancies and start the server.
47
+
48
+ ```shell
49
+ bundle
50
+ bundle exec rackup
51
+ ```
52
+
53
+ The `rackup` command will start a Cuba server using the sample file in `examples/bot.rb`.
54
+ There you should replace the `YOUR_MESSENGER_PAGE_TOKEN_HERE` string with the page token provided by Facebook (follow the [official guide](https://developers.facebook.com/docs/messenger-platform) to know more).
55
+
56
+ ## Installation
57
+
58
+ Add following line to your Gemfile:
59
+
60
+ ```ruby
61
+ gem 'messenger-bot-ruby'
62
+ ```
63
+
64
+ And then execute:
65
+
66
+ ```shell
67
+ $ bundle
68
+ ```
69
+
70
+ Or install it system-wide:
71
+
72
+ ```shell
73
+ $ gem install messenger-bot-ruby
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ Take a look at the `examples/bot.rb` file reported below.
79
+ I'm planning to add detailed informations in the next few days.
80
+
81
+ ```ruby
82
+ require 'bundler/setup'
83
+ require 'cuba'
84
+ require 'multi_json'
85
+ require 'messenger/bot'
86
+
87
+ token = "YOUR_MESSENGER_PAGE_TOKEN_HERE"
88
+ bot = Messenger::Bot::Client.new(token)
89
+
90
+ # deserialize JSON data from request body
91
+ def json_load(request_body)
92
+ request_body.rewind
93
+ body = request_body.read
94
+ MultiJson.load body
95
+ end
96
+
97
+ Cuba.define do
98
+ on get do
99
+ on "messenger" do
100
+ on param("hub.mode"), param("hub.challenge"), param("hub.verify_token") do |mode, challenge, token|
101
+ if mode == "subscribe"
102
+ # TODO: check the verify_token value that you inserted on the facebook developer page
103
+ res.write challenge
104
+ end
105
+ end
106
+ end
107
+ on root do
108
+ res.write "Hello world!"
109
+ end
110
+ end
111
+
112
+ on post do
113
+ puts "Got a post call #{res.to_json}"
114
+ on "messenger" do
115
+ data = json_load req.body
116
+ # puts "#{data}"
117
+ res.write "" #200
118
+ callback = Messenger::Bot::Types::Callback.new(data)
119
+ for e in callback.entry
120
+ for mess in e.messaging
121
+ if mess.message
122
+ if mess.sender.id # We have someone to send the message to!
123
+ options = {bot: bot, messaging: mess, token: token}
124
+ bot.api.messages(recipient: {id: mess.sender.id}, message: { text: "Hello from a Bot!"})
125
+ end
126
+ else
127
+ puts "Received Postback or delivery"
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ ```
136
+
137
+ ## Aknowledgments
138
+
139
+ Idea and initial implementation by [Matteo Gavagnin](https://twitter.com/macteo)
140
+ Thanks again to [Alexander Tipugin](mailto:atipugin@gmail.com) for inspiration and the [original gem](https://github.com/atipugin/telegram-bot-ruby) architecture.
141
+
142
+ ## Contributing
143
+
144
+ 1. Fork it
145
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
146
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
147
+ 4. Push to the branch (`git push origin my-new-feature`)
148
+ 5. Create new Pull Request
149
+
150
+ ## License
151
+
152
+ Released under MIT license.
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'bundler/setup'
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'messenger/bot'
4
+
5
+ require 'pry'
6
+ Pry.start
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
@@ -0,0 +1,3 @@
1
+ require './examples/bot.rb'
2
+
3
+ run Cuba
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'cuba'
4
+ require 'multi_json'
5
+ require 'messenger/bot'
6
+
7
+ token = "YOUR_MESSENGER_PAGE_TOKEN_HERE"
8
+ bot = Messenger::Bot::Client.new(token)
9
+
10
+ # deserialize JSON data from request body
11
+ def json_load(request_body)
12
+ request_body.rewind
13
+ body = request_body.read
14
+ MultiJson.load body
15
+ end
16
+
17
+ Cuba.define do
18
+ on get do
19
+ on "messenger" do
20
+ on param("hub.mode"), param("hub.challenge"), param("hub.verify_token") do |mode, challenge, token|
21
+ if mode == "subscribe"
22
+ # TODO: check the verify_token value that you inserted on the facebook developer page
23
+ res.write challenge
24
+ end
25
+ end
26
+ end
27
+ on root do
28
+ res.write "Hello world!"
29
+ end
30
+ end
31
+
32
+ on post do
33
+ puts "Got a post call #{res.to_json}"
34
+ on "messenger" do
35
+ data = json_load req.body
36
+ # puts "#{data}"
37
+ res.write "" #200
38
+ callback = Messenger::Bot::Types::Callback.new(data)
39
+ for e in callback.entry
40
+ for mess in e.messaging
41
+ if mess.message
42
+ if mess.sender.id # We have someone to send the message to!
43
+ options = {bot: bot, messaging: mess, token: token}
44
+ bot.api.messages(recipient: {id: mess.sender.id}, message: { text: "Hello from a Bot!"})
45
+ end
46
+ else
47
+ puts "Received Postback or delivery"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,10 @@
1
+ require 'httmultiparty'
2
+ require 'persistent_httparty'
3
+ require 'virtus'
4
+
5
+ require 'messenger/bot/types'
6
+ require 'messenger/bot/exceptions'
7
+ require 'messenger/bot/api'
8
+ require 'messenger/bot/null_logger'
9
+ require 'messenger/bot/client'
10
+ require 'messenger/bot/version'
@@ -0,0 +1,87 @@
1
+ module Messenger
2
+ module Bot
3
+ class Api
4
+ include HTTMultiParty
5
+ ENDPOINTS = %w(
6
+ messages
7
+ ).freeze
8
+ POOL_SIZE = ENV.fetch('MESSENGER_BOT_POOL_SIZE', 1).to_i.freeze
9
+
10
+ attr_reader :token
11
+
12
+ base_uri 'https://graph.facebook.com/v2.6/'
13
+ persistent_connection_adapter pool_size: POOL_SIZE,
14
+ keep_alive: 30,
15
+ force_retry: true
16
+
17
+ def initialize(token)
18
+ @token = token
19
+ end
20
+
21
+ def method_missing(method_name, *args, &block)
22
+ endpoint = method_name.to_s
23
+ endpoint = camelize(endpoint) if endpoint.include?('_')
24
+
25
+ ENDPOINTS.include?(endpoint) ? call(endpoint, *args) : super
26
+ end
27
+
28
+ def respond_to_missing?(*args)
29
+ method_name = args[0].to_s
30
+ method_name = camelize(method_name) if method_name.include?('_')
31
+
32
+ ENDPOINTS.include?(method_name) || super
33
+ end
34
+
35
+ def user_profile(user_id)
36
+ response = self.class.get("#{user_id}?fields=first_name,last_name,profile_pic&access_token=#{token}")
37
+ if response.code == 200
38
+ response.to_hash
39
+ else
40
+ fail Exceptions::ResponseError.new(response),
41
+ 'Messenger API has returned the error.'
42
+ end
43
+ end
44
+
45
+ def call(endpoint, raw_params = {})
46
+ params = build_params(raw_params)
47
+ response = self.class.post("/me/#{endpoint}?access_token=#{token}", query: params)
48
+ if response.code == 200
49
+ response.to_hash
50
+ else
51
+ fail Exceptions::ResponseError.new(response),
52
+ 'Messenger API has returned the error.'
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def build_params(h)
59
+ h.each_with_object({}) do |(key, value), params|
60
+ params[key] = sanitize_value(value)
61
+ end
62
+ end
63
+
64
+ def sanitize_value(value)
65
+ jsonify(jsonify_with_file_preservation(value))
66
+ end
67
+
68
+ def jsonify_with_file_preservation(value)
69
+ if !value.is_a?(File)
70
+ return value.to_h.to_json
71
+ end
72
+ return value
73
+ end
74
+
75
+ def jsonify(value)
76
+ return value unless value.is_a?(Array)
77
+ value.map { |i| i.to_h.select { |_, v| v } }.to_json
78
+ end
79
+
80
+ def camelize(method_name)
81
+ words = method_name.split('_')
82
+ words.drop(1).map(&:capitalize!)
83
+ words.join
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,66 @@
1
+ module Messenger
2
+ module Bot
3
+ class Client
4
+ TIMEOUT_EXCEPTIONS = [Timeout::Error]
5
+ TIMEOUT_EXCEPTIONS << Net::ReadTimeout if Net.const_defined?(:ReadTimeout)
6
+
7
+ attr_reader :api, :offset, :timeout
8
+ attr_accessor :logger
9
+
10
+ def self.run(*args, &block)
11
+ new(*args).run(&block)
12
+ end
13
+
14
+ def initialize(token, h = {})
15
+ options = default_options.merge(h)
16
+ @api = Api.new(token)
17
+ @offset = options[:offset]
18
+ @timeout = options[:timeout]
19
+ @logger = options[:logger]
20
+ end
21
+
22
+ def run
23
+ yield self
24
+ end
25
+
26
+ def listen(&block)
27
+ logger.info('Starting bot')
28
+ running = true
29
+ Signal.trap('INT') { running = false }
30
+ fetch_updates(&block) while running
31
+ exit
32
+ end
33
+
34
+ def fetch_updates
35
+ response = api.getUpdates(offset: offset, timeout: timeout)
36
+ return unless response['ok']
37
+
38
+ response['result'].each do |data|
39
+ update = Types::Update.new(data)
40
+ @offset = update.update_id.next
41
+ message = extract_message(update)
42
+ log_incoming_message(message)
43
+ yield message
44
+ end
45
+ rescue *TIMEOUT_EXCEPTIONS
46
+ retry
47
+ end
48
+
49
+ private
50
+
51
+ def default_options
52
+ { offset: 0, timeout: 20, logger: NullLogger.new }
53
+ end
54
+
55
+ def extract_message(update)
56
+ update.inline_query || update.chosen_inline_result || update.message
57
+ end
58
+
59
+ def log_incoming_message(message)
60
+ logger.info(
61
+ format('Incoming message: text="%s" uid=%i', message, message.from.id)
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,2 @@
1
+ require 'messenger/bot/exceptions/base'
2
+ require 'messenger/bot/exceptions/response_error'
@@ -0,0 +1,7 @@
1
+ module Messenger
2
+ module Bot
3
+ module Exceptions
4
+ class Base < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ module Messenger
2
+ module Bot
3
+ module Exceptions
4
+ class ResponseError < Base
5
+ attr_reader :response
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ end
10
+
11
+ def to_s
12
+ super +
13
+ format(' (%s)', data.map { |k, v| %(#{k}: "#{v}") }.join(', '))
14
+ end
15
+
16
+ def error_code
17
+ data[:error_code] || data['error_code']
18
+ end
19
+
20
+ private
21
+
22
+ def data
23
+ @data ||= begin
24
+ JSON.parse(response.body)
25
+ rescue JSON::ParserError
26
+ { error_code: response.code, uri: response.request.last_uri.to_s }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ module Messenger
2
+ module Bot
3
+ class NullLogger < Logger
4
+ def initialize(*)
5
+ end
6
+
7
+ def add(*)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ require 'messenger/bot/types/base'
2
+ require 'messenger/bot/types/payload'
3
+ require 'messenger/bot/types/element'
4
+ require 'messenger/bot/types/button'
5
+ require 'messenger/bot/types/attachment'
6
+ require 'messenger/bot/types/sender'
7
+ require 'messenger/bot/types/recipient'
8
+ require 'messenger/bot/types/delivery'
9
+ require 'messenger/bot/types/postback'
10
+ require 'messenger/bot/types/message'
11
+ require 'messenger/bot/types/messaging'
12
+ require 'messenger/bot/types/entry'
13
+ require 'messenger/bot/types/callback'
14
+ require 'messenger/bot/types/button_template'
15
+ require 'messenger/bot/types/generic_template'
16
+ require 'messenger/bot/types/receipt_element'
17
+ require 'messenger/bot/types/address'
18
+ require 'messenger/bot/types/summary'
19
+ require 'messenger/bot/types/adjustment'
20
+ require 'messenger/bot/types/receipt_template'
@@ -0,0 +1,14 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Address < Base
5
+ attribute :street_1, String
6
+ attribute :street_2, String
7
+ attribute :city, String
8
+ attribute :postal_code, String
9
+ attribute :state, String
10
+ attribute :country, String
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Adjustment < Base
5
+ attribute :name, String
6
+ attribute :amount, Float
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Attachment < Base
5
+ attribute :type, String
6
+ attribute :payload, Payload
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Base
5
+ include Virtus.model
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Button < Base
5
+ attribute :type, String # web_url or postback
6
+ attribute :title, String
7
+ attribute :url, String # Required for web_url buttons
8
+ attribute :payload, String # Required for postback buttons
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class ButtonTemplate < Base
5
+ attribute :template_type, String # value must be button
6
+ attribute :text, String
7
+ attribute :buttons, Array[Button]
8
+ alias_method :to_s, :text
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Callback < Base
5
+ attribute :object, String
6
+ attribute :entry, Array[Entry]
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Delivery < Base
5
+ attribute :mids, Array[String]
6
+ attribute :watermark, Integer
7
+ attribute :seq, Integer
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Element < Base
5
+ attribute :mids, Array[String]
6
+ attribute :watermark, Integer
7
+ attribute :seq, Integer
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Entry < Base
5
+ attribute :id, Integer
6
+ attribute :time, Integer
7
+ attribute :messaging, Array[Messaging]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class GenericTemplate < Base
5
+ attribute :template_type, String # generic
6
+ attribute :elements, Array[Element]
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ =begin
13
+
14
+ # Generic Template Guidelines
15
+
16
+ ## Limits
17
+
18
+ - Title: 45 characters
19
+ - Subtitle: 80 characters
20
+ - Call-to-action title: 20 characters
21
+ - Call-to-action items: 3 buttons
22
+ - Bubbles per message (horizontal scroll): 10 elements
23
+
24
+ ## Image Dimensions
25
+
26
+ Image ratio is 1.91:1
27
+
28
+ =end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Image < Base
5
+ attribute :url, String
6
+ alias_method :to_s, :url
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ # Only jpeg and png
@@ -0,0 +1,10 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class ImageAttachment < Base
5
+ attribute :type, String, :default => "image"
6
+ attribute :payload, Image
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Message < Base
5
+ attribute :text, String
6
+ attribute :mid, String
7
+ attribute :seq, Integer
8
+ attribute :attachments, Array[Attachment]
9
+
10
+ alias_method :to_s, :text
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Messaging < Base
5
+ attribute :sender, Sender
6
+ attribute :recipient, Recipient
7
+ attribute :timestamp, Integer
8
+ attribute :message, Message
9
+ attribute :delivery, Delivery
10
+ attribute :postback, Postback
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Payload < Base
5
+ attribute :url, String
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Postback < Base
5
+ attribute :payload, String
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class ReceiptElement < Base
5
+ attribute :title, String
6
+ attribute :subtitle, String
7
+ attribute :quantity, Float
8
+ attribute :price, String
9
+ attribute :currency, String
10
+ attribute :image_url, String
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class ReceiptTemplate < Base
5
+ attribute :template_type, String # receipt
6
+ attribute :recipient_name, String
7
+ attribute :order_number, String
8
+ attribute :currency, String
9
+ attribute :payment_method, String
10
+ attribute :timestamp, String
11
+ attribute :order_url, String
12
+ attribute :elements, Array[ReceiptElement]
13
+ attribute :address, Address
14
+ attribute :summary, Summary
15
+ attribute :adjustments, Array[Adjustment]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Recipient < Base
5
+ attribute :id, Integer
6
+ attribute :phone_number, String
7
+
8
+ # alias_method :to_s, :text
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Sender < Base
5
+ attribute :id, Integer
6
+ attribute :phone_number, String
7
+
8
+ # alias_method :to_s, :text
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class Summary < Base
5
+ attribute :subtotal, Float
6
+ attribute :shipping_cost, Float
7
+ attribute :total_tax, Float
8
+ attribute :total_cost, Float
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Messenger
2
+ module Bot
3
+ module Types
4
+ class TemplateAttachment < Base
5
+ attribute :type, String, :default => "template"
6
+ attribute :payload, Hash
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Messenger
2
+ module Bot
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'messenger/bot/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'messenger-bot-ruby'
8
+ spec.version = Messenger::Bot::VERSION
9
+ spec.authors = ['Matteo Gavagnin', 'Alexander Tipugin']
10
+ spec.email = ['m@macteo.it', 'atipugin@gmail.com']
11
+ spec.licenses = ['MIT']
12
+ spec.summary = "Ruby wrapper for Messenger's Bot API"
13
+ spec.homepage = 'https://github.com/macteo/messenger-bot-ruby'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = 'exe'
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'httmultiparty', '~> 0.3'
21
+ spec.add_dependency 'persistent_httparty', '~> 0.1'
22
+ spec.add_dependency 'virtus', '~> 1.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.9'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'pry', '~> 0.10'
27
+ spec.add_development_dependency 'cuba', '~> 3.6'
28
+ spec.add_development_dependency 'multi_json', '~> 1.11'
29
+ end
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: messenger-bot-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matteo Gavagnin
8
+ - Alexander Tipugin
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2016-04-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httmultiparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.3'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: persistent_httparty
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '0.1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '0.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: virtus
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.9'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.9'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '10.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '10.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '0.10'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.10'
98
+ - !ruby/object:Gem::Dependency
99
+ name: cuba
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '3.6'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '3.6'
112
+ - !ruby/object:Gem::Dependency
113
+ name: multi_json
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '1.11'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '1.11'
126
+ description:
127
+ email:
128
+ - m@macteo.it
129
+ - atipugin@gmail.com
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".gitignore"
135
+ - CHANGELOG.md
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - bin/console
142
+ - bin/setup
143
+ - config.ru
144
+ - examples/bot.rb
145
+ - lib/messenger/bot.rb
146
+ - lib/messenger/bot/api.rb
147
+ - lib/messenger/bot/client.rb
148
+ - lib/messenger/bot/exceptions.rb
149
+ - lib/messenger/bot/exceptions/base.rb
150
+ - lib/messenger/bot/exceptions/response_error.rb
151
+ - lib/messenger/bot/null_logger.rb
152
+ - lib/messenger/bot/types.rb
153
+ - lib/messenger/bot/types/address.rb
154
+ - lib/messenger/bot/types/adjustment.rb
155
+ - lib/messenger/bot/types/attachment.rb
156
+ - lib/messenger/bot/types/base.rb
157
+ - lib/messenger/bot/types/button.rb
158
+ - lib/messenger/bot/types/button_template.rb
159
+ - lib/messenger/bot/types/callback.rb
160
+ - lib/messenger/bot/types/delivery.rb
161
+ - lib/messenger/bot/types/element.rb
162
+ - lib/messenger/bot/types/entry.rb
163
+ - lib/messenger/bot/types/generic_template.rb
164
+ - lib/messenger/bot/types/image.rb
165
+ - lib/messenger/bot/types/image_attachment.rb
166
+ - lib/messenger/bot/types/message.rb
167
+ - lib/messenger/bot/types/messaging.rb
168
+ - lib/messenger/bot/types/payload.rb
169
+ - lib/messenger/bot/types/postback.rb
170
+ - lib/messenger/bot/types/receipt_element.rb
171
+ - lib/messenger/bot/types/receipt_template.rb
172
+ - lib/messenger/bot/types/recipient.rb
173
+ - lib/messenger/bot/types/sender.rb
174
+ - lib/messenger/bot/types/summary.rb
175
+ - lib/messenger/bot/types/template_attachment.rb
176
+ - lib/messenger/bot/version.rb
177
+ - messenger-bot-ruby.gemspec
178
+ homepage: https://github.com/macteo/messenger-bot-ruby
179
+ licenses:
180
+ - MIT
181
+ metadata: {}
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubyforge_project:
198
+ rubygems_version: 2.5.1
199
+ signing_key:
200
+ specification_version: 4
201
+ summary: Ruby wrapper for Messenger's Bot API
202
+ test_files: []