#!/usr/bin/ruby # ruby irc bot # (c) 2008-2009 Y. Guillot # Published under the terms of WtfPLv2 require 'socket' require 'time' begin ; require 'openssl' ; rescue LoadError ; end class IrcBot attr_accessor :host, :port, :nick, :uhost, :chan attr_accessor :conf attr_accessor :udp def initialize(conf) @conf = conf @host = @conf[:ircd] @port = @conf[:ircd_port] || 6667 @chan = @conf[:chan] @nick = @conf[:nick] @uhost= @conf[:uhost] || 'bot bot bot :da bot' @udp = UDPSocket.open @udp.bind(@conf[:udp_host], @conf[:udp_port]) puts "listening on UDP #{@conf[:udp_host]}:#{@conf[:udp_port]}" end def run connect loop { run_loop } end def connect puts "connecting to irc..." @sock = TCPSocket.open @host, @port if @conf[:ircd_ssl] @sock = OpenSSL::SSL::SSLSocket.new(@sock, OpenSSL::SSL::SSLContext.new) @sock.sync_close = true @sock.connect end sendline "user #@uhost" sendline "nick #@nick" loop do r, w, e = IO.select([@sock]) l = @sock.gets.chomp #puts l case l.split[1] when '376' # connected puts "connected" break when '433' # nick already in use on ircd @nick += rand(1000).to_s sendline "nick #@nick" end end sendline "join #@chan #{@conf[:chan_pass]}" end def run_loop r, w, e = IO.select [@sock, @udp], nil, nil, 0.5 if not r # select() timeout elsif r.include?(@udp) handle_udp elsif r.include?(@sock) handle_sock @sock.gets.chomp end rescue pm "#{$!.class} #{$!.message} #{$!.backtrace.first}", @conf[:admin_nick] sleep 2 end # send to the ircd def sendline(l) @sock.write l.chomp << "\r\n" end # send a private message def pm(l, dst=@chan) l.to_s.gsub("\r", '').each { |l| l = l.chomp l = ' ' if l == '' sendline "PRIVMSG #{dst} :#{l}" } end def handle_sock l case l when /^:(\S*) PRIVMSG (\S*) :(.*)/i handle_privmsg $1, $2, $3 when /^ping (.*)/i sendline "pong #$1" end end # handle messages from the irc server to the bot def handle_privmsg(from, to, msg) case msg when /^!kw1 (.*)/i m = $1 # TODO send data back to ET server # rcon 'et.kornwaffe.de', "message from irc: #{m}" end end # handle message from the udp port def handle_udp msg, from = @udp.recvfrom(1024) fromip = from[3] # the ip that sent us the udp packet # directly forward any data to the irc channel pm(msg) end end conf = { :ircd => 'ipv6.chat.freenode.net', #:ircd_port => 6667, #:ircd_ssl => true, :chan => '#kornwaffe', #:chan_pass => 's3cr3t', :nick => 'bot', :admin_nick => 'bob_ansoethu', # nick of admin, notified of errors :udp_host => 'localhost', :udp_port => 2828, } IrcBot.new(conf).run