warb 1.0.0 → 1.0.1

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -5
  3. data/README.md +32 -9
  4. data/Rakefile +3 -3
  5. data/docs/README.md +4 -1
  6. data/docs/components/README.md +4 -1
  7. data/docs/components/button.md +62 -0
  8. data/docs/components/copy_code_button.md +57 -0
  9. data/docs/components/flow_button.md +102 -0
  10. data/docs/components/url_button.md +57 -0
  11. data/docs/messages/README.md +2 -1
  12. data/docs/messages/flow.md +241 -5
  13. data/docs/messages/interactive_call_to_action_url.md +9 -9
  14. data/docs/messages/interactive_list.md +2 -2
  15. data/docs/messages/interactive_reply_button.md +9 -9
  16. data/docs/messages/template.md +373 -0
  17. data/docs/resources/README.md +14 -0
  18. data/docs/resources/currency.md +22 -0
  19. data/docs/resources/date_time.md +11 -0
  20. data/docs/resources/text.md +9 -0
  21. data/docs/setup.md +45 -1
  22. data/examples/audio.rb +10 -10
  23. data/examples/document.rb +34 -34
  24. data/examples/image.rb +22 -22
  25. data/examples/interactive_call_to_action_url.rb +46 -46
  26. data/examples/interactive_list.rb +61 -61
  27. data/examples/interactive_reply_button.rb +43 -43
  28. data/examples/location.rb +32 -32
  29. data/examples/location_request.rb +11 -11
  30. data/examples/message.rb +8 -8
  31. data/examples/sticker.rb +10 -10
  32. data/examples/video.rb +22 -22
  33. data/examples/webhook.rb +77 -43
  34. data/lib/warb/category.rb +8 -0
  35. data/lib/warb/client.rb +7 -5
  36. data/lib/warb/components/action.rb +12 -8
  37. data/lib/warb/components/button.rb +29 -0
  38. data/lib/warb/components/component.rb +19 -0
  39. data/lib/warb/components/copy_code_button.rb +30 -0
  40. data/lib/warb/components/flow_button.rb +32 -0
  41. data/lib/warb/components/quick_reply_button.rb +15 -0
  42. data/lib/warb/components/url_button.rb +30 -0
  43. data/lib/warb/components/voice_call_button.rb +15 -0
  44. data/lib/warb/configuration.rb +4 -1
  45. data/lib/warb/connection.rb +15 -9
  46. data/lib/warb/dispatcher.rb +4 -3
  47. data/lib/warb/dispatcher_concern.rb +6 -0
  48. data/lib/warb/errors.rb +27 -0
  49. data/lib/warb/indicator_dispatcher.rb +4 -4
  50. data/lib/warb/language.rb +8 -0
  51. data/lib/warb/media_dispatcher.rb +10 -10
  52. data/lib/warb/resources/audio.rb +1 -1
  53. data/lib/warb/resources/contact.rb +22 -20
  54. data/lib/warb/resources/currency.rb +47 -0
  55. data/lib/warb/resources/date_time.rb +34 -0
  56. data/lib/warb/resources/document.rb +1 -1
  57. data/lib/warb/resources/flow.rb +82 -20
  58. data/lib/warb/resources/helpers/header.rb +35 -0
  59. data/lib/warb/resources/image.rb +1 -1
  60. data/lib/warb/resources/interactive_call_to_action_url.rb +10 -8
  61. data/lib/warb/resources/interactive_list.rb +7 -5
  62. data/lib/warb/resources/interactive_reply_button.rb +10 -8
  63. data/lib/warb/resources/location.rb +11 -1
  64. data/lib/warb/resources/location_request.rb +5 -3
  65. data/lib/warb/resources/reaction.rb +1 -1
  66. data/lib/warb/resources/resource.rb +14 -4
  67. data/lib/warb/resources/sticker.rb +1 -1
  68. data/lib/warb/resources/template.rb +163 -0
  69. data/lib/warb/resources/text.rb +31 -3
  70. data/lib/warb/resources/validation.rb +30 -0
  71. data/lib/warb/resources/video.rb +1 -1
  72. data/lib/warb/response.rb +33 -0
  73. data/lib/warb/response_error_handler.rb +42 -0
  74. data/lib/warb/template_dispatcher.rb +21 -0
  75. data/lib/warb/utils.rb +3 -1
  76. data/lib/warb/version.rb +1 -1
  77. data/lib/warb.rb +67 -31
  78. metadata +34 -3
