pixeltrix-prowler 1.0.3 → 1.1.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/CHANGELOG CHANGED
@@ -1,3 +1,20 @@
1
+ *1.1.0 (July 10th, 2009)
2
+
3
+ * Add support for Delayed::Job background processing
4
+
5
+ * Update documentation for instance level configuration
6
+
7
+ * Add support for instance level configuration
8
+
9
+ * Add support for provider key
10
+
11
+ * Clean up implementation
12
+
13
+ * Remove unnecessary configuration
14
+
15
+ * Remove deprecated API
16
+
17
+
1
18
  *1.0.3 (July 9th, 2009)
2
19
 
3
20
  * Add verify method for configured API key
data/INSTALL CHANGED
@@ -32,6 +32,23 @@ To use Prowler within your application just call the notify method, e.g.
32
32
 
33
33
  Prowler.notify "Event", "Description", Prowler::Priority::NORMAL
34
34
 
35
+ If you need to send to multiple accounts from within a single application you
36
+ can create an instance of the Prowler class to override the global settings, e.g.
37
+
38
+ prowler = Prowler.new('apikey', 'application')
39
+ prowler.notify "Event", "Description", Prowler::Priority::NORMAL
40
+
41
+ If performance is a concern then there is built in support for Delayed::Job.
42
+ This can done either on a global basis, e.g.
43
+
44
+ Prowler.configure do |config|
45
+ config.delayed = true
46
+ end
47
+
48
+ or on a individual message basis, e.g.
49
+
50
+ Prowler.notify "Event", "Description", Prowler::Priority::NORMAL, true
51
+
35
52
  ABOUT
36
53
 
37
54
  Prowler relies upon the Prowl iPhone application which is advertised as
data/README CHANGED
@@ -32,6 +32,23 @@ To use Prowler within your application just call the notify method, e.g.
32
32
 
33
33
  Prowler.notify "Event", "Description", Prowler::Priority::NORMAL
34
34
 
35
+ If you need to send to multiple accounts from within a single application you
36
+ can create an instance of the Prowler class to override the global settings, e.g.
37
+
38
+ prowler = Prowler.new('apikey', 'application')
39
+ prowler.notify "Event", "Description", Prowler::Priority::NORMAL
40
+
41
+ If performance is a concern then there is built in support for Delayed::Job.
42
+ This can done either on a global basis, e.g.
43
+
44
+ Prowler.configure do |config|
45
+ config.delayed = true
46
+ end
47
+
48
+ or on a individual message basis, e.g.
49
+
50
+ Prowler.notify "Event", "Description", Prowler::Priority::NORMAL, true
51
+
35
52
  ABOUT
36
53
 
37
54
  Prowler relies upon the Prowl iPhone application which is advertised as
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.1.0
data/lib/prowler.rb CHANGED
@@ -29,6 +29,23 @@
29
29
  #
30
30
  # Prowler.notify "Event", "Description", Prowler::Priority::NORMAL
31
31
  #
32
+ # If you need to send to multiple accounts from within a single application you
33
+ # can create an instance of the Prowler class to override the global settings, e.g.
34
+ #
35
+ # prowler = Prowler.new('apikey', 'application')
36
+ # prowler.notify "Event", "Description", Prowler::Priority::NORMAL
37
+ #
38
+ # If performance is a concern then there is built in support for Delayed::Job.
39
+ # This can done either on a global basis, e.g.
40
+ #
41
+ # Prowler.configure do |config|
42
+ # config.delayed = true
43
+ # end
44
+ #
45
+ # or on a individual message basis, e.g.
46
+ #
47
+ # Prowler.notify "Event", "Description", Prowler::Priority::NORMAL, true
48
+ #
32
49
  # === About
33
50
  #
34
51
  # Prowler relies upon the Prowl iPhone application which is advertised as
@@ -39,15 +56,13 @@
39
56
  # For more about the Prowl application see: http://prowl.weks.net/
40
57
 
41
58
  require 'logger'
42
- require 'net/http'
43
59
  require 'net/https'
60
+ require 'uri'
44
61
 
45
- module Prowler
62
+ class Prowler
46
63
 
