messenger-bot-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []