Commit 87dae821c473c1fbfaddf7b8ec5d73342028d0a2
Exists in
master
and in
1 other branch
Merge pull request #383 from damau/master
Support for multiple XMPP clients and ability to send to a room and user
Showing
7 changed files
with
130 additions
and
20 deletions
Show diff stats
Gemfile
@@ -49,7 +49,7 @@ gem 'campy' | @@ -49,7 +49,7 @@ gem 'campy' | ||
49 | # Hipchat | 49 | # Hipchat |
50 | gem 'hipchat' | 50 | gem 'hipchat' |
51 | # Google Talk | 51 | # Google Talk |
52 | -gem 'xmpp4r' | 52 | +gem 'xmpp4r', :require => ["xmpp4r", "xmpp4r/muc"] |
53 | # Hoiio (SMS) | 53 | # Hoiio (SMS) |
54 | gem 'hoi' | 54 | gem 'hoi' |
55 | # Pushover (iOS Push notifications) | 55 | # Pushover (iOS Push notifications) |
app/models/notification_service.rb
@@ -5,6 +5,9 @@ class NotificationService | @@ -5,6 +5,9 @@ class NotificationService | ||
5 | default_url_options[:host] = ActionMailer::Base.default_url_options[:host] | 5 | default_url_options[:host] = ActionMailer::Base.default_url_options[:host] |
6 | 6 | ||
7 | field :room_id, :type => String | 7 | field :room_id, :type => String |
8 | + field :user_id, :type => String | ||
9 | + field :service_url, :type => String | ||
10 | + field :service, :type => String | ||
8 | field :api_token, :type => String | 11 | field :api_token, :type => String |
9 | field :subdomain, :type => String | 12 | field :subdomain, :type => String |
10 | field :sender_name, :type => String | 13 | field :sender_name, :type => String |
app/models/notification_services/gtalk_service.rb
@@ -9,31 +9,64 @@ class NotificationServices::GtalkService < NotificationService | @@ -9,31 +9,64 @@ class NotificationServices::GtalkService < NotificationService | ||
9 | :placeholder => "password", | 9 | :placeholder => "password", |
10 | :label => "Password" | 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 | [:room_id, { | 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 | def check_params | 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 | end | 35 | end |
22 | end | 36 | end |
23 | 37 | ||
24 | def url | 38 | def url |
25 | - "http://www.google.com/talk/" | 39 | + "http://www.google.com/talk/" || service_url |
26 | end | 40 | end |
27 | 41 | ||
28 | def create_notification(problem) | 42 | def create_notification(problem) |
29 | # build the xmpp client | 43 | # build the xmpp client |
30 | client = Jabber::Client.new(Jabber::JID.new(subdomain)) | 44 | client = Jabber::Client.new(Jabber::JID.new(subdomain)) |
31 | - client.connect("talk.google.com") | 45 | + client.connect(service) |
32 | client.auth(api_token) | 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 | # post the issue to the xmpp room(s) | 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 | end | 63 | end |
38 | end | 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 | end | 72 | end |
db/migrate/20130208135718_allow_custom_xmpp_on_gtalk.rb.rb
0 → 100644
@@ -0,0 +1,17 @@ | @@ -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,6 +5,12 @@ Fabricator :notification_service do | ||
5 | subdomain { sequence :word } | 5 | subdomain { sequence :word } |
6 | end | 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 | Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service" | 15 | Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service" |
10 | end | 16 | end |
spec/models/notification_service/gtalk_service_spec.rb
@@ -4,6 +4,7 @@ describe NotificationService::GtalkService do | @@ -4,6 +4,7 @@ describe NotificationService::GtalkService do | ||
4 | it "it should send a notification to gtalk" do | 4 | it "it should send a notification to gtalk" do |
5 | # setup | 5 | # setup |
6 | notice = Fabricate :notice | 6 | notice = Fabricate :notice |
7 | + problem = notice.problem | ||
7 | notification_service = Fabricate :gtalk_notification_service, :app => notice.app | 8 | notification_service = Fabricate :gtalk_notification_service, :app => notice.app |
8 | problem = notice.problem | 9 | problem = notice.problem |
9 | 10 | ||
@@ -13,24 +14,33 @@ describe NotificationService::GtalkService do | @@ -13,24 +14,33 @@ describe NotificationService::GtalkService do | ||
13 | message = double("message") | 14 | message = double("message") |
14 | Jabber::JID.should_receive(:new).with(notification_service.subdomain).and_return(jid) | 15 | Jabber::JID.should_receive(:new).with(notification_service.subdomain).and_return(jid) |
15 | Jabber::Client.should_receive(:new).with(jid).and_return(gtalk) | 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 | gtalk.should_receive(:auth).with(notification_service.api_token) | 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 | #assert | 29 | #assert |
21 | - gtalk.should_receive(:send).with(message) | ||
22 | - | 30 | + gtalk.should_receive(:send).exactly(2).times.with(message) |
23 | 31 | ||
24 | notification_service.create_notification(problem) | 32 | notification_service.create_notification(problem) |
25 | end | 33 | end |
26 | 34 | ||
27 | - describe "multiple room_ids (or users)" do | 35 | + describe "multiple users_ids" do |
28 | before(:each) do | 36 | before(:each) do |
29 | # setup | 37 | # setup |
30 | @notice = Fabricate :notice | 38 | @notice = Fabricate :notice |
31 | @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app | 39 | @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app |
32 | @problem = @notice.problem | 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 | # gtalk stubbing | 45 | # gtalk stubbing |
36 | @gtalk = mock('GtalkService') | 46 | @gtalk = mock('GtalkService') |
@@ -45,9 +55,11 @@ describe NotificationService::GtalkService do | @@ -45,9 +55,11 @@ describe NotificationService::GtalkService do | ||
45 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) | 55 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) |
46 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) | 56 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) |
47 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) | 57 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) |
58 | + Jabber::MUC::SimpleMUCClient.should_not_receive(:new) | ||
48 | @gtalk.should_receive(:send).exactly(4).times | 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 | @notification_service.create_notification(@problem) | 63 | @notification_service.create_notification(@problem) |
52 | end | 64 | end |
53 | it "should send a notification to all ';' separated users" do | 65 | it "should send a notification to all ';' separated users" do |
@@ -55,9 +67,11 @@ describe NotificationService::GtalkService do | @@ -55,9 +67,11 @@ describe NotificationService::GtalkService do | ||
55 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) | 67 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) |
56 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) | 68 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) |
57 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) | 69 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) |
70 | + Jabber::MUC::SimpleMUCClient.should_not_receive(:new) | ||
58 | @gtalk.should_receive(:send).exactly(4).times | 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 | @notification_service.create_notification(@problem) | 75 | @notification_service.create_notification(@problem) |
62 | end | 76 | end |
63 | it "should send a notification to all ' ' separated users" do | 77 | it "should send a notification to all ' ' separated users" do |
@@ -65,11 +79,47 @@ describe NotificationService::GtalkService do | @@ -65,11 +79,47 @@ describe NotificationService::GtalkService do | ||
65 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) | 79 | Jabber::Message.should_receive(:new).with("second@domain.org", @error_msg) |
66 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) | 80 | Jabber::Message.should_receive(:new).with("third@domain.org", @error_msg) |
67 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) | 81 | Jabber::Message.should_receive(:new).with("fourth@domain.org", @error_msg) |
82 | + Jabber::MUC::SimpleMUCClient.should_not_receive(:new) | ||
68 | @gtalk.should_receive(:send).exactly(4).times | 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 | @notification_service.create_notification(@problem) | 87 | @notification_service.create_notification(@problem) |
72 | end | 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 | end | 122 | end |
123 | + | ||
74 | end | 124 | end |
75 | 125 |
spec/spec_helper.rb
@@ -6,6 +6,7 @@ require 'rspec/rails' | @@ -6,6 +6,7 @@ require 'rspec/rails' | ||
6 | require 'database_cleaner' | 6 | require 'database_cleaner' |
7 | require 'webmock/rspec' | 7 | require 'webmock/rspec' |
8 | require 'xmpp4r' | 8 | require 'xmpp4r' |
9 | +require 'xmpp4r/muc' | ||
9 | 10 | ||
10 | # Requires supporting files with custom matchers and macros, etc, | 11 | # Requires supporting files with custom matchers and macros, etc, |
11 | # in ./support/ and its subdirectories. | 12 | # in ./support/ and its subdirectories. |