adck 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in simple.gemspec
4
+ gemspec
5
+
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ adck (0.1.0)
5
+ multi_json
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.3)
11
+ multi_json (1.3.6)
12
+ rspec (2.8.0)
13
+ rspec-core (~> 2.8.0)
14
+ rspec-expectations (~> 2.8.0)
15
+ rspec-mocks (~> 2.8.0)
16
+ rspec-core (2.8.0)
17
+ rspec-expectations (2.8.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.8.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ adck!
26
+ rspec (~> 2.8.0)
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tal Atlas
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # ADCK
2
+
3
+ a gem for the Apple Push Notification Service (APNS).
4
+
5
+ Based on the [APNS](https://github.com/jpoz/apns) gem by [James Pozdena](https://github.com/jpoz) \<<jpoz@jpoz.net>>
6
+
7
+ ## Install
8
+
9
+ gem install adck
10
+
11
+ or in your Gemfile:
12
+
13
+ gem 'adck'
14
+
15
+ ## Setup
16
+
17
+ You need to have your certificate in the form aof a .pem. If you have yours as a p12 you can run this to convert it:
18
+
19
+ openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
20
+
21
+ ### Defaults
22
+
23
+ You can set the defaults for all connections created by setting them on the `ADCK` object.
24
+
25
+ ADCK.host = 'gateway.push.apple.com'
26
+ ADCK.pem = '/path/to/pem/file'
27
+ ADCK.port = 2195 # default, doesn't need to be set
28
+
29
+ ## Examples
30
+
31
+ ### Quick send one notification
32
+
33
+ device_token = '123abc456def'
34
+
35
+ ADCK(device_token, 'POPUP!')
36
+
37
+ is equivalent to
38
+
39
+ ADCK.send_notification(device_token, 'POPUP!')
40
+
41
+ also the same
42
+
43
+ ADCK.send_notification(device_token, body: 'POPUP!')
44
+
45
+ All of these quick sendings use the default server values and open and close the connection for each notification.
46
+
47
+ ### Multiple notifications
48
+
49
+ Behind the scenes on the single notifications it creates a notification object
50
+
51
+ n1 = ADCK::Notification.new(device_token, 'POPUP!)
52
+
53
+ `Notification` is a combination of a `Message` and a device token.
54
+
55
+ The `Message` creates the payload which is sent to the iPhone.
56
+
57
+ To send many messages quickly
58
+
59
+ n2 = ADCK::Notification.new(device_token, 'POPUP2!)
60
+
61
+ ADCK.send_notifications([n1,n2])
62
+
63
+ or you can
64
+
65
+ ADCK([n1,n2])
66
+
67
+ #### Message
68
+
69
+ A message is just the payload seperated withouat an identifier to send it to the phone. It can take all the options that Apple supports:
70
+
71
+ * `alert` - The actual message being sent
72
+ * `badge` - The number to set the badge count to
73
+ * `sound` - Sound to play for notification
74
+
75
+ The alert property is special and allows for other fields, in place of alert you can pass:
76
+
77
+ * `body` - the text to display
78
+ * `action_loc_key` - Localized key for what to set the action button on the notification to
79
+ * `loc_key` - localized message key, in place of the body you can pass the key from one of your localized plists
80
+ * `loc_args` - if you pass a loc_key you must pass an array to loc_args for what values to fill into the localized arry
81
+ * `launch_image` - the image to display while launching instead of the default one
82
+
83
+ For more details on how these values work plase refer to [Apple's Documentation](http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html)
84
+
85
+ #### Creating a message
86
+
87
+ Messages are passed all the way though so in the previous example where we ran `ADCK(token, 'POPUP!')` it at some point ran `Message.new(body: 'POPUP!')`.
88
+
89
+ Here are some examples of messages:
90
+
91
+ ADCK::Message.new(body: 'This is what the user sees')
92
+
93
+ Now lets add a sound and a badge count:
94
+
95
+ ADCK::Message.new(body: 'This is what the user sees', sound: 'default', badge: 5)
96
+
97
+ What if we don't want to show an action button, just want to pop up a notification with an "OK" button.
98
+
99
+ ADCK::Message.new(body: 'Something you cant do anything about', action_loc_key: nil)
100
+
101
+ #### Sending one message to many people
102
+
103
+ The most performant way to send the same message to a lot of people is to make a message and then pass it an array of tokens to send to.
104
+
105
+ m = ADCK::Message.new(body: 'Cute Kitty!', action_loc_key: "PET_IT")
106
+ m.send_to([token1,token2,…,tokenN])
107
+
108
+ This will open and close a new connection to the server. If you want to use an existing connection you can set it on the message
109
+
110
+ conn = ADCK::Connection.new
111
+ m.connection = conn
112
+
113
+ conn.open
114
+ m.send_to([token1,token2,…,tokenN])
115
+ m.send_to([token1,token2,…,tokenN])
116
+ conn.close
117
+
118
+
119
+ There's one caviat, the message is compiled and frozen upon sending to improve performance. This is primarily an issue when sending badge numbers. I'm working on creating a performant way to send out large numbers of badge updates.
120
+
121
+ m = ADCK::Message.new(body: 'Cute Kitty!', action_loc_key: "PET_IT")
122
+ m.send_to([token1,token2,…,tokenN])
123
+ m.body = 'Cute Kitty2' #=> RuntimeError: can't modify frozen ADCK::Message
124
+
125
+ You can however dupe
126
+
127
+ m = m.dup
128
+ m.body = 'Cute Kitty2'
129
+ m.send_to([token1,token2,…,tokenN])
130
+
131
+ or you can tell the message to not freeze it
132
+
133
+ m = ADCK::Message.new(body: 'Cute Kitty!', action_loc_key: "PET_IT", freeze: false)
134
+ m.send_to([token1,token2,…,tokenN])
135
+ m.body = 'Cute Kitty2'
136
+ m.send_to([token1,token2,…,tokenN])
137
+
138
+ ### Connection
139
+
140
+ A good example of when you'd want to use multiple connections is if you have different `.pem` files (for different apps maybe) that you want to use.
141
+
142
+ conn_iphone = ADCK::Connection.new(pem: Rails.root+'config/pem/iphone.pem')
143
+ conn_ipad = ADCK::Connection.new(pem: Rails.root+'config/pem/ipad.pem')
144
+
145
+ n = ADCK::Notification.new(token, "Sent to both iPhone and iPad apps")
146
+ n2 = ADCK::Notification.new(token2, "Sent to iPad app")
147
+
148
+ conn_iphone.send_notification(n)
149
+ conn_ipad.send_notifications([n,n2])
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/adck.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/adck/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Tal Atlas"]
6
+ gem.email = ["me@tal.by"]
7
+ gem.description = <<-EOF
8
+ Simple Apple push notification service gem
9
+
10
+ Based on the APNS gem by James Pozdena <jpoz@jpoz.net> http://github.com/jpoz/apns
11
+ EOF
12
+ gem.summary = %q{Simple Apple push notification service gem}
13
+ gem.homepage = "https://github.com/delight-labs/ADCK"
14
+
15
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.name = "adck"
19
+ gem.require_paths = ["lib"]
20
+ gem.version = ADCK::VERSION
21
+
22
+ gem.add_dependency('multi_json')
23
+
24
+ gem.add_development_dependency("rspec", ["~> 2.8.0"])
25
+ end
@@ -0,0 +1,78 @@
1
+ module ADCK
2
+ class Connection
3
+ def initialize(opts={})
4
+ @host = opts[:host]||ADCK.host
5
+ @port = opts[:port]||ADCK.port
6
+ @pem = opts[:pem] ||ADCK.pem
7
+ @pass = opts[:pass]||ADCK.pass
8
+
9
+ raise "The path to your pem file is not set. (ADCK.pem = /path/to/cert.pem)" unless @pem
10
+ raise "The path to your pem file does not exist!" unless File.exist?(@pem)
11
+
12
+ @context = OpenSSL::SSL::SSLContext.new
13
+ @context.cert = OpenSSL::X509::Certificate.new(File.read(@pem))
14
+ @context.key = OpenSSL::PKey::RSA.new(File.read(@pem), @pass)
15
+ end
16
+
17
+ def sock
18
+ @sock ||= TCPSocket.new(@host, @port)
19
+ end
20
+
21
+ def ssl
22
+ @ssl ||= begin
23
+ ssl = OpenSSL::SSL::SSLSocket.new(sock,@context)
24
+ ssl.connect
25
+ end
26
+ end
27
+
28
+ def close
29
+ sock.close if @sock
30
+ ssl.close if @ssl
31
+ @sock = nil
32
+ @ssl = nil
33
+ end
34
+
35
+ def open
36
+ is_open = open?
37
+
38
+ _sock, _ssl = sock, ssl
39
+
40
+ yield(sock,ssl) if block_given?
41
+
42
+ if !is_open && block_given?
43
+ close
44
+ end
45
+
46
+ return _sock, _ssl
47
+ end
48
+
49
+ def open?
50
+ !!(@sock || @ssl)
51
+ end
52
+
53
+ def send_notification token, message=nil
54
+ if token.is_a?(Notification)
55
+ n = token
56
+ else
57
+ n = Notification.new(token,message)
58
+ end
59
+
60
+ send_notifications([n])
61
+ end
62
+
63
+ def send_notifications msgs
64
+ open do |sock,ssl|
65
+ msgs.each do |n|
66
+ ssl.write(n.packaged_notification)
67
+ end
68
+ end
69
+ end
70
+
71
+ class << self
72
+ def feedback(opts={})
73
+ opts[:host] ||= ADCK.host.sub('gateway','feedback')
74
+ new(opts)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,152 @@
1
+ module ADCK
2
+ class Message
3
+ ALERT_FIELDS = [
4
+ :body, :action_loc_key, :loc_key, :loc_args, :launch_image
5
+ ]
6
+ FIELDS = ALERT_FIELDS+[
7
+ :alert, :badge, :sound, :other
8
+ ]
9
+ attr_accessor *FIELDS
10
+ attr_accessor :connection
11
+
12
+ def initialize(message)
13
+ if message.is_a? Hash
14
+ @validate = message[:validate]
15
+ @freeze = message[:freeze]
16
+ end
17
+
18
+ set_values_from_arg(message)
19
+
20
+ self.other ||= {}
21
+ end
22
+
23
+ def alert
24
+ a = {}
25
+
26
+ a[:body] = body if body
27
+
28
+ if action_loc_key # is not false or nil
29
+ a[:'action-loc-key'] = action_loc_key
30
+ elsif action_loc_key == false
31
+ a[:'action-loc-key'] = nil
32
+ end
33
+
34
+ a[:'loc-key'] = loc_key unless loc_key.nil?
35
+ a[:'loc-args'] = loc_args unless loc_args.nil?
36
+ a[:'launch-image'] = launch_image unless launch_image.nil?
37
+
38
+ a
39
+ end
40
+
41
+ def alert=val
42
+ set_values_from_arg val, ALERT_FIELDS
43
+ end
44
+
45
+ def action_loc_key=val
46
+ # A nil action-loc-key is significant so set to false for later
47
+ # detection
48
+ @action_loc_key = val.nil? ? false : val
49
+ end
50
+
51
+ def aps
52
+ a = {}
53
+ _alert = alert
54
+ a[:alert] = _alert unless _alert.empty?
55
+ a[:badge] = badge if badge
56
+ a[:sound] = sound if sound
57
+ a
58
+ end
59
+
60
+ def payload(options={})
61
+ other.merge(aps: aps)
62
+ end
63
+ alias as_json payload
64
+
65
+ def validate!
66
+ return to_json if @validate == false
67
+
68
+ if loc_args && !loc_args.is_a?(Array)
69
+ raise InvalidAttribute, 'loc-args should be an array'
70
+ end
71
+
72
+ if body && !body.is_a?(String)
73
+ raise InvalidAttribute, 'body needs to be a string'
74
+ end
75
+
76
+ if action_loc_key && (action_loc_key != false || !action_loc_key.is_a?(String))
77
+ raise InvalidAttribute, 'action-loc-key needs to be set to false/nil/string'
78
+ end
79
+
80
+ if badge && !badge.is_a?(Integer)
81
+ raise InvalidAttribute, 'badge needs to be a number or nil'
82
+ end
83
+
84
+ json = to_json
85
+
86
+ if json.bytesize > 255
87
+ raise PayloadTooLarge, "Payload must be less than 256 bytes, is #{json.bytesize}bytes"
88
+ end
89
+
90
+ json
91
+ end
92
+
93
+ def bytesize
94
+ @package ? @package.bytesize : to_json.bytesize
95
+ end
96
+
97
+ def to_json(options={})
98
+ MultiJson.dump(payload(options))
99
+ end
100
+
101
+ def package
102
+ if @freeze == false
103
+ validate!
104
+ else
105
+ unless @package
106
+ @package = validate!
107
+ freeze
108
+ end
109
+ @package
110
+ end
111
+ end
112
+
113
+ def self.build(opts)
114
+ opts.is_a?(self) ? opts : new(opts)
115
+ end
116
+
117
+ def send_to(device_tokens)
118
+ conn = connection || Connection.new
119
+
120
+ notifications = Array(device_tokens).collect do |token|
121
+ Notification.new(token,self)
122
+ end
123
+
124
+ conn.send_notifications(notifications)
125
+ end
126
+
127
+ def dup
128
+ m = super()
129
+ m.instance_variable_set :@package, nil
130
+ m
131
+ end
132
+
133
+ private
134
+
135
+ def set_values_from_arg val, fields=nil
136
+ if val.is_a?(String)
137
+ self.body = val
138
+ elsif val.is_a?(Hash)
139
+ (fields || FIELDS).each do |key|
140
+ if val.has_key?(key)
141
+ send("#{key}=",val[key])
142
+ end
143
+ end
144
+ else
145
+ raise "Message needs to have either a hash or string"
146
+ end
147
+ end
148
+
149
+ class PayloadTooLarge < RuntimeError; end
150
+ class InvalidAttribute < RuntimeError; end
151
+ end
152
+ end
@@ -0,0 +1,27 @@
1
+ module ADCK
2
+ class Notification
3
+ extend Forwardable
4
+ attr_accessor :device_token, :message
5
+ def_delegators :message, :alert, :badge, :sound, :other, :as_json
6
+
7
+ def initialize(device_token, message)
8
+ self.device_token = device_token
9
+ self.message = Message.build(message)
10
+ end
11
+
12
+ def packaged_notification
13
+ pt = packaged_token
14
+ pm = message.package
15
+ [0, 0, 32, pt, 0, pm.bytesize, pm].pack("ccca*cca*")
16
+ end
17
+
18
+ def packaged_token
19
+ [device_token.gsub(/[\s|<|>]/,'')].pack('H*')
20
+ end
21
+
22
+ def packaged_message
23
+ message.package
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module ADCK
2
+ VERSION = '0.1.0'
3
+ end
data/lib/adck.rb ADDED
@@ -0,0 +1,66 @@
1
+ require 'forwardable'
2
+ require 'socket'
3
+ require 'openssl'
4
+ require 'json'
5
+ require 'adck/version'
6
+ require 'multi_json'
7
+
8
+ module ADCK
9
+
10
+ @host = 'gateway.sandbox.push.apple.com'
11
+ @port = 2195
12
+ # openssl pkcs12 -in mycert.p12 -out client-cert.pem -nodes -clcerts
13
+ @pem = nil # this should be the path of the pem file not the contentes
14
+ @pass = nil
15
+
16
+ class << self
17
+ attr_accessor :host, :pem, :port, :pass
18
+
19
+ def send_notification token, message=nil
20
+ if token.is_a?(Notification)
21
+ n = token
22
+ else
23
+ n = Notification.new(token,message)
24
+ end
25
+
26
+ send_notifications([n])
27
+ end
28
+
29
+ def send_notifications(notifications)
30
+ Connection.new.open do |sock,ssl|
31
+ notifications.each do |n|
32
+ ssl.write(n.packaged_notification)
33
+ end
34
+ end
35
+ end
36
+
37
+ def feedback
38
+ apns_feedback = []
39
+
40
+ Connection.feedback.open do |sock, ssl|
41
+ while line = sock.gets # Read lines from the socket
42
+ line.strip!
43
+ f = line.unpack('N1n1H140')
44
+ apns_feedback << [Time.at(f[0]), f[2]]
45
+ end
46
+ end
47
+
48
+ apns_feedback
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ def ADCK val, msg=nil
55
+ if val.is_a?(Array)
56
+ ADCK.send_notifications(val)
57
+ elsif val.is_a?(ADCK::Notification)
58
+ ADCK.send_notifications([val])
59
+ else
60
+ ADCK.send_notification(val,msg)
61
+ end
62
+ end
63
+
64
+ require 'adck/notification'
65
+ require 'adck/message'
66
+ require 'adck/connection'
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ADCK::Notification do
4
+
5
+ it "should take a string as the message" do
6
+ n = ADCK::Notification.new('device_token', 'Hello')
7
+ n.alert.should == 'Hello'
8
+ end
9
+
10
+ it "should take a hash as the message" do
11
+ n = ADCK::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3})
12
+ n.alert.should == "Hello iPhone"
13
+ n.badge.should == 3
14
+ end
15
+
16
+ describe '#packaged_message' do
17
+
18
+ it "should return JSON with notification information" do
19
+ n = ADCK::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3, :sound => 'awesome.caf'})
20
+ n.packaged_message.should == "{\"aps\":{\"alert\":\"Hello iPhone\",\"badge\":3,\"sound\":\"awesome.caf\"}}"
21
+ end
22
+
23
+ it "should not include keys that are empty in the JSON" do
24
+ n = ADCK::Notification.new('device_token', {:badge => 3})
25
+ n.packaged_message.should == "{\"aps\":{\"badge\":3}}"
26
+ end
27
+
28
+ end
29
+
30
+ describe '#package_token' do
31
+ it "should package the token" do
32
+ n = ADCK::Notification.new('<5b51030d d5bad758 fbad5004 bad35c31 e4e0f550 f77f20d4 f737bf8d 3d5524c6>', 'a')
33
+ Base64.encode64(n.packaged_token).should == "W1EDDdW611j7rVAEutNcMeTg9VD3fyDU9ze/jT1VJMY=\n"
34
+ end
35
+ end
36
+
37
+ describe '#packaged_notification' do
38
+ it "should package the token" do
39
+ n = ADCK::Notification.new('device_token', {:alert => 'Hello iPhone', :badge => 3, :sound => 'awesome.caf'})
40
+ Base64.encode64(n.packaged_notification).should == "AAAg3vLO/YTnAEB7ImFwcyI6eyJhbGVydCI6IkhlbGxvIGlQaG9uZSIsImJh\nZGdlIjozLCJzb3VuZCI6ImF3ZXNvbWUuY2FmIn19\n"
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ gem 'rspec', '>= 1.2.8'
3
+ require 'rspec'
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'apns')
5
+ require 'base64'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tal Atlas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: multi_json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.8.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.8.0
46
+ description: ! " Simple Apple push notification service gem\n\n Based on the
47
+ APNS gem by James Pozdena <jpoz@jpoz.net> http://github.com/jpoz/apns\n"
48
+ email:
49
+ - me@tal.by
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - Gemfile.lock
57
+ - MIT-LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - adck.gemspec
61
+ - lib/adck.rb
62
+ - lib/adck/connection.rb
63
+ - lib/adck/message.rb
64
+ - lib/adck/notification.rb
65
+ - lib/adck/version.rb
66
+ - spec/apns/notification_spec.rb
67
+ - spec/spec_helper.rb
68
+ homepage: https://github.com/delight-labs/ADCK
69
+ licenses: []
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.24
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Simple Apple push notification service gem
92
+ test_files:
93
+ - spec/apns/notification_spec.rb
94
+ - spec/spec_helper.rb