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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba7478e7dc69de8c24460b8780d2c7c2c0624495
4
- data.tar.gz: 60a772a736040cf834b0cbd08379887d3f3caf01
3
+ metadata.gz: c0002a8167648af1651c41031ec1b600947c5fd7
4
+ data.tar.gz: 399edaa10c599c990ce954a737ee81165548d4fa
5
5
  SHA512:
6
- metadata.gz: 92bc942f56f99fcecea0608cc5e6650df8a0d2b25eac05095163361c1fa08bd78da6dc1a46cb30452b8b79ee811e3d6f4af1f846d210a80bc80607cf468a3436
7
- data.tar.gz: a4f6ffe443cd6dd561dcc99c6e17c1ec9c0c07fa0f3019011ee542965c59300f300a1266d4ff0c9ea05c23f3020abc5a7b4c6a06e51e889939607c96faa9aa4f
6
+ metadata.gz: ff5cc415b65f152f1142bd1ebff07c529e35113b00bcf7b25b5a8f3c8ac29944c0a8f3a924852eccaa91ee383b37a2e2c341b50649d6b22a4738658f540e2821
7
+ data.tar.gz: d23051ac1715597ae5e51d95881fa9337e932f0bdfdc19e5086631c902a473eeb9798976cf9859297bb5e7ad185776a9c6b8fa2aee565477a75937ddabf11bbf
data/.codeclimate.yml ADDED
@@ -0,0 +1,9 @@
1
+ engines:
2
+ rubocop:
3
+ enabled: false
4
+ ratings:
5
+ paths:
6
+ - lib/**
7
+ - "**.rb"
8
+ exclude_paths:
9
+ - spec/**/*
data/.gitignore CHANGED
@@ -1,2 +1,6 @@
1
1
  /Gemfile.lock
2
2
  /pkg
3
+ /coverage
4
+
5
+ spec/test_app/config/secrets.yml
6
+ spec/test_app/log/*
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
- Create `messenger.rb` initializer in you app directory:
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
- # app/config/initializers/messenger.rb
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
- TODO: Write usage instructions here
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'` | &#10004;
117
+ title | String | &#10004;
118
+ value | String | &#10004;
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 | &#10004;
132
+ subtitle | String | &#10004;*
133
+ image_url | String | &#10004;*
134
+ buttons | [`Messenger::Elements::Button`](#button) objects array | &#10004;*
135
+ item_url | String | &#10008;
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 | &#10004;
152
+ street_2 | String | &#10008;
153
+ city | String | &#10004;
154
+ postal_code | String | &#10004;
155
+ state | String | &#10004;
156
+ country | String | &#10004;
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 | &#10004;
177
+ amount | Integer, greater than 0 | &#10004;
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 | &#10004;
191
+ subtilte | String | &#10008;
192
+ quantity | Integer | &#10008;
193
+ price | Decimal | &#10008;
194
+ currency | String, from _ISO 4217 Currency Codes_ | &#10008;
195
+ image_url | String | &#10008;
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 | &#10004;
216
+ currency | String, from _ISO 4217 Currency Codes_ | &#10004;
217
+ payment_method | String | &#10004;
218
+ timestamp | correct timestamp (String) | &#10008;
219
+ order_url | String | &#10008;
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 | &#10008;
240
+ shipping_cost | Decimal | &#10008;
241
+ total_tax | Decimal | &#10008;
242
+ total_cost | Decimal | &#10004;
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 | &#10004;
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 | &#10004;
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 | &#10004;
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 | &#10004;
336
+ buttons | Array of [Messenger::Elements::Button](#button) objects | &#10004;
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 | &#10004;
364
+ order | [Messenger::Elements::Order](#order) object | &#10004;
365
+ elements | Array of [Messenger::Elements::Item](#item) objects | &#10004;
366
+ address | [Messenger::Elements::Address](#address) object | &#10008;
367
+ summary | [Messenger::Elements::Summary](#summary) object | &#10004;
368
+ adjustments | Array of [Messenger::Elements::Adjustment](#adjustment) objects | &#10008;
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 `bin/console` for an interactive prompt that will allow you to experiment.
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
@@ -4,5 +4,5 @@ require "rspec/core/rake_task"
4
4
  task default: :spec
5
5
 
6
6
  task :console do
7
- exec "irb -r messenger -I ./lib"
7
+ exec "irb -r messenger-ruby -I ./lib"
8
8
  end
@@ -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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
- require "messenger"
4
+ require "messenger-ruby"
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
data/circle.yml ADDED
@@ -0,0 +1,6 @@
1
+ dependencies:
2
+ pre:
3
+ - gem install bundler --pre
4
+ machine:
5
+ ruby:
6
+ version: 2.2.0
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ Messenger::Engine.routes.draw do
2
+ get :subscribe, to: "messenger#subscribe"
3
+ get :webhook, to: "messenger#validate"
4
+ end
5
+
6
+ Rails.application.routes.draw do
7
+ post 'messenger/webhook', to: "messenger#webhook"
8
+ end
@@ -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,13 @@
1
+ module Messenger
2
+ module Components
3
+ class Element
4
+ def initialize
5
+ raise 'This class is abstract!'
6
+ end
7
+
8
+ def build
9
+ instance_values.delete_if { |_attribute, value| value.nil? }
10
+ end
11
+ end
12
+ end
13
+ 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,14 @@
1
+ require 'messenger/components/attachment'
2
+
3
+ module Messenger
4
+ module Elements
5
+ class Image < Components::Attachment
6
+ ATTRIBUTES = %w(url).freeze
7
+
8
+ def initialize(url:)
9
+ @url = url
10
+ @type = 'image'
11
+ end
12
+ end
13
+ end
14
+ 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,12 @@
1
+ require 'messenger/components/element'
2
+
3
+ module Messenger
4
+ module Elements
5
+ class Adjustment < Components::Element
6
+ def initialize(name: nil, amount: nil)
7
+ @name = name
8
+ @amount = amount
9
+ end
10
+ end
11
+ end
12
+ 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,13 @@
1
+ module Messenger
2
+ module Elements
3
+ class Text
4
+ def initialize(text:)
5
+ @text = text
6
+ end
7
+
8
+ def build
9
+ instance_values
10
+ end
11
+ end
12
+ end
13
+ 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,7 @@
1
+ require 'rails'
2
+
3
+ module Messenger
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Messenger
6
+ end
7
+ 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
@@ -1,3 +1,3 @@
1
1
  module Messenger
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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.add_development_dependency "bundler", "~> 1.11"
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: 0.1.0
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-18 00:00:00.000000000 Z
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: '1.11'
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: '1.11'
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
- - lib/messenger.rb
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