iterable-api-client 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +733 -1
- data/lib/iterable.rb +61 -1
- data/lib/iterable/api_resource.rb +39 -0
- data/lib/iterable/campaigns.rb +68 -0
- data/lib/iterable/channels.rb +24 -0
- data/lib/iterable/commerce.rb +53 -0
- data/lib/iterable/config.rb +39 -0
- data/lib/iterable/csv_exporter.rb +19 -0
- data/lib/iterable/device.rb +74 -0
- data/lib/iterable/email.rb +28 -0
- data/lib/iterable/email_templates.rb +54 -0
- data/lib/iterable/events.rb +59 -0
- data/lib/iterable/experiments.rb +50 -0
- data/lib/iterable/export.rb +124 -0
- data/lib/iterable/json_exporter.rb +23 -0
- data/lib/iterable/lists.rb +89 -0
- data/lib/iterable/message_types.rb +31 -0
- data/lib/iterable/metadata.rb +24 -0
- data/lib/iterable/metadata_table.rb +93 -0
- data/lib/iterable/push_templates.rb +54 -0
- data/lib/iterable/request.rb +100 -0
- data/lib/iterable/response.rb +46 -0
- data/lib/iterable/templates.rb +37 -0
- data/lib/iterable/users.rb +190 -0
- data/lib/iterable/workflows.rb +30 -0
- metadata +39 -2
- metadata.gz.sig +0 -0
@@ -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
|