require 'thread'
require 'etc'
+require 'date'
require 'fileutils'
-require 'logger'
-
-$debug = false unless $debug
-$daemonize = false unless $daemonize
-
-$dateformat = "%Y/%m/%d %H:%M:%S"
-$logger = Logger.new($stderr)
-$logger.datetime_format = $dateformat
-$logger.level = $cl_loglevel if defined? $cl_loglevel
-$logger.level = 0 if $debug
-
-$log_queue = Queue.new
-$log_thread = nil
require 'pp'
class ServerError < RuntimeError
end
-def rawlog(level, message=nil, who_pos=1)
- call_stack = caller
- if call_stack.length > who_pos
- who = call_stack[who_pos].sub(%r{(?:.+)/([^/]+):(\d+)(:in .*)?}) { "#{$1}:#{$2}#{$3}" }
- else
- who = "(unknown)"
- end
- # Output each line. To distinguish between separate messages and multi-line
- # messages originating at the same time, we blank #{who} after the first message
- # is output.
- # Also, we output strings as-is but for other objects we use pretty_inspect
- case message
- when String
- str = message
- else
- str = message.pretty_inspect rescue '?'
- end
- qmsg = Array.new
- str.each_line { |l|
- qmsg.push [level, l.chomp, who]
- who = ' ' * who.size
- }
- if level == Logger::Severity::ERROR or level == Logger::Severity::FATAL and not $daemonize
- $stderr.puts str
- end
- $log_queue.push qmsg
-end
-
-def halt_logger
- if $log_thread && $log_thread.alive?
- $log_queue << nil
- $log_thread.join
- $log_thread = nil
- end
-end
-
-END { halt_logger }
-
-def restart_logger(newlogger = false)
- halt_logger
-
- $logger = newlogger if newlogger
-
- $log_thread = Thread.new do
- ls = nil
- while ls = $log_queue.pop
- ls.each { |l| $logger.add(*l) }
- end
- end
-end
-
-restart_logger
-
-def log_session_start
- $logger << "\n\n=== #{botclass} session started on #{Time.now.strftime($dateformat)} ===\n\n"
- restart_logger
-end
-
-def log_session_end
- $logger << "\n\n=== #{botclass} session ended on #{Time.now.strftime($dateformat)} ===\n\n"
- $log_queue << nil
-end
-
-def debug(message=nil, who_pos=1)
- rawlog(Logger::Severity::DEBUG, message, who_pos)
-end
-
-def log(message=nil, who_pos=1)
- rawlog(Logger::Severity::INFO, message, who_pos)
-end
-
-def warning(message=nil, who_pos=1)
- rawlog(Logger::Severity::WARN, message, who_pos)
-end
-
-def error(message=nil, who_pos=1)
- rawlog(Logger::Severity::ERROR, message, who_pos)
-end
-
-def fatal(message=nil, who_pos=1)
- rawlog(Logger::Severity::FATAL, message, who_pos)
-end
-
-debug "debug test"
-log "log test"
-warning "warning test"
-error "error test"
-fatal "fatal test"
-
# The following global is used for the improved signal handling.
$interrupted = 0
# these first
+require 'rbot/logger'
require 'rbot/rbotconfig'
-begin
- require 'rubygems'
-rescue LoadError
- log "rubygems unavailable"
-end
-
require 'rbot/load-gettext'
require 'rbot/config'
-
require 'rbot/irc'
require 'rbot/rfc2812'
require 'rbot/ircsocket'
require 'rbot/plugins'
require 'rbot/message'
require 'rbot/language'
+require 'rbot/httputil'
module Irc
# Main bot class, which manages the various components, receives messages,
# handles them or passes them to plugins, and contains core functionality.
class Bot
- COPYRIGHT_NOTICE = "(c) Tom Gilbert and the rbot development team"
- SOURCE_URL = "http://ruby-rbot.org"
+ COPYRIGHT_NOTICE = "(c) Giuseppe Bilotta and the rbot development team"
+ SOURCE_URL = "https://ruby-rbot.org"
# the bot's Auth data
attr_reader :auth
# loads and opens new registry databases, used by the plugins
attr_accessor :registry_factory
+ # web service
+ attr_accessor :webservice
+
# server we are connected to
# TODO multiserver
def server
:default => 1, :requires_restart => false,
:validate => Proc.new { |v| (0..5).include?(v) },
:on_change => Proc.new { |bot, v|
- $logger.level = v
+ LoggerManager.instance.set_level(v)
},
:desc => "The minimum logging level (0=DEBUG,1=INFO,2=WARN,3=ERROR,4=FATAL) for console messages")
Config.register Config::IntegerValue.new('log.keep',
},
:desc => "Percentage of IRC penalty to consider when sending messages to prevent being disconnected for excess flood. Set to 0 to disable penalty control.")
Config.register Config::StringValue.new('core.db',
- :default => default_db,
+ :default => default_db, :store_default => true,
:wizard => true,
:validate => Proc.new { |v| Registry::formats.include? v },
:requires_restart => true,
@config.bot_associate(self)
rescue Exception => e
fatal e
- log_session_end
exit 2
end
end
@registry_factory = Registry.new @config['core.db']
+ @registry_factory.migrate_registry_folder(path)
@logfile = @config['log.file']
- if @logfile.class!=String || @logfile.empty?
+ if @logfile.class != String || @logfile.empty?
logfname = File.basename(botclass).gsub(/^\.+/,'')
logfname << ".log"
@logfile = File.join(botclass, logfname)
# File.umask 0000 # Ensure sensible umask. Adjust as needed.
end
- logger = Logger.new(@logfile,
- @config['log.keep'],
- @config['log.max_size']*1024*1024)
- logger.datetime_format= $dateformat
- logger.level = @config['log.level']
- logger.level = $cl_loglevel if defined? $cl_loglevel
- logger.level = 0 if $debug
-
- restart_logger(logger)
-
- log_session_start
+ # setup logger based on bot configuration
+ LoggerManager.instance.set_level(@config['log.level'])
+ LoggerManager.instance.set_logfile(@logfile, @config['log.keep'], @config['log.max_size'])
if $daemonize
log "Redirecting standard input/output/error"
@plugins = nil
@lang = Language.new(self, @config['core.language'])
+ @httputil = Utils::HttpUtil.new(self)
begin
@auth = Auth::manager
# @auth.load("#{botclass}/botusers.yaml")
rescue Exception => e
fatal e
- log_session_end
exit 2
end
@auth.everyone.set_default_permission("*", true)
# to inform us that our nick has been changed.
if data[:target] == '*'
debug "setting my connection nick to #{new}"
- nick = new
+ @client.user.nick = new
end
@plugins.delegate "nicktaken", data[:nick]
}
debug "interrupted #{$interrupted} times"
if $interrupted >= 3
debug "drastic!"
- log_session_end
exit 2
end
end
connect
rescue SystemExit
- log_session_end
exit 0
rescue Exception => e
error e
# exceptions that ARENT SocketError's. How am I supposed to handle
# that?
rescue SystemExit
- log_session_end
exit 0
rescue Errno::ETIMEDOUT, Errno::ECONNABORTED, TimeoutError, SocketError => e
error "network exception: #{e.pretty_inspect}"
quit_msg = e.to_s
rescue => e
fatal "unexpected exception: #{e.pretty_inspect}"
- log_session_end
exit 2
end
end
debug "\tignoring cleanup error: #{$!}"
end
end
+ @httputil.cleanup
# debug "\tstopping timers ..."
# @timer.stop
# debug "Closing registries"
# now we re-exec
# Note, this fails on Windows
debug "going to exec #{$0} #{@argv.inspect} from #{@run_dir}"
- log_session_end
Dir.chdir(@run_dir)
exec($0, *@argv)
rescue Errno::ENOENT
- log_session_end
exec("ruby", *(@argv.unshift $0))
rescue Exception => e
$interrupted += 1
end
end
- # call the save method for all of the botmodules
- def save
+ # call the save method for all or the specified botmodule
+ #
+ # :botmodule ::
+ # optional botmodule to save
+ def save(botmodule=nil)
@save_mutex.synchronize do
- @plugins.save
+ @plugins.save(botmodule)
end
end
- # call the rescan method for all of the botmodules
- def rescan
+ # call the rescan method for all or just the specified botmodule
+ #
+ # :botmodule ::
+ # instance of the botmodule to rescan
+ def rescan(botmodule=nil)
debug "\tstopping timer..."
@timer.stop
@save_mutex.synchronize do
- @lang.rescan
- @plugins.rescan
+ # @lang.rescan
+ @plugins.rescan(botmodule)
end
@timer.start
end