pushio 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -17,4 +17,5 @@ test/version_tmp
17
17
  tmp
18
18
  .DS_Store
19
19
  /.idea/
20
- /.rvmrc
20
+ /.rvmrc
21
+ /spec/pushio_config.yml
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Push IO LLC
1
+ Copyright (c) 2013 Push IO Inc.
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,26 +1,36 @@
1
1
  # PushIoClient
2
2
 
3
- An easy to use client for integrating push notifications into Ruby-based applications. This gem uses the Push IO API to trigger notification delivery to whatever audience you specify. In order to get full use of this gem you will need to have an active account on https://manage.push.io and have recipient devices registered to receive notifications. Learn more at http://push.io
3
+ An easy to use client for integrating push notifications into Ruby-based applications.
4
+ This gem uses the Push IO API to trigger notification delivery to whatever audience you specify.
5
+ In order to get full use of this gem you will need to have an active account on
6
+ https://manage.push.io and have recipient devices registered to receive notifications.
7
+ Learn more at http://push.io
4
8
 
5
9
  ## Installation
6
10
 
7
11
  Add this line to your application's Gemfile:
8
-
12
+ ```
9
13
  gem 'pushio'
14
+ ```
10
15
 
11
16
  And then execute:
12
17
 
18
+ ```
13
19
  $ bundle
20
+ ```
14
21
 
15
22
  Or install it yourself as:
16
23
 
24
+ ```
17
25
  $ gem install pushio
26
+ ```
27
+
18
28
 
19
29
  ## Usage
20
30
 
21
31
  Configure the client:
22
32
 
23
- ```
33
+ ```ruby
24
34
  PushIo::Client.configure do |config|
