Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Ruby] IRC Bot
#1
Code:
#!ruby
#main.rb

require 'socket'
require 'nandlib'

load 'irc.rb'
$irc = IRC.new 'irc.lolipower.org', 6667, "KawaiiBot"
$irc.owner = 'nand'

load 'events.rb'

fork do
    loop do
        catch :disconnected do
            if $irc.connect
                $irc.handle
            else
                puts "Failed to connect.."
            end
        end
        puts "Disconnected!"
        print "Reconnecting in "
        (5).downto(1) {|n| puts n; sleep 1 }
    end
end

while gets
    load 'irc.rb'
    load 'events.rb'
    puts "Reloaded."
end

#!ruby
#irc.rb

class CatchCall
    attr_accessor :catch, :block
    
    def initialize(catch, block)
        @catch = catch
        @block = block
    end
end

class IRC
    attr_reader :name
    attr :server, :port, :sock
    attr_accessor :owner
    
    def initialize(host, port, name)
        @host = host
        @port = port
        @name = name
        @buffer = ""
        @events = []
        @catchcalls = []
    end
    
    def connect
        begin
            puts "Connecting to #{@host}:#{@port}..."
            @sock = TCPSocket.open(@host, @port)
            puts "Connected."
            
            # Time to register
            sendraw "USER #{((@name + ' ') * 3).chop} :#{@name}"
            sendraw "NICK #{@name}"
            return true
        rescue Exception => exc
            puts "Failed to connect!"
            return false
        end
    end
    
    def send(t, m)
        sendraw "PRIVMSG #{t} :#{m}"
    end
    
    def join(c)
        sendraw "JOIN #{c}"
    end
    
    def part(c)
        sendraw "PART #{c}"
    end
    
    def notice(t, m)
        sendraw "NOTICE #{t} :#{m}"
    end
    
    def sendraw(s)
        raise "Message too long" if s.length > 510
        s << "\r\n" unless s =~ /\r\n$/
        @sock.write s
    end
    
    def recvraw
        str = @sock.gets
        throw :disconnected if str.nil?
        unless @buffer.empty?
            str = @buffer + str
            @buffer = ''
        end
        if str =~ /\r?\n([^\r\n]+)$/
            @buffer = $1
            str = $`
        end
        if block_given? then str.split(/\r?\n/).each {|l| yield l}
        else return str.split(/\r?\n/) end
    end
    
    def handle
        begin
            while recvraw {|s| process s }; end
        
        rescue Exception => exc
            puts "Exception: " << exc.to_s
            print exc.backtrace.join("\n"), "\n"
            notice @owner, "Exception: " << exc.to_s if @owner
            notice @owner, "Location: " << exc.backtrace[0].to_s if @owner
            retry
        end
    end
    
    def process(str)
        raise "malformed packet: \n" << str unless str =~ /^(:[^ ]+ )?([^ ]+)( .*)?$/
        prefix, command, postfix = $1, $2, $3
        prefix.chip!.chop! if prefix
        command.downcase!
        postfix.chip! if postfix
        args = postfix ? postfix.split(/ /) : []
        
        if postfix =~ /:/
            found = nil
            tot = args.deep_dup.inject('') {|n, val|
                (found = val.dup) && val.chip! if !found && val[0] == ':'
                found ? n << (n.empty? ? '' : ' ') << val : n}
            args[args.index(found)..args.length] = tot if found
        end
        
        @events.each do |cc|
            if cc.catch === command
                if Regexp === cc.catch
                    reg = $~.dup
                    cc.block.call(prefix, command, args, reg)
                else
                    cc.block.call(prefix, command, args)
                end
            end
        end
        
        if command == "privmsg" || command == "notice"
            target = args[0]
            message = args[1]
            sender = prefix
            
            target = nick(sender) if isme? target
            
            @catchcalls.each do |cc|
                if cc.catch === message
                    if Regexp === cc.catch
                        reg = $~.dup
                        cc.block.call(sender, target, message, reg)
                    else
                        cc.block.call(sender, target, message)
                    end
                end
            end
        end
    end
    
    def hook(*match, &block)
        match.each do |m|
            m = m.to_s if Integer === m || Symbol === m
            m.downcase! if String === m
            @events << CatchCall.new(m, block)
        end
    end
    
    def catch(*match, &block)
        match.each do |m|
            if String === m || Regexp === m then
                @catchcalls << CatchCall.new(m, block)
            else
                raise ArgumentError, "Keys must be of type String or Regexp", caller
            end
        end
    end
    
    def unhook_all
        @events = []
    end
    
    def uncatch_all
        @catchcalls = []
    end
    
    def myname
        @name
    end
    
    def isme?(s)
        @name == nick(s)
    end
end

def nick(host)
    $1 if host =~/([^!]+)(!.*)?/
end

#!ruby
#events.rb

$irc.unhook_all
$irc.uncatch_all

# Reloading method
$irc.catch(/^!reload$/) do |s, t, m, r|
    if s =~ /.?nand!.*@nand.*/
        puts "Reloading..."
        load 'irc.rb'
        load 'events.rb'
        $irc.notice nick(s), "Reloaded."
    end
end

$irc.hook(:ping) {|s, c, a|
    $irc.sendraw (a.empty? ? "PONG" : "PONG #{a[0]}")
}

$irc.hook(376) {|s, c, a|
    $irc.join "#Aaron"
    $irc.join "#r0b0tz"
}

$irc.hook(:kick) {|s, c, a|
    $irc.join a[0] if $irc.isme? a[1]
}

$irc.catch(/^!ping$/, /^Ping!$/) {|s, t, m, r|
    $irc.send t, "Pong!"
}

$irc.catch(/^!eval (.*)/) {|s, t, m, r|
    if s =~ /nand!.*@nand.*/
        begin
            $irc.send t, "=> " << eval(r[1]).inspect
        rescue Exception => exc
            $irc.send t, "Exception: " << exc.to_s
        end
    end
}

$irc.catch(/^!join (#[^ ]+)$/) {|s, t, m, r|
    $irc.join r[1]
}

$irc.catch(/^!part( #[^ ]+)?$/) {|s, t, m, r|
    $irc.part (r[1].chip ? r[1] : t) unless t == s
}

$irc.catch(/^\001VERSION\001$/i) {|s, t, m, r|
    $irc.notice t, "\1VERSION nandbot v0.whatever (Ruby ver #{RUBY_VERSION})\1"
}

$irc.catch(/^\001PING ([^ ]+)\001$/i) {|s, t, m, r|
    $irc.notice t, "\1PING #{r[1]}\1"
}

$irc.hook(:privmsg) {|s, c, a|
    print a[0], ' <', nick(s), '> ', a[1], "\n"
}

Yep.

another irc bot.

^
Reply
#2
Thanks for great stuff , you're da best BlaiR Big Grin
[Image: 15nrtb7.jpg]
Reply
#3
(08-16-2010, 03:14 PM)Sιℓνєя Wrote: Thanks for great stuff , you're da best BlaiR Big Grin

I dont expect to see any malwares in ruby

anytime soon Big Grin
Reply
#4
(10-04-2010, 05:10 PM)ϟ ⓇⓞⓎⓐⓁ ⓇⓐⓘⓃ ϟ Wrote: Is this even a good irc bot?

yeah i think it is (:
[Image: 15nrtb7.jpg]
Reply
#5
Wow, nice job, even though there are a million IRC bots, still great quality code.
Reply
#6
Thanks for the awesome and great stuff. Much appreciated!
Reply
#7
Thanks for sharing this Smile
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Getting Started With Ruby eax 7 4,690 12-13-2012, 10:03 AM
Last Post: L-Carnitine
  [Tut] How to install Ruby on Mac, Windows and Linux Jordan L. 13 7,569 12-13-2012, 07:49 AM
Last Post: L-Carnitine
  Ruby eBook sockatobi 7 2,731 12-13-2012, 07:48 AM
Last Post: L-Carnitine
  what is ruby on rails DaUB3R 3 1,822 11-01-2012, 04:20 AM
Last Post: johnnymward
  Should I Start Ruby? BreShiE 13 4,931 11-13-2011, 04:14 PM
Last Post: Speedy

Forum Jump:


Users browsing this thread: 1 Guest(s)