Commit 87dae821c473c1fbfaddf7b8ec5d73342028d0a2

Authored by Shuky Dvir
2 parents 397ea672 c7cf0952
Exists in master and in 1 other branch production

Merge pull request #383 from damau/master

Support for multiple XMPP clients and ability to send to a room and user
Gemfile
... ... @@ -49,7 +49,7 @@ gem 'campy'
49 49 # Hipchat
50 50 gem 'hipchat'
51 51 # Google Talk
52   -gem 'xmpp4r'
  52 +gem 'xmpp4r', :require => ["xmpp4r", "xmpp4r/muc"]
53 53 # Hoiio (SMS)
54 54 gem 'hoi'
55 55 # Pushover (iOS Push notifications)
... ...
app/models/notification_service.rb
... ... @@ -5,6 +5,9 @@ class NotificationService
5 5 default_url_options[:host] = ActionMailer::Base.default_url_options[:host]
6 6  
7 7 field :room_id, :type => String
  8 + field :user_id, :type => String
  9 + field :service_url, :type => String
  10 + field :service, :type => String
8 11 field :api_token, :type => String
9 12 field :subdomain, :type => String
10 13 field :sender_name, :type => String
... ...
app/models/notification_services/gtalk_service.rb
... ... @@ -9,31 +9,64 @@ class NotificationServices::GtalkService < NotificationService
9 9 :placeholder => "password",
10 10 :label => "Password"
11 11 }],
  12 + [:user_id, {
  13 + :placeholder => "touser@example.com, anotheruser@example.com",
  14 + :label => "Send To User(s)"
  15 + }, :room_id],
12 16 [:room_id, {
13   - :placeholder => "touser@example.com, anotheruser@example.com",
14   - :label => "Send To User(s)"
  17 + :placeholder => "toroom@conference.example.com",
  18 + :label => "Send To Room (one only)"
  19 + }, :user_id],
  20 + [ :service, {
  21 + :placeholder => "talk.google.com",
  22 + :label => "Jabber Service"
15 23 }],
  24 + [ :service_url, {
  25 + :placeholder => "http://www.google.com/talk/",
  26 + :label => "Link To Jabber Service"
  27 + }]
16 28 ]
17 29  
18 30 def check_params
19   - if Fields.detect {|f| self[f[0]].blank? }
20   - errors.add :base, 'You must specify your Username, Password and To User(s)'
  31 + if Fields.detect { |f| self[f[0]].blank? && self[f[2]].blank? }
  32 + errors.add :base,
  33 + """You must specify your Username, Password, service, service_url
  34 + and either rooms or users to send to or both"""
21 35 end
22 36 end
23 37  
24 38 def url
25   - "http://www.google.com/talk/"
  39 + "http://www.google.com/talk/" || service_url
26 40 end
27 41  
28 42 def create_notification(problem)
29 43 # build the xmpp client
30 44 client = Jabber::Client.new(Jabber::JID.new(subdomain))
31   - client.connect("talk.google.com")
  45 + client.connect(service)
32 46 client.auth(api_token)
33 47  
  48 + #has to look like this to be formatted properly in the client
  49 + message = """#{problem.app.name.to_s}
  50 +http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
  51 +#{notification_description problem}"""
  52 +
34 53 # post the issue to the xmpp room(s)
35   - room_id.gsub(/ /i, ",").gsub(/;/i, ",").split(",").map(&:strip).reject(&:empty?).each do |room|
36   - client.send(Jabber::Message.new(room, "[errbit] http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_description problem}"))
  54 + send_to_users(client, message) unless user_id.blank?
  55 + send_to_muc(client, message) unless room_id.blank?
  56 + end
  57 +
  58 + private
  59 +
  60 + def send_to_users client, message
  61 + user_id.gsub(/ /i, ",").gsub(/;/i, ",").split(",").map(&:strip).reject(&:empty?).each do |user|
  62 + client.send(Jabber::Message.new(user, message))
