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