facebook-messenger 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -2,8 +2,10 @@ module Facebook
|
|
2
2
|
module Messenger
|
3
3
|
class Configuration
|
4
4
|
module Providers
|
5
|
-
# This is the base configuration provider.
|
6
|
-
#
|
5
|
+
# This is the base configuration provider.
|
6
|
+
# User can overwrite this class to customize the environment variables
|
7
|
+
# Be sure to implement all the functions as it raises
|
8
|
+
# NotImplementedError errors.
|
7
9
|
class Base
|
8
10
|
def valid_verify_token?(*)
|
9
11
|
raise NotImplementedError
|
@@ -2,16 +2,21 @@ module Facebook
|
|
2
2
|
module Messenger
|
3
3
|
class Configuration
|
4
4
|
module Providers
|
5
|
-
#
|
5
|
+
# The default configuration provider for environment variables.
|
6
6
|
class Environment
|
7
7
|
def valid_verify_token?(verify_token)
|
8
8
|
verify_token == ENV['VERIFY_TOKEN']
|
9
9
|
end
|
10
10
|
|
11
|
+
# Return String of app secret of Facebook App.
|
12
|
+
# Make sure you are returning the app secret if you overwrite
|
13
|
+
# configuration provider class as this app secret is used to
|
14
|
+
# validate the incoming requests.
|
11
15
|
def app_secret_for(*)
|
12
16
|
ENV['APP_SECRET']
|
13
17
|
end
|
14
18
|
|
19
|
+
# Return String of page access token.
|
15
20
|
def access_token_for(*)
|
16
21
|
ENV['ACCESS_TOKEN']
|
17
22
|
end
|
@@ -13,6 +13,11 @@ module Facebook
|
|
13
13
|
attr_reader :user_msg
|
14
14
|
attr_reader :fbtrace_id
|
15
15
|
|
16
|
+
#
|
17
|
+
# Constructor function.
|
18
|
+
#
|
19
|
+
# @param [Hash] error Hash containing information about error.
|
20
|
+
#
|
16
21
|
def initialize(error)
|
17
22
|
@message = error['message']
|
18
23
|
@type = error['type']
|
@@ -23,8 +28,16 @@ module Facebook
|
|
23
28
|
@fbtrace_id = error['fbtrace_id']
|
24
29
|
end
|
25
30
|
|
31
|
+
#
|
32
|
+
# Function to convert the error into string.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# Error_Object.to_s #=> "Invalid OAuth access token. (subcode: 1234567)"
|
36
|
+
#
|
37
|
+
# @return [String] String describing the error message
|
38
|
+
#
|
26
39
|
def to_s
|
27
|
-
@message
|
40
|
+
"#{@message} (subcode: #{subcode})"
|
28
41
|
end
|
29
42
|
end
|
30
43
|
end
|
@@ -1,18 +1,25 @@
|
|
1
1
|
require 'facebook/messenger/incoming/common'
|
2
2
|
require 'facebook/messenger/incoming/message'
|
3
3
|
require 'facebook/messenger/incoming/message_echo'
|
4
|
+
require 'facebook/messenger/incoming/message_request'
|
4
5
|
require 'facebook/messenger/incoming/delivery'
|
5
6
|
require 'facebook/messenger/incoming/postback'
|
6
7
|
require 'facebook/messenger/incoming/optin'
|
7
8
|
require 'facebook/messenger/incoming/read'
|
8
9
|
require 'facebook/messenger/incoming/account_linking'
|
9
10
|
require 'facebook/messenger/incoming/referral'
|
11
|
+
require 'facebook/messenger/incoming/payment'
|
12
|
+
require 'facebook/messenger/incoming/policy_enforcement'
|
10
13
|
|
11
14
|
module Facebook
|
12
15
|
module Messenger
|
13
|
-
#
|
14
|
-
#
|
16
|
+
#
|
17
|
+
# Module Incoming parses and abstracts incoming requests from Messenger.
|
18
|
+
#
|
15
19
|
module Incoming
|
20
|
+
#
|
21
|
+
# @return [Hash] Hash containing facebook messenger events and its event
|
22
|
+
# handler classes.
|
16
23
|
EVENTS = {
|
17
24
|
'message' => Message,
|
18
25
|
'delivery' => Delivery,
|
@@ -21,14 +28,22 @@ module Facebook
|
|
21
28
|
'read' => Read,
|
22
29
|
'account_linking' => AccountLinking,
|
23
30
|
'referral' => Referral,
|
24
|
-
'message_echo' => MessageEcho
|
31
|
+
'message_echo' => MessageEcho,
|
32
|
+
'message_request' => MessageRequest,
|
33
|
+
'payment' => Payment,
|
34
|
+
'policy_enforcement' => PolicyEnforcement
|
25
35
|
}.freeze
|
26
36
|
|
27
|
-
# Parse the given payload
|
37
|
+
# Parse the given payload and create new object of class related
|
38
|
+
# to event in payload.
|
39
|
+
#
|
40
|
+
# @see https://developers.facebook.com/docs/messenger-platform/webhook-reference
|
41
|
+
#
|
42
|
+
# @raise [Facebook::Messenger::Incoming::UnknownPayload] if event is not
|
43
|
+
# registered in EVENTS constant
|
28
44
|
#
|
29
|
-
# payload
|
45
|
+
# @param [Hash] payload A Hash describing a payload from Facebook.
|
30
46
|
#
|
31
|
-
# * https://developers.facebook.com/docs/messenger-platform/webhook-reference
|
32
47
|
def self.parse(payload)
|
33
48
|
return MessageEcho.new(payload) if payload_is_echo?(payload)
|
34
49
|
|
@@ -39,10 +54,20 @@ module Facebook
|
|
39
54
|
raise UnknownPayload, payload
|
40
55
|
end
|
41
56
|
|
57
|
+
#
|
58
|
+
# Check if event is echo.
|
59
|
+
#
|
60
|
+
# @param [Hash] payload Request payload from facebook.
|
61
|
+
#
|
62
|
+
# @return [Boolean] If event is echo return true else false.
|
63
|
+
#
|
42
64
|
def self.payload_is_echo?(payload)
|
43
65
|
payload.key?('message') && payload['message']['is_echo'] == true
|
44
66
|
end
|
45
67
|
|
68
|
+
#
|
69
|
+
# Class UnknownPayload provides errors related to incoming messages.
|
70
|
+
#
|
46
71
|
class UnknownPayload < Facebook::Messenger::Error; end
|
47
72
|
end
|
48
73
|
end
|
@@ -1,18 +1,24 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
+
#
|
4
5
|
# The AccountLinking class represents an incoming Facebook Messenger
|
5
6
|
# Account Linking webhook, when the Linked Account
|
6
7
|
# or Unlink Account call-to-action have been tapped
|
7
8
|
#
|
8
9
|
# https://developers.facebook.com/docs/messenger-platform/webhook-reference/account-linking
|
10
|
+
#
|
9
11
|
class AccountLinking
|
10
12
|
include Facebook::Messenger::Incoming::Common
|
11
13
|
|
14
|
+
# Return String defining whether account in linked or not.
|
15
|
+
#
|
16
|
+
# @return [String] linked/unlinked.
|
12
17
|
def status
|
13
18
|
@messaging['account_linking']['status']
|
14
19
|
end
|
15
20
|
|
21
|
+
# The authorization code allows to match business user entity to PSID.
|
16
22
|
def authorization_code
|
17
23
|
@messaging['account_linking']['authorization_code']
|
18
24
|
end
|
@@ -1,26 +1,73 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
+
#
|
4
5
|
# Common attributes for all incoming data from Facebook.
|
6
|
+
#
|
5
7
|
module Common
|
6
8
|
attr_reader :messaging
|
7
9
|
|
10
|
+
#
|
11
|
+
# Assign message to instance variable
|
12
|
+
#
|
13
|
+
# @param [Object] messaging Object of message.
|
14
|
+
#
|
8
15
|
def initialize(messaging)
|
9
16
|
@messaging = messaging
|
10
17
|
end
|
11
18
|
|
19
|
+
#
|
20
|
+
# Function return PSID of sender.
|
21
|
+
# @see https://developers.facebook.com/docs/messenger-platform/identity
|
22
|
+
# Info about PSID.
|
23
|
+
# @see https://developers.facebook.com/docs/messenger-platform/webhook#format
|
24
|
+
# Webhook event format.
|
25
|
+
#
|
26
|
+
# @return [String] PSID of sender.
|
27
|
+
#
|
12
28
|
def sender
|
13
29
|
@messaging['sender']
|
14
30
|
end
|
15
31
|
|
32
|
+
#
|
33
|
+
# Function return the page of id from which the message is arrived.
|
34
|
+
#
|
35
|
+
# @return [String] Facebook page id.
|
36
|
+
#
|
16
37
|
def recipient
|
17
38
|
@messaging['recipient']
|
18
39
|
end
|
19
40
|
|
41
|
+
#
|
42
|
+
# If the user responds to your message, the appropriate event
|
43
|
+
# (messages, messaging_postbacks, etc.) will be sent to your webhook,
|
44
|
+
# with a prior_message object appended. The prior_message object
|
45
|
+
# includes the source of the message the user is responding to, as well
|
46
|
+
# as the user_ref used for the original message send.
|
47
|
+
#
|
48
|
+
# @return [Hash] The 'prior_message' hash.
|
49
|
+
#
|
50
|
+
def prior_message
|
51
|
+
@messaging['prior_message']
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Function return timestamp when message is sent.
|
56
|
+
#
|
57
|
+
#
|
58
|
+
# @return [Object] Message time sent.
|
59
|
+
#
|
20
60
|
def sent_at
|
21
61
|
Time.at(@messaging['timestamp'] / 1000)
|
22
62
|
end
|
23
63
|
|
64
|
+
#
|
65
|
+
# Function send sender_action of 'typing_on' to sender.
|
66
|
+
# @see https://developers.facebook.com/docs/messenger-platform/send-messages/sender-actions
|
67
|
+
# Info about sender actions.
|
68
|
+
#
|
69
|
+
# @return Send message to sender.
|
70
|
+
#
|
24
71
|
def typing_on
|
25
72
|
payload = {
|
26
73
|
recipient: sender,
|
@@ -30,6 +77,13 @@ module Facebook
|
|
30
77
|
Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
|
31
78
|
end
|
32
79
|
|
80
|
+
#
|
81
|
+
# Function send sender_action of 'typing_off' to sender.
|
82
|
+
# @see https://developers.facebook.com/docs/messenger-platform/send-messages/sender-actions
|
83
|
+
# Info about sender actions.
|
84
|
+
#
|
85
|
+
# @return Send message to sender.
|
86
|
+
#
|
33
87
|
def typing_off
|
34
88
|
payload = {
|
35
89
|
recipient: sender,
|
@@ -39,6 +93,13 @@ module Facebook
|
|
39
93
|
Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
|
40
94
|
end
|
41
95
|
|
96
|
+
#
|
97
|
+
# Function send sender_action of 'mark_seen' to sender.
|
98
|
+
# @see https://developers.facebook.com/docs/messenger-platform/send-messages/sender-actions
|
99
|
+
# Info about sender actions.
|
100
|
+
#
|
101
|
+
# @return Send message to sender.
|
102
|
+
#
|
42
103
|
def mark_seen
|
43
104
|
payload = {
|
44
105
|
recipient: sender,
|
@@ -48,15 +109,28 @@ module Facebook
|
|
48
109
|
Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
|
49
110
|
end
|
50
111
|
|
112
|
+
#
|
113
|
+
# Send reply to sender.
|
114
|
+
#
|
115
|
+
# @param [Hash] message Hash defining the message.
|
116
|
+
#
|
117
|
+
# @return Send reply to sender.
|
118
|
+
#
|
51
119
|
def reply(message)
|
52
120
|
payload = {
|
53
121
|
recipient: sender,
|
54
|
-
message: message
|
122
|
+
message: message,
|
123
|
+
message_type: Facebook::Messenger::Bot::MessageType::RESPONSE
|
55
124
|
}
|
56
125
|
|
57
126
|
Facebook::Messenger::Bot.deliver(payload, access_token: access_token)
|
58
127
|
end
|
59
128
|
|
129
|
+
#
|
130
|
+
# Function returns the configured access token.
|
131
|
+
#
|
132
|
+
# @return [String] Access token.
|
133
|
+
#
|
60
134
|
def access_token
|
61
135
|
Facebook::Messenger.config.provider.access_token_for(recipient)
|
62
136
|
end
|
@@ -2,6 +2,7 @@ module Facebook
|
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
4
|
# The Delivery class represents the receipt of a delivered message.
|
5
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/message-deliveries
|
5
6
|
class Delivery
|
6
7
|
include Facebook::Messenger::Incoming::Common
|
7
8
|
|
@@ -1,12 +1,24 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
module Incoming
|
4
|
-
#
|
4
|
+
#
|
5
|
+
# Message class represents an incoming Facebook Messenger message event.
|
6
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messages
|
7
|
+
#
|
5
8
|
class Message
|
6
9
|
include Facebook::Messenger::Incoming::Common
|
7
10
|
|
11
|
+
#
|
12
|
+
# @return [Array] Supported attachments for message.
|
8
13
|
ATTACHMENT_TYPES = %w[image audio video file location fallback].freeze
|
9
14
|
|
15
|
+
#
|
16
|
+
# Function returns unique id of message
|
17
|
+
# @see https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messages
|
18
|
+
# Info about received message format.
|
19
|
+
#
|
20
|
+
# @return [String] Unique id of message.
|
21
|
+
#
|
10
22
|
def id
|
11
23
|
@messaging['message']['mid']
|
12
24
|
end
|
@@ -15,34 +27,85 @@ module Facebook
|
|
15
27
|
@messaging['message']['seq']
|
16
28
|
end
|
17
29
|
|
30
|
+
#
|
31
|
+
# Function returns text of message
|
32
|
+
#
|
33
|
+
# @return [String] Text of message.
|
34
|
+
#
|
18
35
|
def text
|
19
36
|
@messaging['message']['text']
|
20
37
|
end
|
21
38
|
|
39
|
+
#
|
40
|
+
# Whether message is echo or not?
|
41
|
+
#
|
42
|
+
# @return [Boolean] If message is echo return true else false.
|
43
|
+
#
|
22
44
|
def echo?
|
23
45
|
@messaging['message']['is_echo']
|
24
46
|
end
|
25
47
|
|
48
|
+
#
|
49
|
+
# Function returns array containing attachment data
|
50
|
+
# @see https://developers.facebook.com/docs/messenger-platform/send-messages#sending_attachments
|
51
|
+
# More info about attachments.
|
52
|
+
#
|
53
|
+
# @return [Array] Attachment data.
|
54
|
+
#
|
26
55
|
def attachments
|
27
56
|
@messaging['message']['attachments']
|
28
57
|
end
|
29
58
|
|
59
|
+
#
|
60
|
+
# If facebook messenger built-in NLP is enabled, message will
|
61
|
+
# contain 'nlp' key in response.
|
62
|
+
# @see https://developers.facebook.com/docs/messenger-platform/built-in-nlp
|
63
|
+
# More information about built-in NLP.
|
64
|
+
#
|
65
|
+
#
|
66
|
+
# @return [Hash] NLP information about message.
|
67
|
+
#
|
68
|
+
def nlp
|
69
|
+
@messaging['message']['nlp']
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Function return app id from message.
|
74
|
+
#
|
75
|
+
# @return [String] App ID.
|
76
|
+
#
|
30
77
|
def app_id
|
31
78
|
@messaging['message']['app_id']
|
32
79
|
end
|
33
80
|
|
81
|
+
#
|
82
|
+
# This meta programming defines function for
|
83
|
+
# every attachment type to check whether the attachment
|
84
|
+
# in message is of defined type or not.
|
85
|
+
#
|
34
86
|
ATTACHMENT_TYPES.each do |attachment_type|
|
35
87
|
define_method "#{attachment_type}_attachment?" do
|
36
88
|
attachment_type?(attachment_type)
|
37
89
|
end
|
38
90
|
end
|
39
91
|
|
92
|
+
#
|
93
|
+
# Get the type of attachment in message.
|
94
|
+
#
|
95
|
+
# @return [String] Attachment type.
|
96
|
+
#
|
40
97
|
def attachment_type
|
41
98
|
return if attachments.nil?
|
42
99
|
|
43
100
|
attachments.first['type']
|
44
101
|
end
|
45
102
|
|
103
|
+
#
|
104
|
+
# Get the URL of attachment in message.
|
105
|
+
# URL is only available for attachments of type image/audio/video/file.
|
106
|
+
#
|
107
|
+
# @return [String] URL of attachment.
|
108
|
+
#
|
46
109
|
def attachment_url
|
47
110
|
return if attachments.nil?
|
48
111
|
return unless %w[image audio video file].include? attachment_type
|
@@ -50,6 +113,12 @@ module Facebook
|
|
50
113
|
attachments.first['payload']['url']
|
51
114
|
end
|
52
115
|
|
116
|
+
#
|
117
|
+
# Get the location coordinates if attachment type is 'location'.
|
118
|
+
# @example [LATITUDE, LONGITUDE]
|
119
|
+
#
|
120
|
+
# @return [Array] Location coordinates.
|
121
|
+
#
|
53
122
|
def location_coordinates
|
54
123
|
return [] unless attachment_type?('location')
|
55
124
|
|
@@ -57,14 +126,30 @@ module Facebook
|
|
57
126
|
[coordinates_data['lat'], coordinates_data['long']]
|
58
127
|
end
|
59
128
|
|
129
|
+
#
|
130
|
+
# Get the payload of quick reply.
|
131
|
+
# @see https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies
|
132
|
+
# More info about quick reply.
|
133
|
+
#
|
134
|
+
# @return [String] Payload string.
|
135
|
+
#
|
60
136
|
def quick_reply
|
61
137
|
return unless @messaging['message']['quick_reply']
|
62
138
|
|
63
139
|
@messaging['message']['quick_reply']['payload']
|
64
140
|
end
|
65
141
|
|
142
|
+
# @private
|
66
143
|
private
|
67
144
|
|
145
|
+
#
|
146
|
+
# Check if attachment in message is of given type or not?
|
147
|
+
#
|
148
|
+
# @param [String] attachment_type Attachment type
|
149
|
+
#
|
150
|
+
# @return [Boolean] If type of attachment in message
|
151
|
+
# and provided attachment type are same then return true else false.
|
152
|
+
#
|
68
153
|
def attachment_type?(attachment_type)
|
69
154
|
!attachments.nil? && attachments.first['type'] == attachment_type
|
70
155
|
end
|