grocer 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.travis.yml +5 -5
- data/CHANGELOG.md +5 -0
- data/README.md +52 -9
- data/grocer.gemspec +1 -1
- data/images/Downloading_the_Push_Notification_Certificate.png +0 -0
- data/images/Exporting_the_certificate_and_private_key.png +0 -0
- data/images/Selecting_both_the_certificate_and_private_key.png +0 -0
- data/lib/grocer/notification.rb +13 -1
- data/lib/grocer/version.rb +1 -1
- data/spec/grocer/notification_spec.rb +10 -0
- metadata +29 -31
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Y2E3NDU5NjNkYjQyYTAyMjUyM2RkOWVhNTljNjNiYWVlMDU5OTkxNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZDRlNTFjOTRhOGI4NzAyNzU3YjEwZjhmNzZhNTcyMmM0Y2QxZTQ3MA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGQ0ZDc5ZWFiOGI1NGE2MjQ4NzQ5ZWE3YzJmYjYxNTcyMDFhNTQyMWQ1Y2Y5
|
10
|
+
YzI4NTEwNGYyN2ViMDFjMWNiYWQ0NGRiOGYzM2Y1YTA4MTVlYzY1MTI2YTU5
|
11
|
+
MjM2M2U4MzQ2Yzc2MDEyOWQ2MDQ4ZDNkOWJkZjZmNzcxYzkyOTE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MTE4YzBiODQ2M2NlNmE0MTJmMzY1NGE2OTBmODc4ZTY5NDY3OGE2MjkxMzMz
|
14
|
+
YWQyMjcwOTM2NDBlYjRkMmFlOWRmZjk4MDRmMjllZmRlYzU0YjQ3ZGJlY2I5
|
15
|
+
MGYwN2QyY2VmZmIwYThhNGI0ZjEyZWM2YTVkMDA4Y2U3OTExMTE=
|
data/.travis.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.1
|
3
|
+
- 2.3.1
|
4
|
+
- 2.2.5
|
5
|
+
- 2.1.10
|
4
6
|
- 2.0.0
|
5
|
-
-
|
6
|
-
- 1.9.2
|
7
|
-
- jruby-19mode
|
7
|
+
- jruby
|
8
8
|
- rbx
|
9
9
|
- rbx-2
|
10
|
-
|
10
|
+
sudo: false
|
11
11
|
addons:
|
12
12
|
code_climate:
|
13
13
|
repo_token: d414084f17a07a6b2d7da72eaa35d92281554a4266ab8d6246fee1f6c0c161b6
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Grocer
|
2
2
|
|
3
|
-
[![Gem Version](
|
4
|
-
[![Code Climate](
|
3
|
+
[![Gem Version](https://img.shields.io/gem/v/grocer.svg)](https://rubygems.org/gems/grocer)
|
4
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/grocer/grocer.svg)](https://codeclimate.com/github/grocer/grocer)
|
5
5
|
[![Build Status](https://img.shields.io/travis/grocer/grocer.svg)](https://travis-ci.org/grocer/grocer)
|
6
6
|
[![Dependency Status](https://img.shields.io/gemnasium/grocer/grocer.svg)](https://gemnasium.com/grocer/grocer)
|
7
7
|
|
@@ -9,12 +9,26 @@
|
|
9
9
|
Service](http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html)
|
10
10
|
to send push notifications to iOS devices.
|
11
11
|
|
12
|
-
There are other gems out there to do this, but **grocer** plans to be the
|
13
|
-
|
12
|
+
There are other gems out there to do this, but **grocer** plans to be the cleanest, most extensible, and friendliest.
|
13
|
+
|
14
|
+
## Important Note
|
15
|
+
|
16
|
+
iOS 9.0 (and subsequent versions) introduced a subtle change to the way push tokens are provided.
|
17
|
+
|
18
|
+
If you delete and then re-install an application the push token is invalidated and a new push token is generated.
|
19
|
+
This is important because the [Feedback service](#feedback) does not deliver the list of invalidated tokens quickly enough to prevent you from using the now invalidated token.
|
20
|
+
|
21
|
+
There is currently a [bug in grocer (#14)](https://github.com/grocer/grocer/issues/14) that will cause the APNS socket connect to hang up and fail to send subsequent notifications when one of these invalid tokens is used.
|
22
|
+
|
23
|
+
This bug combined with the change to push tokens in iOS results in varied reliability of push notification delivery.
|
24
|
+
This may or may not affect you, but if you are seeing a large amount of undelivered notifications - specifically when sending multiple messages in quick succession - it is likely that you are coming up against this.
|
25
|
+
|
26
|
+
We are looking for help [moving over to Apple's HTTP/2 notification API](https://github.com/grocer/grocer/issues/104) which should address this situation.
|
27
|
+
The current maintainer doesn't have time to do this work, but please leave us a note if you would like to drive the effort.
|
14
28
|
|
15
29
|
## Requirements
|
16
30
|
|
17
|
-
* Ruby/MRI 2.
|
31
|
+
* Ruby/MRI 2.x, JRuby 9000, Rubinius 2 & 3
|
18
32
|
|
19
33
|
## Installation
|
20
34
|
|
@@ -77,7 +91,8 @@ notification = Grocer::Notification.new(
|
|
77
91
|
sound: "siren.aiff", # optional
|
78
92
|
expiry: Time.now + 60*60, # optional; 0 is default, meaning the message is not stored
|
79
93
|
identifier: 1234, # optional; must be an integer
|
80
|
-
content_available: true
|
94
|
+
content_available: true, # optional; any truthy value will set 'content-available' to 1
|
95
|
+
mutable_content: true # optional; any truthy value will set 'mutable-content' to 1
|
81
96
|
)
|
82
97
|
|
83
98
|
pusher.push(notification) # return value is the number of bytes sent successfully
|
@@ -269,16 +284,19 @@ Login to the [iOS Provisioning Portal (App IDs)](https://developer.apple.com/ios
|
|
269
284
|
Configure the appropriate certificate for push notifications and download the
|
270
285
|
certificate:
|
271
286
|
|
272
|
-
![Downloading the Push Notification
|
287
|
+
![Downloading the Push Notification
|
288
|
+
Certificate](images/Downloading_the_Push_Notification_Certificate.png)
|
273
289
|
|
274
290
|
Open the file in Keychain Access, then expand the certificate to show both the
|
275
291
|
certificate *and* the private key. Command select so both are highlighted:
|
276
292
|
|
277
|
-
![Selecting both the certificate and private
|
293
|
+
![Selecting both the certificate and private
|
294
|
+
key](images/Selecting_both_the_certificate_and_private_key.png)
|
278
295
|
|
279
296
|
Control click and select to export the 2 items:
|
280
297
|
|
281
|
-
![Exporting the certificate and private
|
298
|
+
![Exporting the certificate and private
|
299
|
+
key](images/Exporting_the_certificate_and_private_key.png)
|
282
300
|
|
283
301
|
Save the items as a `.p12` file. Open a terminal window and run the following
|
284
302
|
command:
|
@@ -295,6 +313,31 @@ the private key. This will be the passphrase used when configuring
|
|
295
313
|
|
296
314
|
The `certificate.pem` file that is generated can be used with **grocer**.
|
297
315
|
|
316
|
+
### Alternative way to generate certificate file (no Mac OS X required)
|
317
|
+
|
318
|
+
Generate private key and unsigned certificate:
|
319
|
+
|
320
|
+
```bash
|
321
|
+
openssl req -nodes -newkey rsa:2048 -keyout push_private_key.pem -out push.csr
|
322
|
+
```
|
323
|
+
|
324
|
+
* Go to Apple Developer site and select [Add iOS Certificate](https://developer.apple.com/account/ios/certificate/certificateCreate.action).
|
325
|
+
* Choose *Apple Push Notification service SSL (Sandbox & Production)*.
|
326
|
+
* Upload the `push.csr` file during the *Generate your certificate* step.
|
327
|
+
* Download `aps.cer` on the next step.
|
328
|
+
|
329
|
+
Create `push.pem` file from `aps.cer` with following command:
|
330
|
+
|
331
|
+
```bash
|
332
|
+
openssl x509 -in aps.cer -inform der -out push.pem
|
333
|
+
```
|
334
|
+
|
335
|
+
Merge `push.pem` file and your private key into `certificate.pem`:
|
336
|
+
|
337
|
+
```bash
|
338
|
+
cat push.pem push_private_key.pem > certificate.pem
|
339
|
+
```
|
340
|
+
|
298
341
|
## Support Channels
|
299
342
|
|
300
343
|
[GitHub Issues](https://github.com/grocer/grocer/issues) and [Pull
|
data/grocer.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
|
|
25
25
|
gem.require_paths = ["lib"]
|
26
26
|
gem.version = Grocer::VERSION
|
27
27
|
|
28
|
-
gem.add_development_dependency 'rspec', '~> 3.
|
28
|
+
gem.add_development_dependency 'rspec', '~> 3.4'
|
29
29
|
gem.add_development_dependency 'pry', '~> 0.10.1'
|
30
30
|
gem.add_development_dependency 'mocha'
|
31
31
|
gem.add_development_dependency 'bourne'
|
Binary file
|
Binary file
|
Binary file
|
data/lib/grocer/notification.rb
CHANGED
@@ -5,9 +5,10 @@ module Grocer
|
|
5
5
|
class Notification
|
6
6
|
MAX_PAYLOAD_SIZE = 2048
|
7
7
|
CONTENT_AVAILABLE_INDICATOR = 1
|
8
|
+
MUTABLE_CONTENT_INDICATOR = 1
|
8
9
|
|
9
10
|
attr_accessor :identifier, :expiry, :device_token
|
10
|
-
attr_reader :alert, :badge, :custom, :sound, :content_available, :category
|
11
|
+
attr_reader :alert, :badge, :custom, :sound, :content_available, :mutable_content, :category
|
11
12
|
|
12
13
|
# Public: Initialize a new Grocer::Notification. You must specify at least an `alert` or `badge`.
|
13
14
|
#
|
@@ -19,6 +20,7 @@ module Grocer
|
|
19
20
|
# :expiry - The Integer representing UNIX epoch date sent to APNS as the notification expiry. (default: 0)
|
20
21
|
# :identifier - The arbitrary Integer sent to APNS to uniquely this notification. (default: 0)
|
21
22
|
# :content_available - The truthy or falsy value indicating the availability of new content for background fetch. (optional)
|
23
|
+
# :mutable_content - The truthy or falsy value indicating whether to have this notification be processed by a Notification Service Extension (since iOS 10) (optional)
|
22
24
|
# :category - The String to be sent as the category portion of the payload. (optional)
|
23
25
|
def initialize(payload = {})
|
24
26
|
@identifier = 0
|
@@ -76,6 +78,15 @@ module Grocer
|
|
76
78
|
!!content_available
|
77
79
|
end
|
78
80
|
|
81
|
+
def mutable_content=(mutable_content)
|
82
|
+
@mutable_content = MUTABLE_CONTENT_INDICATOR if mutable_content
|
83
|
+
@encoded_payload = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def mutable_content?
|
87
|
+
!!mutable_content
|
88
|
+
end
|
89
|
+
|
79
90
|
def validate_payload
|
80
91
|
fail NoPayloadError unless alert || badge || custom
|
81
92
|
fail PayloadTooLargeError if payload_too_large?
|
@@ -98,6 +109,7 @@ module Grocer
|
|
98
109
|
aps_hash[:badge] = badge if badge
|
99
110
|
aps_hash[:sound] = sound if sound
|
100
111
|
aps_hash[:'content-available'] = content_available if content_available?
|
112
|
+
aps_hash[:'mutable-content'] = mutable_content if mutable_content?
|
101
113
|
aps_hash[:category] = category if category
|
102
114
|
|
103
115
|
{ aps: aps_hash }.merge(custom || { })
|
data/lib/grocer/version.rb
CHANGED
@@ -60,6 +60,16 @@ describe Grocer::Notification do
|
|
60
60
|
expect(payload[:aps]).to_not have_key(:'content-available')
|
61
61
|
end
|
62
62
|
|
63
|
+
it 'encodes mutable-content as part of the payload if a truthy value is passed' do
|
64
|
+
notification.mutable_content = :foo
|
65
|
+
expect(payload[:aps][:'mutable-content']).to eq(1)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'does not encode mutable-content as part of the payload if a falsy value is passed' do
|
69
|
+
notification.mutable_content = false
|
70
|
+
expect(payload[:aps]).to_not have_key(:'mutable-content')
|
71
|
+
end
|
72
|
+
|
63
73
|
it "is valid" do
|
64
74
|
expect(notification.valid?).to be true
|
65
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grocer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Lindeman
|
@@ -10,88 +10,84 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-07-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '3.
|
21
|
+
version: '3.4'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '3.
|
28
|
+
version: '3.4'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: pry
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: 0.10.1
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- -
|
40
|
+
- - ~>
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 0.10.1
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: mocha
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - ! '>='
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '0'
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - ! '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '0'
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: bourne
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ! '>='
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: '0'
|
64
64
|
type: :development
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- -
|
68
|
+
- - ! '>='
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: rake
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
|
-
- -
|
82
|
+
- - ! '>='
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '0'
|
85
|
-
description:
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
There are other gems out there to do this,
|
93
|
-
but Grocer plans to be the cleanest, most
|
94
|
-
extensible, and friendliest.
|
85
|
+
description: ! " Grocer interfaces with the Apple Push\n
|
86
|
+
\ Notification Service to send push\n notifications
|
87
|
+
to iOS devices and collect\n notification feedback via
|
88
|
+
the Feedback\n Service.\n\n There
|
89
|
+
are other gems out there to do this,\n but Grocer plans
|
90
|
+
to be the cleanest, most\n extensible, and friendliest.\n"
|
95
91
|
email:
|
96
92
|
- alindeman@gmail.com
|
97
93
|
- steveharman@gmail.com
|
@@ -100,15 +96,18 @@ executables: []
|
|
100
96
|
extensions: []
|
101
97
|
extra_rdoc_files: []
|
102
98
|
files:
|
103
|
-
-
|
104
|
-
-
|
105
|
-
-
|
99
|
+
- .gitignore
|
100
|
+
- .rspec
|
101
|
+
- .travis.yml
|
106
102
|
- CHANGELOG.md
|
107
103
|
- Gemfile
|
108
104
|
- LICENSE
|
109
105
|
- README.md
|
110
106
|
- Rakefile
|
111
107
|
- grocer.gemspec
|
108
|
+
- images/Downloading_the_Push_Notification_Certificate.png
|
109
|
+
- images/Exporting_the_certificate_and_private_key.png
|
110
|
+
- images/Selecting_both_the_certificate_and_private_key.png
|
112
111
|
- lib/grocer.rb
|
113
112
|
- lib/grocer/connection.rb
|
114
113
|
- lib/grocer/error_response.rb
|
@@ -165,17 +164,17 @@ require_paths:
|
|
165
164
|
- lib
|
166
165
|
required_ruby_version: !ruby/object:Gem::Requirement
|
167
166
|
requirements:
|
168
|
-
- -
|
167
|
+
- - ! '>='
|
169
168
|
- !ruby/object:Gem::Version
|
170
169
|
version: '0'
|
171
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
171
|
requirements:
|
173
|
-
- -
|
172
|
+
- - ! '>='
|
174
173
|
- !ruby/object:Gem::Version
|
175
174
|
version: '0'
|
176
175
|
requirements: []
|
177
176
|
rubyforge_project:
|
178
|
-
rubygems_version: 2.
|
177
|
+
rubygems_version: 2.6.6
|
179
178
|
signing_key:
|
180
179
|
specification_version: 4
|
181
180
|
summary: Pushing Apple notifications since 2012.
|
@@ -204,4 +203,3 @@ test_files:
|
|
204
203
|
- spec/grocer_spec.rb
|
205
204
|
- spec/spec_helper.rb
|
206
205
|
- spec/support/notification_helpers.rb
|
207
|
-
has_rdoc:
|