pushover 1.0.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
7
-
6
+ task default: :spec
@@ -1,154 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'pushover'
4
-
5
- include Bini
6
- include Pushover
7
- Options.on("-u", "--user USER", "Which user, can be a saved name or token.") { |o| Options[:user] = o}
8
- Options.on("-a", "--app APPKEY", "Which app to notify, can be a saved name or apikey.") { |o| Options[:token] = o}
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,emergency) (optional).") { |o| Options[:priority] = o}
11
- Options.on("-d", "--device [DEVICE]", "Specify the device to send the notifcation to. (optional).") { |o| Options[:device] = o}
12
- Options.on("-c", "--config_file [FILE]", "Set the target config file.") {|o| Options[:config_file] = o}
13
- Options.on("--url [URL]", "Supplementary URL") { |o| Options[:url] = o }
14
- Options.on("--url_title [TITLE]", "Supplementary URL title.") { |o| Options[:url_title] = o }
15
- Options.on("--time [TIME]", "Set the messages time.") {|o| Options[:timestamp] = o}
16
- Options.on("--save-app NAME", "Saves the application to the config file under NAME.") { |o| Options[:save_app] = o}
17
- Options.on("--save-user NAME", "Saves the user to the config file under NAME.") { |o| Options[:save_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}
24
-
25
- Options.parse!
26
- bail = false
27
-
28
- # Order is important.
29
- if Options[:config_file]
30
- Bini::Config.options[:file] = Options[:config_file]
31
- puts "Selected config file: #{Options[:config_file]}"
32
- # TODO: Make a healper for changing config so it clears/loads automatically.
33
- Bini::Config.clear
34
- Bini::Config.load
35
- end
36
-
37
- if Options[:save_app]
38
- App.add Options[:save_app], Options[:token]
39
- puts "Saved application #{Options[:token]} to #{Options[:save_app]}."
40
- bail = true
41
- end
42
-
43
- if Options[:save_user]
44
- User.add Options[:save_user], Options[:user]
45
- puts "Saved user #{Options[:user]} to #{Options[:save_user]}."
46
- bail = true
47
- end
48
-
49
- exit if bail # We don't care if we have a message, we should exit here.
50
-
51
- if !App.current_app?
52
- puts "Couldn't find an app via the cli or save file."
53
- bail = true
54
- end
55
-
56
- if !User.current_user?
57
- puts "Couldn't find a user via the cli or save file."
58
- bail = true
59
- end
60
-
61
- if Options[:sound_list]
62
- puts "Current Sound List:"
63
- if Pushover.sounds
64
- Pushover.sounds.each { |k,v| puts " #{v}" }
65
- else
66
- puts "Error retrieving sound list, are you connected to the internet? are your credentials correct?"
67
- exit
68
- end
69
- bail = true
70
- end
71
-
72
- if Options[:receipts]
73
- puts 'Updating receipts'
74
- Pushover::Priority.update_receipts
75
- Pushover::Priority::Receipts.each do |k,v|
76
- if v["acknowledged"] != 0
77
- print "Receipt #{k} was acknowledged at #{Time.at v["acknowledged_at"]}, "
78
- else
79
- print "Receipt #{k} has not been acknowledged yet, "
80
- end
81
-
82
- if v["expired"] == 0
83
- puts "and will expire at: #{Time.at v["expires_at"]}."
84
- else
85
- puts "and expired at: #{Time.at v["expires_at"]}."
86
- end
87
- end
88
- exit
89
- end
90
-
91
- if Options[:sound]
92
- sounds = Pushover.sounds
93
- if !sounds
94
- puts "Error retrieving sound list, are you connected to the internet? are your credentials correct?"
95
- exit
96
- end
97
- match = sounds.select { |k,v| v.downcase.start_with? Options[:sound].downcase}
98
- if !match || match.count == 0
99
- puts "No such sound: #{Options[:sound]}."
100
- bail = true
101
- elsif match.count > 1
102
- print "Sound is ambiguous, possible matches: "
103
- match.each {|k,v| print "#{v} "}
104
- print "\n"
105
- bail = true
106
- else
107
- Options[:sound] = match.first[0]
108
- end
109
- end
110
-
111
- if Options[:priority]
112
- # Is this an emergency, did we include everything we need?
113
- if Priority.is_emergency?(Options[:priority])
114
- Options[:retry] = 30 if !Options[:retry]
115
- Options[:expire] = 86400 if !Options[:expire]
116
- end
117
- end
118
-
119
- exit if bail
120
-
121
- message = ARGV.join(" ")
122
- if !message
123
- puts "Must supply a message to be sent."
124
- bail = true
125
- end
126
-
127
- exit if bail
128
-
129
- options = Options[].select { |k,v| v}
130
- options[:token] = Pushover::App.current_app
131
- options[:user] = Pushover::User.current_user
132
-
133
- options.delete :config_file
134
- options.merge! message:message
135
-
136
- response = Pushover.notification options
137
- if response.code == 500
138
- puts "Something is broken at pushover.net and it is returning 500's (server errors). Here is the response body."
139
- puts response.body
140
- exit
141
- end
142
- j = Yajl.load response.body
143
-
144
- if response.code == 200
145
- if Priority.is_emergency?(Options[:priority])
146
- j = Yajl.load response.body
147
- Pushover::Priority.process_receipt j["receipt"]
148
- puts "emergency notification receipt: #{j["receipt"]}"
149
- end
150
- puts "Message sent successfully!"
151
- else
152
- puts "ErrorCode (#{response.code}): #{j['errors'].first}."
153
- end
154
-
@@ -1,148 +1,12 @@
1
- require 'httparty'
2
- require "yajl"
3
- require 'time'
4
- require 'bini'
5
- require 'bini/config'
6
- require 'bini/optparser'
7
- require 'open-uri'
8
- require 'pushover/mixins.rb'
1
+ require 'oj'
2
+ require 'creatable'
9
3
 
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
4
+ require 'pushover/api'
5
+ require 'pushover/message'
6
+ require 'pushover/receipt'
7
+ require 'pushover/response'
8
+ require 'pushover/request'
16
9
 
17
- # The primary pushover namespace.
10
+ # pushover interface for ruby
18
11
  module Pushover
19
- # Unfuckingbelievable. My code, and I still can't get it to work as expected.
20
- Bini.long_name = 'pushover'
21
- # lets save our config to it's own dir, just because.
22
- Bini::Config.options[:file] = "#{Dir.home}/.config/pushover/credentials.yaml"
23
- Bini::Config.load
24
-
25
- extend self
26
-
27
- # [String] The api key to be used for the notifcation.
28
- attr_accessor :token
29
- # [String] of the user token currently being used.
30
- attr_accessor :user
31
- # [String] message the message to be sent.
32
- attr_accessor :message
33
- # [optional,String] Title of the message.
34
- attr_accessor :title
35
- # [optional,String] device to recieve the message.
36
- attr_accessor :device
37
- attr_reader :priority
38
- attr_accessor :url
39
- attr_accessor :url_title
40
- attr_accessor :emergency_retry
41
- attr_accessor :emergency_expire
42
- attr_accessor :emergency_callback
43
- # [optional,String, Fixnum] time a time stamp im one of three forms (epoch, strfmt, rails)
44
- attr_reader :timestamp
45
-
46
- # Stdlib time, seems to take a shitload of options.
47
- # rfc822: Tue, 14 Nov 2000 14:55:07 -0500
48
- # xml: 1979-08-13T06:30:00.313UTC
49
- # Time.parse 'Aug 13, 1979 6:30'
50
- # Time.parse '1979/08/13, 6:30:50 UTC'
51
- def timestamp=(time_string)
52
- @timestamp = timestamp_magic time_string
53
- end
54
-
55
- # push a message to pushover, must supply all variables.
56
- # @param [String] message The message to be sent
57
- # @param [optional, String] title The title of the message
58
- # @param [optional, Fixnum] priority of the message to be sent, from -1 to 1.
59
- # @param [optional, String] device The specific device to be notified.
60
- # @param [optional, String] app api key.
61
- # @param [optional, String] user the user token.
62
- # @return [String] the response from pushover.net, in json.
63
- def notification(tokens={})
64
- tokens[:timestamp] = timestamp_magic tokens[:timestamp] if tokens[:timestamp]
65
- tokens[:priority] = Pushover::Priority.parse tokens[:priority] if tokens[:priority]
66
- tokens[:user] ||= @user
67
- tokens[:token] ||= @token
68
-
69
- HTTParty.post('https://api.pushover.net/1/messages.json', body:tokens)
70
- end
71
-
72
- # Return a [Hash] of sounds.
73
- def sounds
74
- cache_file = "#{Bini.cache_dir}/sounds.json"
75
- sounds = {}
76
-
77
- cache_sounds if File.exists?(cache_file) && File.stat(cache_file).mtime < Time.at(Time.now.day - 1)
78
-
79
- return nil if !cache_sounds
80
- sounds = Yajl.load open(cache_file).read
81
- sounds["sounds"]
82
- end
83
-
84
- # Adds a rails style configure method
85
- def configure
86
- yield self
87
- parameters
88
- end
89
-
90
- # List available parameters and values in those params
91
- def parameters
92
- h = {}
93
- keys.each { |k| h[k.to_sym] = Pushover.instance_variable_get("@#{k}") }
94
- return h
95
- end
96
- alias_method :params, :parameters
97
-
98
- # Returns true or false if all parameters are set.
99
- def parameters?
100
- parameters.values.all?
101
- end
102
-
103
- # Clear all the currently set parameters
104
- def clear
105
- keys.each do |k|
106
- Pushover.instance_variable_set("@#{k}", nil)
107
- end
108
- end
109
-
110
- # A [Array] of keys available in Pushover.
111
- def keys
112
- Pushover.instance_methods.select do |m|
113
- m =~ /=$/
114
- end.map do |m|
115
- m[0..-2]
116
- end
117
- end
118
-
119
-
120
- private
121
-
122
- def timestamp_magic(time_string)
123
- if time_string.class == String
124
- begin
125
- return Time.parse(time_string).to_i
126
- rescue ArgumentError
127
- return time_string.to_i
128
- end
129
- elsif
130
- time_string.class == Fixnum
131
- return time_string
132
- end
133
- end
134
-
135
- def cache_sounds
136
- cache_file = "#{Bini.cache_dir}/sounds.json"
137
-
138
- response = HTTParty.get('https://api.pushover.net/1/sounds.json', query:{token:Pushover::App.current_app})
139
-
140
- return nil if response.code != 200
141
- FileUtils.mkdir_p Bini.cache_dir
142
- f = open(cache_file, 'w')
143
- f.write response.body
144
- f.flush
145
- f.close
146
- return true
147
- end
148
12
  end
@@ -0,0 +1,35 @@
1
+ require 'creatable'
2
+ require 'excon'
3
+ require 'oj'
4
+
5
+ require 'pushover/response'
6
+
7
+ module Pushover
8
+ # Api module
9
+ module Api
10
+ module_function
11
+
12
+ def endpoints
13
+ %i[messages sounds limits receipts validate]
14
+ end
15
+
16
+ def sounds
17
+ %i[ pushover bike bugle cashregister classical cosmic falling gamelan incoming
18
+ intermission magic mechanical pianobar siren spacealarm tugboat alien
19
+ climb persistent echo updown none]
20
+ end
21
+
22
+ def connection
23
+ Excon.new url
24
+ end
25
+
26
+ def initialize
27
+ Excon.defaults[:headers]['Content-Type'] = 'application/json'
28
+ Excon.defaults[:headers]['User-Agent'] = "pushover (ruby gem) v#{Pushover::VERSION}"
29
+ end
30
+
31
+ def url
32
+ "https://api.pushover.net"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ # Pushover interface
2
+ module Pushover
3
+ class Message
4
+ include Creatable
5
+
6
+ attribute name: 'attachment'
7
+ attribute name: 'device', kind_of: String
8
+ attribute name: 'html', kind_of: TrueClass
9
+ attribute name: 'message', kind_of: String
10
+ attribute name: 'priority', kind_of: String
11
+ attribute name: 'sound', kind_of: String
12
+ attribute name: 'timestamp', kind_of: Numeric
13
+ attribute name: 'title', kind_of: String
14
+ attribute name: 'token', kind_of: String
15
+ attribute name: 'response', kind_of: Pushover::Response
16
+ attribute name: 'url_title', kind_of: String
17
+ attribute name: 'url', kind_of: String
18
+ attribute name: 'user', kind_of: String
19
+
20
+ def initialize
21
+ @timestamp = Time.now.to_i
22
+ end
23
+
24
+ def push
25
+ raise ArgumentError, 'user is a required parameter' unless user
26
+ raise ArgumentError, 'token is a required parameter' unless token
27
+ raise ArgumentError, 'message is a required parameter' unless message
28
+
29
+ query = {}
30
+
31
+ attributes.each { |e| query.store e[:name], instance_variable_get("@#{e[:name]}") if instance_variable_get("@#{e[:name]}") }
32
+
33
+ response = Request.create.push(:messages, query)
34
+ response.process
35
+ @response = response
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module Pushover
2
+ # Receipt class
3
+ class Receipt
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module Pushover
2
+ class Request
3
+ include Creatable
4
+
5
+ def push(endpoint, config = {})
6
+ excon_response = Api.connection.post path: "1/#{endpoint}.json", query: config
7
+ response = Response.create original: excon_response
8
+ response.process
9
+ @response = response
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,40 @@
1
+ module Pushover
2
+ class Response
3
+ include Creatable
4
+
5
+ attribute name: 'user', kind_of: String
6
+ attribute name: 'errors', kind_of: Array
7
+ attribute name: 'status', kind_of: Numeric
8
+ attribute name: 'receipt', kind_of: String
9
+ attribute name: 'request', kind_of: String
10
+ attribute name: 'original', kind_of: String
11
+ attribute name: 'limit', kind_of: String
12
+ attribute name: 'remaining', kind_of: String
13
+ attribute name: 'reset', kind_of: String
14
+
15
+ def initialize
16
+ @status = 0
17
+ @errors = []
18
+ end
19
+
20
+ def process
21
+ process_body
22
+ process_headers
23
+ end
24
+
25
+ def process_body
26
+ body = Oj.load original[:body]
27
+
28
+ @status = body["status"]
29
+ @request = body["request"]
30
+ @receipt = body["receipt"] if body["receipt"]
31
+ @errors = body["errors"] if body["errors"]
32
+ end
33
+
34
+ def process_headers
35
+ @limit = original.headers['X-Limit-App-Limit']
36
+ @remaining = original.headers['X-Limit-App-Remaining']
37
+ @reset = original.headers['X-Limit-App-Reset']
38
+ end
39
+ end
40
+ end