Respond to 'help?*'
[six.git] / cybot.rb
blob13c25139e5a156a1377a3d4704afd90447479231
3 # CyBot.
5 # Set the version
6 $version = "0.2"
9 # Some modules we need.
10 puts "CyBot v#{$version} starting up..."
11 require 'thread'
12 require 'pluginbase'
13 require 'configspace/configspace'
16 # =====================
17 # = Plugin management =
18 # =====================
20 # Root plugins. We always need these.
21 RootPlugins = ['plugin', 'irc', 'user', 'test']
23 # Provide a namespace for plugins.
24 module Plugins
25 end
27 # Tries to load the named plugin.
28 # Should reload if already loaded.
29 # Names are lower-case or properly cased?.
30 # RAISES: LoadError, PluginError.
31 def load_plugin(name)
33   # FIXME: Have a few places to look.
35   begin
37     # Try to load.
38     n = name.downcase
39     Plugins.module_eval { load("lib/#{n}.rb") }
41     # Find the class.
42     if (klass = self.class.const_get(n.capitalize))
44       # Initialize it.
45       ins = klass.shared_instance
46       $plugins[ins.name] = ins
47       puts "Core plugin '#{ins.name.capitalize}' loaded."
49     else
50       puts "Error loading core plugin '#{n.capitalize}':"
51       puts "Couldn't locate plugin class."
52     end
54   rescue Exception => e
55     puts "Error loading core plugin '#{n.capitalize}':"
56     puts e.message
57     puts e.backtrace.join("\n")
58   end
60 end
62 # Some global maps.
63 $commands  = {}
64 $hooks     = {}
65 $plugins   = {}
67 # Load global configuration.
68 $config = ConfigSpace.new(ARGV[0]) or return 1
69 $config.prefix = <<EOS
70 # CyBot 0.2 main configuration file. Be careful when editing this file manually,
71 # as it is automatically saved run-time. On-line edit is recomended.
73 #########    --------------------------------------------------    #########
74 #########    REMEMBER TO SHUT DOWN THE BOT BEFORE YOU EDIT THIS    #########
75 #########    --------------------------------------------------    #########
76 #########    This is because the bot writes the whole of this      #########
77 #########    file out when it is closed down.                      #########
78 #########    --------------------------------------------------    #########
79 EOS
81 # Save everything.
82 @save_all_mutex = Mutex.new
83 def save_all(quiet = false)
84   @save_all_mutex.synchronize do
85     puts 'Saving plugin data...' unless quiet
86     $plugins.each do |n,p|
87       begin
88         print "  #{n}... " unless quiet
89         p.save
90         puts "Ok" unless quiet
91       rescue Exception => e
92         puts "Failed with error: #{e.message}" unless quiet
93       end
94     end
95     puts 'Saving global configuration...' unless quiet
96     $config.save
97   end
98 end
100 # Handler on ctrl-c at this point.
101 Signal.trap 'INT' do
102   Signal.trap 'INT', 'DEFAULT'
103   puts 'Shutdown in progress. Press ctrl-c again to abort immediately.'
104   puts 'Asking IRC handlers to quit...'
105   IRC::Server.quit('Ctrl-c pressed on console...')
108 # Load root plugins.
109 $: << File.expand_path('support')
110 RootPlugins.each { |name| load_plugin(name) }
111 $plugins.each_value do |plugin|
112   plugin.on_startup if plugin.respond_to? :on_startup
115 # Set up timer to save data on regular intervals.
116 Thread.new do
117   loop do
118     sleep(60*60)
119     save_all(true)
120   end
123 # Done. Wait for quit.
124 puts 'Startup complete!'
125 IRC::Server.wait
127 # Tell all plugins to save, and then save the main config.
128 puts 'Preparing to exit...'
129 save_all
130 puts 'All done, see you next time.'