facebook-messenger 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f7c4706fe8ba78595fea5ecb1cd09c272b888d5
4
- data.tar.gz: 0c92e230627849cbf801f5b65e64b3d4f86df070
3
+ metadata.gz: e91c65dbe461f44e0516eab4311854cb1e346c67
4
+ data.tar.gz: 8986a3265e3c79aa89ee77476569d6a9a45aa652
5
5
  SHA512:
6
- metadata.gz: b36ffd86c6f2ae36f412295e830ae704dff9352f37da76fe9bd9539d0789dc9e7093d36a6e60212a1154aab532e87e2f134da03c2c0d1184d26589c4253c62c4
7
- data.tar.gz: f62d1a3a1122d0feea5c2aaa36116db5538c44c1358bb308091716c0e04ca93b3377c2e5017384e4dac0904b2af1f948ff63dce2cc6b2b20a6be5b64681199e6
6
+ metadata.gz: 03b239d5a2531fe9f11f483898a76b62c64cb24eb5ab3ae65230600c94485ac522e60526d8513be0718bfb85efc123b3e3c0a6bb0f479d7369783fc837822e7e
7
+ data.tar.gz: 4b22c9a53f9021b8725edb330fe48397b9bd51a571aa9bc85a5982eeef65902b064b171cbd6104848c32ff6d2c875aa823f4b4c51eda754e617d9c7e17e1b510
data/README.md CHANGED
@@ -41,15 +41,14 @@ end
41
41
  ... or even send the human messages out of the blue:
42
42
 
43
43
  ```ruby
44
- Bot.deliver(
44
+ Bot.deliver({
45
45
  recipient: {
46
46
  id: '45123'
47
47
  },
48
48
  message: {
49
49
  text: 'Human?'
50
- },
51
- access_token: ENV['ACCESS_TOKEN']
52
- )
50
+ }
51
+ }, access_token: ENV['ACCESS_TOKEN'])
53
52
  ```
54
53
 
55
54
  ##### Messages with images
@@ -73,7 +72,7 @@ The human may appreciate hints:
73
72
 
74
73
  ```ruby
75
74
  message.reply(
76
- text: 'Human, who is your favorite bot?'
75
+ text: 'Human, who is your favorite bot?',
77
76
  quick_replies: [
78
77
  {
79
78
  content_type: 'text',
@@ -126,7 +125,37 @@ end
126
125
  Show the human you are preparing a message for them:
127
126
 
128
127
  ```ruby
129
- message.type
128
+ Bot.on :message do |message|
129
+ message.typing_on
130
+
131
+ # Do something expensive
132
+
133
+ message.reply(text: 'Hello, human!')
134
+ end
135
+ ```
136
+
137
+ Or that you changed your mind:
138
+
139
+ ```ruby
140
+ Bot.on :message do |message|
141
+ message.typing_on
142
+
143
+ if # something
144
+ message.reply(text: 'Hello, human!')
145
+ else
146
+ message.typing_off
147
+ end
148
+ end
149
+ ```
150
+
151
+ ##### Mark as viewed
152
+
153
+ You can mark messages as seen to keep the human on their toes:
154
+
155
+ ```ruby
156
+ Bot.on :message do |message|
157
+ message.mark_seen
158
+ end
130
159
  ```
131
160
 
132
161
  #### Send to Facebook
@@ -161,24 +190,38 @@ Bot.on :delivery do |delivery|
161
190
  end
162
191
  ```
163
192
 
193
+ #### Referral
194
+
195
+ When the human follows a m.me link with a ref parameter like http://m.me/mybot?ref=myparam,
196
+ you will receive a `referral` event.
197
+
198
+ ```ruby
199
+ Bot.on :referral do |referral|
200
+ referral.sender # => { 'id' => '1008372609250235' }
201
+ referral.recipient # => { 'id' => '2015573629214912' }
202
+ referral.sent_at # => 2016-04-22 21:30:36 +0200
203
+ referral.ref # => 'MYPARAM'
204
+ end
205
+ ```
206
+
164
207
  #### Change thread settings