47
- API_PATH = "/publicapi/add"
48
- DEPRECATED_API_PATH = "/api/add_notification.php?application=%s&event=%s&description=%s"
49
- VERIFY_PATH = "/publicapi/verify?apikey=%s"
50
- USER_AGENT = "Prowler/1.0.3"
64
+ SERVICE_URL = "https://prowl.weks.net/publicapi"
65
+ USER_AGENT = "Prowler/1.1.0"
51
66
 
52
67
  module Priority
53
68
  VERY_LOW = -2
@@ -57,50 +72,50 @@ module Prowler
57
72
  EMERGENCY = 2
58
73
  end
59
74
 
60
- class << self
61
- attr_accessor :host, :port, :secure
62
- attr_accessor :api_key, :username, :password
63
- attr_accessor :application, :send_notifications
75
+ class ConfigurationError < StandardError; end
64
76
 
65
- # The host to connect to.
66
- def host
67
- @host ||= 'prowl.weks.net'
68
- end
77
+ class DelayedJob
78
+ attr_accessor :api_key, :provider_key, :application
79
+ attr_accessor :event, :message, :priority
69
80
 
70
- # The port on which the service runs.
71
- def port
72
- @port || (secure ? 443 : 80)
81
+ def initialize #:nodoc:
82
+ yield self if block_given?
73
83
  end
74
84
 
75
- # Whether the service is running over SSL.
76
- def secure
77
- @secure.nil? ? true : !!@secure
85
+ # Send notification
86
+ def perform
87
+ prowler = Prowler.new(api_key, application, provider_key)
88
+ prowler.notify(event, message, priority, false)
78
89
  end
90
+ end
91
+
92
+ class << self
93
+ attr_accessor :api_key, :provider_key
94
+ attr_accessor :application, :send_notifications
95
+ attr_accessor :read_timeout, :open_timeout #:nodoc:
96
+ attr_accessor :delayed
79
97
 
80
98
  # Call this method to configure your account details in an initializer.
81
99
  def configure
82
100
  yield self
83
101
  end
84
102
 
85
- def username=(value) #:nodoc:
86
- logger.warn "The username/password API has been deprecated please switch to using an API key."
87
- @username = value
103
+ def send_notifications #:nodoc:
104
+ @send_notifications.nil? ? true : !!@send_notifications
88
105
  end
89
106
 
90
- # Whether to send notifications
91
- def send_notifications
92
- @send_notifications.nil? ? true : !!@send_notifications
107
+ def delayed #:nodoc:
108
+ @delayed.nil? ? false : !!@delayed
93
109
  end
94
- alias :send_notifications? :send_notifications
95
110
 
96
111
  # Reset configuration
97
112
  def reset_configuration
98
- @host = @port = @secure = @application = @username = @password = @api_key = nil
113
+ @application = @api_key = @provider_key = nil
99
114
  end
100
115
 
101
116
  # Whether the library has been configured
102
117
  def configured?
103
- !@application.nil? && (!@api_key.nil? || !(@username.nil? || @password.nil?))
118
+ !@application.nil? && !@api_key.nil?
104
119
  end
105
120
 
106
121
  # Returns the default logger or a logger that prints to STDOUT.
@@ -110,75 +125,146 @@ module Prowler
110
125
  @logger ||= Logger.new(STDERR)
111
126
  end
112
127
 
128
+ def read_timeout #:nodoc:
129
+ @read_timeout ||= 5
130
+ end
131
+
132
+ def open_timeout #:nodoc:
133
+ @open_timeout ||= 2
134
+ end
135
+
113
136
  # Send a notification to your iPhone:
114
137
  # * event: The title of notification you want to send.
115
138
  # * message: The text of the notification message you want to send.
116
139
  # * priority: The priority of the notification - see Prowler::Priority. (Optional)
