grocer 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.3.2
4
+
5
+ * Validate the size of the payload before sending a notification
6
+
3
7
  ## 0.3.1
4
8
 
5
9
  * Move repo to the Grocer organization.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://api.travis-ci.org/grocer/grocer.png?branch=master)](https://travis-ci.org/grocer/grocer)
4
4
  [![Dependency Status](https://gemnasium.com/grocer/grocer.png)](https://gemnasium.com/grocer/grocer)
5
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/grocer/grocer)
5
+ [![Code Climate](https://codeclimate.com/github/grocer/grocer.png)](https://codeclimate.com/github/grocer/grocer)
6
6
 
7
7
  **grocer** interfaces with the [Apple Push Notification
8
8
  Service](http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html)
@@ -118,11 +118,22 @@ send any payload for a Passbook notification. If you do, it will be ignored.
118
118
 
119
119
  ```ruby
120
120
  notification = Grocer::PassbookNotification.new(device_token: "...")
121
-
122
121
  # Generates a JSON payload like:
123
122
  # {"aps": {}}
124
123
  ```
125
124
 
125
+ #### Newsstand Notifications
126
+
127
+ Grocer also supports the special Newsstand 'content-available' notification. `Grocer::NewsstandNotification` can be
128
+ used for this. Like `Grocer::PassbookNotification`, it is a specialized kind of notification which does not require
129
+ any payload. Likewise, anything you add to it will be ignored.
130
+
131
+ ```ruby
132
+ notification = Grocer::NewsstandNotification.new(device_token: "...")
133
+ # Generates a JSON payload like:
134
+ # {"aps": {"content-available":1}}
135
+ ````
136
+
126
137
  ### Feedback
127
138
 
128
139
  ```ruby
@@ -137,7 +148,7 @@ feedback = Grocer.feedback(
137
148
  )
138
149
 
139
150
  feedback.each do |attempt|
140
- puts "Device #{attempt.device_token} failed at #{attempt.timestamp}
151
+ puts "Device #{attempt.device_token} failed at #{attempt.timestamp}"
141
152
  end
142
153
  ```
143
154
 
@@ -1,7 +1,4 @@
1
1
  require 'grocer'
2
- require 'grocer/no_gateway_error'
3
- require 'grocer/no_port_error'
4
- require 'grocer/certificate_expired_error'
5
2
  require 'grocer/ssl_connection'
6
3
 
7
4
  module Grocer
@@ -1,5 +1,3 @@
1
- require 'grocer/invalid_format_error'
2
-
3
1
  module Grocer
4
2
  class FailedDeliveryAttempt
5
3
  LENGTH = 38
@@ -0,0 +1,24 @@
1
+ require 'grocer/notification'
2
+
3
+ module Grocer
4
+ # Public: A specialized form of a Grocer::Notification which requires neither
5
+ # an alert nor badge to be present in the payload. It requires only the
6
+ # `device_token` to be set.
7
+ #
8
+ # Examples
9
+ #
10
+ # Grocer::NewsstandNotification.new(device_token: '...')
11
+ class NewsstandNotification < Notification
12
+
13
+ private
14
+
15
+ def validate_payload
16
+ true
17
+ end
18
+
19
+ def payload_hash
20
+ { "content-available" => 1 }
21
+ end
22
+
23
+ end
24
+ end
@@ -1,9 +1,10 @@
1
1
  require 'json'
2
- require 'grocer/no_payload_error'
3
2
 
4
3
  module Grocer
5
4
  # Public: An object used to send notifications to APNS.
6
5
  class Notification
6
+ MAX_PAYLOAD_SIZE = 256
7
+
7
8
  attr_accessor :identifier, :expiry, :device_token, :alert, :badge, :sound,
8
9
  :custom
9
10
 
@@ -41,8 +42,13 @@ module Grocer
41
42
 
42
43
  private
43
44
 
45
+ def payload_too_large?
46
+ encoded_payload.bytesize > MAX_PAYLOAD_SIZE
47
+ end
48
+
44
49
  def validate_payload
45
50
  fail NoPayloadError unless alert || badge
51
+ fail PayloadTooLargeError if payload_too_large?
46
52
  end
47
53
 
48
54
  def encoded_payload
@@ -1,3 +1,3 @@
1
1
  module Grocer
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'
3
3
  end
data/lib/grocer.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'grocer/feedback'
2
2
  require 'grocer/notification'
3
3
  require 'grocer/passbook_notification'
4
+ require 'grocer/newsstand_notification'
4
5
  require 'grocer/feedback_connection'
5
6
  require 'grocer/push_connection'
6
7
  require 'grocer/pusher'
@@ -8,6 +9,13 @@ require 'grocer/version'
8
9
  require 'grocer/server'
9
10
 
10
11
  module Grocer
12
+ Error = Class.new(::StandardError)
13
+ InvalidFormatError = Class.new(Error)
14
+ NoGatewayError = Class.new(Error)
15
+ NoPayloadError = Class.new(Error)
16
+ NoPortError = Class.new(Error)
17
+ PayloadTooLargeError = Class.new(Error)
18
+ CertificateExpiredError = Module.new
11
19
 
12
20
  def self.env
13
21
  ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'grocer/newsstand_notification'
3
+ require 'grocer/shared_examples_for_notifications'
4
+
5
+ describe Grocer::NewsstandNotification do
6
+ describe 'binary format' do
7
+ let(:payload_options) { Hash.new }
8
+ let(:payload_from_bytes) { notification.to_bytes[45..-1] }
9
+ let(:payload_dictionary_from_bytes) { JSON.parse(payload_from_bytes, symbolize_names: true) }
10
+
11
+ include_examples 'a notification'
12
+
13
+ it 'does require a payload' do
14
+ expect(payload_dictionary_from_bytes[:'content-available']).to_not be_nil
15
+ end
16
+
17
+ it 'has a content-available hash' do
18
+ expect(payload_dictionary_from_bytes[:'content-available']).to eq(1)
19
+ end
20
+
21
+ end
22
+ end
@@ -46,12 +46,20 @@ describe Grocer::Notification do
46
46
  expect(bytes[43...45]).to eq([payload_from_bytes.bytesize].pack('n'))
47
47
  end
48
48
 
49
- context 'invalid payload' do
49
+ context 'missing payload' do
50
50
  let(:payload_options) { Hash.new }
51
51
 
52
52
  it 'raises an error when neither alert nor badge is specified' do
53
53
  -> { notification.to_bytes }.should raise_error(Grocer::NoPayloadError)
54
54
  end
55
55
  end
56
+
57
+ context 'oversized payload' do
58
+ let(:payload_options) { { alert: 'a' * (Grocer::Notification::MAX_PAYLOAD_SIZE + 1) } }
59
+
60
+ it 'raises an error when the size of the payload in bytes is too large' do
61
+ -> { notification.to_bytes }.should raise_error(Grocer::PayloadTooLargeError)
62
+ end
63
+ end
56
64
  end
57
65
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grocer
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.3.2
4
5
  prerelease:
5
- version: 0.3.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Andy Lindeman
@@ -11,88 +11,88 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-01-05 00:00:00.000000000 Z
14
+ date: 2013-02-28 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- version_requirements: !ruby/object:Gem::Requirement
17
+ name: rspec
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
18
20
  requirements:
19
21
  - - ~>
20
22
  - !ruby/object:Gem::Version
21
23
  version: '2.11'
22
- none: false
23
- name: rspec
24
24
  type: :development
25
25
  prerelease: false
26
- requirement: !ruby/object:Gem::Requirement
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
27
28
  requirements:
28
29
  - - ~>
29
30
  - !ruby/object:Gem::Version
30
31
  version: '2.11'
31
- none: false
32
32
  - !ruby/object:Gem::Dependency
33
- version_requirements: !ruby/object:Gem::Requirement
33
+ name: pry
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
34
36
  requirements:
35
37
  - - ~>
36
38
  - !ruby/object:Gem::Version
37
39
  version: 0.9.8
38
- none: false
39
- name: pry
40
40
  type: :development
41
41
  prerelease: false
42
- requirement: !ruby/object:Gem::Requirement
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
43
44
  requirements:
44
45
  - - ~>
45
46
  - !ruby/object:Gem::Version
46
47
  version: 0.9.8
47
- none: false
48
48
  - !ruby/object:Gem::Dependency
49
- version_requirements: !ruby/object:Gem::Requirement
49
+ name: mocha
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
50
52
  requirements:
51
53
  - - ! '>='
52
54
  - !ruby/object:Gem::Version
53
55
  version: '0'
54
- none: false
55
- name: mocha
56
56
  type: :development
57
57
  prerelease: false
58
- requirement: !ruby/object:Gem::Requirement
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
59
60
  requirements:
60
61
  - - ! '>='
61
62
  - !ruby/object:Gem::Version
62
63
  version: '0'
63
- none: false
64
64
  - !ruby/object:Gem::Dependency
65
- version_requirements: !ruby/object:Gem::Requirement
65
+ name: bourne
66
+ requirement: !ruby/object:Gem::Requirement
67
+ none: false
66
68
  requirements:
67
69
  - - ! '>='
68
70
  - !ruby/object:Gem::Version
69
71
  version: '0'
70
- none: false
71
- name: bourne
72
72
  type: :development
73
73
  prerelease: false
74
- requirement: !ruby/object:Gem::Requirement
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
75
76
  requirements:
76
77
  - - ! '>='
77
78
  - !ruby/object:Gem::Version
78
79
  version: '0'
79
- none: false
80
80
  - !ruby/object:Gem::Dependency
81
- version_requirements: !ruby/object:Gem::Requirement
81
+ name: rake
82
+ requirement: !ruby/object:Gem::Requirement
83
+ none: false
82
84
  requirements:
83
85
  - - ! '>='
84
86
  - !ruby/object:Gem::Version
85
87
  version: '0'
86
- none: false
87
- name: rake
88
88
  type: :development
89
89
  prerelease: false
90
- requirement: !ruby/object:Gem::Requirement
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
91
92
  requirements:
92
93
  - - ! '>='
93
94
  - !ruby/object:Gem::Version
94
95
  version: '0'
95
- none: false
96
96
  description: ! " Grocer interfaces with the Apple Push\n
97
97
  \ Notification Service to send push\n notifications
98
98
  to iOS devices and collect\n notification feedback via
@@ -117,16 +117,12 @@ files:
117
117
  - Rakefile
118
118
  - grocer.gemspec
119
119
  - lib/grocer.rb
120
- - lib/grocer/certificate_expired_error.rb
121
120
  - lib/grocer/connection.rb
122
121
  - lib/grocer/extensions/deep_symbolize_keys.rb
123
122
  - lib/grocer/failed_delivery_attempt.rb
124
123
  - lib/grocer/feedback.rb
125
124
  - lib/grocer/feedback_connection.rb
126
- - lib/grocer/invalid_format_error.rb
127
- - lib/grocer/no_gateway_error.rb
128
- - lib/grocer/no_payload_error.rb
129
- - lib/grocer/no_port_error.rb
125
+ - lib/grocer/newsstand_notification.rb
130
126
  - lib/grocer/notification.rb
131
127
  - lib/grocer/notification_reader.rb
132
128
  - lib/grocer/passbook_notification.rb
@@ -147,6 +143,7 @@ files:
147
143
  - spec/grocer/failed_delivery_attempt_spec.rb
148
144
  - spec/grocer/feedback_connection_spec.rb
149
145
  - spec/grocer/feedback_spec.rb
146
+ - spec/grocer/newsstand_notification_spec.rb
150
147
  - spec/grocer/notification_reader_spec.rb
151
148
  - spec/grocer/notification_spec.rb
152
149
  - spec/grocer/passbook_notification_spec.rb
@@ -166,17 +163,23 @@ rdoc_options: []
166
163
  require_paths:
167
164
  - lib
168
165
  required_ruby_version: !ruby/object:Gem::Requirement
166
+ none: false
169
167
  requirements:
170
168
  - - ! '>='
171
169
  - !ruby/object:Gem::Version
172
170
  version: '0'
173
- none: false
171
+ segments:
172
+ - 0
173
+ hash: -399715243168588084
174
174
  required_rubygems_version: !ruby/object:Gem::Requirement
175
+ none: false
175
176
  requirements:
176
177
  - - ! '>='
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
- none: false
180
+ segments:
181
+ - 0
182
+ hash: -399715243168588084
180
183
  requirements: []
181
184
  rubyforge_project:
182
185
  rubygems_version: 1.8.23
@@ -192,6 +195,7 @@ test_files:
192
195
  - spec/grocer/failed_delivery_attempt_spec.rb
193
196
  - spec/grocer/feedback_connection_spec.rb
194
197
  - spec/grocer/feedback_spec.rb
198
+ - spec/grocer/newsstand_notification_spec.rb
195
199
  - spec/grocer/notification_reader_spec.rb
196
200
  - spec/grocer/notification_spec.rb
197
201
  - spec/grocer/passbook_notification_spec.rb
@@ -203,4 +207,3 @@ test_files:
203
207
  - spec/grocer/ssl_server_spec.rb
204
208
  - spec/grocer_spec.rb
205
209
  - spec/spec_helper.rb
206
- has_rdoc:
@@ -1,3 +0,0 @@
1
- module Grocer
2
- CertificateExpiredError = Module.new
3
- end
@@ -1,4 +0,0 @@
1
- module Grocer
2
- class InvalidFormatError < StandardError
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module Grocer
2
- class NoGatewayError < StandardError
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module Grocer
2
- class NoPayloadError < StandardError
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module Grocer
2
- class NoPortError < StandardError
3
- end
4
- end