pushover 0.99.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 384098813f10cc5c417e2e4f833ba8b7e7e58397
4
- data.tar.gz: 30885b1bda002d1e5a95ae34ab5c67328e4f5b95
3
+ metadata.gz: fba81cc748d32d1fcb33b9033b31884f69b75446
4
+ data.tar.gz: cb9b81b74147841ed98a4e99ab6c56f1ae2a994c
5
5
  SHA512:
6
- metadata.gz: 584baf258b9ef963b9f818203fbc9c3a507feb0fb5c7a214b2aa01627853fcddee08264048cf156116343641e74202f1916a6444251a83ba8fd635f1ecee50ea
7
- data.tar.gz: ce345127bb007692d1faab0973c35f0f4d752145ff1b62a74f39888fefbab7ec19bde59e48ed53124dc22a8965a4c96fc394162ae633b4d8f9b6db19c3d7160c
6
+ metadata.gz: 006c0109d54e20428d8042694a00cd9a24eb79103b922eea16e571c85e72d614d6a8ba08f7defbef26ddf700f282ea20a6c19d95256797ad65e5070ffe0df2e0
7
+ data.tar.gz: 93c9d2647e1136b4ebd8ca3d88afc2433e949199e21e265de32da249e91a78cec3a39cb7dae75718d9ca27d0fa310f16a3234642febc901acba8f26a6888cb9e
data/.travis.yml CHANGED
@@ -3,9 +3,12 @@ bundler_args: --without development
3
3
  rvm:
4
4
  - 1.9.2
5
5
  - 1.9.3
6
+ - 2.0.0
6
7
  - rbx-19mode
7
8
 
8
9
  branches:
9
10
  only:
10
11
  - master
11
12
  - development
13
+
14
+ script: bundle exec rspec -b spec
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 "pry-debugger"
8
- gem "redcarpet"
9
- gem "guard"
10
- gem "guard-bundler"
11
- gem "guard-rspec"
12
- gem "guard-yard"
13
- gem "guard-shell"
14
- gem 'libnotify', :require => false
15
- gem 'growl', :require => false
16
- gem 'rb-inotify', :require => false
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 "rake"
24
- gem "webmock"
25
- gem "childprocess"
26
- gem 'simplecov', :require => false
27
- gem 'simplecov-rcov', :require => false
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 spec/lib/#{m[1]}_spec.rb" }
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
- $ gem install pushover
12
+ % gem install pushover
13
13
 
14
14
  To use inside of an application, add this to the your gemfile:
15
15
 
16
- $ gem 'pushover'
16
+ % gem 'pushover'
17
17
 
18
18
  and run bundle to make it available:
19
19
 
20
- $ bundle
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
- $ pushover -h
49
+ % pushover -h
50
50
 
51
51
  To send a message.
52
52
 
53
- $ pushover -u user_token -a app_key message is the rest of the cli.
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
- $ pushover --(c)onfig_file /tmp/config_file
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
- $ pushover --(t)itle "A title"
70
+ % pushover --(t)itle "A title"
71
71
 
72
- $ pushover --(t)itle "A title"
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
- $ pushover --(p)riority high
78
+ % pushover --(p)riority high
79
79
 
80
- $ pushover --(p)riority h
80
+ % pushover --(p)riority h
81
81
 
82
- $ pushover --(p)riority -1
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
- $ pushover --(d)evice "Device name"
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
- $ pushover --url "http://www.github.com/erniebrodeur/pushover"
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
- $ pushover --url "http://www.git.com/erniebrodeur/pushover" --url_title "This repo."
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
- $ pushover --time 1331249662
116
+ % pushover --time 1331249662
107
117
 
108
- $ pushover --time "6:30"
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
- $ pushover -u user_token --save-user email@somewhere.net
152
+ % pushover -u user_token --save-user email@somewhere.net
129
153
 
130
154
  ##### Application
131
155
 
132
- $ pushover -a app_key --save-app myApp
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
- $ pushover -a myApp -u email@somewhere.net Hello from somewhere!
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
- $ pushover so now I can just send an app.
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
@@ -1,7 +1,7 @@
1
+ require "bundler/gem_tasks"
1
2
  require 'rspec/core/rake_task'
2
3
 
3
4
  RSpec::Core::RakeTask.new(:spec)
4
5
 
5
6
  task :default => :spec
6
7
 
7
- require "bundler/gem_tasks"
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 ARGV.empty?
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
- # I do both just as an example, you can configure it this way and have it
65
- # pre-configured:
66
- Pushover.configure do |c|
67
- c.user = User.current_user
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
- # Or in real time, which will also overwrite the .configure block.
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
- if response.code == "200"
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 "net/https"
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] = priority_magic tokens[:priority] if tokens[:priority]
58
-
59
- url = URI.parse("https://api.pushover.net/1/messages.json")
60
- req = Net::HTTP::Post.new(url.path, {'User-Agent' => "Ruby pushover gem: #{Pushover::VERSION}"})
61
- req.set_form_data(params.merge(tokens).select {|k,v| v != nil})
62
- res = Net::HTTP.new(url.host, url.port)
63
- res.use_ssl = true
64
- res.verify_mode = OpenSSL::SSL::VERIFY_PEER
65
- res.start {|http| http.request(req) }
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
- keys ||= [:token, :user, :message, :title, :priority, :device, :timestamp, :url, :url_title]
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 priority_magic(level)
115
- if level.class == String
116
- if level =~ /^[lL]/
117
- return -1
118
- elsif level =~ /^[hH]/
119
- return 1
120
- else
121
- return 0
122
- end
123
- elsif level.class == Fixnum
124
- return level
125
- end
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
- end
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,7 @@
1
+ class Hash
2
+ def first
3
+ self.each do |k,v|
4
+ return {k => v}
5
+ end
6
+ end
7
+ 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
 
@@ -1,4 +1,4 @@
1
1
  module Pushover
2
2
  # The current version of Pushover.
3
- VERSION = "0.99.2"
3
+ VERSION = "1.0.0"
4
4
  end
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 'bini', '~> 0.6.0'
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
@@ -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
+
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe "application" do
4
4
  before(:each) do
5
- Bini::Config.file = "tmp/test.save"
6
5
  Bini::Config.clear
7
6
  Bini::Options.clear
8
7
  App.current_app = nil
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe "user" do
4
4
  before(:each) do
5
- Bini::Config.file = "tmp/test.save"
6
5
  Bini::Config.clear
7
6
  Bini::Options.clear
8
7
  User.current_user = nil
@@ -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
- stub_http_request(:post, "https://api.pushover.net/1/messages.json").to_return(:status => 200,
33
- :headers => {}, :body => good_result).with(:body => hash_including({token:'good_token', user:'good_user'}))
34
- stub_http_request(:post, "https://api.pushover.net/1/messages.json").to_return(:status => 200,
35
- :headers => {}, :body => bad_token).with(:body => hash_including({token:'bad_token', user:'good_user'}))
36
- stub_http_request(:post, "https://api.pushover.net/1/messages.json").to_return(:status => 200,
37
- :headers => {}, :body => bad_user).with(:body => hash_including({token:'good_token', user:'bad_user'}))
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.99.2
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-06-13 00:00:00.000000000 Z
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: '0'
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: '0'
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.6.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.6.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.2
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