25
35
  config.app_guid = [your app guid from https://manage.push.io]
26
36
  config.sender_secret = [for your app on https://manage.push.io]
@@ -28,14 +38,28 @@ end
28
38
  ```
29
39
 
30
40
  Send a broadcast push to everyone registered for your app:
31
- ```
32
- push_client = PushIo::Client.new
33
- notification_id = push_client.broadcast :message => "Hello everyone!"
41
+ ```ruby
42
+ notification_id = PushIo::Client.deliver_broadcast :payload => {:message => "Broadcast Test"}
34
43
  ```
35
44
 
36
45
  Send a push to an audience:
46
+ ```ruby
47
+ notification_id = PushIo::Client.deliver_to_audience "friends", :payload => {:message => "Howdy Friends", :payload_apns => {:badge => 8}}
48
+ ```
49
+
50
+ Send a push to a targeted query:
51
+ ```ruby
52
+ notification_id = PushIo::Client.deliver_to_query "Alpha or Bravo", :payload => {:message => "Query Test"}
37
53
  ```
38
- push_client.deliver_to_audience "friends", :message => "Howdy friends", :count => 8
54
+
55
+ Send a push to a known device ID:
56
+ ```ruby
57
+ notification_id = PushIo::Client.deliver_to_ids "APIKEY1234_a123", ['B3606524-AE35-458A-9FE9-7B6FE8D99CE4'], :payload => {:message => "Hello Push IO"}
58
+ ```
59
+
60
+ Send a push to a known device Token:
61
+ ```ruby
62
+ notification_id = PushIo::Client.deliver_to_tokens "APIKEY1234_a123", ['abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd'], :payload => {:message => "Hello Push IO"}
39
63
  ```
40
64
 
41
65
 
@@ -1,6 +1,7 @@
1
1
  module PushIo
2
2
  require 'multi_json'
3
3
  require 'httpclient'
4
+ require 'push_io/utils'
4
5
  require 'push_io/version'
5
6
  require 'push_io/errors'
6
7
  require 'push_io/configuration'
@@ -1,8 +1,11 @@
1
1
  module PushIo
2
2
  class Client
3
3
  attr_reader :config
4
+ attr_accessor :httpclient
5
+
4
6
  def initialize(attributes = {})
5
7
  @config = PushIo::Client.config.dup
8
+ self.httpclient = HTTPClient.new
6
9
  attributes.each do |name, value|
7
10
  @config.send("#{name}=", value) if @config.respond_to?("#{name}=")
8
11
  end
@@ -23,23 +26,113 @@ module PushIo
23
26
  end
24
27
  end
25
28
 
26
- def broadcast(*payload)
27
- send_post(payload, {:audience => "broadcast"})
29
+ def deliver(*args)
30
+ opts = args.extract_options!
31
+ send_post(opts) if ready_to_deliver?(opts)
32
+ end
33
+
34
+ def deliver_broadcast(*args)
35
+ opts = args.extract_options!
36
+ opts.delete(:audience) if opts[:audience]
37
+ opts.delete(:tag_query) if opts[:tag_query]
38
+ opts[:audience] = 'broadcast'
39
+ send_post(opts) if ready_to_deliver?(opts)
40
+ end
41
+
42
+ def deliver_to_audience(audience, *args)
43
+ opts = args.extract_options!
44
+ opts.delete(:tag_query) if opts[:tag_query]
45
+ opts[:audience] = audience
46
+ raise PushIo::MissingOptionsError, "An audience was not specified" unless opts[:audience]
47
+ send_post(opts) if ready_to_deliver?(opts)
48
+ end
49
+
50
+ def deliver_to_query(query, *args)
51
+ opts = args.extract_options!
52
+ opts.delete(:audience) if opts[:audience]
53
+ opts[:tag_query] = query
54
+ raise PushIo::MissingOptionsError, "A query was not specified" unless opts[:tag_query]
55
+ send_post(opts) if ready_to_deliver?(opts)
28
56
  end
29
57
 
30
- def deliver_to_audience(audience, *payload)
31
- send_post(payload, {:audience => audience})
58
+ def deliver_to_ids(api_key, device_id_array, *args)
59
+ opts = args.extract_options!
60
+ opts.delete(:audience) if opts[:audience]
61
+ opts.delete(:tag_query) if opts[:tag_query]
62
+ raise PushIo::MissingOptionsError, "A valid API Key was not specified" unless api_key =~ PushIo::API_KEY_REGEX
63
+ raise PushIo::MissingOptionsError, "Device IDs need to be specified in an array" unless device_id_array.is_a? Array
64
+ opts[:recipient_ids] = {api_key => device_id_array}
65
+ send_devices_post(opts) if ready_to_deliver_to_devices?(opts)
32
66
  end
33
67
 
68
+ def deliver_to_tokens(api_key, device_token_array, *args)
69
+ opts = args.extract_options!
70
+ opts.delete(:audience) if opts[:audience]
71
+ opts.delete(:tag_query) if opts[:tag_query]
72
+ raise PushIo::MissingOptionsError, "A valid API Key was not specified" unless api_key =~ PushIo::API_KEY_REGEX
73
+ raise PushIo::MissingOptionsError, "Device tokens need to be specified in an array" unless device_token_array.is_a? Array
74
+ opts[:recipient_tokens] = {api_key => device_token_array}
75
+ send_devices_post(opts) if ready_to_deliver_to_devices?(opts)
76
+ end
77
+
78
+
34
79
  private
80
+
81
+ def ready_to_deliver?(opts)
82
+ if (opts.keys & [:tag_query, :audience]).empty?
83
+ raise PushIo::MissingOptionsError, "No tag_query or audience was specified"
84
+ end
85
+ if (opts.keys & [:tag_query, :audience]).length == 2
86
+ raise PushIo::MissingOptionsError, "Please specify tag_query or audience but not both"
87
+ end
88
+ raise PushIo::MissingOptionsError, "Please specify a payload" unless opts[:payload]
89
+ true
90
+ end
91
+
35
92
  def send_url
36
93
  "#{@config.endpoint_url}#{PushIo::NOTIFY_APP_PATH}#{@config.app_guid}/#{@config.sender_secret}"
37
94
  end
38
- def send_post(payload, args)
39
- response = HTTPClient.new.post(send_url, {:body => build_post(args, payload)})
95
+
96
+ def send_post(opts)
97
+ response = self.httpclient.post(send_url, {:body => build_post(opts)})
98
+ parse_response(response)
99
+ end
100
+
101
+ def build_post(opts)
102
+ opts[:payload] = MultiJson.dump(opts[:payload])
103
+ opts[:recipient_ids] = MultiJson.dump(opts[:recipient_ids]) if opts[:recipient_ids]
104
+ opts[:recipient_tokens] = MultiJson.dump(opts[:recipient_tokens]) if opts[:recipient_tokens]
105
+ opts
106
+ end
107
+
108
+ def parse_response(response)
109
+ if response.code == 201
110
+ response_hash = MultiJson.load(response.body)
111
+ return response_hash['notification_guid']
112
+ end
113
+ raise PushIo::DeliveryError, response.body
40
114
  end
41
- def build_post(args, payload)
42
- args.merge({:payload => MultiJson.dump(payload)})
115
+
116
+
117
+ def send_devices_url
118
+ "#{@config.endpoint_url}#{PushIo::NOTIFY_DEVICES_PATH}#{@config.app_guid}/#{@config.sender_secret}"
43
119
  end
120
+
121
+ def send_devices_post(opts)
122
+ response = self.httpclient.post(send_devices_url, {:body => build_post(opts)})
123
+ parse_response(response)
124
+ end
125
+
126
+ def ready_to_deliver_to_devices?(opts)
127
+ if (opts.keys & [:recipient_ids, :recipient_tokens]).empty?
128
+ raise PushIo::MissingOptionsError, "No tag_query or audience was specified"
129
+ end
130
+ if (opts.keys & [:recipient_ids, :recipient_tokens]).length == 2
131
+ raise PushIo::MissingOptionsError, "Please specify recipient_ids or recipient_tokens but not both"
132
+ end
133
+ raise PushIo::MissingOptionsError, "Please specify a payload" unless opts[:payload]
134
+ true
135
+ end
136
+
44
137
  end
45
138
  end
@@ -14,4 +14,6 @@ end
14
14
  module PushIo
15
15
  ENDPOINT_URL = "https://manage.push.io"
16
16
  NOTIFY_APP_PATH = "/api/v1/notify_app/"
17
+ NOTIFY_DEVICES_PATH = "/api/v1/notify_devices/"
18
+ API_KEY_REGEX = /\A[a-zA-Z0-9]{10}_[a-zA-Z0-9]{4}\Z/
17
19
  end
@@ -1,4 +1,8 @@
1
1
  module PushIo
2
2
  class UnconfiguredClientError < StandardError
3
3
  end
4
+ class MissingOptionsError < StandardError
5
+ end
6
+ class DeliveryError < StandardError
7
+ end
4
8
  end
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def extract_options!
3
+ last.is_a?(::Hash) ? pop : {}
4
+ end unless defined? Array.new.extract_options!
5
+ end
@@ -1,3 +1,3 @@
1
1
  module PushIo
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -2,7 +2,7 @@
2
2
  require File.expand_path('../lib/push_io/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Push IO LLC", "Sean McKibben"]
5
+ gem.authors = ["Push IO Inc.", "Sean McKibben"]
6
6
  gem.email = ["sean@push.io"]
7
7
  gem.description = %q{Ruby client library to send push notifications via the Push IO API. See: http://push.io for more information and to set up your account.}
8
8
  gem.summary = %q{This gem enables developers to easily create new notifications and send them via the Push IO API from Ruby apps.}
@@ -4,21 +4,34 @@ require 'push_io'
4
4
  describe PushIo do
5
5
  context "unconfigured" do
6
6
  it "should tell you how to configure" do
7
- expect{PushIo::Client.new}.to raise_error(PushIo::UnconfiguredClientError)
7
+ expect { PushIo::Client.new }.to raise_error(PushIo::UnconfiguredClientError)
8
8
 
9
9
  end
10
10
  end
11
11
  context "configured" do
12
+ test_keys_path = File.expand_path("../pushio_config.yml", __FILE__)
13
+ test_keys = {}
14
+ if File.exists? test_keys_path
15
+ test_keys = YAML.load_file(test_keys_path)
16
+ end
17
+ let(:endpoint_url) { test_keys[:endpoint_url] || "https://manage.push.io" }
18
+ let(:app_guid) { test_keys[:app_guid] || "abcdefghij" }
19
+ let(:api_key) { test_keys[:api_key] || "abcdefghij_apns" }
20
+ let(:sender_secret) { test_keys[:sender_secret] || "m42PGzAqQAdEcY1w2fpN" }
21
+ let(:device_id) { test_keys[:device_id] || "B3606524-AE35-458A-9FE9-7B6FE8D99CE4" }
22
+ let(:device_token) { test_keys[:device_token] || "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd" }
12
23
  before :each do
13
24
  PushIo::Client.configure do |config|
14
- config.app_guid = "1234"
15
- config.sender_secret = "5678"
25
+ config.endpoint_url = endpoint_url
26
+ config.app_guid = app_guid
27
+ config.sender_secret = sender_secret
16
28
  end
17
29
  end
18
30
  it "should allow configuration" do
19
31
  client = PushIo::Client.new
20
- client.config.app_guid.should == "1234"
21
- client.config.sender_secret.should == "5678"
32
+ client.config.app_guid.should == app_guid
33
+ client.config.sender_secret.should == sender_secret
34
+ client.config.endpoint_url.should == endpoint_url
22
35
  end
23
36
  it "should allow configuration override" do
24
37
  client = PushIo::Client.new(:app_guid => "aaaa", :sender_secret => "qqqq")
@@ -27,11 +40,59 @@ describe PushIo do
27
40
  end
28
41
  it "makes a send url" do
29
42
  client = PushIo::Client.new
30
- client.send(:send_url).should == "https://manage.push.io/api/v1/notify_app/1234/5678"
31
- client = PushIo::Client.new(:app_guid => "aaaa", :sender_secret => "qqqq")
32
- client.send(:send_url).should == "https://manage.push.io/api/v1/notify_app/aaaa/qqqq"
33
- client = PushIo::Client.new(:endpoint_url => "http://somewhere.else.entirely.org")
34
- client.send(:send_url).should == "http://somewhere.else.entirely.org/api/v1/notify_app/1234/5678"
43
+ client.send(:send_url).should == "#{endpoint_url}/api/v1/notify_app/#{app_guid}/#{sender_secret}"
44
+ client = PushIo::Client.new(:endpoint_url => "http://localhost:3000", :app_guid => "aaaa", :sender_secret => "qqqq")
45
+ client.send(:send_url).should == "http://localhost:3000/api/v1/notify_app/aaaa/qqqq"
46
+ end
47
+
48
+ it "sends inlined" do
49
+ notification_id = PushIo::Client.new.deliver_broadcast :payload => {:message => "Inlined Test"}
50
+ notification_id.should_not be_nil
51
+ notification_id.should start_with app_guid
52
+ end
53
+ it "sends a generic push" do
54
+ client = PushIo::Client.new
55
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
56
+ notification_id = client.deliver :payload => {:message => "Generic Test"}, :tag_query => "Alpha or Bravo"
57
+ notification_id.should_not be_nil
58
+ notification_id.should start_with app_guid
59
+ end
60
+ it "sends a broadcast" do
61
+ client = PushIo::Client.new
62
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
63
+ notification_id = client.deliver_broadcast :payload => {:message => "Broadcast Test"}
64
+ notification_id.should_not be_nil
65
+ notification_id.should start_with app_guid
66
+ end
67
+ it "sends to an audience" do
68
+ client = PushIo::Client.new
69
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
70
+ notification_id = client.deliver_to_audience "broadcast", :payload => {:message => "Howdy Friends", :payload_apns => {:badge => 8}}
71
+ notification_id.should_not be_nil
72
+ notification_id.should start_with app_guid
73
+ end
74
+ it "sends a query push" do
75
+ client = PushIo::Client.new
76
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
77
+ notification_id = client.deliver_to_query "Alpha or Bravo", :payload => {:message => "Query Test"}
78
+ notification_id.should_not be_nil
79
+ notification_id.should start_with app_guid
80
+ end
81
+
82
+ it "sends to device ids" do
83
+ client = PushIo::Client.new
84
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
85
+ notification_id = client.deliver_to_ids api_key, [device_id], :payload => {:message => "Device ID Test"}
86
+ notification_id.should_not be_nil
87
+ notification_id.should start_with app_guid
88
+ end
89
+
90
+ it "sends to device tokens" do
91
+ client = PushIo::Client.new
92
+ client.send(:httpclient).send(:debug_dev=, STDOUT)
93
+ notification_id = client.deliver_to_tokens api_key, [device_token], :payload => {:message => "Device Token Test"}
94
+ notification_id.should_not be_nil
95
+ notification_id.should start_with app_guid
35
96
  end
36
97
  end
37
98
 
@@ -0,0 +1,2 @@
1
+ :app_guid: ABCDEFGHIJ
2
+ :sender_secret: xxxxxxxxxxxxxxxxxxxxx
metadata CHANGED
@@ -1,20 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - Push IO LLC
8
+ - Push IO Inc.
9
9
  - Sean McKibben
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-09-19 00:00:00.000000000 Z
13
+ date: 2013-07-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httpclient
17
- requirement: &70259231551220 !ruby/object:Gem::Requirement
17
+ requirement: &70111734375140 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 2.2.7
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70259231551220
25
+ version_requirements: *70111734375140
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: multi_json
28
- requirement: &70259231550500 !ruby/object:Gem::Requirement
28
+ requirement: &70111734374220 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.3.0
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70259231550500
36
+ version_requirements: *70111734374220
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rspec
39
- requirement: &70259231549820 !ruby/object:Gem::Requirement
39
+ requirement: &70111734373300 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: 2.11.0
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70259231549820
47
+ version_requirements: *70111734373300
48
48
  description: ! 'Ruby client library to send push notifications via the Push IO API.
49
49
  See: http://push.io for more information and to set up your account.'
50
50
  email:
@@ -62,9 +62,11 @@ files:
62
62
  - lib/push_io/client.rb
63
63
  - lib/push_io/configuration.rb
64
64
  - lib/push_io/errors.rb
65
+ - lib/push_io/utils.rb
65
66
  - lib/push_io/version.rb
66
67
  - pushio.gemspec
67
68
  - spec/push_io_spec.rb
69
+ - spec/pushio_config.example.yml
68
70
  homepage: ''
69
71
  licenses: []
70
72
  post_install_message:
@@ -92,3 +94,4 @@ summary: This gem enables developers to easily create new notifications and send
92
94
  via the Push IO API from Ruby apps.
93
95
  test_files:
94
96
  - spec/push_io_spec.rb
97
+ - spec/pushio_config.example.yml