# Author: Michael Brailsford # aka brailsmt # Purpose: Provides the ability to track various tokens that are spoken in a # channel. # Copyright: 2002 Michael Brailsford. All rights reserved. # License: This plugin is licensed under the BSD license. The terms of # which follow. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. class StatsPlugin < Plugin @@commands = { "stats" => "handle_stats", "track" => "handle_track", "untrack" => "handle_untrack", "listtokens" => "handle_listtokens", "rmabuser" => "handle_rmabuser" } #{{{ def initialize super @listen = true @channels = Hash.new #check to see if a stats token file already exists for this channel... Dir["#{@bot.botclass}/stats/*"].each { |fname| channel = File.basename fname tokens = Hash.new IO.foreach(fname) { |line| if line =~ /^(\S+)\s*<=>(.*)/ tokens[$1] = parse_token_stats $2 end } @channels[channel] = tokens } end #}}} #{{{ def cleanup @channels = nil end #}}} #{{{ def help(plugin, topic="") "Stats: The stats plugin tracks various tokens from users in the channel. The tokens are only tracked if it is the only thing on a line.\nUsage: stats -- lists the stats for \n [un]track -- Adds or deletes from the list of tokens\n listtokens -- lists the tokens that are currently being tracked" end #}}} #{{{ def privmsg(m) if not m.params and not m.plugin =~ /listtokens/ m.reply "What a crazy fool! Did you mean |help stats?" return end meth = self.method(@@commands[m.plugin]) meth.call(m) end #}}} #{{{ def save Dir.mkdir("#{@bot.botclass}/stats") if not FileTest.directory?("#{@bot.botclass}/stats") #save the tokens to a file... @channels.each_pair { |channel, tokens| if not tokens.empty? File.open("#{@bot.botclass}/stats/#{channel}", "w") { |f| tokens.each { |token, datahash| f.puts "#{token} <=> #{datahash_to_s(datahash)}" } } else File.delete "#{@bot.botclass}/stats/#{channel}" end } end #}}} #{{{ def listen(m) if not m.private? tokens = @channels[m.target] if not @@commands[m.plugin] tokens.each_pair { |key, hsh| if not m.message.scan(/#{Regexp.escape(key)}/).empty? if hsh[m.sourcenick] hsh[m.sourcenick] += 1 else hsh[m.sourcenick] = 1 end end } end end #This is the old code {{{ # if not m.private? # tokens = @channels[m.target] # hsh = tokens[m.message] # if hsh # if hsh[m.sourcenick] # hsh[m.sourcenick] += 1 # else # hsh[m.sourcenick] = 1 # end # end # end }}} end #}}} #The following are helper functions for the plugin {{{ def datahash_to_s(dhash) rv = "" dhash.each { |key, val| rv << "#{key}:#{val} " } rv.chomp end def parse_token_stats(stats) rv = Hash.new stats.split(" ").each { |nickstat| nick, stat = nickstat.split ":" rv[nick] = stat.to_i } rv end #}}} #The following are handler methods for dealing with each command from IRC {{{ #{{{ def handle_stats(m) if not m.private? total = 0 tokens = @channels[m.target] hsh = tokens[m.params] msg1 = "" if not hsh.empty? sorted = hsh.sort { |i, j| j[1] <=> i[1] } sorted.each { |a| total += a[1] } msg = "Stats for #{m.params}. Said #{total} times. The top sayers are " if sorted[0..2] msg << "#{sorted[0].join ':'}" if sorted[0] msg << ", #{sorted[1].join ':'}" if sorted[1] msg << ", and #{sorted[2].join ':'}" if sorted[2] msg << "." msg1 << "#{m.sourcenick} has said it " if hsh[m.sourcenick] msg1 << "#{hsh[m.sourcenick]} times." else msg1 << "0 times." end else msg << "#{m.params} has not been said yet!" end @bot.action m.replyto, msg @bot.action m.replyto, msg1 if msg1 else m.reply "#{m.params} is not currently being tracked." end end end #}}} #{{{ def handle_track(m) if not m.private? if @channels[m.target] tokens = @channels[m.target] else tokens = Hash.new @channels[m.target] = tokens end tokens[m.params] = Hash.new m.reply "now tracking #{m.params}" end end #}}} #{{{ def handle_untrack(m) if not m.private? toks = @channels[m.target] if toks.has_key? m.params toks.delete m.params m.reply "no longer tracking #{m.params}" else m.reply "Are your signals crossed? Since when have I tracked that?" end end toks = nil end #}}} #{{{ def handle_listtokens(m) if not m.private? and not @channels.empty? tokens = @channels[m.target] unless tokens.empty? toks = "" tokens.each_key { |k| toks << "#{k} " } @bot.action m.replyto, "is currently keeping stats for: #{toks}" else @bot.action m.replyto, "is not currently keeping stats for anything" end elsif not m.private? @bot.action m.replyto, "is not currently keeping stats for anything" end end #}}} #{{{ def handle_rmabuser(m) m.reply "This feature has not yet been implemented" end #}}} #}}} end plugin = StatsPlugin.new plugin.register("stats") plugin.register("track") plugin.register("untrack") plugin.register("listtokens") #plugin.register("rmabuser")