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