sfmc-fuelsdk-ruby 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +90 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE.md +13 -0
  7. data/README.md +143 -0
  8. data/Rakefile +1 -0
  9. data/lib/marketingcloudsdk/client.rb +296 -0
  10. data/lib/marketingcloudsdk/http_request.rb +118 -0
  11. data/lib/marketingcloudsdk/objects.rb +757 -0
  12. data/lib/marketingcloudsdk/rest.rb +118 -0
  13. data/lib/marketingcloudsdk/soap.rb +282 -0
  14. data/lib/marketingcloudsdk/targeting.rb +99 -0
  15. data/lib/marketingcloudsdk/utils.rb +47 -0
  16. data/lib/marketingcloudsdk/version.rb +39 -0
  17. data/lib/marketingcloudsdk.rb +74 -0
  18. data/lib/new.rb +1240 -0
  19. data/marketingcloudsdk.gemspec +30 -0
  20. data/samples/sample-AddSubscriberToList.rb +56 -0
  21. data/samples/sample-CreateAndStartDataExtensionImport.rb +29 -0
  22. data/samples/sample-CreateAndStartListImport.rb +27 -0
  23. data/samples/sample-CreateContentAreas.rb +48 -0
  24. data/samples/sample-CreateDataExtensions.rb +54 -0
  25. data/samples/sample-CreateProfileAttributes.rb +48 -0
  26. data/samples/sample-SendEmailToDataExtension.rb +23 -0
  27. data/samples/sample-SendEmailToList.rb +23 -0
  28. data/samples/sample-SendTriggeredSends.rb +30 -0
  29. data/samples/sample-bounceevent.rb +70 -0
  30. data/samples/sample-campaign.rb +211 -0
  31. data/samples/sample-clickevent.rb +71 -0
  32. data/samples/sample-contentarea.rb +122 -0
  33. data/samples/sample-dataextension.rb +209 -0
  34. data/samples/sample-directverb.rb +54 -0
  35. data/samples/sample-email.rb +122 -0
  36. data/samples/sample-email.senddefinition.rb +134 -0
  37. data/samples/sample-folder.rb +143 -0
  38. data/samples/sample-import.rb +103 -0
  39. data/samples/sample-list.rb +105 -0
  40. data/samples/sample-list.subscriber.rb +97 -0
  41. data/samples/sample-openevent.rb +70 -0
  42. data/samples/sample-profileattribute.rb +56 -0
  43. data/samples/sample-sentevent.rb +70 -0
  44. data/samples/sample-subscriber.rb +135 -0
  45. data/samples/sample-triggeredsend.rb +129 -0
  46. data/samples/sample-unsubevent.rb +72 -0
  47. data/samples/sample_helper.rb.template +10 -0
  48. data/spec/client_spec.rb +218 -0
  49. data/spec/default_values_fallback_spec.rb +30 -0
  50. data/spec/helper_funcs_spec.rb +11 -0
  51. data/spec/http_request_spec.rb +61 -0
  52. data/spec/objects_helper_spec.rb +32 -0
  53. data/spec/objects_spec.rb +484 -0
  54. data/spec/rest_spec.rb +48 -0
  55. data/spec/soap_spec.rb +140 -0
  56. data/spec/spec_helper.rb +14 -0
  57. data/spec/targeting_spec.rb +44 -0
  58. metadata +262 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e3079faef2d297a9fb708fc9bb3bcc71f9bce3db371359a96ec621bb716e281c