165
208
 
166
209
  You can greet new humans to entice them into talking to you:
167
210
 
168
211
  ```ruby
169
- Facebook::Messenger::Thread.set(
212
+ Facebook::Messenger::Thread.set({
170
213
  setting_type: 'greeting',
171
214
  greeting: {
172
215
  text: 'Welcome to your new bot overlord!'
173
- }
174
- )
216
+ },
217
+ }, access_token: ENV['ACCESS_TOKEN'])
175
218
  ```
176
219
 
177
220
  You can define the action to trigger when new humans click on the Get
178
221
  Started button. Before doing it you should check to select the messaging_postbacks field when setting up your webhook.
179
222
 
180
223
  ```ruby
181
- Facebook::Messenger::Thread.set(
224
+ Facebook::Messenger::Thread.set({
182
225
  setting_type: 'call_to_actions',
183
226
  thread_state: 'new_thread',
184
227
  call_to_actions: [
@@ -186,13 +229,13 @@ Facebook::Messenger::Thread.set(
186
229
  payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_WELCOME'
187
230
  }
188
231
  ]
189
- )
232
+ }, access_token: ENV['ACCESS_TOKEN'])
190
233
  ```
191
234
 
192
235
  You can show a persistent menu to humans.
193
236
 
194
237
  ```ruby
195
- Facebook::Messenger::Thread.set(
238
+ Facebook::Messenger::Thread.set({
196
239
  setting_type: 'call_to_actions',
197
240
  thread_state: 'existing_thread',
198
241
  call_to_actions: [
@@ -212,7 +255,7 @@ Facebook::Messenger::Thread.set(
212
255
  url: 'http://example.com/'
213
256
  }
214
257
  ]
215
- )
258
+ }, access_token: ENV['ACCESS_TOKEN'])
216
259
  ```
217
260
 
218
261
  ## Configuration
@@ -1,3 +1,6 @@
1
+ require 'facebook/messenger/bot/error_parser'
2
+ require 'facebook/messenger/bot/exceptions'
3
+
1
4
  module Facebook
2
5
  module Messenger
3
6
  # The Bot module sends and receives messages.
@@ -7,7 +10,7 @@ module Facebook
7
10
  base_uri 'https://graph.facebook.com/v2.6/me'
8
11
 
9
12
  EVENTS = [:message, :delivery, :postback, :optin,
10
- :read, :account_linking].freeze
13
+ :read, :account_linking, :referral].freeze
11
14
 
12
15
  class << self
13
16
  # Deliver a message with the given payload.
@@ -26,9 +29,9 @@ module Facebook
26
29
  access_token: access_token
27
30
  }
28
31
 
29
- raise_errors_from(response)
32
+ Facebook::Messenger::Bot::ErrorParser.raise_errors_from(response)
30
33
 
31
- response['message_id']
34
+ response.body
32
35
  end
33
36
 
34
37
  # Register a hook for the given event.
@@ -66,34 +69,6 @@ module Facebook
66
69
  $stderr.puts "Ignoring #{event} (no hook registered)"
67
70
  end
68
71
 
69
- # Raise any errors in the given response.
70
- #
71
- # response - A HTTParty::Response object.
72
- #
73
- # Returns nil if no errors were found, otherwises raises appropriately.
74
- def raise_errors_from(response)
75
- return unless response.key? 'error'
76
- error = response['error']
77
-
78
- raise(
79
- error_class_from_error_code(error['code']),
80
- (error['error_data'] || error['message'])
81
- )
82
- end
83
-
84
- # Find the appropriate error class for the given error code.
85
- #
86
- # error_code - An Integer describing an error code.
87
- #
88
- # Returns an error class, or raises KeyError if none was found.
89
- def error_class_from_error_code(error_code)
90
- {
91
- 100 => RecipientNotFound,
92
- 10 => PermissionDenied,
93
- 2 => InternalError
94
- }[error_code] || Facebook::Messenger::Error
95
- end
96
-
97
72
  # Return a Hash of hooks.
