houston 1.0.0 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc1f9887759e151475336ef952b607870f3b29b3
4
- data.tar.gz: 1e09658a9c4177061c0e5137385779dcbee858e1
3
+ metadata.gz: 19ea781099fb74df316010704e9335580db3418c
4
+ data.tar.gz: bb5452a82ab13181e6fee98915a37799ae1dbe0d
5
5
  SHA512:
6
- metadata.gz: 537b0cd3c221e84bc6b156e33eebb07d65edf5c5eb79430b4755f48ad8a7d2fd6532570619d07d12fd17d0d8861b2b64b300b297f498469cacc9cf18e42e75bd
7
- data.tar.gz: 35b91cd235c889a02b2e18828f99c8ea5bcd0a3a67c85f30f69fb467466a97334676bf8365bd15df6fa518303251cc802491cc080359d4f63df91648e25bee02
6
+ metadata.gz: 24c557aa4a8ac29e937cc0f8c4ecccb2bd1218c3f204e3cf273d7c942646e0aa7cd7c01ddc5228ba8d6693ee46a0c65d1a732f2a8c50364ac7d452b8ca274390
7
+ data.tar.gz: 552d74c3ff780d5168fe3a3fda11b31e3da9292c3a13607cc8741fa088e76b4d1c52677bbbe7e40ebcd6c029ce1b7d0a2eed7341fb1525c089303fe95d467717
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- houston (1.0.0)
4
+ houston (2.0.0)
5
5
  commander (~> 4.1)
6
6
  json
7
7
 
@@ -12,13 +12,19 @@ GEM
12
12
  highline (~> 1.6.11)
13
13
  highline (1.6.19)
14
14
  json (1.8.1)
15
+ multi_json (1.8.0)
15
16
  rake (0.9.6)
16
17
  rspec (0.9.4)
18
+ simplecov (0.7.1)
19
+ multi_json (~> 1.0)
20
+ simplecov-html (~> 0.7.1)
21
+ simplecov-html (0.7.1)
17
22
 
18
23
  PLATFORMS
19
24
  ruby
20
25
 
21
26
  DEPENDENCIES
22
27
  houston!
23
- rake (~> 0.9)
24
- rspec (~> 0.6)
28
+ rake
29
+ rspec
30
+ simplecov
data/README.md CHANGED
@@ -60,6 +60,10 @@ connection.write(notification.message)
60
60
  connection.close
