Browse Source

Added Hipchat Agent

Dominik Sander 11 years ago
parent
commit
558eb37ff1
4 changed files with 183 additions and 0 deletions
  1. 1 0
      Gemfile
  2. 3 0
      Gemfile.lock
  3. 76 0
      app/models/agents/hipchat_agent.rb
  4. 103 0
      spec/models/agents/hipchat_agent_spec.rb

+ 1 - 0
Gemfile

@@ -44,6 +44,7 @@ gem 'twitter', '~> 5.7.1'
 gem 'twitter-stream', github: 'cantino/twitter-stream', branch: 'master'
 gem 'em-http-request', '~> 1.1.2'
 gem 'weibo_2', '~> 0.1.4'
+gem 'hipchat', '~> 1.1.0'
 
 gem 'therubyracer', '~> 0.12.1'
 

+ 3 - 0
Gemfile.lock

@@ -121,6 +121,8 @@ GEM
       rails (~> 3.0)
     hashie (2.0.5)
     hike (1.2.3)
+    hipchat (1.1.0)
+      httparty
     http (0.5.0)
       http_parser.rb
     http_parser.rb (0.6.0)
@@ -318,6 +320,7 @@ DEPENDENCIES
   foreman (~> 0.63.0)
   geokit (~> 1.6.7)
   geokit-rails3 (~> 0.1.5)
+  hipchat (~> 1.1.0)
   jquery-rails (~> 3.0.4)
   json (>= 1.7.7)
   jsonpath (~> 0.5.3)

+ 76 - 0
app/models/agents/hipchat_agent.rb

@@ -0,0 +1,76 @@
+module Agents
+  class HipchatAgent < Agent
+    cannot_be_scheduled!
+    cannot_create_events!
+
+    description <<-MD
+      The HipchatAgent sends messages to a Hipchat Room
+
+      To authenticate you need to set the `auth_token`, you can get one at your Hipchat Group Admin page which you can find here:
+
+      `https://`yoursubdomain`.hipchat.com/admin/api`
+
+      Change the `room_name` to the name of the room you want to send notifications to.
+
+      You can provide a `username` and a `message`. When sending a HTML formatted message change `format` to "html".
+      If you want your message to notify the room members change `notify` to "true".
+      Modify the background color of your message via the `color` attribute (one of "yellow", "red", "green", "purple", "gray", or "random")
+
+      If you want to specify either of those attributes per event, you can provide a [JSONPath](http://goessner.net/articles/JsonPath/) for each of them (except the `auth_token`).
+    MD
+
+    def default_options
+      {
+        'auth_token' => '',
+        'room_name' => '',
+        'room_name_path' => '',
+        'username' => "Huginn",
+        'username_path' => '',
+        'message' => "Hello from Huginn!",
+        'message_path' => '',
+        'notify' => false,
+        'notify_path' => '',
+        'color' => 'yellow',
+        'color_path' => '',
+      }
+    end
+
+    def validate_options
+      errors.add(:base, "you need to specify a hipchat auth_token") unless options['auth_token'].present?
+      errors.add(:base, "you need to specify a room_name or a room_name_path") if options['room_name'].blank? && options['room_name_path'].blank?
+    end
+
+    def working?
+      (last_receive_at.present? && last_error_log_at.nil?) || (last_receive_at.present? && last_error_log_at.present? && last_receive_at > last_error_log_at)
+    end
+
+    def receive(incoming_events)
+      client = HipChat::Client.new(options[:auth_token])
+      incoming_events.each do |event|
+        mo = merge_options event
+        client[mo[:room_name]].send(mo[:username], mo[:message], :notify => mo[:notify].to_s == 'true' ? 1 : 0, :color => mo[:color])
+      end
+    end
+
+    private
+    def select_option(event, a)
+      if options[a.to_s + '_path'].present?
+        Utils.value_at(event.payload, options[a.to_s + '_path'])
+      else
+        options[a]
+      end
+    end
+
+    def options_with_path
+      [:room_name, :username, :message, :notify, :color]
+    end
+
+    def merge_options event
+      options.select { |k, v| options_with_path.include? k}.tap do |merged_options|
+        options_with_path.each do |a|
+          merged_options[a] = select_option(event, a)
+        end
+      end
+    end
+  end
+end

+ 103 - 0
spec/models/agents/hipchat_agent_spec.rb

@@ -0,0 +1,103 @@
+require 'spec_helper'
+
+describe Agents::HipchatAgent do
+  before(:each) do
+    @valid_params = {
+                      'auth_token' => 'token',
+                      'room_name' => 'test',
+                      'room_name_path' => '',
+                      'username' => "Huginn",
+                      'username_path' => '$.username',
+                      'message' => "Hello from Huginn!",
+                      'message_path' => '$.message',
+                      'notify' => false,
+                      'notify_path' => '',
+                      'color' => 'yellow',
+                      'color_path' => '',
+                    }
+
+    @checker = Agents::HipchatAgent.new(:name => "somename", :options => @valid_params)
+    @checker.user = users(:jane)
+    @checker.save!
+
+    @event = Event.new
+    @event.agent = agents(:bob_weather_agent)
+    @event.payload = { :room_name => 'test room', :message => 'Looks like its going to rain', username: "Huggin user"}
+    @event.save!
+  end
+
+  describe "validating" do
+    before do
+      @checker.should be_valid
+    end
+
+    it "should require the basecamp username" do
+      @checker.options['auth_token'] = nil
+      @checker.should_not be_valid
+    end
+
+    it "should require the basecamp password" do
+      @checker.options['room_name'] = nil
+      @checker.should_not be_valid
+    end
+
+    it "should require the basecamp user_id" do
+      @checker.options['room_name'] = nil
+      @checker.options['room_name_path'] = 'jsonpath'
+      @checker.should be_valid
+    end
+
+  end
+
+  describe "helpers" do
+    describe "select_option" do
+      it "should use the room_name_path if specified" do
+        @checker.options['room_name_path'] = "$.room_name"
+        @checker.send(:select_option, @event, :room_name).should == "test room"
+      end
+
+      it "should use the normal option when the path option is blank" do
+        @checker.send(:select_option, @event, :room_name).should == "test"
+      end
+    end
+
+    it "should merge all options" do
+      @checker.send(:merge_options, @event).should == {
+        :room_name => "test",
+        :username => "Huggin user",
+        :message => "Looks like its going to rain",
+        :notify => false,
+        :color => "yellow"
+      }
+    end
+  end
+
+  describe "#receive" do
+    it "send a message to the hipchat" do
+      any_instance_of(HipChat::Room) do |obj|
+        mock(obj).send(@event.payload[:username], @event.payload[:message], {:notify => 0, :color => 'yellow'})
+      end
+      @checker.receive([@event])
+    end
+  end
+
+  describe "#working?" do
+    it "should not be working until the first event was received" do
+      @checker.should_not be_working
+      @checker.last_receive_at = Time.now
+      @checker.should be_working
+    end
+
+    it "should not be working when the last error occured after the last received event" do
+      @checker.last_receive_at = Time.now - 1.minute
+      @checker.last_error_log_at = Time.now
+      @checker.should_not be_working
+    end
+
+    it "should be working when the last received event occured after the last error" do
+      @checker.last_receive_at = Time.now
+      @checker.last_error_log_at = Time.now - 1.minute
+      @checker.should be_working
+    end
+  end
+end