pushover 0.99.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/Gemfile +24 -19
- data/Guardfile +17 -1
- data/README.md +56 -20
- data/Rakefile +1 -1
- data/bin/pushover +88 -22
- data/lib/pushover.rb +51 -32
- data/lib/pushover/app.rb +3 -6
- data/lib/pushover/mixins.rb +7 -0
- data/lib/pushover/priority.rb +63 -0
- data/lib/pushover/user.rb +3 -5
- data/lib/pushover/version.rb +1 -1
- data/pushover.gemspec +3 -2
- data/spec/bin/pushover_spec.rb +40 -1
- data/spec/lib/pushover/app_spec.rb +0 -1
- data/spec/lib/pushover/user_spec.rb +0 -1
- data/spec/lib/{pushover/pushover_spec.rb → pushover_spec.rb} +18 -1
- data/spec/spec_helper.rb +15 -6
- data/whatsnew.md +6 -0
- metadata +29 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fba81cc748d32d1fcb33b9033b31884f69b75446
|
4
|
+
data.tar.gz: cb9b81b74147841ed98a4e99ab6c56f1ae2a994c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 006c0109d54e20428d8042694a00cd9a24eb79103b922eea16e571c85e72d614d6a8ba08f7defbef26ddf700f282ea20a6c19d95256797ad65e5070ffe0df2e0
|
7
|
+
data.tar.gz: 93c9d2647e1136b4ebd8ca3d88afc2433e949199e21e265de32da249e91a78cec3a39cb7dae75718d9ca27d0fa310f16a3234642febc901acba8f26a6888cb9e
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,27 +3,32 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :development do
|
6
|
-
gem "pry"
|
7
|
-
gem "
|
8
|
-
gem "
|
9
|
-
gem "guard"
|
10
|
-
gem "guard-
|
11
|
-
gem "guard-
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem '
|
15
|
-
gem '
|
16
|
-
gem 'rb-
|
17
|
-
gem 'rb-fsevent', :require => false
|
18
|
-
gem 'rb-fchange', :require => false
|
6
|
+
gem "pry", :require => false
|
7
|
+
gem "guard", :require => false
|
8
|
+
gem "guard-bundler", :require => false
|
9
|
+
gem "guard-rspec", :require => false
|
10
|
+
gem "guard-yard", :require => false
|
11
|
+
gem "guard-shell", :require => false
|
12
|
+
gem 'libnotify', :require => false
|
13
|
+
gem 'growl', :require => false
|
14
|
+
gem 'rb-inotify', :require => false
|
15
|
+
gem 'rb-fsevent', :require => false
|
16
|
+
gem 'rb-fchange', :require => false
|
19
17
|
end
|
20
18
|
|
21
19
|
group :test do
|
22
|
-
gem "rspec"
|
23
|
-
gem "
|
24
|
-
gem "
|
25
|
-
gem "
|
26
|
-
gem
|
27
|
-
gem
|
20
|
+
gem "rspec", "~> 2.13.0"
|
21
|
+
gem "rspec-core", "~> 2.13.0"
|
22
|
+
gem "rspec-expectations", "~> 2.13.0"
|
23
|
+
gem "rspec-mocks", "~> 2.13.0"
|
24
|
+
gem "rake", "~> 10.1.0"
|
25
|
+
gem "webmock", "~> 1.13.0"
|
28
26
|
end
|
29
27
|
|
28
|
+
group :extended_testing do
|
29
|
+
gem "childprocess", "~> 0.3.9"
|
30
|
+
gem 'simplecov', "~> 0.7.1", :require => false
|
31
|
+
gem 'simplecov-rcov', "~> 0.2.3", :require => false
|
32
|
+
end
|
33
|
+
|
34
|
+
|
data/Guardfile
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
|
+
# Must be an array
|
3
|
+
test_cmd = [
|
4
|
+
"bundle exec pushover a message"
|
5
|
+
]
|
2
6
|
|
3
7
|
guard :bundler do
|
4
8
|
watch 'Gemfile'
|
@@ -7,7 +11,7 @@ end
|
|
7
11
|
|
8
12
|
guard :rspec do
|
9
13
|
watch(%r{^spec/.+_spec\.rb$})
|
10
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec
|
14
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
11
15
|
watch(%r{^bin/(.+)\.rb$}) { |m| "spec/bin/#{m[1]}_spec.rb" }
|
12
16
|
watch('spec/spec_helper.rb') { "spec" }
|
13
17
|
end
|
@@ -15,3 +19,15 @@ end
|
|
15
19
|
# guard :yard do
|
16
20
|
# watch(%r{^lib/(.+)\.rb$})
|
17
21
|
# end
|
22
|
+
|
23
|
+
# guard :shell do
|
24
|
+
# watch /.*/ do |m|
|
25
|
+
# puts "Time: #{Time.now}, file saved: #{m}"
|
26
|
+
# test_cmd.each do |cmd|
|
27
|
+
|
28
|
+
# puts "=" * 80
|
29
|
+
# puts "cmd: #{cmd}"
|
30
|
+
# puts `#{cmd}`
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
data/README.md
CHANGED
@@ -9,15 +9,15 @@ This gem provides a CLI and an API interface to http://pushover.net.
|
|
9
9
|
|
10
10
|
To install:
|
11
11
|
|
12
|
-
|
12
|
+
% gem install pushover
|
13
13
|
|
14
14
|
To use inside of an application, add this to the your gemfile:
|
15
15
|
|
16
|
-
|
16
|
+
% gem 'pushover'
|
17
17
|
|
18
18
|
and run bundle to make it available:
|
19
19
|
|
20
|
-
|
20
|
+
% bundle
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
@@ -46,11 +46,11 @@ Pushover.notification(message: 'message', title: 'title')
|
|
46
46
|
|
47
47
|
To get help do, try ```--(h)elp```
|
48
48
|
|
49
|
-
|
49
|
+
% pushover -h
|
50
50
|
|
51
51
|
To send a message.
|
52
52
|
|
53
|
-
|
53
|
+
% pushover -u user_token -a app_key message is the rest of the cli.
|
54
54
|
|
55
55
|
#### Optional parameters
|
56
56
|
|
@@ -60,52 +60,62 @@ Most optional parameters have a shorter form you can use. If that's the case, t
|
|
60
60
|
|
61
61
|
The file to use for stored settings (including credentials).
|
62
62
|
|
63
|
-
|
63
|
+
% pushover --(c)onfig_file /tmp/config_file
|
64
64
|
|
65
65
|
|
66
66
|
#### Title
|
67
67
|
|
68
68
|
The title of the message, if not supplied it will end up being the app name.
|
69
69
|
|
70
|
-
|
70
|
+
% pushover --(t)itle "A title"
|
71
71
|
|
72
|
-
|
72
|
+
% pushover --(t)itle "A title"
|
73
73
|
|
74
74
|
#### Priority
|
75
75
|
|
76
76
|
Priority of the message, either (low,normal,high) or (-1,0,1). For the string you only need the first letter.
|
77
77
|
|
78
|
-
|
78
|
+
% pushover --(p)riority high
|
79
79
|
|
80
|
-
|
80
|
+
% pushover --(p)riority h
|
81
81
|
|
82
|
-
|
82
|
+
% pushover --(p)riority -1
|
83
|
+
|
84
|
+
#### Emergency Notifications
|
85
|
+
|
86
|
+
Currently retry/expire is supported, currently these are in seconds. Callback url's are not.
|
87
|
+
|
88
|
+
% pushover --emergency_retry 60
|
89
|
+
|
90
|
+
% pushover --emergency_expire 3600
|
91
|
+
|
92
|
+
It won't pre-check values sent to the api, so you will need to tune for the current min/max values or check api documentation.
|
83
93
|
|
84
94
|
#### Device
|
85
95
|
|
86
96
|
Specific device to send the message too, must be registered at pushover.net
|
87
97
|
|
88
|
-
|
98
|
+
% pushover --(d)evice "Device name"
|
89
99
|
|
90
100
|
#### URL
|
91
101
|
|
92
102
|
Supplementary URL that can be passed with the message.
|
93
103
|
|
94
|
-
|
104
|
+
% pushover --url "http://www.github.com/erniebrodeur/pushover"
|
95
105
|
|
96
106
|
##### URL Title
|
97
107
|
|
98
108
|
The display string of the supplementary URL.
|
99
109
|
|
100
|
-
|
110
|
+
% pushover --url "http://www.git.com/erniebrodeur/pushover" --url_title "This repo."
|
101
111
|
|
102
112
|
#### Time
|
103
113
|
|
104
114
|
Time is tricky, I just pass the string off to the stdlib ```Time.parse```. Therefore, if it fails I can't do much about it. Though, it shouldn't fail, it seems to take just a ton of stuff. You can always handle this yourself and just pass in an epoch (string or fixnum).
|
105
115
|
|
106
|
-
|
116
|
+
% pushover --time 1331249662
|
107
117
|
|
108
|
-
|
118
|
+
% pushover --time "6:30"
|
109
119
|
|
110
120
|
##### String examples
|
111
121
|
|
@@ -119,30 +129,56 @@ As far as I can tell, you can toss a ton of different things and get an output.
|
|
119
129
|
* 14:30
|
120
130
|
* Aug 21
|
121
131
|
|
132
|
+
##### Sounds
|
133
|
+
|
134
|
+
Get the available list of sounds:
|
135
|
+
|
136
|
+
% pushover --sound_list
|
137
|
+
|
138
|
+
Play a specific sound with a message:
|
139
|
+
|
140
|
+
% pushover --sound Magic
|
141
|
+
% pushover --sound per
|
142
|
+
|
143
|
+
* You only need to supply an unambiguous partial string.
|
144
|
+
* It is not case sensitive.
|
145
|
+
|
122
146
|
#### Saving
|
123
147
|
|
124
148
|
You can also save and use stored information. The username/application are titles. They can be anything you want to reference them.
|
125
149
|
|
126
150
|
##### User
|
127
151
|
|
128
|
-
|
152
|
+
% pushover -u user_token --save-user email@somewhere.net
|
129
153
|
|
130
154
|
##### Application
|
131
155
|
|
132
|
-
|
156
|
+
% pushover -a app_key --save-app myApp
|
133
157
|
|
134
158
|
Delete done in the api, not lifted to the cli.
|
135
159
|
|
136
160
|
Now, you can use these to send messages instead of having to remember the key:
|
137
161
|
|
138
|
-
|
162
|
+
% pushover -a myApp -u email@somewhere.net Hello from somewhere!
|
139
163
|
|
140
164
|
If you don't supply the application or user name, it will use the first one in the save file.
|
141
165
|
|
142
|
-
|
166
|
+
% pushover so now I can just send an app.
|
143
167
|
|
144
168
|
Anytime you supply tokens directly to the cli, it will ignore any saved information and try them. This allows you to use it as a once-off tool while keeping credentials stored.
|
145
169
|
|
170
|
+
## TODO
|
171
|
+
|
172
|
+
### 1.0 tree
|
173
|
+
|
174
|
+
* Callback urls.
|
175
|
+
* Receipt testing.
|
176
|
+
|
177
|
+
### 2.0 tree
|
178
|
+
|
179
|
+
* Rebuild the CLI so it works more like a git/bundle command.
|
180
|
+
* More argument/string magic.
|
181
|
+
|
146
182
|
## Contributing
|
147
183
|
|
148
184
|
1. Fork it
|
data/Rakefile
CHANGED
data/bin/pushover
CHANGED
@@ -7,7 +7,7 @@ include Pushover
|
|
7
7
|
Options.on("-u", "--user USER", "Which user, can be a saved name or token.") { |o| Options[:user] = o}
|
8
8
|
Options.on("-a", "--app APPKEY", "Which app to notify, can be a saved name or apikey.") { |o| Options[:token] = o}
|
9
9
|
Options.on("-t", "--title [TITLE]", "Set the title of the notification (optional).") { |o| Options[:title] = o}
|
10
|
-
Options.on("-p", "--priority [PRIORITY]", "Set the priority of the notification from (low,normal,high) (optional).") { |o| Options[:priority] = o}
|
10
|
+
Options.on("-p", "--priority [PRIORITY]", "Set the priority of the notification from (low,normal,high,emergency) (optional).") { |o| Options[:priority] = o}
|
11
11
|
Options.on("-d", "--device [DEVICE]", "Specify the device to send the notifcation to. (optional).") { |o| Options[:device] = o}
|
12
12
|
Options.on("-c", "--config_file [FILE]", "Set the target config file.") {|o| Options[:config_file] = o}
|
13
13
|
Options.on("--url [URL]", "Supplementary URL") { |o| Options[:url] = o }
|
@@ -15,6 +15,12 @@ Options.on("--url_title [TITLE]", "Supplementary URL title.") { |o| Options[:url
|
|
15
15
|
Options.on("--time [TIME]", "Set the messages time.") {|o| Options[:timestamp] = o}
|
16
16
|
Options.on("--save-app NAME", "Saves the application to the config file under NAME.") { |o| Options[:save_app] = [Options[:appkey], o]}
|
17
17
|
Options.on("--save-user NAME", "Saves the user to the config file under NAME.") { |o| Options[:save_user] = [Options[:user], o]}
|
18
|
+
Options.on("--sound [SOUND]", "Specify the sound to use. Can be a partial string as long as it is unambiguous enough.") { |o| Options[:sound] = o}
|
19
|
+
Options.on("--sound_list", "Display the current list of available sounds. Requires an app token.") { |o| Options[:sound_list] = true}
|
20
|
+
Options.on("--emergency_retry [TIME]", "The time in seconds between retries.") { |o| Options[:retry] = o}
|
21
|
+
Options.on("--emergency_expire [TIME]", "How long the emergency notification will hang around.") { |o| Options[:expire] = o}
|
22
|
+
Options.on("--emergency_callback_url [URL]", "A callback url to use when the notification is acknowledged.") { |o| Options[:callback] = o}
|
23
|
+
Options.on("--receipts", "List the receipts cached and if they have been acknowledged or not.") {|o| Options[:receipts] = true}
|
18
24
|
|
19
25
|
Options.parse!
|
20
26
|
bail = false
|
@@ -37,16 +43,7 @@ if Options[:save_user]
|
|
37
43
|
bail = true
|
38
44
|
end
|
39
45
|
|
40
|
-
if
|
41
|
-
puts "You must supply a message."
|
42
|
-
bail = true
|
43
|
-
end
|
44
|
-
|
45
|
-
message = ARGV.join(" ")
|
46
|
-
if !message
|
47
|
-
puts "Must supply a message to be sent."
|
48
|
-
bail = true
|
49
|
-
end
|
46
|
+
exit if bail # We don't care if we have a message, we should exit here.
|
50
47
|
|
51
48
|
if !App.current_app?
|
52
49
|
puts "Couldn't find an app via the cli or save file."
|
@@ -54,31 +51,100 @@ if !App.current_app?
|
|
54
51
|
end
|
55
52
|
|
56
53
|
if !User.current_user?
|
57
|
-
puts User.current_user?
|
58
54
|
puts "Couldn't find a user via the cli or save file."
|
59
55
|
bail = true
|
60
56
|
end
|
61
57
|
|
58
|
+
if Options[:sound_list]
|
59
|
+
puts "Current Sound List:"
|
60
|
+
if Pushover.sounds
|
61
|
+
Pushover.sounds.each { |k,v| puts " #{v}" }
|
62
|
+
else
|
63
|
+
puts "Error retrieving sound list, are you connected to the internet? are your credentials correct?"
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
bail = true
|
67
|
+
end
|
68
|
+
|
69
|
+
if Options[:receipts]
|
70
|
+
puts 'Updating receipts'
|
71
|
+
Pushover::Priority.update_receipts
|
72
|
+
Pushover::Priority::Receipts.each do |k,v|
|
73
|
+
if v["acknowledged"] != 0
|
74
|
+
print "Receipt #{k} was acknowledged at #{Time.at v["acknowledged_at"]}, "
|
75
|
+
else
|
76
|
+
print "Receipt #{k} has not been acknowledged yet, "
|
77
|
+
end
|
78
|
+
|
79
|
+
if v["expired"] == 0
|
80
|
+
puts "and will expire at: #{Time.at v["expires_at"]}."
|
81
|
+
else
|
82
|
+
puts "and expired at: #{Time.at v["expires_at"]}."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
if Options[:sound]
|
89
|
+
sounds = Pushover.sounds
|
90
|
+
if !sounds
|
91
|
+
puts "Error retrieving sound list, are you connected to the internet? are your credentials correct?"
|
92
|
+
exit
|
93
|
+
end
|
94
|
+
match = sounds.select { |k,v| v.downcase.start_with? Options[:sound].downcase}
|
95
|
+
if !match || match.count == 0
|
96
|
+
puts "No such sound: #{Options[:sound]}."
|
97
|
+
bail = true
|
98
|
+
elsif match.count > 1
|
99
|
+
print "Sound is ambiguous, possible matches: "
|
100
|
+
match.each {|k,v| print "#{v} "}
|
101
|
+
print "\n"
|
102
|
+
bail = true
|
103
|
+
else
|
104
|
+
Options[:sound] = match.first[0]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
if Options[:priority]
|
109
|
+
# Is this an emergency, did we include everything we need?
|
110
|
+
if Priority.is_emergency?(Options[:priority])
|
111
|
+
Options[:retry] = 30 if !Options[:retry]
|
112
|
+
Options[:expire] = 86400 if !Options[:expire]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
62
116
|
exit if bail
|
63
117
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
c.token = App.current_app
|
118
|
+
message = ARGV.join(" ")
|
119
|
+
if !message
|
120
|
+
puts "Must supply a message to be sent."
|
121
|
+
bail = true
|
69
122
|
end
|
70
123
|
|
71
|
-
|
124
|
+
exit if bail
|
125
|
+
|
72
126
|
options = Options[].select { |k,v| v}
|
127
|
+
options[:token] = Pushover::App.current_app
|
128
|
+
options[:user] = Pushover::User.current_user
|
73
129
|
options.delete :config_file
|
74
130
|
options.merge! message:message
|
75
|
-
response = Pushover.notification options
|
76
131
|
|
77
|
-
|
132
|
+
response = Pushover.notification options
|
133
|
+
if response.code == 500
|
134
|
+
puts "Something is broken at pushover.net and it is returning 500's (server errors). Here is the response body."
|
135
|
+
puts response.body
|
136
|
+
exit
|
137
|
+
end
|
138
|
+
j = Yajl.load response.body
|
139
|
+
|
140
|
+
if response.code == 200
|
141
|
+
if Priority.is_emergency?(Options[:priority])
|
142
|
+
j = Yajl.load response.body
|
143
|
+
Pushover::Priority.process_receipt j["receipt"]
|
144
|
+
puts "emergency notification receipt: #{j["receipt"]}"
|
145
|
+
end
|
78
146
|
puts "Message sent successfully!"
|
79
147
|
else
|
80
|
-
j = Yajl.load response.body
|
81
148
|
puts "ErrorCode (#{response.code}): #{j['errors'].first}."
|
82
149
|
end
|
83
150
|
|
84
|
-
|
data/lib/pushover.rb
CHANGED
@@ -1,17 +1,25 @@
|
|
1
|
-
require
|
1
|
+
require 'httparty'
|
2
2
|
require "yajl"
|
3
3
|
require 'time'
|
4
4
|
require 'bini'
|
5
5
|
require 'bini/config'
|
6
6
|
require 'bini/optparser'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'pushover/mixins.rb'
|
9
|
+
|
10
|
+
module Pushover
|
11
|
+
autoload :VERSION, "pushover/version"
|
12
|
+
autoload :App, "pushover/app"
|
13
|
+
autoload :User, "pushover/user"
|
14
|
+
autoload :Priority, "pushover/priority"
|
15
|
+
end
|
7
16
|
|
8
|
-
require "pushover/version"
|
9
|
-
require "pushover/app"
|
10
|
-
require "pushover/user"
|
11
17
|
# The primary pushover namespace.
|
12
18
|
module Pushover
|
19
|
+
# Unfuckingbelievable. My code, and I still can't get it to work as expected.
|
20
|
+
Bini.long_name = 'pushover'
|
13
21
|
# lets save our config to it's own dir, just because.
|
14
|
-
Bini::Config.file = "#{Dir.home}/.config/pushover/credentials.yaml"
|
22
|
+
Bini::Config.options[:file] = "#{Dir.home}/.config/pushover/credentials.yaml"
|
15
23
|
Bini::Config.load
|
16
24
|
|
17
25
|
extend self
|
@@ -26,14 +34,14 @@ module Pushover
|
|
26
34
|
attr_accessor :title
|
27
35
|
# [optional,String] device to recieve the message.
|
28
36
|
attr_accessor :device
|
37
|
+
attr_reader :priority
|
29
38
|
attr_accessor :url
|
30
39
|
attr_accessor :url_title
|
40
|
+
attr_accessor :emergency_retry
|
41
|
+
attr_accessor :emergency_expire
|
42
|
+
attr_accessor :emergency_callback
|
31
43
|
# [optional,String, Fixnum] time a time stamp im one of three forms (epoch, strfmt, rails)
|
32
44
|
attr_reader :timestamp
|
33
|
-
attr_reader :priority
|
34
|
-
def priority=(level)
|
35
|
-
@priority = priority_magic level
|
36
|
-
end
|
37
45
|
|
38
46
|
# Stdlib time, seems to take a shitload of options.
|
39
47
|
# rfc822: Tue, 14 Nov 2000 14:55:07 -0500
|
@@ -54,15 +62,22 @@ module Pushover
|
|
54
62
|
# @return [String] the response from pushover.net, in json.
|
55
63
|
def notification(tokens={})
|
56
64
|
tokens[:timestamp] = timestamp_magic tokens[:timestamp] if tokens[:timestamp]
|
57
|
-
tokens[:priority] =
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
65
|
+
tokens[:priority] = Pushover::Priority.parse tokens[:priority] if tokens[:priority]
|
66
|
+
|
67
|
+
response = HTTParty.post('https://api.pushover.net/1/messages.json', body:tokens)
|
68
|
+
response
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return a [Hash] of sounds.
|
72
|
+
def sounds
|
73
|
+
cache_file = "#{Bini.cache_dir}/sounds.json"
|
74
|
+
sounds = {}
|
75
|
+
|
76
|
+
cache_sounds if File.exists?(cache_file) && File.stat(cache_file).mtime < Time.at(Time.now.day - 1)
|
77
|
+
|
78
|
+
return nil if !cache_sounds
|
79
|
+
sounds = Yajl.load open(cache_file).read
|
80
|
+
sounds["sounds"]
|
66
81
|
end
|
67
82
|
|
68
83
|
# Adds a rails style configure method
|
@@ -93,9 +108,14 @@ module Pushover
|
|
93
108
|
|
94
109
|
# A [Array] of keys available in Pushover.
|
95
110
|
def keys
|
96
|
-
|
111
|
+
Pushover.instance_methods.select do |m|
|
112
|
+
m =~ /=$/
|
113
|
+
end.map do |m|
|
114
|
+
m[0..-2]
|
115
|
+
end
|
97
116
|
end
|
98
117
|
|
118
|
+
|
99
119
|
private
|
100
120
|
|
101
121
|
def timestamp_magic(time_string)
|
@@ -111,18 +131,17 @@ module Pushover
|
|
111
131
|
end
|
112
132
|
end
|
113
133
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
134
|
+
def cache_sounds
|
135
|
+
cache_file = "#{Bini.cache_dir}/sounds.json"
|
136
|
+
|
137
|
+
response = HTTParty.get('https://api.pushover.net/1/sounds.json', query:{token:Pushover::App.current_app})
|
138
|
+
|
139
|
+
return nil if response.code != 200
|
140
|
+
FileUtils.mkdir_p Bini.cache_dir
|
141
|
+
f = open(cache_file, 'w')
|
142
|
+
f.write response.body
|
143
|
+
f.flush
|
144
|
+
f.close
|
145
|
+
return true
|
126
146
|
end
|
127
147
|
end
|
128
|
-
|
data/lib/pushover/app.rb
CHANGED
@@ -34,7 +34,7 @@ module Pushover
|
|
34
34
|
# @return [Boolean] return the results of the save attempt.
|
35
35
|
def add(name, api_key)
|
36
36
|
App.new name, api_key
|
37
|
-
Bini::Config.save
|
37
|
+
Bini::Config.save
|
38
38
|
end
|
39
39
|
|
40
40
|
def remove(name)
|
@@ -45,11 +45,8 @@ module Pushover
|
|
45
45
|
# did something get supplied on the cli? try to find it.
|
46
46
|
if Bini::Options[:apikey]
|
47
47
|
@current_app = find Bini::Options[:apikey]
|
48
|
-
|
49
|
-
|
50
|
-
# no? do we have anything we can return?
|
51
|
-
if !@current_app
|
52
|
-
@current_app = find Bini::Config[:applications].first[0] if Bini::Config[:applications]
|
48
|
+
else
|
49
|
+
@current_app = find Bini::Config[:applications].values.first if Bini::Config[:applications]
|
53
50
|
end
|
54
51
|
@current_app
|
55
52
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Pushover
|
2
|
+
module Priority
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# A sash for our receipts.
|
6
|
+
Receipts = Bini::Sash.new options:{
|
7
|
+
file:"#{Bini.cache_dir}/receipts.yaml", auto_load:true, auto_save:true
|
8
|
+
}
|
9
|
+
LEVELS = {
|
10
|
+
low:-1,
|
11
|
+
normal:0,
|
12
|
+
high:1,
|
13
|
+
emergency:2
|
14
|
+
}
|
15
|
+
|
16
|
+
def priority=(level)
|
17
|
+
@priority = parse level
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse(level)
|
21
|
+
return level if level.class == Fixnum
|
22
|
+
if level.class == String
|
23
|
+
LEVELS.each { |k,v| return v if k.to_s.start_with? level.downcase }
|
24
|
+
end
|
25
|
+
|
26
|
+
return 0
|
27
|
+
end
|
28
|
+
|
29
|
+
# Pull one from cache, or fetch one if not available.
|
30
|
+
def find_receipt(prefix)
|
31
|
+
results = Receipts.select { |k,v| k =~ /^#{prefix}/ }
|
32
|
+
return nil if results.empty?
|
33
|
+
return results.first
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_receipts
|
37
|
+
updates = Receipts.select {|k,v| v["acknowledged"] == 0 && v["expired"] == 0}
|
38
|
+
updates.keys.each do |key|
|
39
|
+
process_receipt key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_receipt(receipt)
|
44
|
+
r = fetch_receipt(receipt)
|
45
|
+
|
46
|
+
return nil if !r
|
47
|
+
Receipts[receipt] = r.to_h
|
48
|
+
|
49
|
+
return Receipts[receipt]
|
50
|
+
end
|
51
|
+
|
52
|
+
def is_emergency?(priority)
|
53
|
+
return true if priority && Pushover::Priority.parse(priority) == LEVELS[:emergency]
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def fetch_receipt(receipt)
|
59
|
+
HTTParty.get("https://api.pushover.net/1/receipts/#{receipt}.json",
|
60
|
+
body:{token:Pushover::App.current_app})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/pushover/user.rb
CHANGED
@@ -35,7 +35,7 @@ module Pushover
|
|
35
35
|
# @return [Boolean] return the results of the save attempt.
|
36
36
|
def add(name, token)
|
37
37
|
User.new name, token
|
38
|
-
Bini::Config.save
|
38
|
+
Bini::Config.save
|
39
39
|
end
|
40
40
|
|
41
41
|
def remove(name)
|
@@ -47,12 +47,10 @@ module Pushover
|
|
47
47
|
# did something get supplied on the cli? try to find it.
|
48
48
|
if Bini::Options[:token]
|
49
49
|
@current_user = find Bini::Options[:token]
|
50
|
+
elsif !@current_user
|
51
|
+
@current_user = find Bini::Config[:users].values.first if Bini::Config[:users]
|
50
52
|
end
|
51
53
|
|
52
|
-
# no? do we have anything we can return?
|
53
|
-
if !@current_user
|
54
|
-
@current_user = find Bini::Config[:users].first[0] if Bini::Config[:users]
|
55
|
-
end
|
56
54
|
@current_user
|
57
55
|
end
|
58
56
|
|
data/lib/pushover/version.rb
CHANGED
data/pushover.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |gem|
|
|
26
26
|
gem.has_rdoc = 'yard'
|
27
27
|
|
28
28
|
# dependencies.
|
29
|
-
gem.add_runtime_dependency 'yajl-ruby'
|
30
|
-
gem.add_runtime_dependency '
|
29
|
+
gem.add_runtime_dependency 'yajl-ruby', "= 1.1.0"
|
30
|
+
gem.add_runtime_dependency 'httparty', "= 0.11.0"
|
31
|
+
gem.add_runtime_dependency 'bini', "= 0.7.0"
|
31
32
|
end
|
data/spec/bin/pushover_spec.rb
CHANGED
@@ -28,7 +28,6 @@ if ENV["TEST_CLI"] =~ /^t/
|
|
28
28
|
it "sends messages" do
|
29
29
|
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} a message", 3, 3
|
30
30
|
p.run!
|
31
|
-
#binding.pry
|
32
31
|
p.stdout.should include("success"), "#{p.stderr}"
|
33
32
|
end
|
34
33
|
end
|
@@ -54,5 +53,45 @@ if ENV["TEST_CLI"] =~ /^t/
|
|
54
53
|
open(FAKE_CRED_FILE).read.should include 'default'
|
55
54
|
end
|
56
55
|
end
|
56
|
+
describe "sounds" do
|
57
|
+
it "will list sounds" do
|
58
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} --sound_list", 3, 3
|
59
|
+
p.run!
|
60
|
+
p.stdout.should include "Current Sound"
|
61
|
+
p.stdout.should include "Pushover (default)"
|
62
|
+
p.stdout.should include "None (silent)"
|
63
|
+
end
|
64
|
+
it "will play a sound (based on partial string)" do
|
65
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} a message --sound none", 3, 3
|
66
|
+
p.run!
|
67
|
+
p.stdout.should include "success"
|
68
|
+
end
|
69
|
+
it "will fail if the sound is unavailble" do
|
70
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} a message --sound slkdjg", 3, 3
|
71
|
+
p.run!
|
72
|
+
p.stdout.should include "No such sound"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
describe "emergency notifications" do
|
76
|
+
it "will respond to emergency parameters" do
|
77
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} an emergency message retry test --priority em --emergency_retry 180", 3, 3
|
78
|
+
p.run!
|
79
|
+
p.stdout.should include "success"
|
80
|
+
|
81
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} an emergency message expires test --priority em --emergency_expire 7200", 3, 3
|
82
|
+
p.run!
|
83
|
+
p.stdout.should include "success"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "will print the receipt" do
|
87
|
+
p = CLIProcess.new "#{CMD} --config_file #{CRED_FILE} an emergency message --priority em", 3, 3
|
88
|
+
p.run!
|
89
|
+
p.stdout.should include "receipt"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "will accept a callback url"
|
93
|
+
end
|
57
94
|
end
|
58
95
|
end
|
96
|
+
|
97
|
+
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Pushover" do
|
4
|
+
before :all do
|
5
|
+
Bini.cache_dir = "tmp/cache_dir"
|
6
|
+
Bini.data_dir = "tmp/data_dir"
|
7
|
+
Bini.config_dir = "tmp/config_dir"
|
8
|
+
end
|
4
9
|
before :each do
|
5
10
|
App.current_app = nil
|
6
11
|
User.current_user = nil
|
@@ -85,6 +90,18 @@ describe "Pushover" do
|
|
85
90
|
WebMock.should have_requested(:post, /api.pushover.net/).with { |req| req.body.include? 'timestamp=1' }
|
86
91
|
end
|
87
92
|
end
|
93
|
+
|
94
|
+
describe "Sounds" do
|
95
|
+
it "will cache the sounds locally for at least a day" do
|
96
|
+
setup_webmocks
|
97
|
+
cache_file = "#{Bini.cache_dir}/sounds.json"
|
98
|
+
FileUtils.rm(cache_file) if File.exist?(cache_file)
|
99
|
+
Pushover.sounds.keys.should include("pushover")
|
100
|
+
stat = File.stat(cache_file)
|
101
|
+
Pushover.sounds.keys.should include("none")
|
102
|
+
stat.mtime.to_i.should eq File.stat(cache_file).mtime.to_i
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
88
106
|
end
|
89
107
|
end
|
90
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,9 @@ require 'webmock/rspec'
|
|
15
15
|
require 'pushover'
|
16
16
|
|
17
17
|
include Pushover
|
18
|
+
Bini.long_name = 'pushover'
|
19
|
+
Bini::Config.options[:file] = "tmp/test.save"
|
20
|
+
Bini::Config.load
|
18
21
|
|
19
22
|
RSpec.configure do |config|
|
20
23
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -28,11 +31,17 @@ def setup_webmocks
|
|
28
31
|
good_result = '{"status":1}'
|
29
32
|
bad_token = '{"token":"invalid","errors":["application token is invalid"],"status":0}'
|
30
33
|
bad_user = '{"user":"invalid","errors":["user identifier is invalid"],"status":0}'
|
34
|
+
sounds = '{"sounds":{"pushover":"Pushover (default)","bike":"Bike","bugle":"Bugle","cashregister":"Cash Register","classical":"Classical","cosmic":"Cosmic","falling":"Falling","gamelan":"Gamelan","incoming":"Incoming","intermission":"Intermission","magic":"Magic","mechanical":"Mechanical","pianobar":"Piano Bar","siren":"Siren","spacealarm":"Space Alarm","tugboat":"Tug Boat","alien":"Alien Alarm (long)","climb":"Climb (long)","persistent":"Persistent (long)","echo":"Pushover Echo (long)","updown":"Up Down (long)","none":"None (silent)"},"status":1,"request":"14ef413f6a3bf74efee3e140efe63df9"}'
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
:
|
36
|
-
|
37
|
-
|
36
|
+
stub_request(:post, "https://api.pushover.net/1/messages.json").
|
37
|
+
with(body:hash_including(token:'good_token', user:'good_user')).
|
38
|
+
to_return(body:good_result, code:200)
|
39
|
+
stub_request(:post, "https://api.pushover.net/1/messages.json").
|
40
|
+
with(body:hash_including(token:'bad_token')).
|
41
|
+
to_return(body:bad_token, code:400)
|
42
|
+
stub_request(:post, "https://api.pushover.net/1/messages.json").
|
43
|
+
with(body:hash_including(user:'bad_user')).
|
44
|
+
to_return(body:bad_user, code:400)
|
45
|
+
stub_request(:get, /https:\/\/api.pushover.net\/1\/sounds.json.*/).
|
46
|
+
to_return(body:sounds, code:200)
|
38
47
|
end
|
data/whatsnew.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## Unreleased
|
2
|
+
* Sounds.
|
3
|
+
* Emergency notifications.
|
4
|
+
* Will properly trap 500 (server errors) being returned from the server.
|
5
|
+
* Dropped the local sash in favor of the bini copy.
|
6
|
+
|
1
7
|
## 0.99.2:
|
2
8
|
* Version constraint (thanks @freeatnet) on bini, I stupidily upgraded one without the other.
|
3
9
|
|
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pushover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernie Brodeur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yajl-ruby
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - '
|
17
|
+
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.1.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - '
|
24
|
+
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httparty
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.11.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.11.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bini
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- -
|
45
|
+
- - '='
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
47
|
+
version: 0.7.0
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- -
|
52
|
+
- - '='
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
54
|
+
version: 0.7.0
|
41
55
|
description: Api (and CLI) to interface with pushover.net
|
42
56
|
email:
|
43
57
|
- ebrodeur@ujami.net
|
@@ -58,14 +72,16 @@ files:
|
|
58
72
|
- bin/pushover
|
59
73
|
- lib/pushover.rb
|
60
74
|
- lib/pushover/app.rb
|
75
|
+
- lib/pushover/mixins.rb
|
76
|
+
- lib/pushover/priority.rb
|
61
77
|
- lib/pushover/user.rb
|
62
78
|
- lib/pushover/version.rb
|
63
79
|
- pushover.gemspec
|
64
80
|
- spec/bin/pushover_spec.rb
|
65
81
|
- spec/cli_spec_helper.rb
|
66
82
|
- spec/lib/pushover/app_spec.rb
|
67
|
-
- spec/lib/pushover/pushover_spec.rb
|
68
83
|
- spec/lib/pushover/user_spec.rb
|
84
|
+
- spec/lib/pushover_spec.rb
|
69
85
|
- spec/spec_helper.rb
|
70
86
|
- whatsnew.md
|
71
87
|
homepage: https://github.com/erniebrodeur/pushover
|
@@ -94,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
110
|
version: '0'
|
95
111
|
requirements: []
|
96
112
|
rubyforge_project:
|
97
|
-
rubygems_version: 2.0.
|
113
|
+
rubygems_version: 2.0.3
|
98
114
|
signing_key:
|
99
115
|
specification_version: 4
|
100
116
|
summary: This gem provides both an API and CLI interface to pushover.net.
|
@@ -102,7 +118,7 @@ test_files:
|
|
102
118
|
- spec/bin/pushover_spec.rb
|
103
119
|
- spec/cli_spec_helper.rb
|
104
120
|
- spec/lib/pushover/app_spec.rb
|
105
|
-
- spec/lib/pushover/pushover_spec.rb
|
106
121
|
- spec/lib/pushover/user_spec.rb
|
122
|
+
- spec/lib/pushover_spec.rb
|
107
123
|
- spec/spec_helper.rb
|
108
124
|
has_rdoc: yard
|