61
61
  ```
62
62
 
63
+ ## Versioning
64
+
65
+ Houston 2.0 supports the new [enhanced notification format](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4). Support for the legacy notification format is available in 1.x releases.
66
+
63
67
  ## Command Line Tool
64
68
 
65
69
  Houston also comes with the `apn` binary, which provides a convenient way to test notifications from the command line.
data/houston.gemspec CHANGED
@@ -16,8 +16,9 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency "commander", "~> 4.1"
17
17
  s.add_dependency "json"
18
18
 
19
- s.add_development_dependency "rspec", "~> 0.6"
20
- s.add_development_dependency "rake", "~> 0.9"
19
+ s.add_development_dependency "rspec"
20
+ s.add_development_dependency "rake"
21
+ s.add_development_dependency "simplecov"
21
22
 
22
23
  s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
23
24
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -71,7 +71,9 @@ module Houston
71
71
  end
72
72
 
73
73
  if error
74
- command, status, index = error.unpack("cci")
74
+ command, status, index = error.unpack("ccN")
75
+ # status == 10 means shutdown, and the given id is the last one successfully sent
76
+ index += 1 if status == 10
75
77
  notifications.slice!(0..index)
76
78
  notifications.each(&:mark_as_unsent!)
77
79
  push(*notifications)
@@ -4,7 +4,7 @@ module Houston
4
4
  class Notification
5
5
  MAXIMUM_PAYLOAD_SIZE = 256
6
6
 
7
- attr_accessor :token, :alert, :badge, :sound, :content_available, :custom_data, :id, :expiry
7
+ attr_accessor :token, :alert, :badge, :sound, :content_available, :custom_data, :id, :expiry, :priority
8
8
  attr_reader :sent_at
9
9
 
10
10
  alias :device :token
@@ -17,6 +17,7 @@ module Houston
17
17
  @sound = options.delete(:sound)
18
18
  @expiry = options.delete(:expiry)
19
19
  @id = options.delete(:id)
20
+ @priority = options.delete(:priority)
20
21
  @content_available = options.delete(:content_available)
21
22
 
22
23
  @custom_data = options
@@ -34,12 +35,12 @@ module Houston
34
35
  end
35
36
 
36
37
  def message
37
- json = payload.to_json
38
- device_token = [@token.gsub(/[<\s>]/, '')].pack('H*')
39
- @expiry ||= Time.now + 86400
40
- @id ||= 0
41
-
42
- [1, @id, @expiry.to_i, 0, 32, device_token, 0, json.bytes.count, json].pack('ciicca*cca*')
38
+ data = [device_token_item,
39
+ payload_item,
40
+ identifier_item,
41
+ expiration_item,
42
+ priority_item].compact.join
43
+ [2, data.bytes.count, data].pack('cNa*')
43
44
  end
44
45
 
45
46
  def mark_as_sent!
@@ -57,5 +58,28 @@ module Houston
57
58
  def valid?
58
59
  payload.to_json.bytesize <= MAXIMUM_PAYLOAD_SIZE
59
60
  end
61
+
62
+ private
63
+
64
+ def device_token_item
65
+ [1, 32, @token.gsub(/[<\s>]/, '')].pack('cnH*')
66
+ end
67
+
68
+ def payload_item
69
+ json = payload.to_json
70
+ [2, json.bytes.count, json].pack('cna*')
71
+ end
72
+
73
+ def identifier_item
74
+ [3, 4, @id].pack('cnN') unless @id.nil?
75
+ end
76
+
77
+ def expiration_item
78
+ [4, 4, @expiry].pack('cnN') unless @expiry.nil?
79
+ end
80
+
81
+ def priority_item
82
+ [5, 1, @priority].pack('cnc') unless @priority.nil?
83
+ end
60
84
  end
61
85
  end
@@ -1,3 +1,3 @@
1
1
  module Houston
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,199 @@
1
+ require 'spec_helper'
2
+
3
+ describe Houston::Notification do
4
+ let(:notification_options) {
5
+ {
6
+ token: '<ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969>',
7
+ alert: 'Houston, we have a problem.',
8
+ badge: 2701,
9
+ sound: 'sosumi.aiff',
10
+ expiry: 1234567890,
11
+ id: 42,
12
+ priority: 10,
13
+ content_available: true,
14
+ # custom data
15
+ key1: 1,
16
+ key2: 'abc'
17
+ }
18
+ }
19
+
20
+ subject { Houston::Notification.new(notification_options) }
21
+
22
+ its(:token) { should == '<ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969>' }
23
+ its(:alert) { should == 'Houston, we have a problem.' }
24
+ its(:badge) { should == 2701 }
25
+ its(:sound) { should == 'sosumi.aiff' }
26
+ its(:expiry) { should == 1234567890 }
27
+ its(:id) { should == 42 }
28
+ its(:priority) { should == 10 }
29
+ its(:content_available) { should be_true }
30
+ its(:custom_data) { should == { key1: 1, key2: 'abc' } }
31
+
32
+ context 'using :device instead of :token' do
33
+ subject do
34
+ notification_options[:device] = notification_options[:token]
35
+ notification_options.delete(:token)
36
+ Houston::Notification.new(notification_options)
37
+ end
38
+
39
+ its(:device) { '<ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969>' }
40
+ end
41
+
42
+ describe '#payload' do
43
+ it 'should create a compliant dictionary' do
44
+ subject.payload.should == {
45
+ 'aps' => {
46
+ 'alert' => 'Houston, we have a problem.',
47
+ 'badge' => 2701,
48
+ 'sound' => 'sosumi.aiff',
49
+ 'content-available' => 1
50
+ },
51
+ :key1 => 1,
52
+ :key2 => 'abc'
53
+ }
54
+ end
55
+
56
+ it 'should create a dictionary of only custom data and empty aps' do
57
+ Houston::Notification.new(key1: 123, key2: 'xyz').payload.should == {
58
+ 'aps' => {},
59
+ :key1 => 123,
60
+ :key2 => 'xyz'
61
+ }
62
+ end
63
+
64
+ it 'should create a dictionary only with alerts' do
65
+ Houston::Notification.new(alert: 'Hello, World!').payload.should == {
66
+ 'aps' => { 'alert' => 'Hello, World!' }
67
+ }
68
+ end
69
+
70
+ it 'should create a dictionary only with badges' do
71
+ Houston::Notification.new(badge: '123').payload.should == {
72
+ 'aps' => { 'badge' => 123 }
73
+ }
74
+ end
75
+
76
+ it 'should create a dictionary only with sound' do
77
+ Houston::Notification.new(sound: 'ring.aiff').payload.should == {
78
+ 'aps' => { 'sound' => 'ring.aiff' }
79
+ }
80
+ end
81
+
82
+ it 'should create a dictionary only with content-available' do
83
+ Houston::Notification.new(content_available: true).payload.should == {
84
+ 'aps' => { 'content-available' => 1 }
85
+ }
86
+ end
87
+
88
+ it 'should allow custom data inside aps key' do
89
+ notification_options = { :badge => 567, 'aps' => { 'loc-key' => 'my-key' } }
90
+ Houston::Notification.new(notification_options).payload.should == {
91
+ 'aps' => { 'loc-key' => 'my-key', 'badge' => 567 }
92
+ }
93
+ end
94
+ end
95
+
96
+ describe '#sent?' do
97
+ it 'should be false initially' do
98
+ subject.sent?.should be_false
99
+ end
100
+
101
+ it 'should be true after marking as sent' do
102
+ subject.mark_as_sent!
103
+ subject.sent?.should be_true
104
+ end
105
+
106
+ it 'should be false after marking as unsent' do
107
+ subject.mark_as_sent!
108
+ subject.mark_as_unsent!
109
+ subject.sent?.should be_false
110
+ end
111
+ end
112
+
113
+ describe '#message' do
114
+ it 'should create a message with command 2' do
115
+ command, _1, _2 = subject.message.unpack('cNa*')
116
+ command.should == 2
117
+ end
118
+
119
+ it 'should create a message with correct frame length' do
120
+ _1, length, _2 = subject.message.unpack('cNa*')
121
+ length.should == 182
122
+ end
123
+
124
+ def parse_items(items_stream)
125
+ items = []
126
+ until items_stream.empty?
127
+ item_id, item_length, items_stream = items_stream.unpack('cna*')
128
+ item_data, items_stream = items_stream.unpack("a#{item_length}a*")
129
+ items << [item_id, item_length, item_data]
130
+ end
131
+ items
132
+ end
133
+
134
+ it 'should include five items' do
135
+ _1, _2, items_stream = subject.message.unpack('cNa*')
136
+ parse_items(items_stream).should have(5).items
137
+ end
138
+
139
+ it 'should include an item #1 with the token as hexadecimal' do
140
+ _1, _2, items_stream = subject.message.unpack('cNa*')
141
+ items = parse_items(items_stream)
142
+ items.should include([1, 32, ['ce8be6272e43e85516033e24b4c289220eeda4879c477160b2545e95b68b5969'].pack('H*')])
143
+ end
144
+
145
+ it 'should include an item #2 with the payload as JSON' do
146
+ _1, _2, items_stream = subject.message.unpack('cNa*')
147
+ items = parse_items(items_stream)
148
+ items.should include([2, 126, '{"key1":1,"key2":"abc","aps":{"alert":"Houston, we have a problem.","badge":2701,"sound":"sosumi.aiff","content-available":1}}'])
149
+ end
150
+
151
+ it 'should include an item #3 with the identifier' do
152
+ _1, _2, items_stream = subject.message.unpack('cNa*')
153
+ items = parse_items(items_stream)
154
+ items.should include([3, 4, [42].pack('N')])
155
+ end
156
+
157
+ it 'should include an item #4 with the expiry' do
158
+ _1, _2, items_stream = subject.message.unpack('cNa*')
159
+ items = parse_items(items_stream)
160
+ items.should include([4, 4, [1234567890].pack('N')])
161
+ end
162
+
163
+ it 'should include an item #4 with the priority' do
164
+ _1, _2, items_stream = subject.message.unpack('cNa*')
165
+ items = parse_items(items_stream)
166
+ items.should include([5, 1, [10].pack('c')])
167
+ end
168
+
169
+ it 'might be missing the identifier item' do
170
+ notification_options.delete(:id)
171
+ notification = Houston::Notification.new(notification_options)
172
+ msg = notification.message
173
+ _1, _2, items_stream = notification.message.unpack('cNa*')
174
+ items = parse_items(items_stream)
175
+ items.should have(4).items
176
+ items.find { |item| item[0] == 3 }.should be_nil
177
+ end
178
+
179
+ it 'might be missing the expiry item' do
180
+ notification_options.delete(:expiry)
181
+ notification = Houston::Notification.new(notification_options)
182
+ msg = notification.message
183
+ _1, _2, items_stream = notification.message.unpack('cNa*')
184
+ items = parse_items(items_stream)
185
+ items.should have(4).items
186
+ items.find { |item| item[0] == 4 }.should be_nil
187
+ end
188
+
189
+ it 'might be missing the priority item' do
190
+ notification_options.delete(:priority)
191
+ notification = Houston::Notification.new(notification_options)
192
+ msg = notification.message
193
+ _1, _2, items_stream = notification.message.unpack('cNa*')
194
+ items = parse_items(items_stream)
195
+ items.should have(4).items
196
+ items.find { |item| item[0] == 5 }.should be_nil
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,10 @@
1
+ unless ENV['CI']
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ add_filter '/spec/'
6
+ end
7
+ end
8
+
9
+ require 'houston'
10
+ require 'rspec'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: houston
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattt Thompson
@@ -42,30 +42,44 @@ dependencies:
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
- version: '0.6'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
- version: '0.6'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
- version: '0.9'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
- version: '0.9'
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: Houston is a simple gem for sending Apple Push Notifications. Pass your
70
84
  credentials, construct your message, and send it.
71
85
  email: m@mattt.me
@@ -86,6 +100,8 @@ files:
86
100
  - ./LICENSE
87
101
  - ./Rakefile
88
102
  - ./README.md
103
+ - spec/notification_spec.rb
104
+ - spec/spec_helper.rb
89
105
  - bin/apn
90
106
  homepage: http://github.com/mattt/houston
91
107
  licenses:
@@ -111,4 +127,6 @@ rubygems_version: 2.0.3
111
127
  signing_key:
112
128
  specification_version: 4
113
129
  summary: Send Apple Push Notifications
114
- test_files: []
130
+ test_files:
131
+ - spec/notification_spec.rb
132
+ - spec/spec_helper.rb