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 +2 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +26 -0
- data/MIT-LICENSE +22 -0
- data/README.md +149 -0
- data/Rakefile +2 -0
- data/adck.gemspec +25 -0
- data/lib/adck/connection.rb +78 -0
- data/lib/adck/message.rb +152 -0
- data/lib/adck/notification.rb +27 -0
- data/lib/adck/version.rb +3 -0
- data/lib/adck.rb +66 -0
- data/spec/apns/notification_spec.rb +44 -0
- data/spec/spec_helper.rb +5 -0
- metadata +94 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
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
|
data/lib/adck/message.rb
ADDED
@@ -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
|
data/lib/adck/version.rb
ADDED
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
|
data/spec/spec_helper.rb
ADDED
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
|