X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=data%2Frbot%2Fplugins%2Fkeywords.rb;h=da32078096152ccc33fe71f6064eb48fe0764a83;hb=90656f4203a0a989b6fb110d4a07598dd186b84c;hp=5daff9f660edd99636b080d80b60472c19ecaf0d;hpb=2541e09611bfb631c1d0859e117ef237aa264704;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/data/rbot/plugins/keywords.rb b/data/rbot/plugins/keywords.rb index 5daff9f6..da320780 100644 --- a/data/rbot/plugins/keywords.rb +++ b/data/rbot/plugins/keywords.rb @@ -28,6 +28,19 @@ class Keyword end end + # return an array of all the possible values + def to_factoids(key) + ar = Array.new + @values.each { |val| + debug "key #{key}, value #{val}" + vals = val.split(" or ") + vals.each { |v| + ar << "%s %s %s" % [key, @type, v] + } + } + return ar + end + # describe the keyword (show all values without interpolation) def desc @values.join(" | ") @@ -88,6 +101,9 @@ class Keywords < Plugin Config.register Config::IntegerValue.new('keyword.search_results', :default => 3, :desc => "How many search results to display at a time") + Config.register Config::ArrayValue.new('keyword.ignore_words', + :default => ["how", "that", "these", "they", "this", "what", "when", "where", "who", "why", "you"], + :desc => "A list of words that the bot should passively ignore.") # create a new KeywordPlugin instance, associated to bot +bot+ def initialize @@ -100,9 +116,10 @@ class Keywords < Plugin scan # import old format keywords into DBHash - if(File.exist?("#{@bot.botclass}/keywords.rbot")) + olds = @bot.path 'keywords.rbot' + if File.exist? olds log "auto importing old keywords.rbot" - IO.foreach("#{@bot.botclass}/keywords.rbot") do |line| + IO.foreach(olds) do |line| if(line =~ /^(.*?)\s*<=(is|are)?=?>\s*(.*)$/) lhs = $1 mhs = $2 @@ -113,7 +130,7 @@ class Keywords < Plugin @keywords[lhs] = Keyword.new(mhs, values).dump end end - File.rename("#{@bot.botclass}/keywords.rbot", "#{@bot.botclass}/keywords.rbot.old") + File.rename(olds, olds + ".old") end end @@ -121,15 +138,12 @@ class Keywords < Plugin # have been added def scan # first scan for old DBHash files, and convert them - Dir["#{@bot.botclass}/keywords/*"].each {|f| + Dir[datafile('*')].each {|f| next unless f =~ /\.db$/ log "upgrading keyword db #{f} (rbot 0.9.5 or prior) database format" newname = f.gsub(/\.db$/, ".kdb") - old = BDB::Hash.open f, nil, - "r+", 0600 - new = BDB::CIBtree.open(newname, nil, - BDB::CREATE | BDB::EXCL, - 0600) + old = BDB::Hash.open f, nil, "r+", 0600 + new = BDB::CIBtree.open(newname, nil, BDB::CREATE | BDB::EXCL, 0600) old.each {|k,v| new[k] = v } @@ -139,7 +153,7 @@ class Keywords < Plugin } # then scan for current DBTree files, and load them - Dir["#{@bot.botclass}/keywords/*"].each {|f| + Dir[@bot.path('keywords', '*')].each {|f| next unless f =~ /\.kdb$/ hsh = DBTree.new @bot, f, true key = File.basename(f).gsub(/\.kdb$/, "") @@ -148,7 +162,7 @@ class Keywords < Plugin } # then scan for non DB files, and convert/import them and delete - Dir["#{@bot.botclass}/keywords/*"].each {|f| + Dir[@bot.path('keywords', '*')].each {|f| next if f =~ /\.kdb$/ next if f =~ /CVS$/ log "auto converting keywords from #{f}" @@ -176,28 +190,28 @@ class Keywords < Plugin # upgrade data files found in old rbot formats to current def upgrade_data - if File.exist?("#{@bot.botclass}/keywords.db") + olds = @bot.path 'keywords.db' + if File.exist? olds log "upgrading old keywords (rbot 0.9.5 or prior) database format" - old = BDB::Hash.open "#{@bot.botclass}/keywords.db", nil, - "r+", 0600 + old = BDB::Hash.open olds, nil, "r+", 0600 old.each {|k,v| @keywords[k] = v } old.close @keywords.flush - File.rename("#{@bot.botclass}/keywords.db", "#{@bot.botclass}/keywords.db.old") + File.rename(olds, olds + ".old") end - if File.exist?("#{@bot.botclass}/keyword.db") + olds.replace(@bot.path('keyword.db')) + if File.exist? olds log "upgrading old keywords (rbot 0.9.9 or prior) database format" - old = BDB::CIBtree.open "#{@bot.botclass}/keyword.db", nil, - "r+", 0600 + old = BDB::CIBtree.open olds, nil, "r+", 0600 old.each {|k,v| @keywords[k] = v } old.close @keywords.flush - File.rename("#{@bot.botclass}/keyword.db", "#{@bot.botclass}/keyword.db.old") + File.rename(olds, olds + ".old") end end @@ -207,7 +221,7 @@ class Keywords < Plugin end def oldsave - File.open("#{@bot.botclass}/keywords.rbot", "w") do |file| + File.open(@bot.path("keywords.rbot"), "w") do |file| @keywords.each do |key, value| file.puts "#{key}<=#{value.type}=>#{value.dump}" end @@ -245,6 +259,11 @@ class Keywords < Plugin return false end + # is +word+ a passively ignored keyword? + def ignored_word?(word) + @bot.config["keyword.ignore_words"].include?(word) + end + # m:: PrivMessage containing message info # key:: key being queried # quiet:: optional, if false, complain if +key+ is not found @@ -306,6 +325,12 @@ class Keywords < Plugin case plugin when /keyword/ case topic + when 'export' + 'keyword export => exports definitions to keyword_factoids.rbot' + when 'stats' + 'keyword stats => show statistics about static facts' + when 'wipe' + 'keyword wipe => forgets everything about a keyword' when 'lookup' 'keyword [lookup] => look up the definition for a keyword; writing "lookup" is optional' when 'set' @@ -329,7 +354,7 @@ class Keywords < Plugin when '' ' => respond by setting the topic to the rest of the definition' else - 'keyword module (fact learning and regurgitation) topics: lookup, set, forget, tell, search, listen, address, , , , ' + 'keyword module (fact learning and regurgitation) topics: lookup, set, forget, tell, search, listen, address, stats, export, wipe, , , , ' end when "forget" 'forget => forget a keyword' @@ -430,9 +455,45 @@ class Keywords < Plugin # forget one of the dynamic keywords def keyword_forget(m, key) - if(@keywords.has_key?(key)) - @keywords.delete(key) - @bot.okay m.replyto + if @keywords.delete(key) + m.okay + else + m.reply _("couldn't find keyword %{key}" % { :key => key }) + end + end + + # low-level keyword wipe command for when forget doesn't work + def keyword_wipe(m, key) + reg = @keywords.registry + reg.env.begin(reg) { |t, b| + b.delete_if { |k, v| + (k == key) && (m.reply "wiping keyword #{key} with stored value #{Marshal.restore(v)}") + } + t.commit + } + m.reply "done" + end + + # export keywords to factoids file + def keyword_factoids_export + ar = Array.new + + debug @keywords.keys + + @keywords.each { |k, val| + next unless val + kw = Keyword.restore(val) + ar |= kw.to_factoids(k) + } + + # TODO check factoids config + # also TODO: runtime export + dir = @bot.path 'factoids' + fname = File.join(dir,"keyword_factoids.rbot") + + Dir.mkdir(dir) unless FileTest.directory?(dir) + Utils.safe_save(fname) do |file| + file.puts ar end end @@ -441,10 +502,19 @@ class Keywords < Plugin case m.plugin when "keyword" case m.params + when /^export$/ + begin + keyword_factoids_export + m.okay + rescue + m.reply _("failed to export keywords as factoids (%{err})" % {:err => $!}) + end when /^set\s+(.+?)\s+(is|are)\s+(.+)$/ keyword_command(m, $1, $2, $3) if @bot.auth.allow?('keycmd', m.source, m.replyto) when /^forget\s+(.+)$/ keyword_forget(m, $1) if @bot.auth.allow?('keycmd', m.source, m.replyto) + when /^wipe\s(.+)$/ # note that only one space is stripped, allowing removal of space-prefixed keywords + keyword_wipe(m, $1) if @bot.auth.allow?('keycmd', m.source, m.replyto) when /^lookup\s+(.+)$/ keyword_lookup(m, $1) if @bot.auth.allow?('keyword', m.source, m.replyto) when /^stats\s*$/ @@ -486,10 +556,10 @@ class Keywords < Plugin # TODO option to do if(m.message =~ /^(.*)$/, ie try any line as a # keyword lookup. if m.message =~ /^(.*\S)\s*\?\s*$/ and (m.address? or not @bot.config["keyword.address"]) - keyword_lookup m, $1, true if @bot.auth.allow?("keyword", m.source) + keyword_lookup m, $1, true if !ignored_word?($1) && @bot.auth.allow?("keyword", m.source) elsif @bot.config["keyword.listen"] && (m.message =~ /^(.*?)\s+(is|are)\s+(.*)$/) # TODO MUCH more selective on what's allowed here - keyword_command m, $1, $2, $3, true if @bot.auth.allow?("keycmd", m.source) + keyword_command m, $1, $2, $3, true if !ignored_word?($1) && @bot.auth.allow?("keycmd", m.source) end end end