facebook-messenger 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4cc6286ba13cf8c0c5239c5c50645cfce5af44c6
4
- data.tar.gz: 1c8ab52a23996258d2f4db0254424727471c8c3e
3
+ metadata.gz: 55e300c4f11036d518035144eaf94581e5e99ce5
4
+ data.tar.gz: ca59746d98d4fab7f37284468fe57c6cf6414106
5
5
  SHA512:
6
- metadata.gz: 0ecf386733c99eea428f1704d569703a8f2959412e4bde1139a0d64c5e4dc94d31d34ad9daeb95bd00dfd82de0af35128d7a9a011ffb9c41cc527dfa9c47b569
7
- data.tar.gz: 09382794eb526905b5aa4d809156f05ac5dad9794ab920977dc1cb6ff98b47f954a4e0a350cdb86a1555731943ce195cad2fbd543dded414708a904aa1ee36fc
6
+ metadata.gz: 3b3e31067f8f111b86d712d68566b8f6de895ccd016a71d47b8ccc9b6a886cd99a1e84db20ec2860f006903b63cef874656a0cfc383cc0b7d6f728b32df9022c
7
+ data.tar.gz: 3dc23071c67f9060f27125646afb8236c5cac30b101311ac880242611b141a80ff31012642ff04e89a93a6d100e8d7498713a565dedb91d39748810ea579564e
@@ -52,6 +52,7 @@ module Facebook
52
52
  when Incoming::Delivery then trigger(:delivery, callback)
53
53
  when Incoming::Postback then trigger(:postback, callback)
54
54
  when Incoming::Optin then trigger(:optin, callback)
55
+ when Incoming::Read then trigger(:read, callback)
55
56
  end
56
57
  end
57
58
 
@@ -2,6 +2,7 @@ require 'facebook/messenger/incoming/message'
2
2
  require 'facebook/messenger/incoming/delivery'
3
3
  require 'facebook/messenger/incoming/postback'
4
4
  require 'facebook/messenger/incoming/optin'
5
+ require 'facebook/messenger/incoming/read'
5
6
 
6
7
  module Facebook
7
8
  module Messenger
@@ -12,7 +13,8 @@ module Facebook
12
13
  'message' => Message,
13
14
  'delivery' => Delivery,
14
15
  'postback' => Postback,
15
- 'optin' => Optin
16
+ 'optin' => Optin,
17
+ 'read' => Read
16
18
  }.freeze
17
19
 
18
20
  # Parse the given payload.
@@ -0,0 +1,30 @@
1
+ module Facebook
2
+ module Messenger
3
+ module Incoming
4
+ # The Read class represents the user reading a delivered message.
5
+ class Read
6
+ attr_reader :messaging
7
+
8
+ def initialize(messaging)
9
+ @messaging = messaging
10
+ end
11
+
12
+ def at
13
+ Time.at(@messaging['read']['watermark'] / 1000)
14
+ end
15
+
16
+ def seq
17
+ @messaging['read']['seq']
18
+ end
19
+
20
+ def sender
21
+ @messaging['sender']
22
+ end
23
+
24
+ def recipient
25
+ @messaging['recipient']
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,6 +4,8 @@ require 'openssl'
4
4
 
5
5
  module Facebook
6
6
  module Messenger
7
+ class BadRequestError < Error; end
8
+
7
9
  # This module holds the server that processes incoming messages from the
8
10
  # Facebook Messenger Platform.
9
11
  class Server
@@ -15,9 +17,12 @@ module Facebook
15
17
  @request = Rack::Request.new(env)
16
18
  @response = Rack::Response.new
17
19
 
18
- if @request.get? then verify
19
- elsif @request.post? then receive
20
- else @response.status = 405
20
+ if @request.get?
21
+ verify
22
+ elsif @request.post?
23
+ receive
24
+ else
25
+ @response.status = 405
21
26
  end
22
27
 
23
28
  @response.finish
@@ -38,46 +43,74 @@ module Facebook
38
43
  end
39
44
 
40
45
  def receive
41
- return if app_secret && !integrity?
46
+ body = @request.body.read
42
47
 
