forked from nomad-cli/houston
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapn
executable file
·161 lines (126 loc) · 6.03 KB
/
apn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env ruby
require 'commander/import'
require 'houston'
HighLine.track_eof = false # Fix for built-in Ruby
Signal.trap("INT") {} # Suppress backtrace when exiting command
program :version, Houston::VERSION
program :description, 'A command-line interface for sending push notifications'
program :help, 'Author', 'Mattt Thompson <m@mattt.me>'
program :help, 'Website', 'https://github.com/mattt'
program :help_formatter, :compact
default_command :help
command :push do |c|
c.syntax = 'apn push TOKEN [...]'
c.summary = 'Sends an Apple Push Notification to specified devices'
c.description = ''
c.example 'description', 'apn push <token> -m "Hello, World" -b 57 -s sosumi.aiff'
c.option '-m', '--alert ALERT', 'Body of the alert to send in the push notification'
c.option '-b', '--badge NUMBER', 'Badge number to set with the push notification'
c.option '-s', '--sound SOUND', 'Sound to play with the notification'
c.option '-y', '--category CATEGORY', 'Category of notification'
c.option '-n', '--[no]-newsstand', 'Indicates content available for Newsstand'
c.option '-d', '--data KEY=VALUE', Array, 'Passes custom data to payload (as comma-delimited "key=value" declarations)'
c.option '-P', '--payload PAYLOAD', 'JSON payload for notifications'
c.option '-e', '--environment ENV', [:production, :development], 'Environment to send push notification (production or development (default))'
c.option '-c', '--certificate CERTIFICATE', 'Path to certificate (.pem) file'
c.option '-p', '--[no]-passphrase', 'Prompt for a certificate passphrase'
c.action do |args, options|
say_error "One or more device tokens required" and abort if args.empty?
@environment = options.environment.downcase.to_sym rescue :development
say_error "Invalid environment,'#{@environment}' (should be either :development or :production)" and abort unless [:development, :production].include?(@environment)
@certificate = options.certificate
say_error "Missing certificate file option (-c /path/to/certificate.pem)" and abort unless @certificate
say_error "Could not find certificate file '#{@certificate}'" and abort unless File.exists?(@certificate)
@passphrase = options.passphrase ? password : ""
@alert = options.alert
@badge = options.badge.nil? ? nil : options.badge.to_i
@sound = options.sound
@category = options.category
@content_available = !!options.newsstand
if options.payload
begin
@data = JSON.parse(options.payload)
rescue => message
say_error "Exception parsing JSON payload: #{message}" and abort
end
elsif options.data
begin
@data = Hash[options.data.collect{|data| data.split(/\=/)}]
rescue => message
say_error "Exception parsing JSON payload: #{message}" and abort
end
end
unless @alert or @badge or @content_available or @data
placeholder = "Enter your alert message"
@alert = ask_editor placeholder
say_error "Payload contents required" and abort if @alert.nil? or @alert == placeholder
end
@notifications = []
args.each do |token|
notification = Houston::Notification.new(@data || {})
notification.token = token
notification.alert = @alert if @alert
notification.badge = @badge if @badge
notification.sound = @sound if @sound
notification.category = @category if @category
notification.content_available = @content_available if @content_available
@notifications << notification
end
client = (@environment == :production) ? Houston::Client.production : Houston::Client.development
client.certificate = File.read(@certificate)
client.passphrase = @passphrase
begin
client.push(*@notifications)
sent, unsent = @notifications.partition{|notification| notification.sent?}
if sent.any?
case sent.length
when 1
say_ok "1 push notification sent successfully"
else
say_ok "#{sent.length} push notifications sent successfully"
end
end
if unsent.any?
tokens = unsent.map{|notification| "\n - #{notification.token}"}.join
case unsent.length
when 1
say_error "1 push notification unsuccessful (#{tokens})"
else
say_error "#{unsent.length} push notifications unsuccessful (#{tokens})"
end
end
rescue => message
say_error "Exception sending notification: #{message}" and abort
end
end
end
command :feedback do |c|
c.syntax = 'apn feedback [...]'
c.summary = 'Queries the APN Feedback Service for failed device tokens.'
c.description = ''
c.example 'description', 'apn feedback -c /path/to/apple_push_certificate.pem'
c.option '-c', '--certificate CERTIFICATE', 'Path to certificate (.pem) file'
c.option '-e', '--environment ENV', [:production, :development], 'Environment to send push notification (production or development (default))'
c.option '-p', '--[no]-passphrase', 'Prompt for a certificate passphrase'
c.action do |args, options|
@environment = options.environment.downcase.to_sym rescue :development
say_error "Invalid environment,'#{@environment}' (should be either :development or :production)" and abort unless [:development, :production].include?(@environment)
@certificate = options.certificate
say_error "Missing certificate file option (-c /path/to/certificate.pem)" and abort unless @certificate
say_error "Could not find certificate file '#{@certificate}'" and abort unless File.exists?(@certificate)
@passphrase = options.passphrase ? password : ""
client = (@environment == :production) ? Houston::Client.production : Houston::Client.development
client.certificate = File.read(@certificate)
client.passphrase = @passphrase
begin
feedbackDevices = client.unregistered_devices
if feedbackDevices.any? && feedbackDevices.length > 0
puts feedbackDevices.to_json
else
say_ok "No feedback available"
end
rescue => message
say_error "Exception querying feedback: #{message}" and abort
end
end
end