urbanairship 5.6.0 → 6.0.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
- data/CHANGELOG +30 -0
- data/README.rst +1 -0
- data/docs/ab_tests.rst +162 -0
- data/docs/attributes.rst +52 -0
- data/docs/automations.rst +212 -0
- data/docs/index.rst +3 -0
- data/docs/push.rst +24 -0
- data/docs/sms.rst +19 -0
- data/docs/static_lists.rst +2 -2
- data/lib/urbanairship.rb +12 -0
- data/lib/urbanairship/ab_tests/ab_test.rb +88 -0
- data/lib/urbanairship/ab_tests/experiment.rb +45 -0
- data/lib/urbanairship/ab_tests/variant.rb +34 -0
- data/lib/urbanairship/automations/automation.rb +105 -0
- data/lib/urbanairship/automations/pipeline.rb +52 -0
- data/lib/urbanairship/client.rb +22 -9
- data/lib/urbanairship/common.rb +63 -16
- data/lib/urbanairship/configuration.rb +2 -1
- data/lib/urbanairship/custom_events/custom_event.rb +60 -0
- data/lib/urbanairship/custom_events/payload.rb +89 -0
- data/lib/urbanairship/devices/attribute.rb +54 -0
- data/lib/urbanairship/devices/channel_tags.rb +1 -1
- data/lib/urbanairship/devices/channel_uninstall.rb +10 -10
- data/lib/urbanairship/devices/create_and_send.rb +4 -4
- data/lib/urbanairship/devices/devicelist.rb +28 -7
- data/lib/urbanairship/devices/email.rb +5 -5
- data/lib/urbanairship/devices/email_notification.rb +11 -4
- data/lib/urbanairship/devices/named_user.rb +6 -6
- data/lib/urbanairship/devices/open_channel.rb +22 -23
- data/lib/urbanairship/devices/segment.rb +5 -5
- data/lib/urbanairship/devices/sms.rb +40 -9
- data/lib/urbanairship/devices/static_lists.rb +12 -12
- data/lib/urbanairship/push/location.rb +7 -7
- data/lib/urbanairship/push/push.rb +23 -13
- data/lib/urbanairship/push/schedule.rb +9 -0
- data/lib/urbanairship/reports/response_statistics.rb +9 -9
- data/lib/urbanairship/version.rb +1 -1
- metadata +16 -5
data/lib/urbanairship/client.rb
CHANGED
@@ -13,10 +13,12 @@ module Urbanairship
|
|
13
13
|
#
|
14
14
|
# @param [Object] key Application Key
|
15
15
|
# @param [Object] secret Application Secret
|
16
|
+
# @param [String] token Application Auth Token (for custom events endpoint)
|
16
17
|
# @return [Object] Client
|
17
|
-
def initialize(key: required('key'), secret: required('secret'))
|
18
|
+
def initialize(key: required('key'), secret: required('secret'), token: nil)
|
18
19
|
@key = key
|
19
20
|
@secret = secret
|
21
|
+
@token = token
|
20
22
|
end
|
21
23
|
|
22
24
|
# Send a request to Airship's API
|
@@ -25,10 +27,11 @@ module Urbanairship
|
|
25
27
|
# @param [Object] body Request Body
|
26
28
|
# @param [Object] url Request URL
|
27
29
|
# @param [Object] content_type Content-Type
|
28
|
-
# @param [Object]
|
30
|
+
# @param [Object] encoding Encoding
|
31
|
+
# @param [Symbol] auth_type (:basic|:bearer)
|
29
32
|
# @return [Object] Push Response
|
30
33
|
def send_request(method: required('method'), url: required('url'), body: nil,
|
31
|
-
content_type: nil, encoding: nil)
|
34
|
+
content_type: nil, encoding: nil, auth_type: :basic)
|
32
35
|
req_type = case method
|
33
36
|
when 'GET'
|
34
37
|
:get
|
@@ -46,9 +49,14 @@ module Urbanairship
|
|
46
49
|
headers['Accept'] = 'application/vnd.urbanairship+json; version=3'
|
47
50
|
headers['Content-type'] = content_type unless content_type.nil?
|
48
51
|
headers['Content-Encoding'] = encoding unless encoding.nil?
|
52
|
+
|
53
|
+
if auth_type == :bearer
|
54
|
+
raise ArgumentError.new('token must be provided as argument if auth_type=bearer') if @token.nil?
|
55
|
+
headers['X-UA-Appkey'] = @key
|
56
|
+
headers['Authorization'] = "Bearer #{@token}"
|
57
|
+
end
|
49
58
|
|
50
|
-
debug = "Making #{method} request to #{url}.\n"+
|
51
|
-
"\tHeaders:\n"
|
59
|
+
debug = "Making #{method} request to #{url}.\n"+ "\tHeaders:\n"
|
52
60
|
debug += "\t\tcontent-type: #{content_type}\n" unless content_type.nil?
|
53
61
|
debug += "\t\tcontent-encoding: gzip\n" unless encoding.nil?
|
54
62
|
debug += "\t\taccept: application/vnd.urbanairship+json; version=3\n"
|
@@ -56,15 +64,20 @@ module Urbanairship
|
|
56
64
|
|
57
65
|
logger.debug(debug)
|
58
66
|
|
59
|
-
|
67
|
+
params = {
|
60
68
|
method: method,
|
61
69
|
url: url,
|
62
70
|
headers: headers,
|
63
|
-
user: @key,
|
64
|
-
password: @secret,
|
65
71
|
payload: body,
|
66
72
|
timeout: Urbanairship.configuration.timeout
|
67
|
-
|
73
|
+
}
|
74
|
+
|
75
|
+
if auth_type == :basic
|
76
|
+
params[:user] = @key
|
77
|
+
params[:password] = @secret
|
78
|
+
end
|
79
|
+
|
80
|
+
response = RestClient::Request.execute(params)
|
68
81
|
|
69
82
|
logger.debug("Received #{response.code} response. Headers:\n\t#{response.headers}\nBody:\n\t#{response.body}")
|
70
83
|
Response.check_code(response.code, response)
|
data/lib/urbanairship/common.rb
CHANGED
@@ -4,22 +4,69 @@ require 'urbanairship/loggable'
|
|
4
4
|
module Urbanairship
|
5
5
|
# Features mixed in to all classes
|
6
6
|
module Common
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
7
|
+
def url_for(path)
|
8
|
+
"https://#{Urbanairship.configuration.server}/api#{path}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def apid_url(path='')
|
12
|
+
url_for("/apids/#{path}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def channel_url(path='')
|
16
|
+
url_for("/channels/#{path}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_and_send_url(path='')
|
20
|
+
url_for("/create-and-send/#{path}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def custom_events_url(path='')
|
24
|
+
url_for("/custom-events/#{path}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def device_token_url(path='')
|
28
|
+
url_for("/device_tokens/#{path}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def experiments_url(path='')
|
32
|
+
url_for("/experiments/#{path}")
|
33
|
+
end
|
34
|
+
|
35
|
+
def lists_url(path='')
|
36
|
+
url_for("/lists/#{path}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def location_url(path='')
|
40
|
+
url_for("/location/#{path}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def named_users_url(path='')
|
44
|
+
url_for("/named_users/#{path}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def open_channel_url(path='')
|
48
|
+
channel_url("/open/#{path}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def pipelines_url(path='')
|
52
|
+
url_for("/pipelines/#{path}")
|
53
|
+
end
|
54
|
+
|
55
|
+
def push_url(path='')
|
56
|
+
url_for("/push/#{path}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def reports_url(path='')
|
60
|
+
url_for("/reports/#{path}")
|
61
|
+
end
|
62
|
+
|
63
|
+
def schedules_url(path='')
|
64
|
+
url_for("/schedules/#{path}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def segments_url(path='')
|
68
|
+
url_for("/segments/#{path}")
|
69
|
+
end
|
23
70
|
|
24
71
|
# Helper method for required keyword args in Ruby 2.0 that is compatible with 2.1+
|
25
72
|
# @example
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Urbanairship
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :custom_logger, :log_path, :log_level, :timeout
|
3
|
+
attr_accessor :custom_logger, :log_path, :log_level, :server, :timeout
|
4
4
|
|
5
5
|
def initialize
|
6
|
+
@server = 'go.urbanairship.com'
|
6
7
|
@custom_logger = nil
|
7
8
|
@log_path = nil
|
8
9
|
@log_level = Logger::INFO
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'urbanairship'
|
3
|
+
require 'urbanairship/common'
|
4
|
+
require 'urbanairship/loggable'
|
5
|
+
|
6
|
+
module Urbanairship
|
7
|
+
module CustomEvents
|
8
|
+
class CustomEvent
|
9
|
+
include Urbanairship::Common
|
10
|
+
include Urbanairship::Loggable
|
11
|
+
|
12
|
+
attr_accessor :events
|
13
|
+
|
14
|
+
def initialize(client: required('client'))
|
15
|
+
@client = client
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
fail ArgumentError, 'events must be an array of custom events' unless events.is_a?(Array)
|
20
|
+
|
21
|
+
response = @client.send_request(
|
22
|
+
auth_type: :bearer,
|
23
|
+
body: JSON.dump(events),
|
24
|
+
content_type: 'application/json',
|
25
|
+
method: 'POST',
|
26
|
+
url: custom_events_url
|
27
|
+
)
|
28
|
+
cer = CustomEventResponse.new(body: response['body'], code: response['code'])
|
29
|
+
logger.info { cer.format }
|
30
|
+
|
31
|
+
cer
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Response to a successful custom event creation.
|
36
|
+
class CustomEventResponse
|
37
|
+
attr_reader :ok, :operation_id, :payload, :status_code
|
38
|
+
|
39
|
+
def initialize(body: nil, code: nil)
|
40
|
+
@payload = (body.nil? || body.empty?) ? {} : body
|
41
|
+
@ok = payload['ok']
|
42
|
+
@operation_id = payload['operationId']
|
43
|
+
@status_code = code
|
44
|
+
end
|
45
|
+
|
46
|
+
# String Formatting of the CustomEventResponse
|
47
|
+
#
|
48
|
+
# @return [Object] String Formatted CustomEventResponse
|
49
|
+
def format
|
50
|
+
"Received [#{status_code}] response code.\nBody:\n#{formatted_body}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def formatted_body
|
54
|
+
payload
|
55
|
+
.map { |key, value| "#{key}:\t#{value.to_s || 'None'}" }
|
56
|
+
.join("\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'urbanairship'
|
2
|
+
require 'urbanairship/common'
|
3
|
+
|
4
|
+
module Urbanairship
|
5
|
+
module CustomEvents
|
6
|
+
module Payload
|
7
|
+
include Urbanairship::Common
|
8
|
+
|
9
|
+
def custom_events(
|
10
|
+
body: required('body'),
|
11
|
+
occurred: required('occurred'),
|
12
|
+
user: required('user')
|
13
|
+
)
|
14
|
+
compact_helper({
|
15
|
+
body: body,
|
16
|
+
occurred: format_timestamp(occurred),
|
17
|
+
user: user
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
# Body specific portion of CustomEvent Object
|
22
|
+
def custom_events_body(
|
23
|
+
interaction_id: nil, interaction_type: nil, name: required('name'),
|
24
|
+
properties: nil, session_id: nil, transaction: nil, value: nil
|
25
|
+
)
|
26
|
+
|
27
|
+
validates_name_format(name)
|
28
|
+
validates_value_format(value)
|
29
|
+
|
30
|
+
compact_helper({
|
31
|
+
interaction_id: interaction_id,
|
32
|
+
interaction_type: interaction_type,
|
33
|
+
name: name,
|
34
|
+
properties: properties,
|
35
|
+
session_id: session_id,
|
36
|
+
transaction: transaction,
|
37
|
+
value: value
|
38
|
+
})
|
39
|
+
end
|
40
|
+
|
41
|
+
# User specific portion of CustomEvent Object
|
42
|
+
def custom_events_user(
|
43
|
+
amazon_channel: nil, android_channel: nil, channel: nil,
|
44
|
+
ios_channel: nil, named_user_id: nil, web_channel: nil
|
45
|
+
)
|
46
|
+
res = compact_helper({
|
47
|
+
amazon_channel: amazon_channel,
|
48
|
+
android_channel: android_channel,
|
49
|
+
channel: channel,
|
50
|
+
ios_channel: ios_channel,
|
51
|
+
named_user_id: named_user_id,
|
52
|
+
web_channel: web_channel,
|
53
|
+
})
|
54
|
+
|
55
|
+
fail ArgumentError, 'at least one user identifier must be defined' if res.empty?
|
56
|
+
|
57
|
+
res
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Formatters
|
62
|
+
# ------------------------------------------------------------------------
|
63
|
+
|
64
|
+
def format_timestamp(timestamp)
|
65
|
+
return timestamp if timestamp.is_a?(String)
|
66
|
+
|
67
|
+
timestamp.strftime('%Y-%m-%dT%H:%M:%S')
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
# Validators
|
72
|
+
# ------------------------------------------------------------------------
|
73
|
+
|
74
|
+
NAME_REGEX = /^[a-z0-9_\-]+$/
|
75
|
+
def validates_name_format(name)
|
76
|
+
return if name =~ NAME_REGEX
|
77
|
+
|
78
|
+
fail ArgumentError, 'invalid "name": it must follows this pattern /^[a-z0-9_\-]+$/'
|
79
|
+
end
|
80
|
+
|
81
|
+
def validates_value_format(value)
|
82
|
+
return if value.nil?
|
83
|
+
return if value.is_a?(Numeric)
|
84
|
+
|
85
|
+
fail ArgumentError, 'invalid "value": must be a number'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'urbanairship'
|
2
|
+
|
3
|
+
module Urbanairship
|
4
|
+
module Devices
|
5
|
+
class Attribute
|
6
|
+
include Urbanairship::Common
|
7
|
+
include Urbanairship::Loggable
|
8
|
+
attr_accessor :attribute,
|
9
|
+
:operator,
|
10
|
+
:precision,
|
11
|
+
:value
|
12
|
+
|
13
|
+
def initialize(client: required('client'))
|
14
|
+
@client = client
|
15
|
+
end
|
16
|
+
|
17
|
+
def payload
|
18
|
+
if precision
|
19
|
+
date_attribute
|
20
|
+
elsif value.is_a? String
|
21
|
+
text_attribute
|
22
|
+
elsif value.is_a? Integer
|
23
|
+
number_attribute
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def number_attribute
|
28
|
+
{
|
29
|
+
'attribute': attribute,
|
30
|
+
'operator': operator,
|
31
|
+
'value': value
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def text_attribute
|
36
|
+
{
|
37
|
+
'attribute': attribute,
|
38
|
+
'operator': operator,
|
39
|
+
'value': value
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def date_attribute
|
44
|
+
{
|
45
|
+
'attribute': attribute,
|
46
|
+
'operator': operator,
|
47
|
+
'precision': precision,
|
48
|
+
'value': value
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -23,7 +23,7 @@ module Urbanairship
|
|
23
23
|
response = @client.send_request(
|
24
24
|
method: 'POST',
|
25
25
|
body: JSON.dump(channels),
|
26
|
-
url:
|
26
|
+
url: channel_url('uninstall/'),
|
27
27
|
content_type: 'application/json'
|
28
28
|
)
|
29
29
|
|
@@ -31,33 +31,33 @@ module Urbanairship
|
|
31
31
|
response
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
35
|
-
|
34
|
+
|
35
|
+
|
36
36
|
class OpenChannelUninstall
|
37
37
|
include Urbanairship::Common
|
38
38
|
include Urbanairship::Loggable
|
39
39
|
attr_reader :client
|
40
|
-
|
40
|
+
|
41
41
|
def initialize(client: required('client'))
|
42
42
|
@client = client
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def uninstall(address: required('address'),
|
46
46
|
open_platform: required('open_platform'))
|
47
|
-
|
47
|
+
|
48
48
|
body = {
|
49
49
|
address: address,
|
50
50
|
open_platform_name: open_platform
|
51
51
|
}
|
52
|
-
|
52
|
+
|
53
53
|
response = @client.send_request(
|
54
54
|
method: 'POST',
|
55
55
|
body: JSON.dump(body),
|
56
|
-
url:
|
56
|
+
url: open_channel_url('uninstall/'),
|
57
57
|
content_type: 'application/json'
|
58
58
|
)
|
59
|
-
|
60
|
-
logger.info { "Successfully
|
59
|
+
|
60
|
+
logger.info { "Successfully uninstalled open channel with address: #{address}"}
|
61
61
|
response
|
62
62
|
end
|
63
63
|
end
|
@@ -44,7 +44,7 @@ module Urbanairship
|
|
44
44
|
campaign_object = {'categories': campaigns}
|
45
45
|
full_payload[:campaigns] = campaign_object
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
full_payload
|
49
49
|
end
|
50
50
|
|
@@ -52,7 +52,7 @@ module Urbanairship
|
|
52
52
|
response = @client.send_request(
|
53
53
|
method: 'POST',
|
54
54
|
body: JSON.dump(payload),
|
55
|
-
url:
|
55
|
+
url: create_and_send_url,
|
56
56
|
content_type: 'application/json'
|
57
57
|
)
|
58
58
|
logger.info("Running create and send for addresses #{@addresses}")
|
@@ -63,7 +63,7 @@ module Urbanairship
|
|
63
63
|
response = @client.send_request(
|
64
64
|
method: 'POST',
|
65
65
|
body: JSON.dump(payload),
|
66
|
-
url:
|
66
|
+
url: create_and_send_url('validate'),
|
67
67
|
content_type: 'application/json'
|
68
68
|
)
|
69
69
|
logger.info("Validating payload for create and send")
|
@@ -84,7 +84,7 @@ module Urbanairship
|
|
84
84
|
response = @client.send_request(
|
85
85
|
method: 'POST',
|
86
86
|
body: JSON.dump(scheduled_payload),
|
87
|
-
url:
|
87
|
+
url: schedules_url('create-and-send'),
|
88
88
|
content_type: 'application/json'
|
89
89
|
)
|
90
90
|
logger.info("Scheduling create and send operation with name #{@name}")
|