houston 0.2.4 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +28 -8
  4. data/LICENSE +1 -1
  5. data/README.md +123 -24
  6. data/Rakefile +4 -8
  7. data/bin/apn +70 -5
  8. data/coverage/assets/0.7.1/application.css +1110 -0
  9. data/coverage/assets/0.7.1/application.js +626 -0
  10. data/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  11. data/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  12. data/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  13. data/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  14. data/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  15. data/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  16. data/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  17. data/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  18. data/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  19. data/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  20. data/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  21. data/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  22. data/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  23. data/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  24. data/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  25. data/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  26. data/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  27. data/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  28. data/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  29. data/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  30. data/coverage/assets/0.7.1/favicon_green.png +0 -0
  31. data/coverage/assets/0.7.1/favicon_red.png +0 -0
  32. data/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  33. data/coverage/assets/0.7.1/loading.gif +0 -0
  34. data/coverage/assets/0.7.1/magnify.png +0 -0
  35. data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  36. data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  37. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  38. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  39. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  40. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  41. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  42. data/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  43. data/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  44. data/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  45. data/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  46. data/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  47. data/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  48. data/coverage/assets/0.8.0/application.css +799 -0
  49. data/coverage/assets/0.8.0/application.js +1559 -0
  50. data/coverage/assets/0.8.0/colorbox/border.png +0 -0
  51. data/coverage/assets/0.8.0/colorbox/controls.png +0 -0
  52. data/coverage/assets/0.8.0/colorbox/loading.gif +0 -0
  53. data/coverage/assets/0.8.0/colorbox/loading_background.png +0 -0
  54. data/coverage/assets/0.8.0/favicon_green.png +0 -0
  55. data/coverage/assets/0.8.0/favicon_red.png +0 -0
  56. data/coverage/assets/0.8.0/favicon_yellow.png +0 -0
  57. data/coverage/assets/0.8.0/loading.gif +0 -0
  58. data/coverage/assets/0.8.0/magnify.png +0 -0
  59. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  60. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  61. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  62. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  63. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  64. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  65. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  66. data/coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  67. data/coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  68. data/coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  69. data/coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  70. data/coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  71. data/coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  72. data/coverage/index.html +1810 -0
  73. data/houston-2.2.2.gem +0 -0
  74. data/houston-2.2.3.gem +0 -0
  75. data/houston.gemspec +17 -16
  76. data/lib/houston/client.rb +39 -9
  77. data/lib/houston/connection.rb +3 -3
  78. data/lib/houston/notification.rb +87 -6
  79. data/lib/houston/version.rb +3 -0
  80. data/lib/houston.rb +1 -4
  81. data/spec/client_spec.rb +100 -0
  82. data/spec/notification_spec.rb +315 -0
  83. data/spec/spec_helper.rb +31 -0
  84. metadata +119 -32
  85. data/apple_push_notification_production.pem +0 -136
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e5aecadd372ded4ba46d1ae9eca31fbcab168644
4
- data.tar.gz: f39b14600dbfe3610cc3b6d6024b5cdee0941471
3
+ metadata.gz: cfbcea0735347e252416d11e2ae57e506ba71ffd
4
+ data.tar.gz: 7e9b26d48fd1ad27fe068ec0f3a7cfe2c2f307d9
5
5
  SHA512:
6
- metadata.gz: 22539e7ac680df2138dc00a1e1688dbeb1e7c7c0973687f6c1bad64b1e64676cf7b8ecf88e3b209fcc49f743b7acc778c23d5a8e470d72d877815d86e7a55c3a
7
- data.tar.gz: f95928800e51dda1313e1df4aeec8da7a1b0fb8543e6d124e7ff162dd01f7dfbd0307ede39ea56b6eff4c3ae2c2677dab98e891cbd52d00517a632506ece07cf
6
+ metadata.gz: f6104dd4c1221816bc7e8f779c508c0fed230210d8c5b387d804e9d1120d83b88785ccfa398410190be4eb34ffa28ead665f9c836f76cb6224661c64924fb529
7
+ data.tar.gz: 301d4d835c5de3497aa5ed4330f3bb4207e0a0f54849a7747f6bd6927c414b1cff15700df430f7b3a91a7a68ad63720ffb49dd14f7beba22c23df7ff9c153176
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/Gemfile.lock CHANGED
@@ -1,24 +1,44 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- houston (0.2.4)
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.1.3)
11
+ commander (4.2.0)
12
12
  highline (~> 1.6.11)
13
- highline (1.6.19)
14
- json (1.8.0)
15
- rake (0.9.2.2)
16
- rspec (0.6.4)
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 (~> 0.9)
24
- rspec (~> 0.6)
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/mattt/nomad-cli.com/assets/houston-banner.png)
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/defunkt/resque), or rolling you own infrastructure, integrating Houston couldn't be simpler.
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.io)
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's 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!_.
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/mattt/cupertino) (Apple Dev Center management), [Shenzhen](https://github.com/mattt/shenzhen) (Building & Distribution), [Venice](https://github.com/mattt/venice) (In-App Purchase Receipt Verification), and [Dubai](https://github.com/mattt/dubai) (Passbook pass generation).
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/mattt/houston), and [Orbiter](https://github.com/mattt/Orbiter).
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("/path/to/apple_push_notification.pem")
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 = "<ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b5969>"
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 = "Hello, World!"
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 = "sosumi.aiff"
40
+ notification.sound = 'sosumi.aiff'
41
+ notification.category = 'INVITE_CATEGORY'
39
42
  notification.content_available = true
40
- notification.custom_data = {foo: "bar"}
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("/path/to/apple_push_notification.pem")
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 = "Hello, World!"
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
- ### AppDelegate.m
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 covert the p12 file to a pem file:
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
- ## Contact
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
- Mattt Thompson
213
+ ## Creator
113
214
 
114
- - http://github.com/mattt
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 "bundler"
2
- Bundler.setup
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
- gemspec = eval(File.read("houston.gemspec"))
4
+ RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :build => "#{gemspec.full_name}.gem"
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
- @content_available = options.newsstand
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 @newsstand or @data
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