messenger-ruby 0.1.0 → 1.0.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/.codeclimate.yml +9 -0
- data/.gitignore +4 -0
- data/README.md +392 -7
- data/Rakefile +1 -1
- data/app/controllers/messenger/messenger_controller.rb +45 -0
- data/bin/console +1 -1
- data/circle.yml +6 -0
- data/config/routes.rb +8 -0
- data/lib/messenger-ruby.rb +41 -0
- data/lib/messenger/client.rb +20 -0
- data/lib/messenger/components/attachment.rb +35 -0
- data/lib/messenger/components/element.rb +13 -0
- data/lib/messenger/components/elements/bubble.rb +19 -0
- data/lib/messenger/components/elements/button.rb +23 -0
- data/lib/messenger/components/elements/image.rb +14 -0
- data/lib/messenger/components/elements/receipt/address.rb +16 -0
- data/lib/messenger/components/elements/receipt/adjustment.rb +12 -0
- data/lib/messenger/components/elements/receipt/item.rb +16 -0
- data/lib/messenger/components/elements/receipt/order.rb +15 -0
- data/lib/messenger/components/elements/receipt/summary.rb +14 -0
- data/lib/messenger/components/elements/text.rb +13 -0
- data/lib/messenger/components/templates/buttons.rb +16 -0
- data/lib/messenger/components/templates/generic.rb +15 -0
- data/lib/messenger/components/templates/receipt.rb +36 -0
- data/lib/messenger/engine.rb +7 -0
- data/lib/messenger/params.rb +43 -0
- data/lib/messenger/request.rb +24 -0
- data/lib/messenger/version.rb +1 -1
- data/messenger-ruby.gemspec +8 -1
- metadata +113 -7
- data/lib/messenger.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0002a8167648af1651c41031ec1b600947c5fd7
|
4
|
+
data.tar.gz: 399edaa10c599c990ce954a737ee81165548d4fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff5cc415b65f152f1142bd1ebff07c529e35113b00bcf7b25b5a8f3c8ac29944c0a8f3a924852eccaa91ee383b37a2e2c341b50649d6b22a4738658f540e2821
|
7
|
+
data.tar.gz: d23051ac1715597ae5e51d95881fa9337e932f0bdfdc19e5086631c902a473eeb9798976cf9859297bb5e7ad185776a9c6b8fa2aee565477a75937ddabf11bbf
|
data/.codeclimate.yml
ADDED
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
# messenger-ruby
|
2
|
+
[](https://rubygems.org/gems/messenger-ruby)
|
3
|
+
[](https://circleci.com/gh/netguru/messenger-ruby)
|
4
|
+
[](https://codeclimate.com/github/netguru/messenger-ruby)
|
5
|
+
[](https://codeclimate.com/github/netguru/messenger-ruby)
|
6
|
+
|
7
|
+
A simple library for supporting implementation of [Facebook Messenger Bots](https://developers.facebook.com/products/messenger/).
|
2
8
|
|
3
9
|
## Installation
|
4
10
|
|
5
11
|
Add this line to your application's Gemfile:
|
6
12
|
|
7
13
|
```ruby
|
8
|
-
gem 'messenger-ruby'
|
14
|
+
gem 'messenger-ruby', git: 'https://github.com/netguru/messenger-ruby.git'
|
9
15
|
```
|
10
16
|
|
11
17
|
And then execute:
|
@@ -18,23 +24,402 @@ Or install it yourself as:
|
|
18
24
|
|
19
25
|
## Configuration
|
20
26
|
|
21
|
-
|
27
|
+
#### Facebook steps
|
28
|
+
|
29
|
+
* [create Facebook page](https://www.facebook.com/pages/create/) (skip if you want to use existing page)
|
30
|
+
* [create Facebook app](https://developers.facebook.com/quickstarts/?platform=web) (skip if you want to use existing app)
|
31
|
+
* go to [Facebook for Developers](https://developers.facebook.com/apps/) and get `Page Access Token` (step __3. Get Page Access Token__ from [this tutorial](https://developers.facebook.com/docs/messenger-platform/quickstart#steps]))
|
32
|
+
|
33
|
+
#### Initializer
|
34
|
+
|
35
|
+
Create `messenger.rb` initializer in you app directory and paste `Page Access Token` from previous step:
|
22
36
|
|
23
37
|
```ruby
|
24
|
-
#
|
38
|
+
# YOUR_APP/config/initializers/messenger.rb
|
25
39
|
Messenger.configure do |config|
|
26
|
-
config.verify_token = '
|
27
|
-
config.page_access_token = '
|
40
|
+
config.verify_token = '<VERIFY_TOKEN>' #will be used in webhook verifiction
|
41
|
+
config.page_access_token = '<PAGE_ACCESS_TOKEN>'
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
#### Routes
|
46
|
+
|
47
|
+
Add to your `routes.rb`:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# YOUR_APP/config/routes.rb
|
51
|
+
mount Messenger::Engine, at: "/messenger"
|
52
|
+
|
53
|
+
```
|
54
|
+
|
55
|
+
#### Controller
|
56
|
+
|
57
|
+
Create `messenger_controller.rb` in your controllers directory - controller has to inherit from `Messenger::MessengerController`:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
# YOUR_APP/app/controllers/messenger_controller.rb
|
61
|
+
class MessengerController < Messenger::MessengerController
|
62
|
+
def webhook
|
63
|
+
#logic here
|
64
|
+
render nothing: true, status: 200
|
65
|
+
end
|
28
66
|
end
|
29
67
|
```
|
30
68
|
|
69
|
+
`2XX` status is necessary to not clog your bot.
|
70
|
+
|
71
|
+
If you want your controller to be named differently, please update your `routes.rb` with appropriate route for `post /messenger/webhook` request.
|
72
|
+
|
73
|
+
#### Bot subscription
|
74
|
+
|
75
|
+
Run your application and:
|
76
|
+
* complete step __2. Setup Webhook__ from [this tutorial](https://developers.facebook.com/docs/messenger-platform/quickstart#steps) - _if you mounted `Messenger::Engine` at `/messenger` and your application can be found at `https://example.com`, your `Callback URL` will be `https://example.com/messenger/webhook`_
|
77
|
+
* visit `/messenger/subscribe` in your app (it's replacement for __[4. Subscribe the App to the Page](https://developers.facebook.com/docs/messenger-platform/quickstart#steps)__ step) - call `subscribe` action anytime you want to refresh subscription of your app
|
78
|
+
|
31
79
|
## Usage
|
32
80
|
|
33
|
-
|
81
|
+
To send message you need to create [Messenger::Request](#messengerrequest) with one of the available [components](#components) and pass it to [Messenger::Client](#messengerclient)::send method. You can send message only to users who subscribed to your page (e.g. sent some message before).
|
82
|
+
|
83
|
+
### Messenger::Request
|
84
|
+
|
85
|
+
It's used to build parameters for Facebook API. Requires [component](#components) and `recipient_id`.
|
86
|
+
|
87
|
+
Example usage:
|
88
|
+
```ruby
|
89
|
+
Messenger::Request.new(some_component, recipient_id)
|
90
|
+
```
|
91
|
+
|
92
|
+
### Messenger::Client
|
93
|
+
|
94
|
+
Sends requests to Facebook API. Has two methods:
|
95
|
+
* `get_user_profile` - requires id of existing facebook user
|
96
|
+
* `send` - requires [Messenger::Request](#messengerrequest) object
|
97
|
+
|
98
|
+
Example usage:
|
99
|
+
```ruby
|
100
|
+
Messenger::Client.get_user_profile(user_id) #=> hash with name, surname and profile picture
|
101
|
+
Messenger::Client.send(request) #=> hash with message details or exception if request is incorrect
|
102
|
+
```
|
103
|
+
|
104
|
+
Please note that unsuccessful `send` will be shown in logs as `Facebook API response from invalid request: ...`
|
105
|
+
|
106
|
+
### Elements
|
107
|
+
|
108
|
+
Elements can't be used outside of templates.
|
109
|
+
|
110
|
+
#### Button
|
111
|
+
|
112
|
+
Lives inside [Bubble](#bubble) element or [Button template](#button-template).
|
113
|
+
|
114
|
+
Attribute | Allowed values | Required?
|
115
|
+
--------- | -------------- | :--------:
|
116
|
+
type | `'web_url'`, `'postback'` | ✔
|
117
|
+
title | String | ✔
|
118
|
+
value | String | ✔
|
119
|
+
|
120
|
+
Example usage:
|
121
|
+
```ruby
|
122
|
+
Messenger::Elements::Button.new(type: 'web_url', title: 'Button', value: 'http://github.com')
|
123
|
+
```
|
124
|
+
|
125
|
+
#### Bubble
|
126
|
+
|
127
|
+
Part of [Generic template](#button-template).
|
128
|
+
|
129
|
+
Attribute | Allowed values | Required?
|
130
|
+
--------- | -------------- | :--------:
|
131
|
+
title | String | ✔
|
132
|
+
subtitle | String | ✔*
|
133
|
+
image_url | String | ✔*
|
134
|
+
buttons | [`Messenger::Elements::Button`](#button) objects array | ✔*
|
135
|
+
item_url | String | ✘
|
136
|
+
|
137
|
+
`*` - at least one of them is required
|
138
|
+
|
139
|
+
Example usage:
|
140
|
+
```ruby
|
141
|
+
Messenger::Elements::Bubble.new(title: 'First', subtitle: 'Bubble')
|
142
|
+
|
143
|
+
```
|
144
|
+
|
145
|
+
#### Address
|
146
|
+
|
147
|
+
Used by [Receipt template](#receipt-template).
|
148
|
+
|
149
|
+
Attribute | Allowed values | Required?
|
150
|
+
--------- | -------------- | :--------:
|
151
|
+
street_1 | String | ✔
|
152
|
+
street_2 | String | ✘
|
153
|
+
city | String | ✔
|
154
|
+
postal_code | String | ✔
|
155
|
+
state | String | ✔
|
156
|
+
country | String | ✔
|
157
|
+
|
158
|
+
Example usage:
|
159
|
+
```ruby
|
160
|
+
Messenger::Elements::Address.new(
|
161
|
+
street_1: 'Vachel Lindsay Dr',
|
162
|
+
street_2: '',
|
163
|
+
city: 'Springfield',
|
164
|
+
postal_code: '62701',
|
165
|
+
state: 'IL',
|
166
|
+
country:'USA'
|
167
|
+
)
|
168
|
+
```
|
169
|
+
|
170
|
+
#### Adjustment
|
171
|
+
|
172
|
+
Used by [Receipt template](#receipt-template).
|
173
|
+
|
174
|
+
Attribute | Allowed values | Required?
|
175
|
+
--------- | -------------- | :--------:
|
176
|
+
name | String | ✔
|
177
|
+
amount | Integer, greater than 0 | ✔
|
178
|
+
|
179
|
+
Example usage:
|
180
|
+
```ruby
|
181
|
+
Messenger::Elements::Adjustment.new(name: 'Adjustment 1', amount: 20)
|
182
|
+
```
|
183
|
+
|
184
|
+
#### Item
|
185
|
+
|
186
|
+
Used by [Receipt template](#receipt-template).
|
187
|
+
|
188
|
+
Attribute | Allowed values | Required?
|
189
|
+
--------- | -------------- | :--------:
|
190
|
+
title | String | ✔
|
191
|
+
subtilte | String | ✘
|
192
|
+
quantity | Integer | ✘
|
193
|
+
price | Decimal | ✘
|
194
|
+
currency | String, from _ISO 4217 Currency Codes_ | ✘
|
195
|
+
image_url | String | ✘
|
196
|
+
|
197
|
+
Example usage:
|
198
|
+
```ruby
|
199
|
+
Messenger::Elements::Item.new(
|
200
|
+
title: 'Cool Tshirt',
|
201
|
+
subtitle: 'XXL White',
|
202
|
+
quantity: 3,
|
203
|
+
price: 34,
|
204
|
+
currency: 'USD',
|
205
|
+
image_url: 'http://assets.servedby-buysellads.com/p/manage/asset/id/25397'
|
206
|
+
)
|
207
|
+
```
|
208
|
+
|
209
|
+
#### Order
|
210
|
+
|
211
|
+
Used by [Receipt template](#receipt-template).
|
212
|
+
|
213
|
+
Attribute | Allowed values | Required?
|
214
|
+
--------- | -------------- | :--------:
|
215
|
+
order_number | String, unique per conversation | ✔
|
216
|
+
currency | String, from _ISO 4217 Currency Codes_ | ✔
|
217
|
+
payment_method | String | ✔
|
218
|
+
timestamp | correct timestamp (String) | ✘
|
219
|
+
order_url | String | ✘
|
220
|
+
|
221
|
+
Example usage:
|
222
|
+
```ruby
|
223
|
+
Messenger::Elements::Order.new(
|
224
|
+
order_number: 'R190581345',
|
225
|
+
currency: 'USD',
|
226
|
+
payment_method: 'Visa',
|
227
|
+
timestamp: '1428444852',
|
228
|
+
order_url: 'http://petersapparel.parseapp.com/order?order_id=123456'
|
229
|
+
)
|
230
|
+
```
|
231
|
+
|
232
|
+
#### Summary
|
233
|
+
|
234
|
+
|
235
|
+
Used by [Receipt template](#receipt-template).
|
236
|
+
|
237
|
+
Attribute | Allowed values | Required?
|
238
|
+
--------- | -------------- | :--------:
|
239
|
+
subtotal | Decimal | ✘
|
240
|
+
shipping_cost | Decimal | ✘
|
241
|
+
total_tax | Decimal | ✘
|
242
|
+
total_cost | Decimal | ✔
|
243
|
+
|
244
|
+
Example usage:
|
245
|
+
```ruby
|
246
|
+
Messenger::Elements::Summary.new(subtotal: 70, shipping_cost: 20, total_tax: 10, total_cost: 100)
|
247
|
+
```
|
248
|
+
|
249
|
+
### Components
|
250
|
+
|
251
|
+
You can find more info about what can be send in [Messenger Platform Docs](https://developers.facebook.com/docs/messenger-platform/send-api-reference).
|
252
|
+
|
253
|
+
#### Text
|
254
|
+
|
255
|
+
Attribute | Allowed values | Required?
|
256
|
+
--------- | -------------- | :--------:
|
257
|
+
text | String | ✔
|
258
|
+
|
259
|
+
|
260
|
+
Here is complete example on how to send sample text to the user:
|
261
|
+
```ruby
|
262
|
+
if fb_params.message?
|
263
|
+
Messenger::Client.send(
|
264
|
+
Messenger::Request.new(
|
265
|
+
Messenger::Elements::Text.new(text: 'some text'),
|
266
|
+
fb_params.sender_id
|
267
|
+
)
|
268
|
+
)
|
269
|
+
end
|
270
|
+
|
271
|
+
#make sure to send 200 at the end
|
272
|
+
render nothing: true, status: 200
|
273
|
+
```
|
274
|
+
|
275
|
+
#### Image
|
276
|
+
|
277
|
+
Attribute | Allowed values | Required?
|
278
|
+
--------- | -------------- | :--------:
|
279
|
+
url | String | ✔
|
280
|
+
|
281
|
+
|
282
|
+
Sending images is simple as well:
|
283
|
+
```ruby
|
284
|
+
...
|
285
|
+
Messenger::Client.send(
|
286
|
+
Messenger::Request.new(
|
287
|
+
Messenger::Elements::Image.new(url: 'http://lorempixel.com/400/400/cats'),
|
288
|
+
fb_params.sender_id
|
289
|
+
)
|
290
|
+
)
|
291
|
+
...
|
292
|
+
```
|
293
|
+
|
294
|
+
#### Generic template
|
295
|
+
|
296
|
+
Attribute | Allowed values | Required?
|
297
|
+
--------- | -------------- | :--------:
|
298
|
+
elements | Array of [Messenger::Elements::Bubble](#bubble) objects | ✔
|
299
|
+
|
300
|
+
Example usage:
|
301
|
+
```ruby
|
302
|
+
|
303
|
+
#define bubbles here...
|
304
|
+
bubble1 = Messenger::Elements::Bubble.new(
|
305
|
+
title: 'Bubble 1',
|
306
|
+
subtitle: 'Cool Bubble',
|
307
|
+
item_url: 'http://lorempixel.com/400/400/cats',
|
308
|
+
image_url: 'http://lorempixel.com/400/400/cats',
|
309
|
+
buttons: [
|
310
|
+
Messenger::Elements::Button.new(
|
311
|
+
type: 'web_url',
|
312
|
+
title: 'Show Website',
|
313
|
+
value: 'https://petersapparel.parseapp.com'
|
314
|
+
)
|
315
|
+
]
|
316
|
+
)
|
317
|
+
|
318
|
+
bubble2 = ...
|
319
|
+
|
320
|
+
#lets create Generic template
|
321
|
+
generic = Messenger::Templates::Generic.new(
|
322
|
+
elements: [bubble1, bubble2]
|
323
|
+
)
|
324
|
+
|
325
|
+
#now send Generic template to the user
|
326
|
+
Messenger::Client.send(
|
327
|
+
Messenger::Request.new(generic, fb_params.sender_id)
|
328
|
+
)
|
329
|
+
```
|
330
|
+
|
331
|
+
#### Button template
|
332
|
+
|
333
|
+
Attribute | Allowed values | Required?
|
334
|
+
--------- | -------------- | :--------:
|
335
|
+
text | String | ✔
|
336
|
+
buttons | Array of [Messenger::Elements::Button](#button) objects | ✔
|
337
|
+
|
338
|
+
Example usage:
|
339
|
+
```ruby
|
340
|
+
|
341
|
+
#lets create Buttons template
|
342
|
+
buttons = Messenger::Templates::Buttons.new(
|
343
|
+
text: 'Some Cool Text',
|
344
|
+
buttons: [
|
345
|
+
Messenger::Elements::Button.new(
|
346
|
+
type: 'web_url',
|
347
|
+
title: 'Show Website',
|
348
|
+
value: 'https://petersapparel.parseapp.com'
|
349
|
+
)
|
350
|
+
]
|
351
|
+
)
|
352
|
+
|
353
|
+
#now send Buttons template to the user
|
354
|
+
Messenger::Client.send(
|
355
|
+
Messenger::Request.new(buttons, fb_params.sender_id)
|
356
|
+
)
|
357
|
+
```
|
358
|
+
|
359
|
+
#### Receipt template
|
360
|
+
|
361
|
+
Attribute | Allowed values | Required?
|
362
|
+
--------- | -------------- | :--------:
|
363
|
+
recipient_name | String | ✔
|
364
|
+
order | [Messenger::Elements::Order](#order) object | ✔
|
365
|
+
elements | Array of [Messenger::Elements::Item](#item) objects | ✔
|
366
|
+
address | [Messenger::Elements::Address](#address) object | ✘
|
367
|
+
summary | [Messenger::Elements::Summary](#summary) object | ✔
|
368
|
+
adjustments | Array of [Messenger::Elements::Adjustment](#adjustment) objects | ✘
|
369
|
+
|
370
|
+
Example usage:
|
371
|
+
```ruby
|
372
|
+
#define order element here...
|
373
|
+
order = Messenger::Elements::Order.new(
|
374
|
+
order_number: 'R190581345',
|
375
|
+
currency: 'USD',
|
376
|
+
payment_method: 'Visa',
|
377
|
+
timestamp: '1428444852',
|
378
|
+
order_url: 'http://petersapparel.parseapp.com/order?order_id=123456'
|
379
|
+
)
|
380
|
+
|
381
|
+
#and define all other template elements
|
382
|
+
item1 = ...
|
383
|
+
item2 = ...
|
384
|
+
address = ...
|
385
|
+
summary = ...
|
386
|
+
adjustment1 = ...
|
387
|
+
adjustment2 = ...
|
388
|
+
|
389
|
+
#lets create Receipt template
|
390
|
+
receipt = Messenger::Templates::Receipt.new(
|
391
|
+
recipient_name: 'Random Recipient',
|
392
|
+
order: order,
|
393
|
+
elements: [item1, item2],
|
394
|
+
address: address,
|
395
|
+
summary: summary,
|
396
|
+
adjustments: [adjustment1, adjustment2]
|
397
|
+
)
|
398
|
+
|
399
|
+
#now send Receipt template to the user
|
400
|
+
Messenger::Client.send(
|
401
|
+
Messenger::Request.new(receipt, fb_params.sender_id)
|
402
|
+
)
|
403
|
+
|
404
|
+
```
|
405
|
+
|
406
|
+
### fb_params
|
407
|
+
|
408
|
+
Deserializes params recived from Facebook. Available in MessengerController. Methods:
|
409
|
+
|
410
|
+
* `message?`
|
411
|
+
* `delivery?`
|
412
|
+
* `postback?`
|
413
|
+
* `attachments`
|
414
|
+
* `text_message`
|
415
|
+
* `sender_id`
|
416
|
+
* `recipient_id`
|
417
|
+
|
418
|
+
_Will be extended soon._
|
34
419
|
|
35
420
|
## Development
|
36
421
|
|
37
|
-
After checking out the repo, run `bin/setup` to install dependencies. You can also run `
|
422
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `rake console` for an interactive prompt that will allow you to experiment.
|
38
423
|
|
39
424
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
40
425
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
class MessengerController < ActionController::Base
|
5
|
+
def validate
|
6
|
+
if verify_token_valid? && access_token_valid?
|
7
|
+
render json: params["hub.challenge"]
|
8
|
+
elsif !verify_token_valid?
|
9
|
+
render json: 'Invalid verify token'
|
10
|
+
else
|
11
|
+
render json: 'Invalid page access token'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def subscribe
|
16
|
+
render json: activate_bot
|
17
|
+
rescue RestClient::BadRequest
|
18
|
+
render json: 'Invalid page access token'
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def app_location
|
24
|
+
"https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=#{Messenger.config.page_access_token}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def activate_bot
|
28
|
+
RestClient.post(app_location, nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def access_token_valid?
|
32
|
+
JSON.parse(RestClient.get(app_location)).key?('data')
|
33
|
+
rescue RestClient::BadRequest
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
def verify_token_valid?
|
38
|
+
params["hub.verify_token"] == Messenger.config.verify_token
|
39
|
+
end
|
40
|
+
|
41
|
+
def fb_params
|
42
|
+
Params.new(params)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/bin/console
CHANGED
data/circle.yml
ADDED
data/config/routes.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "messenger/version"
|
2
|
+
require "messenger/configuration"
|
3
|
+
|
4
|
+
require "messenger/components/elements/text"
|
5
|
+
require "messenger/components/elements/image"
|
6
|
+
require "messenger/components/elements/button"
|
7
|
+
require "messenger/components/elements/bubble"
|
8
|
+
|
9
|
+
require "messenger/components/elements/receipt/address"
|
10
|
+
require "messenger/components/elements/receipt/adjustment"
|
11
|
+
require "messenger/components/elements/receipt/item"
|
12
|
+
require "messenger/components/elements/receipt/order"
|
13
|
+
require "messenger/components/elements/receipt/summary"
|
14
|
+
|
15
|
+
require "messenger/components/templates/buttons"
|
16
|
+
require "messenger/components/templates/generic"
|
17
|
+
require "messenger/components/templates/receipt"
|
18
|
+
|
19
|
+
require "messenger/client"
|
20
|
+
require "messenger/request"
|
21
|
+
|
22
|
+
module Messenger
|
23
|
+
class << self
|
24
|
+
attr_accessor :config
|
25
|
+
|
26
|
+
def config
|
27
|
+
@config ||= Configuration.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def configure
|
31
|
+
yield(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset
|
35
|
+
@config = Configuration.new
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
require "messenger/engine"
|
41
|
+
require "messenger/params"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Messenger
|
2
|
+
class Client
|
3
|
+
def self.get_user_profile(user_id)
|
4
|
+
RestClient.get(
|
5
|
+
"https://graph.facebook.com/v2.6/#{user_id}?fields=first_name,last_name,profile_pic \
|
6
|
+
&access_token=#{Messenger.config.page_access_token}"
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.send(data)
|
11
|
+
RestClient.post(
|
12
|
+
"https://graph.facebook.com/v2.6/me/messages?access_token=#{Messenger.config.page_access_token}",
|
13
|
+
data.build.to_json,
|
14
|
+
content_type: :json
|
15
|
+
)
|
16
|
+
rescue RestClient::ExceptionWithResponse => err
|
17
|
+
puts "\nFacebook API response from invalid request:\n#{err.response}\n\n"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Messenger
|
2
|
+
module Components
|
3
|
+
class Attachment
|
4
|
+
def initialize
|
5
|
+
raise 'This class is abstract!'
|
6
|
+
end
|
7
|
+
|
8
|
+
def build
|
9
|
+
{
|
10
|
+
attachment: {
|
11
|
+
type: @type,
|
12
|
+
payload: payload
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def all_attributes
|
18
|
+
return instance_values unless defined?(flattened_attributes)
|
19
|
+
instance_values.merge! flattened_attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
def payload
|
23
|
+
all_attributes.select { |attribute, value| allowed_attribute?(attribute) && value.present? }
|
24
|
+
end
|
25
|
+
|
26
|
+
def allowed_attribute?(attribute)
|
27
|
+
self.class::ATTRIBUTES.include?(attribute)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_elements(elements)
|
31
|
+
elements.map { |element| element.build } if elements.present?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'messenger/components/element'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Elements
|
5
|
+
class Bubble < Components::Element
|
6
|
+
def initialize(title:, subtitle: nil, item_url: nil, image_url: nil, buttons: nil)
|
7
|
+
@title = title
|
8
|
+
@subtitle = subtitle
|
9
|
+
@image_url = image_url
|
10
|
+
@item_url = item_url
|
11
|
+
@buttons = build_buttons(buttons)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_buttons(buttons)
|
15
|
+
buttons.map { |button| button.build } if buttons.present?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Messenger
|
2
|
+
module Elements
|
3
|
+
class Button
|
4
|
+
def initialize(type:, title:, value:)
|
5
|
+
@type = type
|
6
|
+
@title = title
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def build
|
11
|
+
{ type: @type, title: @title }.merge! eval(@type.to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def web_url
|
15
|
+
{ url: @value }
|
16
|
+
end
|
17
|
+
|
18
|
+
def postback
|
19
|
+
{ payload: @value }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'messenger/components/element'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Elements
|
5
|
+
class Address < Components::Element
|
6
|
+
def initialize(street_1:, street_2: nil, city:, postal_code:, state:, country:)
|
7
|
+
@street_1 = street_1
|
8
|
+
@street_2 = street_2
|
9
|
+
@city = city
|
10
|
+
@postal_code = postal_code
|
11
|
+
@state = state
|
12
|
+
@country = country
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'messenger/components/element'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Elements
|
5
|
+
class Item < Components::Element
|
6
|
+
def initialize(title:, subtitle: nil, quantity: nil, price: nil, currency: nil, image_url: nil)
|
7
|
+
@title = title
|
8
|
+
@subtitle = subtitle
|
9
|
+
@quantity = quantity
|
10
|
+
@price = price
|
11
|
+
@currency = currency
|
12
|
+
@image_url = image_url
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'messenger/components/element'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Elements
|
5
|
+
class Order < Components::Element
|
6
|
+
def initialize(order_number:, currency:, payment_method:, timestamp: nil, order_url: nil)
|
7
|
+
@order_number = order_number
|
8
|
+
@currency = currency
|
9
|
+
@payment_method = payment_method
|
10
|
+
@timestamp = timestamp
|
11
|
+
@order_url = order_url
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'messenger/components/element'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Elements
|
5
|
+
class Summary < Components::Element
|
6
|
+
def initialize(subtotal: nil, shipping_cost: nil, total_tax: nil, total_cost:)
|
7
|
+
@subtotal = subtotal
|
8
|
+
@shipping_cost = shipping_cost
|
9
|
+
@total_tax = total_tax
|
10
|
+
@total_cost = total_cost
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'messenger/components/attachment'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Templates
|
5
|
+
class Buttons < Components::Attachment
|
6
|
+
ATTRIBUTES = %w(template_type text buttons).freeze
|
7
|
+
|
8
|
+
def initialize(text:, buttons:)
|
9
|
+
@type = 'template'
|
10
|
+
@template_type = 'button'
|
11
|
+
@text = text
|
12
|
+
@buttons = build_elements(buttons)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'messenger/components/attachment'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Templates
|
5
|
+
class Generic < Components::Attachment
|
6
|
+
ATTRIBUTES = %w(template_type elements).freeze
|
7
|
+
|
8
|
+
def initialize(elements:)
|
9
|
+
@type = 'template'
|
10
|
+
@template_type = 'generic'
|
11
|
+
@elements = build_elements(elements)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'messenger/components/attachment'
|
2
|
+
|
3
|
+
module Messenger
|
4
|
+
module Templates
|
5
|
+
class Receipt < Components::Attachment
|
6
|
+
ATTRIBUTES = %w(
|
7
|
+
template_type
|
8
|
+
recipient_name
|
9
|
+
order_number
|
10
|
+
currency
|
11
|
+
payment_method
|
12
|
+
timestamp
|
13
|
+
order_url
|
14
|
+
elements
|
15
|
+
address
|
16
|
+
summary
|
17
|
+
adjustments
|
18
|
+
).freeze
|
19
|
+
|
20
|
+
def initialize(recipient_name:, order:, elements:, address: nil, summary:, adjustments: nil)
|
21
|
+
@type = 'template'
|
22
|
+
@template_type = 'receipt'
|
23
|
+
@recipient_name = recipient_name
|
24
|
+
@order = order
|
25
|
+
@elements = build_elements(elements)
|
26
|
+
@address = address.build
|
27
|
+
@summary = summary.build
|
28
|
+
@adjustments = build_elements(adjustments)
|
29
|
+
end
|
30
|
+
|
31
|
+
def flattened_attributes
|
32
|
+
@order.build
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Messenger
|
2
|
+
class Params
|
3
|
+
attr_accessor :params
|
4
|
+
|
5
|
+
def initialize(params)
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
def message?
|
10
|
+
messaging_entry.key?('message')
|
11
|
+
end
|
12
|
+
|
13
|
+
def delivery?
|
14
|
+
messaging_entry.key?('delivery')
|
15
|
+
end
|
16
|
+
|
17
|
+
def postback?
|
18
|
+
messaging_entry.key?('postback')
|
19
|
+
end
|
20
|
+
|
21
|
+
def attachments
|
22
|
+
messaging_entry['message']['attachments'].map { |a| a['payload']['url'] }
|
23
|
+
end
|
24
|
+
|
25
|
+
def text_message
|
26
|
+
messaging_entry['message']['text']
|
27
|
+
end
|
28
|
+
|
29
|
+
def sender_id
|
30
|
+
messaging_entry['sender']['id']
|
31
|
+
end
|
32
|
+
|
33
|
+
def recipient_id
|
34
|
+
messaging_entry['recipient']['id']
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def messaging_entry
|
40
|
+
params['entry'][0]['messaging'][0]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Messenger
|
2
|
+
class Request
|
3
|
+
def initialize(component, recipient_id)
|
4
|
+
@recipient_id = recipient_id
|
5
|
+
@body = body
|
6
|
+
add_element(component)
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
return @body
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_element(element)
|
14
|
+
@body[:message].merge! element.build
|
15
|
+
end
|
16
|
+
|
17
|
+
def body
|
18
|
+
{
|
19
|
+
recipient: { id: @recipient_id },
|
20
|
+
message: {}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/messenger/version.rb
CHANGED
data/messenger-ruby.gemspec
CHANGED
@@ -18,7 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.
|
21
|
+
spec.add_dependency 'rest-client'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler"
|
22
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
25
|
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency 'rspec-rails'
|
27
|
+
spec.add_development_dependency 'webmock'
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "rails"
|
30
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
24
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: messenger-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- justynjozwiak
|
@@ -9,22 +9,36 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-04-
|
12
|
+
date: 2016-04-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: bundler
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
17
31
|
requirements:
|
18
|
-
- - "
|
32
|
+
- - ">="
|
19
33
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
34
|
+
version: '0'
|
21
35
|
type: :development
|
22
36
|
prerelease: false
|
23
37
|
version_requirements: !ruby/object:Gem::Requirement
|
24
38
|
requirements:
|
25
|
-
- - "
|
39
|
+
- - ">="
|
26
40
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
41
|
+
version: '0'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: rake
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,6 +67,76 @@ dependencies:
|
|
53
67
|
- - ">="
|
54
68
|
- !ruby/object:Gem::Version
|
55
69
|
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec-rails
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: webmock
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: pry
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rails
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: codeclimate-test-reporter
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
56
140
|
description:
|
57
141
|
email:
|
58
142
|
- justyn.jozwiak@netguru.pl
|
@@ -61,15 +145,37 @@ executables: []
|
|
61
145
|
extensions: []
|
62
146
|
extra_rdoc_files: []
|
63
147
|
files:
|
148
|
+
- ".codeclimate.yml"
|
64
149
|
- ".gitignore"
|
65
150
|
- ".rspec"
|
66
151
|
- Gemfile
|
67
152
|
- README.md
|
68
153
|
- Rakefile
|
154
|
+
- app/controllers/messenger/messenger_controller.rb
|
69
155
|
- bin/console
|
70
156
|
- bin/setup
|
71
|
-
-
|
157
|
+
- circle.yml
|
158
|
+
- config/routes.rb
|
159
|
+
- lib/messenger-ruby.rb
|
160
|
+
- lib/messenger/client.rb
|
161
|
+
- lib/messenger/components/attachment.rb
|
162
|
+
- lib/messenger/components/element.rb
|
163
|
+
- lib/messenger/components/elements/bubble.rb
|
164
|
+
- lib/messenger/components/elements/button.rb
|
165
|
+
- lib/messenger/components/elements/image.rb
|
166
|
+
- lib/messenger/components/elements/receipt/address.rb
|
167
|
+
- lib/messenger/components/elements/receipt/adjustment.rb
|
168
|
+
- lib/messenger/components/elements/receipt/item.rb
|
169
|
+
- lib/messenger/components/elements/receipt/order.rb
|
170
|
+
- lib/messenger/components/elements/receipt/summary.rb
|
171
|
+
- lib/messenger/components/elements/text.rb
|
172
|
+
- lib/messenger/components/templates/buttons.rb
|
173
|
+
- lib/messenger/components/templates/generic.rb
|
174
|
+
- lib/messenger/components/templates/receipt.rb
|
72
175
|
- lib/messenger/configuration.rb
|
176
|
+
- lib/messenger/engine.rb
|
177
|
+
- lib/messenger/params.rb
|
178
|
+
- lib/messenger/request.rb
|
73
179
|
- lib/messenger/version.rb
|
74
180
|
- messenger-ruby.gemspec
|
75
181
|
homepage: https://github.com/netguru/messenger-ruby
|
data/lib/messenger.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require "messenger/version"
|
2
|
-
require "messenger/configuration"
|
3
|
-
|
4
|
-
module Messenger
|
5
|
-
class << self
|
6
|
-
attr_accessor :config
|
7
|
-
|
8
|
-
def config
|
9
|
-
@config ||= Configuration.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def configure
|
13
|
-
yield(config)
|
14
|
-
end
|
15
|
-
|
16
|
-
def reset
|
17
|
-
@config = Configuration.new
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|