pushover 1.0.4 → 2.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.
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