117
- def notify(event, message, priority = Priority::NORMAL)
118
- raise RuntimeError, "Prowler needs to be configured first before using it" unless configured?
119
-
120
- http = Net::HTTP.new(host, port)
121
- http.use_ssl = secure
122
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
123
- http.start do
124
- headers = {
125
- 'User-Agent' => USER_AGENT
126
- }
127
- http.read_timeout = 5 # seconds
128
- http.open_timeout = 2 # seconds
129
- if api_key
130
- request = Net::HTTP::Post.new(API_PATH, headers)
131
- request.set_form_data({ 'apikey' => api_key, 'priority' => priority, 'application' => application, 'event' => event, 'description' => message })
132
- else
133
- request = Net::HTTP::Get.new(sprintf(DEPRECATED_API_PATH, URI.escape(application), URI.escape(event), URI.escape(message)), headers)
134
- request.basic_auth(username, password)
135
- end
136
- response = begin
137
- http.request(request) if send_notifications?
138
- rescue TimeoutError => e
139
- logger.error "Timeout while contacting the Prowl server."
140
- nil
141
- end
142
- case response
143
- when Net::HTTPSuccess then
144
- logger.info "Prowl Success: #{response.class}"
145
- when NilClass then
146
- # Do nothing
147
- else
148
- logger.error "Prowl Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
149
- end
140
+ # * delayed: Whether to use Delayed::Job to send notifications. (Optional)
141
+ def notify(event, message, priority = Priority::NORMAL, delayed = self.delayed)
142
+ raise ConfigurationError, "You must provide an API key to send notifications" if api_key.nil?
143
+ raise ConfigurationError, "You must provide an application name to send notifications" if application.nil?
144
+ if delayed
145
+ enqueue_delayed_job(self, event, message, priority)
146
+ else
147
+ perform(
148
+ :add, api_key, provider_key,
149
+ {
150
+ :application => application,
151
+ :event => event,
152
+ :description => message,
153
+ :priority => priority
154
+ }
155
+ )
150
156
  end
151
157
  end
152
158
 
153
159
  # Verify the configured API key is valid
154
160
  def verify
155
- raise RuntimeError, "Prowler needs to be configured first before using it" unless api_key
156
-
157
- http = Net::HTTP.new(host, port)
158
- http.use_ssl = secure
159
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
160
- http.start do
161
- headers = {
162
- 'User-Agent' => USER_AGENT
163
- }
164
- http.read_timeout = 5 # seconds
165
- http.open_timeout = 2 # seconds
166
- request = Net::HTTP::Get.new(sprintf(VERIFY_PATH, api_key), headers)
167
- response = begin
168
- http.request(request) if send_notifications?
169
- rescue TimeoutError => e
170
- logger.error "Timeout while contacting the Prowl server."
171
- nil
172
- end
173
- case response
174
- when Net::HTTPSuccess then
175
- logger.info "Prowl Success: #{response.class}"
176
- true
177
- else
178
- logger.error "Prowl Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
179
- false
161
+ raise ConfigurationError, "You must provide an API key to verify" if api_key.nil?
162
+ perform(:verify, api_key, provider_key, {}, :get)
163
+ end
164
+
165
+ def perform(command, api_key, provider_key, data = {}, method = :post) #:nodoc:
166
+ params = { :apikey => api_key, :provider_key => provider_key }.merge(data).delete_if { |k,v| v.nil? }
167
+ case method
168
+ when :post
169
+ perform_post(command, params)
170
+ else
171
+ perform_get(command, params)
172
+ end
173
+ end
174
+
175
+ def enqueue_delayed_job(config, event, message, priority) #:nodoc:
176
+ record = Delayed::Job.enqueue(DelayedJob.new do |job|
177
+ job.api_key = config.api_key
178
+ job.provider_key = config.provider_key
179
+ job.application = config.application
180
+ job.event = event
181
+ job.message = message
182
+ job.priority = priority
183
+ end)
184
+ !record.new_record?
185
+ end
186
+
187
+ private
188
+ def headers(extra_headers = {}) #:nodoc:
189
+ { 'User-Agent' => USER_AGENT }.merge(extra_headers)
190
+ end
191
+
192
+ def perform_get(command, params) #:nodoc:
193
+ url = URI.parse("#{SERVICE_URL}/#{command}?#{params.map{ |k,v| %(#{URI.encode(k.to_s)}=#{URI.encode(v.to_s)}) }.join('&')}")
194
+ request = Net::HTTP::Get.new("#{url.path}?#{url.query}", headers)
195
+ perform_request(url, request)
196
+ end
197
+
198
+ def perform_post(command, params) #:nodoc:
199
+ url = URI.parse("#{SERVICE_URL}/#{command}")
200
+ request = Net::HTTP::Post.new(url.path, headers)
201
+ request.form_data = params
202
+ perform_request(url, request)
203
+ end
204
+
205
+ def perform_request(url, request) #:nodoc:
206
+ http = Net::HTTP.new(url.host, url.port)
207
+ http.use_ssl = true
208
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
209
+ http.read_timeout = read_timeout
210
+ http.open_timeout = open_timeout
211
+ http.start do
212
+ begin
213
+ return true unless send_notifications
214
+ response = http.request(request)
215
+ case response
216
+ when Net::HTTPSuccess then
217
+ logger.info "Prowl Success: #{response.class}"
218
+ true
219
+ else
220
+ logger.error "Prowl Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
221
+ false
222
+ end
223
+ rescue TimeoutError => e
224
+ logger.error "Timeout while contacting the Prowl server."
225
+ false
226
+ end
180
227
  end