data/examples/sticker.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../lib/warb"
3
+ require_relative '../lib/warb'
4
4
 
5
5
  # Configure your variables here
6
6
 
7
- access_token = ""
8
- business_id = ""
9
- sender_id = ""
10
- recipient_number = ""
7
+ access_token = ''
8
+ business_id = ''
9
+ sender_id = ''
10
+ recipient_number = ''
11
11
 
12
- image_link = ""
12
+ image_link = ''
13
13
 
14
14
  # We recommend testing one section at a time, as it can be overwhelming to see all the messages at once.
15
15
  # So you can comment out the sections you don't want to test.
@@ -25,8 +25,8 @@ warb_from_setup = Warb.setup do |config|
25
25
  end
26
26
 
27
27
  # To send sticker using its ID, you may need to retrieve it first, which can be retrieved this way
28
- file_path = "" # fill this in with the file path pointing to wherever the sticker is located
29
- file_type = "image/webp" # fill this in with the mimetype of the sticker to be uploaded
28
+ file_path = '' # fill this in with the file path pointing to wherever the sticker is located
29
+ file_type = 'image/webp' # fill this in with the mimetype of the sticker to be uploaded
30
30
  # only image/webp is allowed for sticker file type
31
31
  image_id = warb_from_setup.sticker.upload(file_path: file_path, file_type: file_type)
32
32
  # if you already have an sticker id, you can simply replace the above line with such id
@@ -53,8 +53,8 @@ warb_from_new = Warb.new(
53
53
  )
54
54
 
55
55
  # Same as stated above, if you need a sticker id, you can upload it this way
56
- file_path = "" # fill this in with the file path pointing to wherever the sticker is located
57
- file_type = "" # fill this in with the mimetype of the sticker to be uploaded
56
+ file_path = '' # fill this in with the file path pointing to wherever the sticker is located
57
+ file_type = '' # fill this in with the mimetype of the sticker to be uploaded
58
58
  # allow values for file_type: sticker/aac, sticker/amr, sticker/mpeg, sticker/mp4 or sticker/ogg
59
59
  image_id = warb_from_setup.sticker.upload(file_path: file_path, file_type: file_type)
60
60
  # if you already have a sticker id, you can simply replace the above line with such id
data/examples/video.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../lib/warb"
3
+ require_relative '../lib/warb'
4
4
 
5
5
  # Configure your variables here
6
6
 
7
- access_token = ""
8
- business_id = ""
9
- sender_id = ""
10
- recipient_number = ""
7
+ access_token = ''
8
+ business_id = ''
9
+ sender_id = ''
10
+ recipient_number = ''
11
11
 
12
- video_link = ""
12
+ video_link = ''
13
13
 
14
14
  # We recommend testing one section at a time, as it can be overwhelming to see all the messages at once.
15
15
  # So you can comment out the sections you don't want to test.
@@ -25,24 +25,24 @@ warb_from_setup = Warb.setup do |config|
25
25
  end
26
26
 
27
27
  # To send video using its ID, you may need to retrieve it first, which can be retrieved this way
28
- file_path = "" # fill this in with the file path pointing to wherever the video is located
29
- file_type = "" # fill this in with the mimetype of the video to be uploaded. allowed values: "video/3gpp" or "video/mp4"
28
+ file_path = '' # fill this in with the file path pointing to wherever the video is located
29
+ file_type = '' # fill this in with the mimetype of the video to be uploaded. allowed values: "video/3gpp" or "video/mp4"
30
30
  video_id = warb_from_setup.video.upload(file_path: file_path, file_type: file_type)
31
31
  # if you already have a video id, you can simply replace the above line with such id
32
32
 
33
33
  warb_from_setup.video.dispatch(recipient_number, media_id: video_id)
