Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --bot.rb--
- require 'socket' # Required to connect to server
- require 'timeout' # Required for status queue checking
- require 'mysql'
- require File.dirname(__FILE__) + '/Plugin'
- # Default config Variables
- $db = Mysql.new("localhost", "root")
- $db.select_db("bot")
- config = $db.query( "select * from config" )
- config =config.fetch_hash
- $channels = $db.query( "select channel from channels where serverid ='#{config['id']}'" )
- class Bot
- # Instance vars that may be read/written externally.
- attr_writer :sock
- attr_reader :sock
- # Constructor
- def initialize(config)
- # General config variables
- @server = config["server"]
- @port = config["port"]
- $nick = config["nick"]
- @altnick = config["altnick"]
- @realname = config["realname"]
- $admin = config["admin"]
- $owner = $admin;
- $admin_pass = config["admin_pass"]
- # True servername (declare to supress initialization warnings).
- @servername = nil
- # Info hash (for tracking user info).
- @info = Hash.new()
- # Buffer hash (declare 'all' key to supress initialization warnings).
- $buffer = { 'all' => nil }
- end
- # Initialize the socket.
- def initSocket
- puts "Connecting to #{@server} on port #{@port}"
- @sock = TCPSocket.new(@server, @port)
- end
- # Send a PRIVMSG.
- def msg(channel, msg)
- if msg =~ /(.+)?(\[.+\])(.+)?/i
- msg = "#{$1}#{$2}#{$3}"
- end
- self.cmd("PRIVMSG #{channel} :#{msg}");
- end
- def msgbox(type, msg)
- max = 0
- text = ""
- msg.each_line do |line|
- line = line.strip
- if line.length > max
- max = line.length + 2
- end
- end
- msg.each_line do |line|
- line = line.strip
- len = max - 2 - line.length
- text = "#{text}| #{line}"
- count = 0
- while count != len
- text = "#{text} "
- count = count + 1
- end
- text = "#{text} |\n"
- end
- count = 0
- line=""
- while count != max
- line = "#{line}-"
- count = count + 1
- end
- count = 0
- remove = line.length - type.length - 2
- limit = remove / 2
- while count != limit
- firstline = "#{firstline}-"
- count = count + 1
- end
- puts "\n+#{firstline}[#{type.upcase}]#{firstline}+\n#{text}+#{line}+"
- if type.upcase == "FATAL ERROR"
- exit
- end
- end
- # Send a raw command.
- def cmd(command)
- # Optional, document (log) sent data.
- self.doc(command);
- # Send raw command.
- @sock.puts(command);
- end
- # Log received data.
- def log(buf)
- # Print to screen.
- puts '>> ' + buf
- # Hack to determine own hostname.
- if buf =~ /:#{$nick}!(.+)@(\S+) (.+)/
- @hostname = $2
- end
- # Optional log to file or db.
- end
- # Log sent data (document).
- def doc(buf)
- # Print to screen.
- puts '<< ' + buf
- # Optional log to file or db.
- end
- def isOperator(nick, channel)
- if @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\~" or
- @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\@" or
- @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\&"
- return true
- end
- return false
- end
- # Flush the buffer, without destroying array structure
- def flush
- # For each key in the hash, set to nil.
- $buffer.each_key {|key| $buffer[key] = nil}
- end
- # Parse the buffer, and fetch tokens.
- def parse_buffer(buf)
- $buffer['all'] = buf;
- # If it is a standard line (MODE, PRIVMSG, JOIN, etc..)
- if buf.chomp =~ /:(.+)!(.+)@(\S+) (.+)/
- $buffer['username'] = $1
- $buffer['ident'] = $2
- $buffer['hostname'] = $3
- buffet = $4 # buffet === buffer snippet
- case buffet
- when /JOIN :(.+)/i
- $buffer['command'] = "JOIN"
- $buffer['channel'] = $1
- # Get info for @info hash
- # A bit hackish.. wish not to request on every JOIN -- could be a drain / lag
- self.cmd("WHO #{$buffer['username']}")
- # Auto voice users.
- unless $buffer['username'].include? $nick
- self.cmd("MODE #{$buffer['channel']} +v #{$buffer['username']}")
- end
- when /^PART (\S+) :?(.*)/i
- $buffer['command'] = "PART"
- $buffer['channel'] = $1
- $buffer['argument'] = $2
- # Remove user from status hash.
- @info[$1.upcase][$buffer['username'].upcase] = nil
- when /QUIT :?(.*)/i
- $buffer['command'] = "QUIT"
- $buffer['argument'] = $1
- # Remove user from status hash.
- @info.each_key {|x| @info[x.upcase][$buffer['username'].upcase] = nil}
- when /PRIVMSG (.+) :(.+)/i
- $buffer['command'] = "PRIVMSG"
- $buffer['argument'] = $2
- $buffer['channel'] = $1
- # When we get a true private message, the channel will be our nick,
- # so to reply, let's force channel to be the user who sent the message.
- $buffer['channel'] = $buffer['username'] if $buffer['channel'] =~ /^#{$nick}$/i
- when /NICK :(\S+)/i
- $buffer['command'] = "NICK"
- # Move users statuses to new username, remove old instances
- @info.each_key do |_ch|
- if @info[_ch.upcase][$buffer['username'].upcase] != nil
- @info[_ch.upcase][$1.upcase.strip] = Hash.new()
- @info[_ch.upcase][$1.upcase.strip] = @info[_ch.upcase][$buffer['username'].upcase]
- @info[_ch.upcase][$buffer['username'].upcase] = nil
- puts 'changed'
- end
- end
- $buffer['username'] = $1
- when /MODE (\S+) (.+)/i
- $buffer['command'] = "MODE"
- $buffer['channel'] = $1
- $buffer['argument'] = $2
- when /KICK (\S+) (\S+)(\s:){0,1}(.*)/i
- $buffer['command'] = "KICK"
- $buffer['channel'] = $1
- $buffer['victim'] = $2
- $buffer['argument'] = $4
- # Remove user from status hash.
- @info[$1.upcase][$2.upcase] = nil
- when /NOTICE (.+) :(.+)/i
- $buffer['command'] = "NOTICE"
- $buffer['channel'] = $1
- $buffer['argument'] = $2
- # Default
- else
- $buffer['command'] = "UNDEFINED"
- end
- end
- end
- # Process commands triggered by server messages.
- def process_directives
- # Connection established. Send information.
- if $buffer['all'] =~ /NOTICE AUTH :\*\*\* (checking ident|Found your hostname \(cached\))/i
- self.cmd("NICK #{$nick}")
- self.cmd("USER #{$nick} 0 * :#{@realname}")
- self.cmd("MODE #{$nick} +iw")
- end
- # Duplicate nick, use alternative.
- if $buffer['all'] =~ /433/
- self.cmd("NICK #{@altnick}")
- self.cmd("USER #{@altnick} 0 * :#{@realname}")
- end
- # Handshake.
- if $buffer['all'] =~ /001/
- @servername = $`.to_s.strip
- end
- # This is the correct way to join a channel.
- # Wait first for the MOTD to finish, then proceed.
- if $buffer['all'] =~ /#{@servername} (376|422) #{$nick}/
- chans = $channels.num_rows
- i=0
- while i != chans
- self.cmd("JOIN #{$channels.fetch_row}")
- i = i + 1
- end
- end
- # Reply to PING's with the same argument.
- if $buffer['all'] =~ /PING :(.+)/
- self.cmd("PONG :#{$1}")
- end
- if $buffer['all'] =~ /ERROR :Closing Link|Server Terminating/i
- exit 0
- end
- # NAMES
- # if $buffer['all'] =~ /353/
- #
- # end
- #
- if $buffer['all'] =~ /366 #{$nick} (\S+)/i
- self.cmd( "WHO #{$1}")
- end
- #
- if $buffer['all'] =~ /352 #{$nick} (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) :(\S+) (.*)/i
- @info[$1.upcase] = Hash.new() if @info[$1.upcase] == nil
- @info[$1.upcase][$5.upcase] = Hash.new()
- @info[$1.upcase][$5.upcase]['ident'] = $2
- @info[$1.upcase][$5.upcase]['host'] = $3
- @info[$1.upcase][$5.upcase]['leaf'] = $4
- @info[$1.upcase][$5.upcase]['mode'] = $6 #
- @info[$1.upcase][$5.upcase]['hops'] = $7
- @info[$1.upcase][$5.upcase]['extra'] = $8
- end
- end
- # Process commands triggerd by text, mode, kick, (etc).
- def process_commands
- case $buffer['command']
- when "PRIVMSG"
- if $buffer['argument'] =~ /^.auth (.*) (.*)/i
- user = $1
- pass = $2
- if user == $admin and pass == $admin_pass
- self.cmd("MODE #{@channel} +o #{$buffer['username']}")
- $owner = $buffer['username']
- self.msg($buffer['channel'], "Hello #{$buffer['username']}, You are now this bot's owner")
- puts $owner + " is now owner of this bot"
- end
- end
- if $buffer['argument'] =~ /^.die (.*)/i
- pass = $1
- if pass == $admin_pass
- self.cmd("QUIT :Shutdown Requested by #{$buffer['username']}")
- end
- end
- # Auto greet reply
- if $buffer['argument'] =~ /^(hi|yo|hey|howdy|hola|sup|salut|greetings|hello) #{$nick}/i
- self.msg($buffer['channel'], "yo #{$buffer['username']}.")
- end
- # whoami
- if $buffer['argument'] =~ /^.whoami/i
- self.msg($buffer['channel'], "username : #{$buffer['username']}")
- self.msg($buffer['channel'], "ident : #{$buffer['ident']}")
- self.msg($buffer['channel'], "hostname : #{$buffer['hostname']}")
- end
- # reverse
- if $buffer['argument'] =~ /^.reverse (.+)/i
- self.msg($buffer['channel'], $1.chomp.reverse)
- end
- # count
- if $buffer['argument'] =~ /^.count (.+)/i
- self.msg($buffer['channel'], "Length is #{$1.chomp.length}")
- end
- # action template
- if $buffer['argument'] =~ /ACTION (.+)/i
- # self.msg($buffer['channel'], $buffer['argument'])
- end
- # raw execution
- if $buffer['argument'] =~ /^.exec (.+)/i
- if $buffer['username'].include? $owner
- self.cmd($1)
- else
- self.msg($buffer['channel'], "No No, me no exec your commands, go do '" + $1 + "' yourself k? cool thnx buhbye")
- self.msg($admin, $buffer['channel'] + " just tried to execute " + $1)
- end
- end
- # fetch user status. "what is bob in #chan"
- if $buffer['argument'] =~ /^what is (.+) (in|on) (.+)/i
- _nick = $1.upcase.strip
- _chan = $3.upcase.strip
- if @info[_chan] != nil
- if @info[_chan][_nick] != nil
- if @info[_chan][_nick]['mode'].include? "\~"
- self.msg($buffer['channel'], "Owner")
- elsif @info[_chan][_nick]['mode'].include? "\&"
- self.msg($buffer['channel'], "Protected")
- elsif @info[_chan][_nick]['mode'].include? "\@"
- self.msg($buffer['channel'], "Operator")
- elsif @info[_chan][_nick]['mode'].include? "\%"
- self.msg($buffer['channel'], "Half-Op")
- elsif @info[_chan][_nick]['mode'].include? "\+"
- self.msg($buffer['channel'], "Voiced")
- else
- self.msg($buffer['channel'], "Normal User")
- end
- else
- self.msg($buffer['channel'], "I don't see them.")
- end
- end
- end
- if $buffer['argument'] =~ /^.fetch (\S+) (.+)/i
- if @info[$1.upcase] != nil
- if @info[$1.upcase][$2.upcase.strip] != nil
- self.msg($buffer['channel'], "Ident: #{@info[$1.upcase][$2.upcase.strip]['ident']}")
- self.msg($buffer['channel'], "Host : #{@info[$1.upcase][$2.upcase.strip]['host']}")
- self.msg($buffer['channel'], "Leaf : #{@info[$1.upcase][$2.upcase.strip]['leaf']}")
- self.msg($buffer['channel'], "Mode : #{@info[$1.upcase][$2.upcase.strip]['mode']}")
- self.msg($buffer['channel'], "Hops : #{@info[$1.upcase][$2.upcase.strip]['hops']}")
- self.msg($buffer['channel'], "Extra: #{@info[$1.upcase][$2.upcase.strip]['extra']}")
- end
- end
- end
- if $buffer['argument'] =~ /^.help/i
- self.msg($buffer['channel'], "[HELP] Available Commands are as follows:")
- self.msg($buffer['channel'], "[HELP] .help")
- self.msg($buffer['channel'], "[HELP] .whoami")
- self.msg($buffer['channel'], "[HELP] .auth USER PASSWORD")
- self.msg($buffer['channel'], "[HELP] .count STRING")
- self.msg($buffer['channel'], "[HELP] .reverse STRING")
- self.msg($buffer['channel'], "[HELP] .fetch CHANNEL USER")
- self.msg($buffer['channel'], "[HELP] what is USER in|on CHANNEL")
- self.msg($buffer['channel'], "[HELP] .plugin_list (INACTIVE | ACTIVE | ALL)")
- self.msg($buffer['channel'], "[HELP] .plugin_activate PLUGINAME")
- self.msg($buffer['channel'], "[HELP] .plugin_deactivate PLUGINAME")
- self.msg($buffer['channel'], "[HELP] .plugin_about PLUGINAME")
- $commands.each do |com|
- self.msg($buffer['channel'], "[HELP] #{com[1]}")
- end
- end
- if $buffer['argument'] =~ /^.plugin_(.*) (.+)/i
- mode = $1
- args = $2
- if mode == "list"
- if args.upcase == "INACTIVE"
- Plugin.list_deact
- elsif args.upcase == "ACTIVE"
- Plugin.list_act
- elsif args.upcase == "ALL"
- Plugin.list_act
- Plugin.list_deact
- else
- self.msg($buffer['channel'], "[ERROR] Syntax of this command is \".plugin_list active/inactive/all\"")
- end
- end
- if mode == "activate"
- if $buffer['username'].include? $owner
- Plugin.act(args)
- end
- end
- if mode == "deactivate"
- if $buffer['username'].include? $owner
- Plugin.deact(args)
- end
- end
- if mode == "about" || mode == "describe"
- Plugin.about_plugin(args)
- end
- end
- when "KICK"
- # If it is us, let's rejoin the channel.
- if $buffer['victim'] =~ /#{$nick}/i
- self.cmd("JOIN #{$buffer['channel']}")
- end
- when "MODE"
- # If mode is a ban..
- # TODO: fix for multiple bans " +bbb *!*@*.net *!*@*.org *!*@*.com "
- if $buffer['argument'] =~ /\+b (.+)!(.+)@(.+)/i
- _n = $1 and _i = $2 and _h = $3
- _victim = "#{$1}!#{$2}@#{$3}"
- # Create regular expressions from the ban mask
- _n.gsub!(/\*/, '(.*)')
- _i.gsub!(/^~/, '')
- _i.gsub!(/\*/, '(.*)')
- _h.gsub!(/\*/, '(.*)')
- # If it is us.. let's kick/ban them, and unban ourselves.
- if $nick =~ /#{_n}/i and $nick =~ /#{_i}/i and @hostname =~ /#{_h}/i
- self.cmd("KICK #{$buffer['channel']} #{$buffer['username']} :<3 #{$nick}")
- # Create a ban mask from the user doing the ban " *!*ident*@*.host "
- _ident = $1 if $buffer['ident'] =~ /~?(.+)/i
- _host = $1 if $buffer['hostname'] =~ /[a-zA-Z\-]+\.(.+)/i
- self.cmd("MODE #{$buffer['channel']} +b *!*#{_ident}@*.#{_host}")
- self.cmd("MODE #{$buffer['channel']} -b #{_victim}")
- end
- end
- # If a + usermode change..
- if $buffer['all'] =~ /MODE (.+) (\+|\-)(\w)+ (.+)/i
- self.cmd("WHO #{$1}")
- end
- # Default
- else
- # some nop statement?
- x = nil
- end
- # Clear buffer to avoid parsing multiple times.
- self.flush
- end
- end
- # Create the core object.
- @core = Bot.new(config)
- config = config.sort
- txt = ""
- for conf in config
- if conf[0] == "admin_pass"
- else
- txt = "#{txt}#{conf[0]} => #{conf[1]}\n"
- end
- end
- $core.msgbox("config", txt)
- Plugin.LoadAll
- puts ""
- # Initialize the socket.
- begin
- $core.initSocket
- rescue
- $core.msgbox("fatal error", "Cannot connect to server (No Route to host)")
- end
- while true
- begin
- Timeout::timeout(7) do |blah|
- # Read in text, line by line.
- while $buf = $core.sock.gets do
- # Log to screen and or file / db.
- $core.log($buf)
- # Parse buffer, fetch tokens.
- $core.parse_buffer($buf)
- Plugin.process($buf)
- # Process directives and commands.
- $core.process_directives
- $core.process_commands
- Plugin.run_freq
- end
- end
- rescue Timeout::Error
- Plugin.run_freq
- #exit
- end
- end
- --Plugin.rb--
- class Plugin
- @loaded_plugins = {}
- @enabled_plugins = {}
- $commands = Hash.new()
- class << self
- attr_reader :loaded_plugins
- attr_reader :enabled_plugins
- private :new
- end
- def self.define(name, &block)
- p = new
- p.instance_eval(&block)
- self.loaded_plugins[name] = p
- end
- def self.mod(name, enabled)
- self.enabled_plugins[name] = enabled
- end
- def self.LoadAll
- i=0
- a=0
- Dir[File.dirname(__FILE__) + "/plugins/*.rb"].each do |x|
- mods = $db.query( "select * from plugins" )
- mods.each do |y|
- if x.upcase.include? y[0]
- name = y[0]
- begin
- load x
- plugin = File.open(x).read
- plugin.each_line do |line|
- if line =~ /\/\^(\\\+|\\\.)(.+)\/i( \#)?(.+)?/i
- arg = $4
- $commands[a] = "#{$1}#{$2.gsub(/\?|\(|\.|\\S|\+|\\|\)|\*/i, '')} #{arg}".gsub(/\\/i, '')
- a = a + 1
- end
- end
- if y[1].to_i == 1
- self.mod(y[0],1)
- puts "Loading #{name} as enabled\n"
- else
- self.mod(y[0],0)
- puts "Loading #{name} as disabled\n"
- end
- rescue
- puts "! #{name} contains errors and was not loaded !\n"
- end
- end
- end
- end
- end
- def self.act(mod)
- mod = mod.upcase
- self.enabled_plugins.each do |plugin|
- if plugin[0].include? mod
- if plugin[1] == 1
- $core.msg($buffer['channel'], "[ACTIVATE PLUGIN] #{mod.capitalize} already enabled")
- else
- $core.msg($buffer['channel'], "[ACTIVATE PLUGIN] #{mod.capitalize} is now enabled")
- self.mod(mod,1)
- modded = $db.query( "UPDATE plugins SET enabled = '1' WHERE mod_name = '#{mod}'" )
- end
- end
- end
- end
- def self.list_act
- $core.msg($buffer['channel'], "[ACTIVE PLUGINS]")
- self.enabled_plugins.each do |plugin|
- if plugin[1] == 1
- $core.msg($buffer['channel'], "#{plugin[0].capitalize}")
- end
- end
- end
- def self.list_deact
- $core.msg($buffer['channel'], "[INACTIVE PLUGINS]")
- self.enabled_plugins.each do |plugin|
- if plugin[1] == 0
- $core.msg($buffer['channel'], "#{plugin[0].capitalize}")
- end
- end
- end
- def self.deact(mod)
- mod = mod.upcase
- self.enabled_plugins.each do |plugin|
- if plugin[0].include? mod
- if plugin[1] == 1
- $core.msg($buffer['channel'], "[DEACTIVATE PLUGIN] #{mod.capitalize} is now disabled")
- self.mod(mod,0)
- modded = $db.query( "UPDATE plugins SET enabled = '0' WHERE mod_name = '#{mod}'" )
- else
- $core.msg($buffer['channel'], "[DEACTIVATE PLUGIN] #{mod.capitalize} already disabled")
- end
- end
- end
- end
- def self.about_plugin(mod)
- mod = mod.upcase.gsub(/ /i, '_')
- puts mod
- self.loaded_plugins.each do |plugin|
- if plugin[0] == mod
- if self.enabled_plugins[plugin[0]].to_i === 1
- plugin[1].about
- end
- end
- end
- end
- def self.process(buf)
- self.loaded_plugins.each do |plugin|
- if self.enabled_plugins[plugin[0]].to_i === 1
- # If it is a standard line (MODE, PRIVMSG, JOIN, etc..)
- if buf.chomp =~ /:(.+)!(.+)@(\S+) (.+)/
- plugin[1].procedure()
- end
- end
- end
- end
- def self.run_freq()
- self.loaded_plugins.each do |plugin|
- if self.enabled_plugins[plugin[0]].to_i === 1
- plugin[1].freq()
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment