fuelsdk 0.0.1
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.
- data/.gitignore +24 -0
- data/Gemfile +3 -0
- data/Guardfile +8 -0
- data/README.md +117 -0
- data/Rakefile +1 -0
- data/fuelsdk.gemspec +30 -0
- data/lib/fuelsdk.rb +572 -0
- data/lib/fuelsdk/client.rb +142 -0
- data/lib/fuelsdk/http_request.rb +79 -0
- data/lib/fuelsdk/objects.rb +143 -0
- data/lib/fuelsdk/rest.rb +84 -0
- data/lib/fuelsdk/soap.rb +177 -0
- data/lib/fuelsdk/targeting.rb +22 -0
- data/lib/fuelsdk/version.rb +3 -0
- data/lib/new.rb +1204 -0
- data/samples/sample-AddSubscriberToList.rb +52 -0
- data/samples/sample-CreateDataExtensions.rb +51 -0
- data/samples/sample-bounceevent.rb +68 -0
- data/samples/sample-campaign.rb +212 -0
- data/samples/sample-clickevent.rb +68 -0
- data/samples/sample-contentarea.rb +114 -0
- data/samples/sample-dataextension.rb +192 -0
- data/samples/sample-email.rb +114 -0
- data/samples/sample-folder.rb +143 -0
- data/samples/sample-list.rb +105 -0
- data/samples/sample-list.subscriber.rb +97 -0
- data/samples/sample-openevent.rb +68 -0
- data/samples/sample-sentevent.rb +69 -0
- data/samples/sample-subscriber.rb +136 -0
- data/samples/sample-triggeredsend.rb +122 -0
- data/samples/sample-unsubevent.rb +68 -0
- data/samples/sample_helper.rb +8 -0
- data/spec/fuelsdk/client_spec.rb +21 -0
- data/spec/fuelsdk_spec.rb +197 -0
- data/spec/helper_funcs_spec.rb +11 -0
- data/spec/http_request_spec.rb +36 -0
- data/spec/rest_spec.rb +48 -0
- data/spec/soap_spec.rb +44 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/targeting_spec.rb +39 -0
- metadata +239 -0
data/lib/fuelsdk/soap.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'savon'
|
2
|
+
module FuelSDK
|
3
|
+
|
4
|
+
class SoapResponse < FuelSDK::ET_Response
|
5
|
+
|
6
|
+
def continue
|
7
|
+
rsp = nil
|
8
|
+
if more?
|
9
|
+
rsp = unpack @client.soap_client.call(:retrieve, :message => {'ContinueRequest' => request_id})
|
10
|
+
else
|
11
|
+
puts 'No more data'
|
12
|
+
end
|
13
|
+
|
14
|
+
rsp
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def unpack raw
|
19
|
+
@code = raw.http.code
|
20
|
+
@request_id = raw.body[raw.body.keys.first][:request_id]
|
21
|
+
|
22
|
+
@message = parse_msg raw
|
23
|
+
@success = @message == 'OK'
|
24
|
+
|
25
|
+
|
26
|
+
@results += (parse_rslts raw)
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_msg raw
|
30
|
+
raw.soap_fault? ? raw.body[:fault][:faultstring] : raw.body[raw.body.keys.first][:overall_status]
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_rslts raw
|
34
|
+
@more = (raw.body[raw.body.keys.first][:overall_status] == 'MoreDataAvailable')
|
35
|
+
rslts = raw.body[raw.body.keys.first][:results] || []
|
36
|
+
rslts = [rslts] unless rslts.kind_of? Array
|
37
|
+
rslts
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class DescribeResponse < SoapResponse
|
42
|
+
attr_reader :properties, :retrievable, :updatable, :required
|
43
|
+
private
|
44
|
+
def parse_rslts raw
|
45
|
+
@retrievable, @updatable, @required, @properties = [], [], [], [], []
|
46
|
+
rslts = raw.body[raw.body.keys.first][:object_definition][:properties]
|
47
|
+
rslts.each do |r|
|
48
|
+
@retrievable << r[:name] if r[:is_retrievable]
|
49
|
+
@updatable << r[:name] if r[:is_updatable]
|
50
|
+
@required << r[:name] if r[:is_required]
|
51
|
+
@properties << r[:name]
|
52
|
+
end
|
53
|
+
@success = true # overall_status is missing from definition response, so need to set here manually
|
54
|
+
rslts
|
55
|
+
rescue
|
56
|
+
@message = "Unable to describe #{raw.locals[:message]['DescribeRequests']['ObjectDefinitionRequest']['ObjectType']}"
|
57
|
+
@success = false
|
58
|
+
[]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Soap
|
63
|
+
attr_accessor :wsdl, :debug, :internal_token
|
64
|
+
|
65
|
+
include FuelSDK::Targeting
|
66
|
+
|
67
|
+
def header
|
68
|
+
raise 'Require legacy token for soap header' unless internal_token
|
69
|
+
{
|
70
|
+
'oAuth' => {'oAuthToken' => internal_token},
|
71
|
+
:attributes! => { 'oAuth' => { 'xmlns' => 'http://exacttarget.com' }}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def debug
|
76
|
+
@debug ||= false
|
77
|
+
end
|
78
|
+
|
79
|
+
def wsdl
|
80
|
+
@wsdl ||= 'https://webservice.exacttarget.com/etframework.wsdl'
|
81
|
+
end
|
82
|
+
|
83
|
+
def soap_client
|
84
|
+
self.refresh unless internal_token
|
85
|
+
@soap_client ||= Savon.client(
|
86
|
+
soap_header: header,
|
87
|
+
wsdl: wsdl,
|
88
|
+
endpoint: endpoint,
|
89
|
+
wsse_auth: ["*", "*"],
|
90
|
+
raise_errors: false,
|
91
|
+
log: debug,
|
92
|
+
open_timeout:180,
|
93
|
+
read_timeout: 180
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
def soap_describe object_type
|
98
|
+
message = {
|
99
|
+
'DescribeRequests' => {
|
100
|
+
'ObjectDefinitionRequest' => {
|
101
|
+
'ObjectType' => object_type
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
DescribeResponse.new soap_client.call(:describe, :message => message), self
|
107
|
+
end
|
108
|
+
|
109
|
+
def soap_get object_type, properties=nil, filter=nil
|
110
|
+
if properties.nil?
|
111
|
+
rsp = soap_describe object_type
|
112
|
+
if rsp.success?
|
113
|
+
properties = rsp.retrievable
|
114
|
+
else
|
115
|
+
rsp.instance_variable_set(:@message, "Unable to get #{object_type}") # back door update
|
116
|
+
return rsp
|
117
|
+
end
|
118
|
+
elsif properties.kind_of? Hash
|
119
|
+
properties = properties.keys
|
120
|
+
elsif properties.kind_of? String
|
121
|
+
properties = [properties]
|
122
|
+
end
|
123
|
+
|
124
|
+
message = {'ObjectType' => object_type, 'Properties' => properties}
|
125
|
+
|
126
|
+
if filter and filter.kind_of? Hash
|
127
|
+
message['Filter'] = filter
|
128
|
+
message[:attributes!] = { 'Filter' => { 'xsi:type' => 'tns:SimpleFilterPart' } }
|
129
|
+
|
130
|
+
if filter.has_key?('LogicalOperator')
|
131
|
+
message[:attributes!] = { 'Filter' => { 'xsi:type' => 'tns:ComplexFilterPart' }}
|
132
|
+
message['Filter'][:attributes!] = {
|
133
|
+
'LeftOperand' => { 'xsi:type' => 'tns:SimpleFilterPart' },
|
134
|
+
'RightOperand' => { 'xsi:type' => 'tns:SimpleFilterPart' }}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
message = {'RetrieveRequest' => message}
|
138
|
+
|
139
|
+
soap_request :retrieve, :message => message
|
140
|
+
end
|
141
|
+
|
142
|
+
def soap_post object_type, properties
|
143
|
+
soap_cud :create, object_type, properties
|
144
|
+
end
|
145
|
+
|
146
|
+
def soap_patch object_type, properties
|
147
|
+
soap_cud :update, object_type, properties
|
148
|
+
end
|
149
|
+
|
150
|
+
def soap_delete object_type, properties
|
151
|
+
soap_cud :delete, object_type, properties
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
def soap_cud action, object_type, properties
|
156
|
+
message = {
|
157
|
+
'Objects' => properties,
|
158
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + object_type) } }
|
159
|
+
}
|
160
|
+
soap_request action, :message => message
|
161
|
+
end
|
162
|
+
|
163
|
+
def soap_request action, message
|
164
|
+
retried = false
|
165
|
+
begin
|
166
|
+
rsp = soap_client.call(action, message)
|
167
|
+
rescue
|
168
|
+
raise if retried
|
169
|
+
retried = true
|
170
|
+
retry
|
171
|
+
end
|
172
|
+
SoapResponse.new rsp, self
|
173
|
+
rescue
|
174
|
+
SoapResponse.new rsp, self
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module FuelSDK::Targeting
|
2
|
+
attr_accessor :access_token
|
3
|
+
attr_reader :endpoint
|
4
|
+
|
5
|
+
include FuelSDK::HTTPRequest
|
6
|
+
|
7
|
+
def endpoint
|
8
|
+
unless @endpoint
|
9
|
+
determine_stack
|
10
|
+
end
|
11
|
+
@endpoint
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def determine_stack
|
16
|
+
options = {'params' => {'access_token' => self.access_token}}
|
17
|
+
response = get("https://www.exacttargetapis.com/platform/v1/endpoints/soap", options)
|
18
|
+
@endpoint = response['url']
|
19
|
+
rescue => e
|
20
|
+
raise 'Unable to determine stack using: ' + e.message
|
21
|
+
end
|
22
|
+
end
|
data/lib/new.rb
ADDED
@@ -0,0 +1,1204 @@
|
|
1
|
+
require "fuelsdk/version"
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'savon'
|
6
|
+
require 'date'
|
7
|
+
require 'json'
|
8
|
+
require 'yaml'
|
9
|
+
require 'jwt'
|
10
|
+
|
11
|
+
|
12
|
+
def indifferent_access key, hash
|
13
|
+
hash[key.to_sym] || hash[key.to_s]
|
14
|
+
end
|
15
|
+
|
16
|
+
module FuelSDK
|
17
|
+
|
18
|
+
class Soap
|
19
|
+
def client
|
20
|
+
'soap'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Rest
|
25
|
+
def client
|
26
|
+
'rest'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Client
|
31
|
+
attr_reader :id, :secret, :signature
|
32
|
+
|
33
|
+
def initialize params={}, debug=false
|
34
|
+
@debug = debug
|
35
|
+
@id = indifferent_access :clientid, params
|
36
|
+
@secret = indifferent_access :clientsecret, params
|
37
|
+
@signature = indifferent_access :appsignature, params
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class SoapClient < Client
|
42
|
+
def initialize getWSDL=true, params={}, debug=false
|
43
|
+
super params, debug
|
44
|
+
@wsdl = params["defaultwsdl"]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class RestClient < Client
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# parse response
|
53
|
+
class ET_Constructor
|
54
|
+
attr_accessor :status, :code, :message, :results, :request_id, :moreResults
|
55
|
+
|
56
|
+
def initialize(response = nil, rest = false)
|
57
|
+
@results = []
|
58
|
+
if !response.nil? && !rest then
|
59
|
+
envelope = response.hash[:envelope]
|
60
|
+
@@body = envelope[:body]
|
61
|
+
|
62
|
+
if ((!response.soap_fault?) or (!response.http_error?)) then
|
63
|
+
@code = response.http.code
|
64
|
+
@status = true
|
65
|
+
elsif (response.soap_fault?) then
|
66
|
+
@code = response.http.code
|
67
|
+
@message = @@body[:fault][:faultstring]
|
68
|
+
@status = false
|
69
|
+
elsif (response.http_error?) then
|
70
|
+
@code = response.http.code
|
71
|
+
@status = false
|
72
|
+
end
|
73
|
+
elsif
|
74
|
+
@code = response.code
|
75
|
+
@status = true
|
76
|
+
if @code != "200" then
|
77
|
+
@status = false
|
78
|
+
end
|
79
|
+
|
80
|
+
begin
|
81
|
+
@results = JSON.parse(response.body)
|
82
|
+
rescue
|
83
|
+
@message = response.body
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ET_CreateWSDL
|
91
|
+
|
92
|
+
def initialize(path)
|
93
|
+
# Get the header info for the correct wsdl
|
94
|
+
response = HTTPI.head(@wsdl)
|
95
|
+
if response and (response.code >= 200 and response.code <= 400) then
|
96
|
+
header = response.headers
|
97
|
+
# Check when the WSDL was last modified
|
98
|
+
modifiedTime = Date.parse(header['last-modified'])
|
99
|
+
p = path + '/ExactTargetWSDL.xml'
|
100
|
+
# Check if a local file already exists
|
101
|
+
if (File.file?(p) and File.readable?(p) and !File.zero?(p)) then
|
102
|
+
createdTime = File.new(p).mtime.to_date
|
103
|
+
|
104
|
+
# Check if the locally created WSDL older than the production WSDL
|
105
|
+
if createdTime < modifiedTime then
|
106
|
+
createIt = true
|
107
|
+
else
|
108
|
+
createIt = false
|
109
|
+
end
|
110
|
+
else
|
111
|
+
createIt = true
|
112
|
+
end
|
113
|
+
|
114
|
+
if createIt then
|
115
|
+
res = open(@wsdl).read
|
116
|
+
File.open(p, 'w+') { |f|
|
117
|
+
f.write(res)
|
118
|
+
}
|
119
|
+
end
|
120
|
+
@status = response.code
|
121
|
+
else
|
122
|
+
@status = response.code
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class ET_Client < ET_CreateWSDL
|
128
|
+
attr_accessor :auth, :ready, :status, :debug, :authToken
|
129
|
+
attr_reader :authTokenExpiration,:internalAuthToken, :wsdlLoc, :clientId,
|
130
|
+
:clientSecret, :soapHeader, :authObj, :path, :appsignature, :stackID, :refreshKey
|
131
|
+
|
132
|
+
def initialize(getWSDL = true, debug = false, params = nil)
|
133
|
+
config = YAML.load_file("config.yaml")
|
134
|
+
@clientId = config["clientid"]
|
135
|
+
@clientSecret = config["clientsecret"]
|
136
|
+
@appsignature = config["appsignature"]
|
137
|
+
@wsdl = config["defaultwsdl"]
|
138
|
+
@debug = debug
|
139
|
+
|
140
|
+
begin
|
141
|
+
@path = File.dirname(__FILE__)
|
142
|
+
|
143
|
+
#make a new WSDL
|
144
|
+
if getWSDL then
|
145
|
+
super(@path)
|
146
|
+
end
|
147
|
+
|
148
|
+
if params && params.has_key?("jwt") then
|
149
|
+
jwt = JWT.decode(params["jwt"], @appsignature, true);
|
150
|
+
@authToken = jwt['request']['user']['oauthToken']
|
151
|
+
@authTokenExpiration = Time.new + jwt['request']['user']['expiresIn']
|
152
|
+
@internalAuthToken = jwt['request']['user']['internalOauthToken']
|
153
|
+
@refreshKey = jwt['request']['user']['refreshToken']
|
154
|
+
|
155
|
+
self.determineStack
|
156
|
+
|
157
|
+
@authObj = {'oAuth' => {'oAuthToken' => @internalAuthToken}}
|
158
|
+
@authObj[:attributes!] = { 'oAuth' => { 'xmlns' => 'http://exacttarget.com' }}
|
159
|
+
|
160
|
+
myWSDL = File.read(@path + '/ExactTargetWSDL.xml')
|
161
|
+
@auth = Savon.client(
|
162
|
+
soap_header: @authObj,
|
163
|
+
wsdl: myWSDL,
|
164
|
+
endpoint: @endpoint,
|
165
|
+
wsse_auth: ["*", "*"],
|
166
|
+
raise_errors: false,
|
167
|
+
log: @debug,
|
168
|
+
open_timeout:180,
|
169
|
+
read_timeout: 180
|
170
|
+
)
|
171
|
+
else
|
172
|
+
self.refreshToken
|
173
|
+
end
|
174
|
+
|
175
|
+
rescue
|
176
|
+
raise
|
177
|
+
end
|
178
|
+
|
179
|
+
if ((@auth.operations.length > 0) and (@status >= 200 and @status <= 400)) then
|
180
|
+
@ready = true
|
181
|
+
else
|
182
|
+
@ready = false
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def debug=(value)
|
187
|
+
@debug = value
|
188
|
+
end
|
189
|
+
|
190
|
+
def refreshToken(force = nil)
|
191
|
+
#If we don't already have a token or the token expires within 5 min(300 seconds), get one
|
192
|
+
if ((@authToken.nil? || Time.new + 300 > @authTokenExpiration) || force) then
|
193
|
+
begin
|
194
|
+
uri = URI.parse("https://auth.exacttargetapis.com/v1/requestToken?legacy=1")
|
195
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
196
|
+
http.use_ssl = true
|
197
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
198
|
+
jsonPayload = {'clientId' => @clientId, 'clientSecret' => @clientSecret}
|
199
|
+
|
200
|
+
#Pass in the refreshKey if we have it
|
201
|
+
if @refreshKey then
|
202
|
+
jsonPayload['refreshToken'] = @refreshKey
|
203
|
+
end
|
204
|
+
|
205
|
+
request.body = jsonPayload.to_json
|
206
|
+
request.add_field "Content-Type", "application/json"
|
207
|
+
tokenResponse = JSON.parse(http.request(request).body)
|
208
|
+
|
209
|
+
if !tokenResponse.has_key?('accessToken') then
|
210
|
+
raise 'Unable to validate App Keys(ClientID/ClientSecret) provided: ' + http.request(request).body
|
211
|
+
end
|
212
|
+
|
213
|
+
@authToken = tokenResponse['accessToken']
|
214
|
+
@authTokenExpiration = Time.new + tokenResponse['expiresIn']
|
215
|
+
@internalAuthToken = tokenResponse['legacyToken']
|
216
|
+
if tokenResponse.has_key?("refreshToken") then
|
217
|
+
@refreshKey = tokenResponse['refreshToken']
|
218
|
+
end
|
219
|
+
|
220
|
+
if @endpoint.nil? then
|
221
|
+
self.determineStack
|
222
|
+
end
|
223
|
+
|
224
|
+
@authObj = {'oAuth' => {'oAuthToken' => @internalAuthToken}}
|
225
|
+
@authObj[:attributes!] = { 'oAuth' => { 'xmlns' => 'http://exacttarget.com' }}
|
226
|
+
|
227
|
+
myWSDL = File.read(@path + '/ExactTargetWSDL.xml')
|
228
|
+
@auth = Savon.client(
|
229
|
+
soap_header: @authObj,
|
230
|
+
wsdl: myWSDL,
|
231
|
+
endpoint: @endpoint,
|
232
|
+
wsse_auth: ["*", "*"],
|
233
|
+
raise_errors: false,
|
234
|
+
log: @debug
|
235
|
+
)
|
236
|
+
|
237
|
+
rescue Exception => e
|
238
|
+
raise 'Unable to validate App Keys(ClientID/ClientSecret) provided: ' + e.message
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def AddSubscriberToList(emailAddress, listIDs, subscriberKey = nil)
|
244
|
+
newSub = ET_Subscriber.new
|
245
|
+
newSub.authStub = self
|
246
|
+
lists = []
|
247
|
+
|
248
|
+
listIDs.each{ |p|
|
249
|
+
lists.push({"ID"=> p})
|
250
|
+
}
|
251
|
+
|
252
|
+
newSub.props = {"EmailAddress" => emailAddress, "Lists" => lists}
|
253
|
+
if !subscriberKey.nil? then
|
254
|
+
newSub.props['SubscriberKey'] = subscriberKey;
|
255
|
+
end
|
256
|
+
|
257
|
+
# Try to add the subscriber
|
258
|
+
postResponse = newSub.post
|
259
|
+
|
260
|
+
if postResponse.status == false then
|
261
|
+
# If the subscriber already exists in the account then we need to do an update.
|
262
|
+
# Update Subscriber On List
|
263
|
+
if postResponse.results[0][:error_code] == "12014" then
|
264
|
+
patchResponse = newSub.patch
|
265
|
+
return patchResponse
|
266
|
+
end
|
267
|
+
end
|
268
|
+
return postResponse
|
269
|
+
end
|
270
|
+
|
271
|
+
def CreateDataExtensions(dataExtensionDefinitions)
|
272
|
+
newDEs = ET_DataExtension.new
|
273
|
+
newDEs.authStub = self
|
274
|
+
|
275
|
+
newDEs.props = dataExtensionDefinitions
|
276
|
+
postResponse = newDEs.post
|
277
|
+
|
278
|
+
return postResponse
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
protected
|
283
|
+
def determineStack()
|
284
|
+
begin
|
285
|
+
uri = URI.parse("https://www.exacttargetapis.com/platform/v1/endpoints/soap?access_token=" + @authToken)
|
286
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
287
|
+
|
288
|
+
http.use_ssl = true
|
289
|
+
|
290
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
291
|
+
|
292
|
+
contextResponse = JSON.parse(http.request(request).body)
|
293
|
+
@endpoint = contextResponse['url']
|
294
|
+
|
295
|
+
rescue StandardError => e
|
296
|
+
raise 'Unable to determine stack using /platform/v1/tokenContext: ' + e.message
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
class ET_Describe < ET_Constructor
|
302
|
+
def initialize(authStub = nil, objType = nil)
|
303
|
+
begin
|
304
|
+
authStub.refreshToken
|
305
|
+
response = authStub.auth.call(:describe, :message => {
|
306
|
+
'DescribeRequests' =>
|
307
|
+
{'ObjectDefinitionRequest' =>
|
308
|
+
{'ObjectType' => objType}
|
309
|
+
}
|
310
|
+
})
|
311
|
+
ensure
|
312
|
+
super(response)
|
313
|
+
|
314
|
+
if @status then
|
315
|
+
objDef = @@body[:definition_response_msg][:object_definition]
|
316
|
+
|
317
|
+
if objDef then
|
318
|
+
@overallStatus = true
|
319
|
+
else
|
320
|
+
@overallStatus = false
|
321
|
+
end
|
322
|
+
@results = @@body[:definition_response_msg][:object_definition][:properties]
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
class ET_Post < ET_Constructor
|
329
|
+
def initialize(authStub, objType, props = nil)
|
330
|
+
@results = []
|
331
|
+
|
332
|
+
begin
|
333
|
+
authStub.refreshToken
|
334
|
+
if props.is_a? Array then
|
335
|
+
obj = {
|
336
|
+
'Objects' => [],
|
337
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
338
|
+
}
|
339
|
+
props.each{ |p|
|
340
|
+
obj['Objects'] << p
|
341
|
+
}
|
342
|
+
else
|
343
|
+
obj = {
|
344
|
+
'Objects' => props,
|
345
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
346
|
+
}
|
347
|
+
end
|
348
|
+
|
349
|
+
response = authStub.auth.call(:create, :message => obj)
|
350
|
+
|
351
|
+
ensure
|
352
|
+
super(response)
|
353
|
+
if @status then
|
354
|
+
if @@body[:create_response][:overall_status] != "OK"
|
355
|
+
@status = false
|
356
|
+
end
|
357
|
+
#@results = @@body[:create_response][:results]
|
358
|
+
if !@@body[:create_response][:results].nil? then
|
359
|
+
if !@@body[:create_response][:results].is_a? Hash then
|
360
|
+
@results = @results + @@body[:create_response][:results]
|
361
|
+
else
|
362
|
+
@results.push(@@body[:create_response][:results])
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
class ET_Delete < ET_Constructor
|
371
|
+
|
372
|
+
def initialize(authStub, objType, props = nil)
|
373
|
+
@results = []
|
374
|
+
begin
|
375
|
+
authStub.refreshToken
|
376
|
+
if props.is_a? Array then
|
377
|
+
obj = {
|
378
|
+
'Objects' => [],
|
379
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
380
|
+
}
|
381
|
+
props.each{ |p|
|
382
|
+
obj['Objects'] << p
|
383
|
+
}
|
384
|
+
else
|
385
|
+
obj = {
|
386
|
+
'Objects' => props,
|
387
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
388
|
+
}
|
389
|
+
end
|
390
|
+
|
391
|
+
response = authStub.auth.call(:delete, :message => obj)
|
392
|
+
ensure
|
393
|
+
super(response)
|
394
|
+
if @status then
|
395
|
+
if @@body[:delete_response][:overall_status] != "OK"
|
396
|
+
@status = false
|
397
|
+
end
|
398
|
+
if !@@body[:delete_response][:results].is_a? Hash then
|
399
|
+
@results = @results + @@body[:delete_response][:results]
|
400
|
+
else
|
401
|
+
@results.push(@@body[:delete_response][:results])
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
class ET_Patch < ET_Constructor
|
409
|
+
def initialize(authStub, objType, props = nil)
|
410
|
+
@results = []
|
411
|
+
begin
|
412
|
+
authStub.refreshToken
|
413
|
+
if props.is_a? Array then
|
414
|
+
obj = {
|
415
|
+
'Objects' => [],
|
416
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
417
|
+
}
|
418
|
+
props.each{ |p|
|
419
|
+
obj['Objects'] << p
|
420
|
+
}
|
421
|
+
else
|
422
|
+
obj = {
|
423
|
+
'Objects' => props,
|
424
|
+
:attributes! => { 'Objects' => { 'xsi:type' => ('tns:' + objType) } }
|
425
|
+
}
|
426
|
+
end
|
427
|
+
|
428
|
+
response = authStub.auth.call(:update, :message => obj)
|
429
|
+
|
430
|
+
ensure
|
431
|
+
super(response)
|
432
|
+
if @status then
|
433
|
+
if @@body[:update_response][:overall_status] != "OK"
|
434
|
+
@status = false
|
435
|
+
end
|
436
|
+
if !@@body[:update_response][:results].is_a? Hash then
|
437
|
+
@results = @results + @@body[:update_response][:results]
|
438
|
+
else
|
439
|
+
@results.push(@@body[:update_response][:results])
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
class ET_Continue < ET_Constructor
|
447
|
+
def initialize(authStub, request_id)
|
448
|
+
@results = []
|
449
|
+
authStub.refreshToken
|
450
|
+
obj = {'ContinueRequest' => request_id}
|
451
|
+
response = authStub.auth.call(:retrieve, :message => {'RetrieveRequest' => obj})
|
452
|
+
|
453
|
+
super(response)
|
454
|
+
|
455
|
+
if @status then
|
456
|
+
if @@body[:retrieve_response_msg][:overall_status] != "OK" && @@body[:retrieve_response_msg][:overall_status] != "MoreDataAvailable" then
|
457
|
+
@status = false
|
458
|
+
@message = @@body[:retrieve_response_msg][:overall_status]
|
459
|
+
end
|
460
|
+
|
461
|
+
@moreResults = false
|
462
|
+
if @@body[:retrieve_response_msg][:overall_status] == "MoreDataAvailable" then
|
463
|
+
@moreResults = true
|
464
|
+
end
|
465
|
+
|
466
|
+
if (!@@body[:retrieve_response_msg][:results].is_a? Hash) && (!@@body[:retrieve_response_msg][:results].nil?) then
|
467
|
+
@results = @results + @@body[:retrieve_response_msg][:results]
|
468
|
+
elsif (!@@body[:retrieve_response_msg][:results].nil?)
|
469
|
+
@results.push(@@body[:retrieve_response_msg][:results])
|
470
|
+
end
|
471
|
+
|
472
|
+
# Store the Last Request ID for use with continue
|
473
|
+
@request_id = @@body[:retrieve_response_msg][:request_id]
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
class ET_Get < ET_Constructor
|
479
|
+
def initialize(authStub, objType, props = nil, filter = nil)
|
480
|
+
@results = []
|
481
|
+
authStub.refreshToken
|
482
|
+
if !props then
|
483
|
+
resp = ET_Describe.new(authStub, objType)
|
484
|
+
if resp then
|
485
|
+
props = []
|
486
|
+
resp.results.map { |p|
|
487
|
+
if p[:is_retrievable] then
|
488
|
+
props << p[:name]
|
489
|
+
end
|
490
|
+
}
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
# If the properties is a hash, then we just want to use the keys
|
495
|
+
if props.is_a? Hash then
|
496
|
+
obj = {'ObjectType' => objType,'Properties' => props.keys}
|
497
|
+
else
|
498
|
+
obj = {'ObjectType' => objType,'Properties' => props}
|
499
|
+
end
|
500
|
+
|
501
|
+
if filter then
|
502
|
+
if filter.has_key?('LogicalOperator') then
|
503
|
+
obj['Filter'] = filter
|
504
|
+
obj[:attributes!] = { 'Filter' => { 'xsi:type' => 'tns:ComplexFilterPart' }}
|
505
|
+
obj['Filter'][:attributes!] = { 'LeftOperand' => { 'xsi:type' => 'tns:SimpleFilterPart' }, 'RightOperand' => { 'xsi:type' => 'tns:SimpleFilterPart' }}
|
506
|
+
else
|
507
|
+
obj['Filter'] = filter
|
508
|
+
obj[:attributes!] = { 'Filter' => { 'xsi:type' => 'tns:SimpleFilterPart' } }
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
response = authStub.auth.call(:retrieve, :message => {
|
513
|
+
'RetrieveRequest' => obj
|
514
|
+
})
|
515
|
+
|
516
|
+
super(response)
|
517
|
+
|
518
|
+
if @status then
|
519
|
+
if @@body[:retrieve_response_msg][:overall_status] != "OK" && @@body[:retrieve_response_msg][:overall_status] != "MoreDataAvailable" then
|
520
|
+
@status = false
|
521
|
+
@message = @@body[:retrieve_response_msg][:overall_status]
|
522
|
+
end
|
523
|
+
|
524
|
+
@moreResults = false
|
525
|
+
if @@body[:retrieve_response_msg][:overall_status] == "MoreDataAvailable" then
|
526
|
+
@moreResults = true
|
527
|
+
end
|
528
|
+
|
529
|
+
if (!@@body[:retrieve_response_msg][:results].is_a? Hash) && (!@@body[:retrieve_response_msg][:results].nil?) then
|
530
|
+
@results = @results + @@body[:retrieve_response_msg][:results]
|
531
|
+
elsif (!@@body[:retrieve_response_msg][:results].nil?)
|
532
|
+
@results.push(@@body[:retrieve_response_msg][:results])
|
533
|
+
end
|
534
|
+
|
535
|
+
# Store the Last Request ID for use with continue
|
536
|
+
@request_id = @@body[:retrieve_response_msg][:request_id]
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
class ET_BaseObject
|
542
|
+
attr_accessor :authStub, :props
|
543
|
+
attr_reader :obj, :lastRequestID, :endpoint
|
544
|
+
|
545
|
+
def initialize
|
546
|
+
@authStub = nil
|
547
|
+
@props = nil
|
548
|
+
@filter = nil
|
549
|
+
@lastRequestID = nil
|
550
|
+
@endpoint = nil
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
class ET_GetSupport < ET_BaseObject
|
555
|
+
attr_accessor :filter
|
556
|
+
|
557
|
+
def get(props = nil, filter = nil)
|
558
|
+
if props and props.is_a? Array then
|
559
|
+
@props = props
|
560
|
+
end
|
561
|
+
|
562
|
+
if @props and @props.is_a? Hash then
|
563
|
+
@props = @props.keys
|
564
|
+
end
|
565
|
+
|
566
|
+
if filter and filter.is_a? Hash then
|
567
|
+
@filter = filter
|
568
|
+
end
|
569
|
+
obj = ET_Get.new(@authStub, @obj, @props, @filter)
|
570
|
+
|
571
|
+
@lastRequestID = obj.request_id
|
572
|
+
|
573
|
+
return obj
|
574
|
+
end
|
575
|
+
|
576
|
+
def info()
|
577
|
+
ET_Describe.new(@authStub, @obj)
|
578
|
+
end
|
579
|
+
|
580
|
+
def getMoreResults()
|
581
|
+
ET_Continue.new(@authStub, @lastRequestID)
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
class ET_CUDSupport < ET_GetSupport
|
586
|
+
|
587
|
+
def post()
|
588
|
+
if props and props.is_a? Hash then
|
589
|
+
@props = props
|
590
|
+
end
|
591
|
+
|
592
|
+
if @extProps then
|
593
|
+
@extProps.each { |key, value|
|
594
|
+
@props[key.capitalize] = value
|
595
|
+
}
|
596
|
+
end
|
597
|
+
|
598
|
+
ET_Post.new(@authStub, @obj, @props)
|
599
|
+
end
|
600
|
+
|
601
|
+
def patch()
|
602
|
+
if props and props.is_a? Hash then
|
603
|
+
@props = props
|
604
|
+
end
|
605
|
+
|
606
|
+
ET_Patch.new(@authStub, @obj, @props)
|
607
|
+
end
|
608
|
+
|
609
|
+
def delete()
|
610
|
+
if props and props.is_a? Hash then
|
611
|
+
@props = props
|
612
|
+
end
|
613
|
+
|
614
|
+
ET_Delete.new(@authStub, @obj, @props)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
class ET_GetSupportRest < ET_BaseObject
|
619
|
+
attr_reader :urlProps, :urlPropsRequired, :lastPageNumber
|
620
|
+
|
621
|
+
def get(props = nil)
|
622
|
+
if props and props.is_a? Hash then
|
623
|
+
@props = props
|
624
|
+
end
|
625
|
+
|
626
|
+
completeURL = @endpoint
|
627
|
+
additionalQS = {}
|
628
|
+
|
629
|
+
if @props and @props.is_a? Hash then
|
630
|
+
@props.each do |k,v|
|
631
|
+
if @urlProps.include?(k) then
|
632
|
+
completeURL.sub!("{#{k}}", v)
|
633
|
+
else
|
634
|
+
additionalQS[k] = v
|
635
|
+
end
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
@urlPropsRequired.each do |value|
|
640
|
+
if !@props || !@props.has_key?(value) then
|
641
|
+
raise "Unable to process request due to missing required prop: #{value}"
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
@urlProps.each do |value|
|
646
|
+
completeURL.sub!("/{#{value}}", "")
|
647
|
+
end
|
648
|
+
|
649
|
+
obj = ET_GetRest.new(@authStub, completeURL,additionalQS)
|
650
|
+
|
651
|
+
if obj.results.has_key?('page') then
|
652
|
+
@lastPageNumber = obj.results['page']
|
653
|
+
pageSize = obj.results['pageSize']
|
654
|
+
if obj.results.has_key?('count') then
|
655
|
+
count = obj.results['count']
|
656
|
+
elsif obj.results.has_key?('totalCount') then
|
657
|
+
count = obj.results['totalCount']
|
658
|
+
end
|
659
|
+
|
660
|
+
if !count.nil? && count > (@lastPageNumber * pageSize) then
|
661
|
+
obj.moreResults = true
|
662
|
+
end
|
663
|
+
end
|
664
|
+
return obj
|
665
|
+
end
|
666
|
+
|
667
|
+
def getMoreResults()
|
668
|
+
if props and props.is_a? Hash then
|
669
|
+
@props = props
|
670
|
+
end
|
671
|
+
|
672
|
+
originalPageValue = "1"
|
673
|
+
removePageFromProps = false
|
674
|
+
|
675
|
+
if !@props.nil? && @props.has_key?('$page') then
|
676
|
+
originalPageValue = @props['page']
|
677
|
+
else
|
678
|
+
removePageFromProps = true
|
679
|
+
end
|
680
|
+
|
681
|
+
if @props.nil?
|
682
|
+
@props = {}
|
683
|
+
end
|
684
|
+
|
685
|
+
@props['$page'] = @lastPageNumber + 1
|
686
|
+
|
687
|
+
obj = self.get
|
688
|
+
|
689
|
+
if removePageFromProps then
|
690
|
+
@props.delete('$page')
|
691
|
+
else
|
692
|
+
@props['$page'] = originalPageValue
|
693
|
+
end
|
694
|
+
|
695
|
+
return obj
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
class ET_CUDSupportRest < ET_GetSupportRest
|
700
|
+
|
701
|
+
def post()
|
702
|
+
completeURL = @endpoint
|
703
|
+
|
704
|
+
if @props and @props.is_a? Hash then
|
705
|
+
@props.each do |k,v|
|
706
|
+
if @urlProps.include?(k) then
|
707
|
+
completeURL.sub!("{#{k}}", v)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
@urlPropsRequired.each do |value|
|
713
|
+
if !@props || !@props.has_key?(value) then
|
714
|
+
raise "Unable to process request due to missing required prop: #{value}"
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
# Clean Optional Parameters from Endpoint URL first
|
719
|
+
@urlProps.each do |value|
|
720
|
+
completeURL.sub!("/{#{value}}", "")
|
721
|
+
end
|
722
|
+
|
723
|
+
ET_PostRest.new(@authStub, completeURL, @props)
|
724
|
+
end
|
725
|
+
|
726
|
+
def patch()
|
727
|
+
completeURL = @endpoint
|
728
|
+
# All URL Props are required when doing Patch
|
729
|
+
@urlProps.each do |value|
|
730
|
+
if !@props || !@props.has_key?(value) then
|
731
|
+
raise "Unable to process request due to missing required prop: #{value}"
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
if @props and @props.is_a? Hash then
|
736
|
+
@props.each do |k,v|
|
737
|
+
if @urlProps.include?(k) then
|
738
|
+
completeURL.sub!("{#{k}}", v)
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
obj = ET_PatchRest.new(@authStub, completeURL, @props)
|
744
|
+
end
|
745
|
+
|
746
|
+
def delete()
|
747
|
+
completeURL = @endpoint
|
748
|
+
# All URL Props are required when doing Patch
|
749
|
+
@urlProps.each do |value|
|
750
|
+
if !@props || !@props.has_key?(value) then
|
751
|
+
raise "Unable to process request due to missing required prop: #{value}"
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
755
|
+
if @props and @props.is_a? Hash then
|
756
|
+
@props.each do |k,v|
|
757
|
+
if @urlProps.include?(k) then
|
758
|
+
completeURL.sub!("{#{k}}", v)
|
759
|
+
end
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
ET_DeleteRest.new(@authStub, completeURL)
|
764
|
+
end
|
765
|
+
|
766
|
+
end
|
767
|
+
|
768
|
+
|
769
|
+
class ET_GetRest < ET_Constructor
|
770
|
+
def initialize(authStub, endpoint, qs = nil)
|
771
|
+
authStub.refreshToken
|
772
|
+
|
773
|
+
if qs then
|
774
|
+
qs['access_token'] = authStub.authToken
|
775
|
+
else
|
776
|
+
qs = {"access_token" => authStub.authToken}
|
777
|
+
end
|
778
|
+
|
779
|
+
uri = URI.parse(endpoint)
|
780
|
+
uri.query = URI.encode_www_form(qs)
|
781
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
782
|
+
http.use_ssl = true
|
783
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
784
|
+
requestResponse = http.request(request)
|
785
|
+
|
786
|
+
@moreResults = false
|
787
|
+
|
788
|
+
obj = super(requestResponse, true)
|
789
|
+
return obj
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
|
794
|
+
class ET_ContinueRest < ET_Constructor
|
795
|
+
def initialize(authStub, endpoint, qs = nil)
|
796
|
+
authStub.refreshToken
|
797
|
+
|
798
|
+
if qs then
|
799
|
+
qs['access_token'] = authStub.authToken
|
800
|
+
else
|
801
|
+
qs = {"access_token" => authStub.authToken}
|
802
|
+
end
|
803
|
+
|
804
|
+
uri = URI.parse(endpoint)
|
805
|
+
uri.query = URI.encode_www_form(qs)
|
806
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
807
|
+
http.use_ssl = true
|
808
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
809
|
+
requestResponse = http.request(request)
|
810
|
+
|
811
|
+
@moreResults = false
|
812
|
+
|
813
|
+
super(requestResponse, true)
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
|
818
|
+
class ET_PostRest < ET_Constructor
|
819
|
+
def initialize(authStub, endpoint, payload)
|
820
|
+
authStub.refreshToken
|
821
|
+
|
822
|
+
qs = {"access_token" => authStub.authToken}
|
823
|
+
uri = URI.parse(endpoint)
|
824
|
+
uri.query = URI.encode_www_form(qs)
|
825
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
826
|
+
http.use_ssl = true
|
827
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
828
|
+
request.body = payload.to_json
|
829
|
+
request.add_field "Content-Type", "application/json"
|
830
|
+
requestResponse = http.request(request)
|
831
|
+
|
832
|
+
super(requestResponse, true)
|
833
|
+
|
834
|
+
end
|
835
|
+
end
|
836
|
+
|
837
|
+
class ET_PatchRest < ET_Constructor
|
838
|
+
def initialize(authStub, endpoint, payload)
|
839
|
+
authStub.refreshToken
|
840
|
+
|
841
|
+
qs = {"access_token" => authStub.authToken}
|
842
|
+
uri = URI.parse(endpoint)
|
843
|
+
uri.query = URI.encode_www_form(qs)
|
844
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
845
|
+
http.use_ssl = true
|
846
|
+
request = Net::HTTP::Patch.new(uri.request_uri)
|
847
|
+
request.body = payload.to_json
|
848
|
+
request.add_field "Content-Type", "application/json"
|
849
|
+
requestResponse = http.request(request)
|
850
|
+
super(requestResponse, true)
|
851
|
+
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
class ET_DeleteRest < ET_Constructor
|
856
|
+
def initialize(authStub, endpoint)
|
857
|
+
authStub.refreshToken
|
858
|
+
|
859
|
+
qs = {"access_token" => authStub.authToken}
|
860
|
+
|
861
|
+
uri = URI.parse(endpoint)
|
862
|
+
uri.query = URI.encode_www_form(qs)
|
863
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
864
|
+
http.use_ssl = true
|
865
|
+
request = Net::HTTP::Delete.new(uri.request_uri)
|
866
|
+
requestResponse = http.request(request)
|
867
|
+
super(requestResponse, true)
|
868
|
+
|
869
|
+
end
|
870
|
+
end
|
871
|
+
|
872
|
+
class ET_Campaign < ET_CUDSupportRest
|
873
|
+
def initialize
|
874
|
+
super
|
875
|
+
@endpoint = 'https://www.exacttargetapis.com/hub/v1/campaigns/{id}'
|
876
|
+
@urlProps = ["id"]
|
877
|
+
@urlPropsRequired = []
|
878
|
+
end
|
879
|
+
|
880
|
+
class Asset < ET_CUDSupportRest
|
881
|
+
def initialize
|
882
|
+
super
|
883
|
+
@endpoint = 'https://www.exacttargetapis.com/hub/v1/campaigns/{id}/assets/{assetId}'
|
884
|
+
@urlProps = ["id", "assetId"]
|
885
|
+
@urlPropsRequired = ["id"]
|
886
|
+
end
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
890
|
+
class ET_Subscriber < ET_CUDSupport
|
891
|
+
def initialize
|
892
|
+
super
|
893
|
+
@obj = 'Subscriber'
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
class ET_DataExtension < ET_CUDSupport
|
898
|
+
attr_accessor :columns
|
899
|
+
|
900
|
+
def initialize
|
901
|
+
super
|
902
|
+
@obj = 'DataExtension'
|
903
|
+
end
|
904
|
+
|
905
|
+
def post
|
906
|
+
originalProps = @props
|
907
|
+
|
908
|
+
if @props.is_a? Array then
|
909
|
+
multiDE = []
|
910
|
+
@props.each { |currentDE|
|
911
|
+
currentDE['Fields'] = {}
|
912
|
+
currentDE['Fields']['Field'] = []
|
913
|
+
currentDE['columns'].each { |key|
|
914
|
+
currentDE['Fields']['Field'].push(key)
|
915
|
+
}
|
916
|
+
currentDE.delete('columns')
|
917
|
+
multiDE.push(currentDE.dup)
|
918
|
+
}
|
919
|
+
|
920
|
+
@props = multiDE
|
921
|
+
else
|
922
|
+
@props['Fields'] = {}
|
923
|
+
@props['Fields']['Field'] = []
|
924
|
+
|
925
|
+
@columns.each { |key|
|
926
|
+
@props['Fields']['Field'].push(key)
|
927
|
+
}
|
928
|
+
end
|
929
|
+
|
930
|
+
obj = super
|
931
|
+
@props = originalProps
|
932
|
+
return obj
|
933
|
+
end
|
934
|
+
|
935
|
+
def patch
|
936
|
+
@props['Fields'] = {}
|
937
|
+
@props['Fields']['Field'] = []
|
938
|
+
@columns.each { |key|
|
939
|
+
@props['Fields']['Field'].push(key)
|
940
|
+
}
|
941
|
+
obj = super
|
942
|
+
@props.delete("Fields")
|
943
|
+
return obj
|
944
|
+
end
|
945
|
+
|
946
|
+
class Column < ET_GetSupport
|
947
|
+
def initialize
|
948
|
+
super
|
949
|
+
@obj = 'DataExtensionField'
|
950
|
+
end
|
951
|
+
|
952
|
+
def get
|
953
|
+
|
954
|
+
if props and props.is_a? Array then
|
955
|
+
@props = props
|
956
|
+
end
|
957
|
+
|
958
|
+
if @props and @props.is_a? Hash then
|
959
|
+
@props = @props.keys
|
960
|
+
end
|
961
|
+
|
962
|
+
if filter and filter.is_a? Hash then
|
963
|
+
@filter = filter
|
964
|
+
end
|
965
|
+
|
966
|
+
fixCustomerKey = false
|
967
|
+
if filter and filter.is_a? Hash then
|
968
|
+
@filter = filter
|
969
|
+
if @filter.has_key?("Property") && @filter["Property"] == "CustomerKey" then
|
970
|
+
@filter["Property"] = "DataExtension.CustomerKey"
|
971
|
+
fixCustomerKey = true
|
972
|
+
end
|
973
|
+
end
|
974
|
+
|
975
|
+
obj = ET_Get.new(@authStub, @obj, @props, @filter)
|
976
|
+
@lastRequestID = obj.request_id
|
977
|
+
|
978
|
+
if fixCustomerKey then
|
979
|
+
@filter["Property"] = "CustomerKey"
|
980
|
+
end
|
981
|
+
|
982
|
+
return obj
|
983
|
+
end
|
984
|
+
end
|
985
|
+
|
986
|
+
class Row < ET_CUDSupport
|
987
|
+
attr_accessor :Name, :CustomerKey
|
988
|
+
|
989
|
+
def initialize()
|
990
|
+
super
|
991
|
+
@obj = "DataExtensionObject"
|
992
|
+
end
|
993
|
+
|
994
|
+
def get
|
995
|
+
getName
|
996
|
+
if props and props.is_a? Array then
|
997
|
+
@props = props
|
998
|
+
end
|
999
|
+
|
1000
|
+
if @props and @props.is_a? Hash then
|
1001
|
+
@props = @props.keys
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
if filter and filter.is_a? Hash then
|
1005
|
+
@filter = filter
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
obj = ET_Get.new(@authStub, "DataExtensionObject[#{@Name}]", @props, @filter)
|
1009
|
+
@lastRequestID = obj.request_id
|
1010
|
+
|
1011
|
+
return obj
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def post
|
1015
|
+
getCustomerKey
|
1016
|
+
originalProps = @props
|
1017
|
+
## FIX THIS
|
1018
|
+
if @props.is_a? Array then
|
1019
|
+
=begin
|
1020
|
+
multiRow = []
|
1021
|
+
@props.each { |currentDE|
|
1022
|
+
|
1023
|
+
currentDE['columns'].each { |key|
|
1024
|
+
currentDE['Fields'] = {}
|
1025
|
+
currentDE['Fields']['Field'] = []
|
1026
|
+
currentDE['Fields']['Field'].push(key)
|
1027
|
+
}
|
1028
|
+
currentDE.delete('columns')
|
1029
|
+
multiRow.push(currentDE.dup)
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
@props = multiRow
|
1033
|
+
=end
|
1034
|
+
else
|
1035
|
+
currentFields = []
|
1036
|
+
currentProp = {}
|
1037
|
+
|
1038
|
+
@props.each { |key,value|
|
1039
|
+
currentFields.push({"Name" => key, "Value" => value})
|
1040
|
+
}
|
1041
|
+
currentProp['CustomerKey'] = @CustomerKey
|
1042
|
+
currentProp['Properties'] = {}
|
1043
|
+
currentProp['Properties']['Property'] = currentFields
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
obj = ET_Post.new(@authStub, @obj, currentProp)
|
1047
|
+
@props = originalProps
|
1048
|
+
obj
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
def patch
|
1052
|
+
getCustomerKey
|
1053
|
+
currentFields = []
|
1054
|
+
currentProp = {}
|
1055
|
+
|
1056
|
+
@props.each { |key,value|
|
1057
|
+
currentFields.push({"Name" => key, "Value" => value})
|
1058
|
+
}
|
1059
|
+
currentProp['CustomerKey'] = @CustomerKey
|
1060
|
+
currentProp['Properties'] = {}
|
1061
|
+
currentProp['Properties']['Property'] = currentFields
|
1062
|
+
|
1063
|
+
ET_Patch.new(@authStub, @obj, currentProp)
|
1064
|
+
end
|
1065
|
+
def delete
|
1066
|
+
getCustomerKey
|
1067
|
+
currentFields = []
|
1068
|
+
currentProp = {}
|
1069
|
+
|
1070
|
+
@props.each { |key,value|
|
1071
|
+
currentFields.push({"Name" => key, "Value" => value})
|
1072
|
+
}
|
1073
|
+
currentProp['CustomerKey'] = @CustomerKey
|
1074
|
+
currentProp['Keys'] = {}
|
1075
|
+
currentProp['Keys']['Key'] = currentFields
|
1076
|
+
|
1077
|
+
ET_Delete.new(@authStub, @obj, currentProp)
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
private
|
1081
|
+
def getCustomerKey
|
1082
|
+
if @CustomerKey.nil? then
|
1083
|
+
if @CustomerKey.nil? && @Name.nil? then
|
1084
|
+
raise 'Unable to process DataExtension::Row request due to CustomerKey and Name not being defined on ET_DatExtension::row'
|
1085
|
+
else
|
1086
|
+
de = ET_DataExtension.new
|
1087
|
+
de.authStub = @authStub
|
1088
|
+
de.props = ["Name","CustomerKey"]
|
1089
|
+
de.filter = {'Property' => 'CustomerKey','SimpleOperator' => 'equals','Value' => @Name}
|
1090
|
+
getResponse = de.get
|
1091
|
+
if getResponse.status && (getResponse.results.length == 1) then
|
1092
|
+
@CustomerKey = getResponse.results[0][:customer_key]
|
1093
|
+
else
|
1094
|
+
raise 'Unable to process DataExtension::Row request due to unable to find DataExtension based on Name'
|
1095
|
+
end
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def getName
|
1101
|
+
if @Name.nil? then
|
1102
|
+
if @CustomerKey.nil? && @Name.nil? then
|
1103
|
+
raise 'Unable to process DataExtension::Row request due to CustomerKey and Name not being defined on ET_DatExtension::row'
|
1104
|
+
else
|
1105
|
+
de = ET_DataExtension.new
|
1106
|
+
de.authStub = @authStub
|
1107
|
+
de.props = ["Name","CustomerKey"]
|
1108
|
+
de.filter = {'Property' => 'CustomerKey','SimpleOperator' => 'equals','Value' => @CustomerKey}
|
1109
|
+
getResponse = de.get
|
1110
|
+
if getResponse.status && (getResponse.results.length == 1) then
|
1111
|
+
@Name = getResponse.results[0][:name]
|
1112
|
+
else
|
1113
|
+
raise 'Unable to process DataExtension::Row request due to unable to find DataExtension based on CustomerKey'
|
1114
|
+
end
|
1115
|
+
end
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
class ET_List < ET_CUDSupport
|
1122
|
+
def initialize
|
1123
|
+
super
|
1124
|
+
@obj = 'List'
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
class Subscriber < ET_GetSupport
|
1128
|
+
def initialize
|
1129
|
+
super
|
1130
|
+
@obj = 'ListSubscriber'
|
1131
|
+
end
|
1132
|
+
end
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
class ET_Email < ET_CUDSupport
|
1136
|
+
def initialize
|
1137
|
+
super
|
1138
|
+
@obj = 'Email'
|
1139
|
+
end
|
1140
|
+
end
|
1141
|
+
|
1142
|
+
class ET_TriggeredSend < ET_CUDSupport
|
1143
|
+
attr_accessor :subscribers
|
1144
|
+
def initialize
|
1145
|
+
super
|
1146
|
+
@obj = 'TriggeredSendDefinition'
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
def send
|
1150
|
+
@tscall = {"TriggeredSendDefinition" => @props, "Subscribers" => @subscribers}
|
1151
|
+
ET_Post.new(@authStub, "TriggeredSend", @tscall)
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
class ET_ContentArea < ET_CUDSupport
|
1156
|
+
def initialize
|
1157
|
+
super
|
1158
|
+
@obj = 'ContentArea'
|
1159
|
+
end
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
class ET_Folder < ET_CUDSupport
|
1163
|
+
def initialize
|
1164
|
+
super
|
1165
|
+
@obj = 'DataFolder'
|
1166
|
+
end
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
class ET_SentEvent < ET_GetSupport
|
1170
|
+
def initialize
|
1171
|
+
super
|
1172
|
+
@obj = 'SentEvent'
|
1173
|
+
end
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
class ET_OpenEvent < ET_GetSupport
|
1177
|
+
def initialize
|
1178
|
+
super
|
1179
|
+
@obj = 'OpenEvent'
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
class ET_BounceEvent < ET_GetSupport
|
1184
|
+
def initialize
|
1185
|
+
super
|
1186
|
+
@obj = 'BounceEvent'
|
1187
|
+
end
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
class ET_UnsubEvent < ET_GetSupport
|
1191
|
+
def initialize
|
1192
|
+
super
|
1193
|
+
@obj = 'UnsubEvent'
|
1194
|
+
end
|
1195
|
+
end
|
1196
|
+
|
1197
|
+
class ET_ClickEvent < ET_GetSupport
|
1198
|
+
def initialize
|
1199
|
+
super
|
1200
|
+
@obj = 'ClickEvent'
|
1201
|
+
end
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
end
|