98
73
  def hooks
99
74
  @hooks ||= {}
@@ -113,10 +88,6 @@ module Facebook
113
88
  )
114
89
  end
115
90
  end
116
-
117
- class RecipientNotFound < Facebook::Messenger::Error; end
118
- class PermissionDenied < Facebook::Messenger::Error; end
119
- class InternalError < Facebook::Messenger::Error; end
120
91
  end
121
92
  end
122
93
  end
@@ -0,0 +1,111 @@
1
+ module Facebook
2
+ module Messenger
3
+ module Bot
4
+ # Parses and raises Facebook response errors for the send API.
5
+ class ErrorParser
6
+ INTERNAL_ERROR_CODES = {
7
+ 1200 => []
8
+ }.freeze
9
+
10
+ ACCESS_TOKEN_ERROR_CODES = {
11
+ 190 => []
12
+ }.freeze
13
+
14
+ ACCOUNT_LINKING_ERROR_CODES = {
15
+ 10_303 => []
16
+ }.freeze
17
+
18
+ LIMIT_ERROR_CODES = {
19
+ 4 => [2_018_022],
20
+ 100 => [2_018_109],
21
+ 613 => [nil]
22
+ }.freeze
23
+
24
+ BAD_PARAMETER_ERROR_CODES = {
25
+ 100 => [nil, 2_018_001]
26
+ }.freeze
27
+
28
+ PERMISSION_ERROR_CODES = {
29
+ 10 => [2_018_065, 2_018_108],
30
+ 200 => [1_545_041, 2_018_028, 2_018_027, 2_018_021],
31
+ 230 => [nil]
32
+ }.freeze
33
+
34
+ class << self
35
+ # Raise any errors in the given response.
36
+ #
37
+ # response - A HTTParty::Response object.
38
+ #
39
+ # Returns nil if no errors were found, otherwises raises appropriately
40
+ def raise_errors_from(response)
41
+ return unless response.key? 'error'
42
+
43
+ error = response['error']
44
+
45
+ error_code = error['code']
46
+ error_subcode = error['error_subcode']
47
+
48
+ raise_code_only_error(error_code, error) if error_subcode.nil?
49
+
50
+ raise_code_subcode_error(error_code, error_subcode, error)
51
+
52
+ # Default to unidentified error
53
+ raise FacebookError, error
54
+ end
55
+
56
+ private
57
+
58
+ def raise_code_only_error(error_code, args)
59
+ raise InternalError, args if internal_error?(error_code)
60
+ raise AccessTokenError, args if access_token_error?(error_code)
61
+ raise AccountLinkingError, args if account_linking_error?(
62
+ error_code
63
+ )
64
+ end
65
+
66
+ def raise_code_subcode_error(error_code, error_subcode, args)
67
+ raise LimitError, args if limit_error?(error_code,
68
+ error_subcode)
69
+ raise BadParameterError, args if bad_parameter_error?(error_code,
70
+ error_subcode)
71
+ raise PermissionError, args if permission_error?(error_code,
72
+ error_subcode)
73
+ end
74
+
75
+ def internal_error?(error_code)
76
+ INTERNAL_ERROR_CODES.keys.include? error_code
77
+ end
78
+
79
+ def access_token_error?(error_code)
80
+ ACCESS_TOKEN_ERROR_CODES.keys.include? error_code
81
+ end
82
+
83
+ def account_linking_error?(error_code)
84
+ ACCOUNT_LINKING_ERROR_CODES.keys.include? error_code
85
+ end
86
+
87
+ def limit_error?(error_code, error_subcode)
88
+ limit_errors = LIMIT_ERROR_CODES[error_code]
89
+ return unless limit_errors
90
+
91
+ limit_errors.include? error_subcode
92
+ end
93
+
94
+ def bad_parameter_error?(error_code, error_subcode)
95
+ bad_parameter_errors = BAD_PARAMETER_ERROR_CODES[error_code]
96
+ return unless bad_parameter_errors
97
+
98
+ bad_parameter_errors.include? error_subcode
99
+ end
100
+
101
+ def permission_error?(error_code, error_subcode)
102
+ permission_errors = PERMISSION_ERROR_CODES[error_code]
103
+ return unless permission_errors
104
+
105
+ permission_errors.include? error_subcode
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,15 @@
1
+ module Facebook
2
+ module Messenger
3
+ module Bot
4
+ # Base Facebook Messenger send API exception.
5
+ class SendError < Facebook::Messenger::FacebookError; end
6
+
7
+ class AccessTokenError < SendError; end
8
+ class AccountLinkingError < SendError; end
9
+ class BadParameterError < SendError; end
10
+ class InternalError < SendError; end
11
+ class LimitError < SendError; end
12
+ class PermissionError < SendError; end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,31 @@
1
1
  module Facebook