37 63 end
38 64 end
  65 +
  66 + def send_to_muc client, message
  67 + #TODO: set this so that it can send to multiple rooms like users, nb multiple room joins in one send fail randomly so leave as one room for the moment
  68 + muc = Jabber::MUC::SimpleMUCClient.new(client)
  69 + muc.join(room_id + "/errbit")
  70 + muc.send(Jabber::Message.new(room_id, message))
  71 + end
39 72 end
... ...
db/migrate/20130208135718_allow_custom_xmpp_on_gtalk.rb.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class AllowCustomXmppOnGtalk < Mongoid::Migration
  2 + def self.up
  3 + App.all.each do |app|
  4 + if app.notification_service and app.notification_service._type.include?("Gtalk")
  5 + user_id = app.notification_service.room_id
  6 + app.notification_service.update_attributes(:service => 'talk.google.com',
  7 + :service_url => "http://www.google.com/talk/",
  8 + :user_id => user_id,
  9 + :room_id => nil)
  10 +
  11 + end
  12 + end
  13 + end
  14 +
  15 + def self.down
  16 + end
  17 +end
... ...
spec/fabricators/notification_service_fabricator.rb
... ... @@ -5,6 +5,12 @@ Fabricator :notification_service do
5 5 subdomain { sequence :word }
6 6 end
7 7  
8   -%w(campfire gtalk hipchat hoiio pushover hubot).each do |t|
  8 +Fabricator :gtalk_notification_service, :from => :notification_service, :class_name => "NotificationService::GtalkService" do
  9 + user_id { sequence :word }
  10 + service_url { sequence :word }
  11 + service { sequence :word }
  12 +end
  13 +
  14 +%w(campfire hipchat hoiio pushover hubot).each do |t|
9 15 Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service"
10 16 end
... ...
spec/models/notification_service/gtalk_service_spec.rb
... ... @@ -4,6 +4,7 @@ describe NotificationService::GtalkService do
4 4 it "it should send a notification to gtalk" do
5 5 # setup
6 6 notice = Fabricate :notice
  7 + problem = notice.problem
7 8 notification_service = Fabricate :gtalk_notification_service, :app => notice.app
8 9 problem = notice.problem
9 10  
... ... @@ -13,24 +14,33 @@ describe NotificationService::GtalkService do
13 14 message = double("message")
14 15 Jabber::JID.should_receive(:new).with(notification_service.subdomain).and_return(jid)
15 16 Jabber::Client.should_receive(:new).with(jid).and_return(gtalk)
16   - gtalk.should_receive(:connect)
  17 + gtalk.should_receive(:connect).with(notification_service.service)
17 18 gtalk.should_receive(:auth).with(notification_service.api_token)
18   - Jabber::Message.should_receive(:new).with(notification_service.room_id, "[errbit] http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_service.notification_description problem}").and_return(message)
19   -
  19 + message_value = """#{problem.app.name.to_s}
  20 +http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
  21 +#{notification_service.notification_description problem}"""
  22 +
  23 + Jabber::Message.should_receive(:new).with(notification_service.user_id, message_value).and_return(message)
  24 + Jabber::Message.should_receive(:new).with(notification_service.room_id, message_value).and_return(message)
  25 +
  26 + Jabber::MUC::SimpleMUCClient.should_receive(:new).and_return(gtalk)
  27 + gtalk.should_receive(:join).with(notification_service.room_id + "/errbit")
  28 +
20 29 #assert
21   - gtalk.should_receive(:send).with(message)
22   -
  30 + gtalk.should_receive(:send).exactly(2).times.with(message)
23 31  
24 32 notification_service.create_notification(problem)
25 33 end
26 34  
27   - describe "multiple room_ids (or users)" do
  35 + describe "multiple users_ids" do
28 36 before(:each) do
29 37 # setup
30 38 @notice = Fabricate :notice
31 39 @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app
32 40 @problem = @notice.problem
33   - @error_msg = "[errbit] http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} #{@notification_service.notification_description @problem}"
  41 + @error_msg = """#{@problem.app.name.to_s}
  42 +http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s}
  43 +#{@notification_service.notification_description @problem}"""
