kapso-client-ruby 1.0.1 → 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 +477 -477
- data/README.md +1053 -752
- 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 +387 -387
- data/examples/rails/models.rb +239 -239
- data/examples/rails/notifications_controller.rb +226 -226
- 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 +75 -75
- data/lib/kapso_client_ruby/rails/generators/templates/env.erb +20 -20
- data/lib/kapso_client_ruby/rails/generators/templates/initializer.rb.erb +32 -32
- data/lib/kapso_client_ruby/rails/generators/templates/message_service.rb.erb +137 -137
- data/lib/kapso_client_ruby/rails/generators/templates/webhook_controller.rb.erb +61 -61
- data/lib/kapso_client_ruby/rails/railtie.rb +54 -54
- data/lib/kapso_client_ruby/rails/service.rb +188 -188
- data/lib/kapso_client_ruby/rails/tasks.rake +166 -166
- 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 -74
- 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 +12 -3
|
@@ -1,254 +1,257 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require '
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
puts "
|
|
35
|
-
puts "
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
puts "
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{ type: '
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
puts "
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
#
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
#
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
puts "
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
#
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
puts "
|
|
193
|
-
puts "
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
puts "
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
puts "
|
|
238
|
-
raise
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kapso-client-ruby'
|
|
4
|
+
require 'dotenv'
|
|
5
|
+
|
|
6
|
+
Dotenv.load
|
|
7
|
+
|
|
8
|
+
puts "=== Media Management Examples ==="
|
|
9
|
+
|
|
10
|
+
# Initialize client
|
|
11
|
+
client = KapsoClientRuby::Client.new(
|
|
12
|
+
access_token: ENV['WHATSAPP_ACCESS_TOKEN'],
|
|
13
|
+
debug: true # Enable debug logging
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Example 1: Upload Media File
|
|
17
|
+
puts "\n--- Upload Media File ---"
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
# Upload an image file
|
|
21
|
+
upload_response = client.media.upload(
|
|
22
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
23
|
+
type: 'image',
|
|
24
|
+
file: 'path/to/your/image.jpg', # Replace with actual file path
|
|
25
|
+
filename: 'my_image.jpg'
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
media_id = upload_response.id
|
|
29
|
+
puts "File uploaded successfully!"
|
|
30
|
+
puts "Media ID: #{media_id}"
|
|
31
|
+
|
|
32
|
+
# Get media metadata
|
|
33
|
+
metadata = client.media.get(media_id: media_id)
|
|
34
|
+
puts "\nMedia Metadata:"
|
|
35
|
+
puts "URL: #{metadata.url}"
|
|
36
|
+
puts "MIME Type: #{metadata.mime_type}"
|
|
37
|
+
puts "File Size: #{metadata.file_size} bytes"
|
|
38
|
+
puts "SHA256: #{metadata.sha256}"
|
|
39
|
+
|
|
40
|
+
# Send the uploaded media
|
|
41
|
+
message_response = client.messages.send_image(
|
|
42
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
43
|
+
to: '+1234567890',
|
|
44
|
+
image: { id: media_id, caption: 'Uploaded via Ruby SDK!' }
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
puts "\nMessage sent with uploaded media: #{message_response.messages.first.id}"
|
|
48
|
+
|
|
49
|
+
rescue KapsoClientRuby::Errors::GraphApiError => e
|
|
50
|
+
puts "Upload error: #{e.message}"
|
|
51
|
+
puts "Category: #{e.category}"
|
|
52
|
+
|
|
53
|
+
case e.category
|
|
54
|
+
when :media
|
|
55
|
+
puts "Media-specific error - check file format, size, or type"
|
|
56
|
+
when :parameter
|
|
57
|
+
puts "Parameter error - check phone_number_id and file path"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Example 2: Upload Different Media Types
|
|
62
|
+
puts "\n--- Upload Different Media Types ---"
|
|
63
|
+
|
|
64
|
+
media_examples = [
|
|
65
|
+
{ type: 'image', file: 'examples/sample_image.jpg', message_method: :send_image },
|
|
66
|
+
{ type: 'audio', file: 'examples/sample_audio.mp3', message_method: :send_audio },
|
|
67
|
+
{ type: 'video', file: 'examples/sample_video.mp4', message_method: :send_video },
|
|
68
|
+
{ type: 'document', file: 'examples/sample_document.pdf', message_method: :send_document }
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
media_examples.each do |example|
|
|
72
|
+
begin
|
|
73
|
+
next unless File.exist?(example[:file]) # Skip if file doesn't exist
|
|
74
|
+
|
|
75
|
+
puts "\nUploading #{example[:type]}: #{example[:file]}"
|
|
76
|
+
|
|
77
|
+
upload_response = client.media.upload(
|
|
78
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
79
|
+
type: example[:type],
|
|
80
|
+
file: example[:file]
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
puts "Uploaded #{example[:type]} - Media ID: #{upload_response.id}"
|
|
84
|
+
|
|
85
|
+
# Send message with the uploaded media
|
|
86
|
+
case example[:message_method]
|
|
87
|
+
when :send_image
|
|
88
|
+
client.messages.send_image(
|
|
89
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
90
|
+
to: '+1234567890',
|
|
91
|
+
image: { id: upload_response.id, caption: "#{example[:type].capitalize} via Ruby SDK" }
|
|
92
|
+
)
|
|
93
|
+
when :send_audio
|
|
94
|
+
client.messages.send_audio(
|
|
95
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
96
|
+
to: '+1234567890',
|
|
97
|
+
audio: { id: upload_response.id }
|
|
98
|
+
)
|
|
99
|
+
when :send_video
|
|
100
|
+
client.messages.send_video(
|
|
101
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
102
|
+
to: '+1234567890',
|
|
103
|
+
video: { id: upload_response.id, caption: "Video via Ruby SDK" }
|
|
104
|
+
)
|
|
105
|
+
when :send_document
|
|
106
|
+
client.messages.send_document(
|
|
107
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
108
|
+
to: '+1234567890',
|
|
109
|
+
document: {
|
|
110
|
+
id: upload_response.id,
|
|
111
|
+
caption: "Document via Ruby SDK",
|
|
112
|
+
filename: File.basename(example[:file])
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
puts "Message sent successfully!"
|
|
118
|
+
|
|
119
|
+
rescue KapsoClientRuby::Errors::GraphApiError => e
|
|
120
|
+
puts "Error with #{example[:type]}: #{e.message}"
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
puts "File error with #{example[:file]}: #{e.message}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Example 3: Download Media
|
|
127
|
+
puts "\n--- Download Media ---"
|
|
128
|
+
|
|
129
|
+
begin
|
|
130
|
+
# First, get a media ID (you would normally get this from webhook or previous upload)
|
|
131
|
+
sample_media_id = "your_media_id_here" # Replace with actual media ID
|
|
132
|
+
|
|
133
|
+
# Download media content
|
|
134
|
+
puts "Downloading media: #{sample_media_id}"
|
|
135
|
+
|
|
136
|
+
# Method 1: Download to memory
|
|
137
|
+
content = client.media.download(
|
|
138
|
+
media_id: sample_media_id,
|
|
139
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
140
|
+
as: :binary
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
puts "Downloaded #{content.length} bytes"
|
|
144
|
+
|
|
145
|
+
# Method 2: Save directly to file
|
|
146
|
+
saved_path = client.media.save_to_file(
|
|
147
|
+
media_id: sample_media_id,
|
|
148
|
+
filepath: "downloaded_media_#{sample_media_id}.jpg",
|
|
149
|
+
phone_number_id: ENV['PHONE_NUMBER_ID']
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
puts "Media saved to: #{saved_path}"
|
|
153
|
+
|
|
154
|
+
# Method 3: Get as base64
|
|
155
|
+
base64_content = client.media.download(
|
|
156
|
+
media_id: sample_media_id,
|
|
157
|
+
phone_number_id: ENV['PHONE_NUMBER_ID'],
|
|
158
|
+
as: :base64
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
puts "Base64 content (first 100 chars): #{base64_content[0..100]}..."
|
|
162
|
+
|
|
163
|
+
rescue KapsoClientRuby::Errors::GraphApiError => e
|
|
164
|
+
puts "Download error: #{e.message}"
|
|
165
|
+
|
|
166
|
+
if e.http_status == 404
|
|
167
|
+
puts "Media not found - it may have been deleted or expired"
|
|
168
|
+
elsif e.http_status == 403
|
|
169
|
+
puts "Access denied - check your permissions"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Example 4: Media Management with Kapso Proxy
|
|
174
|
+
puts "\n--- Media Management with Kapso Proxy ---"
|
|
175
|
+
|
|
176
|
+
begin
|
|
177
|
+
# Initialize Kapso client
|
|
178
|
+
kapso_client = KapsoClientRuby::Client.new(
|
|
179
|
+
kapso_api_key: ENV['KAPSO_API_KEY'],
|
|
180
|
+
base_url: 'https://app.kapso.ai/api/meta'
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# With Kapso proxy, phone_number_id is required for media operations
|
|
184
|
+
media_id = "sample_media_id"
|
|
185
|
+
|
|
186
|
+
# Get media info (includes enhanced metadata from Kapso)
|
|
187
|
+
info = kapso_client.media.info(
|
|
188
|
+
media_id: media_id,
|
|
189
|
+
phone_number_id: ENV['PHONE_NUMBER_ID']
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
puts "Media Info:"
|
|
193
|
+
puts "ID: #{info[:id]}"
|
|
194
|
+
puts "MIME Type: #{info[:mime_type]}"
|
|
195
|
+
puts "Size: #{info[:file_size]} bytes"
|
|
196
|
+
puts "URL: #{info[:url]}"
|
|
197
|
+
|
|
198
|
+
rescue KapsoClientRuby::Errors::GraphApiError => e
|
|
199
|
+
puts "Kapso media error: #{e.message}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Example 5: Error Handling and Retry Logic
|
|
203
|
+
puts "\n--- Error Handling and Retry Logic ---"
|
|
204
|
+
|
|
205
|
+
def upload_with_retry(client, phone_number_id, file_path, max_retries = 3)
|
|
206
|
+
retries = 0
|
|
207
|
+
|
|
208
|
+
begin
|
|
209
|
+
client.media.upload(
|
|
210
|
+
phone_number_id: phone_number_id,
|
|
211
|
+
type: 'image',
|
|
212
|
+
file: file_path
|
|
213
|
+
)
|
|
214
|
+
rescue KapsoClientRuby::Errors::GraphApiError => e
|
|
215
|
+
retries += 1
|
|
216
|
+
|
|
217
|
+
case e.retry_hint[:action]
|
|
218
|
+
when :retry
|
|
219
|
+
if retries <= max_retries
|
|
220
|
+
puts "Retrying upload (attempt #{retries}/#{max_retries})..."
|
|
221
|
+
sleep(1 * retries) # Exponential backoff
|
|
222
|
+
retry
|
|
223
|
+
else
|
|
224
|
+
puts "Max retries exceeded"
|
|
225
|
+
raise
|
|
226
|
+
end
|
|
227
|
+
when :retry_after
|
|
228
|
+
if retries <= max_retries && e.retry_hint[:retry_after_ms]
|
|
229
|
+
delay_seconds = e.retry_hint[:retry_after_ms] / 1000.0
|
|
230
|
+
puts "Rate limited. Waiting #{delay_seconds} seconds..."
|
|
231
|
+
sleep(delay_seconds)
|
|
232
|
+
retry
|
|
233
|
+
else
|
|
234
|
+
raise
|
|
235
|
+
end
|
|
236
|
+
when :do_not_retry
|
|
237
|
+
puts "Permanent error - do not retry: #{e.message}"
|
|
238
|
+
raise
|
|
239
|
+
else
|
|
240
|
+
puts "Unknown error - manual intervention needed: #{e.message}"
|
|
241
|
+
raise
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
begin
|
|
247
|
+
response = upload_with_retry(
|
|
248
|
+
client,
|
|
249
|
+
ENV['PHONE_NUMBER_ID'],
|
|
250
|
+
'examples/sample_image.jpg'
|
|
251
|
+
)
|
|
252
|
+
puts "Upload successful with retry logic: #{response.id}"
|
|
253
|
+
rescue => e
|
|
254
|
+
puts "Final upload error: #{e.message}"
|
|
255
|
+
end
|
|
256
|
+
|
|
254
257
|
puts "\n=== Media Management Examples Completed ==="
|