urbanairship 2.4.1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fcee0f1f419c973ed8f480899359df8205ef23f6
4
+ data.tar.gz: 70e3a0e2e5f3527d25e02afb522b65dd2dcf4e16
5
+ SHA512:
6
+ metadata.gz: 7dd348a203f1f9cfaf1a4e796a4c44b8b303180a91b1e0a43fa00ca6daa6f746c97cbca7ed063bb1ce35e625b2022d4d5427321dec3282ad502d9f19d9855f7f
7
+ data.tar.gz: d64ec3eafef734228058582157ad9abbb13e425bbfc10cfdd05b724ab64d565e3a22c5777fd53e2cefea0d289d50d6afe471eb63617ea6180ed0da995e2b609c
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # App
12
+ urbanairship.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -f d
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2.1
5
+ - 2.2.2
6
+ script: bundle exec rspec
data/CHANGELOG ADDED
@@ -0,0 +1,13 @@
1
+ --------------------
2
+ 3.0.1
3
+ --------------------
4
+ - Updating Gemspec to show required Ruby Version correctly
5
+
6
+
7
+
8
+ --------------------
9
+ 3.0.0
10
+ --------------------
11
+ - added CHANGELOG
12
+ - rewrite with v3 support for push and scheduled push
13
+ - backwards incompatible with previous versions of library
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ require 'guard/rspec/dsl'
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ # RSpec files
6
+ rspec = dsl.rspec
7
+ watch(rspec.spec_helper) { rspec.spec_dir }
8
+ watch(rspec.spec_support) { rspec.spec_dir }
9
+ watch(rspec.spec_files)
10
+
11
+ # Ruby files
12
+ ruby = dsl.ruby
13
+ dsl.watch_spec_files_for(ruby.lib_files)
14
+ end
data/LICENSE CHANGED
@@ -1,29 +1,13 @@
1
- Copyright (c) 2012, Groupon, Inc.
2
- All rights reserved.
1
+ Copyright 2015 Urban Airship
3
2
 
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions
6
- are met:
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
7
6
 
8
- Redistributions of source code must retain the above copyright notice,
9
- this list of conditions and the following disclaimer.
7
+ http://www.apache.org/licenses/LICENSE-2.0
10
8
 