34 44  
35 45 # gtalk stubbing
36 46 @gtalk = mock('GtalkService')
... ... @@ -45,9 +55,11 @@ describe NotificationService::GtalkService do
45 55 Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg)
46 56 Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg)
47 57 Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg)
  58 + Jabber::MUC::SimpleMUCClient.should_not_receive(:new)
48 59 @gtalk.should_receive(:send).exactly(4).times
49 60  
50   - @notification_service.room_id = "first@domain.org,second@domain.org, third@domain.org , fourth@domain.org "
  61 + @notification_service.user_id = "first@domain.org,second@domain.org, third@domain.org , fourth@domain.org "
  62 + @notification_service.room_id = ""
51 63 @notification_service.create_notification(@problem)
52 64 end
53 65 it "should send a notification to all ';' separated users" do
... ... @@ -55,9 +67,11 @@ describe NotificationService::GtalkService do
55 67 Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg)
56 68 Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg)
57 69 Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg)
  70 + Jabber::MUC::SimpleMUCClient.should_not_receive(:new)
58 71 @gtalk.should_receive(:send).exactly(4).times
59 72  
60   - @notification_service.room_id = "first@domain.org;second@domain.org; third@domain.org ; fourth@domain.org "
  73 + @notification_service.user_id = "first@domain.org;second@domain.org; third@domain.org ; fourth@domain.org "
  74 + @notification_service.room_id = ""
61 75 @notification_service.create_notification(@problem)
62 76 end
63 77 it "should send a notification to all ' ' separated users" do
... ... @@ -65,11 +79,47 @@ describe NotificationService::GtalkService do
65 79 Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg)
66 80 Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg)
67 81 Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg)
  82 + Jabber::MUC::SimpleMUCClient.should_not_receive(:new)
68 83 @gtalk.should_receive(:send).exactly(4).times
69 84  
70   - @notification_service.room_id = "first@domain.org second@domain.org third@domain.org fourth@domain.org "
  85 + @notification_service.user_id = "first@domain.org second@domain.org third@domain.org fourth@domain.org "
  86 + @notification_service.room_id = ""
71 87 @notification_service.create_notification(@problem)
72 88 end
  89 +
  90 + end
  91 +
  92 + it "it should send a notification to room only" do
  93 + # setup
  94 + notice = Fabricate :notice
  95 + problem = notice.problem
  96 + notification_service = Fabricate :gtalk_notification_service, :app => notice.app
  97 + problem = notice.problem
  98 +
  99 + #gtalk stubbing
  100 + gtalk = mock('GtalkService')
  101 + jid = double("jid")
  102 + message = double("message")
  103 + Jabber::JID.should_receive(:new).with(notification_service.subdomain).and_return(jid)
  104 + Jabber::Client.should_receive(:new).with(jid).and_return(gtalk)
  105 + gtalk.should_receive(:connect)
  106 + gtalk.should_receive(:auth).with(notification_service.api_token)
  107 + message_value = """#{problem.app.name.to_s}
  108 +http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
  109 +#{notification_service.notification_description problem}"""
  110 +
  111 + Jabber::Message.should_receive(:new).with(notification_service.room_id, message_value).and_return(message)
  112 +
  113 + Jabber::MUC::SimpleMUCClient.should_receive(:new).and_return(gtalk)
  114 + gtalk.should_receive(:join).with(notification_service.room_id + "/errbit")
  115 +
  116 + notification_service.user_id = ""
  117 +
  118 + #assert
  119 + gtalk.should_receive(:send).with(message)
  120 +
  121 + notification_service.create_notification(problem)
73 122 end
  123 +
74 124 end
75 125  
... ...
spec/spec_helper.rb
... ... @@ -6,6 +6,7 @@ require &#39;rspec/rails&#39;
6 6 require 'database_cleaner'
7 7 require 'webmock/rspec'
8 8 require 'xmpp4r'
  9 +require 'xmpp4r/muc'
9 10  
10 11 # Requires supporting files with custom matchers and macros, etc,
11 12 # in ./support/ and its subdirectories.
... ...