houston 2.1.0 → 2.2.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +22 -16
  3. data/README.md +19 -1
  4. data/bin/apn +3 -0
  5. data/coverage/assets/0.8.0/application.css +799 -0
  6. data/coverage/assets/0.8.0/application.js +1559 -0
  7. data/coverage/assets/0.8.0/colorbox/border.png +0 -0
  8. data/coverage/assets/0.8.0/colorbox/controls.png +0 -0
  9. data/coverage/assets/0.8.0/colorbox/loading.gif +0 -0
  10. data/coverage/assets/0.8.0/colorbox/loading_background.png +0 -0
  11. data/coverage/assets/0.8.0/favicon_green.png +0 -0
  12. data/coverage/assets/0.8.0/favicon_red.png +0 -0
  13. data/coverage/assets/0.8.0/favicon_yellow.png +0 -0
  14. data/coverage/assets/0.8.0/loading.gif +0 -0
  15. data/coverage/assets/0.8.0/magnify.png +0 -0
  16. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  17. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  18. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  19. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  20. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  21. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  22. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  23. data/coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  24. data/coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  25. data/coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  26. data/coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  27. data/coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  28. data/coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  29. data/coverage/index.html +319 -163
  30. data/houston.gemspec +1 -1
  31. data/lib/houston/client.rb +1 -0
  32. data/lib/houston/notification.rb +30 -5
  33. data/lib/houston/version.rb +1 -1
  34. data/spec/client_spec.rb +2 -2
  35. data/spec/notification_spec.rb +23 -10
  36. metadata +28 -4
data/houston.gemspec CHANGED
@@ -16,7 +16,7 @@ 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", "~> 2.0"
19
+ s.add_development_dependency "rspec", "~> 3.0"
20
20
  s.add_development_dependency "rake"
21
21
  s.add_development_dependency "simplecov"
22
22
 
@@ -72,6 +72,7 @@ module Houston
72
72
 
73
73
  if error
74
74
  command, status, index = error.unpack("ccN")
75
+ notifications[index].apns_error_code = status
75
76
  notifications.slice!(0..index)
76
77
  notifications.each(&:mark_as_unsent!)
77
78
  push(*notifications)
@@ -2,10 +2,28 @@ require 'json'
2
2
 
3
3
  module Houston
4
4
  class Notification
5
- MAXIMUM_PAYLOAD_SIZE = 256
5
+ class APNSError < RuntimeError
6
+ # See: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW12
7
+ CODES = {
8
+ 0 => "No errors encountered",
9
+ 1 => "Processing error",
10
+ 2 => "Missing device token",
11
+ 3 => "Missing topic",
12
+ 4 => "Missing payload",
13
+ 5 => "Invalid token size",
14
+ 6 => "Invalid topic size",
15
+ 7 => "Invalid payload size",
16
+ 8 => "Invalid token",
17
+ 10 => "Shutdown",
18
+ 255 => "Unknown error"
19
+ }
20
+ end
21
+
22
+ MAXIMUM_PAYLOAD_SIZE = 2048
6
23
 
7
- attr_accessor :token, :alert, :badge, :sound, :content_available, :custom_data, :id, :expiry, :priority
24
+ attr_accessor :token, :alert, :badge, :sound, :category, :content_available, :custom_data, :id, :expiry, :priority
8
25
  attr_reader :sent_at
26
+ attr_writer :apns_error_code
9
27
 
10
28
  alias :device :token
11
29
  alias :device= :token=
@@ -15,6 +33,7 @@ module Houston
15
33
  @alert = options.delete(:alert)
16
34
  @badge = options.delete(:badge)
17
35
  @sound = options.delete(:sound)
36
+ @category = options.delete(:category)
18
37
  @expiry = options.delete(:expiry)
19
38
  @id = options.delete(:id)
20
39
  @priority = options.delete(:priority)
@@ -24,11 +43,13 @@ module Houston
24
43
  end
25
44
 
26
45
  def payload
27
- json = {}.merge(@custom_data || {})
46
+ json = {}.merge(@custom_data || {}).inject({}){|h,(k,v)| h[k.to_s] = v; h}
47
+
28
48
  json['aps'] ||= {}
29
49
  json['aps']['alert'] = @alert if @alert
30
50
  json['aps']['badge'] = @badge.to_i rescue 0 if @badge
31
51
  json['aps']['sound'] = @sound if @sound
52
+ json['aps']['category'] = @category if @category
32
53
  json['aps']['content-available'] = 1 if @content_available
33
54
 
34
55
  json
@@ -59,10 +80,14 @@ module Houston
59
80
  payload.to_json.bytesize <= MAXIMUM_PAYLOAD_SIZE
60
81
  end
61
82
 
83
+ def error
84
+ APNSError.new(APNSError::CODES[@apns_error_code]) if @apns_error_code.nonzero?
85
+ end
86
+
62
87
  private
63
-
88
+
64
89
  def device_token_item
65
- [1, 32, @token.gsub(/[<\s>]/, '')].pack('cnH*')
90
+ [1, 32, @token.gsub(/[<\s>]/, '')].pack('cnH64')
66
91
  end
67
92
 
68
93
  def payload_item
@@ -1,3 +1,3 @@
1
1
  module Houston
2
- VERSION = "2.1.0"
2
+ VERSION = "2.2.0"
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -83,7 +83,7 @@ describe Houston::Client do
83
83
 
84
84
  describe '#unregistered_devices' do
85
85
  it 'should correctly parse the feedback response and create a dictionary of unregistered devices with timestamps' do