34
- warb_from_setup.video.dispatch(recipient_number, media_id: video_id, caption: "OPTIONAL - Image caption")
34
+ warb_from_setup.video.dispatch(recipient_number, media_id: video_id, caption: 'OPTIONAL - Image caption')
35
35
  warb_from_setup.video.dispatch(recipient_number, link: video_link)
36
- warb_from_setup.video.dispatch(recipient_number, link: video_link, caption: "OPTIONAL - Image caption")
36
+ warb_from_setup.video.dispatch(recipient_number, link: video_link, caption: 'OPTIONAL - Image caption')
37
37
 
38
38
  warb_from_setup.video.dispatch(recipient_number) do |builder|
39
39
  builder.media_id = video_id
40
- builder.caption = "OPTIONAL - Image caption"
40
+ builder.caption = 'OPTIONAL - Image caption'
41
41
  end
42
42
 
43
43
  warb_from_setup.video.dispatch(recipient_number) do |builder|
44
44
  builder.link = video_link
45
- builder.caption = "OPTIONAL - Image caption"
45
+ builder.caption = 'OPTIONAL - Image caption'
46
46
  end
47
47
 
48
48
  # ############################################ #
@@ -56,24 +56,24 @@ warb_from_new = Warb.new(
56
56
  )
57
57
 
58
58
  # Same as stated above, if you need a video id, you can upload it this way
59
- file_path = "" # fill this in with the file path pointing to wherever the video is located
60
- file_type = "" # fill this in with the mimetype of the video to be uploaded. allowed values: "video/3gpp" or "video/mp4"
59
+ file_path = '' # fill this in with the file path pointing to wherever the video is located
60
+ file_type = '' # fill this in with the mimetype of the video to be uploaded. allowed values: "video/3gpp" or "video/mp4"
61
61
  video_id = warb_from_setup.video.upload(file_path: file_path, file_type: file_type)
62
62
  # if you already have a video id, you can simply replace the above line with such id
63
63
 
64
64
  warb_from_new.video.dispatch(recipient_number, media_id: video_id)
65
- warb_from_new.video.dispatch(recipient_number, media_id: video_id, caption: "OPTIONAL - Image caption")
65
+ warb_from_new.video.dispatch(recipient_number, media_id: video_id, caption: 'OPTIONAL - Image caption')
66
66
  warb_from_new.video.dispatch(recipient_number, link: video_link)
67
- warb_from_new.video.dispatch(recipient_number, link: video_link, caption: "OPTIONAL - Image caption")
67
+ warb_from_new.video.dispatch(recipient_number, link: video_link, caption: 'OPTIONAL - Image caption')
68
68
 
69
69
  warb_from_new.video.dispatch(recipient_number) do |builder|
70
70
  builder.media_id = video_id
71
- builder.caption = "OPTIONAL - Image caption"
71
+ builder.caption = 'OPTIONAL - Image caption'
72
72
  end
73
73
 
74
74
  warb_from_new.video.dispatch(recipient_number) do |builder|
75
75
  builder.link = video_link
76
- builder.caption = "OPTIONAL - Image caption"
76
+ builder.caption = 'OPTIONAL - Image caption'
77
77
  end
78
78
 
79
79
  # ################################################# #
@@ -81,16 +81,16 @@ end
81
81
  # ################################################# #
82
82
 
83
83
  Warb.video.dispatch(recipient_number, media_id: video_id)
84
- Warb.video.dispatch(recipient_number, media_id: video_id, caption: "OPTIONAL - Image caption")
84
+ Warb.video.dispatch(recipient_number, media_id: video_id, caption: 'OPTIONAL - Image caption')
85
85
  Warb.video.dispatch(recipient_number, link: video_link)
86
- Warb.video.dispatch(recipient_number, link: video_link, caption: "OPTIONAL - Image caption")
86
+ Warb.video.dispatch(recipient_number, link: video_link, caption: 'OPTIONAL - Image caption')
87
87
 
88
88
  Warb.video.dispatch(recipient_number) do |builder|
89
89
  builder.media_id = video_id
90
- builder.caption = "OPTIONAL - Image caption"
90
+ builder.caption = 'OPTIONAL - Image caption'
91
91
  end
92
92
 
