Merge pull request #230 from dsander/hipchat_agent

Added Hipchat Agent

Andrew Cantino 10 lat temu
rodzic
commit
c4ec10ac40
4 zmienionych plików z 183 dodań i 0 usunięć
  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'
44 44
 gem 'twitter-stream', github: 'cantino/twitter-stream', branch: 'master'
45 45
 gem 'em-http-request', '~> 1.1.2'
46 46
 gem 'weibo_2', '~> 0.1.4'
47
+gem 'hipchat', '~> 1.1.0'
47 48
 
48 49
 gem 'therubyracer', '~> 0.12.1'
49 50
 

+ 3 - 0
Gemfile.lock

@@ -121,6 +121,8 @@ GEM
121 121
       rails (~> 3.0)
122 122
     hashie (2.0.5)
123 123
     hike (1.2.3)
124
+    hipchat (1.1.0)
125
+      httparty
124 126
     http (0.5.0)
125 127
       http_parser.rb
126 128
     http_parser.rb (0.6.0)
@@ -318,6 +320,7 @@ DEPENDENCIES
318 320
   foreman (~> 0.63.0)
319 321
   geokit (~> 1.6.7)
320 322
   geokit-rails3 (~> 0.1.5)
323
+  hipchat (~> 1.1.0)
321 324
   jquery-rails (~> 3.0.4)
322 325
   json (>= 1.7.7)
323 326
   jsonpath (~> 0.5.3)

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

@@ -0,0 +1,76 @@
1
+module Agents
2
+  class HipchatAgent < Agent
3
+    cannot_be_scheduled!
4
+    cannot_create_events!
5
+
6
+    description <<-MD
7
+      The HipchatAgent sends messages to a Hipchat Room
8
+
9
+      To authenticate you need to set the `auth_token`, you can get one at your Hipchat Group Admin page which you can find here:
10
+
11
+      `https://`yoursubdomain`.hipchat.com/admin/api`
12
+
13
+      Change the `room_name` to the name of the room you want to send notifications to.
14
+
15
+      You can provide a `username` and a `message`. When sending a HTML formatted message change `format` to "html".
16
+      If you want your message to notify the room members change `notify` to "true".
17
+      Modify the background color of your message via the `color` attribute (one of "yellow", "red", "green", "purple", "gray", or "random")
18
+
19
+      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`).
20
+    MD
21
+
22
+    def default_options
23
+      {
24
+        'auth_token' => '',
25
+        'room_name' => '',
26
+        'room_name_path' => '',
27
+        'username' => "Huginn",
28
+        'username_path' => '',
29
+        'message' => "Hello from Huginn!",
30
+        'message_path' => '',
31
+        'notify' => false,
32
+        'notify_path' => '',
33
+        'color' => 'yellow',
34
+        'color_path' => '',
35
+      }
36
+    end
37
+
38
+    def validate_options
39
+      errors.add(:base, "you need to specify a hipchat auth_token") unless options['auth_token'].present?
40
+      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?
41
+    end
42
+
43
+    def working?
44
+      (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)
45
+    end
46
+
47
+    def receive(incoming_events)
48
+      client = HipChat::Client.new(options[:auth_token])
49
+      incoming_events.each do |event|
50
+        mo = merge_options event
51
+        client[mo[:room_name]].send(mo[:username], mo[:message], :notify => mo[:notify].to_s == 'true' ? 1 : 0, :color => mo[:color])
52
+      end
53
+    end
54
+
55
+    private
56
+    def select_option(event, a)
57
+      if options[a.to_s + '_path'].present?
58
+        Utils.value_at(event.payload, options[a.to_s + '_path'])
59
+      else
60
+        options[a]
61
+      end
62
+    end
63
+
64
+    def options_with_path
65
+      [:room_name, :username, :message, :notify, :color]
66
+    end
67
+
68
+    def merge_options event
69
+      options.select { |k, v| options_with_path.include? k}.tap do |merged_options|
70
+        options_with_path.each do |a|
71
+          merged_options[a] = select_option(event, a)
72
+        end
73
+      end
74
+    end
75
+  end
76
+end

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

@@ -0,0 +1,103 @@
1
+require 'spec_helper'
2
+
3
+describe Agents::HipchatAgent do
4
+  before(:each) do
5
+    @valid_params = {
6
+                      'auth_token' => 'token',
7
+                      'room_name' => 'test',
8
+                      'room_name_path' => '',
9
+                      'username' => "Huginn",
10
+                      'username_path' => '$.username',
11
+                      'message' => "Hello from Huginn!",
12
+                      'message_path' => '$.message',
13
+                      'notify' => false,
14
+                      'notify_path' => '',
15
+                      'color' => 'yellow',
16
+                      'color_path' => '',
17
+                    }
18
+
19
+    @checker = Agents::HipchatAgent.new(:name => "somename", :options => @valid_params)
20
+    @checker.user = users(:jane)
21
+    @checker.save!
22
+
23
+    @event = Event.new
24
+    @event.agent = agents(:bob_weather_agent)
25
+    @event.payload = { :room_name => 'test room', :message => 'Looks like its going to rain', username: "Huggin user"}
26
+    @event.save!
27
+  end
28
+
29
+  describe "validating" do
30
+    before do
31
+      @checker.should be_valid
32
+    end
33
+
34
+    it "should require the basecamp username" do
35
+      @checker.options['auth_token'] = nil
36
+      @checker.should_not be_valid
37
+    end
38
+
39
+    it "should require the basecamp password" do
40
+      @checker.options['room_name'] = nil
41
+      @checker.should_not be_valid
42
+    end
43
+
44
+    it "should require the basecamp user_id" do
45
+      @checker.options['room_name'] = nil
46
+      @checker.options['room_name_path'] = 'jsonpath'
47
+      @checker.should be_valid
48
+    end
49
+
50
+  end
51
+
52
+  describe "helpers" do
53
+    describe "select_option" do
54
+      it "should use the room_name_path if specified" do
55
+        @checker.options['room_name_path'] = "$.room_name"
56
+        @checker.send(:select_option, @event, :room_name).should == "test room"
57
+      end
58
+
59
+      it "should use the normal option when the path option is blank" do
60
+        @checker.send(:select_option, @event, :room_name).should == "test"
61
+      end
62
+    end
63
+
64
+    it "should merge all options" do
65
+      @checker.send(:merge_options, @event).should == {
66
+        :room_name => "test",
67
+        :username => "Huggin user",
68
+        :message => "Looks like its going to rain",
69
+        :notify => false,
70
+        :color => "yellow"
71
+      }
72
+    end
73
+  end
74
+
75
+  describe "#receive" do
76
+    it "send a message to the hipchat" do
77
+      any_instance_of(HipChat::Room) do |obj|
78
+        mock(obj).send(@event.payload[:username], @event.payload[:message], {:notify => 0, :color => 'yellow'})
79
+      end
80
+      @checker.receive([@event])
81
+    end
82
+  end
83
+
84
+  describe "#working?" do
85
+    it "should not be working until the first event was received" do
86
+      @checker.should_not be_working
87
+      @checker.last_receive_at = Time.now
88
+      @checker.should be_working
89
+    end
90
+
91
+    it "should not be working when the last error occured after the last received event" do
92
+      @checker.last_receive_at = Time.now - 1.minute
93
+      @checker.last_error_log_at = Time.now
94
+      @checker.should_not be_working
95
+    end
96
+
97
+    it "should be working when the last received event occured after the last error" do
98
+      @checker.last_receive_at = Time.now
99
+      @checker.last_error_log_at = Time.now - 1.minute
100
+      @checker.should be_working
101
+    end
102
+  end
103
+end