-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added GrowlAgent for sending Growl notifications over GNTP #172
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
require 'ruby-growl' | ||
|
||
module Agents | ||
class GrowlAgent < Agent | ||
attr_reader :growler | ||
|
||
cannot_be_scheduled! | ||
cannot_create_events! | ||
|
||
description <<-MD | ||
The GrowlAgent sends any events it receives to a Growl GNTP server immediately. | ||
|
||
It is assumed that events have a `message` or `text` key, which will hold the body of the growl notification, and a `subject` key, which will have the headline of the Growl notification. You can use Event Formatting Agent if your event does not provide these keys. | ||
|
||
Set `expected_receive_period_in_days` to the maximum amount of time that you'd expect to pass between Events being received by this Agent. | ||
MD | ||
|
||
def default_options | ||
{ | ||
'growlserver' => 'localhost', | ||
'growlpassword' => '', | ||
'growlappname' => 'HuginnGrowl', | ||
'growlnotificationname' => 'Notification', | ||
'expected_receive_period_in_days' => "2" | ||
} | ||
end | ||
|
||
def working? | ||
last_receive_at && last_receive_at > options['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs? | ||
end | ||
|
||
def validate_options | ||
unless options['growlserver'].present? && options['expected_receive_period_in_days'].present? | ||
errors.add(:base, "growlserver and expected_receive_period_in_days are required fields") | ||
end | ||
end | ||
|
||
def register_growl | ||
@growler = Growl.new options['growlserver'], options['growlappname'], "GNTP" | ||
@growler.password = options['growlpassword'] | ||
@growler.add_notification options['growlnotificationname'] | ||
end | ||
|
||
def notify_growl(subject, message) | ||
@growler.notify(options['growlnotificationname'],subject,message) | ||
end | ||
|
||
def receive(incoming_events) | ||
register_growl | ||
incoming_events.each do |event| | ||
message = (event.payload['message'] || event.payload['text']).to_s | ||
subject = event.payload['subject'].to_s | ||
if message.present? && subject.present? | ||
log "Sending Growl notification '#{subject}': '#{message}' to #{options['growlserver']} with event #{event.id}" | ||
notify_growl(subject,message) | ||
else | ||
log "Event #{event.id} not sent, message and subject expected" | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
require 'spec_helper' | ||
|
||
describe Agents::GrowlAgent do | ||
before do | ||
@checker = Agents::GrowlAgent.new(:name => 'a growl agent', | ||
:options => { :growlserver => 'localhost', | ||
:growlappname => 'HuginnGrowlApp', | ||
:growlpassword => 'mypassword', | ||
:growlnotificationname => 'Notification', | ||
:expected_receive_period_in_days => '1' }) | ||
@checker.user = users(:bob) | ||
@checker.save! | ||
|
||
stub.any_instance_of(Growl).notify | ||
|
||
@event = Event.new | ||
@event.agent = agents(:bob_weather_agent) | ||
@event.payload = { :subject => 'Weather Alert!', :message => 'Looks like its going to rain' } | ||
@event.save! | ||
end | ||
|
||
describe "#working?" do | ||
it "checks if events have been received within the expected receive period" do | ||
@checker.should_not be_working # No events received | ||
Agents::GrowlAgent.async_receive @checker.id, [@event.id] | ||
@checker.reload.should be_working # Just received events | ||
two_days_from_now = 2.days.from_now | ||
stub(Time).now { two_days_from_now } | ||
@checker.reload.should_not be_working # More time has passed than the expected receive period without any new events | ||
end | ||
end | ||
|
||
describe "validation" do | ||
before do | ||
@checker.should be_valid | ||
end | ||
|
||
it "should validate presence of of growlserver" do | ||
@checker.options[:growlserver] = "" | ||
@checker.should_not be_valid | ||
end | ||
|
||
it "should validate presence of expected_receive_period_in_days" do | ||
@checker.options[:expected_receive_period_in_days] = "" | ||
@checker.should_not be_valid | ||
end | ||
end | ||
|
||
describe "register_growl" do | ||
it "should set the password for the Growl connection from the agent options" do | ||
@checker.register_growl | ||
@checker.growler.password.should eql(@checker.options[:growlpassword]) | ||
end | ||
|
||
it "should add a notification to the Growl connection" do | ||
any_instance_of(Growl) do |obj| | ||
mock(obj).add_notification(@checker.options[:growlnotificationname]) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing here as I suggested below: make sure the block gets called. |
||
|
||
@checker.register_growl | ||
end | ||
end | ||
|
||
describe "notify_growl" do | ||
before do | ||
@checker.register_growl | ||
end | ||
|
||
it "should call Growl.notify with the correct notification name, subject, and message" do | ||
message = "message" | ||
subject = "subject" | ||
any_instance_of(Growl) do |obj| | ||
mock(obj).notify(@checker.options[:growlnotificationname],subject,message) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recommend also ensuring that this block gets called
|
||
end | ||
@checker.notify_growl(subject,message) | ||
end | ||
end | ||
|
||
describe "receive" do | ||
def generate_events_array | ||
events = [] | ||
(2..rand(7)).each do | ||
events << @event | ||
end | ||
return events | ||
end | ||
|
||
it "should call register_growl once regardless of number of events received" do | ||
mock.proxy(@checker).register_growl.once | ||
@checker.receive(generate_events_array) | ||
end | ||
|
||
it "should call notify_growl one time for each event received" do | ||
events = generate_events_array | ||
events.each do |event| | ||
mock.proxy(@checker).notify_growl(event.payload['subject'],event.payload['message']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style: We always put spaces after commas. |
||
end | ||
@checker.receive(events) | ||
end | ||
|
||
it "should not call notify_growl if message or subject are missing" do | ||
event_without_a_subject = Event.new | ||
event_without_a_subject.agent = agents(:bob_weather_agent) | ||
event_without_a_subject.payload = { :message => 'Looks like its going to rain' } | ||
event_without_a_subject.save! | ||
|
||
event_without_a_message = Event.new | ||
event_without_a_message.agent = agents(:bob_weather_agent) | ||
event_without_a_message.payload = { :subject => 'Weather Alert YO!' } | ||
event_without_a_message.save! | ||
|
||
mock.proxy(@checker).notify_growl.never | ||
@checker.receive([event_without_a_subject,event_without_a_message]) | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be up for renaming these to
growl_server
,growl_password
,growl_app_name
, etc? That's more our style in this app.