Merge pull request #2074 from dsander/add-callback-to-growlagent

Add more options to the GrowlAgent
This commit is contained in:
Dominik Sander 2017-08-01 19:35:16 +02:00 committed by GitHub
commit af5da3a165
3 changed files with 89 additions and 39 deletions

View file

@ -1,9 +1,11 @@
module Agents
class GrowlAgent < Agent
include FormConfigurable
attr_reader :growler
cannot_be_scheduled!
cannot_create_events!
can_dry_run!
gem_dependency_check { defined?(Growl) }
@ -11,10 +13,16 @@ module Agents
The Growl Agent sends any events it receives to a Growl GNTP server immediately.
#{'## Include `ruby-growl` in your Gemfile to use this Agent!' if dependencies_missing?}
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.
The option `message`, which will hold the body of the growl notification, and the `subject` option,
which will have the headline of the Growl notification are required. All other options are optional.
When `callback_url` is set to a URL clicking on the notification will open the link in your default browser.
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.
Have a look at the [Wiki](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) to learn
more about liquid templating.
MD
def default_options
@ -23,12 +31,27 @@ module Agents
'growl_password' => '',
'growl_app_name' => 'HuginnGrowl',
'growl_notification_name' => 'Notification',
'expected_receive_period_in_days' => "2"
'expected_receive_period_in_days' => "2",
'subject' => '{{subject}}',
'message' => '{{message}}',
'sticky' => 'false',
'priority' => '0'
}
end
form_configurable :growl_server
form_configurable :growl_password
form_configurable :growl_app_name
form_configurable :growl_notification_name
form_configurable :expected_receive_period_in_days
form_configurable :subject
form_configurable :message, type: :text
form_configurable :sticky, type: :boolean
form_configurable :priority
form_configurable :callback_url
def working?
last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
last_receive_at && last_receive_at > options['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
end
def validate_options
@ -38,25 +61,31 @@ module Agents
end
def register_growl
@growler = Growl.new interpolated['growl_server'], interpolated['growl_app_name'], "GNTP"
@growler = Growl::GNTP.new(interpolated['growl_server'], interpolated['growl_app_name'])
@growler.password = interpolated['growl_password']
@growler.add_notification interpolated['growl_notification_name']
@growler.add_notification(interpolated['growl_notification_name'])
end
def notify_growl(subject, message)
@growler.notify(interpolated['growl_notification_name'], subject, message)
def notify_growl(subject:, message:, priority:, sticky:, callback_url:)
@growler.notify(interpolated['growl_notification_name'], subject, message, priority, sticky, nil, callback_url)
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 #{interpolated(event)['growl_server']} with event #{event.id}"
notify_growl(subject,message)
else
log "Event #{event.id} not sent, message and subject expected"
interpolate_with(event) do
register_growl
message = interpolated[:message]
subject = interpolated[:subject]
if message.present? && subject.present?
log "Sending Growl notification '#{subject}': '#{message}' to #{interpolated(event)['growl_server']} with event #{event.id}"
notify_growl(subject: subject,
message: message,
priority: interpolated[:priority].to_i,
sticky: boolify(interpolated[:sticky]) || false,
callback_url: interpolated[:callback_url].presence)
else
log "Event #{event.id} not sent, message and subject expected"
end
end
end
end

View file

@ -0,0 +1,18 @@
class MigrateGrowlAgentToLiquid < ActiveRecord::Migration[5.1]
def up
Agents::GrowlAgent.find_each do |agent|
agent.options['subject'] = '{{subject}}' if agent.options['subject'].blank?
agent.options['message'] = '{{ message | default: text }}' if agent.options['message'].blank?
agent.save(validate: false)
end
end
def down
Agents::GrowlAgent.find_each do |agent|
%w(subject message sticky priority).each do |key|
agent.options.delete(key)
end
agent.save(validate: false)
end
end
end

View file

@ -7,11 +7,13 @@ describe Agents::GrowlAgent do
:growl_app_name => 'HuginnGrowlApp',
:growl_password => 'mypassword',
:growl_notification_name => 'Notification',
:expected_receive_period_in_days => '1' })
expected_receive_period_in_days: '1' ,
message: '{{message}}',
subject: '{{subject}}'})
@checker.user = users(:bob)
@checker.save!
stub.any_instance_of(Growl).notify
stub.any_instance_of(Growl::GNTP).notify
@event = Event.new
@event.agent = agents(:bob_weather_agent)
@ -45,7 +47,7 @@ describe Agents::GrowlAgent do
expect(@checker).not_to 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
@ -54,34 +56,34 @@ describe Agents::GrowlAgent do
it "should add a notification to the Growl connection" do
called = false
any_instance_of(Growl) do |obj|
any_instance_of(Growl::GNTP) do |obj|
called = true
mock(obj).add_notification(@checker.options[:growl_notification_name])
end
@checker.register_growl
expect(called).to be_truthy
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"
called = false
any_instance_of(Growl) do |obj|
any_instance_of(Growl::GNTP) do |obj|
called = true
mock(obj).notify(@checker.options[:growl_notification_name],subject,message)
mock(obj).notify(@checker.options[:growl_notification_name], subject, message, 0, false, nil, '')
end
@checker.notify_growl(subject,message)
@checker.notify_growl(subject: subject, message: message, sticky: false, priority: 0, callback_url: '')
expect(called).to be_truthy
end
end
describe "receive" do
def generate_events_array
events = []
@ -90,31 +92,32 @@ describe Agents::GrowlAgent do
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)
it "should call register_growl once per received event" do
events = generate_events_array
mock.proxy(@checker).register_growl.times(events.length)
@checker.receive(events)
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'])
mock.proxy(@checker).notify_growl(subject: event.payload['subject'], message: event.payload['message'], priority: 0, sticky: false, callback_url: nil)
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