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
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)
# 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
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
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(", ")
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
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
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
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 <module> => list configuration keys for module <module>"
when "get"
m.reply "config set <key> <value> => set configuration value for key <key> to <value>"
when "desc"
m.reply "config desc <key> => describe what key <key> configures"
+ when "add"
+ m.reply "config add <value> to <key> => add value <value> to key <key> if <key> is an array"
+ when "rm"
+ m.reply "config rm <value> from <key> => remove value <value> from key <key> if <key> is an array"
else
m.reply "no help for config #{topic}"
end
@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',
if(File.exist?("#{@@bot.botclass}/conf.yaml"))
begin
newconfig = YAML::load_file("#{@@bot.botclass}/conf.yaml")
- @@config.update newconfig
+ newconfig.each { |key, val|
+ @@config[key.intern] = val
+ }
return
rescue
- $stderr.puts "failed to read conf.yaml: #{$!}"
+ error "failed to read conf.yaml: #{$!}"
end
end
# if we got here, we need to run the first-run wizard
save
end
- # write current configuration to #{botclass}/conf.rbot
+ # write current configuration to #{botclass}/conf.yaml
def save
begin
debug "Writing new conf.yaml ..."
File.open("#{@@bot.botclass}/conf.yaml.new", "w") do |file|
- file.puts @@config.to_yaml
+ 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
- $stderr.puts "failed to write configuration file conf.yaml! #{$!}"
- debug "#{e.class}: #{e}"
- debug e.backtrace.join("\n")
+ error "failed to write configuration file conf.yaml! #{$!}"
+ error "#{e.class}: #{e}"
+ error e.backtrace.join("\n")
end
end
@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?