simple IRC bot written in Ruby
1 2 #!/usr/local/bin/ruby 3 4 require "socket" 5 6 # Don't allow use of "tainted" data by potentially dangerous operations 7 $SAFE=1 8 9 # The irc class, which talks to the server and holds the main event loop 10 class IRC 11 def initialize(server, port, nick, channel) 12 @server = server 13 @port = port 14 @nick = nick 15 @channel = channel 16 end 17 def send(s) 18 # Send a message to the irc server and print it to the screen 19 puts "--> #{s}" 20 @irc.send "#{s}\n", 0 21 end 22 def connect() 23 # Connect to the IRC server 24 @irc = TCPSocket.open(@server, @port) 25 send "USER blah blah blah :blah blah" 26 send "NICK #{@nick}" 27 send "JOIN #{@channel}" 28 end 29 def evaluate(s) 30 # Make sure we have a valid expression (for security reasons), and 31 # evaluate it if we do, otherwise return an error message 32 if s =~ /^[-+*\/\d\s\eE.()]*$/ then 33 begin 34 s.untaint 35 return eval(s).to_s 36 rescue Exception => detail 37 puts detail.message() 38 end 39 end 40 return "Error" 41 end 42 def handle_server_input(s) 43 # This isn't at all efficient, but it shows what we can do with Ruby 44 # (Dave Thomas calls this construct "a multiway if on steroids") 45 case s.strip 46 when /^PING :(.+)$/i 47 puts "[ Server ping ]" 48 send "PONG :#{$1}" 49 when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]PING (.+)[\001]$/i 50 puts "[ CTCP PING from #{$1}!#{$2}@#{$3} ]" 51 send "NOTICE #{$1} :\001PING #{$4}\001" 52 when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]VERSION[\001]$/i 53 puts "[ CTCP VERSION from #{$1}!#{$2}@#{$3} ]" 54 send "NOTICE #{$1} :\001VERSION Ruby-irc v0.042\001" 55 when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s(.+)\s:EVAL (.+)$/i 56 puts "[ EVAL #{$5} from #{$1}!#{$2}@#{$3} ]" 57 send "PRIVMSG #{(($4==@nick)?$1:$4)} :#{evaluate($5)}" 58 else 59 puts s 60 end 61 end 62 def main_loop() 63 # Just keep on truckin' until we disconnect 64 while true 65 ready = select([@irc, $stdin], nil, nil, nil) 66 next if !ready 67 for s in ready[0] 68 if s == $stdin then 69 return if $stdin.eof 70 s = $stdin.gets 71 send s 72 elsif s == @irc then 73 return if @irc.eof 74 s = @irc.gets 75 handle_server_input(s) 76 end 77 end 78 end 79 end 80 end 81 82 # The main program 83 # If we get an exception, then print it out and keep going (we do NOT want 84 # to disconnect unexpectedly!) 85 irc = IRC.new('efnet.skynet.be', 6667, 'Alt-255', '#cout') 86 irc.connect() 87 begin 88 irc.main_loop() 89 rescue Interrupt 90 rescue Exception => detail 91 puts detail.message() 92 print detail.backtrace.join("\n") 93 retry 94 end
Source: rubystuff.org