93
93
  Warb.video.dispatch(recipient_number) do |builder|
94
94
  builder.link = video_link
95
- builder.caption = "OPTIONAL - Image caption"
95
+ builder.caption = 'OPTIONAL - Image caption'
96
96
  end
data/examples/webhook.rb CHANGED
@@ -1,35 +1,69 @@
1
- require "sinatra/base"
2
- require "faraday"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/warb'
4
+ require 'sinatra/base'
5
+ require 'faraday'
6
+ require 'openssl'
3
7
 
4
8
  class Webhook < Sinatra::Base
9
+
10
+ Warb.setup do |config|
11
+ config.access_token = token
12
+ config.business_id = business
13
+ config.sender_id = sender
14
+ end
15
+
5
16
  configure do
6
- set :bind, "0.0.0.0"
17
+ set :bind, '0.0.0.0'
7
18
  set :port, 3000
8
19
  set :host_authorization, { permitted_hosts: [] }
9
20
  end
10
21
 
11
- post "/webhook" do
12
- request_body = JSON.parse(request.body.read)
22
+ helpers do
23
+ def verify_signature!(raw_body)
24
+ header = request.env['HTTP_X_HUB_SIGNATURE_256']
25
+
26
+ halt 400, 'Missing X-Hub-Signature-256' if APP_SECRET && (!header || header.empty?)
27
+
28
+ received = header.sub('sha256=', '')
29
+ expected = OpenSSL::HMAC.hexdigest('SHA256', APP_SECRET, raw_body)
30
+
31
+ unless Rack::Utils.secure_compare(received, expected)
32
+ puts "⚠️ Invalid webhook signature."
33
+ halt 403, 'Invalid signature'
34
+ end
35
+
36
+ true
37
+ end
38
+ end
39
+
40
+ post '/webhook' do
41
+ request.body.rewind
42
+ raw_body = request.body.read
43
+
44
+ verify_signature!(raw_body)
45
+
46
+ request_body = JSON.parse(raw_body)
13
47
 
14
48
  puts "\n🪝 Incoming webhook message: #{request_body}"
15
49
 
16
- message = request_body.dig("entry", 0, "changes", 0, "value", "messages", 0)
50
+ message = request_body.dig('entry', 0, 'changes', 0, 'value', 'messages', 0)
17
51
 
18
- if message && message["type"] == "text"
19
- message_id = message["id"]
52
+ if message && message['type'] == 'text'
53
+ message_id = message['id']
20
54
 
21
55
  Warb.indicator.mark_as_read(message_id)
22
56
 
23
- Warb.message.dispatch(message["from"], reply_to: message_id, message: "Echo #{message["text"]["body"]}")
57
+ Warb.message.dispatch(message['from'], reply_to: message_id, message: "Echo #{message['text']['body']}")
24
58
 
25
59
  reaction = {
26
60
  message_id:,
27
- emoji: ""
61
+ emoji: ''
28
62
  }
29
63
 
30
- Warb.reaction.dispatch(message["from"], **reaction)
31
- elsif message && message["type"] == "location"
32
- message_id = message["id"]
64
+ Warb.reaction.dispatch(message['from'], **reaction)
65
+ elsif message && message['type'] == 'location'
66
+ message_id = message['id']
33
67
 
34
68
  Warb.indicator.mark_as_read(message_id)
35
69
 
@@ -40,15 +74,15 @@ class Webhook < Sinatra::Base
40
74
  sleep 2
41
75
 
42
76
  location = {
43
- latitude: message["location"]["latitude"],
44
- longitude: message["location"]["longitude"],
45
- name: message["location"]["name"],
46
- address: message["location"]["address"]
77
+ latitude: message['location']['latitude'],
78
+ longitude: message['location']['longitude'],
79
+ name: message['location']['name'],
80
+ address: message['location']['address']
47
81
  }
48
82
 
49
- Warb.location.dispatch(message["from"], reply_to: message_id, **location)
50
- elsif message && message["type"] == "image"
51
- message_id = message["id"]
83
+ Warb.location.dispatch(message['from'], reply_to: message_id, **location)
84
+ elsif message && message['type'] == 'image'
85
+ message_id = message['id']
52
86
 
