facebook-messenger 0.4.2 → 0.5.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 +24 -9
- data/lib/facebook/messenger.rb +6 -2
- data/lib/facebook/messenger/bot.rb +6 -6
- data/lib/facebook/messenger/configuration.rb +4 -5
- data/lib/facebook/messenger/incoming/delivery.rb +9 -7
- data/lib/facebook/messenger/incoming/message.rb +13 -7
- data/lib/facebook/messenger/incoming/optin.rb +8 -6
- data/lib/facebook/messenger/incoming/postback.rb +8 -6
- data/lib/facebook/messenger/server.rb +35 -5
- data/lib/facebook/messenger/subscriptions.rb +17 -9
- data/lib/facebook/messenger/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cc6286ba13cf8c0c5239c5c50645cfce5af44c6
|
4
|
+
data.tar.gz: 1c8ab52a23996258d2f4db0254424727471c8c3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ecf386733c99eea428f1704d569703a8f2959412e4bde1139a0d64c5e4dc94d31d34ad9daeb95bd00dfd82de0af35128d7a9a011ffb9c41cc527dfa9c47b569
|
7
|
+
data.tar.gz: 09382794eb526905b5aa4d809156f05ac5dad9794ab920977dc1cb6ff98b47f954a4e0a350cdb86a1555731943ce195cad2fbd543dded414708a904aa1ee36fc
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
[![Dependency Status](https://img.shields.io/gemnasium/hyperoslo/facebook-messenger.svg?style=flat)](https://gemnasium.com/hyperoslo/facebook-messenger)
|
9
9
|
[![Code Climate](https://img.shields.io/codeclimate/github/hyperoslo/facebook-messenger.svg?style=flat)](https://codeclimate.com/github/hyperoslo/facebook-messenger)
|
10
10
|
[![Coverage Status](https://img.shields.io/coveralls/hyperoslo/facebook-messenger.svg?style=flat)](https://coveralls.io/r/hyperoslo/facebook-messenger)
|
11
|
+
[![Join the chat at https://gitter.im/hyperoslo/facebook-messenger](https://badges.gitter.im/hyperoslo/facebook-messenger.svg)](https://gitter.im/hyperoslo/facebook-messenger?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
11
12
|
|
12
13
|
## Installation
|
13
14
|
|
@@ -26,11 +27,12 @@ require 'facebook/messenger'
|
|
26
27
|
include Facebook::Messenger
|
27
28
|
|
28
29
|
Bot.on :message do |message|
|
29
|
-
message.id
|
30
|
-
message.sender
|
31
|
-
message.seq
|
32
|
-
message.sent_at
|
33
|
-
message.text
|
30
|
+
message.id # => 'mid.1457764197618:41d102a3e1ae206a38'
|
31
|
+
message.sender # => { 'id' => '1008372609250235' }
|
32
|
+
message.seq # => 73
|
33
|
+
message.sent_at # => 2016-04-22 21:30:36 +0200
|
34
|
+
message.text # => 'Hello, bot!'
|
35
|
+
message.attachments # => [ { 'type' => 'image', 'payload' => { 'url' => 'https://www.example.com/1.jpg' } } ]
|
34
36
|
|
35
37
|
Bot.deliver(
|
36
38
|
recipient: message.sender,
|
@@ -129,9 +131,7 @@ Bot.on :optin do |optin|
|
|
129
131
|
optin.ref # => 'CONTACT_SKYNET'
|
130
132
|
|
131
133
|
Bot.deliver(
|
132
|
-
recipient:
|
133
|
-
id: '45123'
|
134
|
-
},
|
134
|
+
recipient: optin.sender,
|
135
135
|
message: {
|
136
136
|
text: 'Ah, human!'
|
137
137
|
}
|
@@ -169,13 +169,24 @@ token of your choosing.
|
|
169
169
|
|
170
170
|
Use the generated access token and your verify token to configure your bot:
|
171
171
|
|
172
|
+
##### ... pass a block, or
|
173
|
+
|
172
174
|
```ruby
|
173
175
|
Facebook::Messenger.configure do |config|
|
174
176
|
config.access_token = 'EAAG6WgW...'
|
177
|
+
config.app_secret = '__app_secret_here__'
|
175
178
|
config.verify_token = 'my_voice_is_my_password_verify_me'
|
176
179
|
end
|
177
180
|
```
|
178
181
|
|
182
|
+
##### ... set directly
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
Facebook::Messenger.config.access_token = 'EAAG6WgW...'
|
186
|
+
Facebook::Messenger.config.app_secret = '__app_secret_here__'
|
187
|
+
Facebook::Messenger.config.verify_token = 'my_voice_is_my_password_verify_me'
|
188
|
+
```
|
189
|
+
|
179
190
|
### Subscribe your Application to a Page
|
180
191
|
|
181
192
|
Once you've configured your bot, subscribe it to the Page to get messages
|
@@ -243,11 +254,14 @@ reference constants. You'll need to explicitly load `app/bot`, then:
|
|
243
254
|
|
244
255
|
```ruby
|
245
256
|
# config/initializers/bot.rb
|
246
|
-
|
257
|
+
unless Rails.env.production?
|
247
258
|
Dir["#{Rails.root}/app/bot/**/*.rb"].each { |file| require file }
|
248
259
|
end
|
249
260
|
```
|
250
261
|
|
262
|
+
To test your locally running bot, you can use [ngrok]. This will create a secure
|
263
|
+
tunnel to localhost so that Facebook can reach the webhook.
|
264
|
+
|
251
265
|
## Development
|
252
266
|
|
253
267
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run
|
@@ -280,3 +294,4 @@ If you're using Facebook Messenger, we probably want to [hire you].
|
|
280
294
|
[developers.facebook.com]: https://developers.facebook.com/
|
281
295
|
[rack]: https://github.com/rack/rack
|
282
296
|
[send-to-messenger-plugin]: https://developers.facebook.com/docs/messenger-platform/plugin-reference
|
297
|
+
[ngrok]: https://ngrok.com/
|
data/lib/facebook/messenger.rb
CHANGED
@@ -10,11 +10,15 @@ module Facebook
|
|
10
10
|
# All the code for this gem resides in this module.
|
11
11
|
module Messenger
|
12
12
|
def self.configure
|
13
|
-
yield
|
13
|
+
yield config
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.config
|
17
|
-
Configuration
|
17
|
+
@config ||= Configuration.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.config=(config)
|
21
|
+
@config = config
|
18
22
|
end
|
19
23
|
|
20
24
|
configure do |config|
|
@@ -45,13 +45,13 @@ module Facebook
|
|
45
45
|
#
|
46
46
|
# * https://developers.facebook.com/docs/messenger-platform/webhook-reference
|
47
47
|
def receive(payload)
|
48
|
-
|
48
|
+
callback = Facebook::Messenger::Incoming.parse(payload)
|
49
49
|
|
50
|
-
case
|
51
|
-
when Incoming::Message then trigger(:message,
|
52
|
-
when Incoming::Delivery then trigger(:delivery,
|
53
|
-
when Incoming::Postback then trigger(:postback,
|
54
|
-
when Incoming::Optin then trigger(:optin,
|
50
|
+
case callback
|
51
|
+
when Incoming::Message then trigger(:message, callback)
|
52
|
+
when Incoming::Delivery then trigger(:delivery, callback)
|
53
|
+
when Incoming::Postback then trigger(:postback, callback)
|
54
|
+
when Incoming::Optin then trigger(:optin, callback)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module Facebook
|
2
2
|
module Messenger
|
3
3
|
# This module holds the configuration.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :access_token
|
6
|
+
attr_accessor :app_secret
|
7
|
+
attr_accessor :verify_token
|
9
8
|
end
|
10
9
|
end
|
11
10
|
end
|
@@ -3,28 +3,30 @@ module Facebook
|
|
3
3
|
module Incoming
|
4
4
|
# The Delivery class represents the receipt of a delivered message.
|
5
5
|
class Delivery
|
6
|
-
|
7
|
-
|
6
|
+
attr_reader :messaging
|
7
|
+
|
8
|
+
def initialize(messaging)
|
9
|
+
@messaging = messaging
|
8
10
|
end
|
9
11
|
|
10
12
|
def ids
|
11
|
-
@
|
13
|
+
@messaging['delivery']['mids']
|
12
14
|
end
|
13
15
|
|
14
16
|
def at
|
15
|
-
Time.at(@
|
17
|
+
Time.at(@messaging['delivery']['watermark'] / 1000)
|
16
18
|
end
|
17
19
|
|
18
20
|
def seq
|
19
|
-
@
|
21
|
+
@messaging['delivery']['seq']
|
20
22
|
end
|
21
23
|
|
22
24
|
def sender
|
23
|
-
@
|
25
|
+
@messaging['sender']
|
24
26
|
end
|
25
27
|
|
26
28
|
def recipient
|
27
|
-
@
|
29
|
+
@messaging['recipient']
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -3,28 +3,34 @@ module Facebook
|
|
3
3
|
module Incoming
|
4
4
|
# The Message class represents an incoming Facebook Messenger message.
|
5
5
|
class Message
|
6
|
-
|
7
|
-
|
6
|
+
attr_reader :messaging
|
7
|
+
|
8
|
+
def initialize(messaging)
|
9
|
+
@messaging = messaging
|
8
10
|
end
|
9
11
|
|
10
12
|
def id
|
11
|
-
@
|
13
|
+
@messaging['message']['mid']
|
12
14
|
end
|
13
15
|
|
14
16
|
def sender
|
15
|
-
@
|
17
|
+
@messaging['sender']
|
16
18
|
end
|
17
19
|
|
18
20
|
def seq
|
19
|
-
@
|
21
|
+
@messaging['message']['seq']
|
20
22
|
end
|
21
23
|
|
22
24
|
def sent_at
|
23
|
-
Time.at(@
|
25
|
+
Time.at(@messaging['timestamp'] / 1000)
|
24
26
|
end
|
25
27
|
|
26
28
|
def text
|
27
|
-
@
|
29
|
+
@messaging['message']['text']
|
30
|
+
end
|
31
|
+
|
32
|
+
def attachments
|
33
|
+
@messaging['message']['attachments']
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
@@ -6,24 +6,26 @@ module Facebook
|
|
6
6
|
#
|
7
7
|
# https://developers.facebook.com/docs/messenger-platform/plugin-reference
|
8
8
|
class Optin
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :messaging
|
10
|
+
|
11
|
+
def initialize(messaging)
|
12
|
+
@messaging = messaging
|
11
13
|
end
|
12
14
|
|
13
15
|
def sender
|
14
|
-
@
|
16
|
+
@messaging['sender']
|
15
17
|
end
|
16
18
|
|
17
19
|
def recipient
|
18
|
-
@
|
20
|
+
@messaging['recipient']
|
19
21
|
end
|
20
22
|
|
21
23
|
def sent_at
|
22
|
-
Time.at(@
|
24
|
+
Time.at(@messaging['timestamp'] / 1000)
|
23
25
|
end
|
24
26
|
|
25
27
|
def ref
|
26
|
-
@
|
28
|
+
@messaging['optin']['ref']
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -3,24 +3,26 @@ module Facebook
|
|
3
3
|
module Incoming
|
4
4
|
# The Postback class represents an incoming Facebook Messenger postback.
|
5
5
|
class Postback
|
6
|
-
|
7
|
-
|
6
|
+
attr_reader :messaging
|
7
|
+
|
8
|
+
def initialize(messaging)
|
9
|
+
@messaging = messaging
|
8
10
|
end
|
9
11
|
|
10
12
|
def sender
|
11
|
-
@
|
13
|
+
@messaging['sender']
|
12
14
|
end
|
13
15
|
|
14
16
|
def recipient
|
15
|
-
@
|
17
|
+
@messaging['recipient']
|
16
18
|
end
|
17
19
|
|
18
20
|
def sent_at
|
19
|
-
Time.at(@
|
21
|
+
Time.at(@messaging['timestamp'] / 1000)
|
20
22
|
end
|
21
23
|
|
22
24
|
def payload
|
23
|
-
@
|
25
|
+
@messaging['postback']['payload']
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'json'
|
3
|
+
require 'openssl'
|
3
4
|
|
4
5
|
module Facebook
|
5
6
|
module Messenger
|
@@ -14,18 +15,19 @@ module Facebook
|
|
14
15
|
@request = Rack::Request.new(env)
|
15
16
|
@response = Rack::Response.new
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
when @request.post? then receive
|
18
|
+
if @request.get? then verify
|
19
|
+
elsif @request.post? then receive
|
20
20
|
else @response.status = 405
|
21
21
|
end
|
22
22
|
|
23
23
|
@response.finish
|
24
24
|
end
|
25
25
|
|
26
|
+
private
|
27
|
+
|
26
28
|
def verify
|
27
|
-
if @request['hub.verify_token'] == verify_token
|
28
|
-
@response.write @request['hub.challenge']
|
29
|
+
if @request.params['hub.verify_token'] == verify_token
|
30
|
+
@response.write @request.params['hub.challenge']
|
29
31
|
else
|
30
32
|
@response.write 'Error; wrong verify token'
|
31
33
|
end
|
@@ -36,6 +38,8 @@ module Facebook
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def receive
|
41
|
+
return if app_secret && !integrity?
|
42
|
+
|
39
43
|
hash = JSON.parse(@request.body.read)
|
40
44
|
|
41
45
|
# Facebook may batch several items in the 'entry' array during
|
@@ -48,6 +52,32 @@ module Facebook
|
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
55
|
+
|
56
|
+
def integrity?
|
57
|
+
Rack::Utils.secure_compare(x_hub_signature, signature)
|
58
|
+
end
|
59
|
+
|
60
|
+
def x_hub_signature
|
61
|
+
@request.env['HTTP_X_HUB_SIGNATURE'.freeze]
|
62
|
+
end
|
63
|
+
|
64
|
+
def signature
|
65
|
+
format('sha1=%s'.freeze, generate_hmac(@request.body.read))
|
66
|
+
ensure
|
67
|
+
@request.body.rewind
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_hmac(content)
|
71
|
+
OpenSSL::HMAC.hexdigest(
|
72
|
+
OpenSSL::Digest.new('sha1'),
|
73
|
+
app_secret,
|
74
|
+
content
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def app_secret
|
79
|
+
Facebook::Messenger.config.app_secret
|
80
|
+
end
|
51
81
|
end
|
52
82
|
end
|
53
83
|
end
|
@@ -8,30 +8,38 @@ module Facebook
|
|
8
8
|
|
9
9
|
base_uri 'https://graph.facebook.com/v2.6/me'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
format :json
|
12
|
+
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def subscribe
|
16
|
+
response = post '/subscribed_apps'
|
15
17
|
|
16
18
|
raise_errors(response)
|
17
19
|
|
18
20
|
true
|
19
21
|
end
|
20
22
|
|
21
|
-
def
|
22
|
-
response = delete '/subscribed_apps'
|
23
|
-
access_token: Facebook::Messenger.config.access_token
|
24
|
-
}
|
23
|
+
def unsubscribe
|
24
|
+
response = delete '/subscribed_apps'
|
25
25
|
|
26
26
|
raise_errors(response)
|
27
27
|
|
28
28
|
true
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def raise_errors(response)
|
32
32
|
raise Error, response['error']['message'] if response.key? 'error'
|
33
33
|
end
|
34
34
|
|
35
|
+
def default_options
|
36
|
+
super.merge(
|
37
|
+
query: {
|
38
|
+
access_token: Facebook::Messenger.config.access_token
|
39
|
+
}
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
35
43
|
class Error < Facebook::Messenger::Error; end
|
36
44
|
end
|
37
45
|
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.
|
4
|
+
version: 0.5.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-05-
|
11
|
+
date: 2016-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -28,14 +28,14 @@ dependencies:
|
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.6.4
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.6.4
|
41
41
|
- !ruby/object:Gem::Dependency
|