kapso-client-ruby 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +81 -81
- data/CHANGELOG.md +262 -91
- data/Gemfile +20 -20
- data/RAILS_INTEGRATION.md +478 -0
- data/README.md +1053 -734
- data/Rakefile +40 -40
- data/TEMPLATE_TOOLS_GUIDE.md +120 -120
- data/WHATSAPP_24_HOUR_GUIDE.md +133 -133
- data/examples/advanced_features.rb +352 -349
- data/examples/advanced_messaging.rb +241 -0
- data/examples/basic_messaging.rb +139 -136
- data/examples/enhanced_interactive.rb +400 -0
- data/examples/flows_usage.rb +307 -0
- data/examples/interactive_messages.rb +343 -0
- data/examples/media_management.rb +256 -253
- data/examples/rails/jobs.rb +388 -0
- data/examples/rails/models.rb +240 -0
- data/examples/rails/notifications_controller.rb +227 -0
- data/examples/template_management.rb +393 -390
- data/kapso-ruby-logo.jpg +0 -0
- data/lib/kapso_client_ruby/client.rb +321 -316
- data/lib/kapso_client_ruby/errors.rb +348 -329
- data/lib/kapso_client_ruby/rails/generators/install_generator.rb +76 -0
- data/lib/kapso_client_ruby/rails/generators/templates/env.erb +21 -0
- data/lib/kapso_client_ruby/rails/generators/templates/initializer.rb.erb +33 -0
- data/lib/kapso_client_ruby/rails/generators/templates/message_service.rb.erb +138 -0
- data/lib/kapso_client_ruby/rails/generators/templates/webhook_controller.rb.erb +62 -0
- data/lib/kapso_client_ruby/rails/railtie.rb +55 -0
- data/lib/kapso_client_ruby/rails/service.rb +189 -0
- data/lib/kapso_client_ruby/rails/tasks.rake +167 -0
- data/lib/kapso_client_ruby/resources/calls.rb +172 -172
- data/lib/kapso_client_ruby/resources/contacts.rb +190 -190
- data/lib/kapso_client_ruby/resources/conversations.rb +103 -103
- data/lib/kapso_client_ruby/resources/flows.rb +382 -0
- data/lib/kapso_client_ruby/resources/media.rb +205 -205
- data/lib/kapso_client_ruby/resources/messages.rb +760 -380
- data/lib/kapso_client_ruby/resources/phone_numbers.rb +85 -85
- data/lib/kapso_client_ruby/resources/templates.rb +283 -283
- data/lib/kapso_client_ruby/types.rb +348 -262
- data/lib/kapso_client_ruby/version.rb +5 -5
- data/lib/kapso_client_ruby.rb +75 -68
- data/scripts/.env.example +17 -17
- data/scripts/kapso_template_finder.rb +91 -91
- data/scripts/sdk_setup.rb +404 -404
- data/scripts/test.rb +60 -60
- metadata +24 -3
|
@@ -1,263 +1,349 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module KapsoClientRuby
|
|
4
|
-
module Types
|
|
5
|
-
# Message status types
|
|
6
|
-
MESSAGE_STATUSES = %w[accepted held_for_quality_assessment].freeze
|
|
7
|
-
|
|
8
|
-
# Template status types
|
|
9
|
-
TEMPLATE_STATUSES = %w[APPROVED PENDING REJECTED PAUSED IN_APPEAL DISABLED].freeze
|
|
10
|
-
|
|
11
|
-
# Template categories
|
|
12
|
-
TEMPLATE_CATEGORIES = %w[MARKETING UTILITY AUTHENTICATION UNKNOWN].freeze
|
|
13
|
-
|
|
14
|
-
# Media types
|
|
15
|
-
MEDIA_TYPES = %w[image audio video document sticker].freeze
|
|
16
|
-
|
|
17
|
-
# Interactive message types
|
|
18
|
-
INTERACTIVE_TYPES = %w[button list product product_list flow address location_request call_permission].freeze
|
|
19
|
-
|
|
20
|
-
# Message response structure
|
|
21
|
-
class SendMessageResponse
|
|
22
|
-
attr_reader :messaging_product, :contacts, :messages
|
|
23
|
-
|
|
24
|
-
def initialize(data)
|
|
25
|
-
@messaging_product = data['messaging_product']
|
|
26
|
-
@contacts = data['contacts']&.map { |c| MessageContact.new(c) } || []
|
|
27
|
-
@messages = data['messages']&.map { |m| MessageInfo.new(m) } || []
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
class MessageContact
|
|
32
|
-
attr_reader :input, :wa_id
|
|
33
|
-
|
|
34
|
-
def initialize(data)
|
|
35
|
-
@input = data['input']
|
|
36
|
-
@wa_id = data['wa_id']
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
class MessageInfo
|
|
41
|
-
attr_reader :id, :message_status
|
|
42
|
-
|
|
43
|
-
def initialize(data)
|
|
44
|
-
@id = data['id']
|
|
45
|
-
@message_status = data['message_status']
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Media response structures
|
|
50
|
-
class MediaUploadResponse
|
|
51
|
-
attr_reader :id
|
|
52
|
-
|
|
53
|
-
def initialize(data)
|
|
54
|
-
@id = data['id']
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
class MediaMetadataResponse
|
|
59
|
-
attr_reader :messaging_product, :url, :mime_type, :sha256, :file_size, :id
|
|
60
|
-
|
|
61
|
-
def initialize(data)
|
|
62
|
-
@messaging_product = data['messaging_product']
|
|
63
|
-
@url = data['url']
|
|
64
|
-
@mime_type = data['mime_type']
|
|
65
|
-
@sha256 = data['sha256']
|
|
66
|
-
@file_size = data['file_size']
|
|
67
|
-
@id = data['id']
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Template structures
|
|
72
|
-
class MessageTemplate
|
|
73
|
-
attr_reader :id, :name, :category, :language, :status, :components,
|
|
74
|
-
:quality_score_category, :warnings, :previous_category,
|
|
75
|
-
:library_template_name, :last_updated_time
|
|
76
|
-
|
|
77
|
-
def initialize(data)
|
|
78
|
-
@id = data['id']
|
|
79
|
-
@name = data['name']
|
|
80
|
-
@category = data['category']
|
|
81
|
-
@language = data['language']
|
|
82
|
-
@status = data['status']
|
|
83
|
-
@components = data['components']
|
|
84
|
-
@quality_score_category = data['quality_score_category']
|
|
85
|
-
@warnings = data['warnings']
|
|
86
|
-
@previous_category = data['previous_category']
|
|
87
|
-
@library_template_name = data['library_template_name']
|
|
88
|
-
@last_updated_time = data['last_updated_time']
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
class TemplateCreateResponse
|
|
93
|
-
attr_reader :id, :status, :category
|
|
94
|
-
|
|
95
|
-
def initialize(data)
|
|
96
|
-
@id = data['id']
|
|
97
|
-
@status = data['status']
|
|
98
|
-
@category = data['category']
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Paging structures
|
|
103
|
-
class GraphPaging
|
|
104
|
-
attr_reader :cursors, :next_page, :previous_page
|
|
105
|
-
|
|
106
|
-
def initialize(data)
|
|
107
|
-
@cursors = data['cursors'] || {}
|
|
108
|
-
@next_page = data['next']
|
|
109
|
-
@previous_page = data['previous']
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def before
|
|
113
|
-
cursors['before']
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def after
|
|
117
|
-
cursors['after']
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
class PagedResponse
|
|
122
|
-
attr_reader :data, :paging
|
|
123
|
-
|
|
124
|
-
def initialize(data, item_class = nil)
|
|
125
|
-
@data = if item_class && data['data'].is_a?(Array)
|
|
126
|
-
data['data'].map { |item| item_class.new(item) }
|
|
127
|
-
else
|
|
128
|
-
data['data'] || []
|
|
129
|
-
end
|
|
130
|
-
@paging = GraphPaging.new(data['paging'] || {})
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Success response
|
|
135
|
-
class GraphSuccessResponse
|
|
136
|
-
attr_reader :success
|
|
137
|
-
|
|
138
|
-
def initialize(data = nil)
|
|
139
|
-
@success = data.nil? || data['success'] || true
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def success?
|
|
143
|
-
@success
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# Business profile structures
|
|
148
|
-
class BusinessProfileEntry
|
|
149
|
-
attr_reader :about, :address, :description, :email, :websites,
|
|
150
|
-
:vertical, :profile_picture_url, :profile_picture_handle
|
|
151
|
-
|
|
152
|
-
def initialize(data)
|
|
153
|
-
@about = data['about']
|
|
154
|
-
@address = data['address']
|
|
155
|
-
@description = data['description']
|
|
156
|
-
@email = data['email']
|
|
157
|
-
@websites = data['websites']
|
|
158
|
-
@vertical = data['vertical']
|
|
159
|
-
@profile_picture_url = data['profile_picture_url']
|
|
160
|
-
@profile_picture_handle = data['profile_picture_handle']
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Conversation structures
|
|
165
|
-
class ConversationRecord
|
|
166
|
-
attr_reader :id, :phone_number, :phone_number_id, :status, :last_active_at,
|
|
167
|
-
:kapso, :metadata
|
|
168
|
-
|
|
169
|
-
def initialize(data)
|
|
170
|
-
@id = data['id']
|
|
171
|
-
@phone_number = data['phone_number']
|
|
172
|
-
@phone_number_id = data['phone_number_id']
|
|
173
|
-
@status = data['status']
|
|
174
|
-
@last_active_at = data['last_active_at']
|
|
175
|
-
@kapso = data['kapso']
|
|
176
|
-
@metadata = data['metadata']
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Contact structures
|
|
181
|
-
class ContactRecord
|
|
182
|
-
attr_reader :wa_id, :phone_number, :profile_name, :metadata
|
|
183
|
-
|
|
184
|
-
def initialize(data)
|
|
185
|
-
@wa_id = data['wa_id']
|
|
186
|
-
@phone_number = data['phone_number']
|
|
187
|
-
@profile_name = data['profile_name']
|
|
188
|
-
@metadata = data['metadata']
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
# Call structures
|
|
193
|
-
class CallRecord
|
|
194
|
-
attr_reader :id, :direction, :status, :duration_seconds, :started_at,
|
|
195
|
-
:ended_at, :whatsapp_conversation_id, :whatsapp_contact_id
|
|
196
|
-
|
|
197
|
-
def initialize(data)
|
|
198
|
-
@id = data['id']
|
|
199
|
-
@direction = data['direction']
|
|
200
|
-
@status = data['status']
|
|
201
|
-
@duration_seconds = data['duration_seconds']
|
|
202
|
-
@started_at = data['started_at']
|
|
203
|
-
@ended_at = data['ended_at']
|
|
204
|
-
@whatsapp_conversation_id = data['whatsapp_conversation_id']
|
|
205
|
-
@whatsapp_contact_id = data['whatsapp_contact_id']
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
class CallConnectResponse
|
|
210
|
-
attr_reader :messaging_product, :calls
|
|
211
|
-
|
|
212
|
-
def initialize(data)
|
|
213
|
-
@messaging_product = data['messaging_product']
|
|
214
|
-
@calls = data['calls'] || []
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
class CallActionResponse < GraphSuccessResponse
|
|
219
|
-
attr_reader :messaging_product
|
|
220
|
-
|
|
221
|
-
def initialize(data)
|
|
222
|
-
super(data)
|
|
223
|
-
@messaging_product = data['messaging_product']
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
#
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KapsoClientRuby
|
|
4
|
+
module Types
|
|
5
|
+
# Message status types
|
|
6
|
+
MESSAGE_STATUSES = %w[accepted held_for_quality_assessment].freeze
|
|
7
|
+
|
|
8
|
+
# Template status types
|
|
9
|
+
TEMPLATE_STATUSES = %w[APPROVED PENDING REJECTED PAUSED IN_APPEAL DISABLED].freeze
|
|
10
|
+
|
|
11
|
+
# Template categories
|
|
12
|
+
TEMPLATE_CATEGORIES = %w[MARKETING UTILITY AUTHENTICATION UNKNOWN].freeze
|
|
13
|
+
|
|
14
|
+
# Media types
|
|
15
|
+
MEDIA_TYPES = %w[image audio video document sticker].freeze
|
|
16
|
+
|
|
17
|
+
# Interactive message types
|
|
18
|
+
INTERACTIVE_TYPES = %w[button list product product_list flow address location_request call_permission].freeze
|
|
19
|
+
|
|
20
|
+
# Message response structure
|
|
21
|
+
class SendMessageResponse
|
|
22
|
+
attr_reader :messaging_product, :contacts, :messages
|
|
23
|
+
|
|
24
|
+
def initialize(data)
|
|
25
|
+
@messaging_product = data['messaging_product']
|
|
26
|
+
@contacts = data['contacts']&.map { |c| MessageContact.new(c) } || []
|
|
27
|
+
@messages = data['messages']&.map { |m| MessageInfo.new(m) } || []
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class MessageContact
|
|
32
|
+
attr_reader :input, :wa_id
|
|
33
|
+
|
|
34
|
+
def initialize(data)
|
|
35
|
+
@input = data['input']
|
|
36
|
+
@wa_id = data['wa_id']
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class MessageInfo
|
|
41
|
+
attr_reader :id, :message_status
|
|
42
|
+
|
|
43
|
+
def initialize(data)
|
|
44
|
+
@id = data['id']
|
|
45
|
+
@message_status = data['message_status']
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Media response structures
|
|
50
|
+
class MediaUploadResponse
|
|
51
|
+
attr_reader :id
|
|
52
|
+
|
|
53
|
+
def initialize(data)
|
|
54
|
+
@id = data['id']
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class MediaMetadataResponse
|
|
59
|
+
attr_reader :messaging_product, :url, :mime_type, :sha256, :file_size, :id
|
|
60
|
+
|
|
61
|
+
def initialize(data)
|
|
62
|
+
@messaging_product = data['messaging_product']
|
|
63
|
+
@url = data['url']
|
|
64
|
+
@mime_type = data['mime_type']
|
|
65
|
+
@sha256 = data['sha256']
|
|
66
|
+
@file_size = data['file_size']
|
|
67
|
+
@id = data['id']
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Template structures
|
|
72
|
+
class MessageTemplate
|
|
73
|
+
attr_reader :id, :name, :category, :language, :status, :components,
|
|
74
|
+
:quality_score_category, :warnings, :previous_category,
|
|
75
|
+
:library_template_name, :last_updated_time
|
|
76
|
+
|
|
77
|
+
def initialize(data)
|
|
78
|
+
@id = data['id']
|
|
79
|
+
@name = data['name']
|
|
80
|
+
@category = data['category']
|
|
81
|
+
@language = data['language']
|
|
82
|
+
@status = data['status']
|
|
83
|
+
@components = data['components']
|
|
84
|
+
@quality_score_category = data['quality_score_category']
|
|
85
|
+
@warnings = data['warnings']
|
|
86
|
+
@previous_category = data['previous_category']
|
|
87
|
+
@library_template_name = data['library_template_name']
|
|
88
|
+
@last_updated_time = data['last_updated_time']
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class TemplateCreateResponse
|
|
93
|
+
attr_reader :id, :status, :category
|
|
94
|
+
|
|
95
|
+
def initialize(data)
|
|
96
|
+
@id = data['id']
|
|
97
|
+
@status = data['status']
|
|
98
|
+
@category = data['category']
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Paging structures
|
|
103
|
+
class GraphPaging
|
|
104
|
+
attr_reader :cursors, :next_page, :previous_page
|
|
105
|
+
|
|
106
|
+
def initialize(data)
|
|
107
|
+
@cursors = data['cursors'] || {}
|
|
108
|
+
@next_page = data['next']
|
|
109
|
+
@previous_page = data['previous']
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def before
|
|
113
|
+
cursors['before']
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def after
|
|
117
|
+
cursors['after']
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class PagedResponse
|
|
122
|
+
attr_reader :data, :paging
|
|
123
|
+
|
|
124
|
+
def initialize(data, item_class = nil)
|
|
125
|
+
@data = if item_class && data['data'].is_a?(Array)
|
|
126
|
+
data['data'].map { |item| item_class.new(item) }
|
|
127
|
+
else
|
|
128
|
+
data['data'] || []
|
|
129
|
+
end
|
|
130
|
+
@paging = GraphPaging.new(data['paging'] || {})
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Success response
|
|
135
|
+
class GraphSuccessResponse
|
|
136
|
+
attr_reader :success
|
|
137
|
+
|
|
138
|
+
def initialize(data = nil)
|
|
139
|
+
@success = data.nil? || data['success'] || true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def success?
|
|
143
|
+
@success
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Business profile structures
|
|
148
|
+
class BusinessProfileEntry
|
|
149
|
+
attr_reader :about, :address, :description, :email, :websites,
|
|
150
|
+
:vertical, :profile_picture_url, :profile_picture_handle
|
|
151
|
+
|
|
152
|
+
def initialize(data)
|
|
153
|
+
@about = data['about']
|
|
154
|
+
@address = data['address']
|
|
155
|
+
@description = data['description']
|
|
156
|
+
@email = data['email']
|
|
157
|
+
@websites = data['websites']
|
|
158
|
+
@vertical = data['vertical']
|
|
159
|
+
@profile_picture_url = data['profile_picture_url']
|
|
160
|
+
@profile_picture_handle = data['profile_picture_handle']
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Conversation structures
|
|
165
|
+
class ConversationRecord
|
|
166
|
+
attr_reader :id, :phone_number, :phone_number_id, :status, :last_active_at,
|
|
167
|
+
:kapso, :metadata
|
|
168
|
+
|
|
169
|
+
def initialize(data)
|
|
170
|
+
@id = data['id']
|
|
171
|
+
@phone_number = data['phone_number']
|
|
172
|
+
@phone_number_id = data['phone_number_id']
|
|
173
|
+
@status = data['status']
|
|
174
|
+
@last_active_at = data['last_active_at']
|
|
175
|
+
@kapso = data['kapso']
|
|
176
|
+
@metadata = data['metadata']
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Contact structures
|
|
181
|
+
class ContactRecord
|
|
182
|
+
attr_reader :wa_id, :phone_number, :profile_name, :metadata
|
|
183
|
+
|
|
184
|
+
def initialize(data)
|
|
185
|
+
@wa_id = data['wa_id']
|
|
186
|
+
@phone_number = data['phone_number']
|
|
187
|
+
@profile_name = data['profile_name']
|
|
188
|
+
@metadata = data['metadata']
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Call structures
|
|
193
|
+
class CallRecord
|
|
194
|
+
attr_reader :id, :direction, :status, :duration_seconds, :started_at,
|
|
195
|
+
:ended_at, :whatsapp_conversation_id, :whatsapp_contact_id
|
|
196
|
+
|
|
197
|
+
def initialize(data)
|
|
198
|
+
@id = data['id']
|
|
199
|
+
@direction = data['direction']
|
|
200
|
+
@status = data['status']
|
|
201
|
+
@duration_seconds = data['duration_seconds']
|
|
202
|
+
@started_at = data['started_at']
|
|
203
|
+
@ended_at = data['ended_at']
|
|
204
|
+
@whatsapp_conversation_id = data['whatsapp_conversation_id']
|
|
205
|
+
@whatsapp_contact_id = data['whatsapp_contact_id']
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
class CallConnectResponse
|
|
210
|
+
attr_reader :messaging_product, :calls
|
|
211
|
+
|
|
212
|
+
def initialize(data)
|
|
213
|
+
@messaging_product = data['messaging_product']
|
|
214
|
+
@calls = data['calls'] || []
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
class CallActionResponse < GraphSuccessResponse
|
|
219
|
+
attr_reader :messaging_product
|
|
220
|
+
|
|
221
|
+
def initialize(data)
|
|
222
|
+
super(data)
|
|
223
|
+
@messaging_product = data['messaging_product']
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Flow structures
|
|
228
|
+
class FlowResponse
|
|
229
|
+
attr_reader :id, :name, :status, :categories, :validation_errors, :json_version
|
|
230
|
+
|
|
231
|
+
def initialize(data)
|
|
232
|
+
@id = data['id']
|
|
233
|
+
@name = data['name']
|
|
234
|
+
@status = data['status']
|
|
235
|
+
@categories = data['categories'] || []
|
|
236
|
+
@validation_errors = data['validation_errors']
|
|
237
|
+
@json_version = data['json_version']
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
class FlowData < FlowResponse
|
|
242
|
+
attr_reader :endpoint_uri, :preview, :whatsapp_business_account, :application
|
|
243
|
+
|
|
244
|
+
def initialize(data)
|
|
245
|
+
super(data)
|
|
246
|
+
@endpoint_uri = data['endpoint_uri']
|
|
247
|
+
@preview = data['preview']
|
|
248
|
+
@whatsapp_business_account = data['whatsapp_business_account']
|
|
249
|
+
@application = data['application']
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
class FlowAssetResponse
|
|
254
|
+
attr_reader :validation_errors, :success
|
|
255
|
+
|
|
256
|
+
def initialize(data)
|
|
257
|
+
@validation_errors = data['validation_errors'] || []
|
|
258
|
+
@success = data['success'] || validation_errors.empty?
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def valid?
|
|
262
|
+
validation_errors.empty?
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def errors
|
|
266
|
+
validation_errors
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
class FlowPreviewResponse
|
|
271
|
+
attr_reader :preview_url, :expires_at
|
|
272
|
+
|
|
273
|
+
def initialize(data)
|
|
274
|
+
preview_data = data['preview'] || {}
|
|
275
|
+
@preview_url = preview_data['preview_url']
|
|
276
|
+
@expires_at = preview_data['expires_at']
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
class FlowEventData
|
|
281
|
+
attr_reader :version, :screen, :data, :flow_token, :action
|
|
282
|
+
|
|
283
|
+
def initialize(data)
|
|
284
|
+
@version = data['version']
|
|
285
|
+
@screen = data['screen']
|
|
286
|
+
@data = data['data'] || {}
|
|
287
|
+
@flow_token = data['flow_token']
|
|
288
|
+
@action = data['action']
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
class FlowScreen
|
|
293
|
+
attr_reader :id, :title, :data, :terminal, :success, :error_message
|
|
294
|
+
|
|
295
|
+
def initialize(data)
|
|
296
|
+
@id = data['id']
|
|
297
|
+
@title = data['title']
|
|
298
|
+
@data = data['data'] || {}
|
|
299
|
+
@terminal = data['terminal'] || false
|
|
300
|
+
@success = data['success']
|
|
301
|
+
@error_message = data['error_message']
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def terminal?
|
|
305
|
+
@terminal
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def success?
|
|
309
|
+
@success
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Utility method to convert snake_case to camelCase for API requests
|
|
314
|
+
def self.to_camel_case(str)
|
|
315
|
+
str.split('_').map.with_index { |word, i| i == 0 ? word : word.capitalize }.join
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Utility method to convert camelCase to snake_case for Ruby conventions
|
|
319
|
+
def self.to_snake_case(str)
|
|
320
|
+
str.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Deep convert hash keys from camelCase to snake_case
|
|
324
|
+
def self.deep_snake_case_keys(obj)
|
|
325
|
+
case obj
|
|
326
|
+
when Hash
|
|
327
|
+
obj.transform_keys { |key| to_snake_case(key.to_s) }
|
|
328
|
+
.transform_values { |value| deep_snake_case_keys(value) }
|
|
329
|
+
when Array
|
|
330
|
+
obj.map { |item| deep_snake_case_keys(item) }
|
|
331
|
+
else
|
|
332
|
+
obj
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Deep convert hash keys from snake_case to camelCase
|
|
337
|
+
def self.deep_camel_case_keys(obj)
|
|
338
|
+
case obj
|
|
339
|
+
when Hash
|
|
340
|
+
obj.transform_keys { |key| to_camel_case(key.to_s) }
|
|
341
|
+
.transform_values { |value| deep_camel_case_keys(value) }
|
|
342
|
+
when Array
|
|
343
|
+
obj.map { |item| deep_camel_case_keys(item) }
|
|
344
|
+
else
|
|
345
|
+
obj
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
263
349
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module KapsoClientRuby
|
|
4
|
-
VERSION = '1.0.
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KapsoClientRuby
|
|
4
|
+
VERSION = '1.0.2'
|
|
5
|
+
end
|