53
87
  Warb.indicator.mark_as_read(message_id)
54
88
 
@@ -67,39 +101,39 @@ class Webhook < Sinatra::Base
67
101
  # below, we resend the received image, using its id.
68
102
 
69
103
  image = {
70
- media_id: message["image"]["id"],
71
- link: message["image"]["link"],
72
- caption: message["image"]["caption"]
104
+ media_id: message['image']['id'],
105
+ link: message['image']['link'],
106
+ caption: message['image']['caption']
73
107
  }
74
108
 
75
- Warb.image.dispatch(message["from"], reply_to: message_id, **image)
109
+ Warb.image.dispatch(message['from'], reply_to: message_id, **image)
76
110
 
77
111
  # and here, we download the received image
78
112
  Warb.image.download(media_id: image[:media_id], file_path: "#{Time.now}.jpg")
79
- elsif message && message["type"] == "document"
80
- message_id = message["id"]
113
+ elsif message && message['type'] == 'document'
114
+ message_id = message['id']
81
115
 
82
116
  Warb.indicator.mark_as_read(message_id)
83
117
 
84
118
  document = {
85
- id: message["document"]["id"],
86
- link: message["document"]["link"],
87
- caption: message["document"]["caption"],
88
- filename: message["document"]["filename"]
119
+ id: message['document']['id'],
120
+ link: message['document']['link'],
121
+ caption: message['document']['caption'],
122
+ filename: message['document']['filename']
89
123
  }
90
124
 
91
- Warb.document.dispatch(message["from"], reply_to: message_id, **document)
92
- elsif message && message["type"] == "sticker"
93
- message_id = message["id"]
125
+ Warb.document.dispatch(message['from'], reply_to: message_id, **document)
126
+ elsif message && message['type'] == 'sticker'
127
+ message_id = message['id']
94
128
 
95
129
  Warb.indicator.mark_as_read(message_id)
96
130
 
97
131
  sticker = {
98
- media_id: message["sticker"]["id"],
99
- link: message["sticker"]["link"]
132
+ media_id: message['sticker']['id'],
133
+ link: message['sticker']['link']
100
134
  }
101
135
 
102
- Warb.sticker.dispatch(message["from"], reply_to: message_id, **sticker)
136
+ Warb.sticker.dispatch(message['from'], reply_to: message_id, **sticker)
103
137
  # you could keep adding verifications for different types of messages...
104
138
  # elsif message && message["type"] == "image"
105
139
  # elsif message && message["type"] == "video"
@@ -115,12 +149,12 @@ class Webhook < Sinatra::Base
115
149
  # this is the endpoint which gets called to verify the server within the Meta's API
116
150
  # you can do whatever you want here to verify your server
117
151
  # returning the challenge value which was received as query param is enough
118
- get "/webhook" do
119
- mode = params["hub.mode"]
120
- token = params["hub.verify_token"]
121
- challenge = params["hub.challenge"]
152
+ get '/webhook' do
153
+ mode = params['hub.mode']
154
+ token = params['hub.verify_token']
155
+ challenge = params['hub.challenge']
122
156
 
123
- if mode == "subscribe" && token == Warb.configuration.webhook_verify_token
157
+ if mode == 'subscribe' && token == Warb.configuration.webhook_verify_token
124
158
  status 200
125
159
  body challenge
126
160
 
@@ -135,8 +169,8 @@ class Webhook < Sinatra::Base
135
169
  private
136
170
 
137
171
  def conn
138
- @conn ||= Faraday.new("https://graph.facebook.com/v22.0") do |conn|
139
- conn.headers["Authorization"] = "Bearer #{Warb.configuration.access_token}" if Warb.configuration.access_token
172
+ @conn ||= Faraday.new('https://graph.facebook.com/v22.0') do |conn|
173
+ conn.headers['Authorization'] = "Bearer #{Warb.configuration.access_token}" if Warb.configuration.access_token
140
174
  conn.request(:json)
141
175
  conn.response(:json)
142
176
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Category
5
+ MARKETING = 'MARKETING'
6
+ UTILITY = 'UTILITY'
7
+ end
8
+ end
data/lib/warb/client.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "connection"
3
+ require_relative 'connection'
4
4
  module Warb
