customerio 5.6.0 → 6.1.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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "addressable/uri"
2
4
 
3
5
  module Customerio
@@ -8,21 +10,40 @@ module Customerio
8
10
  end
9
11
 
10
12
  class Client
11
- PUSH_OPENED = 'opened'
12
- PUSH_CONVERTED = 'converted'
13
- PUSH_DELIVERED = 'delivered'
14
-
15
- VALID_PUSH_EVENTS = [PUSH_OPENED, PUSH_CONVERTED, PUSH_DELIVERED]
16
-
17
- class MissingIdAttributeError < RuntimeError; end
18
- class ParamError < RuntimeError; end
13
+ DELIVERY_OPENED = "opened"
14
+ DELIVERY_CLICKED = "clicked"
15
+ DELIVERY_CONVERTED = "converted"
16
+ DELIVERY_DELIVERED = "delivered"
17
+ DELIVERY_BOUNCED = "bounced"
18
+ DELIVERY_DEFERRED = "deferred"
19
+ DELIVERY_DROPPED = "dropped"
20
+ DELIVERY_SPAMMED = "spammed"
21
+
22
+ VALID_DELIVERY_METRICS = [
23
+ DELIVERY_OPENED, DELIVERY_CLICKED, DELIVERY_CONVERTED,
24
+ DELIVERY_DELIVERED, DELIVERY_BOUNCED, DELIVERY_DEFERRED,
25
+ DELIVERY_DROPPED, DELIVERY_SPAMMED
26
+ ].freeze
27
+
28
+ VALID_PUSH_EVENTS = [DELIVERY_OPENED, DELIVERY_CONVERTED, DELIVERY_DELIVERED].freeze
29
+
30
+ # @deprecated Use DELIVERY_OPENED, DELIVERY_CONVERTED, DELIVERY_DELIVERED instead.
31
+ PUSH_OPENED = DELIVERY_OPENED
32
+ PUSH_CONVERTED = DELIVERY_CONVERTED
33
+ PUSH_DELIVERED = DELIVERY_DELIVERED
34
+
35
+ class MissingIdAttributeError < StandardError; end
36
+ class ParamError < StandardError; end
19
37
 
20
38
  def initialize(site_id, api_key, options = {})
21
- options[:region] = Customerio::Regions::US if options[:region].nil?
22
- raise "region must be an instance of Customerio::Regions::Region" unless options[:region].is_a?(Customerio::Regions::Region)
39
+ options = options.dup
40
+ options[:region] = Regions::US if options[:region].nil?
41
+ unless options[:region].is_a?(Regions::Region)
42
+ raise ArgumentError, "region must be an instance of Customerio::Regions::Region"
43
+ end
23
44
 
24
45
  options[:url] = options[:region].track_url if options[:url].nil? || options[:url].empty?
25
- @client = Customerio::BaseClient.new({ site_id: site_id, api_key: api_key }, options)
46
+ @client = BaseClient.new({ site_id: site_id, api_key: api_key }, options)
26
47
  end
27
48
 
28
49
  def identify(attributes)
@@ -30,90 +51,122 @@ module Customerio
30
51
  end
31
52
 
32
53
  def delete(customer_id)
33
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
54
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
55
+
34
56
  @client.request_and_verify_response(:delete, customer_path(customer_id))
35
57
  end
36
58
 
37
59
  def suppress(customer_id)
38
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
60
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
61
+
39
62
  @client.request_and_verify_response(:post, suppress_path(customer_id))
40
63
  end
41
64
 
42
65
  def unsuppress(customer_id)
43
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
66
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
67
+
44
68
  @client.request_and_verify_response(:post, unsuppress_path(customer_id))
45
69
  end
46
70
 
47
- def track(customer_id, event_name, attributes = {})
48
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
49
- raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
71
+ def track(customer_id, event_name, attributes = {}, id: nil, timestamp: nil)
72
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
73
+ raise ParamError, "event_name must be a non-empty string" if empty?(event_name)
50
74
 
51
- create_customer_event(customer_id, event_name, attributes)
75
+ create_customer_event(customer_id, event_name, attributes, id: id, timestamp: timestamp)
52
76
  end
53
77
 
54
78
  def pageview(customer_id, page, attributes = {})
55
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
56
- raise ParamError.new("page must be a non-empty string") if is_empty?(page)
79
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
80
+ raise ParamError, "page must be a non-empty string" if empty?(page)
57
81
 
