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.
- 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
|