2
2
  module Messenger
3
+ # Base Facebook Messenger exception.
3
4
  class Error < StandardError; end
5
+
6
+ # Base error class for Facebook API errors.
7
+ class FacebookError < Error
8
+ attr_reader :message
9
+ attr_reader :type
10
+ attr_reader :code
11
+ attr_reader :subcode
12
+ attr_reader :user_title
13
+ attr_reader :user_msg
14
+ attr_reader :fbtrace_id
15
+
16
+ def initialize(error)
17
+ @message = error['message']
18
+ @type = error['type']
19
+ @code = error['code']
20
+ @subcode = error['error_subcode']
21
+ @user_title = error['error_user_title']
22
+ @user_msg = error['error_user_msg']
23
+ @fbtrace_id = error['fbtrace_id']
24
+ end
25
+
26
+ def to_s
27
+ @message
28
+ end
29
+ end
4
30
  end
5
31
  end
@@ -5,6 +5,7 @@ require 'facebook/messenger/incoming/postback'
5
5
  require 'facebook/messenger/incoming/optin'
6
6
  require 'facebook/messenger/incoming/read'
7
7
  require 'facebook/messenger/incoming/account_linking'
8
+ require 'facebook/messenger/incoming/referral'
8
9
 
9
10
  module Facebook
10
11
  module Messenger
@@ -17,7 +18,8 @@ module Facebook
17
18
  'postback' => Postback,
18
19
  'optin' => Optin,
19
20
  'read' => Read,
20
- 'account_linking' => AccountLinking
21
+ 'account_linking' => AccountLinking,
22
+ 'referral' => Referral
21
23
  }.freeze
22
24
 
23
25
  # Parse the given payload.
@@ -21,7 +21,7 @@ module Facebook
21
21
  Time.at(@messaging['timestamp'] / 1000)
22
22
  end
23
23
 