58
82
  create_pageview_event(customer_id, page, attributes)
59
83
  end
60
84
 
61
- def track_anonymous(anonymous_id, event_name, attributes = {})
62
- raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
85
+ def track_anonymous(anonymous_id, event_name, attributes = {}, id: nil, timestamp: nil)
86
+ raise ParamError, "event_name must be a non-empty string" if empty?(event_name)
63
87
 
64
- create_anonymous_event(anonymous_id, event_name, attributes)
88
+ create_anonymous_event(anonymous_id, event_name, attributes, id: id, timestamp: timestamp)
65
89
  end
66
90
 
67
- def add_device(customer_id, device_id, platform, data={})
68
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
69
- raise ParamError.new("device_id must be a non-empty string") if is_empty?(device_id)
70
- raise ParamError.new("platform must be a non-empty string") if is_empty?(platform)
91
+ def add_device(customer_id, device_id, platform, data = {})
92
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
93
+ raise ParamError, "device_id must be a non-empty string" if empty?(device_id)
94
+ raise ParamError, "platform must be a non-empty string" if empty?(platform)
71
95
 
72
- if data.nil?
73
- data = {}
74
- end
96
+ data = {} if data.nil?
75
97
 
76
- raise ParamError.new("data parameter must be a hash") unless data.is_a?(Hash)
98
+ raise ParamError, "data parameter must be a hash" unless data.is_a?(Hash)
77
99
 
78
- @client.request_and_verify_response(:put, device_path(customer_id), {
79
- :device => data.update({
80
- :id => device_id,
81
- :platform => platform,
82
- })
83
- })
100
+ @client.request_and_verify_response(
101
+ :put,
102
+ device_path(customer_id),
103
+ device: data.merge(id: device_id, platform: platform)
104
+ )
84
105
  end
85
106
 
86
107
  def delete_device(customer_id, device_id)
87
- raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
88
- raise ParamError.new("device_id must be a non-empty string") if is_empty?(device_id)
108
+ raise ParamError, "customer_id must be a non-empty string" if empty?(customer_id)
109
+ raise ParamError, "device_id must be a non-empty string" if empty?(device_id)
89
110
 
90
111
  @client.request_and_verify_response(:delete, device_id_path(customer_id, device_id))
91
112
  end
92
113
 
93
114
  def track_push_notification_event(event_name, attributes = {})
94
- keys = [:delivery_id, :device_id, :timestamp]
95
- attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }].
96
- select { |k, v| keys.include?(k) }
115
+ keys = %i[delivery_id device_id timestamp]
116
+ attributes = symbolize_keys(attributes).slice(*keys)
117
+
118
+ unless VALID_PUSH_EVENTS.include?(event_name)
119
+ raise ParamError, "event_name must be one of opened, converted, or delivered"
120
+ end
121
+
122
+ raise ParamError, "delivery_id must be a non-empty string" if empty?(attributes[:delivery_id])
123
+ raise ParamError, "device_id must be a non-empty string" if empty?(attributes[:device_id])
124
+ raise ParamError, "timestamp must be a valid timestamp" unless valid_timestamp?(attributes[:timestamp])
125
+
126
+ @client.request_and_verify_response(
127
+ :post,
128
+ track_push_notification_event_path,
129
+ attributes.merge(event: event_name)
130
+ )
131
+ end
97
132
 
98
- raise ParamError.new('event_name must be one of opened, converted, or delivered') unless VALID_PUSH_EVENTS.include?(event_name)
99
- raise ParamError.new('delivery_id must be a non-empty string') unless attributes[:delivery_id] != "" and !attributes[:delivery_id].nil?
100
- raise ParamError.new('device_id must be a non-empty string') unless attributes[:device_id] != "" and !attributes[:device_id].nil?
101
- raise ParamError.new('timestamp must be a valid timestamp') unless valid_timestamp?(attributes[:timestamp])
133
+ def track_delivery_metric(metric_name, attributes = {})
134
+ keys = %i[delivery_id timestamp recipient reason href]
135
+ attributes = symbolize_keys(attributes).slice(*keys)
136
+
137
+ unless VALID_DELIVERY_METRICS.include?(metric_name)
138
+ raise ParamError, "metric_name must be one of: #{VALID_DELIVERY_METRICS.join(', ')}"
139
+ end
140
+
141
+ raise ParamError, "delivery_id must be a non-empty string" if empty?(attributes[:delivery_id])
142
+
143
+ body = { delivery_id: attributes[:delivery_id], metric: metric_name }
144
+ validate_timestamp!(attributes[:timestamp])
145
+ body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
146
+ body[:recipient] = attributes[:recipient] unless empty?(attributes[:recipient])
147
+ body[:reason] = attributes[:reason] unless empty?(attributes[:reason])
148
+ body[:href] = attributes[:href] unless empty?(attributes[:href])
102
149
 