4
+ data.tar.gz: 957550337f783b15637f431fa0f3b07567c2f85ca2473213b06ca917f55f2ee6
5
+ SHA512:
6
+ metadata.gz: c4ff5b9020c3d6b41b8caa7f69e49202fbb079b77d62a77226ce8bf96bf5f2a62f80347c2f2d4a1d7f549bf6de86bb52d0b65e2b67d434781dd8bb4f27704c45
7
+ data.tar.gz: 4948aa1cb5041c2c4b80760a981ddede7d446af2208a50a2d5297d70c030207c49d374327f81c905a47742bd6f12dcee7f6f6f31453640acd34d88d18e962f7f
data/.gitignore ADDED
@@ -0,0 +1,28 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ samples/soap_cache_file.json
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
20
+ sample.rb
21
+ ExactTargetWSDL.xml
22
+ config.yaml
23
+ /objsamples/config.yaml
24
+ /objsamples/AllTest.bat
25
+ samples/sample_helper.rb
26
+ .DS_STORE
27
+ gengem.bat
28
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sfmc-fuelsdk-ruby (1.1.0)
5
+ json (~> 1.8, >= 1.8.1)
6
+ jwt (~> 1.0, >= 1.0.0)
7
+ savon (= 2.2.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ akami (1.2.2)
13
+ gyoku (>= 0.4.0)
14
+ nokogiri
15
+ builder (3.2.3)
16
+ coderay (1.1.2)
17
+ diff-lcs (1.3)
18
+ ffi (1.9.25)
19
+ ffi (1.9.25-x86-mingw32)
20
+ formatador (0.2.5)
21
+ guard (1.8.3)
22
+ formatador (>= 0.2.4)
23
+ listen (~> 1.3)
24
+ lumberjack (>= 1.0.2)
25
+ pry (>= 0.9.10)
26
+ thor (>= 0.14.6)
27
+ guard-rspec (2.6.0)
28
+ guard (>= 1.8)
29
+ rspec (~> 2.13)
30
+ gyoku (1.0.0)
31
+ builder (>= 2.1.2)
32
+ httpi (2.0.2)
33
+ rack
34
+ json (1.8.6)
35
+ jwt (1.5.6)
36
+ listen (1.3.1)
37
+ rb-fsevent (>= 0.9.3)
38
+ rb-inotify (>= 0.9)
39
+ rb-kqueue (>= 0.2)
40
+ lumberjack (1.0.13)
41
+ method_source (0.9.0)
42
+ mini_portile2 (2.3.0)
43
+ nokogiri (1.8.5)
44
+ mini_portile2 (~> 2.3.0)
45
+ nori (2.1.0)
46
+ pry (0.11.3)
47
+ coderay (~> 1.1.0)
48
+ method_source (~> 0.9.0)
49
+ rack (2.0.6)
50
+ rake (0.9.6)
51
+ rb-fsevent (0.10.3)
52
+ rb-inotify (0.9.10)
53
+ ffi (>= 0.5.0, < 2)
54
+ rb-kqueue (0.2.5)
55
+ ffi (>= 0.5.0)
56
+ rspec (2.99.0)
57
+ rspec-core (~> 2.99.0)
58
+ rspec-expectations (~> 2.99.0)
59
+ rspec-mocks (~> 2.99.0)
60
+ rspec-core (2.99.2)
61
+ rspec-expectations (2.99.2)
62
+ diff-lcs (>= 1.1.3, < 2.0)
63
+ rspec-mocks (2.99.4)
64
+ savon (2.2.0)
65
+ akami (~> 1.2.0)
66
+ builder (>= 2.1.2)
67
+ gyoku (~> 1.0.0)
68
+ httpi (~> 2.0.2)
69
+ nokogiri (>= 1.4.0)
70
+ nori (~> 2.1.0)
71
+ wasabi (~> 3.1.0)
72
+ thor (0.20.0)
73
+ wasabi (3.1.0)
74
+ httpi (~> 2.0)
75
+ nokogiri (>= 1.4.0)
76
+
77
+ PLATFORMS
78
+ ruby
79
+ x86-mingw32
80
+
81
+ DEPENDENCIES
82
+ bundler (~> 1.3)
83
+ guard (~> 1.1)
84
+ guard-rspec (~> 2.0)
85
+ rake (~> 0.9)
86
+ rspec (~> 2.0)
87
+ sfmc-fuelsdk-ruby!
88
+
89
+ BUNDLED WITH
90
+ 1.17.1
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ guard 'rspec' do
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ end
8
+
data/LICENSE.md ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2013 ExactTarget, Inc.
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+
11
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ FuelSDK-Ruby / MarketingCloudSDK-Ruby
2
+ =====================================
3
+
4
+ ExactTarget Fuel SDK / SalesforceMarektingCloudSDK for Ruby
5
+
6
+ ## Overview ##
7
+ The Fuel SDK for Ruby provides easy access to ExactTarget's Fuel API Family services, including a collection of REST APIs and a SOAP API. These APIs provide access to ExactTarget functionality via common collection types such as array/hash.
8
+
9
+ ## New Features in Version 1.1.0 ##
10
+ - **Added support for your tenant's endpoints - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/your-subdomain-tenant-specific-endpoints.htm) **
11
+ - **MarketingCloudSDK gem will be available as sfmc-fuelsdk-ruby on ruby gems.
12
+
13
+ ## Migrationg to version to version 1.0 ##
14
+ - **FuelSDK gem has been renamed to MarketingCloudSDK and will be availbale as marketingcloudsdk on ruby gems.
15
+
16
+ ## New Features in Version .9 ##
17
+ - **Streamlined Folder Support**: All objects that support folders within the UI now have a standardized property called folderId.
18
+ - **Interaction Support**: Now supports Import and Email::SendDefinition objects .
19
+ - **Profile Attribute Support**: Added the ability to manage profile attributes through the ProfileAttribute object.
20
+ - **Support for single request to Add/Update**:A single request can be made which will create the object if one doesn't already or update one if it does. This works for Subscriber, DataExtension::Row, and List objects using the Put method.
21
+ - **Tracking Events Batching Support**: By default, all tracking event types will only pull new data since the last time a request was made using the same filter. If you would like to override this functionality to pull all data, simply set the GetSinceLastBatch property to false.
22
+ - **Automatic Asset Organization for Hub Apps**: Applications that authenticate by providing a JWT will automatically have all created assets placed into a folder based on the HubExchange app's name.
23
+ - **Greater Flexibility for Authentication**:Yaml config file is no longer required in order to define the authentication parameters. They are now required inputs when instantiating the Client class so they can be stored anywhere.
24
+
25
+ ## Migrating from old version ##
26
+ - MarkeitngCloudSDK is now gem, Going forward FuelSDK gem will be available as marketingcloudsdk on ruby gems.
27
+ - Config.yaml is no longer used. ClientID/ClientSecret will now need to be passed when instantiating the Client class.
28
+ - Previous versions of the SalesforceMarketingCloudSDK exposed objects with the prefix "ET_". For backwards compatibility you can still access objects this way.
29
+ Subscriber can be accessed using MarketingCloudSDK::Subscriber or ET_Subscriber.
30
+
31
+ ## Requirements ##
32
+ - Ruby Version 2.2.5
33
+ - Savon 2.2.0
34
+
35
+ ## Getting Started ##
36
+ Build the gem from the source
37
+
38
+ ```ruby
39
+ gem build marketingcloudsdk.gemspec
40
+ ```
41
+
42
+ Install the newly built gem
43
+
44
+ ```ruby
45
+ gem install marketingcloudsdk-1.1.0.gem
46
+ ```
47
+
48
+ If you have not registered your application or you need to lookup your Application Key or Application Signature values, please go to App Center at [Code@: ExactTarget's Developer Community](http://code.exacttarget.com/appcenter "Code@ App Center").
49
+
50
+
51
+ ## Example Request ##
52
+
53
+ Add a require statement to reference the SalesforceMarketingCloud SDK's functionality:
54
+ > require 'marketingcloudsdk'
55
+
56
+ Next, create an instance of the Client class:
57
+ > myClient = MarketingCloudSDK::Client.new {'client' => { 'id' => CLIENTID, 'secret' => SECRET }}
58
+
59
+ Create an instance of the object type we want to work with:
60
+ > list = MarketingCloudSDK::List.new
61
+
62
+ Associate the Client to the object using the client property:
63
+ > list.client = myClient
64
+
65
+ Utilize one of the List methods:
66
+ > response = list.get
67
+
68
+ Print out the results for viewing
69
+ > p response
70
+
71
+ **Example Output:**
72
+
73
+ <pre>
74
+ <MarketingCloudSDK::SoapResponse:0x007fb86abcf190
75
+ @body= {:retrieve_response_msg=> {:overall_status=>"OK", :request_id=>"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", :results=>..}
76
+ @code= 200,
77
+ @message= 'OK',
78
+ @request_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
79
+ @results=
80
+ [{:client=>{:id=>"xxxx"},
81
+ :partner_key=>nil,
82
+ :created_date=>
83
+ #<DateTime: 2013-05-30T23:02:00+00:00 ((2456443j,82920s,0n),+0s,2299161j)>,
84
+ :id=>"xxxx",
85
+ :object_id=>nil,
86
+ :email_address=>"xxxx",
87
+ :attributes=>
88
+ [{:name=>"Full Name", :value=>"Justin Barber"},
89
+ {:name=>"Gender", :value=>nil},
90
+ {:name=>"Email Address", :value=>"xxx"},
91
+ {:name=>"User Defined", :value=>"02/02/1982"}],
92
+ :subscriber_key=>"xxxx",
93
+ :status=>"Active",
94
+ :email_type_preference=>"HTML",
95
+ :"@xsi:type"=>"Subscriber"},
96
+ @success=true>
97
+ </pre>
98
+
99
+ ## Client Class ##
100
+
101
+ The Client class takes care of many of the required steps when accessing ExactTarget's API, including retrieving appropriate access tokens, handling token state for managing refresh, and determining the appropriate endpoints for API requests. In order to leverage the advantages this class provides, use a single instance of this class for an entire session. Do not instantiate a new Client object for each request made.
102
+
103
+ Client class accepts multiple parameters
104
+
105
+ **Parameters** - Allows for passing authentication information for use with SSO with a JWT or for passing ClientID/ClientSecret.
106
+ Additionally the API hostname (base_api_url),Authentication URL (request_token_url) and the SOAP endpoint (soap_endpoint) is now configurable:
107
+
108
+ Example passing ClientID/ClientSecret:
109
+ > myclient = MarketingCloudSDK::Client.new({'client' => {'id' => 'exampleID','secret' => 'exampleSecret'}})
110
+
111
+ Example passing ClientID/ClientSecret/AppSignature/JWT:
112
+ > myclient = MarketingCloudSDK::Client.new({'client' => {'id' => 'exampleID','secret' => 'exampleSecret', 'signature'=>'examplesig'}, 'jwt'=>'exampleJWT'})
113
+
114
+ Example passing ClientID/ClientSecret/BaseAPIUrl/ReqTokenAuthUrl/Soap Endpoint
115
+ > myclient = MarketingCloudSDK::Client.new('client' => {'id' => 'exampleID', 'secret' => 'exampleSecret', 'base_api_url' => 'http://getapis', 'request_token_url' => 'http://authapi', 'soap_endpoint' => 'http://soapendpoint'})
116
+
117
+ **Note** - The following defaults apply if the following parameters are omitted:
118
+ - base_api_url: https://www.exacttargetapis.com
119
+ - request_token_url: https://auth.exacttargetapis.com/v1/requestToken
120
+ - soap_endpoint: https://webservice.exacttarget.com/Service.asmx
121
+
122
+ **Debug** - If 2nd parameter for debug is set to true, all API requests that the Fuel SDK is making behind the scenes will be logged. This option should only be set to true in order to troubleshoot during the development process and should never be used in a production scenario.
123
+ > myclient = MarketingCloudSDK::Client.new auth, true <br>
124
+
125
+
126
+ ## Responses ##
127
+ All methods on MarketingCloud SDK objects return a generic object that follows the same structure, regardless of the type of call. This object contains a common set of properties used to display details about the request.
128
+
129
+ - success?: Boolean value that indicates if the call was successful
130
+ - code: HTTP Error Code (will always be 200 for SOAP requests)
131
+ - message: Text values containing more details in the event of an error
132
+ - results: Collection containing the details unique to the method called.
133
+ - more? - Boolean value that indicates on Get requests if more data is available.
134
+
135
+
136
+ ## Samples ##
137
+ Find more sample files that illustrate using all of the available functions for ExactTarget objects exposed through the API in the samples directory.
138
+
139
+
140
+
141
+
142
+
143
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,296 @@
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
+
36
+ =end
37
+
38
+ require 'securerandom'
39
+ module MarketingCloudSDK
40
+ class Response
41
+ # not doing accessor so user, can't update these values from response.
42
+ # You will see in the code some of these
43
+ # items are being updated via back doors and such.
44
+ attr_reader :code, :message, :results, :request_id, :body, :raw
45
+
46
+ # some defaults
47
+ def success
48
+ @success ||= false
49
+ end
50
+ alias :success? :success
51
+ alias :status :success # backward compatibility
52
+
53
+ def more
54
+ @more ||= false
55
+ end
56
+ alias :more? :more
57
+
58
+ def initialize raw, client
59
+ @client = client # keep connection with client in case we request more
60
+ @results = []
61
+ @raw = raw
62
+ unpack raw
63
+ rescue => ex # all else fails return raw
64
+ puts ex.message
65
+ raw
66
+ end
67
+
68
+ def continue
69
+ raise NotImplementedError
70
+ end
71
+
72
+ private
73
+ def unpack raw
74
+ raise NotImplementedError
75
+ end
76
+ end
77
+
78
+ class Client
79
+ attr_accessor :debug, :access_token, :auth_token, :internal_token, :refresh_token,
80
+ :id, :secret, :signature, :base_api_url, :package_name, :package_folders, :parent_folders, :auth_token_expiration,
81
+ :request_token_url, :soap_endpoint
82
+
83
+ include MarketingCloudSDK::Soap
84
+ include MarketingCloudSDK::Rest
85
+
86
+ def jwt= encoded_jwt
87
+ raise 'Require app signature to decode JWT' unless self.signature
88
+ decoded_jwt = JWT.decode(encoded_jwt, self.signature, true)
89
+
90
+ self.auth_token = decoded_jwt['request']['user']['oauthToken']
91
+ self.internal_token = decoded_jwt['request']['user']['internalOauthToken']
92
+ self.refresh_token = decoded_jwt['request']['user']['refreshToken']
93
+ self.auth_token_expiration = Time.new + decoded_jwt['request']['user']['expiresIn']
94
+ self.package_name = decoded_jwt['request']['application']['package']
95
+ end
96
+
97
+ def initialize(params={}, debug=false)
98
+ @refresh_mutex = Mutex.new
99
+ self.debug = debug
100
+ client_config = params['client']
101
+ if client_config
102
+ self.id = client_config["id"]
103
+ self.secret = client_config["secret"]
104
+ self.signature = client_config["signature"]
105
+ self.base_api_url = !(client_config["base_api_url"].to_s.strip.empty?) ? client_config["base_api_url"] : 'https://www.exacttargetapis.com'
106
+ self.request_token_url = !(client_config["request_token_url"].to_s.strip.empty?) ? client_config["request_token_url"] : 'https://auth.exacttargetapis.com/v1/requestToken'
107
+ self.soap_endpoint = client_config["soap_endpoint"]
108
+ end
109
+
110
+ # Set a default value in case no 'client' params is sent
111
+ if (!self.base_api_url)
112
+ self.base_api_url = 'https://www.exacttargetapis.com'
113
+ end
114
+
115
+ # Leaving this for backwards compatibility
116
+ if (!self.request_token_url)
117
+ self.request_token_url = params['request_token_url'] ? params['request_token_url'] : 'https://auth.exacttargetapis.com/v1/requestToken'
118
+ end
119
+
120
+ self.jwt = params['jwt'] if params['jwt']
121
+ self.refresh_token = params['refresh_token'] if params['refresh_token']
122
+
123
+ self.wsdl = params["defaultwsdl"] if params["defaultwsdl"]
124
+ end
125
+
126
+ def refresh force=false
127
+ @refresh_mutex.synchronize do
128
+ raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)
129
+ #If we don't already have a token or the token expires within 5 min(300 seconds)
130
+ if (self.access_token.nil? || Time.new + 300 > self.auth_token_expiration || force) then
131
+ payload = Hash.new.tap do |h|
132
+ h['clientId']= id
133
+ h['clientSecret'] = secret
134
+ h['refreshToken'] = refresh_token if refresh_token
135
+ h['accessType'] = 'offline'
136
+ end
137
+
138
+ options = Hash.new.tap do |h|
139
+ h['data'] = payload
140
+ h['content_type'] = 'application/json'
141
+ h['params'] = {'legacy' => 1}
142
+ end
143
+ response = post(request_token_url, options)
144
+ raise "Unable to refresh token: #{response['message']}" unless response.has_key?('accessToken')
145
+
146
+ self.access_token = response['accessToken']
147
+ self.internal_token = response['legacyToken']
148
+ self.auth_token_expiration = Time.new + response['expiresIn']
149
+ self.refresh_token = response['refreshToken'] if response.has_key?("refreshToken")
150
+ return true
151
+ else
152
+ return false
153
+ end
154
+ end
155
+ end
156
+
157
+ def refresh!
158
+ refresh true
159
+ end
160
+
161
+ def AddSubscriberToList(email, ids, subscriber_key = nil)
162
+ s = MarketingCloudSDK::Subscriber.new
163
+ s.client = self
164
+ lists = ids.collect{|id| {'ID' => id}}
165
+ s.properties = {"EmailAddress" => email, "Lists" => lists}
166
+ p s.properties
167
+ s.properties['SubscriberKey'] = subscriber_key if subscriber_key
168
+
169
+ # Try to add the subscriber
170
+ if(rsp = s.post and rsp.results.first[:error_code] == '12014')
171
+ # subscriber already exists we need to update.
172
+ rsp = s.patch
173
+ end
174
+ rsp
175
+ end
176
+
177
+ def CreateDataExtensions(definitions)
178
+ de = MarketingCloudSDK::DataExtension.new
179
+ de.client = self
180
+ de.properties = definitions
181
+ de.post
182
+ end
183
+ def SendTriggeredSends(arrayOfTriggeredRecords)
184
+ sendTS = ET_TriggeredSend.new
185
+ sendTS.authStub = self
186
+
187
+ sendTS.properties = arrayOfTriggeredRecords
188
+ sendResponse = sendTS.send
189
+
190
+ return sendResponse
191
+ end
192
+ def SendEmailToList(emailID, listID, sendClassificationCustomerKey)
193
+ email = ET_Email::SendDefinition.new
194
+ email.properties = {"Name"=>SecureRandom.uuid, "CustomerKey"=>SecureRandom.uuid, "Description"=>"Created with RubySDK"}
195
+ email.properties["SendClassification"] = {"CustomerKey"=>sendClassificationCustomerKey}
196
+ email.properties["SendDefinitionList"] = {"List"=> {"ID"=>listID}, "DataSourceTypeID"=>"List"}
197
+ email.properties["Email"] = {"ID"=>emailID}
198
+ email.authStub = self
199
+ result = email.post
200
+ if result.status then
201
+ sendresult = email.send
202
+ if sendresult.status then
203
+ deleteresult = email.delete
204
+ return sendresult
205
+ else
206
+ raise "Unable to send using send definition due to: #{result.results[0][:status_message]}"
207
+ end
208
+ else
209
+ raise "Unable to create send definition due to: #{result.results[0][:status_message]}"
210
+ end
211
+ end
212
+
213
+ def SendEmailToDataExtension(emailID, sendableDataExtensionCustomerKey, sendClassificationCustomerKey)
214
+ email = ET_Email::SendDefinition.new
215
+ email.properties = {"Name"=>SecureRandom.uuid, "CustomerKey"=>SecureRandom.uuid, "Description"=>"Created with RubySDK"}
216
+ email.properties["SendClassification"] = {"CustomerKey"=> sendClassificationCustomerKey}
217
+ email.properties["SendDefinitionList"] = {"CustomerKey"=> sendableDataExtensionCustomerKey, "DataSourceTypeID"=>"CustomObject"}
218
+ email.properties["Email"] = {"ID"=>emailID}
219
+ email.authStub = self
220
+ result = email.post
221
+ if result.status then
222
+ sendresult = email.send
223
+ if sendresult.status then
224
+ deleteresult = email.delete
225
+ return sendresult
226
+ else
227
+ raise "Unable to send using send definition due to: #{result.results[0][:status_message]}"
228
+ end
229
+ else
230
+ raise "Unable to create send definition due to: #{result.results[0][:status_message]}"
231
+ end
232
+ end
233
+ def CreateAndStartListImport(listId,fileName)
234
+ import = ET_Import.new
235
+ import.authStub = self
236
+ import.properties = {"Name"=> "SDK Generated Import #{DateTime.now.to_s}"}
237
+ import.properties["CustomerKey"] = SecureRandom.uuid
238
+ import.properties["Description"] = "SDK Generated Import"
239
+ import.properties["AllowErrors"] = "true"
240
+ import.properties["DestinationObject"] = {"ID"=>listId}
241
+ import.properties["FieldMappingType"] = "InferFromColumnHeadings"
242
+ import.properties["FileSpec"] = fileName
243
+ import.properties["FileType"] = "CSV"
244
+ import.properties["RetrieveFileTransferLocation"] = {"CustomerKey"=>"ExactTarget Enhanced FTP"}
245
+ import.properties["UpdateType"] = "AddAndUpdate"
246
+ result = import.post
247
+
248
+ if result.status then
249
+ return import.start
250
+ else
251
+ raise "Unable to create import definition due to: #{result.results[0][:status_message]}"
252
+ end
253
+ end
254
+
255
+ def CreateAndStartDataExtensionImport(dataExtensionCustomerKey, fileName, overwrite)
256
+ import = ET_Import.new
257
+ import.authStub = self
258
+ import.properties = {"Name"=> "SDK Generated Import #{DateTime.now.to_s}"}
259
+ import.properties["CustomerKey"] = SecureRandom.uuid
260
+ import.properties["Description"] = "SDK Generated Import"
261
+ import.properties["AllowErrors"] = "true"
262
+ import.properties["DestinationObject"] = {"CustomerKey"=>dataExtensionCustomerKey}
263
+ import.properties["FieldMappingType"] = "InferFromColumnHeadings"
264
+ import.properties["FileSpec"] = fileName
265
+ import.properties["FileType"] = "CSV"
266
+ import.properties["RetrieveFileTransferLocation"] = {"CustomerKey"=>"ExactTarget Enhanced FTP"}
267
+ if overwrite then
268
+ import.properties["UpdateType"] = "Overwrite"
269
+ else
270
+ import.properties["UpdateType"] = "AddAndUpdate"
271
+ end
272
+ result = import.post
273
+
274
+ if result.status then
275
+ return import.start
276
+ else
277
+ raise "Unable to create import definition due to: #{result.results[0][:status_message]}"
278
+ end
279
+ end
280
+
281
+ def CreateProfileAttributes(allAttributes)
282
+ attrs = ET_ProfileAttribute.new
283
+ attrs.authStub = self
284
+ attrs.properties = allAttributes
285
+ return attrs.post
286
+ end
287
+
288
+ def CreateContentAreas(arrayOfContentAreas)
289
+ postC = ET_ContentArea.new
290
+ postC.authStub = self
291
+ postC.properties = arrayOfContentAreas
292
+ sendResponse = postC.post
293
+ return sendResponse
294
+ end
295
+ end
296
+ end