181
228
  end
229
+ end
230
+
231
+ attr_accessor :api_key, :provider_key #:nodoc:
232
+ attr_accessor :application, :send_notifications #:nodoc:
233
+
234
+ # Create an instance for sending to different accounts within a single Rails application
235
+ # * api_key: Your API key.
236
+ # * application: The name of your application.
237
+ # * provider_key: Key to override the rate limit of 1000 requests per hour. (Optional)
238
+ def initialize(api_key, application, provider_key = nil)
239
+ @api_key, @application, @provider_key = api_key, application, provider_key
240
+ end
241
+
242
+ # Send a notification to your iPhone:
243
+ # * event: The title of notification you want to send.
244
+ # * message: The text of the notification message you want to send.
245
+ # * priority: The priority of the notification - see Prowler::Priority. (Optional)
246
+ # * delayed: Whether to use Delayed::Job to send notifications. (Optional)
247
+ def notify(event, message, priority = Priority::NORMAL, delayed = self.class.delayed)
248
+ raise ConfigurationError, "You must provide an API key to send notifications" if api_key.nil?
249
+ raise ConfigurationError, "You must provide an application name to send notifications" if application.nil?
250
+ if delayed
251
+ self.class.enqueue_delayed_job(self, event, message, priority)
252
+ else
253
+ self.class.perform(
254
+ :add, api_key, provider_key,
255
+ {
256
+ :application => application,
257
+ :event => event,
258
+ :description => message,
259
+ :priority => priority
260
+ }
261
+ )
182
262
  end
183
263
  end
264
+
265
+ # Verify the configured API key is valid
266
+ def verify
267
+ raise ConfigurationError, "You must provide an API key to verify" if api_key.nil?
268
+ self.class.perform(:verify, api_key, provider_key, {}, :get)
269
+ end
184
270
  end
data/prowler.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{prowler}
5
- s.version = "1.0.3"
5
+ s.version = "1.1.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Andrew White"]
9
- s.date = %q{2009-07-09}
9
+ s.date = %q{2009-07-10}
10
10
  s.description = %q{A simple wrapper class that provides basic access to the Prowl API.}
11
11
  s.email = %q{andyw@pixeltrix.co.uk}