43
- hash = JSON.parse(@request.body.read)
48
+ check_integrity(body) if app_secret
44
49
 
45
- # Facebook may batch several items in the 'entry' array during
46
- # periods of high load.
47
- hash['entry'].each do |entry|
48
- # Facebook may batch several items in the 'messaging' array during
49
- # periods of high load.
50
- entry['messaging'].each do |messaging|
51
- Facebook::Messenger::Bot.receive(messaging)
52
- end
53
- end
50
+ events = parse_events(body)
51
+
52
+ trigger_events(events)
53
+ rescue BadRequestError => error
54
+ respond_with_error(error)
54
55
  end
55
56
 
56
- def integrity?
57
- Rack::Utils.secure_compare(x_hub_signature, signature)
57
+ WARNING = 'The X-Hub-Signature header is not present in the request. ' \
58
+ 'This is expected for the first webhook requests. If this ' \
59
+ 'continues after some time, check your app\'s secret token.'.freeze
60
+
61
+ def check_integrity(body)
62
+ x_hub_signature = @request.env['HTTP_X_HUB_SIGNATURE'.freeze].to_s
63
+
64
+ unless x_hub_signature.start_with?('sha1='.freeze)
65
+ $stderr.puts(WARNING)
66
+
67
+ raise BadRequestError, 'Error getting integrity signature'.freeze
68
+ end
69
+
70
+ unless secure_compare(x_hub_signature, signature(body))
71
+ raise BadRequestError, 'Error checking message integrity'.freeze
72
+ end
58
73
  end
59
74
 
60
- def x_hub_signature
61
- @request.env['HTTP_X_HUB_SIGNATURE'.freeze]
75
+ def secure_compare(x, y)
76
+ Rack::Utils.secure_compare(x, y)
62
77
  end
63
78
 
64
- def signature
65
- format('sha1=%s'.freeze, generate_hmac(@request.body.read))
66
- ensure
67
- @request.body.rewind
79
+ def signature(body)
80
+ format('sha1=%s'.freeze, generate_hmac(body))
68
81
  end
69
82
 
70
83
  def generate_hmac(content)
71
- OpenSSL::HMAC.hexdigest(
72
- OpenSSL::Digest.new('sha1'),
73
- app_secret,
74
- content
75
- )
84
+ OpenSSL::HMAC.hexdigest('sha1'.freeze, app_secret, content)
76
85
  end
77
86
 
78
87
  def app_secret
79
88
  Facebook::Messenger.config.app_secret
80
89
  end
90
+
91
+ def parse_events(body)
92
+ JSON.parse(body)
93
+ rescue JSON::ParserError
94
+ raise BadRequestError, 'Error parsing request body format'
95
+ end
96
+
97
+ def trigger_events(events)
98
+ # Facebook may batch several items in the 'entry' array during
99
+ # periods of high load.
100
+ events['entry'.freeze].each do |entry|
101
+ # Facebook may batch several items in the 'messaging' array during
102
+ # periods of high load.
103
+ entry['messaging'.freeze].each do |messaging|
104
+ Facebook::Messenger::Bot.receive(messaging)
105
+ end
106
+ end
107
+ end
108
+
109
+ def respond_with_error(error)
110
+ @response.status = 400
111
+ @response.write(error.message)
112
+ @response.headers['Content-Type'.freeze] = 'text/plain'.freeze
113
+ end
81
114
  end
82
115
  end
83
116
  end
@@ -1,5 +1,5 @@
1
1
  module Facebook
2
2
  module Messenger
3
- VERSION = '0.5.0'.freeze
3
+ VERSION = '0.6.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.5.0
4
+ version: 0.6.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-26 00:00:00.000000000 Z
11
+ date: 2016-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -169,6 +169,7 @@ files:
169
169
  - lib/facebook/messenger/incoming/message.rb
170
170
  - lib/facebook/messenger/incoming/optin.rb
171
171
  - lib/facebook/messenger/incoming/postback.rb
172
+ - lib/facebook/messenger/incoming/read.rb
172
173
  - lib/facebook/messenger/server.rb
173
174
  - lib/facebook/messenger/subscriptions.rb
174
175
  - lib/facebook/messenger/version.rb