103
- @client.request_and_verify_response(:post, track_push_notification_event_path, attributes.merge(event: event_name))
150
+ @client.request_and_verify_response(:post, delivery_metrics_path, body)
104
151
  end
105
152
 
106
153
  def merge_customers(primary_id_type, primary_id, secondary_id_type, secondary_id)
107
- raise ParamError.new("invalid primary_id_type") if !is_valid_id_type?(primary_id_type)
108
- raise ParamError.new("primary_id must be a non-empty string") if is_empty?(primary_id)
109
- raise ParamError.new("invalid secondary_id_type") if !is_valid_id_type?(secondary_id_type)
110
- raise ParamError.new("secondary_id must be a non-empty string") if is_empty?(secondary_id)
154
+ raise ParamError, "invalid primary_id_type" unless valid_id_type?(primary_id_type)
155
+ raise ParamError, "primary_id must be a non-empty string" if empty?(primary_id)
156
+ raise ParamError, "invalid secondary_id_type" unless valid_id_type?(secondary_id_type)
157
+ raise ParamError, "secondary_id must be a non-empty string" if empty?(secondary_id)
111
158
 
112
- body = { :primary => {primary_id_type => primary_id}, :secondary => {secondary_id_type => secondary_id} }
159
+ body = { primary: { primary_id_type => primary_id }, secondary: { secondary_id_type => secondary_id } }
113
160
 
114
161
  @client.request_and_verify_response(:post, merge_customers_path, body)
115
162
  end
116
163
 
164
+ def batch(operations)
165
+ raise ParamError, "operations must be a non-empty array" unless operations.is_a?(Array) && !operations.empty?
166
+
167
+ @client.request_and_verify_response(:post, batch_path, batch: operations)
168
+ end
169
+
117
170
  private
118
171
 
119
172
  def escape(val)
@@ -142,17 +195,25 @@ module Customerio
142
195
  end
143
196
 
144
197
  def track_push_notification_event_path
145
- "/push/events"
198
+ "/push/events"
199
+ end
200
+
201
+ def delivery_metrics_path
202
+ "/api/v1/metrics"
146
203
  end
147
204
 
148
205
  def merge_customers_path
149
206
  "/api/v1/merge_customers"
150
207
  end
151
208
 
209
+ def batch_path
210
+ "/api/v2/batch"
211
+ end
212
+
152
213
  def create_or_update(attributes = {})
153
- attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
154
- if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id]) && is_empty?(attributes[:customer_id])
155
- raise MissingIdAttributeError.new("Must provide a customer id")
214
+ attributes = symbolize_keys(attributes)
215
+ if empty?(attributes[:id]) && empty?(attributes[:cio_id]) && empty?(attributes[:customer_id])
216
+ raise MissingIdAttributeError, "Must provide a customer id"
156
217
  end
157
218
 
158
219
  # Use cio_id as the identifier, if present,
@@ -169,12 +230,9 @@ module Customerio
169
230
  #
170
231
  # 3. id: The id value.
171
232
  customer_id = attributes[:id]
172
- if !is_empty?(attributes[:cio_id])
173
- customer_id = "cio_" + attributes[:cio_id]
174
- end
175
- if !is_empty?(attributes[:customer_id])
176
- customer_id = attributes[:customer_id]
177
- end
233
+ customer_id = "cio_#{attributes[:cio_id]}" unless empty?(attributes[:cio_id])
234
+ customer_id = attributes[:customer_id] unless empty?(attributes[:customer_id])
235
+
178
236
  # customer_id is not an attribute, so remove it.
179
237
  attributes.delete(:customer_id)
180
238
 
@@ -182,20 +240,24 @@ module Customerio
182
240
  @client.request_and_verify_response(:put, url, attributes)
183
241
  end
184
242
 
