Ver código fonte

Merge pull request #258 from mwerner/jabber_agent

Add Jabber Agent
Andrew Cantino 11 anos atrás
pai
commit
07243cee34
4 arquivos alterados com 154 adições e 7 exclusões
  1. 1 0
      Gemfile
  2. 8 7
      Gemfile.lock
  3. 64 0
      app/models/agents/jabber_agent.rb
  4. 81 0
      spec/models/agents/jabber_agent_spec.rb

+ 1 - 0
Gemfile

@@ -59,6 +59,7 @@ 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 'xmpp4r',  '~> 0.5.6'
 
 gem 'therubyracer', '~> 0.12.1'
 

+ 8 - 7
Gemfile.lock

@@ -86,10 +86,11 @@ GEM
       warden (~> 1.2.3)
     diff-lcs (1.2.5)
     docile (1.1.3)
-    dotenv (0.10.0)
+    dotenv (0.11.1)
+      dotenv-deployment (~> 0.0.2)
     dotenv-deployment (0.0.2)
-    dotenv-rails (0.10.0)
-      dotenv (= 0.10.0)
+    dotenv-rails (0.11.1)
+      dotenv (= 0.11.1)
     em-http-request (1.1.2)
       addressable (>= 2.3.4)
       cookiejar
@@ -158,7 +159,7 @@ GEM
     mime-types (1.25.1)
     mini_portile (0.5.3)
     minitest (5.3.3)
-    multi_json (1.9.2)
+    multi_json (1.9.3)
     multi_xml (0.5.5)
     multipart-post (2.0.0)
     mysql2 (0.3.15)
@@ -226,7 +227,7 @@ GEM
       uuid (~> 2.3, >= 2.3.5)
     rufus-scheduler (3.0.7)
       tzinfo
-    safe_yaml (1.0.2)
+    safe_yaml (1.0.3)
     sass (3.2.19)
     sass-rails (4.0.3)
       railties (>= 4.0.0, < 5.0)
@@ -285,8 +286,6 @@ GEM
       ethon (>= 0.7.0)
     tzinfo (1.1.0)
       thread_safe (~> 0.1)
-    tzinfo-data (1.2014.2)
-      tzinfo (>= 1.0.0)
     uglifier (2.5.0)
       execjs (>= 0.3.0)
       json (>= 1.8.0)
@@ -306,6 +305,7 @@ GEM
       addressable
       httparty (> 0.6.0)
       json (> 1.4.0)
+    xmpp4r (0.5.6)
 
 PLATFORMS
   ruby
@@ -362,3 +362,4 @@ DEPENDENCIES
   webmock
   weibo_2 (~> 0.1.4)
   wunderground (~> 1.2.0)
+  xmpp4r (~> 0.5.6)

+ 64 - 0
app/models/agents/jabber_agent.rb

@@ -0,0 +1,64 @@
+module Agents
+  class JabberAgent < Agent
+    cannot_be_scheduled!
+    cannot_create_events!
+
+    description <<-MD
+      The JabberAgent will send any events it receives to your Jabber/XMPP IM account.
+
+      Specify the `jabber_server` and `jabber_port` for your Jabber server.
+
+      The `message` is sent from `jabber_sender` to `jaber_receiver`. This message
+      can contain any keys found in the source's payload, escaped using double curly braces.
+      ex: `"News Story: <$.title>: <$.url>"`
+    MD
+
+    def default_options
+      {
+        'jabber_server'   => '127.0.0.1',
+        'jabber_port'     => '5222',
+        'jabber_sender'   => 'huginn@localhost',
+        'jabber_receiver' => 'muninn@localhost',
+        'jabber_password' => '',
+        'message'         => 'It will be <$.temp> out tomorrow',
+        '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 receive(incoming_events)
+      incoming_events.each do |event|
+        log "Sending IM to #{options['jabber_receiver']} with event #{event.id}"
+        deliver body(event)
+      end
+    end
+
+    def validate_options
+      errors.add(:base, "server and username is required") unless credentials_present?
+    end
+
+    def deliver(text)
+      client.send Jabber::Message::new(options['jabber_receiver'], text).set_type(:chat)
+    end
+
+    private
+
+    def client
+      Jabber::Client.new(Jabber::JID::new(options['jabber_sender'])).tap do |sender|
+        sender.connect(options['jabber_server'], (options['jabber_port'] || '5222'))
+        sender.auth(options['jabber_password'])
+      end
+    end
+
+    def credentials_present?
+      options['jabber_server'].present? && options['jabber_sender'].present? && options['jabber_receiver'].present?
+    end
+
+    def body(event)
+      Utils.interpolate_jsonpaths(options['message'], event.payload)
+    end
+  end
+end

+ 81 - 0
spec/models/agents/jabber_agent_spec.rb

@@ -0,0 +1,81 @@
+require 'spec_helper'
+
+describe Agents::JabberAgent do
+  let(:sent) { [] }
+  let(:config) {
+    {
+      jabber_server: '127.0.0.1',
+      jabber_port: '5222',
+      jabber_sender: 'foo@localhost',
+      jabber_receiver: 'bar@localhost',
+      jabber_password: 'password',
+      message: 'Warning! <$.title> - <$.url>',
+      expected_receive_period_in_days: '2'
+    }
+  }
+
+  let(:agent) do
+    Agents::JabberAgent.new(name: 'Jabber Agent', options: config).tap do |a|
+      a.user = users(:bob)
+      a.save!
+    end
+  end
+
+  let(:event) do
+    Event.new.tap do |e|
+      e.agent = agents(:bob_weather_agent)
+      e.payload = { :title => 'Weather Alert!', :url => 'http://www.weather.com/' }
+      e.save!
+    end
+  end
+
+  before do
+    stub.any_instance_of(Agents::JabberAgent).deliver { |message| sent << message }
+  end
+
+  describe "#working?" do
+    it "checks if events have been received within the expected receive period" do
+      agent.should_not be_working # No events received
+      Agents::JabberAgent.async_receive agent.id, [event.id]
+      agent.reload.should be_working # Just received events
+      two_days_from_now = 2.days.from_now
+      stub(Time).now { two_days_from_now }
+      agent.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
+      agent.should be_valid
+    end
+
+    it "should validate presence of of jabber_server" do
+      agent.options[:jabber_server] = ""
+      agent.should_not be_valid
+    end
+
+    it "should validate presence of jabber_sender" do
+      agent.options[:jabber_sender] = ""
+      agent.should_not be_valid
+    end
+
+    it "should validate presence of jabber_receiver" do
+      agent.options[:jabber_receiver] = ""
+      agent.should_not be_valid
+    end
+  end
+
+  describe "receive" do
+    it "should send an IM for each event" do
+      event2 = Event.new.tap do |e|
+        e.agent = agents(:bob_weather_agent)
+        e.payload = { :title => 'Another Weather Alert!', :url => 'http://www.weather.com/we-are-screwed' }
+        e.save!
+      end
+
+      agent.receive([event, event2])
+      sent.should == [ 'Warning! Weather Alert! - http://www.weather.com/',
+                       'Warning! Another Weather Alert! - http://www.weather.com/we-are-screwed']
+    end
+  end
+end