facebook-messenger 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/README.md +151 -10
- data/lib/facebook/messenger.rb +3 -0
- data/lib/facebook/messenger/bot.rb +43 -10
- data/lib/facebook/messenger/bot/message_type.rb +13 -0
- data/lib/facebook/messenger/bot/messaging_type.rb +12 -0
- data/lib/facebook/messenger/bot/tag.rb +27 -0
- data/lib/facebook/messenger/configuration.rb +3 -1
- data/lib/facebook/messenger/configuration/providers/base.rb +4 -2
- data/lib/facebook/messenger/configuration/providers/environment.rb +6 -1
- data/lib/facebook/messenger/error.rb +14 -1
- data/lib/facebook/messenger/incoming.rb +31 -6
- data/lib/facebook/messenger/incoming/account_linking.rb +6 -0
- data/lib/facebook/messenger/incoming/common.rb +75 -1
- data/lib/facebook/messenger/incoming/delivery.rb +1 -0
- data/lib/facebook/messenger/incoming/message.rb +86 -1
- data/lib/facebook/messenger/incoming/message_echo.rb +2 -2
- data/lib/facebook/messenger/incoming/message_request.rb +13 -0
- data/lib/facebook/messenger/incoming/optin.rb +18 -1
- data/lib/facebook/messenger/incoming/payment.rb +49 -0
- data/lib/facebook/messenger/incoming/policy_enforcement.rb +21 -0
- data/lib/facebook/messenger/incoming/postback.rb +5 -1
- data/lib/facebook/messenger/incoming/read.rb +3 -0
- data/lib/facebook/messenger/incoming/referral.rb +5 -2
- data/lib/facebook/messenger/profile.rb +43 -3
- data/lib/facebook/messenger/server.rb +40 -4
- data/lib/facebook/messenger/server_no_error.rb +36 -0
- data/lib/facebook/messenger/subscriptions.rb +42 -2
- data/lib/facebook/messenger/version.rb +3 -1
- metadata +12 -5
@@ -1,8 +1,8 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
-
# The Message echo class represents an
|
5
|
-
#
|
4
|
+
# The Message echo class represents an incoming Facebook Messenger message
|
5
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/message-echoes
|
6
6
|
class MessageEcho < Message
|
7
7
|
end
|
8
8
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Facebook
|
2
|
+
module Messenger
|
3
|
+
module Incoming
|
4
|
+
# The Message request class represents an
|
5
|
+
# incoming Facebook Messenger message request accepted by the user
|
6
|
+
class MessageRequest < Message
|
7
|
+
def accept?
|
8
|
+
@messaging['message_request'] == 'accept'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,16 +1,33 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
+
#
|
4
5
|
# The Optin class represents an incoming Facebook Messenger optin,
|
5
6
|
# which occurs when a user engages by using the Send-to-Messenger Plugin.
|
6
7
|
#
|
7
|
-
# https://developers.facebook.com/docs/messenger-platform/plugin-reference
|
8
|
+
# @see https://developers.facebook.com/docs/messenger-platform/plugin-reference
|
9
|
+
#
|
8
10
|
class Optin
|
9
11
|
include Facebook::Messenger::Incoming::Common
|
10
12
|
|
13
|
+
#
|
14
|
+
# Function returns 'data-ref' attribute that was defined
|
15
|
+
# with the entry point.
|
16
|
+
#
|
17
|
+
# @return [String] data-ref attribute.
|
18
|
+
#
|
11
19
|
def ref
|
12
20
|
@messaging['optin']['ref']
|
13
21
|
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Function returns 'user_ref' attribute defined in checkbox plugin.
|
25
|
+
#
|
26
|
+
# @return [String] user-ref attribute.
|
27
|
+
#
|
28
|
+
def user_ref
|
29
|
+
@messaging['optin']['user_ref']
|
30
|
+
end
|
14
31
|
end
|
15
32
|
end
|
16
33
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Facebook
|
2
|
+
module Messenger
|
3
|
+
module Incoming
|
4
|
+
# The Payment class represents a successful purchase using the Buy Button
|
5
|
+
#
|
6
|
+
# https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/payment
|
7
|
+
class Payment
|
8
|
+
include Facebook::Messenger::Incoming::Common
|
9
|
+
|
10
|
+
# The payment portion of the payload.
|
11
|
+
class Payment
|
12
|
+
def initialize(payment)
|
13
|
+
@payment = payment
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return String containing developer defined payload.
|
17
|
+
def payload
|
18
|
+
@payment['payload']
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return hash containing the requested information from user when they
|
22
|
+
# click buy button.
|
23
|
+
def user_info
|
24
|
+
@payment['requested_user_info']
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return hash containing the payment credential information.
|
28
|
+
def payment_credential
|
29
|
+
@payment['payment_credential']
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return hash containing the information about amount of purchase.
|
33
|
+
def amount
|
34
|
+
@payment['amount']
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return string containing option_id of selected shipping option.
|
38
|
+
def shipping_option_id
|
39
|
+
@payment['shipping_option_id']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def payment
|
44
|
+
@payment ||= Payment.new(@messaging['payment'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Facebook
|
2
|
+
module Messenger
|
3
|
+
module Incoming
|
4
|
+
# The PolicyEnforcement class represents an incoming webhook response from
|
5
|
+
# Facebook when they are notifying your app of a policy violation
|
6
|
+
#
|
7
|
+
# https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_policy_enforcement
|
8
|
+
class PolicyEnforcement
|
9
|
+
include Facebook::Messenger::Incoming::Common
|
10
|
+
|
11
|
+
def action
|
12
|
+
@messaging['policy_enforcement']['action']
|
13
|
+
end
|
14
|
+
|
15
|
+
def reason
|
16
|
+
@messaging['policy_enforcement']['reason']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
-
# The Postback class represents an incoming Facebook Messenger
|
4
|
+
# The Postback class represents an incoming Facebook Messenger
|
5
|
+
# postback events.
|
6
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_postbacks
|
5
7
|
class Postback
|
6
8
|
include Facebook::Messenger::Incoming::Common
|
7
9
|
|
10
|
+
# Return String of developer defined payload.
|
8
11
|
def payload
|
9
12
|
@messaging['postback']['payload']
|
10
13
|
end
|
11
14
|
|
15
|
+
# Return hash containing the referral information of user.
|
12
16
|
def referral
|
13
17
|
return if @messaging['postback']['referral'].nil?
|
14
18
|
@referral ||= Referral::Referral.new(
|
@@ -2,13 +2,16 @@ module Facebook
|
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
4
|
# The Read class represents the user reading a delivered message.
|
5
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/message-reads
|
5
6
|
class Read
|
6
7
|
include Facebook::Messenger::Incoming::Common
|
7
8
|
|
9
|
+
# Return time object when message is read by user.
|
8
10
|
def at
|
9
11
|
Time.at(@messaging['read']['watermark'] / 1000)
|
10
12
|
end
|
11
13
|
|
14
|
+
# Return Integer defining the sequence number of message.
|
12
15
|
def seq
|
13
16
|
@messaging['read']['seq']
|
14
17
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
-
#
|
4
|
+
# Referral class represents an incoming Facebook Messenger referral event.
|
5
5
|
#
|
6
|
-
# https://developers.facebook.com/docs/messenger-platform/
|
6
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messaging_referrals
|
7
7
|
class Referral
|
8
8
|
include Facebook::Messenger::Incoming::Common
|
9
9
|
|
@@ -13,14 +13,17 @@ module Facebook
|
|
13
13
|
@referral = referral
|
14
14
|
end
|
15
15
|
|
16
|
+
# Return String of ref data set in referrer.
|
16
17
|
def ref
|
17
18
|
@referral['ref']
|
18
19
|
end
|
19
20
|
|
21
|
+
# Return String of referral source.
|
20
22
|
def source
|
21
23
|
@referral['source']
|
22
24
|
end
|
23
25
|
|
26
|
+
# Return String of referral type.
|
24
27
|
def type
|
25
28
|
@referral['type']
|
26
29
|
end
|
@@ -2,18 +2,31 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Facebook
|
4
4
|
module Messenger
|
5
|
-
# This module handles changing messenger profile (menu, start & greeting).
|
6
5
|
#
|
7
|
-
#
|
6
|
+
# This module provide functionality to manage the messenger profile.
|
7
|
+
# @see https://developers.facebook.com/docs/messenger-platform/messenger-profile
|
8
|
+
#
|
8
9
|
module Profile
|
9
10
|
include HTTParty
|
10
11
|
|
11
|
-
base_uri
|
12
|
+
# Define base_uri for HTTParty.
|
13
|
+
base_uri 'https://graph.facebook.com/v2.9/me'
|
12
14
|
|
13
15
|
format :json
|
14
16
|
|
15
17
|
module_function
|
16
18
|
|
19
|
+
#
|
20
|
+
# Set the messenger profile.
|
21
|
+
#
|
22
|
+
# @raise [Facebook::Messenger::Profile::Error] if there is any error
|
23
|
+
# in response.
|
24
|
+
#
|
25
|
+
# @param [Hash] settings Hash defining the profile settings.
|
26
|
+
# @param [String] access_token Access token of facebook page.
|
27
|
+
#
|
28
|
+
# @return [Boolean] If profile is successfully set, return true.
|
29
|
+
#
|
17
30
|
def set(settings, access_token:)
|
18
31
|
response = post '/messenger_profile', body: settings.to_json, query: {
|
19
32
|
access_token: access_token
|
@@ -24,6 +37,17 @@ module Facebook
|
|
24
37
|
true
|
25
38
|
end
|
26
39
|
|
40
|
+
#
|
41
|
+
# Unset the messenger profile.
|
42
|
+
#
|
43
|
+
# @raise [Facebook::Messenger::Profile::Error] if there is any error
|
44
|
+
# in response.
|
45
|
+
#
|
46
|
+
# @param [Hash] settings Hash defining the profile settings.
|
47
|
+
# @param [String] access_token Access token of facebook page.
|
48
|
+
#
|
49
|
+
# @return [Boolean] If profile is successfully removed, return true.
|
50
|
+
#
|
27
51
|
def unset(settings, access_token:)
|
28
52
|
response = delete '/messenger_profile', body: settings.to_json, query: {
|
29
53
|
access_token: access_token
|
@@ -34,10 +58,23 @@ module Facebook
|
|
34
58
|
true
|
35
59
|
end
|
36
60
|
|
61
|
+
#
|
62
|
+
# Function raise error if response has error key.
|
63
|
+
#
|
64
|
+
# @raise [Facebook::Messenger::Profile::Error] if error is present
|
65
|
+
# in response.
|
66
|
+
#
|
67
|
+
# @param [Hash] response Response hash from facebook.
|
68
|
+
#
|
37
69
|
def raise_errors(response)
|
38
70
|
raise Error, response['error'] if response.key? 'error'
|
39
71
|
end
|
40
72
|
|
73
|
+
#
|
74
|
+
# Default HTTParty options.
|
75
|
+
#
|
76
|
+
# @return [Hash] Default HTTParty options.
|
77
|
+
#
|
41
78
|
def default_options
|
42
79
|
super.merge(
|
43
80
|
headers: {
|
@@ -46,6 +83,9 @@ module Facebook
|
|
46
83
|
)
|
47
84
|
end
|
48
85
|
|
86
|
+
#
|
87
|
+
# Class Error provides errors related to profile subscriptions.
|
88
|
+
#
|
49
89
|
class Error < Facebook::Messenger::FacebookError; end
|
50
90
|
end
|
51
91
|
end
|
@@ -12,13 +12,16 @@ module Facebook
|
|
12
12
|
some time, check your app's secret token.
|
13
13
|
HEREDOC
|
14
14
|
|
15
|
+
#
|
15
16
|
# This module holds the server that processes incoming messages from the
|
16
17
|
# Facebook Messenger Platform.
|
18
|
+
#
|
17
19
|
class Server
|
18
20
|
def self.call(env)
|
19
21
|
new.call(env)
|
20
22
|
end
|
21
23
|
|
24
|
+
# Rack handler for request.
|
22
25
|
def call(env)
|
23
26
|
@request = Rack::Request.new(env)
|
24
27
|
@response = Rack::Response.new
|
@@ -34,8 +37,14 @@ module Facebook
|
|
34
37
|
@response.finish
|
35
38
|
end
|
36
39
|
|
40
|
+
# @private
|
37
41
|
private
|
38
42
|
|
43
|
+
#
|
44
|
+
# Function validates the verification request which is sent by Facebook
|
45
|
+
# to validate the entered endpoint.
|
46
|
+
# @see https://developers.facebook.com/docs/graph-api/webhooks#callback
|
47
|
+
#
|
39
48
|
def verify
|
40
49
|
if valid_verify_token?(@request.params['hub.verify_token'])
|
41
50
|
@response.write @request.params['hub.challenge']
|
@@ -44,6 +53,10 @@ module Facebook
|
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
56
|
+
#
|
57
|
+
# Function handles the webhook events.
|
58
|
+
# @raise BadRequestError if the request is tampered.
|
59
|
+
#
|
47
60
|
def receive
|
48
61
|
check_integrity
|
49
62
|
|
@@ -52,12 +65,16 @@ module Facebook
|
|
52
65
|
respond_with_error(error)
|
53
66
|
end
|
54
67
|
|
68
|
+
#
|
55
69
|
# Check the integrity of the request.
|
70
|
+
# @see https://developers.facebook.com/docs/messenger-platform/webhook#security
|
56
71
|
#
|
57
|
-
#
|
72
|
+
# @raise BadRequestError if the request has been tampered with.
|
58
73
|
#
|
59
|
-
# Returns nothing.
|
60
74
|
def check_integrity
|
75
|
+
# If app secret is not found in environment, return.
|
76
|
+
# So for the security purpose always add provision in
|
77
|
+
# configuration provider to return app secret.
|
61
78
|
return unless app_secret_for(parsed_body['entry'][0]['id'])
|
62
79
|
|
63
80
|
unless signature.start_with?('sha1='.freeze)
|
@@ -75,17 +92,21 @@ module Facebook
|
|
75
92
|
@request.env['HTTP_X_HUB_SIGNATURE'.freeze].to_s
|
76
93
|
end
|
77
94
|
|
95
|
+
#
|
78
96
|
# Verify that the signature given in the X-Hub-Signature header matches
|
79
97
|
# that of the body.
|
80
98
|
#
|
81
|
-
#
|
99
|
+
# @return [Boolean] true if request is valid else false.
|
100
|
+
#
|
82
101
|
def valid_signature?
|
83
102
|
Rack::Utils.secure_compare(signature, signature_for(body))
|
84
103
|
end
|
85
104
|
|
105
|
+
#
|
86
106
|
# Sign the given string.
|
87
107
|
#
|
88
|
-
#
|
108
|
+
# @return [String] A string describing its signature.
|
109
|
+
#
|
89
110
|
def signature_for(string)
|
90
111
|
format('sha1=%s'.freeze, generate_hmac(string))
|
91
112
|
end
|
@@ -115,13 +136,23 @@ module Facebook
|
|
115
136
|
@body ||= @request.body.read
|
116
137
|
end
|
117
138
|
|
139
|
+
#
|
118
140
|
# Returns a Hash describing the parsed request body.
|
141
|
+
# @raise JSON::ParserError if body hash is not valid.
|
142
|
+
#
|
143
|
+
# @return [JSON] Parsed body hash.
|
144
|
+
#
|
119
145
|
def parsed_body
|
120
146
|
@parsed_body ||= JSON.parse(body)
|
121
147
|
rescue JSON::ParserError
|
122
148
|
raise BadRequestError, 'Error parsing request body format'
|
123
149
|
end
|
124
150
|
|
151
|
+
#
|
152
|
+
# Function hand over the webhook event to handlers.
|
153
|
+
#
|
154
|
+
# @param [Hash] events Parsed body hash in webhook event.
|
155
|
+
#
|
125
156
|
def trigger(events)
|
126
157
|
# Facebook may batch several items in the 'entry' array during
|
127
158
|
# periods of high load.
|
@@ -137,6 +168,11 @@ module Facebook
|
|
137
168
|
end
|
138
169
|
end
|
139
170
|
|
171
|
+
#
|
172
|
+
# If received request is tampered, sent 400 code in response.
|
173
|
+
#
|
174
|
+
# @param [Object] error Error object.
|
175
|
+
#
|
140
176
|
def respond_with_error(error)
|
141
177
|
@response.status = 400
|
142
178
|
@response.write(error.message)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'server'
|
2
|
+
|
3
|
+
module Facebook
|
4
|
+
module Messenger
|
5
|
+
# Server rescuing all errors sending the backtrace back to the chat
|
6
|
+
# FOR DEVELOPPING PURPOSE
|
7
|
+
class ServerNoError < Server
|
8
|
+
SCREAMING_FACE = "\xF0\x9F\x98\xB1".freeze
|
9
|
+
MAX_MESSAGE_LENGTH = 639
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
super
|
13
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
14
|
+
send(SCREAMING_FACE)
|
15
|
+
send(e.inspect)
|
16
|
+
send(e.backtrace.join("\n")[0..MAX_MESSAGE_LENGTH - 3] + '...')
|
17
|
+
|
18
|
+
@response.status = 200
|
19
|
+
@response.finish
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def sender
|
25
|
+
parsed_body['entry'][0]['messaging'][0]['sender']
|
26
|
+
end
|
27
|
+
|
28
|
+
def send(text)
|
29
|
+
Bot.deliver({
|
30
|
+
recipient: sender,
|
31
|
+
message: { text: text }
|
32
|
+
}, access_token: ENV['ACCESS_TOKEN'])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -2,16 +2,31 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Facebook
|
4
4
|
module Messenger
|
5
|
-
#
|
5
|
+
#
|
6
|
+
# Module Subscriptions handles subscribing and unsubscribing Applications
|
7
|
+
# to Pages.
|
8
|
+
#
|
6
9
|
module Subscriptions
|
7
10
|
include HTTParty
|
8
11
|
|
9
|
-
base_uri 'https://graph.facebook.com/v2.
|
12
|
+
base_uri 'https://graph.facebook.com/v2.9/me'
|
10
13
|
|
11
14
|
format :json
|
12
15
|
|
13
16
|
module_function
|
14
17
|
|
18
|
+
#
|
19
|
+
# Function subscribe the facebook app to page.
|
20
|
+
# @see https://developers.facebook.com/docs/graph-api/reference/page/subscribed_apps
|
21
|
+
#
|
22
|
+
# @raise [Facebook::Messenger::Subscriptions::Error] if there is any error
|
23
|
+
# in the response of subscribed_apps request.
|
24
|
+
#
|
25
|
+
# @param [String] access_token Access token of page to which bot has
|
26
|
+
# to subscribe.
|
27
|
+
#
|
28
|
+
# @return [Boolean] TRUE
|
29
|
+
#
|
15
30
|
def subscribe(access_token:)
|
16
31
|
response = post '/subscribed_apps', query: {
|
17
32
|
access_token: access_token
|
@@ -22,6 +37,18 @@ module Facebook
|
|
22
37
|
true
|
23
38
|
end
|
24
39
|
|
40
|
+
#
|
41
|
+
# Function unsubscribe the app from facebook page.
|
42
|
+
# @see https://developers.facebook.com/docs/graph-api/reference/page/subscribed_apps
|
43
|
+
#
|
44
|
+
# @raise [Facebook::Messenger::Subscriptions::Error] if there is any error
|
45
|
+
# in the response of subscribed_apps request.
|
46
|
+
#
|
47
|
+
# @param [String] access_token Access token of page from which app has
|
48
|
+
# to unsubscribe.
|
49
|
+
#
|
50
|
+
# @return [Boolean] TRUE
|
51
|
+
#
|
25
52
|
def unsubscribe(access_token:)
|
26
53
|
response = delete '/subscribed_apps', query: {
|
27
54
|
access_token: access_token
|
@@ -32,10 +59,23 @@ module Facebook
|
|
32
59
|
true
|
33
60
|
end
|
34
61
|
|
62
|
+
#
|
63
|
+
# If there is any error in response, raise error.
|
64
|
+
#
|
65
|
+
# @raise [Facebook::Messenger::Subscriptions::Error] If there is error
|
66
|
+
# in response.
|
67
|
+
#
|
68
|
+
# @param [Hash] response Response from facebook.
|
69
|
+
#
|
70
|
+
# @return Raise the error.
|
71
|
+
#
|
35
72
|
def raise_errors(response)
|
36
73
|
raise Error, response['error'] if response.key? 'error'
|
37
74
|
end
|
38
75
|
|
76
|
+
#
|
77
|
+
# Class Error provides errors related to subscriptions.
|
78
|
+
#
|
39
79
|
class Error < Facebook::Messenger::FacebookError; end
|
40
80
|
end
|
41
81
|
end
|