5
5
  class Client
6
6
  include DispatcherConcern
@@ -10,6 +10,7 @@ module Warb
10
10
 
11
11
  def_delegators :@configuration, :access_token, :sender_id, :business_id, :adapter, :logger
12
12
 
13
+ # rubocop:disable Metrics/ParameterLists
13
14
  def initialize(configuration = nil, access_token: nil, sender_id: nil, business_id: nil,
14
15
  adapter: nil, logger: nil)
15
16
  @configuration = (configuration || Warb.configuration).dup
@@ -20,21 +21,22 @@ module Warb
20
21
  @configuration.adapter = adapter || @configuration.adapter
21
22
  @configuration.logger = logger || @configuration.logger
22
23
  end
24
+ # rubocop:enable Metrics/ParameterLists
23
25
 
24
26
  def get(endpoint, data = {}, **args)
25
- conn.send_request(http_method: "get", endpoint: endpoint, data: data, **args)
27
+ conn.send_request(http_method: 'get', endpoint: endpoint, data: data, **args)
26
28
  end
27
29
 
28
30
  def post(endpoint, data = {}, **args)
29
- conn.send_request(http_method: "post", endpoint: endpoint, data: data, **args)
31
+ conn.send_request(http_method: 'post', endpoint: endpoint, data: data, **args)
30
32
  end
31
33
 
32
34
  def put(endpoint, data = {}, **args)
33
- conn.send_request(http_method: "put", endpoint: endpoint, data: data, **args)
35
+ conn.send_request(http_method: 'put', endpoint: endpoint, data: data, **args)
34
36
  end
35
37
 
36
38
  def delete(endpoint, data = {}, **args)
37
- conn.send_request(http_method: "delete", endpoint: endpoint, data: data, **args)
39
+ conn.send_request(http_method: 'delete', endpoint: endpoint, data: data, **args)
38
40
  end
39
41
 
40
42
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Warb
2
4
  module Components
3
5
  class Row
@@ -24,12 +26,12 @@ module Warb
24
26
  @rows = rows
25
27
  end
26
28
 
27
- def add_row(**args, &block)
29
+ def add_row(**args, &)
28
30
  row = Row.new(**args)
29
31
 
30
32
  @rows << row
31
33
 
32
- block_given? ? row.tap(&block) : row
34
+ block_given? ? row.tap(&) : row
33
35
  end
34
36
 
35
37
  def to_h
@@ -37,7 +39,7 @@ module Warb
37
39
  title: @title,
38
40
  rows: @rows.map.with_index do |row, index|
39
41
  row_title = row.title.slice(0, 10)
40
- title = row_title.normalize.gsub(/\s/, "").downcase
42
+ title = row_title.normalize.gsub(/\s/, '').downcase
41
43
  id = "#{title}_#{index}"
42
44
 
43
45
  row.to_h.merge(id: id)
@@ -54,12 +56,12 @@ module Warb
54
56
  @sections = sections
55
57
  end
56
58
 
57
- def add_section(**args, &block)
59
+ def add_section(**args, &)
58
60
  section = Section.new(**args)
59
61
 
60
62
  @sections << section
61
63
 
62
- block_given? ? section.tap(&block) : section
64
+ block_given? ? section.tap(&) : section
63
65
  end
64
66
 
65
67
  def to_h
@@ -77,14 +79,15 @@ module Warb
77
79
  @buttons_texts = buttons_texts
78
80
  end
79
81
 
82
+ # rubocop:disable Metrics/MethodLength
80
83
  def to_h
