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