12
12
  s.extra_rdoc_files = [
data/test/prowler_test.rb CHANGED
@@ -13,32 +13,14 @@ class ProwlerTest < Test::Unit::TestCase
13
13
 
14
14
  should "be done with a block" do
15
15
  Prowler.configure do |config|
16
- config.host = "prowler"
17
- config.port = 666
18
- config.secure = false
19
16
  config.api_key = "apikey"
20
17
  config.application = "application"
21
18
  end
22
19
 
23
- assert_equal "prowler", Prowler.host
24
- assert_equal 666, Prowler.port
25
- assert_equal false, Prowler.secure
26
20
  assert_equal "apikey", Prowler.api_key
27
21
  assert_equal "application", Prowler.application
28
22
  end
29
23
 
30
- should "set a default host" do
31
- assert_equal "prowl.weks.net", Prowler.host
32
- end
33
-
34
- should "set a default port" do
35
- assert_equal 443, Prowler.port
36
- end
37
-
38
- should "default to secure" do
39
- assert_equal true, Prowler.secure
40
- end
41
-
42
24
  should "not set a default application" do
43
25
  assert_equal nil, Prowler.application
44
26
  end
@@ -47,55 +29,63 @@ class ProwlerTest < Test::Unit::TestCase
47
29
  assert_equal nil, Prowler.api_key
48
30
  end
49
31
 
50
- should "raise an exception if not configured" do
51
- assert_raises RuntimeError do
52
- Prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
53
- end
32
+ should "override class configuration when using an instance" do
33
+ prowler = Prowler.new("apikey2", "application2")
34
+ assert_equal "apikey2", prowler.api_key
35
+ assert_equal "application2", prowler.application
54
36
  end
55
37
  end
56
38
 
57
- context "Prowler deprecated configuration" do
39
+ context "Sending a notification" do
58
40
  setup do
59
- Logger.any_instance.stubs(:warn)
60
41
  Prowler.reset_configuration
42
+ Prowler.configure do |config|
43
+ config.api_key = "apikey"
44
+ config.application = "Application Name"
45
+ end
61
46
  Prowler.send_notifications = false
62
47
  end
63
48
 
64
- should "be done with a block" do
65
- Prowler.configure do |config|
66
- config.host = "prowler"
67
- config.port = 666
68
- config.secure = false
69
- config.application = "application"
70
- config.username = "username"
71
- config.password = "password"
49
+ should "raise an exception if API key not configured" do
50
+ Prowler.reset_configuration
51
+ assert_raises Prowler::ConfigurationError do
52
+ Prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
72
53
  end
73
54
 
74
- assert_equal "username", Prowler.username
75
- assert_equal "password", Prowler.password
55
+ prowler = Prowler.new(nil, nil)
56
+ assert_raises Prowler::ConfigurationError do
57
+ prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
58
+ end
76
59
  end
77
60
 
78
- should "log a warning when using the deprecated API" do
79
- Logger.any_instance.expects(:warn).with("The username/password API has been deprecated please switch to using an API key.")
80
- Prowler.configure { |config| config.username = "username" }
81
- end
61
+ should "raise an exception if application not configured" do
62
+ Prowler.reset_configuration
63
+ Prowler.configure do |config|
64
+ config.api_key = "apikey"
65
+ end
66
+ assert_raises Prowler::ConfigurationError do
67
+ Prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
68
+ end
82
69
 
83
- should "not set a default username" do
84
- assert_equal nil, Prowler.username
70
+ prowler = Prowler.new("apikey", nil)
71
+ assert_raises Prowler::ConfigurationError do
72
+ prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
73
+ end
85
74
  end
86
75
 
87
- should "not set a default password" do
88
- assert_equal nil, Prowler.password
76
+ should "not verify SSL certificates" do
77
+ Net::HTTP.any_instance.expects(:use_ssl=).with(true)
78
+ Net::HTTP.any_instance.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
79
+ Prowler.notify("Event Name", "Message Text", Prowler::Priority::NORMAL)
89
80
  end
90
81
 
91
- should "raise an exception if not configured" do
92
- assert_raises RuntimeError do
93
- Prowler.notify("Event", "Description", Prowler::Priority::NORMAL)
94
- end
82
+ should "not send notifications if send_notifications is false" do
83
+ Net::HTTP.any_instance.expects(:request).never
84
+ Prowler.notify("Event Name", "Message Text", Prowler::Priority::NORMAL)
95
85
  end
96
86
  end
97
87
 
98
- context "Sending a notification" do
88
+ context "Verifying an API key" do
99
89
  setup do
100
90
  Prowler.reset_configuration
101
91
  Prowler.configure do |config|
@@ -105,15 +95,27 @@ class ProwlerTest < Test::Unit::TestCase
105
95
  Prowler.send_notifications = false
106
96
  end
107
97
 
98
+ should "raise an exception if API key not configured" do
99
+ Prowler.reset_configuration
100
+ assert_raises Prowler::ConfigurationError do
101
+ Prowler.verify
102
+ end
103
+
104
+ prowler = Prowler.new(nil, nil)
105
+ assert_raises Prowler::ConfigurationError do
106
+ prowler.verify
107
+ end
108
+ end
109
+
108
110
  should "not verify SSL certificates" do
109
111
  Net::HTTP.any_instance.expects(:use_ssl=).with(true)
110
112
  Net::HTTP.any_instance.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
111
- Prowler.notify("Event Name", "Message Text", Prowler::Priority::NORMAL)
113
+ Prowler.verify
112
114
  end
113
115
 
114
116
  should "not send notifications if send_notifications is false" do
115
117
  Net::HTTP.any_instance.expects(:request).never
116
- Prowler.notify("Event Name", "Message Text", Prowler::Priority::NORMAL)
118
+ Prowler.verify
117
119
  end
118
120
  end
119
121
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pixeltrix-prowler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew White
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-09 00:00:00 -07:00
12
+ date: 2009-07-10 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15