From c1ca338fdb32b05fd047730be9ca6569d22c6806 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Mon, 20 Mar 2017 14:08:34 +0000 Subject: Updated gems to (roughly) jessie versions; removed XMPP support. Also changed the postgres tests to "skip" if no postgres db is available. --- Gemfile | 57 +- Gemfile.lock | 145 ++-- lib/mauve/configuration_builders/person.rb | 5 +- lib/mauve/notifier.rb | 46 +- lib/mauve/notifiers.rb | 1 - .../notifiers/templates/email_subject.txt.erb | 2 +- lib/mauve/notifiers/templates/hipchat.txt.erb | 2 +- lib/mauve/notifiers/templates/sms.txt.erb | 23 +- lib/mauve/notifiers/templates/xmpp.html.erb | 23 - lib/mauve/notifiers/templates/xmpp.txt.erb | 22 - lib/mauve/notifiers/xmpp.rb | 837 --------------------- lib/mauve/people_list.rb | 5 - lib/mauve/person.rb | 14 +- test/mauve_test_helper.rb | 2 +- test/tc_mauve_configuration_builders_person.rb | 3 - test/tc_mauve_database_peculiarities.rb | 2 +- 16 files changed, 134 insertions(+), 1055 deletions(-) mode change 120000 => 100644 lib/mauve/notifiers/templates/sms.txt.erb delete mode 100644 lib/mauve/notifiers/templates/xmpp.html.erb delete mode 100644 lib/mauve/notifiers/templates/xmpp.txt.erb delete mode 100644 lib/mauve/notifiers/xmpp.rb diff --git a/Gemfile b/Gemfile index 8c0ed3c..0bd6198 100644 --- a/Gemfile +++ b/Gemfile @@ -1,36 +1,35 @@ source "https://rubygems.org" -gem "bcrypt-ruby", "=3.0.1" -gem "timecop", "=0.3.5" -gem "log4r", "=1.0.6" -gem "ipaddress", "=0.8.0" -gem "webmock", "=1.7.6" -gem "ruby_protobuf", "=0.4.11" -gem "json", "=1.8.1" -gem "datamapper", "=1.2.0" -gem "dm-aggregates", "=1.2.0" -gem "dm-do-adapter", "=1.2.0" -gem "dm-migrations", "=1.2.0" -gem "dm-postgres-adapter", "=1.2.0" -gem "dm-sqlite-adapter", "=1.2.0" -gem "dm-transactions", "=1.2.0" -gem "dm-types", "=1.2.0" -gem "dm-validations", "=1.2.0" -gem "sanitize", "=2.0.3" -gem "rmail", "=1.1.0" -gem "xmpp4r", "=0.5.6" -gem "thin", "=1.6.3" -gem "haml", "=3.0.15" -gem "RedCloth" -gem "rack" -gem "rack-protection" -gem "rack-test" -gem "rack-flash3" -gem "tilt", "=1.3.3" -gem "sinatra", "=1.4.6" -gem "locale", "=2.1.0" +gem "bcrypt-ruby", "= 3.1.5" +gem "log4r", "= 1.1.10" +gem "ipaddress", "= 0.8.0" +gem "ruby_protobuf", "= 0.4.11" +gem "json", "= 1.8.1" +gem "datamapper" +gem "dm-aggregates" +gem "dm-do-adapter" +gem "dm-migrations" +gem "dm-postgres-adapter" +gem "dm-sqlite-adapter" +gem "dm-transactions" +gem "dm-types" +gem "dm-validations" +gem "sanitize", "= 2.1.0" +gem "rmail", "= 1.1.0" +gem "thin", "= 1.6.3" +gem "haml", "= 4.0.5" +gem "RedCloth", "= 4.2.9" +gem "rack", "= 1.5.2" +gem "rack-protection", "= 1.5.2" +gem "rack-flash3", "= 1.0.5" +gem "tilt", "= 1.4.1" +gem "sinatra", "~> 1.4.5" +gem "locale", "= 2.1.0" group :test do gem "simplecov", :require => false + gem "rack-test", "= 0.6.3" + gem "webmock", "= 1.19.0" + gem "timecop", "= 0.7.1" end diff --git a/Gemfile.lock b/Gemfile.lock index 8a4017f..437527d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,12 +2,15 @@ GEM remote: https://rubygems.org/ specs: RedCloth (4.2.9) - addressable (2.3.8) - bcrypt-ruby (3.0.1) - crack (0.4.2) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) + bcrypt (3.1.11) + bcrypt-ruby (3.1.5) + bcrypt (>= 3.1.3) + crack (0.4.3) safe_yaml (~> 1.0.0) - daemons (1.2.2) - data_objects (0.10.15) + daemons (1.2.4) + data_objects (0.10.17) addressable (~> 2.1) datamapper (1.2.0) dm-aggregates (~> 1.2.0) @@ -33,12 +36,12 @@ GEM dm-postgres-adapter (1.2.0) dm-do-adapter (~> 1.2.0) do_postgres (~> 0.10.6) - dm-serializer (1.2.0) + dm-serializer (1.2.2) dm-core (~> 1.2.0) - fastercsv (~> 1.5.4) - json (~> 1.5.4) - json_pure (~> 1.5.4) - multi_json (~> 1.0.3) + fastercsv (~> 1.5) + json (~> 1.6) + json_pure (~> 1.6) + multi_json (~> 1.0) dm-sqlite-adapter (1.2.0) dm-do-adapter (~> 1.2.0) do_sqlite3 (~> 0.10.6) @@ -46,98 +49,98 @@ GEM dm-core (~> 1.2.0) dm-transactions (1.2.0) dm-core (~> 1.2.0) - dm-types (1.2.0) - bcrypt-ruby (~> 3.0.0) + dm-types (1.2.2) + bcrypt-ruby (~> 3.0) dm-core (~> 1.2.0) - fastercsv (~> 1.5.4) - json (~> 1.5.4) - multi_json (~> 1.0.3) - stringex (~> 1.3.0) - uuidtools (~> 2.1.2) + fastercsv (~> 1.5) + json (~> 1.6) + multi_json (~> 1.0) + stringex (~> 1.4) + uuidtools (~> 2.1) dm-validations (1.2.0) dm-core (~> 1.2.0) - do_postgres (0.10.15) - data_objects (= 0.10.15) - do_sqlite3 (0.10.15) - data_objects (= 0.10.15) + do_postgres (0.10.17) + data_objects (= 0.10.17) + do_sqlite3 (0.10.17) + data_objects (= 0.10.17) docile (1.1.5) - eventmachine (1.0.7) + eventmachine (1.2.3) fastercsv (1.5.5) - haml (3.0.15) + haml (4.0.5) + tilt ipaddress (0.8.0) - json (1.5.4) - json_pure (1.5.5) - spruz (~> 0.2.8) + json (1.8.1) + json_pure (1.8.6) locale (2.1.0) - log4r (1.0.6) - multi_json (1.0.4) - nokogiri (1.5.11) - rack (1.6.0) + log4r (1.1.10) + mini_portile2 (2.1.0) + multi_json (1.12.1) + nokogiri (1.7.1) + mini_portile2 (~> 2.1.0) + public_suffix (2.0.5) + rack (1.5.2) rack-flash3 (1.0.5) rack - rack-protection (1.5.3) + rack-protection (1.5.2) rack rack-test (0.6.3) rack (>= 1.0) rmail (1.1.0) ruby_protobuf (0.4.11) safe_yaml (1.0.4) - sanitize (2.0.3) - nokogiri (>= 1.4.4, < 1.6) - simplecov (0.9.2) + sanitize (2.1.0) + nokogiri (>= 1.4.4) + simplecov (0.14.1) docile (~> 1.1.0) - multi_json (~> 1.0) - simplecov-html (~> 0.9.0) - simplecov-html (0.9.0) - sinatra (1.4.6) - rack (~> 1.4) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + sinatra (1.4.8) + rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) - spruz (0.2.13) - stringex (1.3.3) + stringex (1.5.1) thin (1.6.3) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0) rack (~> 1.0) - tilt (1.3.3) - timecop (0.3.5) + tilt (1.4.1) + timecop (0.7.1) uuidtools (2.1.5) - webmock (1.7.6) - addressable (~> 2.2, > 2.2.5) - crack (>= 0.1.7) - xmpp4r (0.5.6) + webmock (1.19.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) PLATFORMS ruby DEPENDENCIES - RedCloth - bcrypt-ruby (= 3.0.1) - datamapper (= 1.2.0) - dm-aggregates (= 1.2.0) - dm-do-adapter (= 1.2.0) - dm-migrations (= 1.2.0) - dm-postgres-adapter (= 1.2.0) - dm-sqlite-adapter (= 1.2.0) - dm-transactions (= 1.2.0) - dm-types (= 1.2.0) - dm-validations (= 1.2.0) - haml (= 3.0.15) + RedCloth (= 4.2.9) + bcrypt-ruby (= 3.1.5) + datamapper + dm-aggregates + dm-do-adapter + dm-migrations + dm-postgres-adapter + dm-sqlite-adapter + dm-transactions + dm-types + dm-validations + haml (= 4.0.5) ipaddress (= 0.8.0) - json (= 1.5.4) + json (= 1.8.1) locale (= 2.1.0) - log4r (= 1.0.6) - rack - rack-flash3 - rack-protection - rack-test + log4r (= 1.1.10) + rack (= 1.5.2) + rack-flash3 (= 1.0.5) + rack-protection (= 1.5.2) + rack-test (= 0.6.3) rmail (= 1.1.0) ruby_protobuf (= 0.4.11) - sanitize (= 2.0.3) + sanitize (= 2.1.0) simplecov - sinatra (= 1.4.6) + sinatra (~> 1.4.5) thin (= 1.6.3) - tilt (= 1.3.3) - timecop (= 0.3.5) - webmock (= 1.7.6) - xmpp4r (= 0.5.6) + tilt (= 1.4.1) + timecop (= 0.7.1) + webmock (= 1.19.0) diff --git a/lib/mauve/configuration_builders/person.rb b/lib/mauve/configuration_builders/person.rb index aac5f69..ccc67aa 100644 --- a/lib/mauve/configuration_builders/person.rb +++ b/lib/mauve/configuration_builders/person.rb @@ -23,7 +23,6 @@ module Mauve is_attribute "password" is_attribute "sms" is_attribute "email" - is_attribute "xmpp" is_attribute "hipchat" is_flag_attribute "notify_when_on_holiday" @@ -109,8 +108,8 @@ module Mauve # Set up some default notify levels. # if person.urgent.nil? and person.normal.nil? and person.low.nil? - person.urgent = Proc.new { sms ; xmpp ; email } - person.normal = Proc.new { xmpp ; email } + person.urgent = Proc.new { sms ; email } + person.normal = Proc.new { email } person.low = Proc.new { email } end diff --git a/lib/mauve/notifier.rb b/lib/mauve/notifier.rb index 35ac019..4939b03 100644 --- a/lib/mauve/notifier.rb +++ b/lib/mauve/notifier.rb @@ -1,6 +1,5 @@ require 'mauve/mauve_thread' require 'mauve/notifiers' -require 'mauve/notifiers/xmpp' module Mauve @@ -15,8 +14,7 @@ module Mauve include Singleton # Stop the notifier thread. This just makes sure that all the - # notifications in the buffer have been sent before closing the XMPP - # connection. + # notifications in the buffer have been sent. # def stop super @@ -25,11 +23,6 @@ module Mauve # Flush the queue. # main_loop - - if Configuration.current.notification_methods['xmpp'] - Configuration.current.notification_methods['xmpp'].close - end - end # @@ -69,43 +62,6 @@ module Mauve # # def main_loop - - # - # Make sure we're connected to the XMPP server if needed on every iteration. - # - xmpp = Configuration.current.notification_methods['xmpp'] - - if xmpp and !xmpp.ready? - # - # Connect to XMPP server - # - xmpp.connect - - # - # Join all chats and shit. Unless the connection failed. - # - Configuration.current.people.each do |username, person| - # - # Ignore people without XMPP stanzas. - # - next unless person.respond_to?(:xmpp) and person.xmpp - - # - # For each JID, either ensure they're on our roster, or that we're in - # that chat room. - # - jid = if xmpp.is_muc?(person.xmpp) - xmpp.join_muc(person.xmpp) - else - xmpp.ensure_roster_and_subscription!(person.xmpp) - end - - Configuration.current.people[username].xmpp = jid unless jid.nil? - - end if xmpp.ready? - - end - # # Cycle through the buffer. # diff --git a/lib/mauve/notifiers.rb b/lib/mauve/notifiers.rb index 383db5e..424b2c1 100644 --- a/lib/mauve/notifiers.rb +++ b/lib/mauve/notifiers.rb @@ -2,7 +2,6 @@ require 'mauve/notifiers/email' require 'mauve/notifiers/sms_default' require 'mauve/notifiers/sms_aql' require 'mauve/notifiers/sms_clockwork' -require 'mauve/notifiers/xmpp' require 'mauve/notifiers/hipchat' module Mauve diff --git a/lib/mauve/notifiers/templates/email_subject.txt.erb b/lib/mauve/notifiers/templates/email_subject.txt.erb index 802c711..45fda99 120000 --- a/lib/mauve/notifiers/templates/email_subject.txt.erb +++ b/lib/mauve/notifiers/templates/email_subject.txt.erb @@ -1 +1 @@ -xmpp.txt.erb \ No newline at end of file +sms.txt.erb \ No newline at end of file diff --git a/lib/mauve/notifiers/templates/hipchat.txt.erb b/lib/mauve/notifiers/templates/hipchat.txt.erb index 802c711..45fda99 120000 --- a/lib/mauve/notifiers/templates/hipchat.txt.erb +++ b/lib/mauve/notifiers/templates/hipchat.txt.erb @@ -1 +1 @@ -xmpp.txt.erb \ No newline at end of file +sms.txt.erb \ No newline at end of file diff --git a/lib/mauve/notifiers/templates/sms.txt.erb b/lib/mauve/notifiers/templates/sms.txt.erb deleted file mode 120000 index 802c711..0000000 --- a/lib/mauve/notifiers/templates/sms.txt.erb +++ /dev/null @@ -1 +0,0 @@ -xmpp.txt.erb \ No newline at end of file diff --git a/lib/mauve/notifiers/templates/sms.txt.erb b/lib/mauve/notifiers/templates/sms.txt.erb new file mode 100644 index 0000000..c148f41 --- /dev/null +++ b/lib/mauve/notifiers/templates/sms.txt.erb @@ -0,0 +1,22 @@ +<%=alert.id %>: <%= alert.update_type.upcase %> (<%= alert.level %>): <% +case alert.update_type +when "cleared" +%><%= alert.cleared_at.to_s_relative %><% +when "acknowledged" +%><%= alert.acknowledged_at.to_s_relative %> by <%= alert.acknowledged_by %> until <%= alert.will_unacknowledge_at.to_s_human %><% +else +%><%= alert.raised_at.to_s_relative %><% +end +%>: <%= alert.subject %> <%= alert.summary %><% +if alert.source != alert.subject +%> -- from <%= alert.source %><% +end +%>. <%=WebInterface.url_for(alert)%><% +if defined? was_suppressed and defined? will_suppress + if was_suppressed and not will_suppress +%> (Normal service for <%= alert.level %> alerts has resumed.)<% + elsif will_suppress and not was_suppressed +%> (Further <%= alert.level %> alerts suppressed until things calm down.)<% + end +end +%> diff --git a/lib/mauve/notifiers/templates/xmpp.html.erb b/lib/mauve/notifiers/templates/xmpp.html.erb deleted file mode 100644 index 7792bd9..0000000 --- a/lib/mauve/notifiers/templates/xmpp.html.erb +++ /dev/null @@ -1,23 +0,0 @@ - -<%= alert.id%>: <%= alert.update_type.upcase %> (<%= alert.level %>): <% -case alert.update_type -when "cleared" -%><%= alert.cleared_at.to_s_relative %><% -when "acknowledged" -%><%= alert.acknowledged_at.to_s_relative %> by <%= alert.acknowledged_by %> until <%= alert.will_unacknowledge_at.to_s_human %><% -else -%><%= alert.raised_at.to_s_relative %><% -end -%>: <%= alert.subject %> <%= alert.summary %><% -if alert.source != alert.subject -%> -- from <%= alert.source %><% -end -%>.<% -if defined? was_suppressed and defined? will_suppress - if was_suppressed and not will_suppress -%>
Normal service for <%= alert.level %> alerts has resumed.<% - elsif will_suppress and not was_suppressed -%>
Further <%= alert.level %> alerts suppressed until things calm down.<% - end -end -%> diff --git a/lib/mauve/notifiers/templates/xmpp.txt.erb b/lib/mauve/notifiers/templates/xmpp.txt.erb deleted file mode 100644 index c148f41..0000000 --- a/lib/mauve/notifiers/templates/xmpp.txt.erb +++ /dev/null @@ -1,22 +0,0 @@ -<%=alert.id %>: <%= alert.update_type.upcase %> (<%= alert.level %>): <% -case alert.update_type -when "cleared" -%><%= alert.cleared_at.to_s_relative %><% -when "acknowledged" -%><%= alert.acknowledged_at.to_s_relative %> by <%= alert.acknowledged_by %> until <%= alert.will_unacknowledge_at.to_s_human %><% -else -%><%= alert.raised_at.to_s_relative %><% -end -%>: <%= alert.subject %> <%= alert.summary %><% -if alert.source != alert.subject -%> -- from <%= alert.source %><% -end -%>. <%=WebInterface.url_for(alert)%><% -if defined? was_suppressed and defined? will_suppress - if was_suppressed and not will_suppress -%> (Normal service for <%= alert.level %> alerts has resumed.)<% - elsif will_suppress and not was_suppressed -%> (Further <%= alert.level %> alerts suppressed until things calm down.)<% - end -end -%> diff --git a/lib/mauve/notifiers/xmpp.rb b/lib/mauve/notifiers/xmpp.rb deleted file mode 100644 index 8ab6d48..0000000 --- a/lib/mauve/notifiers/xmpp.rb +++ /dev/null @@ -1,837 +0,0 @@ -require 'log4r' -require 'xmpp4r' -require 'xmpp4r/roster' -require 'xmpp4r/muc' -# require 'xmpp4r/xhtml' -# require 'xmpp4r/discovery/helper/helper' -require 'mauve/notifiers/debug' - - - -# -# A couple of monkey patches to fix up all this nonsense. -# -module Jabber - # - # Monkey patch of the close commands. For good reasons, though I can't - # remember why. - # - class Stream - def close - # - # Just close - # - close! - end - - def close! - 10.times do - pr = 0 - @tbcbmutex.synchronize { pr = @processing } - break if pr == 0 - Thread::pass if pr > 0 - sleep 1 - end - - # Order Matters here! If this method is called from within - # @parser_thread then killing @parser_thread first would - # mean the other parts of the method fail to execute. - # That would be bad. So kill parser_thread last - @tbcbmutex.synchronize { @processing = 0 } - if @fd and !@fd.closed? - @fd.close - stop - end - @status = DISCONNECTED - end - end -end - - - - -module Mauve - module Notifiers - - # - # This is the Jabber/XMMP notifiers module. - # - module Xmpp - - # - # The default provider is XMMP, although this should really be broken out - # into its own provider to allow multple ways of doing XMPP. - # - class Default - - include Jabber - - # Atrtribute. - attr_reader :name - - # Atrtribute. - attr_accessor :password - - def initialize(name) - Jabber::logger = self.logger -# Jabber::debug = true -# Jabber::warnings = true - - @name = name - @mucs = {} - @roster = nil - @closing = false - @client = nil - end - - # The logger instance - # - # @return [Log4r::Logger] - def logger - # Give the logger a sane name - @logger ||= Log4r::Logger.new self.class.to_s.sub(/::Default$/,"") - end - - # Sets the client's JID - # - # @param [String] jid The JID required. - # @return [Jabber::JID] The client JID. - def jid=(jid) - @jid = JID.new(jid) - end - - # Connects to the XMPP server, and sets up the roster - # - # @return [Jabber::Client, NilClass] The connected client, or nil in the case of failure - def connect - logger.debug "Starting connection to #{@jid}" - - # Make sure we're disconnected. - self.close if @client.is_a?(Client) - - @client = Client.new(@jid) - - @closing = false - @client.connect - @client.auth_nonsasl(@password, false) - @roster = Roster::Helper.new(@client) - - # Unconditionally accept all roster add requests, and respond with a - # roster add + subscription request of our own if we're not subscribed - # already - @roster.add_subscription_request_callback do |ri, presence| - Thread.new do - if is_known_contact?(presence.from) - logger.info("Accepting subscription request from #{presence.from}") - @roster.accept_subscription(presence.from) - ensure_roster_and_subscription!(presence.from) - else - logger.info("Declining subscription request from #{presence.from}") - @roster.decline_subscription(presence.from) - end - end.join - end - - @client.add_message_callback do |m| - receive_message(m) - end - - @roster.wait_for_roster - - @client.send(Presence.new(nil, "Woo!").set_type(nil)) - - logger.info "Connected as #{@jid}" - - # @client.on_exception do |ex, stream, where| - # - # The XMPP4R exception clauses in Stream all close the stream, so - # we just need to reconnect. - # - # unless ex.nil? or @closing - # logger.warn(["Caught",ex.class,ex.to_s,"during XMPP",where].join(" ")) - # logger.debug ex.backtrace.join("\n") - # self.close - # end - # end - rescue StandardError => ex - logger.error "Connect failed #{ex.to_s}" - logger.debug ex.backtrace.join("\n") - self.close - @client = nil - end - - def stop - @client.stop - end - - # - # Closes the XMPP connection, if possible. Sets @client to nil. - # - # @return [NilClass] - def close - @closing = true - if @client - if @client.is_connected? - @mucs.each do |jid, muc| - muc[:client].exit("Goodbye!") if muc[:client].active? - end - @client.send(Presence.new(nil, "Goodbye!").set_type(:unavailable)) - end - @client.close! - end - @client = nil - end - - # Determines if the client is ready. - # - # @return [Boolean] - def ready? - @client.is_a?(Jabber::Client) and @client.is_connected? - end - - # Attempt to send an alert using XMPP. - # - # @param [String] destination The JID you're sending the alert to. This should be - # a bare JID in the case of an individual, or +muc:room@server+ for - # chatrooms (XEP0045). - # - # @param [Mauve::Alert] alert This is turned into a pretty - # message and sent to the destination as a message, if +conditions+ - # are met. - # - # @param [Array] all_alerts Currently ignored. - # - # @param [Hash] conditions Conditions that determine if an alert should be sent - # - # @option conditions [Array] :if_presence Checks whether the jid in question - # has a presence matching one or more of the choices - see - # Mauve::Notifiers::Xmpp::Default#check_jid_has_presence for options. - # - # @return [Boolean] - def send_alert(destination, alert, all_alerts, conditions = {}) - destination_jid = JID.new(destination) - - was_suppressed = conditions[:was_suppressed] || false - will_suppress = conditions[:will_suppress] || false - - if conditions && !check_alert_conditions(destination_jid, conditions) - logger.info("Alert conditions not met, not sending XMPP alert to #{destination_jid}") - return false - end - - template_file = File.join(File.dirname(__FILE__),"templates","xmpp.txt.erb") - - txt = if File.exists?(template_file) - ERB.new(File.read(template_file)).result(binding).chomp - else - logger.error("Could not find xmpp.txt.erb template") - alert.to_s - end - - template_file = File.join(File.dirname(__FILE__),"templates","xmpp.html.erb") - - xhtml = if File.exists?(template_file) - ERB.new(File.read(template_file)).result(binding).chomp - else - logger.error("Could not find xmpp.txt.erb template") - alert.to_s - end - - msg_type = (is_muc?(destination_jid) ? :groupchat : :chat) - - send_message(destination_jid, txt, xhtml, msg_type) - end - - # Sends a message to the destionation. - def send_message(jid, msg, html_msg=nil, msg_type=:chat) - return false unless self.ready? - - jid = JID.new(jid) unless jid.is_a?(JID) - - message = Message.new(jid) - message.body = msg - if html_msg - begin - html_msg = REXML::Document.new(html_msg) unless html_msg.is_a?(REXML::Document) - message.add_element(html_msg) - rescue REXML::ParseException - logger.error "Bad XHTML: #{html_msg.inspect}" - end - end - - message.to = jid - message.type = msg_type - - if message.type == :groupchat and is_muc?(jid) - jid = join_muc(jid.strip) - muc = @mucs[jid][:client] - - if muc - muc.send(message) - true - else - logger.warn "Failed to join MUC #{jid} when trying to send a message" - false - end - else - # - # We aren't interested in sending things to people who aren't online. - # - ensure_roster_and_subscription!(jid) - - if check_jid_has_presence(jid) - @client.send(message) - true - else - false - end - end - end - - # - # Joins a chat, and returns the stripped JID of the chat joined. - # - def join_muc(jid, password=nil) - self.connect unless self.ready? - - return unless self.ready? - - if jid.is_a?(String) and jid =~ /^muc:(.*)/ - jid = JID.new($1) - end - - unless jid.is_a?(JID) - logger.warn "#{jid} is not a MUC" - return - end - - jid.resource = @client.jid.resource if jid.resource.to_s.empty? - - if !@mucs[jid.strip] - - logger.debug("Adding new MUC client for #{jid}") - - @mucs[jid.strip] = {:jid => jid, :password => password, :client => Jabber::MUC::MUCClient.new(@client)} - - # Add some callbacks - @mucs[jid.strip][:client].add_message_callback do |m| - receive_message(m) - end - - @mucs[jid.strip][:client].add_private_message_callback do |m| - receive_message(m) - end - - end - - if !@mucs[jid.strip][:client].active? - # - # Make sure we have a resource. - # - @mucs[jid.strip][:client].join(jid, password) - - logger.info("Joined #{jid.strip}") - else - logger.debug("Already joined #{jid.strip}.") - end - - # - # Return the JID object - # - jid.strip - end - - # - # Checks whether the destination JID is a MUC. - # - def is_muc?(jid) - (jid.is_a?(JID) and @mucs.keys.include?(jid.strip)) or - (jid.to_s =~ /^muc:(.*)/) - - # - # It would be nice to use service discovery to determin this, but it - # turns out that it is shite in xmpp4r. It doesn't return straight - # away with an answer, making it a bit useless. Some sort of weird - # threading issue, I think. - # - # begin - # logger.warn caller.join("\n") - # cl = Discovery::Helper.new(@client) - # res = cl.get_info_for(jid.strip) - # @client.wait - # logger.warn "hello #{res.inspect}" - # res.is_a?(Discovery::IqQueryDiscoInfo) and res.identity.category == :conference - # rescue Jabber::ServerError => ex - # false - # end - end - - # - # Checks to see if the JID is in our roster, and whether we are - # subscribed to it or not. Will add to the roster and subscribe as - # is necessary to ensure both are true. - # - def ensure_roster_and_subscription!(jid) - self.connect unless self.ready? - - return unless self.ready? - - return jid if is_muc?(jid) - - jid = JID.new(jid) unless jid.is_a?(JID) - - ri = @roster.find(jid).values.first - @roster.add(jid, nil, true) if ri.nil? - - ri = @roster.find(jid).values.first - ri.subscribe unless [:to, :both, :remove].include?(ri.subscription) - ri.jid - rescue StandardError => ex - logger.error("Problem ensuring that #{jid} is subscribed and in mauve's roster: #{ex.inspect}") - nil - end - - protected - - def receive_message(msg) - # - # Don't talk to self - # - if @jid == msg.from or @mucs.any?{|jid, muc| muc.is_a?(Hash) and muc.has_key?(:client) and muc[:client].jid == msg.from} - return nil - end - - # We only want to hear messages from known contacts. - unless is_known_contact?(msg.from) - # ignore message - logger.info "Ignoring message from unknown contact #{msg.from}" - return nil - end - - case msg.type - when :error - receive_error_message(msg) - when :groupchat - receive_groupchat_message(msg) - else - receive_normal_message(msg) - end - end - - def receive_error_message(msg) - logger.warn("Caught XMPP error #{msg}") - nil - end - - def receive_normal_message(msg) - # - # Treat invites specially - # - if msg.x("jabber:x:conference") - # - # recieved an invite. Need to mangle the jid. - # - jid =JID.new(msg.x("jabber:x:conference").attribute("jid")) - # jid.resource = @client.jid.resource - logger.info "Received an invite to #{jid}" - unless join_muc(jid) - logger.warn "Failed to join MUC #{jid} following invitation" - return nil - end - elsif msg.body - # - # Received a message with a body. - # - jid = msg.from - end - - if jid - reply = parse_command(msg) - send_message(jid, reply, nil, msg.type) - end - end - - def receive_groupchat_message(msg) - # - # We only want group chat messages from MUCs we're already joined to, - # that we've not sent ourselves, that are not historical, and that - # match our resource or node in the body. - # - if @mucs[msg.from.strip][:client].is_a?(MUC::MUCClient) and - msg.x("jabber:x:delay") == nil and - (msg.body =~ /\b#{Regexp.escape(@mucs[msg.from.strip][:client].jid.resource)}\b/i or - msg.body =~ /\b#{Regexp.escape(@client.jid.node)}\b/i) - - receive_normal_message(msg) - end - end - - def parse_command(msg) - case msg.body - when /help(\s+\w+)?/i - do_parse_help(msg) - when /show\s?/i - do_parse_show(msg) - when /ack/i - do_parse_ack(msg) - when /clear/i - do_parse_clear(msg) - when /destroy\s?/i - "Sorry -- destroy has been disabled. Try \"clear\" instead." - else - File.executable?('/usr/games/fortune') ? `/usr/games/fortune -s -n 60`.chomp : "I'd love to stay and chat, but I'm really quite busy" - end - end - - def do_parse_help(msg) - msg.body =~ /help\s+(\w+)/i - cmd = $1 - - return case cmd - when /^show/ - < for