Skip to content

Instantly share code, notes, and snippets.

@joakimk
Forked from jpr5/bot.rb
Created April 29, 2011 06:05
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save joakimk/947924 to your computer and use it in GitHub Desktop.
Save joakimk/947924 to your computer and use it in GitHub Desktop.
XMPP/Ruby Bot for HipChat with support for multiple rooms
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment