fuelsdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,142 @@
1
+ module FuelSDK
2
+ class ET_Response
3
+ # not doing accessor so user, can't update these values from response.
4
+ # You will see in the code some of these
5
+ # items are being updated via back doors and such.
6
+ attr_reader :code, :message, :results, :request_id, :body, :raw
7
+
8
+ # some defaults
9
+ def success
10
+ @success ||= false
11
+ end
12
+ alias :success? :success
13
+ alias :status :success # backward compatibility
14
+
15
+ def more
16
+ @more ||= false
17
+ end
18
+ alias :more? :more
19
+
20
+ def initialize raw, client
21
+ @client = client # keep connection with client in case we request more
22
+ @results = []
23
+ @raw = raw
24
+ @body = raw.body
25
+ unpack raw
26
+ rescue => ex # all else fails return raw
27
+ puts ex.message
28
+ raw
29
+ end
30
+
31
+ def continue
32
+ raise NotImplementedError
33
+ end
34
+
35
+ private
36
+ def unpack raw
37
+ raise NotImplementedError
38
+ end
39
+ end
40
+
41
+ class ET_Client
42
+ attr_accessor :debug, :access_token, :auth_token, :internal_token, :refresh_token,
43
+ :id, :secret, :signature
44
+
45
+ include FuelSDK::Soap
46
+ include FuelSDK::Rest
47
+
48
+ def jwt= encoded_jwt
49
+ raise 'Require app signature to decode JWT' unless self.signature
50
+ decoded_jwt = JWT.decode(encoded_jwt, self.signature, true)
51
+
52
+ self.auth_token = decoded_jwt['request']['user']['oauthToken']
53
+ self.internal_token = decoded_jwt['request']['user']['internalOauthToken']
54
+ self.refresh_token = decoded_jwt['request']['user']['refreshToken']
55
+ #@authTokenExpiration = Time.new + decoded_jwt['request']['user']['expiresIn']
56
+ end
57
+
58
+ def initialize(params={}, debug=false)
59
+ self.debug = debug
60
+ client_config = params['client']
61
+ if client_config
62
+ self.id = client_config["id"]
63
+ self.secret = client_config["secret"]
64
+ self.signature = client_config["signature"]
65
+ end
66
+
67
+ self.jwt = params['jwt'] if params['jwt']
68
+ self.refresh_token = params['refresh_token'] if params['refresh_token']
69
+
70
+ self.wsdl = params["defaultwsdl"] if params["defaultwsdl"]
71
+ end
72
+
73
+ def refresh force=false
74
+ raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)
75
+
76
+ if (self.access_token.nil? || force)
77
+ payload = Hash.new.tap do |h|
78
+ h['clientId']= id
79
+ h['clientSecret'] = secret
80
+ h['refreshToken'] = refresh_token if refresh_token
81
+ h['accessType'] = 'offline'
82
+ end
83
+
84
+ options = Hash.new.tap do |h|
85
+ h['data'] = payload
86
+ h['content_type'] = 'application/json'
87
+ h['params'] = {'legacy' => 1}
88
+ end
89
+
90
+ response = post("https://auth.exacttargetapis.com/v1/requestToken", options)
91
+ raise "Unable to refresh token: #{response['message']}" unless response.has_key?('accessToken')
92
+
93
+ self.access_token = response['accessToken']
94
+ self.internal_token = response['legacyToken']
95
+ #@authTokenExpiration = Time.new + tokenResponse['expiresIn']
96
+ self.refresh_token = response['refreshToken'] if response.has_key?("refreshToken")
97
+ end
98
+ end
99
+
100
+ def refresh!
101
+ refresh true
102
+ end
103
+
104
+ #def AddSubscriberToList(emailAddress, listIDs, subscriberKey = nil)
105
+ # newSub = FuelSDK::ET_Subscriber.new
106
+ # newSub.authStub = self
107
+ # lists = []
108
+
109
+ # listIDs.each{ |p|
110
+ # lists.push({"ID"=> p})
111
+ # }
112
+
113
+ # newSub.props = {"EmailAddress" => emailAddress, "Lists" => lists}
114
+ # if !subscriberKey.nil? then
115
+ # newSub.props['SubscriberKey'] = subscriberKey;
116
+ # end
117
+
118
+ # # Try to add the subscriber
119
+ # postResponse = newSub.post
120
+
121
+ # if postResponse.status == false then
122
+ # # If the subscriber already exists in the account then we need to do an update.
123
+ # # Update Subscriber On List
124
+ # if postResponse.results[0][:error_code] == "12014" then
125
+ # patchResponse = newSub.patch
126
+ # return patchResponse
127
+ # end
128
+ # end
129
+ # return postResponse
130
+ #end
131
+
132
+ #def CreateDataExtensions(dataExtensionDefinitions)
133
+ # newDEs = FuelSDK::ET_DataExtension.new
134
+ # newDEs.authStub = self
135
+
136
+ # newDEs.props = dataExtensionDefinitions
137
+ # postResponse = newDEs.post
138
+
139
+ # return postResponse
140
+ #end
141
+ end
142
+ end
@@ -0,0 +1,79 @@
1
+ require 'open-uri'
2
+ require 'net/https'
3
+ require 'json'
4
+
5
+ module FuelSDK
6
+
7
+ class HTTPResponse < FuelSDK::ET_Response
8
+
9
+ def initialize raw, client, request
10
+ super raw, client
11
+ @request = request
12
+ end
13
+
14
+ def continue
15
+ rsp = nil
16
+ if more?
17
+ rsp = unpack @client.rest_get(@request['url'], @request['options'])
18
+ else
19
+ puts 'No more data'
20
+ end
21
+
22
+ rsp
23
+ end
24
+
25
+ def [] key
26
+ @results[key]
27
+ end
28
+
29
+ private
30
+ def unpack raw
31
+ @code = raw.code.to_i
32
+ @message = raw.message
33
+ @body = JSON.parse(raw.body) rescue {}
34
+ @results = @body
35
+ @more = ((@results['count'] || @results['totalCount']) > @results['page'] * @results['pageSize']) rescue false
36
+ @success = @message == 'OK'
37
+ end
38
+
39
+ # by default try everything against results
40
+ def method_missing method, *args, &block
41
+ @results.send(method, *args, &block)
42
+ end
43
+ end
44
+
45
+ module HTTPRequest
46
+
47
+ request_methods = ['get', 'post', 'patch', 'delete']
48
+ request_methods.each do |method|
49
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
50
+ def #{method}(url, options={}) # def post(url, options)
51
+ request Net::HTTP::#{method.capitalize}, url, options # request Net::HTTP::Post, url, options
52
+ end # end
53
+ EOT
54
+ end
55
+
56
+ private
57
+
58
+ def generate_uri(url, params=nil)
59
+ uri = URI.parse(url)
60
+ uri.query = URI.encode_www_form(params) if params
61
+ uri
62
+ end
63
+
64
+ def request(method, url, options={})
65
+ uri = generate_uri url, options['params']
66
+
67
+ http = Net::HTTP.new(uri.host, uri.port)
68
+ http.use_ssl = true
69
+
70
+ data = options['data']
71
+ _request = method.new uri.request_uri
72
+ _request.body = data.to_json if data
73
+ _request.content_type = options['content_type'] if options['content_type']
74
+ response = http.request(_request)
75
+
76
+ HTTPResponse.new(response, self, :url => url, :options => options)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,143 @@
1
+ module FuelSDK
2
+ module ET_SoapGet
3
+ def get
4
+ client.soap_get id, properties, filter
5
+ end
6
+
7
+ def info
8
+ client.soap_describe id
9
+ end
10
+ end
11
+
12
+ module ET_SoapCUD #create, update, delete
13
+ def post
14
+ client.soap_post id, properties
15
+ end
16
+
17
+ def patch
18
+ client.soap_patch id, properties
19
+ end
20
+
21
+ def delete
22
+ client.soap_delete id, properties
23
+ end
24
+ end
25
+
26
+ module ET_RestGet
27
+ def get
28
+ client.rest_get id, properties
29
+ end
30
+ end
31
+
32
+ module ET_RestCUD
33
+ def post
34
+ client.rest_post id, properties
35
+ end
36
+
37
+ def patch
38
+ client.rest_patch id, properties
39
+ end
40
+
41
+ def delete
42
+ client.rest_delete id, properties
43
+ end
44
+ end
45
+
46
+ class ET_Base
47
+ attr_accessor :filter, :properties, :client
48
+ attr_reader :id
49
+
50
+ alias props= properties= # backward compatibility
51
+ alias authStub= client= # backward compatibility
52
+
53
+ def id
54
+ self.class.name.split('::').pop.split('_').pop
55
+ end
56
+ end
57
+
58
+ class ET_BounceEvent < ET_Base
59
+ include ET_SoapGet
60
+ end
61
+
62
+ class ET_ClickEvent < ET_Base
63
+ include ET_SoapGet
64
+ end
65
+
66
+ class ET_ContentArea < ET_Base
67
+ include ET_SoapGet
68
+ include ET_SoapCUD
69
+ end
70
+
71
+ class ET_Folder < ET_Base
72
+ include ET_SoapGet
73
+ include ET_SoapCUD
74
+ def id
75
+ 'DataFolder'
76
+ end
77
+ end
78
+
79
+ class ET_Email < ET_Base
80
+ include ET_SoapGet
81
+ include ET_SoapCUD
82
+ end
83
+
84
+ class ET_List < ET_Base
85
+ include ET_SoapGet
86
+ include ET_SoapCUD
87
+
88
+ class Subscriber < ET_Base
89
+ include ET_SoapGet
90
+ def id
91
+ 'ListSubscriber'
92
+ end
93
+ end
94
+ end
95
+
96
+ class ET_OpenEvent < ET_Base
97
+ include ET_SoapGet
98
+ end
99
+
100
+ class ET_SentEvent < ET_Base
101
+ include ET_SoapGet
102
+ end
103
+
104
+ class ET_Subscriber < ET_Base
105
+ include ET_SoapGet
106
+ include ET_SoapCUD
107
+ end
108
+
109
+ class ET_UnsubEvent < ET_Base
110
+ include ET_SoapGet
111
+ end
112
+
113
+ class ET_Campaign < ET_Base
114
+ include ET_RestGet
115
+ include ET_RestCUD
116
+
117
+
118
+ def properties
119
+ @properties ||= {}
120
+ @properties.merge! 'id' => '' unless @properties.include? 'id'
121
+ @properties
122
+ end
123
+
124
+ def id
125
+ "https://www.exacttargetapis.com/hub/v1/campaigns/%{id}"
126
+ end
127
+
128
+ class Asset < ET_Base
129
+ include ET_RestGet
130
+ include ET_RestCUD
131
+
132
+ def properties
133
+ @properties ||= {}
134
+ @properties.merge! 'assetId' => '' unless @properties.include? 'assetId'
135
+ @properties
136
+ end
137
+
138
+ def id
139
+ 'https://www.exacttargetapis.com/hub/v1/campaigns/%{id}/assets/%{assetId}'
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,84 @@
1
+ module FuelSDK
2
+ module Rest
3
+
4
+ include FuelSDK::Targeting
5
+
6
+ def rest_client
7
+ self
8
+ end
9
+
10
+ def normalize_keys obj
11
+ if obj and obj.is_a? Hash
12
+ obj.keys.each do |k|
13
+ obj[(k.to_sym rescue k) || k] = obj.delete(k)
14
+ end
15
+ end
16
+ obj
17
+ end
18
+
19
+ def get_url_properties url, properties
20
+ url_property_names = url.scan(/(%{(.+?)})/).collect{|frmt, name| name}
21
+ url_properties = {}
22
+ properties.keys.each do |k|
23
+ if url_property_names.include? k
24
+ url_properties[k] = properties.delete(k)
25
+ end
26
+ end
27
+ url_properties
28
+ end
29
+
30
+ def complete_url url, url_properties
31
+ normalize_keys(url_properties)
32
+ url = url % url_properties if url_properties
33
+ url.end_with?('/') ? url.chop : url
34
+ rescue KeyError => ex
35
+ raise "#{ex.message} to complete #{url}"
36
+ end
37
+
38
+ def parse_properties url, properties
39
+ url_properties = get_url_properties url, properties
40
+ url = complete_url url, url_properties
41
+ [url, properties]
42
+ end
43
+
44
+ def rest_get url, properties={}
45
+ url, properties = parse_properties url, properties
46
+ rest_request :get, url, {'params' => properties}
47
+ end
48
+
49
+ def rest_delete url, properties={}
50
+ url, properties = parse_properties url, properties
51
+ rest_request :delete, url
52
+ end
53
+
54
+ def rest_patch url, properties={}
55
+ url, payload = parse_properties url, properties
56
+ rest_request :patch, url, {'data' => payload,
57
+ 'content_type' => 'application/json'}
58
+ end
59
+
60
+ def rest_post url, properties={}
61
+ url, payload = parse_properties url, properties
62
+ rest_request :post, url, {'data' => payload,
63
+ 'content_type' => 'application/json'}
64
+ end
65
+
66
+ private
67
+ def rest_request action, url, options={}
68
+ retried = false
69
+ begin
70
+ (options['params'] ||= {}).merge! 'access_token' => access_token
71
+ rsp = rest_client.send(action, url, options)
72
+ raise 'Unauthorized' if rsp.message == 'Unauthorized'
73
+ rescue
74
+ raise if retried
75
+ self.refresh! # ask for forgiveness not, permission
76
+ retried = true
77
+ retry
78
+ end
79
+ rsp
80
+ rescue
81
+ rsp
82
+ end
83
+ end
84
+ end