fuelsdk_json_bump 0.0.5
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 +7 -0
- data/.gitignore +26 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +91 -0
- data/Guardfile +8 -0
- data/LICENSE.md +13 -0
- data/README.md +127 -0
- data/Rakefile +1 -0
- data/fuelsdk.gemspec +30 -0
- data/lib/fuelsdk.rb +74 -0
- data/lib/fuelsdk/client.rb +282 -0
- data/lib/fuelsdk/http_request.rb +116 -0
- data/lib/fuelsdk/objects.rb +757 -0
- data/lib/fuelsdk/rest.rb +122 -0
- data/lib/fuelsdk/soap.rb +288 -0
- data/lib/fuelsdk/targeting.rb +58 -0
- data/lib/fuelsdk/utils.rb +47 -0
- data/lib/fuelsdk/version.rb +39 -0
- data/lib/new.rb +1240 -0
- data/samples/sample-AddSubscriberToList.rb +56 -0
- data/samples/sample-CreateAndStartDataExtensionImport.rb +29 -0
- data/samples/sample-CreateAndStartListImport.rb +27 -0
- data/samples/sample-CreateContentAreas.rb +48 -0
- data/samples/sample-CreateDataExtensions.rb +54 -0
- data/samples/sample-CreateProfileAttributes.rb +48 -0
- data/samples/sample-SendEmailToDataExtension.rb +23 -0
- data/samples/sample-SendEmailToList.rb +23 -0
- data/samples/sample-SendTriggeredSends.rb +30 -0
- data/samples/sample-bounceevent.rb +70 -0
- data/samples/sample-campaign.rb +211 -0
- data/samples/sample-clickevent.rb +71 -0
- data/samples/sample-contentarea.rb +122 -0
- data/samples/sample-dataextension.rb +209 -0
- data/samples/sample-directverb.rb +55 -0
- data/samples/sample-email.rb +122 -0
- data/samples/sample-email.senddefinition.rb +134 -0
- data/samples/sample-folder.rb +143 -0
- data/samples/sample-import.rb +104 -0
- data/samples/sample-list.rb +105 -0
- data/samples/sample-list.subscriber.rb +97 -0
- data/samples/sample-openevent.rb +70 -0
- data/samples/sample-profileattribute.rb +57 -0
- data/samples/sample-sentevent.rb +70 -0
- data/samples/sample-subscriber.rb +136 -0
- data/samples/sample-triggeredsend.rb +130 -0
- data/samples/sample-unsubevent.rb +72 -0
- data/samples/sample_helper.rb.template +8 -0
- data/spec/client_spec.rb +200 -0
- data/spec/helper_funcs_spec.rb +11 -0
- data/spec/http_request_spec.rb +36 -0
- data/spec/objects_helper_spec.rb +32 -0
- data/spec/objects_spec.rb +484 -0
- data/spec/rest_spec.rb +48 -0
- data/spec/soap_spec.rb +140 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/targeting_spec.rb +39 -0
- metadata +250 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2013 ExactTarget, Inc.
|
3
|
+
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
7
|
+
|
8
|
+
following conditions are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
11
|
+
|
12
|
+
following disclaimer.
|
13
|
+
|
14
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
15
|
+
|
16
|
+
following disclaimer in the documentation and/or other materials provided with the distribution.
|
17
|
+
|
18
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
19
|
+
|
20
|
+
products derived from this software without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
23
|
+
|
24
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
25
|
+
|
26
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
27
|
+
|
28
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
|
30
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
31
|
+
|
32
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
33
|
+
|
34
|
+
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
35
|
+
=end
|
36
|
+
|
37
|
+
require 'open-uri'
|
38
|
+
require 'net/https'
|
39
|
+
require 'json'
|
40
|
+
|
41
|
+
module FuelSDK
|
42
|
+
|
43
|
+
class HTTPResponse < FuelSDK::Response
|
44
|
+
|
45
|
+
def initialize raw, client, request
|
46
|
+
super raw, client
|
47
|
+
@request = request
|
48
|
+
end
|
49
|
+
|
50
|
+
def continue
|
51
|
+
rsp = nil
|
52
|
+
if more?
|
53
|
+
@request['options']['page'] = @results['page'].to_i + 1
|
54
|
+
rsp = unpack @client.rest_get(@request['url'], @request['options'])
|
55
|
+
else
|
56
|
+
puts 'No more data'
|
57
|
+
end
|
58
|
+
|
59
|
+
rsp
|
60
|
+
end
|
61
|
+
|
62
|
+
def [] key
|
63
|
+
@results[key]
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def unpack raw
|
68
|
+
@code = raw.code.to_i
|
69
|
+
@message = raw.message
|
70
|
+
@body = JSON.parse(raw.body) rescue {}
|
71
|
+
@results = @body
|
72
|
+
@more = ((@results['count'] || @results['totalCount']) > @results['page'] * @results['pageSize']) rescue false
|
73
|
+
@success = @message == 'OK'
|
74
|
+
end
|
75
|
+
|
76
|
+
# by default try everything against results
|
77
|
+
def method_missing method, *args, &block
|
78
|
+
@results.send(method, *args, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module HTTPRequest
|
83
|
+
|
84
|
+
request_methods = ['get', 'post', 'patch', 'delete']
|
85
|
+
request_methods.each do |method|
|
86
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
87
|
+
def #{method}(url, options={}) # def post(url, options)
|
88
|
+
request Net::HTTP::#{method.capitalize}, url, options # request Net::HTTP::Post, url, options
|
89
|
+
end # end
|
90
|
+
EOT
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def generate_uri(url, params=nil)
|
96
|
+
uri = URI.parse(url)
|
97
|
+
uri.query = URI.encode_www_form(params) if params
|
98
|
+
uri
|
99
|
+
end
|
100
|
+
|
101
|
+
def request(method, url, options={})
|
102
|
+
uri = generate_uri url, options['params']
|
103
|
+
|
104
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
105
|
+
http.use_ssl = true
|
106
|
+
|
107
|
+
data = options['data']
|
108
|
+
_request = method.new uri.request_uri
|
109
|
+
_request.body = data.to_json if data
|
110
|
+
_request.content_type = options['content_type'] if options['content_type']
|
111
|
+
response = http.request(_request)
|
112
|
+
|
113
|
+
HTTPResponse.new(response, self, :url => url, :options => options)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,757 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2013 ExactTarget, Inc.
|
3
|
+
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
7
|
+
|
8
|
+
following conditions are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
11
|
+
|
12
|
+
following disclaimer.
|
13
|
+
|
14
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
15
|
+
|
16
|
+
following disclaimer in the documentation and/or other materials provided with the distribution.
|
17
|
+
|
18
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
19
|
+
|
20
|
+
products derived from this software without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
23
|
+
|
24
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
25
|
+
|
26
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
27
|
+
|
28
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
|
30
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
31
|
+
|
32
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
33
|
+
|
34
|
+
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
35
|
+
=end
|
36
|
+
|
37
|
+
module FuelSDK
|
38
|
+
module Objects
|
39
|
+
module Soap
|
40
|
+
module Read
|
41
|
+
attr_accessor :filter
|
42
|
+
def get _id=nil
|
43
|
+
client.soap_get _id||id, properties, filter
|
44
|
+
end
|
45
|
+
|
46
|
+
def info
|
47
|
+
client.soap_describe id
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module CUD #create, update, delete
|
52
|
+
def post
|
53
|
+
if self.respond_to?('folder_property') && !self.folder_id.nil?
|
54
|
+
properties[self.folder_property] = self.folder_id
|
55
|
+
elsif self.respond_to?('folder_property') && !self.folder_property.nil? && !client.package_name.nil? then
|
56
|
+
if client.package_folders.nil? then
|
57
|
+
getPackageFolder = ET_Folder.new
|
58
|
+
getPackageFolder.authStub = client
|
59
|
+
getPackageFolder.properties = ["ID", "ContentType"]
|
60
|
+
getPackageFolder.filter = {"Property" => "Name", "SimpleOperator" => "equals", "Value" => client.package_name}
|
61
|
+
resultPackageFolder = getPackageFolder.get
|
62
|
+
if resultPackageFolder.status then
|
63
|
+
client.package_folders = {}
|
64
|
+
resultPackageFolder.results.each do |value|
|
65
|
+
client.package_folders[value[:content_type]] = value[:id]
|
66
|
+
end
|
67
|
+
else
|
68
|
+
raise "Unable to retrieve folders from account due to: #{resultPackageFolder.message}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if !client.package_folders.has_key?(self.folder_media_type) then
|
73
|
+
if client.parentFolders.nil? then
|
74
|
+
parentFolders = ET_Folder.new
|
75
|
+
parentFolders.authStub = client
|
76
|
+
parentFolders.properties = ["ID", "ContentType"]
|
77
|
+
parentFolders.filter = {"Property" => "ParentFolder.ID", "SimpleOperator" => "equals", "Value" => "0"}
|
78
|
+
resultParentFolders = parentFolders.get
|
79
|
+
if resultParentFolders.status then
|
80
|
+
client.parent_folders = {}
|
81
|
+
resultParentFolders.results.each do |value|
|
82
|
+
client.parent_folders[value[:content_type]] = value[:id]
|
83
|
+
end
|
84
|
+
else
|
85
|
+
raise "Unable to retrieve folders from account due to: #{resultParentFolders.message}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
newFolder = ET_Folder.new
|
90
|
+
newFolder.authStub = client
|
91
|
+
newFolder.properties = {"Name" => client.package_name, "Description" => client.package_name, "ContentType"=> self.folder_media_type, "IsEditable"=>"true", "ParentFolder" => {"ID" => client.parentFolders[self.folder_media_type]}}
|
92
|
+
folderResult = newFolder.post
|
93
|
+
if folderResult.status then
|
94
|
+
client.package_folders[self.folder_media_type] = folderResult.results[0][:new_id]
|
95
|
+
else
|
96
|
+
raise "Unable to create folder for Post due to: #{folderResult.message}"
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
properties[self.folder_property] = client.package_folders[self.folder_media_type]
|
101
|
+
end
|
102
|
+
client.soap_post id, properties
|
103
|
+
end
|
104
|
+
|
105
|
+
def patch
|
106
|
+
client.soap_patch id, properties
|
107
|
+
end
|
108
|
+
|
109
|
+
def delete
|
110
|
+
client.soap_delete id, properties
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module Upsert
|
115
|
+
def put
|
116
|
+
client.soap_put id, properties
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
module Rest
|
123
|
+
module Read
|
124
|
+
def get
|
125
|
+
client.rest_get id, properties
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
module CUD
|
130
|
+
def post
|
131
|
+
client.rest_post id, properties
|
132
|
+
end
|
133
|
+
|
134
|
+
def patch
|
135
|
+
client.rest_patch id, properties
|
136
|
+
end
|
137
|
+
|
138
|
+
def delete
|
139
|
+
client.rest_delete id, properties
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
class Base
|
146
|
+
attr_accessor :properties, :client
|
147
|
+
attr_reader :id
|
148
|
+
|
149
|
+
alias props= properties= # backward compatibility
|
150
|
+
alias authStub= client= # backward compatibility
|
151
|
+
|
152
|
+
def properties
|
153
|
+
#@properties = [@properties].compact unless @properties.kind_of? Array
|
154
|
+
@properties
|
155
|
+
end
|
156
|
+
|
157
|
+
#Backwards compatibility
|
158
|
+
def props
|
159
|
+
@properties
|
160
|
+
end
|
161
|
+
|
162
|
+
def id
|
163
|
+
self.class.id
|
164
|
+
end
|
165
|
+
|
166
|
+
class << self
|
167
|
+
def id
|
168
|
+
self.name.split('::').pop
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class BounceEvent < Objects::Base
|
175
|
+
attr_accessor :get_since_last_batch
|
176
|
+
include Objects::Soap::Read
|
177
|
+
end
|
178
|
+
|
179
|
+
class ClickEvent < Objects::Base
|
180
|
+
attr_accessor :get_since_last_batch
|
181
|
+
include Objects::Soap::Read
|
182
|
+
end
|
183
|
+
|
184
|
+
class ContentArea < Objects::Base
|
185
|
+
include Objects::Soap::Read
|
186
|
+
include Objects::Soap::CUD
|
187
|
+
attr_accessor :folder_id
|
188
|
+
|
189
|
+
def folder_property
|
190
|
+
'CategoryID'
|
191
|
+
end
|
192
|
+
|
193
|
+
def folder_media_type
|
194
|
+
'content'
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class DataFolder < Objects::Base
|
199
|
+
include Objects::Soap::Read
|
200
|
+
include Objects::Soap::CUD
|
201
|
+
end
|
202
|
+
|
203
|
+
class Folder < DataFolder
|
204
|
+
class << self
|
205
|
+
def id
|
206
|
+
DataFolder.id
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class Email < Objects::Base
|
212
|
+
include Objects::Soap::Read
|
213
|
+
include Objects::Soap::CUD
|
214
|
+
attr_accessor :folder_id
|
215
|
+
|
216
|
+
def folder_property
|
217
|
+
'CategoryID'
|
218
|
+
end
|
219
|
+
|
220
|
+
def folder_media_type
|
221
|
+
'email'
|
222
|
+
end
|
223
|
+
|
224
|
+
class SendDefinition < Objects::Base
|
225
|
+
include Objects::Soap::Read
|
226
|
+
include Objects::Soap::CUD
|
227
|
+
attr_accessor :folder_id
|
228
|
+
|
229
|
+
def id
|
230
|
+
'EmailSendDefinition'
|
231
|
+
end
|
232
|
+
|
233
|
+
def folder_property
|
234
|
+
'CategoryID'
|
235
|
+
end
|
236
|
+
|
237
|
+
def folder_media_type
|
238
|
+
'userinitiatedsends'
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
def send
|
243
|
+
perform_response = client.soap_perform id, 'start' , properties
|
244
|
+
if perform_response.status then
|
245
|
+
@last_task_id = perform_response.results[0][:result][:task][:id]
|
246
|
+
end
|
247
|
+
perform_response
|
248
|
+
end
|
249
|
+
|
250
|
+
def status
|
251
|
+
client.soap_get "Send", ['ID','CreatedDate', 'ModifiedDate', 'Client.ID', 'Email.ID', 'SendDate','FromAddress','FromName','Duplicates','InvalidAddresses','ExistingUndeliverables','ExistingUnsubscribes','HardBounces','SoftBounces','OtherBounces','ForwardedEmails','UniqueClicks','UniqueOpens','NumberSent','NumberDelivered','NumberTargeted','NumberErrored','NumberExcluded','Unsubscribes','MissingAddresses','Subject','PreviewURL','SentDate','EmailName','Status','IsMultipart','SendLimit','SendWindowOpen','SendWindowClose','BCCEmail','EmailSendDefinition.ObjectID','EmailSendDefinition.CustomerKey'], {'Property' => 'ID','SimpleOperator' => 'equals','Value' => @last_task_id}
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
attr_accessor :last_task_id
|
256
|
+
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
class Import < Objects::Base
|
263
|
+
include Objects::Soap::Read
|
264
|
+
include Objects::Soap::CUD
|
265
|
+
|
266
|
+
|
267
|
+
def id
|
268
|
+
'ImportDefinition'
|
269
|
+
end
|
270
|
+
|
271
|
+
def post
|
272
|
+
originalProp = properties
|
273
|
+
cleanProps
|
274
|
+
obj = super
|
275
|
+
properties = originalProp
|
276
|
+
return obj
|
277
|
+
end
|
278
|
+
|
279
|
+
def patch
|
280
|
+
originalProp = properties
|
281
|
+
cleanProps
|
282
|
+
obj = super
|
283
|
+
properties = originalProp
|
284
|
+
return obj
|
285
|
+
end
|
286
|
+
|
287
|
+
def start
|
288
|
+
perform_response = client.soap_perform id, 'start' , properties
|
289
|
+
if perform_response.status then
|
290
|
+
@last_task_id = perform_response.results[0][:result][:task][:id]
|
291
|
+
end
|
292
|
+
perform_response
|
293
|
+
end
|
294
|
+
|
295
|
+
def status
|
296
|
+
client.soap_get "ImportResultsSummary", ['ImportDefinitionCustomerKey','TaskResultID','ImportStatus','StartDate','EndDate','DestinationID','NumberSuccessful','NumberDuplicated','NumberErrors','TotalRows','ImportType'], {'Property' => 'TaskResultID','SimpleOperator' => 'equals','Value' => @last_task_id}
|
297
|
+
end
|
298
|
+
|
299
|
+
private
|
300
|
+
attr_accessor :last_task_id
|
301
|
+
|
302
|
+
def cleanProps
|
303
|
+
# If the ID property is specified for the destination then it must be a list import
|
304
|
+
if properties.has_key?('DestinationObject') then
|
305
|
+
if properties['DestinationObject'].has_key?('ID') then
|
306
|
+
properties[:attributes!] = { 'DestinationObject' => { 'xsi:type' => 'tns:List'}}
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
class List < Objects::Base
|
314
|
+
include Objects::Soap::Read
|
315
|
+
include Objects::Soap::CUD
|
316
|
+
attr_accessor :folder_id
|
317
|
+
|
318
|
+
def folder_property
|
319
|
+
'Category'
|
320
|
+
end
|
321
|
+
|
322
|
+
def folder_media_type
|
323
|
+
'list'
|
324
|
+
end
|
325
|
+
|
326
|
+
class Subscriber < Objects::Base
|
327
|
+
include Objects::Soap::Read
|
328
|
+
def id
|
329
|
+
'ListSubscriber'
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class OpenEvent < Objects::Base
|
335
|
+
attr_accessor :get_since_last_batch
|
336
|
+
include Objects::Soap::Read
|
337
|
+
end
|
338
|
+
|
339
|
+
class SentEvent < Objects::Base
|
340
|
+
attr_accessor :get_since_last_batch
|
341
|
+
include Objects::Soap::Read
|
342
|
+
end
|
343
|
+
|
344
|
+
class Subscriber < Objects::Base
|
345
|
+
include Objects::Soap::Read
|
346
|
+
include Objects::Soap::CUD
|
347
|
+
include Objects::Soap::Upsert
|
348
|
+
end
|
349
|
+
|
350
|
+
class UnsubEvent < Objects::Base
|
351
|
+
attr_accessor :get_since_last_batch
|
352
|
+
include Objects::Soap::Read
|
353
|
+
end
|
354
|
+
|
355
|
+
class ProfileAttribute < Objects::Base
|
356
|
+
def get
|
357
|
+
client.soap_describe "Subscriber"
|
358
|
+
end
|
359
|
+
|
360
|
+
def post
|
361
|
+
client.soap_configure "PropertyDefinition","create", properties
|
362
|
+
end
|
363
|
+
|
364
|
+
def delete
|
365
|
+
client.soap_configure "PropertyDefinition","delete", properties
|
366
|
+
end
|
367
|
+
|
368
|
+
def patch
|
369
|
+
client.soap_configure "PropertyDefinition","update", properties
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
class TriggeredSend < Objects::Base
|
374
|
+
include Objects::Soap::Read
|
375
|
+
include Objects::Soap::CUD
|
376
|
+
attr_accessor :folder_id, :subscribers
|
377
|
+
def id
|
378
|
+
'TriggeredSendDefinition'
|
379
|
+
end
|
380
|
+
|
381
|
+
def folder_property
|
382
|
+
'CategoryID'
|
383
|
+
end
|
384
|
+
|
385
|
+
def folder_media_type
|
386
|
+
'triggered_send'
|
387
|
+
end
|
388
|
+
|
389
|
+
def send
|
390
|
+
if self.properties.is_a? Array then
|
391
|
+
tscall = []
|
392
|
+
self.properties.each{ |p|
|
393
|
+
tscall.push({"TriggeredSendDefinition" => {"CustomerKey" => p["CustomerKey"]}, "Subscribers" => p["Subscribers"]})
|
394
|
+
}
|
395
|
+
else
|
396
|
+
tscall = {"TriggeredSendDefinition" => self.properties, "Subscribers" => @subscribers}
|
397
|
+
end
|
398
|
+
client.soap_post 'TriggeredSend', tscall
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
class DataExtension < Objects::Base
|
403
|
+
include Objects::Soap::Read
|
404
|
+
include Objects::Soap::CUD
|
405
|
+
attr_accessor :fields, :folder_id
|
406
|
+
|
407
|
+
def folder_property
|
408
|
+
'CategoryID'
|
409
|
+
end
|
410
|
+
|
411
|
+
def folder_media_type
|
412
|
+
'dataextension'
|
413
|
+
end
|
414
|
+
|
415
|
+
alias columns= fields= # backward compatibility
|
416
|
+
|
417
|
+
def post
|
418
|
+
munge_fields self.properties
|
419
|
+
super
|
420
|
+
end
|
421
|
+
|
422
|
+
def patch
|
423
|
+
munge_fields self.properties
|
424
|
+
super
|
425
|
+
end
|
426
|
+
|
427
|
+
class Column < Objects::Base
|
428
|
+
include Objects::Soap::Read
|
429
|
+
def id
|
430
|
+
'DataExtensionField'
|
431
|
+
end
|
432
|
+
def get
|
433
|
+
if filter and filter.kind_of? Hash and \
|
434
|
+
filter.include? 'Property' and filter['Property'] == 'CustomerKey'
|
435
|
+
filter['Property'] = 'DataExtension.CustomerKey'
|
436
|
+
end
|
437
|
+
super
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
class Row < Objects::Base
|
442
|
+
include Objects::Soap::Read
|
443
|
+
include Objects::Soap::CUD
|
444
|
+
include Objects::Soap::Upsert
|
445
|
+
|
446
|
+
attr_accessor :name, :customer_key
|
447
|
+
|
448
|
+
# backward compatibility
|
449
|
+
alias Name= name=
|
450
|
+
alias CustomerKey= customer_key=
|
451
|
+
|
452
|
+
def id
|
453
|
+
'DataExtensionObject'
|
454
|
+
end
|
455
|
+
|
456
|
+
def get
|
457
|
+
super "#{id}[#{name}]"
|
458
|
+
end
|
459
|
+
|
460
|
+
def name
|
461
|
+
unless @name
|
462
|
+
retrieve_required
|
463
|
+
end
|
464
|
+
@name
|
465
|
+
end
|
466
|
+
|
467
|
+
def customer_key
|
468
|
+
unless @customer_key
|
469
|
+
retrieve_required
|
470
|
+
end
|
471
|
+
@customer_key
|
472
|
+
end
|
473
|
+
|
474
|
+
def post
|
475
|
+
munge_properties self.properties
|
476
|
+
super
|
477
|
+
end
|
478
|
+
|
479
|
+
def patch
|
480
|
+
munge_properties self.properties
|
481
|
+
super
|
482
|
+
end
|
483
|
+
|
484
|
+
def put
|
485
|
+
munge_properties self.properties
|
486
|
+
super
|
487
|
+
end
|
488
|
+
|
489
|
+
def delete
|
490
|
+
munge_keys self.properties
|
491
|
+
super
|
492
|
+
end
|
493
|
+
|
494
|
+
private
|
495
|
+
#::TODO::
|
496
|
+
# opportunity for meta programming here... but need to get this out the door
|
497
|
+
def munge_keys d
|
498
|
+
if d.kind_of? Array
|
499
|
+
d.each do |o|
|
500
|
+
|
501
|
+
next if explicit_keys(o) && explicit_customer_key(o)
|
502
|
+
|
503
|
+
formatted = []
|
504
|
+
o['CustomerKey'] = customer_key unless explicit_customer_key o
|
505
|
+
unless explicit_properties(o)
|
506
|
+
o.each do |k, v|
|
507
|
+
next if k == 'CustomerKey'
|
508
|
+
formatted.concat FuelSDK.format_name_value_pairs k => v
|
509
|
+
o.delete k
|
510
|
+
end
|
511
|
+
o['Keys'] = {'Key' => formatted }
|
512
|
+
end
|
513
|
+
end
|
514
|
+
else
|
515
|
+
formatted = []
|
516
|
+
d.each do |k, v|
|
517
|
+
next if k == 'CustomerKey'
|
518
|
+
formatted.concat FuelSDK.format_name_value_pairs k => v
|
519
|
+
d.delete k
|
520
|
+
end
|
521
|
+
d['CustomerKey'] = customer_key
|
522
|
+
d['Keys'] = {'Key' => formatted }
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
def explicit_keys h
|
527
|
+
h['Keys'] and h['Keys']['Key']
|
528
|
+
end
|
529
|
+
|
530
|
+
def munge_properties d
|
531
|
+
if d.kind_of? Array
|
532
|
+
d.each do |o|
|
533
|
+
next if explicit_properties(o) && explicit_customer_key(o)
|
534
|
+
|
535
|
+
formatted = []
|
536
|
+
o['CustomerKey'] = customer_key unless explicit_customer_key o
|
537
|
+
unless explicit_properties(o)
|
538
|
+
o.each do |k, v|
|
539
|
+
next if k == 'CustomerKey'
|
540
|
+
formatted.concat FuelSDK.format_name_value_pairs k => v
|
541
|
+
o.delete k
|
542
|
+
end
|
543
|
+
o['Properties'] = {'Property' => formatted }
|
544
|
+
end
|
545
|
+
end
|
546
|
+
else
|
547
|
+
formatted = []
|
548
|
+
d.each do |k, v|
|
549
|
+
formatted.concat FuelSDK.format_name_value_pairs k => v
|
550
|
+
d.delete k
|
551
|
+
end
|
552
|
+
d['CustomerKey'] = customer_key
|
553
|
+
d['Properties'] = {'Property' => formatted }
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
def explicit_properties h
|
558
|
+
h['Properties'] and h['Properties']['Property']
|
559
|
+
end
|
560
|
+
|
561
|
+
def explicit_customer_key h
|
562
|
+
h['CustomerKey']
|
563
|
+
end
|
564
|
+
|
565
|
+
def retrieve_required
|
566
|
+
# have to use instance variables so we don't recursivelly retrieve_required
|
567
|
+
if !@name && !@customer_key
|
568
|
+
raise 'Unable to process DataExtension::Row ' \
|
569
|
+
'request due to missing CustomerKey and Name'
|
570
|
+
end
|
571
|
+
if !@name || !@customer_key
|
572
|
+
filter = {
|
573
|
+
'Property' => @name.nil? ? 'CustomerKey' : 'Name',
|
574
|
+
'SimpleOperator' => 'equals',
|
575
|
+
'Value' => @customer_key || @name
|
576
|
+
}
|
577
|
+
rsp = client.soap_get 'DataExtension', ['Name', 'CustomerKey'], filter
|
578
|
+
if rsp.success? && rsp.results.count == 1
|
579
|
+
self.name = rsp.results.first[:name]
|
580
|
+
self.customer_key = rsp.results.first[:customer_key]
|
581
|
+
else
|
582
|
+
raise 'Unable to process DataExtension::Row'
|
583
|
+
end
|
584
|
+
end
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
private
|
589
|
+
|
590
|
+
def munge_fields d
|
591
|
+
# maybe one day will make it smart enough to zip properties and fields if count is same?
|
592
|
+
if d.kind_of? Array and d.count > 1 and (fields and !fields.empty?)
|
593
|
+
# we could map the field to all DataExtensions, but lets make user be explicit.
|
594
|
+
# if they are going to use fields attribute properties should
|
595
|
+
# be a single DataExtension Defined in a Hash
|
596
|
+
raise 'Unable to handle muliple DataExtension definitions and a field definition'
|
597
|
+
end
|
598
|
+
|
599
|
+
if d.kind_of? Array
|
600
|
+
d.each do |de|
|
601
|
+
if (explicit_fields(de) and (de['columns'] || de['fields'] || has_fields)) or
|
602
|
+
(de['columns'] and (de['fields'] || has_fields)) or
|
603
|
+
(de['fields'] and has_fields)
|
604
|
+
raise 'Fields are defined in too many ways. Please only define once.' # ahhh what, to do...
|
605
|
+
end
|
606
|
+
|
607
|
+
# let users who chose, to define fields explicitly within the hash definition
|
608
|
+
next if explicit_fields de
|
609
|
+
|
610
|
+
de['Fields'] = {'Field' => de['columns'] || de['fields'] || fields}
|
611
|
+
# sanitize
|
612
|
+
|
613
|
+
raise 'DataExtension needs atleast one field.' unless de['Fields']['Field']
|
614
|
+
end
|
615
|
+
else
|
616
|
+
self.properties['Fields'] = {'Field' => self.properties['columns'] || self.properties['fields'] || fields}
|
617
|
+
raise 'DataExtension needs atleast one field.' unless self.properties['Fields']['Field']
|
618
|
+
self.properties.delete 'columns'
|
619
|
+
self.properties.delete 'fields'
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
def explicit_fields h
|
624
|
+
h['Fields'] and h['Fields']['Field']
|
625
|
+
end
|
626
|
+
|
627
|
+
def has_fields
|
628
|
+
fields and !fields.empty?
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
632
|
+
class Campaign < Objects::Base
|
633
|
+
include Objects::Rest::Read
|
634
|
+
include Objects::Rest::CUD
|
635
|
+
|
636
|
+
def properties
|
637
|
+
@properties ||= {}
|
638
|
+
@properties.merge! 'id' => '' unless @properties.include? 'id'
|
639
|
+
@properties
|
640
|
+
end
|
641
|
+
|
642
|
+
def id
|
643
|
+
"https://www.exacttargetapis.com/hub/v1/campaigns/%{id}"
|
644
|
+
end
|
645
|
+
|
646
|
+
class Asset < Objects::Base
|
647
|
+
include Objects::Rest::Read
|
648
|
+
include Objects::Rest::CUD
|
649
|
+
|
650
|
+
def properties
|
651
|
+
@properties ||= {}
|
652
|
+
@properties.merge! 'assetId' => '' unless @properties.include? 'assetId'
|
653
|
+
@properties
|
654
|
+
end
|
655
|
+
|
656
|
+
def id
|
657
|
+
'https://www.exacttargetapis.com/hub/v1/campaigns/%{id}/assets/%{assetId}'
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
# Direct Verb Access Section
|
663
|
+
|
664
|
+
class Get < Objects::Base
|
665
|
+
include Objects::Soap::Read
|
666
|
+
attr_accessor :id
|
667
|
+
|
668
|
+
def initialize client, id, properties, filter
|
669
|
+
self.properties = properties
|
670
|
+
self.filter = filter
|
671
|
+
self.client = client
|
672
|
+
self.id = id
|
673
|
+
end
|
674
|
+
|
675
|
+
def get
|
676
|
+
super id
|
677
|
+
end
|
678
|
+
|
679
|
+
class << self
|
680
|
+
def new client, id, properties=nil, filter=nil
|
681
|
+
o = self.allocate
|
682
|
+
o.send :initialize, client, id, properties, filter
|
683
|
+
return o.get
|
684
|
+
end
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
class Post < Objects::Base
|
689
|
+
include Objects::Soap::CUD
|
690
|
+
attr_accessor :id
|
691
|
+
|
692
|
+
def initialize client, id, properties
|
693
|
+
self.properties = properties
|
694
|
+
self.client = client
|
695
|
+
self.id = id
|
696
|
+
end
|
697
|
+
|
698
|
+
def post
|
699
|
+
super
|
700
|
+
end
|
701
|
+
|
702
|
+
class << self
|
703
|
+
def new client, id, properties=nil
|
704
|
+
o = self.allocate
|
705
|
+
o.send :initialize, client, id, properties
|
706
|
+
return o.post
|
707
|
+
end
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
class Delete < Objects::Base
|
712
|
+
include Objects::Soap::CUD
|
713
|
+
attr_accessor :id
|
714
|
+
|
715
|
+
def initialize client, id, properties
|
716
|
+
self.properties = properties
|
717
|
+
self.client = client
|
718
|
+
self.id = id
|
719
|
+
end
|
720
|
+
|
721
|
+
def delete
|
722
|
+
super
|
723
|
+
end
|
724
|
+
|
725
|
+
class << self
|
726
|
+
def new client, id, properties=nil
|
727
|
+
o = self.allocate
|
728
|
+
o.send :initialize, client, id, properties
|
729
|
+
return o.delete
|
730
|
+
end
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
class Patch < Objects::Base
|
735
|
+
include Objects::Soap::CUD
|
736
|
+
attr_accessor :id
|
737
|
+
|
738
|
+
def initialize client, id, properties
|
739
|
+
self.properties = properties
|
740
|
+
self.client = client
|
741
|
+
self.id = id
|
742
|
+
end
|
743
|
+
|
744
|
+
def patch
|
745
|
+
super
|
746
|
+
end
|
747
|
+
|
748
|
+
class << self
|
749
|
+
def new client, id, properties=nil
|
750
|
+
o = self.allocate
|
751
|
+
o.send :initialize, client, id, properties
|
752
|
+
return o.patch
|
753
|
+
end
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
end
|