sendly 3.17.0 → 3.18.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15af9e5d9f56aa0bec8c4f3a10027bfc3df384346106b266b0105a2be3f22e10
4
- data.tar.gz: 5c3d6188cce94d0473b4c37993cce1f2b38a182462de4bd3fab985fe869f2561
3
+ metadata.gz: b45492ba74b05f9d480cea6a2a911c8b6ec9b66c5e197230a0a10ea81e4692f9
4
+ data.tar.gz: 981f6d67200e9725c9e0f546d65a9b575a3cfc4a1d5b935bd8f0c5c2034a1dd1
5
5
  SHA512:
6
- metadata.gz: 42099b42ad72620ea0c33c891711f2ef4f3bb26af55207aeceffc6151a510b83c7dd43f29db26665d186b62f3d4225c50604a4219e24d13e12efad52e75c5c55
7
- data.tar.gz: f04793910474e643da575f141e47b0b102111a14e586143009bf5e420bce87b7035019295200520e9e9e079fce6e3ccc8474a5ea40b3f7fe4c0b82fb7bacd11e
6
+ metadata.gz: 7724bb3862a1b21aab27d4470b41b468585bfbce1fc73eb4f62c851afd710b8e24b54362cd2da64d6e3833b859717510220f4ccf502786330d04950f056fbe8f
7
+ data.tar.gz: e4319bb9b9a322d2b119e1dd1c6da32e68e4c178e2006a2987058a7a5af6112fde9a590aaeee18691ea7427b3b06f0e31be1a351d5e1d2b4ba51c9c89f12987f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sendly (3.17.0)
4
+ sendly (3.18.0)
5
5
  faraday (~> 2.0)
6
6
  faraday-retry (~> 2.0)
7
7
 
data/lib/sendly/client.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "net/http"
4
4
  require "uri"
5
5
  require "json"
6
+ require "securerandom"
6
7
 
7
8
  module Sendly
8
9
  # Main Sendly API client
@@ -73,6 +74,13 @@ module Sendly
73
74
  @templates ||= TemplatesResource.new(self)
74
75
  end
75
76
 
77
+ # Access the Media resource
78
+ #
79
+ # @return [Sendly::Media]
80
+ def media
81
+ @media ||= Media.new(self)
82
+ end
83
+
76
84
  # Access the Campaigns resource
77
85
  #
78
86
  # @return [Sendly::CampaignsResource]
@@ -122,6 +130,60 @@ module Sendly
122
130
  request(:delete, path)
123
131
  end
124
132
 
133
+ # Make a multipart POST request for file uploads
134
+ #
135
+ # @param path [String] API path
136
+ # @param file [String, IO] File path or IO object
137
+ # @param content_type [String] MIME type of the file
138
+ # @param filename [String] Name for the uploaded file
139
+ # @return [Hash] Response body
140
+ def post_multipart(path, file, content_type: "image/jpeg", filename: "upload.jpg")
141
+ uri = build_uri(path, {})
142
+ http = build_http(uri)
143
+
144
+ boundary = "SendlyRuby#{SecureRandom.hex(16)}"
145
+
146
+ file_data = file.is_a?(String) ? File.binread(file) : file.read
147
+
148
+ body = []
149
+ body << "--#{boundary}\r\n"
150
+ body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{filename}\"\r\n"
151
+ body << "Content-Type: #{content_type}\r\n\r\n"
152
+ body << file_data
153
+ body << "\r\n--#{boundary}--\r\n"
154
+
155
+ req = Net::HTTP::Post.new(uri)
156
+ req["Authorization"] = "Bearer #{api_key}"
157
+ req["Accept"] = "application/json"
158
+ req["User-Agent"] = "sendly-ruby/#{VERSION}"
159
+ req["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
160
+ req.body = body.join
161
+
162
+ attempt = 0
163
+ begin
164
+ response = http.request(req)
165
+ handle_response(response)
166
+ rescue Net::OpenTimeout, Net::ReadTimeout
167
+ raise TimeoutError, "Request timed out after #{timeout} seconds"
168
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET, SocketError => e
169
+ raise NetworkError, "Connection failed: #{e.message}"
170
+ rescue RateLimitError => e
171
+ attempt += 1
172
+ if attempt <= max_retries && e.retry_after
173
+ sleep(e.retry_after)
174
+ retry
175
+ end
176
+ raise
177
+ rescue ServerError => e
178
+ attempt += 1
179
+ if attempt <= max_retries
180
+ sleep(2 ** attempt)
181
+ retry
182
+ end
183
+ raise
184
+ end
185
+ end
186
+
125
187
  private
126
188
 
127
189
  def validate_api_key!
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sendly
4
+ class Media
5
+ attr_reader :client
6
+
7
+ def initialize(client)
8
+ @client = client
9
+ end
10
+
11
+ def upload(file, content_type: "image/jpeg", filename: "upload.jpg")
12
+ response = client.post_multipart("/media", file, content_type: content_type, filename: filename)
13
+ MediaFile.new(response)
14
+ end
15
+ end
16
+ end
@@ -36,13 +36,14 @@ module Sendly
36
36
  # text: "Your verification code is 123456",
37
37
  # message_type: "transactional"
38
38
  # )
39
- def send(to:, text:, message_type: nil, metadata: nil)
39
+ def send(to:, text:, message_type: nil, metadata: nil, media_urls: nil)
40
40
  validate_phone!(to)
41
41
  validate_text!(text)
42
42
 
43
43
  body = { to: to, text: text }
44
44
  body[:messageType] = message_type if message_type
45
45
  body[:metadata] = metadata if metadata
46
+ body[:mediaUrls] = media_urls if media_urls
46
47
 
47
48
  response = client.post("/messages", body)
48
49
  # API returns message directly at top level
data/lib/sendly/types.rb CHANGED
@@ -203,6 +203,30 @@ module Sendly
203
203
  end
204
204
  end
205
205
 
206
+ # ============================================================================
207
+ # Media
208
+ # ============================================================================
209
+
210
+ class MediaFile
211
+ attr_reader :id, :url, :content_type, :size_bytes
212
+
213
+ def initialize(data)
214
+ @id = data["id"]
215
+ @url = data["url"]
216
+ @content_type = data["contentType"]
217
+ @size_bytes = data["sizeBytes"]
218
+ end
219
+
220
+ def to_h
221
+ {
222
+ id: id,
223
+ url: url,
224
+ content_type: content_type,
225
+ size_bytes: size_bytes
226
+ }.compact
227
+ end
228
+ end
229
+
206
230
  # ============================================================================
207
231
  # Webhooks
208
232
  # ============================================================================
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sendly
4
- VERSION = "3.17.0"
4
+ VERSION = "3.18.0"
5
5
  end
data/lib/sendly.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "sendly/errors"
8
8
  require_relative "sendly/types"
9
9
  require_relative "sendly/client"
10
10
  require_relative "sendly/messages"
11
+ require_relative "sendly/media"
11
12
  require_relative "sendly/webhooks"
12
13
  require_relative "sendly/webhooks_resource"
13
14
  require_relative "sendly/account_resource"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sendly
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.17.0
4
+ version: 3.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sendly
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-23 00:00:00.000000000 Z
11
+ date: 2026-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -128,6 +128,7 @@ files:
128
128
  - lib/sendly/client.rb
129
129
  - lib/sendly/contacts_resource.rb
130
130
  - lib/sendly/errors.rb
131
+ - lib/sendly/media.rb
131
132
  - lib/sendly/messages.rb
132
133
  - lib/sendly/templates_resource.rb
133
134
  - lib/sendly/types.rb