houston 0.2.4 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +28 -8
- data/LICENSE +1 -1
- data/README.md +123 -24
- data/Rakefile +4 -8
- data/bin/apn +70 -5
- data/coverage/assets/0.7.1/application.css +1110 -0
- data/coverage/assets/0.7.1/application.js +626 -0
- data/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/coverage/assets/0.7.1/loading.gif +0 -0
- data/coverage/assets/0.7.1/magnify.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/assets/0.8.0/application.css +799 -0
- data/coverage/assets/0.8.0/application.js +1559 -0
- data/coverage/assets/0.8.0/colorbox/border.png +0 -0
- data/coverage/assets/0.8.0/colorbox/controls.png +0 -0
- data/coverage/assets/0.8.0/colorbox/loading.gif +0 -0
- data/coverage/assets/0.8.0/colorbox/loading_background.png +0 -0
- data/coverage/assets/0.8.0/favicon_green.png +0 -0
- data/coverage/assets/0.8.0/favicon_red.png +0 -0
- data/coverage/assets/0.8.0/favicon_yellow.png +0 -0
- data/coverage/assets/0.8.0/loading.gif +0 -0
- data/coverage/assets/0.8.0/magnify.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/index.html +1810 -0
- data/houston-2.2.2.gem +0 -0
- data/houston-2.2.3.gem +0 -0
- data/houston.gemspec +17 -16
- data/lib/houston/client.rb +39 -9
- data/lib/houston/connection.rb +3 -3
- data/lib/houston/notification.rb +87 -6
- data/lib/houston/version.rb +3 -0
- data/lib/houston.rb +1 -4
- data/spec/client_spec.rb +100 -0
- data/spec/notification_spec.rb +315 -0
- data/spec/spec_helper.rb +31 -0
- metadata +119 -32
- data/apple_push_notification_production.pem +0 -136
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfbcea0735347e252416d11e2ae57e506ba71ffd
|
4
|
+
data.tar.gz: 7e9b26d48fd1ad27fe068ec0f3a7cfe2c2f307d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6104dd4c1221816bc7e8f779c508c0fed230210d8c5b387d804e9d1120d83b88785ccfa398410190be4eb34ffa28ead665f9c836f76cb6224661c64924fb529
|
7
|
+
data.tar.gz: 301d4d835c5de3497aa5ed4330f3bb4207e0a0f54849a7747f6bd6927c414b1cff15700df430f7b3a91a7a68ad63720ffb49dd14f7beba22c23df7ff9c153176
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,24 +1,44 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
houston (
|
4
|
+
houston (2.2.3)
|
5
5
|
commander (~> 4.1)
|
6
6
|
json
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
commander (4.
|
11
|
+
commander (4.2.0)
|
12
12
|
highline (~> 1.6.11)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
docile (1.1.5)
|
15
|
+
highline (1.6.21)
|
16
|
+
json (1.8.1)
|
17
|
+
multi_json (1.10.1)
|
18
|
+
rake (10.3.2)
|
19
|
+
rspec (3.0.0)
|
20
|
+
rspec-core (~> 3.0.0)
|
21
|
+
rspec-expectations (~> 3.0.0)
|
22
|
+
rspec-mocks (~> 3.0.0)
|
23
|
+
rspec-core (3.0.3)
|
24
|
+
rspec-support (~> 3.0.0)
|
25
|
+
rspec-expectations (3.0.3)
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
+
rspec-support (~> 3.0.0)
|
28
|
+
rspec-mocks (3.0.3)
|
29
|
+
rspec-support (~> 3.0.0)
|
30
|
+
rspec-support (3.0.3)
|
31
|
+
simplecov (0.9.0)
|
32
|
+
docile (~> 1.1.0)
|
33
|
+
multi_json
|
34
|
+
simplecov-html (~> 0.8.0)
|
35
|
+
simplecov-html (0.8.0)
|
17
36
|
|
18
37
|
PLATFORMS
|
19
38
|
ruby
|
20
39
|
|
21
40
|
DEPENDENCIES
|
22
41
|
houston!
|
23
|
-
rake
|
24
|
-
rspec (~> 0
|
42
|
+
rake
|
43
|
+
rspec (~> 3.0)
|
44
|
+
simplecov
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2012 Mattt Thompson (http://mattt.me/)
|
1
|
+
Copyright (c) 2012–2015 Mattt Thompson (http://mattt.me/)
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
![Houston](https://raw.github.com/
|
1
|
+
![Houston](https://raw.github.com/nomad/nomad.github.io/assets/houston-banner.png)
|
2
2
|
|
3
3
|
Push Notifications don't have to be difficult.
|
4
4
|
|
5
5
|
Houston is a simple gem for sending Apple Push Notifications. Pass your credentials, construct your message, and send it.
|
6
6
|
|
7
|
-
In a production application, you will probably want to schedule or queue notifications into a background job. Whether you're using [queue_classic](https://github.com/ryandotsmith/queue_classic), [resque](https://github.com/
|
7
|
+
In a production application, you will probably want to schedule or queue notifications into a background job. Whether you're using [queue_classic](https://github.com/ryandotsmith/queue_classic), [resque](https://github.com/resque/resque), or rolling you own infrastructure, integrating Houston couldn't be simpler.
|
8
8
|
|
9
|
-
Another caveat is that Houston doesn't manage device tokens for you. For that, you should check out [Helios](http://helios.
|
9
|
+
Another caveat is that Houston doesn't manage device tokens for you. For that, you should check out [Helios](http://github.com/helios-framework/helios).
|
10
10
|
|
11
|
-
> Houston
|
11
|
+
> Houston is named for [Houston, TX](http://en.wikipedia.org/wiki/Houston), the metonymical home of [NASA's Johnson Space Center](http://en.wikipedia.org/wiki/Lyndon_B._Johnson_Space_Center), as in _Houston, We Have Liftoff!_.
|
12
12
|
|
13
|
-
> It's part of a series of world-class command-line utilities for iOS development, which includes [Cupertino](https://github.com/
|
13
|
+
> It's part of a series of world-class command-line utilities for iOS development, which includes [Cupertino](https://github.com/nomad/cupertino) (Apple Dev Center management), [Shenzhen](https://github.com/nomad/shenzhen) (Building & Distribution), [Venice](https://github.com/nomad/venice) (In-App Purchase Receipt Verification), [Dubai](https://github.com/nomad/dubai) (Passbook pass generation), and [Nashville](https://github.com/nomad/nashville) (iTunes Store API).
|
14
14
|
|
15
|
-
> This project is also part of a series of open source libraries covering the mission-critical aspects of an iOS app's infrastructure. Be sure to check out its sister projects: [GroundControl](https://github.com/mattt/GroundControl), [SkyLab](https://github.com/mattt/SkyLab), [houston](https://github.com/
|
15
|
+
> This project is also part of a series of open source libraries covering the mission-critical aspects of an iOS app's infrastructure. Be sure to check out its sister projects: [GroundControl](https://github.com/mattt/GroundControl), [SkyLab](https://github.com/mattt/SkyLab), [houston](https://github.com/nomad/houston), and [Orbiter](https://github.com/mattt/Orbiter).
|
16
16
|
|
17
17
|
## Installation
|
18
18
|
|
@@ -21,56 +21,133 @@ Another caveat is that Houston doesn't manage device tokens for you. For that, y
|
|
21
21
|
## Usage
|
22
22
|
|
23
23
|
```ruby
|
24
|
+
require 'houston'
|
25
|
+
|
24
26
|
# Environment variables are automatically read, or can be overridden by any specified options. You can also
|
25
27
|
# conveniently use `Houston::Client.development` or `Houston::Client.production`.
|
26
28
|
APN = Houston::Client.development
|
27
|
-
APN.certificate = File.read(
|
29
|
+
APN.certificate = File.read('/path/to/apple_push_notification.pem')
|
28
30
|
|
29
31
|
# An example of the token sent back when a device registers for notifications
|
30
|
-
token =
|
32
|
+
token = '<ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969>'
|
31
33
|
|
32
34
|
# Create a notification that alerts a message to the user, plays a sound, and sets the badge on the app
|
33
35
|
notification = Houston::Notification.new(device: token)
|
34
|
-
notification.alert =
|
36
|
+
notification.alert = 'Hello, World!'
|
35
37
|
|
36
|
-
# Notifications can also change the badge count, have a custom sound, indicate available Newsstand content, or pass along arbitrary data.
|
38
|
+
# Notifications can also change the badge count, have a custom sound, have a category identifier, indicate available Newsstand content, or pass along arbitrary data.
|
37
39
|
notification.badge = 57
|
38
|
-
notification.sound =
|
40
|
+
notification.sound = 'sosumi.aiff'
|
41
|
+
notification.category = 'INVITE_CATEGORY'
|
39
42
|
notification.content_available = true
|
40
|
-
notification.
|
43
|
+
notification.mutable_content = true
|
44
|
+
notification.custom_data = { foo: 'bar' }
|
45
|
+
notification.url_args = %w[boarding A998]
|
46
|
+
notification.thread_id = 'notify-team-ios'
|
41
47
|
|
42
48
|
# And... sent! That's all it takes.
|
43
49
|
APN.push(notification)
|
44
50
|
```
|
45
51
|
|
52
|
+
To generate a `.pem` file, it is recommended to use [fastlane pem](https://fastlane.tools/pem), which completely automates the process of creating the certificate.
|
53
|
+
|
54
|
+
## Configuration
|
55
|
+
|
56
|
+
Houston will attempt to load configuration data from environment variables, if they're present. The following variables will be used.
|
57
|
+
|
58
|
+
| Environment Variable | Description |
|
59
|
+
| --- | --- |
|
60
|
+
| `APN_GATEWAY_URI` | The base URI for the APNS service to use. If left blank, will use the default APNS Production Gateway URI. |
|
61
|
+
| `APN_FEEDBACK_URI` | The base URI for the APNS feedback service to use. If left blank, will use the default APNS Production Feedback URI. |
|
62
|
+
| `APN_CERTIFICATE` | The file path to a valid APNS push certificate in `.pem` format (see "[Converting Your Certificate](#converting-your-certificate)" below). |
|
63
|
+
| `APN_CERTIFICATE_DATA` | The contents of a valid APNS push certificate in `.pem` format (see "[Converting Your Certificate](#converting-your-certificate)" below); used in lieu of `APN_CERTIFICATE` if that variable is not provided. |
|
64
|
+
| `APN_CERTIFICATE_PASSPHRASE` | If the APNS certificate is protected by a passphrase, provide this variable to use when decrypting it. |
|
65
|
+
| `APN_TIMEOUT` | The timeout used when communicating with APNS. If not provided, the default of 0.5 seconds is used. |
|
66
|
+
|
67
|
+
### Error Handling
|
68
|
+
|
69
|
+
If an error occurs when sending a particular notification, its `error` attribute will be populated:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
puts "Error: #{notification.error}." if notification.error
|
73
|
+
```
|
74
|
+
|
75
|
+
### Silent Notifications
|
76
|
+
|
77
|
+
To send a silent push notification, set `sound` to an empty string (`''`):
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
Houston::Notification.new(sound: '', content_available: true)
|
81
|
+
```
|
82
|
+
|
83
|
+
### Mutable Notifications
|
84
|
+
|
85
|
+
To send a mutable push notification (supported by iOS 10+), set `mutable_content` to `true`:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
Houston::Notification.new(mutable_content: true)
|
89
|
+
```
|
90
|
+
|
46
91
|
### Persistent Connections
|
47
92
|
|
48
93
|
If you want to manage your own persistent connection to Apple push services, such as for background workers, here's how to do it:
|
49
94
|
|
50
95
|
```ruby
|
51
|
-
certificate = File.read(
|
52
|
-
passphrase =
|
53
|
-
connection = Houston::Connection.new(APPLE_DEVELOPMENT_GATEWAY_URI, certificate, passphrase)
|
96
|
+
certificate = File.read('/path/to/apple_push_notification.pem')
|
97
|
+
passphrase = '...'
|
98
|
+
connection = Houston::Connection.new(Houston::APPLE_DEVELOPMENT_GATEWAY_URI, certificate, passphrase)
|
54
99
|
connection.open
|
55
100
|
|
56
101
|
notification = Houston::Notification.new(device: token)
|
57
|
-
notification.alert =
|
102
|
+
notification.alert = 'Hello, World!'
|
58
103
|
connection.write(notification.message)
|
59
104
|
|
60
105
|
connection.close
|
61
106
|
```
|
62
107
|
|
108
|
+
### Feedback Service
|
109
|
+
|
110
|
+
Apple provides a feedback service to query for unregistered device tokens, these are devices that have failed to receive a push notification and should be removed from your application. You should periodically query for and remove these devices, Apple audits providers to ensure they are removing unregistered devices. To obtain the list of unregistered device tokens:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
Houston::Client.development.devices
|
114
|
+
```
|
115
|
+
|
116
|
+
In practice, you'll use a reference to instance of the APN object you create (see the Usage section). Here's a rake job that marks device tokens as invalid based on the feedback service from Apple. This example assumes devices are tracked in a model called Device (i.e. `User.devices`).
|
117
|
+
|
118
|
+
In `lib/tasks/notifications.rake`:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
namespace :notifications do
|
122
|
+
task device_token_feedback: [:environment] do
|
123
|
+
APN.unregistered_devices.each do |device_hash|
|
124
|
+
# Format: { token: token, timestamp: timestamp }
|
125
|
+
device = Device.find_by(token: device_hash[:token])
|
126
|
+
next unless device.present?
|
127
|
+
# Remove device token
|
128
|
+
device.update_attribute(:device_token, nil)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
## Versioning
|
135
|
+
|
136
|
+
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.
|
137
|
+
|
63
138
|
## Command Line Tool
|
64
139
|
|
65
140
|
Houston also comes with the `apn` binary, which provides a convenient way to test notifications from the command line.
|
66
141
|
|
67
|
-
$ apn push "<token>" -c /path/to/apple_push_notification.pem -m "Hello from the command line!"
|
142
|
+
$ apn push "<token>" -c /path/to/apple_push_notification.pem -m "Hello from the command line! "
|
68
143
|
|
69
144
|
## Enabling Push Notifications on iOS
|
70
145
|
|
71
|
-
###
|
146
|
+
### Objective-C
|
72
147
|
|
73
148
|
```objective-c
|
149
|
+
// AppDelegate.m
|
150
|
+
|
74
151
|
- (void)applicationDidFinishLaunching:(UIApplication *)application {
|
75
152
|
// ...
|
76
153
|
|
@@ -92,6 +169,24 @@ didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
|
92
169
|
}
|
93
170
|
```
|
94
171
|
|
172
|
+
### Swift
|
173
|
+
```swift
|
174
|
+
// AppDelegate.swift
|
175
|
+
|
176
|
+
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
|
177
|
+
application.registerForRemoteNotifications()
|
178
|
+
return true
|
179
|
+
}
|
180
|
+
|
181
|
+
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
182
|
+
// Register the device token with a webservice
|
183
|
+
}
|
184
|
+
|
185
|
+
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
|
186
|
+
print("error \(error)")
|
187
|
+
}
|
188
|
+
```
|
189
|
+
|
95
190
|
## Converting Your Certificate
|
96
191
|
|
97
192
|
> These instructions come from the [APN on Rails](https://github.com/PRX/apn_on_rails) project, which is another great option for sending push notifications.
|
@@ -103,17 +198,21 @@ and the apple certificate as p12 files. Here is a quick walkthrough on how to do
|
|
103
198
|
2. Right click and choose `Export 2 items…`.
|
104
199
|
3. Choose the p12 format from the drop down and name it `cert.p12`.
|
105
200
|
|
106
|
-
Now
|
201
|
+
Now convert the p12 file to a pem file:
|
202
|
+
|
203
|
+
**Unencrypted private key (do not store this certificate in version control)**
|
107
204
|
|
108
205
|
$ openssl pkcs12 -in cert.p12 -out apple_push_notification.pem -nodes -clcerts
|
109
206
|
|
110
|
-
|
207
|
+
**Encrypted private key**
|
208
|
+
|
209
|
+
$ openssl pkcs12 -in cert.p12 -out apple_push_notification.pem -aes256 -clcerts
|
210
|
+
|
211
|
+
You'll have to specify the password in the `APN_CERTIFICATE_PASSPHRASE` environment variable if you use the encrypted option.
|
111
212
|
|
112
|
-
|
213
|
+
## Creator
|
113
214
|
|
114
|
-
|
115
|
-
- http://twitter.com/mattt
|
116
|
-
- m@mattt.me
|
215
|
+
Mattt Thompson ([@mattt](https://twitter.com/mattt))
|
117
216
|
|
118
217
|
## License
|
119
218
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
task :
|
7
|
-
|
8
|
-
file "#{gemspec.full_name}.gem" => gemspec.files + ["houston.gemspec"] do
|
9
|
-
system "gem build houston.gemspec"
|
10
|
-
end
|
6
|
+
task default: :spec
|
data/bin/apn
CHANGED
@@ -25,6 +25,7 @@ command :push do |c|
|
|
25
25
|
c.option '-m', '--alert ALERT', 'Body of the alert to send in the push notification'
|
26
26
|
c.option '-b', '--badge NUMBER', 'Badge number to set with the push notification'
|
27
27
|
c.option '-s', '--sound SOUND', 'Sound to play with the notification'
|
28
|
+
c.option '-y', '--category CATEGORY', 'Category of notification'
|
28
29
|
c.option '-n', '--[no]-newsstand', 'Indicates content available for Newsstand'
|
29
30
|
c.option '-d', '--data KEY=VALUE', Array, 'Passes custom data to payload (as comma-delimited "key=value" declarations)'
|
30
31
|
c.option '-P', '--payload PAYLOAD', 'JSON payload for notifications'
|
@@ -42,12 +43,13 @@ command :push do |c|
|
|
42
43
|
say_error "Missing certificate file option (-c /path/to/certificate.pem)" and abort unless @certificate
|
43
44
|
say_error "Could not find certificate file '#{@certificate}'" and abort unless File.exists?(@certificate)
|
44
45
|
|
45
|
-
@passphrase = options.passphrase ? password :
|
46
|
+
@passphrase = options.passphrase ? password : nil
|
46
47
|
|
47
48
|
@alert = options.alert
|
48
49
|
@badge = options.badge.nil? ? nil : options.badge.to_i
|
49
50
|
@sound = options.sound
|
50
|
-
@
|
51
|
+
@category = options.category
|
52
|
+
@content_available = !!options.newsstand
|
51
53
|
|
52
54
|
if options.payload
|
53
55
|
begin
|
@@ -63,7 +65,7 @@ command :push do |c|
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
66
|
-
unless @alert or @badge or @
|
68
|
+
unless @alert or @badge or @content_available or @data
|
67
69
|
placeholder = "Enter your alert message"
|
68
70
|
@alert = ask_editor placeholder
|
69
71
|
say_error "Payload contents required" and abort if @alert.nil? or @alert == placeholder
|
@@ -76,21 +78,84 @@ command :push do |c|
|
|
76
78
|
notification.alert = @alert if @alert
|
77
79
|
notification.badge = @badge if @badge
|
78
80
|
notification.sound = @sound if @sound
|
81
|
+
notification.category = @category if @category
|
79
82
|
notification.content_available = @content_available if @content_available
|
80
83
|
|
81
84
|
@notifications << notification
|
82
85
|
end
|
83
86
|
|
84
|
-
client = @environment == :production ? Houston::Client.production : Houston::Client.development
|
87
|
+
client = (@environment == :production) ? Houston::Client.production : Houston::Client.development
|
85
88
|
client.certificate = File.read(@certificate)
|
86
89
|
client.passphrase = @passphrase
|
87
90
|
|
88
91
|
begin
|
89
92
|
client.push(*@notifications)
|
93
|
+
|
94
|
+
sent, unsent = @notifications.partition{|notification| notification.sent?}
|
95
|
+
|
96
|
+
if sent.any?
|
97
|
+
case sent.length
|
98
|
+
when 1
|
99
|
+
say_ok "1 push notification sent successfully"
|
100
|
+
else
|
101
|
+
say_ok "#{sent.length} push notifications sent successfully"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
if unsent.any?
|
106
|
+
tokens = unsent.map{|notification| "\n - #{notification.token}"}.join
|
107
|
+
|
108
|
+
case unsent.length
|
109
|
+
when 1
|
110
|
+
say_error "1 push notification unsuccessful (#{tokens})"
|
111
|
+
else
|
112
|
+
say_error "#{unsent.length} push notifications unsuccessful (#{tokens})"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
90
116
|
rescue => message
|
91
117
|
say_error "Exception sending notification: #{message}" and abort
|
92
118
|
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
command :feedback do |c|
|
123
|
+
c.syntax = 'apn feedback [...]'
|
124
|
+
c.summary = 'Queries the APN Feedback Service for failed device tokens.'
|
125
|
+
c.description = ''
|
126
|
+
|
127
|
+
c.example 'description', 'apn feedback -c /path/to/apple_push_certificate.pem'
|
128
|
+
c.option '-c', '--certificate CERTIFICATE', 'Path to certificate (.pem) file'
|
129
|
+
c.option '-e', '--environment ENV', [:production, :development], 'Environment to send push notification (production or development (default))'
|
130
|
+
c.option '-p', '--[no]-passphrase', 'Prompt for a certificate passphrase'
|
131
|
+
|
132
|
+
c.action do |args, options|
|
133
|
+
|
134
|
+
@environment = options.environment.downcase.to_sym rescue :development
|
135
|
+
say_error "Invalid environment,'#{@environment}' (should be either :development or :production)" and abort unless [:development, :production].include?(@environment)
|
136
|
+
|
137
|
+
@certificate = options.certificate
|
138
|
+
say_error "Missing certificate file option (-c /path/to/certificate.pem)" and abort unless @certificate
|
139
|
+
say_error "Could not find certificate file '#{@certificate}'" and abort unless File.exists?(@certificate)
|
140
|
+
|
141
|
+
@passphrase = options.passphrase ? password : nil
|
142
|
+
|
143
|
+
client = (@environment == :production) ? Houston::Client.production : Houston::Client.development
|
144
|
+
client.certificate = File.read(@certificate)
|
145
|
+
client.passphrase = @passphrase
|
146
|
+
|
147
|
+
begin
|
148
|
+
feedbackDevices = client.unregistered_devices
|
149
|
+
|
150
|
+
if feedbackDevices.any? && feedbackDevices.length > 0
|
151
|
+
puts feedbackDevices.to_json
|
152
|
+
else
|
153
|
+
say_ok "No feedback available"
|
154
|
+
end
|
155
|
+
|
156
|
+
rescue => message
|
157
|
+
say_error "Exception querying feedback: #{message}" and abort
|
158
|
+
end
|
93
159
|
|
94
|
-
say_ok "Push notifications successfully sent"
|
95
160
|
end
|
96
161
|
end
|