86
- subject.unregistered_devices.should == [
86
+ expect(subject.unregistered_devices).to eq [
87
87
  {:token=>"ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969", :timestamp=>443779200},
88
88
  {:token=>"ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5970", :timestamp=>1388678223}
89
89
  ]
@@ -92,7 +92,7 @@ describe Houston::Client do
92
92
 
93
93
  describe '#devices' do
94
94
  it 'should correctly parse the feedback response and create an array of unregistered devices' do
95
- subject.devices.should == [
95
+ expect(subject.devices).to eq [
96
96
  "ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969",
97
97
  "ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5970"
98
98
  ]
@@ -11,7 +11,6 @@ describe Houston::Notification do
11
11
  id: 42,
12
12
  priority: 10,
13
13
  content_available: true,
14
- # custom data
15
14
  key1: 1,
16
15
  key2: 'abc'
17
16
  }
@@ -56,7 +55,7 @@ describe Houston::Notification do
56
55
 
57
56
  describe '#content_available' do
58
57
  subject { super().content_available }
59
- it { should be_true }
58
+ it { should be_truthy }
60
59
  end
61
60
 
62
61
  describe '#custom_data' do
@@ -86,16 +85,16 @@ describe Houston::Notification do
86
85
  'sound' => 'sosumi.aiff',
87
86
  'content-available' => 1
88
87
  },
89
- :key1 => 1,
90
- :key2 => 'abc'
88
+ 'key1' => 1,
89
+ 'key2' => 'abc'
91
90
  })
92
91
  end
93
92
 
94
93
  it 'should create a dictionary of only custom data and empty aps' do
95
94
  expect(Houston::Notification.new(key1: 123, key2: 'xyz').payload).to eq({
96
95
  'aps' => {},
97
- :key1 => 123,
98
- :key2 => 'xyz'
96
+ 'key1' => 123,
97
+ 'key2' => 'xyz'
99
98
  })
100
99
  end
101
100
 
@@ -129,22 +128,29 @@ describe Houston::Notification do
129
128
  'aps' => { 'loc-key' => 'my-key', 'badge' => 567 }
130
129
  })
131
130
  end
131
+
132
+ it 'should create notification from hash with string and symbol keys' do
133
+ notification_options = { :badge => 567, :aps => { 'loc-key' => 'my-key' } }
134
+ expect(Houston::Notification.new(notification_options).payload['aps']).to eq({
135
+ 'loc-key' => 'my-key', 'badge' => 567
136
+ })
137
+ end
132
138
  end
133
139
 
134
140
  describe '#sent?' do
135
141
  it 'should be false initially' do
136
- expect(subject.sent?).to be_false
142
+ expect(subject.sent?).to be_falsey
137
143
  end
138
144
 
139
145
  it 'should be true after marking as sent' do
140
146
  subject.mark_as_sent!
141
- expect(subject.sent?).to be_true
147
+ expect(subject.sent?).to be_truthy
142
148
  end
143
149
 
144
150
  it 'should be false after marking as unsent' do
145
151
  subject.mark_as_sent!
146
152
  subject.mark_as_unsent!
147
- expect(subject.sent?).to be_false
153
+ expect(subject.sent?).to be_falsey
148
154
  end
149
155
  end
150
156
 
@@ -198,12 +204,19 @@ describe Houston::Notification do
198
204
  expect(items).to include([4, 4, [1234567890].pack('N')])
199
205
  end
200
206
 
201
- it 'should include an item #4 with the priority' do
207
+ it 'should include an item #5 with the priority' do
202
208
  _1, _2, items_stream = subject.message.unpack('cNa*')
203
209
  items = parse_items(items_stream)
204
210
  expect(items).to include([5, 1, [10].pack('c')])
205
211
  end
206
212
 
213
+ it 'should pad or truncate token so it is 32 bytes long' do
214
+ notification_options[:token] = '<ce8be627 2e43e855 16033e24 b4c28922>'
215
+ _1, _2, items_stream = subject.message.unpack('cNa*')
216
+ items = parse_items(items_stream)
217
+ expect(items).to include([1, 32, ['ce8be6272e43e85516033e24b4c2892200000000000000000000000000000000'].pack('H*')])
218
+ end
219
+
207
220
  it 'might be missing the identifier item' do
208
221
  notification_options.delete(:id)
209
222
  notification = Houston::Notification.new(notification_options)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: houston
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattt Thompson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-12 00:00:00.000000000 Z
11
+ date: 2014-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '2.0'
47
+ version: '3.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: '2.0'
54
+ version: '3.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +128,30 @@ files:
128
128
  - ./coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png
129
129
  - ./coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png
130
130
  - ./coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png
131
+ - ./coverage/assets/0.8.0/application.css
132
+ - ./coverage/assets/0.8.0/application.js
133
+ - ./coverage/assets/0.8.0/colorbox/border.png
134
+ - ./coverage/assets/0.8.0/colorbox/controls.png
135
+ - ./coverage/assets/0.8.0/colorbox/loading.gif
136
+ - ./coverage/assets/0.8.0/colorbox/loading_background.png
137
+ - ./coverage/assets/0.8.0/favicon_green.png
138
+ - ./coverage/assets/0.8.0/favicon_red.png
139
+ - ./coverage/assets/0.8.0/favicon_yellow.png
140
+ - ./coverage/assets/0.8.0/loading.gif
141
+ - ./coverage/assets/0.8.0/magnify.png
142
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
143
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
144
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
145
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
146
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png
147
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
148
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
149
+ - ./coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
150
+ - ./coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png
151
+ - ./coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png
152
+ - ./coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png
153
+ - ./coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png
154
+ - ./coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png
131
155
  - ./coverage/index.html
132
156
  - ./Gemfile
133
157
  - ./Gemfile.lock