messenger-ruby 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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://img.shields.io/gem/v/messenger-ruby.svg?style=flat-square)](https://rubygems.org/gems/messenger-ruby)
|
3
|
+
[![](https://img.shields.io/circleci/project/netguru/messenger-ruby.svg?style=flat-square)](https://circleci.com/gh/netguru/messenger-ruby)
|
4
|
+
[![](http://img.shields.io/codeclimate/github/netguru/messenger-ruby.svg?style=flat-square)](https://codeclimate.com/github/netguru/messenger-ruby)
|
5
|
+
[![](http://img.shields.io/codeclimate/coverage/github/netguru/messenger-ruby.svg?style=flat-square)](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
|