apnd 0.1.4 → 0.1.5
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/README.markdown +24 -1
- data/lib/apnd/daemon.rb +1 -1
- data/lib/apnd/errors.rb +9 -0
- data/lib/apnd/notification.rb +4 -4
- data/lib/apnd/settings.rb +34 -0
- data/lib/apnd/version.rb +1 -1
- data/test/apnd_test.rb +55 -26
- data/test/test_helper.rb +2 -25
- metadata +15 -3
data/README.markdown
CHANGED
@@ -83,12 +83,32 @@ push notifications to APND.
|
|
83
83
|
APND::Notification.upstream_host = 'localhost'
|
84
84
|
APND::Notification.upstream_port = 22195
|
85
85
|
|
86
|
-
|
86
|
+
notification1 = APND::Notification.new(
|
87
87
|
:alert => 'Alert!',
|
88
88
|
:token => 'fe15a27d5df3c34778defb1f4f3880265cc52c0c047682223be59fb68500a9a2',
|
89
|
+
:badge => 1
|
90
|
+
)
|
91
|
+
|
92
|
+
notification2 = APND::Notification.new(
|
93
|
+
:alert => 'Red Alert!',
|
94
|
+
:token => 'fe15a27d5df3c34778defb1f4f3880265cc52c0c047682223be59fb68500a9a2',
|
89
95
|
:badge => 99
|
90
96
|
)
|
91
97
|
|
98
|
+
# Send multiple notifications at once to avoid overhead in
|
99
|
+
# opening/closing the upstream socket connection each time
|
100
|
+
APND::Notification.open_upstream_socket do |sock|
|
101
|
+
sock.puts notification1
|
102
|
+
sock.puts notification2
|
103
|
+
end
|
104
|
+
|
105
|
+
# Send a notification to the upstream socket immediately
|
106
|
+
notification3 = APND::Notification.create(
|
107
|
+
:alert => 'Alert!',
|
108
|
+
:token => 'fe15a27d5df3c34778defb1f4f3880265cc52c0c047682223be59fb68500a9a2',
|
109
|
+
:badge => 0
|
110
|
+
)
|
111
|
+
|
92
112
|
|
93
113
|
## Prerequisites
|
94
114
|
|
@@ -105,6 +125,9 @@ at [developer.apple.com](http://developer.apple.com/).
|
|
105
125
|
|
106
126
|
Ruby must be compiled with OpenSSL support.
|
107
127
|
|
128
|
+
Tests use [Shoulda](http://github.com/thoughtbot/shoulda), and optionally
|
129
|
+
[TURN](https://github.com/TwP/turn).
|
130
|
+
|
108
131
|
|
109
132
|
## Installation
|
110
133
|
|
data/lib/apnd/daemon.rb
CHANGED
@@ -34,7 +34,7 @@ module APND
|
|
34
34
|
#
|
35
35
|
def run!
|
36
36
|
EventMachine::run do
|
37
|
-
ohai "Starting APND Daemon on #{@bind}:#{@port}"
|
37
|
+
ohai "Starting APND Daemon v#{APND::Version} on #{@bind}:#{@port}"
|
38
38
|
EventMachine::start_server(@bind, @port, APND::Daemon::Protocol) do |server|
|
39
39
|
server.queue = @queue
|
40
40
|
end
|
data/lib/apnd/errors.rb
CHANGED
@@ -9,5 +9,14 @@ module APND
|
|
9
9
|
super("Payload is larger than 256 bytes: '#{message}'")
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Raised when parsing a Notification with an invalid header
|
15
|
+
#
|
16
|
+
class InvalidNotificationHeader < StandardError
|
17
|
+
def initialize(header)
|
18
|
+
super("Invalid Notification header: #{header.inspect}")
|
19
|
+
end
|
20
|
+
end
|
12
21
|
end
|
13
22
|
end
|
data/lib/apnd/notification.rb
CHANGED
@@ -81,6 +81,8 @@ module APND
|
|
81
81
|
#
|
82
82
|
def self.valid?(data)
|
83
83
|
parse(data)
|
84
|
+
rescue
|
85
|
+
false
|
84
86
|
end
|
85
87
|
|
86
88
|
#
|
@@ -93,7 +95,7 @@ module APND
|
|
93
95
|
header = buffer.slice!(0, 3).unpack('ccc')
|
94
96
|
|
95
97
|
if header[0] != 0
|
96
|
-
raise
|
98
|
+
raise APND::Errors::InvalidNotificationHeader.new(header)
|
97
99
|
end
|
98
100
|
|
99
101
|
notification.token = buffer.slice!(0, 32).unpack('H*').first
|
@@ -117,8 +119,6 @@ module APND
|
|
117
119
|
end
|
118
120
|
|
119
121
|
notification
|
120
|
-
rescue
|
121
|
-
false
|
122
122
|
end
|
123
123
|
|
124
124
|
#
|
@@ -171,7 +171,7 @@ module APND
|
|
171
171
|
def aps_json
|
172
172
|
return @aps_json if @aps_json
|
173
173
|
json = aps.to_json
|
174
|
-
raise APND::InvalidPayload.new(json) if json.size > 256
|
174
|
+
raise APND::Errors::InvalidPayload.new(json) if json.size > 256
|
175
175
|
@aps_json = json
|
176
176
|
end
|
177
177
|
|
data/lib/apnd/settings.rb
CHANGED
@@ -111,6 +111,18 @@ module APND
|
|
111
111
|
@apple ||= APND::Settings::AppleConnection.new
|
112
112
|
end
|
113
113
|
|
114
|
+
#
|
115
|
+
# Mass assign AppleConnection settings
|
116
|
+
#
|
117
|
+
def apple=(options = {})
|
118
|
+
if options.respond_to?(:keys)
|
119
|
+
apple.cert = options[:cert] if options[:cert]
|
120
|
+
apple.cert_pass = options[:cert_pass] if options[:cert_pass]
|
121
|
+
apple.host = options[:host] if options[:host]
|
122
|
+
apple.port = options[:port] if options[:port]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
114
126
|
#
|
115
127
|
# Returns the Daemon settings
|
116
128
|
#
|
@@ -118,11 +130,33 @@ module APND
|
|
118
130
|
@daemon ||= APND::Settings::Daemon.new
|
119
131
|
end
|
120
132
|
|
133
|
+
#
|
134
|
+
# Mass assign Daemon settings
|
135
|
+
#
|
136
|
+
def daemon=(options = {})
|
137
|
+
if options.respond_to?(:keys)
|
138
|
+
daemon.bind = options[:bind] if options[:bind]
|
139
|
+
daemon.port = options[:port] if options[:port]
|
140
|
+
daemon.log_file = options[:log_file] if options[:log_file]
|
141
|
+
daemon.timer = options[:timer] if options[:timer]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
121
145
|
#
|
122
146
|
# Returns the Notification settings
|
123
147
|
#
|
124
148
|
def notification
|
125
149
|
@notification ||= APND::Settings::Notification.new
|
126
150
|
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Mass assign Notification settings
|
154
|
+
#
|
155
|
+
def notification=(options = {})
|
156
|
+
if options.respond_to?(:keys)
|
157
|
+
notification.port = options[:port] if options[:port]
|
158
|
+
notification.host = options[:host] if options[:host]
|
159
|
+
end
|
160
|
+
end
|
127
161
|
end
|
128
162
|
end
|
data/lib/apnd/version.rb
CHANGED
data/test/apnd_test.rb
CHANGED
@@ -1,40 +1,69 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
@bytes = %|\000\000 \376\025\242}]\363\303Gx\336\373\037O8\200&\\\305,\f\004v\202";\345\237\266\205\000\251\242\000;{"aps":{"sound":"default","alert":"Red Alert, Numba One!"}}|
|
6
|
-
@notification = APND::Notification.new({
|
7
|
-
:token => 'fe15a27d5df3c34778defb1f4f3880265cc52c0c047682223be59fb68500a9a2',
|
8
|
-
:alert => 'Red Alert, Numba One!',
|
9
|
-
:sound => 'default'
|
10
|
-
})
|
11
|
-
end
|
3
|
+
class APNDTest < Test::Unit::TestCase
|
4
|
+
@@bytes = %|\000\000 \376\025\242}]\363\303Gx\336\373\037O8\200&\\\305,\f\004v\202\";\345\237\266\205\000\251\242\000\\{\"location\":\"New York\",\"aps\":{\"badge\":10,\"sound\":\"default\",\"alert\":\"Red Alert, Numba One!\"}}|
|
12
5
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
context "APND Notification" do
|
7
|
+
setup do
|
8
|
+
@notification = APND::Notification.new({
|
9
|
+
:token => 'fe15a27d5df3c34778defb1f4f3880265cc52c0c047682223be59fb68500a9a2',
|
10
|
+
:alert => 'Red Alert, Numba One!',
|
11
|
+
:sound => 'default',
|
12
|
+
:badge => 10,
|
13
|
+
:custom => { 'location' => 'New York' }
|
14
|
+
})
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
context "instances" do
|
18
|
+
should "be initialized with a hash of options" do
|
19
|
+
[:token, :alert, :sound, :badge, :custom].each do |key|
|
20
|
+
assert_not_nil @notification.send(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
should "return a valid hex_token" do
|
25
|
+
expected = %|\376\025\242}]\363\303Gx\336\373\037O8\200&\\\305,\f\004v\202";\345\237\266\205\000\251\242|
|
26
|
+
assert_equal @notification.hex_token, expected
|
27
|
+
end
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
should "return a valid byte string" do
|
30
|
+
assert_equal @notification.to_bytes, @@bytes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should "parse a valid packet" do
|
35
|
+
notification = APND::Notification.parse(@@bytes)
|
24
36
|
|
25
|
-
|
37
|
+
assert notification
|
26
38
|
|
27
|
-
|
28
|
-
|
39
|
+
[:alert, :badge, :custom, :sound, :token, :hex_token, :to_bytes, :aps, :aps_json].each do |key|
|
40
|
+
assert_equal @notification.send(key), notification.send(key)
|
41
|
+
end
|
29
42
|
end
|
30
43
|
|
31
|
-
|
44
|
+
should "raise InvalidNotificationHeader parsing a bad packet" do
|
45
|
+
assert_raise APND::Errors::InvalidNotificationHeader do
|
46
|
+
APND::Notification.parse("I'm not a packet!")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
should "raise InvalidPayload if custom hash is too large" do
|
51
|
+
assert_raise APND::Errors::InvalidPayload do
|
52
|
+
notification = @notification.dup
|
53
|
+
notification.custom = {
|
54
|
+
'lorem' => "Hi! " * 200
|
55
|
+
}
|
56
|
+
APND::Notification.parse(notification.to_bytes)
|
57
|
+
end
|
58
|
+
end
|
32
59
|
end
|
33
60
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
61
|
+
context "APND Daemon" do
|
62
|
+
should "receive multiple Notifications in a single packet" do
|
63
|
+
notifications = [@@bytes, @@bytes, @@bytes].join("\n")
|
64
|
+
notifications.each_line do |line|
|
65
|
+
assert APND::Notification.valid?(line)
|
66
|
+
end
|
38
67
|
end
|
39
68
|
end
|
40
69
|
|
data/test/test_helper.rb
CHANGED
@@ -1,33 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'test/unit'
|
3
|
-
|
4
|
-
dir = File.dirname(File.expand_path(__FILE__))
|
5
|
-
$LOAD_PATH.unshift(File.join(dir, '..', 'lib'))
|
6
|
-
$LOAD_PATH.unshift(dir)
|
7
|
-
|
8
|
-
require 'apnd'
|
3
|
+
require 'shoulda'
|
9
4
|
|
10
5
|
begin
|
11
6
|
require 'turn'
|
12
7
|
rescue LoadError
|
13
8
|
end
|
14
9
|
|
15
|
-
|
16
|
-
# test/spec/mini 3
|
17
|
-
# http://gist.github.com/25455
|
18
|
-
# chris@ozmm.org
|
19
|
-
#
|
20
|
-
def context(*args, &block)
|
21
|
-
return super unless (name = args.first) && block
|
22
|
-
require 'test/unit'
|
23
|
-
klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
|
24
|
-
def self.test(name, &block)
|
25
|
-
define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
|
26
|
-
end
|
27
|
-
def self.xtest(*args) end
|
28
|
-
def self.setup(&block) define_method(:setup, &block) end
|
29
|
-
def self.teardown(&block) define_method(:teardown, &block) end
|
30
|
-
end
|
31
|
-
(class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
|
32
|
-
klass.class_eval &block
|
33
|
-
end
|
10
|
+
require 'apnd'
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 5
|
9
|
+
version: 0.1.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Joshua Priddle
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-09 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -59,6 +59,18 @@ dependencies:
|
|
59
59
|
version: 1.1.0
|
60
60
|
type: :runtime
|
61
61
|
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: shoulda
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
type: :development
|
73
|
+
version_requirements: *id004
|
62
74
|
description: " APND (Apple Push Notification Daemon) is a ruby library to send Apple Push\n Notifications to iPhones.\n"
|
63
75
|
email: jpriddle@nevercraft.net
|
64
76
|
executables:
|