185
- def create_customer_event(customer_id, event_name, attributes = {})
243
+ def create_customer_event(customer_id, event_name, attributes = {}, id: nil, timestamp: nil)
186
244
  create_event(
187
245
  url: "#{customer_path(customer_id)}/events",
188
246
  event_name: event_name,
189
- attributes: attributes
247
+ attributes: attributes,
248
+ id: id,
249
+ timestamp: timestamp
190
250
  )
191
251
  end
192
252
 
193
- def create_anonymous_event(anonymous_id, event_name, attributes = {})
253
+ def create_anonymous_event(anonymous_id, event_name, attributes = {}, id: nil, timestamp: nil)
194
254
  create_event(
195
255
  url: "/api/v1/events",
196
256
  event_name: event_name,
197
257
  anonymous_id: anonymous_id,
198
- attributes: attributes
258
+ attributes: attributes,
259
+ id: id,
260
+ timestamp: timestamp
199
261
  )
200
262
  end
201
263
 
@@ -208,25 +270,41 @@ module Customerio
208
270
  )
209
271
  end
210
272
 
211
- def create_event(url:, event_name:, anonymous_id: nil, event_type: nil, attributes: {})
212
- body = { :name => event_name, :data => attributes }
213
- body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
214
- body[:anonymous_id] = anonymous_id unless is_empty?(anonymous_id)
215
- body[:type] = event_type unless is_empty?(event_type)
273
+ def create_event(url:, event_name:, anonymous_id: nil, event_type: nil, attributes: {}, id: nil, timestamp: nil) # rubocop:disable Metrics/ParameterLists
274
+ body = { name: event_name, data: attributes }
275
+ effective_timestamp = timestamp || attributes[:timestamp]
276
+ if effective_timestamp
277
+ validate_timestamp!(effective_timestamp)
278
+ body[:timestamp] = effective_timestamp
279
+ end
280
+ body[:anonymous_id] = anonymous_id unless empty?(anonymous_id)
281
+ body[:type] = event_type unless empty?(event_type)
282
+ body[:id] = id unless empty?(id)
216
283
 
217
284
  @client.request_and_verify_response(:post, url, body)
218
285
  end
219
286
 
220
287
  def valid_timestamp?(timestamp)
221
- timestamp && timestamp.is_a?(Integer) && timestamp > 999999999 && timestamp < 100000000000
288
+ timestamp.is_a?(Integer) && timestamp > 999_999_999 && timestamp < 100_000_000_000
222
289
  end
223
290
 
224
- def is_empty?(val)
225
- val.nil? || (val.is_a?(String) && val.strip == "")
291
+ def validate_timestamp!(timestamp)
292
+ return if timestamp.nil?
293
+ return if valid_timestamp?(timestamp)
294
+
295
+ raise ParamError, "timestamp must be a valid integer (seconds since epoch, 10-digit range)"
226
296
  end
227
297
 
228
- def is_valid_id_type?(input)
298
+ def empty?(val)
299
+ val.nil? || (val.is_a?(String) && val.strip.empty?)
300
+ end
301
+
302
+ def valid_id_type?(input)
229
303
  [IdentifierType::ID, IdentifierType::CIOID, IdentifierType::EMAIL].include? input
230
304
  end
305
+
306
+ def symbolize_keys(hash)
307
+ hash.transform_keys(&:to_sym)
308
+ end
231
309
  end
232
310
  end
@@ -1,11 +1,10 @@
1
- require 'net/http'
2
- require 'multi_json'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Customerio
5
4
  module Regions
6
5
  Region = Struct.new(:track_url, :api_url)
7
6
 
8
- US = Customerio::Regions::Region.new('https://track.customer.io', 'https://api.customer.io').freeze
9
- EU = Customerio::Regions::Region.new('https://track-eu.customer.io', 'https://api-eu.customer.io').freeze
7
+ US = Region.new("https://track.customer.io", "https://api.customer.io").freeze
8
+ EU = Region.new("https://track-eu.customer.io", "https://api-eu.customer.io").freeze
10
9
  end
11
10
  end
@@ -1,25 +1,12 @@
1
- require 'base64'
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
2
4
 
3
5
  module Customerio
4
6
  class SendEmailRequest