24
- def type
24
+ def typing_on
25
25
  payload = {
26
26
  recipient: sender,
27
27
  sender_action: 'typing_on'
@@ -30,6 +30,24 @@ module Facebook
30
30
  Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
31
31
  end
32
32
 
33
+ def typing_off
34
+ payload = {
35
+ recipient: sender,
36
+ sender_action: 'typing_off'
37
+ }
38
+
39
+ Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
40
+ end
41
+
42
+ def mark_seen
43
+ payload = {
44
+ recipient: sender,
45
+ sender_action: 'mark_seen'
46
+ }
47
+
48
+ Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
49
+ end
50
+
33
51
  def reply(message)
34
52
  payload = {
35
53
  recipient: sender,
@@ -8,6 +8,13 @@ module Facebook
8
8
  def payload
9
9
  @messaging['postback']['payload']
10
10
  end
11
+
12
+ def referral
13
+ return if @messaging['postback']['referral'].nil?
14
+ @referral ||= Referral::Referral.new(
15
+ @messaging['postback']['referral']
16
+ )
17
+ end
11
18
  end
12
19
  end
13
20
  end
@@ -0,0 +1,39 @@
1
+ module Facebook
2
+ module Messenger
3
+ module Incoming
4
+ # The Referral class represents an incoming Facebook Messenger referral.
5
+ #
6
+ # https://developers.facebook.com/docs/messenger-platform/referral-params
7
+ class Referral
8
+ include Facebook::Messenger::Incoming::Common
9
+
10
+ # The referral portion of the payload.
11
+ class Referral
12
+ def initialize(referral)
13
+ @referral = referral
14
+ end
15
+
16
+ def ref
17
+ @referral['ref']
18
+ end
19
+
20
+ def source
21
+ @referral['source']
22
+ end
23
+
24
+ def type
25
+ @referral['type']
26
+ end
27
+ end
28
+
29
+ def referral
30
+ @referral ||= Referral.new(@messaging['referral'])
31
+ end
32
+
33
+ def ref
34
+ referral.ref
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -33,10 +33,10 @@ module Facebook
33
33
  end
34
34
 
35
35
  def raise_errors(response)
36
- raise Error, response['error']['message'] if response.key? 'error'
36
+ raise Error, response['error'] if response.key? 'error'
37
37
  end
38
38
 
39
- class Error < Facebook::Messenger::Error; end
39
+ class Error < Facebook::Messenger::FacebookError; end
40
40
  end
41
41
  end
42
42
  end
@@ -35,7 +35,7 @@ module Facebook
35
35
  end
36
36
 
37
37
  def raise_errors(response)
38
- raise Error, response['error']['message'] if response.key? 'error'
38
+ raise Error, response['error'] if response.key? 'error'
39
39
  end
40
40
 
41
41
  def default_options
@@ -46,7 +46,7 @@ module Facebook
46
46
  )
47
47
  end
48
48
 
49
- class Error < Facebook::Messenger::Error; end
49
+ class Error < Facebook::Messenger::FacebookError; end
50
50
  end
51
51
  end
52
52
  end
@@ -1,5 +1,5 @@
1
1
  module Facebook
2
2
  module Messenger
3
- VERSION = '0.11.1'.freeze
3
+ VERSION = '0.12.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: facebook-messenger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johannes Gorset
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-23 00:00:00.000000000 Z
11
+ date: 2017-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -168,6 +168,8 @@ files:
168
168
  - bin/setup
169
169
  - lib/facebook/messenger.rb
170
170
  - lib/facebook/messenger/bot.rb
171
+ - lib/facebook/messenger/bot/error_parser.rb
172
+ - lib/facebook/messenger/bot/exceptions.rb
171
173
  - lib/facebook/messenger/configuration.rb
172
174
  - lib/facebook/messenger/configuration/providers.rb
173
175
  - lib/facebook/messenger/configuration/providers/base.rb
@@ -181,6 +183,7 @@ files:
181
183
  - lib/facebook/messenger/incoming/optin.rb
182
184
  - lib/facebook/messenger/incoming/postback.rb
183
185
  - lib/facebook/messenger/incoming/read.rb
186
+ - lib/facebook/messenger/incoming/referral.rb
184
187
  - lib/facebook/messenger/server.rb
185
188
  - lib/facebook/messenger/subscriptions.rb
186
189
  - lib/facebook/messenger/thread.rb
@@ -205,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
208
  version: '0'
206
209
  requirements: []
207
210
  rubyforge_project:
208
- rubygems_version: 2.5.1
211
+ rubygems_version: 2.6.8
209
212
  signing_key:
210
213
  specification_version: 4
211
214
  summary: Facebook Messenger client