Skip to content

Instantly share code, notes, and snippets.

@jpr5
Created April 26, 2011 07:13
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jpr5/941931 to your computer and use it in GitHub Desktop.
Save jpr5/941931 to your computer and use it in GitHub Desktop.
XMPP/Ruby Bot for HipChat
#!/usr/bin/env ruby
#
# Script: HipChat bot in Ruby
# Author: Jordan Ritter <jpr5@darkridge.com>
#
unless `rvm-prompt i g`.chomp == "ree@xmpp"
exec("rvm ree@xmpp ruby #{$0}")
end
require 'rubygems'
require 'ruby-debug'
require 'xmpp4r'
require 'xmpp4r/muc/helper/simplemucclient'
require 'open-uri'
require 'cgi'
require 'json'
require 'facets'
require 'facets/random'
class Bot
attr_accessor :config, :client, :muc
def initialize(config)
self.config = config
self.client = Jabber::Client.new(config[:jid])
self.muc = 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))
salutation = config[:nick].split(/\s+/).first
muc.on_message do |time, nick, text|
next unless text =~ /^@?#{salutation}:*\s+(.+)$/i or text =~ /^!(.+)$/
begin
process(nick, $1)
rescue => e
warn "exception: #{e.inspect}"
end
end
muc.join(config[:room] + '/' + config[:nick])
self
end
def process(from, command)
warn "command: #{from}> #{command}"
firstname = from.split(/ /).first
case command
# Speech
when /^(hey|hi|hello|sup|what's up|what's happenin(|g)|yo)(|[!?])$/ then
respond "Yoyoyo #{firstname}, what it is?"
when /I love you/i then
respond "Awww, I love you too #{firstname}!"
when /you're the best/i then
respond "Well shit, #{firstname}, don't I know it!"
# @jordanisms
when /cock|ball|dong/i then
# replace all words in the extensive lexicon with another one
retort = command.gsub(/cock|ball|dong/i) do |match|
# make sure it's a swap
options = %w{ cock ball dong } - [ match.downcase ]
swap = options.at_rand
# case match, character by character
match_bytes = []
match.each_byte {|c| match_bytes << c }
swap_chars = []
swap.each_byte do |c|
was = match_bytes[swap_chars.size]
c = (c & 0xDF) | (was & 0x20)
swap_chars << c.chr
end
next swap_chars.join('')
end
respond retort
# Commands
when /^echo\s+([^\s].*)$/ then
respond "#{from}: #{$1}"
when /^weather\s+([^\s]+)/ then
query = 'select item from weather.forecast where location = "' + $1 + '"'
uri = 'http://query.yahooapis.com/v1/public/yql?format=json&q=' + CGI.escape(query)
data = JSON.parse open(uri).read
item = data["query"]["results"]["channel"]["item"]
title = item["title"]
condition = item["condition"]
response = title
response += " are " + condition['temp'] + ' degrees and ' + condition['text'] if condition
respond response
else
retort = %w{ what huh steak }.at_rand
respond "#{from}: #{retort}?"
end
end
def respond(msg)
muc.send Jabber::Message.new(muc.room, msg)
end
def run
warn "running"
loop { sleep 1 }
end
# For the day when we can connect multiple times and listen on multiple chat
# rooms: Bot.run(settings)
def self.run(config)
bots = []
config[:rooms].each do |room|
config[:room] = room
bots << Bot.new(config).connect
end
bots.last.run
end
end
# Using resource "/bot" on the user JID prevents HipChat from sending the
# history upon channel join.
settings = {
:server => 'chat-a1.hipchat.com',
:jid => '6075_22925@chat.hipchat.com/bot',
:nick => 'Zombot M.',
:room => '6075_engineering@conf.hipchat.com',
# :password => '...',
# :debug => Logger.new(STDOUT),
}
Bot.new(settings).connect.run
# default.gems generated gem export file. Note that any env variable settings will be missing. Append these after using a ';' field separator
columnize -v0.3.2
eventmachine -v0.12.10
facets -v2.9.1
json -v1.5.1
linecache -v0.43
nokogiri -v1.4.4
ruby-debug -v0.10.4
ruby-debug-base -v0.10.4
xmpp4r -v0.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment