#!/usr/bin/env ruby require 'rubygems' require 'xmpp4r' require 'xmpp4r/muc/helper/simplemucclient' # Most of this is borrowed from https://gist.github.com/941931 # Added support for multiple rooms and external handling of messages. # We want the MUC functionality to just handle shit for us. Unfortunately we # have to override/repeat the join method in order to add the directive that # will disable the history being sent to us. :-( module Jabber module MUC class MUCClient def join(jid, password=nil) if active? raise "MUCClient already active" end @jid = (jid.kind_of?(JID) ? jid : JID.new(jid)) activate # Joining pres = Presence.new pres.to = @jid pres.from = @my_jid xmuc = XMUC.new xmuc.password = password pres.add(xmuc) # NOTE: Adding 'maxstanzas="0"' to 'history' subelement of xmuc nixes # the history being sent to us when we join. history = XMPPElement.new('history') history.add_attributes({'maxstanzas' => '0'}) xmuc.add(history) # We don't use Stream#send_with_id here as it's unknown # if the MUC component *always* uses our stanza id. error = nil @stream.send(pres) { |r| if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error # Error from room error = r.error true # type='unavailable' may occur when the MUC kills our previous instance, # but all join-failures should be type='error' elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable # Our own presence reflected back - success if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first) @affiliation = i.affiliation # we're interested in if it's :owner @role = i.role # :moderator ? end handle_presence(r, false) true else # Everything else false end } if error deactivate raise ServerError.new(error) end self end end end end class Bot attr_accessor :config, :client, :mucs def initialize(config) self.config = config self.client = Jabber::Client.new(config[:jid]) self.mucs = {} config[:rooms].each { |name, jid| self.mucs[name] = Jabber::MUC::SimpleMUCClient.new(client) } if Jabber.logger = config[:debug] Jabber.debug = true end self end def connect client.connect client.auth(config[:password]) client.send(Jabber::Presence.new.set_type(:available)) self.mucs.each do |room, muc| muc.on_message do |time, nick, text| next if nick == config[:nick] yield room, nick, text end muc.join(self.config[:rooms][room] + '/' + config[:nick]) end self end def send_message(room, msg) if msg[0, 6] == '/topic' msg = msg.split('/topic').last.strip message = Jabber::Message.new(muc.room) message.subject = msg muc.send message else muc.send Jabber::Message.new(muc.room, msg) end end end bot = Bot.new({ :server => 'conf.hipchat.com', :rooms => { :dev => '...@conf.hipchat.com', :shared => '...@conf.hipchat.com' }, :nick => '...', :jid => '...@chat.hipchat.com', :password => '...' }) bot.connect { |room, nick, message| bot.send_message(room, "Got message from #{nick} in #{room}: #{message}") } loop do sleep 1 end