11
- Redistributions in binary form must reproduce the above copyright
12
- notice, this list of conditions and the following disclaimer in the
13
- documentation and/or other materials provided with the distribution.
14
-
15
- Neither the name of GROUPON nor the names of its contributors may be
16
- used to endorse or promote products derived from this software without
17
- specific prior written permission.
18
-
19
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ [![Build Status](https://travis-ci.org/urbanairship/ruby-library.svg?branch=master)](https://travis-ci.org/urbanairship/ruby-library)
2
+
3
+ # Urbanairship
4
+
5
+ `urbanairship` is a Ruby library for using the [Urban Airship](www.urbanairship.com) web service API for push notifications and rich app pages.
6
+
7
+ ## Requirements
8
+ As of Version 3.0, a Ruby version >= 2.0 must be used.
9
+
10
+ ## Functionality
11
+
12
+ ####BETA Release
13
+ Version 3.0 is a major upgrade and backwards incompatible with earlier versions. This BETA release focuses on support for the new version 3 push API. There is also a major reorganization of the codebase.
14
+
15
+ Note: the BETA release only supports UA's ```/push/``` and ```/schedules/``` endpoints. Expanded support for UA's other endpoints will be in the forthcoming release.
16
+
17
+ ####Forthcoming Release
18
+ To encourage the use of our SDK, which takes care of proper channel registration, support for device token registration will be removed. Support for v1 endpoints will also be removed and transitioned to their v3 equivalents where possible.
19
+
20
+ ## Installation
21
+
22
+ If you have the ```bundler``` gem (if not you can get it with ```$ gem install bundler```) add this line to your application's Gemfile:
23
+
24
+ ```ruby
25
+ gem 'urbanairship'
26
+ ```
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ OR install it yourself as:
33
+
34
+ $ gem install urbanairship
35
+
36
+ ## Usage
37
+
38
+ Once the gem has been installed you can start sending pushes! See http://docs.urbanairship.com/topic-guides/api-examples.html for more examples.
39
+
40
+ ####Broadcast to All Devices
41
+ ```ruby
42
+ require 'urbanairship'
43
+ UA = Urbanairship
44
+ airship = UA::Client.new(key:'application_key', secret:'master_secret')
45
+ p = airship.create_push
46
+ p.audience = UA.all
47
+ p.notification = UA.notification(alert: 'Hello')
48
+ p.device_types = UA.all
49
+ p.send_push
50
+ ```
51
+
52
+ ####Simple Tag Push
53
+ ```ruby
54
+ require 'urbanairship'
55
+ UA = Urbanairship
56
+ airship = UA::Client.new(key:'application_key', secret:'master_secret')
57
+ p = airship.create_push
58
+ p.audience = UA.tag('some_tag')
59
+ p.notification = UA.notification(alert: 'Hello')
60
+ p.device_types = UA.all
61
+ p.send_push
62
+ ```
63
+
64
+ ## Questions
65
+ The best place to ask questions is our support site: http://support.urbanairship.com/
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it ( https://github.com/urbanairship/ruby-library )
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create a new Pull Request
74
+ 6. Sign Urban Airship's [contribution agreement](http://urbanairship.com/legal/contribution-agreement)
75
+ Note: Changes will not be approved and merged without a signed contribution agreement
76
+
77
+ ## Development
78
+
79
+ After checking out the repo, ensure you have ```bundler``` installed (```$ gem install bundler```) run
80
+
81
+ $ bin/setup
82
+
83
+ to install dependencies.
84
+ Then, run
85
+
86
+ $ bin/console
87
+
88
+ for an interactive prompt that will allow you to experiment.
89
+
90
+ OR you can build a local gem to play with:
91
+
92
+ $ gem build urbanairship.gemspec
93
+ $ gem install ./urbanairship-<VERSION>.gem
94
+
95
+ Having a local build will give you better logging if you are running into issues, but be careful to make sure to use our released
96
+ public gem in Production.
data/Rakefile CHANGED
@@ -1,8 +1,7 @@
1
- desc 'Run all the tests'
2
- task :default => :spec
3
-
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new do |t|
6
- t.rspec_opts = ['-c', '-f progress', '-r ./spec/spec_helper.rb']
7
- t.pattern = 'spec/**/*_spec.rb'
1
+ require 'bundler/gem_tasks'
2
+ begin
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
6
+ rescue LoadError
8
7
  end
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'urbanairship'
5
+
6
+ require 'irb'
7
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
data/lib/ext/hash.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def compact
3
+ keep_if { |_, value| !value.nil? }
4
+ end
5
+ end
data/lib/ext/object.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Object
2
+ def try(method)
3
+ send method if respond_to? method
4
+ end
5
+ end
data/lib/urbanairship.rb CHANGED
@@ -1,213 +1,20 @@
1
- require 'json'
2
- require 'net/https'
3
- require 'time'
4
-
5
- require File.join(File.dirname(__FILE__), 'urbanairship/response')
1
+ require 'urbanairship/push/audience'
2
+ require 'urbanairship/push/payload'
3
+ require 'urbanairship/push/schedule'
4
+ require 'urbanairship/push/push'
5
+ require 'urbanairship/client'
6
+ require 'urbanairship/common'
7
+ require 'urbanairship/loggable'
8
+ require 'urbanairship/util'
9
+ require 'urbanairship/version'
6
10
 
7
11
  module Urbanairship
8
- begin
9
- require 'system_timer'
10
- Timer = SystemTimer
11
- rescue LoadError
12
- require 'timeout'
13
- Timer = Timeout
14
- end
15
-
16
- module ClassMethods
17
- attr_accessor :application_key, :application_secret, :master_secret, :logger, :request_timeout, :provider
18
-
19
- def register_device(device_token, options = {})
20
- body = parse_register_options(options).to_json
21
-
22
- if ( (options[:provider] || @provider) == :android ) || ( (options[:provider] || @provider) == 'android' )
23
- do_request(:put, "/api/apids/#{device_token}", :body => body, :authenticate_with => :application_secret)
24
- else
25
- do_request(:put, "/api/device_tokens/#{device_token}", :body => body, :authenticate_with => :application_secret)
26
- end
27
- end
28
-
29
- def unregister_device(device_token, options = {})
30
- if ( (options[:provider] || @provider) == :android ) || ( (options[:provider] || @provider) == 'android' )
31
- do_request(:delete, "/api/apids/#{device_token}", :authenticate_with => :application_secret)
32
- else
33
- do_request(:delete, "/api/device_tokens/#{device_token}", :authenticate_with => :application_secret)
34
- end
35
- end
36
-
37
- def device_info(device_token, options = {})
38
- if ( (options[:provider] || @provider) == :android ) || ( (options[:provider] || @provider) == 'android' )
39
- do_request(:get, "/api/apids/#{device_token}", :authenticate_with => :application_secret)
40
- else
41
- do_request(:get, "/api/device_tokens/#{device_token}", :authenticate_with => :application_secret)
42
- end
43
- end
44
-
45
- def delete_scheduled_push(param)
46
- warn "[DEPRECATED] http://docs.urbanairship.com/reference/api/v3/api-v3-migration-guide.html#api-push-batch"
47
- path = param.is_a?(Hash) ? "/api/push/scheduled/alias/#{param[:alias].to_s}" : "/api/push/scheduled/#{param.to_s}"
48
- do_request(:delete, path, :authenticate_with => :master_secret)
49
- end
50
-
51
- def push(options = {})
52
- body = parse_push_options(options.dup).to_json
53
- do_request(:post, "/api/push/", :body => body, :authenticate_with => :master_secret, :version => options[:version])
54
- end
55
-
56
- def push_to_segment(options = {})
57
- warn "[DEPRECATED] http://docs.urbanairship.com/reference/api/v3/api-v3-migration-guide.html#api-push-segments"
58
- body = parse_push_options(options).to_json
59
- do_request(:post, "/api/push/segments", :body => body, :authenticate_with => :master_secret)
60
- end
61
-
62
- def batch_push(notifications = [])
63
- warn "[DEPRECATION] http://docs.urbanairship.com/reference/api/v3/api-v3-migration-guide.html#api-push-batch"
64
- body = notifications.map{|notification| parse_push_options(notification)}.to_json
65
- do_request(:post, "/api/push/batch/", :body => body, :authenticate_with => :master_secret)
66
- end
67
-
68
- def broadcast_push(options = {})
69
- warn "[DEPRECATED] http://docs.urbanairship.com/reference/api/v3/api-v3-migration-guide.html#api-push-broadcast"
70
- body = parse_push_options(options).to_json
71
- do_request(:post, "/api/push/broadcast/", :body => body, :authenticate_with => :master_secret)
72
- end
73
-
74
- def feedback(time)
75
- do_request(:get, "/api/device_tokens/feedback/?since=#{format_time(time)}", :authenticate_with => :master_secret)
76
- end
77
-
78
- def tags
79
- do_request(:get, "/api/tags/", :authenticate_with => :master_secret)
80
- end
81
-
82
- def add_tag(tag)
83
- do_request(:put, "/api/tags/#{tag}", :authenticate_with => :master_secret, :content_type => 'text/plain')
84
- end
85
-
86
- def remove_tag(tag)
87
- do_request(:delete, "/api/tags/#{tag}", :authenticate_with => :master_secret)
88
- end
89
-
90
- def tags_for_device(device_token)
91
- do_request(:get, "/api/device_tokens/#{device_token}/tags/", :authenticate_with => :master_secret)
92
- end
93
-
94
- def tag_device(params)
95
- provider_field = ( (params[:provider] || @provider) == :android ) || ( (params[:provider] || @provider) == 'android' ) ? :apids : :device_tokens
96
- do_request(:post, "/api/tags/#{params[:tag]}", :body => {provider_field => {:add => [params[:device_token]]}}.to_json, :authenticate_with => :master_secret)
97
- end
98
-
99
- def untag_device(params)
100
- provider_field = ( (params[:provider] || @provider) == :android ) || ( (params[:provider] || @provider) == 'android' ) ? :apids : :device_tokens
101
- do_request(:post, "/api/tags/#{params[:tag]}", :body => {provider_field => {:remove => [params[:device_token]]}}.to_json, :authenticate_with => :master_secret)
102
- end
103
-
104
- def device_tokens
105
- do_request(:get, "/api/device_tokens/", :authenticate_with => :master_secret)
106
- end
107
-
108
- def device_tokens_count
109
- do_request(:get, "/api/device_tokens/count/", :authenticate_with => :master_secret)
110
- end
111
-
112
- def segments
113
- do_request(:get, "/api/segments", :authenticate_with => :master_secret)
114
- end
115
-
116
- def create_segment(segment)
117
- do_request(:post, "/api/segments", :body => segment.to_json, :authenticate_with => :master_secret)
118
- end
119
-
120
- def segment(id)
121
- do_request(:get, "/api/segments/#{id}", :authenticate_with => :master_secret)
122
- end
123
-
124
- def update_segment(id, segment)
125
- do_request(:put, "/api/segments/#{id}", :body => segment.to_json, :authenticate_with => :master_secret)
126
- end
127
-
128
- def delete_segment(id)
129
- do_request(:delete, "/api/segments/#{id}", :authenticate_with => :master_secret)
130
- end
131
-
132
- private
133
-
134
- def do_request(http_method, path, options = {})
135
- verify_configuration_values(:application_key, options[:authenticate_with])
136
-
137
- klass = Net::HTTP.const_get(http_method.to_s.capitalize)
138
-
139
- request = klass.new(path)
140
- request.basic_auth @application_key, instance_variable_get("@#{options[:authenticate_with]}")
141
- request.add_field "Content-Type", options[:content_type] || "application/json"
142
- request.body = options[:body] if options[:body]
143
- request["Accept"] = "application/vnd.urbanairship+json; version=#{options[:version]};" if options[:version]
144
-
145
- Timer.timeout(request_timeout) do
146
- start_time = Time.now
147
- response = http_client.request(request)
148
- log_request_and_response(request, response, Time.now - start_time)
149
- Urbanairship::Response.wrap(response)
150
- end
151
- rescue Timeout::Error
152
- unless logger.nil?
153
- logger.error "Urbanairship request timed out after #{request_timeout} seconds: [#{http_method} #{request.path} #{request.body}]"
154
- end
155
- Urbanairship::Response.wrap(nil, :body => {'error' => 'Request timeout'}, :code => '503')
156
- end
157
-
158
- def verify_configuration_values(*symbols)
159
- absent_values = symbols.select{|symbol| instance_variable_get("@#{symbol}").nil? }
160
- raise("Must configure #{absent_values.join(", ")} before making this request.") unless absent_values.empty?
161
- end
162
-
163
- def http_client
164
- Net::HTTP.new("go.urbanairship.com", 443).tap{|http| http.use_ssl = true}
165
- end
166
-
167
- def parse_register_options(hash = {})
168
- hash[:alias] = hash[:alias].to_s unless hash[:alias].nil?
169
- hash
170
- end
171
-
172
- def parse_push_options(hash = {})
173
- hash[:aliases] = hash[:aliases].map{|a| a.to_s} unless hash[:aliases].nil?
174
- hash[:schedule_for] = hash[:schedule_for].map{|elem| process_scheduled_elem(elem)} unless hash[:schedule_for].nil?
175
- hash.delete(:version)
176
- hash
177
- end
178
-
179
- def log_request_and_response(request, response, time)
180
- return if logger.nil?
181
-
182
- time = (time * 1000).to_i
183
- http_method = request.class.to_s.split('::')[-1]
184
- logger.info "Urbanairship (#{time}ms): [#{http_method} #{request.path}, #{request.body}], [#{response.code}, #{response.body}]"
185
- logger.flush if logger.respond_to?(:flush)
186
- end
187
-
188
- def format_time(time)
189
- time = Time.parse(time) if time.is_a?(String)
190
- time.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
191
- end
192
-
193
- def process_scheduled_elem(elem)
194
- if elem.class == Hash
195
- elem.merge!(:scheduled_time => format_time(elem[:scheduled_time]))
196
- else
197
- format_time(elem)
198
- end
199
- end
200
-
201
- def request_timeout
202
- @request_timeout || 5.0
203
- end
204
- end
205
-
206
- class << self
207
- include ClassMethods
208
- end
12
+ # Make these functions available in the
13
+ # `Urbanairship` namespace, as in the Python
14
+ # library.
15
+ extend Urbanairship::Push::Audience
16
+ extend Urbanairship::Push::Payload
17
+ extend Urbanairship::Push::Schedule
18
+ extend Urbanairship::Push
209
19
 
210
- class Client
211
- include ClassMethods
212
- end
213
20
  end