5
- attr_reader :message
6
-
7
- def initialize(opts)
8
- @message = opts.delete_if { |field| invalid_field?(field) }
9
- @message[:attachments] = {}
10
- @message[:headers] = {}
11
- end
12
-
13
- def attach(name, data, encode: true)
14
- raise "attachment #{name} already exists" if @message[:attachments].has_key?(name)
15
- @message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
16
- end
17
-
18
- private
7
+ REQUIRED_FIELDS = %i[to identifiers].freeze
19
8
 
20
- REQUIRED_FIELDS = %i(to identifiers)
21
-
22
- OPTIONAL_FIELDS = %i(
9
+ OPTIONAL_FIELDS = %i[
23
10
  transactional_message_id
24
11
  message_data
25
12
  headers
@@ -39,14 +26,26 @@ module Customerio
39
26
  disable_css_preprocessing
40
27
  send_at
41
28
  language
42
- )
29
+ ].freeze
30
+
31
+ attr_reader :message
43
32
 
44
- def invalid_field?(field)
45
- !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
33
+ def initialize(opts)
34
+ @message = opts.select { |field, _value| valid_field?(field) }
35
+ @message[:attachments] ||= {}
36
+ @message[:headers] ||= {}
46
37
  end
47
38
 
48
- def encode(data)
49
- Base64.strict_encode64(data)
39
+ def attach(name, data, encode: true)
40
+ raise ArgumentError, "attachment #{name} already exists" if @message[:attachments].key?(name)
41
+
42
+ @message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
43
+ end
44
+
45
+ private
46
+
47
+ def valid_field?(field)
48
+ REQUIRED_FIELDS.include?(field) || OPTIONAL_FIELDS.include?(field)
50
49
  end
51
50
  end
52
51
  end
@@ -1,31 +1,27 @@
1
- require 'base64'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Customerio
4
4
  class SendInAppRequest
5
- attr_reader :message
6
-
7
- def initialize(opts)
8
- @message = opts.delete_if { |field| invalid_field?(field) }
9
- end
10
-
11
- private
5
+ REQUIRED_FIELDS = %i[identifiers transactional_message_id].freeze
12
6
 
13
- REQUIRED_FIELDS = %i(identifiers transactional_message_id)
14
-
15
- OPTIONAL_FIELDS = %i(
7
+ OPTIONAL_FIELDS = %i[
16
8
  message_data
17
9
  disable_message_retention
18
10
  queue_draft
19
11
  send_at
20
12
  language
21
- )
13
+ ].freeze
14
+
15
+ attr_reader :message
22
16
 
23
- def invalid_field?(field)
24
- !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
17
+ def initialize(opts)
18
+ @message = opts.select { |field, _value| valid_field?(field) }
25
19
  end
26
20
 
27
- def encode(data)
28
- Base64.strict_encode64(data)
21
+ private
22
+
23
+ def valid_field?(field)
24
+ REQUIRED_FIELDS.include?(field) || OPTIONAL_FIELDS.include?(field)
29
25
  end
30
26
  end
31
27
  end
@@ -1,31 +1,27 @@
1
- require 'base64'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Customerio
4
4
  class SendInboxMessageRequest
5
- attr_reader :message
6
-
7
- def initialize(opts)
8
- @message = opts.delete_if { |field| invalid_field?(field) }
9
- end
10
-
11
- private
5
+ REQUIRED_FIELDS = %i[identifiers transactional_message_id].freeze
12
6
 
13
- REQUIRED_FIELDS = %i(identifiers transactional_message_id)
14
-
15
- OPTIONAL_FIELDS = %i(
7
+ OPTIONAL_FIELDS = %i[
16
8
  message_data
17
9
  disable_message_retention
18
10
  queue_draft
19
11
  send_at
20
12
  language
21
- )
13
+ ].freeze
14
+
15
+ attr_reader :message
22
16
 
23
- def invalid_field?(field)
24
- !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
17
+ def initialize(opts)
18
+ @message = opts.select { |field, _value| valid_field?(field) }
25
19
  end
26
20
 
27
- def encode(data)
28
- Base64.strict_encode64(data)
21
+ private
22
+
23
+ def valid_field?(field)
24
+ REQUIRED_FIELDS.include?(field) || OPTIONAL_FIELDS.include?(field)
29
25
  end
30
26
  end
31
27
  end
@@ -1,17 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Customerio
2
4
  class SendPushRequest
