sailthru-client 3.0.0 → 4.0.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 +8 -8
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -9
- data/lib/sailthru.rb +20 -962
- data/lib/sailthru/client.rb +849 -0
- data/lib/sailthru/helpers.rb +76 -0
- data/lib/sailthru/version.rb +3 -0
- data/sailthru-client.gemspec +3 -2
- data/test/sailthru/blast_test.rb +1 -1
- data/test/sailthru/content_test.rb +1 -1
- data/test/sailthru/email_test.rb +1 -1
- data/test/sailthru/error_test.rb +5 -4
- data/test/sailthru/file_upload_test.rb +1 -1
- data/test/sailthru/list_test.rb +3 -3
- data/test/sailthru/purchase_test.rb +1 -1
- data/test/sailthru/send_test.rb +1 -17
- data/test/sailthru/stats_test.rb +2 -2
- data/test/sailthru/template_test.rb +1 -1
- data/test/test_helper.rb +1 -1
- metadata +21 -5
- data/Gemfile.lock +0 -22
@@ -0,0 +1,849 @@
|
|
1
|
+
require 'sailthru/helpers'
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/http/post/multipart'
|
5
|
+
require 'uri'
|
6
|
+
require 'cgi'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
module Sailthru
|
10
|
+
class Client
|
11
|
+
DEFAULT_API_URI = 'https://api.sailthru.com'
|
12
|
+
|
13
|
+
include Helpers
|
14
|
+
|
15
|
+
attr_accessor :verify_ssl
|
16
|
+
|
17
|
+
# params:
|
18
|
+
# api_key, String
|
19
|
+
# secret, String
|
20
|
+
# api_uri, String
|
21
|
+
#
|
22
|
+
# Instantiate a new client; constructor optionally takes overrides for key/secret/uri and proxy server settings.
|
23
|
+
def initialize(api_key=nil, secret=nil, api_uri=nil, proxy_host=nil, proxy_port=nil, opts={})
|
24
|
+
@api_key = api_key || Sailthru.api_key || raise(ArgumentError, "You must provide an API key or call Sailthru.credentials() first")
|
25
|
+
@secret = secret || Sailthru.secret || raise(ArgumentError, "You must provide your secret or call Sailthru.credentials() first")
|
26
|
+
@api_uri = api_uri.nil? ? DEFAULT_API_URI : api_uri
|
27
|
+
@proxy_host = proxy_host
|
28
|
+
@proxy_port = proxy_port
|
29
|
+
@verify_ssl = true
|
30
|
+
@opts = opts
|
31
|
+
end
|
32
|
+
|
33
|
+
# params:
|
34
|
+
# template_name, String
|
35
|
+
# email, String
|
36
|
+
# vars, Hash
|
37
|
+
# options, Hash
|
38
|
+
# replyto: override Reply-To header
|
39
|
+
# test: send as test email (subject line will be marked, will not count towards stats)
|
40
|
+
# returns:
|
41
|
+
# Hash, response data from server
|
42
|
+
def send_email(template_name, email, vars={}, options = {}, schedule_time = nil, limit = {})
|
43
|
+
post = {}
|
44
|
+
post[:template] = template_name
|
45
|
+
post[:email] = email
|
46
|
+
post[:vars] = vars if vars.length >= 1
|
47
|
+
post[:options] = options if options.length >= 1
|
48
|
+
post[:schedule_time] = schedule_time if !schedule_time.nil?
|
49
|
+
post[:limit] = limit if limit.length >= 1
|
50
|
+
api_post(:send, post)
|
51
|
+
end
|
52
|
+
|
53
|
+
def multi_send(template_name, emails, vars={}, options = {}, schedule_time = nil, evars = {})
|
54
|
+
post = {}
|
55
|
+
post[:template] = template_name
|
56
|
+
post[:email] = emails
|
57
|
+
post[:vars] = vars if vars.length >= 1
|
58
|
+
post[:options] = options if options.length >= 1
|
59
|
+
post[:schedule_time] = schedule_time if !schedule_time.nil?
|
60
|
+
post[:evars] = evars if evars.length >= 1
|
61
|
+
api_post(:send, post)
|
62
|
+
end
|
63
|
+
|
64
|
+
# params:
|
65
|
+
# send_id, Fixnum
|
66
|
+
# returns:
|
67
|
+
# Hash, response data from server
|
68
|
+
#
|
69
|
+
# Get the status of a send.
|
70
|
+
def get_send(send_id)
|
71
|
+
api_get(:send, {:send_id => send_id.to_s})
|
72
|
+
end
|
73
|
+
|
74
|
+
def cancel_send(send_id)
|
75
|
+
api_delete(:send, {:send_id => send_id.to_s})
|
76
|
+
end
|
77
|
+
|
78
|
+
# params:
|
79
|
+
# name, String
|
80
|
+
# list, String
|
81
|
+
# schedule_time, String
|
82
|
+
# from_name, String
|
83
|
+
# from_email, String
|
84
|
+
# subject, String
|
85
|
+
# content_html, String
|
86
|
+
# content_text, String
|
87
|
+
# options, Hash
|
88
|
+
# returns:
|
89
|
+
# Hash, response data from server
|
90
|
+
#
|
91
|
+
# Schedule a mass mail blast
|
92
|
+
def schedule_blast(name, list, schedule_time, from_name, from_email, subject, content_html, content_text, options = {})
|
93
|
+
post = options ? options : {}
|
94
|
+
post[:name] = name
|
95
|
+
post[:list] = list
|
96
|
+
post[:schedule_time] = schedule_time
|
97
|
+
post[:from_name] = from_name
|
98
|
+
post[:from_email] = from_email
|
99
|
+
post[:subject] = subject
|
100
|
+
post[:content_html] = content_html
|
101
|
+
post[:content_text] = content_text
|
102
|
+
api_post(:blast, post)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Schedule a mass mail blast from template
|
106
|
+
def schedule_blast_from_template(template, list, schedule_time, options={})
|
107
|
+
post = options ? options : {}
|
108
|
+
post[:copy_template] = template
|
109
|
+
post[:list] = list
|
110
|
+
post[:schedule_time] = schedule_time
|
111
|
+
api_post(:blast, post)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Schedule a mass mail blast from previous blast
|
115
|
+
def schedule_blast_from_blast(blast_id, schedule_time, options={})
|
116
|
+
post = options ? options : {}
|
117
|
+
post[:copy_blast] = blast_id
|
118
|
+
#post[:name] = name
|
119
|
+
post[:schedule_time] = schedule_time
|
120
|
+
api_post(:blast, post)
|
121
|
+
end
|
122
|
+
|
123
|
+
# params
|
124
|
+
# blast_id, Fixnum | String
|
125
|
+
# name, String
|
126
|
+
# list, String
|
127
|
+
# schedule_time, String
|
128
|
+
# from_name, String
|
129
|
+
# from_email, String
|
130
|
+
# subject, String
|
131
|
+
# content_html, String
|
132
|
+
# content_text, String
|
133
|
+
# options, hash
|
134
|
+
#
|
135
|
+
# updates existing blast
|
136
|
+
def update_blast(blast_id, name = nil, list = nil, schedule_time = nil, from_name = nil, from_email = nil, subject = nil, content_html = nil, content_text = nil, options = {})
|
137
|
+
data = options ? options : {}
|
138
|
+
data[:blast_id] = blast_id
|
139
|
+
if name != nil
|
140
|
+
data[:name] = name
|
141
|
+
end
|
142
|
+
if list != nil
|
143
|
+
data[:list] = list
|
144
|
+
end
|
145
|
+
if schedule_time != nil
|
146
|
+
data[:schedule_time] = schedule_time
|
147
|
+
end
|
148
|
+
if from_name != nil
|
149
|
+
data[:from_name] = from_name
|
150
|
+
end
|
151
|
+
if from_email != nil
|
152
|
+
data[:from_email] = from_email
|
153
|
+
end
|
154
|
+
if subject != nil
|
155
|
+
data[:subject] = subject
|
156
|
+
end
|
157
|
+
if content_html != nil
|
158
|
+
data[:content_html] = content_html
|
159
|
+
end
|
160
|
+
if content_text != nil
|
161
|
+
data[:content_text] = content_text
|
162
|
+
end
|
163
|
+
api_post(:blast, data)
|
164
|
+
end
|
165
|
+
|
166
|
+
# params:
|
167
|
+
# blast_id, Fixnum | String
|
168
|
+
# options, hash
|
169
|
+
# returns:
|
170
|
+
# Hash, response data from server
|
171
|
+
#
|
172
|
+
# Get information on a previously scheduled email blast
|
173
|
+
def get_blast(blast_id, options={})
|
174
|
+
options[:blast_id] = blast_id.to_s
|
175
|
+
api_get(:blast, options)
|
176
|
+
end
|
177
|
+
|
178
|
+
# params:
|
179
|
+
# blast_id, Fixnum | String
|
180
|
+
#
|
181
|
+
# Cancel a scheduled Blast
|
182
|
+
def cancel_blast(blast_id)
|
183
|
+
api_post(:blast, {:blast_id => blast_id, :schedule_time => ''})
|
184
|
+
end
|
185
|
+
|
186
|
+
# params:
|
187
|
+
# blast_id, Fixnum | String
|
188
|
+
#
|
189
|
+
# Delete a Blast
|
190
|
+
def delete_blast(blast_id)
|
191
|
+
api_delete(:blast, {:blast_id => blast_id})
|
192
|
+
end
|
193
|
+
|
194
|
+
# params:
|
195
|
+
# email, String
|
196
|
+
# returns:
|
197
|
+
# Hash, response data from server
|
198
|
+
#
|
199
|
+
# Return information about an email address, including replacement vars and lists.
|
200
|
+
def get_email(email)
|
201
|
+
api_get(:email, {:email => email})
|
202
|
+
end
|
203
|
+
|
204
|
+
# params:
|
205
|
+
# email, String
|
206
|
+
# vars, Hash
|
207
|
+
# lists, Hash mapping list name => 1 for subscribed, 0 for unsubscribed
|
208
|
+
# options, Hash mapping optional parameters
|
209
|
+
# returns:
|
210
|
+
# Hash, response data from server
|
211
|
+
#
|
212
|
+
# Set replacement vars and/or list subscriptions for an email address.
|
213
|
+
def set_email(email, vars = {}, lists = {}, templates = {}, options = {})
|
214
|
+
data = options
|
215
|
+
data[:email] = email
|
216
|
+
data[:vars] = vars unless vars.empty?
|
217
|
+
data[:lists] = lists unless lists.empty?
|
218
|
+
data[:templates] = templates unless templates.empty?
|
219
|
+
api_post(:email, data)
|
220
|
+
end
|
221
|
+
|
222
|
+
# params:
|
223
|
+
# new_email, String
|
224
|
+
# old_email, String
|
225
|
+
# options, Hash mapping optional parameters
|
226
|
+
# returns:
|
227
|
+
# Hash of response data.
|
228
|
+
#
|
229
|
+
# change a user's email address.
|
230
|
+
def change_email(new_email, old_email, options = {})
|
231
|
+
data = options
|
232
|
+
data[:email] = new_email
|
233
|
+
data[:change_email] = old_email
|
234
|
+
api_post(:email, data)
|
235
|
+
end
|
236
|
+
|
237
|
+
# params:
|
238
|
+
# template_name, String
|
239
|
+
# returns:
|
240
|
+
# Hash of response data.
|
241
|
+
#
|
242
|
+
# Get a template.
|
243
|
+
def get_template(template_name)
|
244
|
+
api_get(:template, {:template => template_name})
|
245
|
+
end
|
246
|
+
|
247
|
+
# params:
|
248
|
+
# template_name, String
|
249
|
+
# template_fields, Hash
|
250
|
+
# returns:
|
251
|
+
# Hash containg response from the server.
|
252
|
+
#
|
253
|
+
# Save a template.
|
254
|
+
def save_template(template_name, template_fields)
|
255
|
+
data = template_fields
|
256
|
+
data[:template] = template_name
|
257
|
+
api_post(:template, data)
|
258
|
+
end
|
259
|
+
|
260
|
+
# params:
|
261
|
+
# template_name, String
|
262
|
+
# returns:
|
263
|
+
# Hash of response data.
|
264
|
+
#
|
265
|
+
# Delete a template.
|
266
|
+
def delete_template(template_name)
|
267
|
+
api_delete(:template, {:template => template_name})
|
268
|
+
end
|
269
|
+
|
270
|
+
# params:
|
271
|
+
# params, Hash
|
272
|
+
# request, String
|
273
|
+
# returns:
|
274
|
+
# boolean, Returns true if the incoming request is an authenticated verify post.
|
275
|
+
def receive_verify_post(params, request)
|
276
|
+
if request.post?
|
277
|
+
[:action, :email, :send_id, :sig].each { |key| return false unless params.has_key?(key) }
|
278
|
+
|
279
|
+
return false unless params[:action] == :verify
|
280
|
+
|
281
|
+
sig = params.delete(:sig)
|
282
|
+
sig = sig.delete_if {|key, value| key == :controller}
|
283
|
+
return false unless sig == get_signature_hash(params, @secret)
|
284
|
+
|
285
|
+
_send = get_send(params[:send_id])
|
286
|
+
return false unless _send.has_key?(:email)
|
287
|
+
|
288
|
+
return false unless _send[:email] == params[:email]
|
289
|
+
|
290
|
+
return true
|
291
|
+
else
|
292
|
+
return false
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# params:
|
297
|
+
# params, Hash
|
298
|
+
# request, String
|
299
|
+
# returns:
|
300
|
+
# TrueClass or FalseClass, Returns true if the incoming request is an authenticated optout post.
|
301
|
+
def receive_optout_post(params, request)
|
302
|
+
if request.post?
|
303
|
+
[:action, :email, :sig].each { |key| return false unless params.has_key?(key) }
|
304
|
+
|
305
|
+
return false unless params[:action] == 'optout'
|
306
|
+
|
307
|
+
sig = params.delete(:sig)
|
308
|
+
sig = sig.delete_if {|key, value| key == :controller}
|
309
|
+
return false unless sig == get_signature_hash(params, @secret)
|
310
|
+
return true
|
311
|
+
else
|
312
|
+
return false
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# params:
|
317
|
+
# params, Hash
|
318
|
+
# request, String
|
319
|
+
# returns:
|
320
|
+
# TrueClass or FalseClass, Returns true if the incoming request is an authenticated hardbounce post.
|
321
|
+
def receive_hardbounce_post(params, request)
|
322
|
+
if request.post?
|
323
|
+
[:action, :email, :sig].each { |key| return false unless params.has_key?(key) }
|
324
|
+
|
325
|
+
return false unless params[:action] == 'hardbounce'
|
326
|
+
|
327
|
+
sig = params.delete(:sig)
|
328
|
+
sig = sig.delete_if {|key, value| key == :controller}
|
329
|
+
return false unless sig == get_signature_hash(params, @secret)
|
330
|
+
return true
|
331
|
+
else
|
332
|
+
return false
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# params:
|
337
|
+
# email, String
|
338
|
+
# items, String
|
339
|
+
# incomplete, Integer
|
340
|
+
# message_id, String
|
341
|
+
# options, Hash
|
342
|
+
# returns:
|
343
|
+
# hash, response from server
|
344
|
+
#
|
345
|
+
# Record that a user has made a purchase, or has added items to their purchase total.
|
346
|
+
def purchase(email, items, incomplete = nil, message_id = nil, options = {})
|
347
|
+
data = options
|
348
|
+
data[:email] = email
|
349
|
+
data[:items] = items
|
350
|
+
|
351
|
+
if incomplete != nil
|
352
|
+
data[:incomplete] = incomplete.to_i
|
353
|
+
end
|
354
|
+
|
355
|
+
if message_id != nil
|
356
|
+
data[:message_id] = message_id
|
357
|
+
end
|
358
|
+
api_post(:purchase, data)
|
359
|
+
end
|
360
|
+
|
361
|
+
# <b>DEPRECATED:</b> Please use either stats_list or stats_blast
|
362
|
+
# params:
|
363
|
+
# stat, String
|
364
|
+
#
|
365
|
+
# returns:
|
366
|
+
# hash, response from server
|
367
|
+
# Request various stats from Sailthru.
|
368
|
+
def get_stats(stat)
|
369
|
+
warn "[DEPRECATION] `get_stats` is deprecated. Please use `stats_list` and `stats_blast` instead"
|
370
|
+
api_get(:stats, {:stat => stat})
|
371
|
+
end
|
372
|
+
|
373
|
+
# params
|
374
|
+
# list, String
|
375
|
+
# date, String
|
376
|
+
#
|
377
|
+
# returns:
|
378
|
+
# hash, response from server
|
379
|
+
# Retrieve information about your subscriber counts on a particular list, on a particular day.
|
380
|
+
def stats_list(list = nil, date = nil)
|
381
|
+
data = {}
|
382
|
+
if list != nil
|
383
|
+
data[:list] = list
|
384
|
+
end
|
385
|
+
if date != nil
|
386
|
+
data[:date] = date
|
387
|
+
end
|
388
|
+
data[:stat] = 'list'
|
389
|
+
api_get(:stats, data)
|
390
|
+
end
|
391
|
+
|
392
|
+
# params
|
393
|
+
# blast_id, String
|
394
|
+
# start_date, String
|
395
|
+
# end_date, String
|
396
|
+
# options, Hash
|
397
|
+
#
|
398
|
+
# returns:
|
399
|
+
# hash, response from server
|
400
|
+
# Retrieve information about a particular blast or aggregated information from all of blasts over a specified date range
|
401
|
+
def stats_blast(blast_id = nil, start_date = nil, end_date = nil, options = {})
|
402
|
+
data = options
|
403
|
+
if blast_id != nil
|
404
|
+
data[:blast_id] = blast_id
|
405
|
+
end
|
406
|
+
if start_date != nil
|
407
|
+
data[:start_date] = start_date
|
408
|
+
end
|
409
|
+
if end_date != nil
|
410
|
+
data[:end_date] = end_date
|
411
|
+
end
|
412
|
+
data[:stat] = 'blast'
|
413
|
+
api_get(:stats, data)
|
414
|
+
end
|
415
|
+
|
416
|
+
# params
|
417
|
+
# template, String
|
418
|
+
# start_date, String
|
419
|
+
# end_date, String
|
420
|
+
# options, Hash
|
421
|
+
#
|
422
|
+
# returns:
|
423
|
+
# hash, response from server
|
424
|
+
# Retrieve information about a particular blast or aggregated information from all of blasts over a specified date range
|
425
|
+
def stats_send(template = nil, start_date = nil, end_date = nil, options = {})
|
426
|
+
data = options
|
427
|
+
if template != nil
|
428
|
+
data[:template] = template
|
429
|
+
end
|
430
|
+
if start_date != nil
|
431
|
+
data[:start_date] = start_date
|
432
|
+
end
|
433
|
+
if end_date != nil
|
434
|
+
data[:end_date] = end_date
|
435
|
+
end
|
436
|
+
data[:stat] = 'send'
|
437
|
+
api_get(:stats, data)
|
438
|
+
end
|
439
|
+
|
440
|
+
# params
|
441
|
+
# title, String
|
442
|
+
# url, String
|
443
|
+
# date, String
|
444
|
+
# tags, Array or Comma separated string
|
445
|
+
# vars, Hash
|
446
|
+
# options, Hash
|
447
|
+
#
|
448
|
+
# Push a new piece of content to Sailthru, triggering any applicable alerts.
|
449
|
+
# http://docs.sailthru.com/api/content
|
450
|
+
def push_content(title, url, date = nil, tags = nil, vars = {}, options = {})
|
451
|
+
data = options
|
452
|
+
data[:title] = title
|
453
|
+
data[:url] = url
|
454
|
+
if date != nil
|
455
|
+
data[:date] = date
|
456
|
+
end
|
457
|
+
if tags != nil
|
458
|
+
if tags.class == Array
|
459
|
+
tags = tags.join(',')
|
460
|
+
end
|
461
|
+
data[:tags] = tags
|
462
|
+
end
|
463
|
+
if vars.length > 0
|
464
|
+
data[:vars] = vars
|
465
|
+
end
|
466
|
+
api_post(:content, data)
|
467
|
+
end
|
468
|
+
|
469
|
+
# params
|
470
|
+
# list, String
|
471
|
+
#
|
472
|
+
# Get information about a list.
|
473
|
+
def get_list(list)
|
474
|
+
api_get(:list, {:list => list})
|
475
|
+
end
|
476
|
+
|
477
|
+
# params
|
478
|
+
#
|
479
|
+
# Get information about all lists
|
480
|
+
def get_lists
|
481
|
+
api_get(:list, {})
|
482
|
+
end
|
483
|
+
|
484
|
+
# params
|
485
|
+
# list, String
|
486
|
+
# options, Hash
|
487
|
+
# Create a list, or update a list.
|
488
|
+
def save_list(list, options = {})
|
489
|
+
data = options
|
490
|
+
data[:list] = list
|
491
|
+
api_post(:list, data)
|
492
|
+
end
|
493
|
+
|
494
|
+
# params
|
495
|
+
# list, String
|
496
|
+
#
|
497
|
+
# Deletes a list
|
498
|
+
def delete_list(list)
|
499
|
+
api_delete(:list, {:list => list})
|
500
|
+
end
|
501
|
+
|
502
|
+
# params
|
503
|
+
# email, String
|
504
|
+
#
|
505
|
+
# get user alert data
|
506
|
+
def get_alert(email)
|
507
|
+
api_get(:alert, {:email => email})
|
508
|
+
end
|
509
|
+
|
510
|
+
# params
|
511
|
+
# email, String
|
512
|
+
# type, String
|
513
|
+
# template, String
|
514
|
+
# _when, String
|
515
|
+
# options, hash
|
516
|
+
#
|
517
|
+
# Add a new alert to a user. You can add either a realtime or a summary alert (daily/weekly).
|
518
|
+
# _when is only required when alert type is weekly or daily
|
519
|
+
def save_alert(email, type, template, _when = nil, options = {})
|
520
|
+
data = options
|
521
|
+
data[:email] = email
|
522
|
+
data[:type] = type
|
523
|
+
data[:template] = template
|
524
|
+
if (type == 'weekly' || type == 'daily')
|
525
|
+
data[:when] = _when
|
526
|
+
end
|
527
|
+
api_post(:alert, data)
|
528
|
+
end
|
529
|
+
|
530
|
+
# params
|
531
|
+
# email, String
|
532
|
+
# alert_id, String
|
533
|
+
#
|
534
|
+
# delete user alert
|
535
|
+
def delete_alert(email, alert_id)
|
536
|
+
data = {:email => email, :alert_id => alert_id}
|
537
|
+
api_delete(:alert, data)
|
538
|
+
end
|
539
|
+
|
540
|
+
# params
|
541
|
+
# job, String
|
542
|
+
# options, hash
|
543
|
+
# report_email, String
|
544
|
+
# postback_url, String
|
545
|
+
# binary_key, String
|
546
|
+
#
|
547
|
+
# interface for making request to job call
|
548
|
+
def process_job(job, options = {}, report_email = nil, postback_url = nil, binary_key = nil)
|
549
|
+
data = options
|
550
|
+
data['job'] = job
|
551
|
+
if !report_email.nil?
|
552
|
+
data['report_email'] = report_email
|
553
|
+
end
|
554
|
+
|
555
|
+
if !postback_url.nil?
|
556
|
+
data['postback_url'] = postback_url
|
557
|
+
end
|
558
|
+
api_post(:job, data, binary_key)
|
559
|
+
end
|
560
|
+
|
561
|
+
# params
|
562
|
+
# emails, String | Array
|
563
|
+
# implementation for import_job
|
564
|
+
def process_import_job(list, emails, report_email = nil, postback_url = nil, options = {})
|
565
|
+
data = options
|
566
|
+
data['list'] = list
|
567
|
+
data['emails'] = Array(emails).join(',')
|
568
|
+
process_job(:import, data, report_email, postback_url)
|
569
|
+
end
|
570
|
+
|
571
|
+
# implementation for import job using file upload
|
572
|
+
def process_import_job_from_file(list, file_path, report_email = nil, postback_url = nil, options = {})
|
573
|
+
data = options
|
574
|
+
data['list'] = list
|
575
|
+
data['file'] = file_path
|
576
|
+
process_job(:import, data, report_email, postback_url, 'file')
|
577
|
+
end
|
578
|
+
|
579
|
+
# implementation for update job using file upload
|
580
|
+
def process_update_job_from_file(file_path, report_email = nil, postback_url = nil, options = {})
|
581
|
+
data = options
|
582
|
+
data['file'] = file_path
|
583
|
+
process_job(:update, data, report_email, postback_url, 'file')
|
584
|
+
end
|
585
|
+
|
586
|
+
# implementation for snapshot job
|
587
|
+
def process_snapshot_job(query = {}, report_email = nil, postback_url = nil, options = {})
|
588
|
+
data = options
|
589
|
+
data['query'] = query
|
590
|
+
process_job(:snapshot, data, report_email, postback_url)
|
591
|
+
end
|
592
|
+
|
593
|
+
# implementation for export list job
|
594
|
+
def process_export_list_job(list, report_email = nil, postback_url = nil, options = {})
|
595
|
+
data = options
|
596
|
+
data['list'] = list
|
597
|
+
process_job(:export_list_data, data, report_email, postback_url)
|
598
|
+
end
|
599
|
+
|
600
|
+
# get status of a job
|
601
|
+
def get_job_status(job_id)
|
602
|
+
api_get(:job, {'job_id' => job_id})
|
603
|
+
end
|
604
|
+
|
605
|
+
# Get user by Sailthru ID
|
606
|
+
def get_user_by_sid(id, fields = {})
|
607
|
+
api_get(:user, {'id' => id, 'fields' => fields})
|
608
|
+
end
|
609
|
+
|
610
|
+
# Get user by specified key
|
611
|
+
def get_user_by_key(id, key, fields = {})
|
612
|
+
data = {
|
613
|
+
'id' => id,
|
614
|
+
'key' => key,
|
615
|
+
'fields' => fields
|
616
|
+
}
|
617
|
+
api_get(:user, data)
|
618
|
+
end
|
619
|
+
|
620
|
+
# Create new user, or update existing user
|
621
|
+
def save_user(id, options = {})
|
622
|
+
data = options
|
623
|
+
data['id'] = id
|
624
|
+
api_post(:user, data)
|
625
|
+
end
|
626
|
+
|
627
|
+
# params
|
628
|
+
# Get an existing trigger
|
629
|
+
def get_triggers
|
630
|
+
api_get(:trigger, {})
|
631
|
+
end
|
632
|
+
|
633
|
+
# params
|
634
|
+
# template, String
|
635
|
+
# trigger_id, String
|
636
|
+
# Get an existing trigger
|
637
|
+
def get_trigger_by_template(template, trigger_id = nil)
|
638
|
+
data = {}
|
639
|
+
data['template'] = template
|
640
|
+
if trigger_id != nil then data['trigger_id'] = trigger_id end
|
641
|
+
api_get(:trigger, data)
|
642
|
+
end
|
643
|
+
|
644
|
+
# params
|
645
|
+
# event, String
|
646
|
+
# Get an existing trigger
|
647
|
+
def get_trigger_by_event(event)
|
648
|
+
data = {}
|
649
|
+
data['event'] = event
|
650
|
+
api_get(:trigger, data)
|
651
|
+
end
|
652
|
+
|
653
|
+
# params
|
654
|
+
# template, String
|
655
|
+
# time, String
|
656
|
+
# time_unit, String
|
657
|
+
# event, String
|
658
|
+
# zephyr, String
|
659
|
+
# Create or update a trigger
|
660
|
+
def post_template_trigger(template, time, time_unit, event, zephyr)
|
661
|
+
data = {}
|
662
|
+
data['template'] = template
|
663
|
+
data['time'] = time
|
664
|
+
data['time_unit'] = time_unit
|
665
|
+
data['event'] = event
|
666
|
+
data['zephyr'] = zephyr
|
667
|
+
api_post(:trigger, data)
|
668
|
+
end
|
669
|
+
|
670
|
+
# params
|
671
|
+
# template, String
|
672
|
+
# time, String
|
673
|
+
# time_unit, String
|
674
|
+
# zephyr, String
|
675
|
+
# Create or update a trigger
|
676
|
+
def post_event_trigger(event, time, time_unit, zephyr)
|
677
|
+
data = {}
|
678
|
+
data['time'] = time
|
679
|
+
data['time_unit'] = time_unit
|
680
|
+
data['event'] = event
|
681
|
+
data['zephyr'] = zephyr
|
682
|
+
api_post(:trigger, data)
|
683
|
+
end
|
684
|
+
|
685
|
+
# params
|
686
|
+
# id, String
|
687
|
+
# event, String
|
688
|
+
# options, Hash (Can contain vars, Hash and/or key)
|
689
|
+
# Notify Sailthru of an Event
|
690
|
+
def post_event(id, event, options = {})
|
691
|
+
data = options
|
692
|
+
data['id'] = id
|
693
|
+
data['event'] = event
|
694
|
+
api_post(:event, data)
|
695
|
+
end
|
696
|
+
|
697
|
+
# Perform API GET request
|
698
|
+
def api_get(action, data)
|
699
|
+
api_request(action, data, 'GET')
|
700
|
+
end
|
701
|
+
|
702
|
+
# Perform API POST request
|
703
|
+
def api_post(action, data, binary_key = nil)
|
704
|
+
api_request(action, data, 'POST', binary_key)
|
705
|
+
end
|
706
|
+
|
707
|
+
#Perform API DELETE request
|
708
|
+
def api_delete(action, data)
|
709
|
+
api_request(action, data, 'DELETE')
|
710
|
+
end
|
711
|
+
|
712
|
+
protected
|
713
|
+
|
714
|
+
# params:
|
715
|
+
# action, String
|
716
|
+
# data, Hash
|
717
|
+
# request, String "GET" or "POST"
|
718
|
+
# returns:
|
719
|
+
# Hash
|
720
|
+
#
|
721
|
+
# Perform an API request, using the shared-secret auth hash.
|
722
|
+
#
|
723
|
+
def api_request(action, data, request_type, binary_key = nil)
|
724
|
+
if !binary_key.nil?
|
725
|
+
binary_key_data = data[binary_key]
|
726
|
+
data.delete(binary_key)
|
727
|
+
end
|
728
|
+
|
729
|
+
if data[:format].nil? || data[:format] == 'json'
|
730
|
+
data = prepare_json_payload(data)
|
731
|
+
else
|
732
|
+
data[:api_key] = @api_key
|
733
|
+
data[:format] ||= 'json'
|
734
|
+
data[:sig] = get_signature_hash(data, @secret)
|
735
|
+
end
|
736
|
+
|
737
|
+
if !binary_key.nil?
|
738
|
+
data[binary_key] = binary_key_data
|
739
|
+
end
|
740
|
+
_result = http_request("#{@api_uri}/#{action}", data, request_type, binary_key)
|
741
|
+
|
742
|
+
# NOTE: don't do the unserialize here
|
743
|
+
if data[:format] == 'json'
|
744
|
+
begin
|
745
|
+
unserialized = JSON.parse(_result)
|
746
|
+
return unserialized ? unserialized : _result
|
747
|
+
rescue JSON::JSONError => e
|
748
|
+
return {'error' => e}
|
749
|
+
end
|
750
|
+
end
|
751
|
+
_result
|
752
|
+
end
|
753
|
+
|
754
|
+
# set up our post request
|
755
|
+
def set_up_post_request(uri, data, headers, binary_key = nil)
|
756
|
+
if !binary_key.nil?
|
757
|
+
binary_data = data[binary_key]
|
758
|
+
|
759
|
+
if binary_data.is_a?(StringIO)
|
760
|
+
data[binary_key] = UploadIO.new(
|
761
|
+
binary_data, "text/plain", "local.path"
|
762
|
+
)
|
763
|
+
else
|
764
|
+
data[binary_key] = UploadIO.new(
|
765
|
+
File.open(binary_data), "text/plain"
|
766
|
+
)
|
767
|
+
end
|
768
|
+
|
769
|
+
req = Net::HTTP::Post::Multipart.new(uri.path, data)
|
770
|
+
else
|
771
|
+
req = Net::HTTP::Post.new(uri.path, headers)
|
772
|
+
req.set_form_data(data)
|
773
|
+
end
|
774
|
+
req
|
775
|
+
end
|
776
|
+
|
777
|
+
# params:
|
778
|
+
# uri, String
|
779
|
+
# data, Hash
|
780
|
+
# method, String "GET" or "POST"
|
781
|
+
# returns:
|
782
|
+
# String, body of response
|
783
|
+
def http_request(uri, data, method = 'POST', binary_key = nil)
|
784
|
+
data = flatten_nested_hash(data, false)
|
785
|
+
|
786
|
+
if method != 'POST'
|
787
|
+
uri += "?" + data.map{ |key, value| "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}" }.join("&")
|
788
|
+
end
|
789
|
+
|
790
|
+
req = nil
|
791
|
+
headers = {"User-Agent" => "Sailthru API Ruby Client #{VERSION}"}
|
792
|
+
|
793
|
+
_uri = URI.parse(uri)
|
794
|
+
|
795
|
+
if method == 'POST'
|
796
|
+
req = set_up_post_request(
|
797
|
+
_uri, data, headers, binary_key
|
798
|
+
)
|
799
|
+
|
800
|
+
else
|
801
|
+
request_uri = "#{_uri.path}?#{_uri.query}"
|
802
|
+
if method == 'DELETE'
|
803
|
+
req = Net::HTTP::Delete.new(request_uri, headers)
|
804
|
+
else
|
805
|
+
req = Net::HTTP::Get.new(request_uri, headers)
|
806
|
+
end
|
807
|
+
end
|
808
|
+
|
809
|
+
begin
|
810
|
+
http = Net::HTTP::Proxy(@proxy_host, @proxy_port).new(_uri.host, _uri.port)
|
811
|
+
|
812
|
+
if _uri.scheme == 'https'
|
813
|
+
http.use_ssl = true
|
814
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @verify_ssl != true # some openSSL client doesn't work without doing this
|
815
|
+
http.ssl_timeout = @opts[:http_ssl_timeout] || 5
|
816
|
+
end
|
817
|
+
http.open_timeout = @opts[:http_open_timeout] || 5
|
818
|
+
http.read_timeout = @opts[:http_read_timeout] || 10
|
819
|
+
http.close_on_empty_response = @opts[:http_close_on_empty_response] || true
|
820
|
+
|
821
|
+
response = http.start do
|
822
|
+
http.request(req)
|
823
|
+
end
|
824
|
+
|
825
|
+
rescue Timeout::Error, Errno::ETIMEDOUT => e
|
826
|
+
raise UnavailableError, "Timed out: #{_uri}"
|
827
|
+
rescue => e
|
828
|
+
raise ClientError, "Unable to open stream to #{_uri}: #{e.message}"
|
829
|
+
end
|
830
|
+
|
831
|
+
response.body || raise(ClientError, "No response received from stream: #{_uri}")
|
832
|
+
end
|
833
|
+
|
834
|
+
def http_multipart_request(uri, data)
|
835
|
+
Net::HTTP::Post::Multipart.new url.path,
|
836
|
+
"file" => UploadIO.new(data['file'], "application/octet-stream")
|
837
|
+
end
|
838
|
+
|
839
|
+
def prepare_json_payload(data)
|
840
|
+
payload = {
|
841
|
+
:api_key => @api_key,
|
842
|
+
:format => 'json', #<3 XML
|
843
|
+
:json => data.to_json
|
844
|
+
}
|
845
|
+
payload[:sig] = get_signature_hash(payload, @secret)
|
846
|
+
payload
|
847
|
+
end
|
848
|
+
end
|
849
|
+
end
|