#-- vim:sw=2:et #++ # # :title: Topic manipulation plugin for rbot # # Author:: Giuseppe Bilotta # Copyright:: (C) 2006-2007 Giuseppe Bilotta # License:: GPL v2 # # Add a bunch of topic manipulation features class TopicPlugin < Plugin def initialize super @separator = "|" # default separator end def help(plugin, topic="") case plugin when "topic" case topic when "add" return "topic add => add at the end the topic" when "prepend" return "topic prepend => add at the beginning of the topic" when "addat" return "topic addat => add at position of the topic" when "del", "delete" return "topic del => remove section from the topic" when "replace" return "topic replace => Replaces section with " when "sep", "separator" return "topic sep(arator) [] => get or set the topic section separator" when "learn" return "topic learn => remembers the topic for later" when "restore" return "topic restore => resets the topic to the latest remembered one" when "clear" return "topic clear => clears the topic" when "set" return "topic set => sets the topic to " when "undo" return "topic undo => undoes the latest change to the topic" else return "topic add(at)|prepend|del(ete)|replace|sep(arator)|learn|restore|clear|set|undo: " + \ "manipulate the topic of the current channel; use topic <#channel> " + \ "for private addressing" end end end def handletopic(m, param) return unless m.kind_of?(PrivMessage) if m.public? ch = m.channel else ch = m.server.get_channel(param[:channel]) unless ch m.reply("I am not in channel #{param[:channel]}") return end end cmd = param[:command] txt = param[:text].to_s case cmd when /^a(dd|ppend)$/ topicappend(m, ch, txt) when 'prepend' topicprepend(m, ch, txt) when 'addat' if txt =~ /\s*(-?\d+)\s+(.*)\s*/ num = $1.to_i - 1 num += 1 if num < 0 txt = $2 topicaddat(m, ch, num, txt) end when /^del(ete)?$/ if txt =~ /\s*(-?\d+)\s*/ num=$1.to_i - 1 num += 1 if num < 0 topicdel(m, ch, num) end when 'set' topicset(m, ch, txt) when 'clear' topicset(m, ch, '') when /^sep(arator)?$/ topicsep(m, ch, txt) when 'learn' learntopic(m, ch) when 'replace' if txt =~ /\s*(-?\d+)\s+(.*)\s*/ num = $1.to_i - 1 num += 1 if num < 0 txt = $2 replacetopic(m, ch, num, txt) end when 'restore' restoretopic(m, ch) when 'undo' undotopic(m, ch) else m.reply 'unknown command' end end def topicsep(m, ch, txt) return if !@bot.auth.allow?("topic::edit::separator", m.source, m.replyto) if txt sep = txt.strip if sep != "" setsep(ch, sep) end end m.reply "Topic separator set to #{getsep(ch)}" end def setsep(ch, sep) raise unless ch.class <= Irc::Channel # TODO multiserver k = ch.downcase if @registry.has_key?(k) data = @registry[k] else data = Hash.new end oldsep = getsep(ch) topic = ch.topic.text topicarray = topic.split(/\s+#{Regexp.escape(oldsep)}\s*/) if sep != oldsep and topicarray.length > 0 newtopic = topicarray.join(" #{sep} ") @bot.topic ch, newtopic if newtopic != topic end data[:separator] = sep @registry[k] = data end def getsep(ch) raise unless ch.class <= Irc::Channel # TODO multiserver k = ch.downcase if @registry.has_key?(k) if @registry[k].has_key?(:separator) return @registry[k][:separator] end end return @separator end def topicaddat(m, ch, num, txt) return if !@bot.auth.allow?("topic::edit::add", m.source, m.replyto) sep = getsep(ch) topic = ch.topic.text topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/) topicarray.insert(num, txt) newtopic = topicarray.join(" #{sep} ") changetopic(m, ch, newtopic) end def topicappend(m, ch, txt) topicaddat(m, ch, -1, txt) end def topicprepend(m, ch, txt) topicaddat(m, ch, 0, txt) end def topicdel(m, ch, num) return if !@bot.auth.allow?("topic::edit::del", m.source, m.replyto) sep = getsep(ch) topic = ch.topic.text topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/) topicarray.delete_at(num) newtopic = topicarray.join(" #{sep} ") changetopic(m, ch, newtopic) end def learntopic(m, ch) return if !@bot.auth.allow?("topic::store::store", m.source, m.replyto) topic = ch.topic.text k = ch.downcase if @registry.has_key?(k) data = @registry[k] else data = Hash.new end data[:topic] = topic @registry[k] = data m.okay end def replacetopic(m, ch, num, txt) return if !@bot.auth.allow?("topic::edit::replace", m.source, m.replyto) sep = getsep(ch) topic = ch.topic.text topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/) topicarray[num] = txt newtopic = topicarray.join(" #{sep} ") changetopic(m, ch, newtopic) end def restoretopic(m, ch) return if !@bot.auth.allow?("topic::store::restore", m.source, m.replyto) k = ch.downcase if @registry.has_key?(k) && @registry[k].has_key?(:topic) topic = @registry[k][:topic] topicset(m, ch, topic) else m.reply "I don't remember any topic for #{ch}" end end def topicset(m, ch, text) return if !@bot.auth.allow?("topic::edit::replace", m.source, m.replyto) changetopic(m, ch, text) end # This method changes the topic on channel +ch+ to +text+, storing # the previous topic for undo def changetopic(m, ch, text) k = ch.downcase if @registry.has_key?(k) data = @registry[k] else data = Hash.new end data[:oldtopic] = ch.topic.text @registry[k] = data @bot.topic ch, text end def undotopic(m, ch) k = ch.downcase if @registry.has_key?(k) data = @registry[k] if data.has_key?(:oldtopic) changetopic(m, ch, data[:oldtopic].dup) return end end m.reply "No recent changes were recorded for #{ch}" end end plugin = TopicPlugin.new plugin.map 'topic :command [*text]', :action => 'handletopic', :public => true, :private => false plugin.map 'topic :channel :command [*text]', :action => 'handletopic', :public => false, :private => true plugin.default_auth('*', false)