3
- attr_reader :message
4
-
5
- def initialize(opts)
6
- @message = opts.delete_if { |field| invalid_field?(field) }
7
- @message[:custom_device] = opts[:device] if opts[:device]
8
- end
9
-
10
- private
11
-
12
- REQUIRED_FIELDS = %i(transactional_message_id identifiers)
5
+ REQUIRED_FIELDS = %i[transactional_message_id identifiers].freeze
13
6
 
14
- OPTIONAL_FIELDS = %i(
7
+ OPTIONAL_FIELDS = %i[
15
8
  to
16
9
  title
17
10
  message
@@ -25,12 +18,20 @@ module Customerio
25
18
  link
26
19
  sound
27
20
  custom_data
28
- device
29
21
  custom_device
30
- )
22
+ ].freeze
23
+
24
+ attr_reader :message
25
+
26
+ def initialize(opts)
27
+ @message = opts.select { |field, _value| valid_field?(field) }
28
+ @message[:custom_device] = opts[:device] if opts[:device]
29
+ end
30
+
31
+ private
31
32
 
32
- def invalid_field?(field)
33
- !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
33
+ def valid_field?(field)
34
+ REQUIRED_FIELDS.include?(field) || OPTIONAL_FIELDS.include?(field)
34
35
  end
35
36
  end
36
37
  end
@@ -1,25 +1,12 @@
1
- require 'base64'
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
2
4
 
3
5
  module Customerio
4
6
  class SendSMSRequest
5
- attr_reader :message
6
-
7
- def initialize(opts)
8
- @message = opts.delete_if { |field| invalid_field?(field) }
9
- @message[:attachments] = {}
10
- @message[:headers] = {}
11
- end
12
-
13
- def attach(name, data, encode: true)
14
- raise "attachment #{name} already exists" if @message[:attachments].has_key?(name)
15
- @message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
16
- end
17
-
18
- private
7
+ REQUIRED_FIELDS = %i[identifiers transactional_message_id].freeze
19
8
 
20
- REQUIRED_FIELDS = %i(identifiers transactional_message_id)
21
-
22
- OPTIONAL_FIELDS = %i(
9
+ OPTIONAL_FIELDS = %i[
23
10
  message_data
24
11
  from
25
12
  to
@@ -29,14 +16,25 @@ module Customerio
29
16
  queue_draft
30
17
  send_at
31
18
  language
32
- )
19
+ ].freeze
20
+
21
+ attr_reader :message
33
22
 
34
- def invalid_field?(field)
35
- !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
23
+ def initialize(opts)
24
+ @message = opts.select { |field, _value| valid_field?(field) }
25
+ @message[:attachments] ||= {}
36
26
  end
37
27
 
38
- def encode(data)
39
- Base64.strict_encode64(data)
28
+ def attach(name, data, encode: true)
29
+ raise ArgumentError, "attachment #{name} already exists" if @message[:attachments].key?(name)
30
+
31
+ @message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
32
+ end
33
+
34
+ private
35
+
36
+ def valid_field?(field)
37
+ REQUIRED_FIELDS.include?(field) || OPTIONAL_FIELDS.include?(field)
40
38
  end
41
39
  end
42
40
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Customerio
4
+ class TriggerBroadcastRequest
5
+ AUDIENCE_FIELDS = %i[recipients emails ids per_user_data data_file_url].freeze
6
+
7
+ OPTIONAL_FIELDS = %i[data email_add_duplicates email_ignore_missing id_ignore_missing].freeze
8
+
9
+ attr_reader :broadcast_id, :message
10
+
11
+ def initialize(opts)
12
+ raise ArgumentError, "broadcast_id is required" unless opts.key?(:broadcast_id)
13
+ raise ArgumentError, "broadcast_id must be an integer" unless opts[:broadcast_id].is_a?(Integer)
14
+
15
+ @broadcast_id = opts[:broadcast_id]
16
+ @message = opts.select { |field, _value| valid_field?(field) }
17
+
18
+ audience = AUDIENCE_FIELDS.select { |field| @message.key?(field) }
19
+ raise ArgumentError, "only one of #{AUDIENCE_FIELDS.join(', ')} can be present" if audience.length > 1
20
+ end
21
+
22
+ private
23
+
24
+ def valid_field?(field)
25
+ OPTIONAL_FIELDS.include?(field) || AUDIENCE_FIELDS.include?(field)
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Customerio
2
- VERSION = "5.6.0"
4
+ VERSION = "6.1.0"
3
5
  end