X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fconfig.rb;h=ab16c442f0986f746e9d1b176ecc3a8c75b8b8dc;hb=05917e75de2cbd14071ef335f4c3129a33f30cf6;hp=e4237e81439059570cb9c6b98a54250610ae519a;hpb=dd0b318cfd3df017b1ec4e44afc2f4e412fd2033;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/config.rb b/lib/rbot/config.rb index e4237e81..ab16c442 100644 --- a/lib/rbot/config.rb +++ b/lib/rbot/config.rb @@ -3,6 +3,14 @@ module Irc require 'yaml' require 'rbot/messagemapper' + unless YAML.respond_to?(:load_file) + def YAML.load_file( filepath ) + File.open( filepath ) do |f| + YAML::load( f ) + end + end + end + class BotConfigValue # allow the definition order to be preserved so that sorting by # definition order is possible. The BotConfigWizard does this to allow @@ -15,12 +23,15 @@ module Irc attr_reader :requires_restart attr_reader :order def initialize(key, params) - unless key =~ /^.+\..+$/ + # Keys must be in the form 'module.name'. + # They will be internally passed around as symbols, + # but we accept them both in string and symbol form. + unless key.to_s =~ /^.+\..+$/ raise ArgumentError,"key must be of the form 'module.name'" end @order = @@order @@order += 1 - @key = key + @key = key.intern if params.has_key? :default @default = params[:default] else @@ -114,6 +125,15 @@ module Irc def to_s get.join(", ") end + def add(val) + curval = self.get + set(curval + [val]) unless curval.include?(val) + end + def rm(val) + curval = self.get + raise ArgumentError, "value #{val} not present" unless curval.include?(val) + set(curval - [val]) + end end class BotConfigEnumValue < BotConfigValue def initialize(key, params) @@ -128,13 +148,13 @@ module Irc end end def parse(string) - unless @values.include?(string) - raise ArgumentError, "invalid value #{string}, allowed values are: " + @values.join(", ") + unless values.include?(string) + raise ArgumentError, "invalid value #{string}, allowed values are: " + values.join(", ") end string end def desc - "#{@desc} [valid values are: " + @values.join(", ") + "]" + "#{@desc} [valid values are: " + values.join(", ") + "]" end end @@ -167,8 +187,17 @@ module Irc # supported via [] def [](key) return @@items[key].value if @@items.has_key?(key) + return @@items[key.intern].value if @@items.has_key?(key.intern) # try to still support unregistered lookups - return @@config[key] if @@config.has_key?(key) + # but warn about them + if @@config.has_key?(key) + warning "Unregistered lookup #{key.inspect}" + return @@config[key] + end + if @@config.has_key?(key.intern) + warning "Unregistered lookup #{key.intern.inspect}" + return @@config[key.intern] + end return false end @@ -185,7 +214,7 @@ module Irc modules = [] if params[:module] @@items.each_key do |key| - mod, name = key.split('.') + mod, name = key.to_s.split('.') next unless mod == params[:module] modules.push key unless modules.include?(name) end @@ -196,7 +225,7 @@ module Irc end else @@items.each_key do |key| - name = key.split('.').first + name = key.to_s.split('.').first modules.push name unless modules.include?(name) end m.reply "modules: " + modules.join(", ") @@ -204,7 +233,7 @@ module Irc end def handle_get(m, params) - key = params[:key] + key = params[:key].to_s.intern unless @@items.has_key?(key) m.reply "no such config key #{key}" return @@ -214,7 +243,7 @@ module Irc end def handle_desc(m, params) - key = params[:key] + key = params[:key].to_s.intern unless @@items.has_key?(key) m.reply "no such config key #{key}" end @@ -223,17 +252,18 @@ module Irc end def handle_unset(m, params) - key = params[:key] + key = params[:key].to_s.intern unless @@items.has_key?(key) m.reply "no such config key #{key}" end @@items[key].unset handle_get(m, params) + m.reply "this config change will take effect on the next restart" if @@items[key].requires_restart end def handle_set(m, params) - key = params[:key] - value = params[:value].to_s + key = params[:key].to_s.intern + value = params[:value].join(" ") unless @@items.has_key?(key) m.reply "no such config key #{key}" return @@ -251,11 +281,53 @@ module Irc end end + def handle_add(m, params) + key = params[:key].to_s.intern + value = params[:value] + unless @@items.has_key?(key) + m.reply "no such config key #{key}" + return + end + unless @@items[key].class <= BotConfigArrayValue + m.reply "config key #{key} is not an array" + return + end + begin + @@items[key].add(value) + rescue ArgumentError => e + m.reply "failed to add #{value} to #{key}: #{e.message}" + return + end + handle_get(m,{:key => key}) + m.reply "this config change will take effect on the next restart" if @@items[key].requires_restart + end + + def handle_rm(m, params) + key = params[:key].to_s.intern + value = params[:value] + unless @@items.has_key?(key) + m.reply "no such config key #{key}" + return + end + unless @@items[key].class <= BotConfigArrayValue + m.reply "config key #{key} is not an array" + return + end + begin + @@items[key].rm(value) + rescue ArgumentError => e + m.reply "failed to remove #{value} from #{key}: #{e.message}" + return + end + handle_get(m,{:key => key}) + m.reply "this config change will take effect on the next restart" if @@items[key].requires_restart + end + def handle_help(m, params) topic = params[:topic] case topic when false - m.reply "config module - bot configuration. usage: list, desc, get, set, unset" + m.reply "config module - bot configuration. usage: list, desc, get, set, unset, add, rm" when "list" m.reply "config list => list configuration modules, config list => list configuration keys for module " when "get" @@ -266,6 +338,10 @@ module Irc m.reply "config set => set configuration value for key to " when "desc" m.reply "config desc => describe what key configures" + when "add" + m.reply "config add to => add value to key if is an array" + when "rm" + m.reply "config rm from => remove value from key if is an array" else m.reply "no help for config #{topic}" end @@ -296,27 +372,52 @@ module Irc @handler.map 'config desc :key', :action => 'handle_desc' @handler.map 'config describe :key', :action => 'handle_desc' @handler.map 'config set :key *value', :action => 'handle_set' + @handler.map 'config add :value to :key', :action => 'handle_add' + @handler.map 'config rm :value from :key', :action => 'handle_rm' + @handler.map 'config del :value from :key', :action => 'handle_rm' + @handler.map 'config delete :value from :key', :action => 'handle_rm' @handler.map 'config unset :key', :action => 'handle_unset' + @handler.map 'config reset :key', :action => 'handle_unset' @handler.map 'config help :topic', :action => 'handle_help', :defaults => {:topic => false} @handler.map 'help config :topic', :action => 'handle_help', :defaults => {:topic => false} if(File.exist?("#{@@bot.botclass}/conf.yaml")) - newconfig = YAML::load_file("#{@@bot.botclass}/conf.yaml") - @@config.update newconfig - else - # first-run wizard! - BotConfigWizard.new(@@bot).run - # save newly created config - save + begin + newconfig = YAML::load_file("#{@@bot.botclass}/conf.yaml") + newconfig.each { |key, val| + @@config[key.intern] = val + } + return + rescue + error "failed to read conf.yaml: #{$!}" + end end + # if we got here, we need to run the first-run wizard + BotConfigWizard.new(@@bot).run + # save newly created config + save end - # write current configuration to #{botclass}/conf.rbot + # write current configuration to #{botclass}/conf.yaml def save - File.open("#{@@bot.botclass}/conf.yaml", "w") do |file| - file.puts @@config.to_yaml + begin + debug "Writing new conf.yaml ..." + File.open("#{@@bot.botclass}/conf.yaml.new", "w") do |file| + savehash = {} + @@config.each { |key, val| + savehash[key.to_s] = val + } + file.puts savehash.to_yaml + end + debug "Officializing conf.yaml ..." + File.rename("#{@@bot.botclass}/conf.yaml.new", + "#{@@bot.botclass}/conf.yaml") + rescue => e + error "failed to write configuration file conf.yaml! #{$!}" + error "#{e.class}: #{e}" + error e.backtrace.join("\n") end end @@ -345,7 +446,7 @@ module Irc @questions.sort{|a,b| a.order <=> b.order }.each do |q| puts q.desc begin - print q.key + " [#{q.to_s}]: " + print q.key.to_s + " [#{q.to_s}]: " response = STDIN.gets response.chop! unless response.empty?