iterable-api-client 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ module Iterable
2
+ ##
3
+ #
4
+ # Interact with /templates/push API endpoints
5
+ #
6
+ # @example Creating push templates endpoint object
7
+ # # With default config
8
+ # templates = Iterable::PushTemplates.new
9
+ # templates.get
10
+ #
11
+ # # With custom config
12
+ # conf = Iterable::Config.new(token: 'new-token')
13
+ # templates = Iterable::PushTemplates.new(config)
14
+ class PushTemplates < ApiResource
15
+ ##
16
+ #
17
+ # Get a push template
18
+ #
19
+ # @param template_id [String|Integer] A push template ID
20
+ # @param params [Hash] Additional params to use such as locale
21
+ #
22
+ # @return [Iterable::Response] A response object
23
+ def get(template_id, params = {})
24
+ params['templateId'] = template_id
25
+ Iterable.request(conf, '/templates/push/get', params).get
26
+ end
27
+
28
+ ##
29
+ #
30
+ # Update a push template
31
+ #
32
+ # @param template_id [String|Integer] A push template ID
33
+ # @param attrs [Hash] Update attributes
34
+ #
35
+ # @return [Iterable::Response] A response object
36
+ def update(template_id, attrs = {})
37
+ attrs['templateId'] = template_id
38
+ Iterable.request(conf, '/templates/push/update').post(attrs)
39
+ end
40
+
41
+ ##
42
+ #
43
+ # Upsert a push template by client template ID
44
+ #
45
+ # @param client_template_id [String] A client template id to use or create
46
+ # @param attrs [Hash] Update attributes
47
+ #
48
+ # @return [Iterable::Response] A response object
49
+ def upsert(client_template_id, attrs = {})
50
+ attrs['clientTemplateId'] = client_template_id
51
+ Iterable.request(conf, '/templates/push/upsert').post(attrs)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,100 @@
1
+ require 'openssl'
2
+ require 'uri'
3
+
4
+ module Iterable
5
+ # @!visibility private
6
+ class Request
7
+ DEFAULT_OPTIONS = {
8
+ use_ssl: true,
9
+ verify_ssl: true,
10
+ verify_mode: OpenSSL::SSL::VERIFY_PEER
11
+ }.freeze
12
+
13
+ DEFAULT_HEADERS = {
14
+ 'accept' => 'application/json',
15
+ 'content-type' => 'application/json'
16
+ }.freeze
17
+
18
+ def initialize(config, path, params = {})
19
+ @config = config
20
+ @uri = build_uri(path, params)
21
+ @net = net_http
22
+ setup_http(@net)
23
+ end
24
+
25
+ def get(headers = {})
26
+ execute :get, {}, headers
27
+ end
28
+
29
+ def post(body = {}, headers = {})
30
+ execute :post, body, headers
31
+ end
32
+
33
+ def put(body = {}, headers = {})
34
+ execute :put, body, headers
35
+ end
36
+
37
+ def delete(headers = {})
38
+ execute :delete, {}, headers
39
+ end
40
+
41
+ private
42
+
43
+ def execute(verb, body = {}, headers = {})
44
+ http = connection(verb, body, headers)
45
+ setup_http(http)
46
+ transmit http
47
+ end
48
+
49
+ def connection(verb, body = {}, headers = {})
50
+ conn_headers = DEFAULT_HEADERS.merge(headers)
51
+ req = Net::HTTP.const_get(verb.to_s.capitalize, false).new(@uri, conn_headers)
52
+ req.body = JSON.dump(body)
53
+ req
54
+ end
55
+
56
+ def setup_http(http)
57
+ DEFAULT_OPTIONS.dup.each do |option, value|
58
+ setter = "#{option.to_sym}="
59
+ http.send(setter, value) if http.respond_to?(setter)
60
+ end
61
+ end
62
+
63
+ def build_uri(path, params = {})
64
+ uri = @config.uri
65
+ uri.path += path
66
+ params['api_key'] = @config.token
67
+ uri.query = URI.encode_www_form(params)
68
+ uri
69
+ end
70
+
71
+ def net_http
72
+ Net::HTTP.new(@uri.hostname, @uri.port, nil, nil, nil, nil)
73
+ end
74
+
75
+ def transmit(req)
76
+ response = nil
77
+ @net.start do |http|
78
+ response = http.request(req, nil, &:read_body)
79
+ end
80
+ handle_response response
81
+ end
82
+
83
+ def handle_response(response)
84
+ redirected = response.is_a?(Net::HTTPRedirection) || response.code == '303'
85
+ if redirected && response['location']
86
+ Response.new Net::HTTP.get_response(uri_for_redirect(response))
87
+ else
88
+ Response.new response
89
+ end
90
+ end
91
+
92
+ def uri_for_redirect(response)
93
+ uri = @config.uri
94
+ redirect_uri = URI(response['location'])
95
+ uri.path = redirect_uri.path
96
+ uri.query = redirect_uri.query
97
+ uri
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,46 @@
1
+ require 'forwardable'
2
+
3
+ module Iterable
4
+ ##
5
+ #
6
+ # Response class is used to get access to raw HTTP request info
7
+ class Response
8
+ extend Forwardable
9
+
10
+ def_delegators :@resp, :code, :message, :uri
11
+
12
+ attr_reader :body
13
+
14
+ # @!visibility private
15
+ def initialize(resp) # @private
16
+ @resp = resp
17
+ @body = parsed_body
18
+ end
19
+
20
+ ##
21
+ #
22
+ # Convenience method to determine if request was successfull or not
23
+ # @return [Boolean]
24
+ def success?
25
+ case @resp.code.to_i
26
+ when (200..299) then true
27
+ else
28
+ false
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ ##
35
+ # Attempts to parse the response as JSON. Will rescue and return original
36
+ # if unable to parse.
37
+ #
38
+ # @return [Hash,Array,String] A parsed JSON object or the original response body
39
+ def parsed_body
40
+ response_body = @resp.body
41
+ MultiJson.load response_body
42
+ rescue MultiJson::ParseError
43
+ response_body
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ module Iterable
2
+ ##
3
+ #
4
+ # Interact with /templates API endpoints
5
+ #
6
+ # @example Creating templates endpoint object
7
+ # # With default config
8
+ # templates = Iterable::Templates.new
9
+ # templates.all
10
+ #
11
+ # # With custom config
12
+ # conf = Iterable::Config.new(token: 'new-token')
13
+ # templates = Iterable::Templates.new(config)
14
+ class Templates < ApiResource
15
+ # Template types
16
+ TYPES = [
17
+ BASE_TYPE = 'Base'.freeze,
18
+ BLAST_TYPE = 'Blast'.freeze,
19
+ TRIGGERED_TYPE = 'Triggered'.freeze,
20
+ WORKFLOW_TYPE = 'Workflow'.freeze
21
+ ].freeze
22
+
23
+ ##
24
+ #
25
+ # Get all templates
26
+ #
27
+ # @return [Iterable::Response] A response object
28
+ def all(params = {})
29
+ Iterable.request(conf, '/templates', params).get
30
+ end
31
+
32
+ def for_client_template_id(client_template_id)
33
+ params = { clientTemplateId: client_template_id }
34
+ Iterable.request(conf, '/templates/getByClientTemplateId', params).get
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,190 @@
1
+ module Iterable
2
+ ##
3
+ #
4
+ # Interact with /users API endpoints
5
+ #
6
+ # @example Creating users endpoint object
7
+ # # With default config
8
+ # templates = Iterable::Users.new
9
+ # templates.get
10
+ #
11
+ # # With custom config
12
+ # conf = Iterable::Config.new(token: 'new-token')
13
+ # templates = Iterable::Users.new(config)
14
+ class Users < ApiResource
15
+ ##
16
+ #
17
+ # Update user data or adds a user if missing. Data is merged - missing
18
+ # fields are not deleted
19
+ #
20
+ # @param email [String] User email to update or create
21
+ # @param attrs [Hash] Additional data to update or add
22
+ #
23
+ # @return [Iterable::Response] A response object
24
+ def update(email, attrs = {})
25
+ attrs['email'] = email
26
+ Iterable.request(conf, '/users/update').post(attrs)
27
+ end
28
+
29
+ ##
30
+ #
31
+ # Bulk update user data or adds it if does not exist. Data is merged and
32
+ # missing fields are not deleted
33
+ #
34
+ # @param users [Array[Hash]] Array of hashes of user details
35
+ #
36
+ # @return [Iterable::Response] A response object
37
+ #
38
+ # @note User fields can be email [String], dataFields [Hash], or userId [String]
39
+ def bulk_update(users = [])
40
+ Iterable.request(conf, '/users/bulkUpdate').post(users: users)
41
+ end
42
+
43
+ ##
44
+ #
45
+ # Update user subscriptions. Overwrites existing data if the field is
46
+ # provided and not null
47
+ #
48
+ # @param email [String] User email to update
49
+ # @param attrs [Hash] Additional data to update
50
+ #
51
+ # @return [Iterable::Response] A response object
52
+ def update_subscriptions(email, attrs = {})
53
+ attrs['email'] = email
54
+ Iterable.request(conf, '/users/updateSubscriptions').post(attrs)
55
+ end
56
+
57
+ ##
58
+ #
59
+ # Update user subscriptions in bulk. Overwrites existing data if the field is
60
+ # provided and not null
61
+ #
62
+ # @param subscriptions [Array[Hash]] An array of subscription update attributes
63
+ #
64
+ # @return [Iterable::Response] A response object
65
+ #
66
+ # @note Refer to [Iterable::Users#update_subscriptions] for what subscription
67
+ # information is needed such as email
68
+ def bulk_update_subscriptions(subscriptions = [])
69
+ attrs = { updateSubscriptionsRequests: subscriptions }
70
+ Iterable.request(conf, '/users/bulkUpdateSubscriptions').post(attrs)
71
+ end
72
+
73
+ ##
74
+ #
75
+ # Get a user by their email
76
+ #
77
+ # @param email [String] The email of the user to get
78
+ #
79
+ # @return [Iterable::Response] A response object
80
+ def for_email(email)
81
+ Iterable.request(conf, "/users/#{email}").get
82
+ end
83
+
84
+ ##
85
+ #
86
+ # Update a user email
87
+ #
88
+ # @param email [String] The email of the user to get
89
+ #
90
+ # @return [Iterable::Response] A response object
91
+ def update_email(email, new_email)
92
+ attrs = { currentEmail: email, newEmail: new_email }
93
+ Iterable.request(conf, '/users/updateEmail').post(attrs)
94
+ end
95
+
96
+ ##
97
+ #
98
+ # Delete a user by their email
99
+ #
100
+ # @param email [String] The email of the user to delete
101
+ #
102
+ # @return [Iterable::Response] A response object
103
+ def delete(email)
104
+ Iterable.request(conf, "/users/#{email}").delete
105
+ end
106
+
107
+ ##
108
+ #
109
+ # Delete a user by their userId
110
+ #
111
+ # @param user_id [String] The userId of the user to delete
112
+ #
113
+ # @return [Iterable::Response] A response object
114
+ def delete_by_id(user_id)
115
+ Iterable.request(conf, "/users/byUserId/#{user_id}").delete
116
+ end
117
+
118
+ ##
119
+ #
120
+ # Get a user by their userId
121
+ #
122
+ # @param user_id [String] The user ID of the user to get
123
+ #
124
+ # @return [Iterable::Response] A response object
125
+ def for_id(user_id)
126
+ Iterable.request(conf, "/users/byUserId/#{user_id}").get
127
+ end
128
+
129
+ ##
130
+ #
131
+ # Get the user fields with mappings from field to type
132
+ #
133
+ # @return [Iterable::Response] A response object
134
+ def fields
135
+ Iterable.request(conf, '/users/getFields').get
136
+ end
137
+
138
+ ##
139
+ #
140
+ # Register a browser token for a user
141
+ #
142
+ # @param email [String] An email of a user
143
+ # @param token [String] The browser token to register
144
+ # @param attrs [Hash] Additional attrs like userId to pass along
145
+ #
146
+ # @return [Iterable::Response] A response object
147
+ #
148
+ # @note An email or userId is required
149
+ def register_browser_token(email, token, attrs = {})
150
+ attrs[:email] = email
151
+ attrs[:browserToken] = token
152
+ Iterable.request(conf, '/users/registerBrowserToken').post(attrs)
153
+ end
154
+
155
+ ##
156
+ #
157
+ # Disable a device
158
+ #
159
+ # @param token [String] A device token to disable
160
+ # @param email [String] Optional user email device belongs to to disable
161
+ # @param user_id [String] Optional user_id device belongs to to disable
162
+ #
163
+ # @return [Iterable::Response] A response object
164
+ #
165
+ # @note An email or userId is required
166
+ def disable_device(token, email = nil, user_id = nil)
167
+ attrs = { token: token }
168
+ attrs[:email] = email if email
169
+ attrs[:userId] = user_id if user_id
170
+ Iterable.request(conf, '/users/disableDevice').post(attrs)
171
+ end
172
+
173
+ ##
174
+ #
175
+ # Get sent messages for a user
176
+ #
177
+ # @param email [String] An email for a user to retreive messages for
178
+ # @param start_time [Time] An optional start time for range of messages
179
+ # @param end_time [Time] An optional end time for range of messages
180
+ # @param params [Hash] Additional params to use to filter messages further
181
+ #
182
+ # @return [Iterable::Response] A response object
183
+ def sent_messages(email, start_time = nil, end_time = nil, params = {})
184
+ params[:email] = email
185
+ params[:startTime] = start_time.to_s if start_time
186
+ params[:endTime] = end_time.to_s if end_time
187
+ Iterable.request(conf, '/users/getSentMessages', params).get
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,30 @@
1
+ module Iterable
2
+ ##
3
+ #
4
+ # Interact with /workflows API endpoints
5
+ #
6
+ # @example Creating workflows endpoint object
7
+ # # With default config
8
+ # templates = Iterable::Workflows.new
9
+ # templates.get
10
+ #
11
+ # # With custom config
12
+ # conf = Iterable::Config.new(token: 'new-token')
13
+ # templates = Iterable::Workflows.new(config)
14
+ class Workflows < ApiResource
15
+ ##
16
+ #
17
+ # Trigger a workflow for an email or a list.
18
+ #
19
+ # @param workflow_id [Integer] workflow_id to trigger
20
+ # @param attrs [Hash] Additional data fields
21
+ #
22
+ # @return [Iterable::Response] A response object
23
+ #
24
+ # @note An email or listId is required to trigger a workflow
25
+ def trigger(workflow_id, attrs = {})
26
+ attrs['workflowId'] = workflow_id
27
+ Iterable.request(conf, '/workflows/triggerWorkflow').post(attrs)
28
+ end
29
+ end
30
+ end