81
84
  {
82
85
  buttons: @buttons_texts.map.with_index do |button_text, index|
83
- text = button_text.normalize.gsub(/\s/, "").downcase
86
+ text = button_text.normalize.gsub(/\s/, '').downcase
84
87
  id = "#{text}_#{index}"
85
88
 
86
89
  {
87
- type: "reply",
90
+ type: 'reply',
88
91
  reply: {
89
92
  id: id,
90
93
  title: button_text
@@ -93,6 +96,7 @@ module Warb
93
96
  end
94
97
  }
95
98
  end
99
+ # rubocop:enable Metrics/MethodLength
96
100
 
97
101
  def add_button_text(button_text)
98
102
  @buttons_texts << button_text
@@ -109,7 +113,7 @@ module Warb
109
113
 
110
114
  def to_h
111
115
  {
112
- name: "cta_url",
116
+ name: 'cta_url',
113
117
  parameters: {
114
118
  display_text: @button_text,
115
119
  url: @url
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class Button < Component
6
+ attr_accessor :index, :sub_type
7
+
8
+ def initialize(**params)
9
+ params[:sub_type] = button_type unless params[:sub_type]
10
+
11
+ super
12
+ end
13
+
14
+ def to_h
15
+ {
16
+ type: 'button',
17
+ sub_type: sub_type || @params[:sub_type],
18
+ index: index || @params[:index]
19
+ }
20
+ end
21
+
22
+ private
23
+
24
+ def button_type
25
+ raise NotImplementedError
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class Component
6
+ def initialize(**params)
7
+ @params = params
8
+ end
9
+
10
+ def to_h
11
+ raise NotImplementedError
12
+ end
13
+
14
+ protected
15
+
16
+ attr_reader :params
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class CopyCodeButton < Button
6
+ BUTTON_TYPE = 'copy_code'
7
+
8
+ attr_accessor :coupon_code
9
+
10
+ def to_h
11
+ button_payload = super
12
+
13
+ if coupon_code || @params[:coupon_code]
14
+ button_payload[:parameters] = Array.new(1, {
15
+ type: 'coupon_code',
16
+ coupon_code: coupon_code || @params[:coupon_code]
17
+ })
18
+ end
19
+
20
+ button_payload
21
+ end
22
+
23
+ private
24
+
25
+ def button_type
26
+ BUTTON_TYPE
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class FlowButton < Button
6
+ BUTTON_TYPE = 'flow'
7
+
8
+ attr_accessor :flow_token, :flow_action_data
9
+
10
+ def to_h
11
+ button_payload = super
12
+
13
+ token = flow_token || @params[:flow_token]
14
+ data = flow_action_data || @params[:flow_action_data]
15
+
16
+ action = {}
17
+ action[:flow_token] = token if token
18
+ action[:flow_action_data] = data if data
19
+
20
+ button_payload[:parameters] = [{ type: 'action', action: action }]
21
+
22
+ button_payload
23
+ end
24
+
25
+ private
26
+
27
+ def button_type
28
+ BUTTON_TYPE
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class QuickReplyButton < Button
6
+ BUTTON_TYPE = 'quick_reply'
7
+
8
+ private
9
+
10
+ def button_type
11
+ BUTTON_TYPE
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class UrlButton < Button
6
+ BUTTON_TYPE = 'url'
7
+
8
+ attr_accessor :text
9
+
10
+ def to_h
11
+ button_payload = super
12
+
13
+ if text || @params[:text]
14
+ button_payload[:parameters] = Array.new(1, {
15
+ type: 'text',
16
+ text: text || @params[:text]
17
+ })
18
+ end
19
+
20
+ button_payload
21
+ end
22
+
23
+ private
24
+
25
+ def button_type
26
+ BUTTON_TYPE
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warb
4
+ module Components
5
+ class VoiceCallButton < Button
6
+ BUTTON_TYPE = 'voice_call'
7
+
8
+ private
9
+
10
+ def button_type
11
+ BUTTON_TYPE
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Warb
2
4
  class Configuration
3
- attr_accessor :access_token, :sender_id, :business_id, :adapter, :logger
5
+ attr_accessor :access_token, :sender_id, :business_id, :adapter, :logger, :custom_errors
4
6
 
5
7
  def initialize(access_token: nil, sender_id: nil, business_id: nil, adapter: nil, logger: nil)
6
8
  @access_token = access_token
@@ -8,6 +10,7 @@ module Warb
8
10
  @business_id = business_id
9
11
  @adapter = adapter || Faraday.default_adapter
10
12
  @logger = logger || Logger.new($stdout)
13
+ @custom_errors = CustomErrors.new.build
11
14
  end
12
15
  end
13
16
  end