]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/topic.rb
webhook: define number for watch/star actions too
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / topic.rb
old mode 100755 (executable)
new mode 100644 (file)
index 075b694..672bf82
-# Author: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
+#-- vim:sw=2:et
+#++
+#
+# :title: Topic manipulation plugin for rbot
+#
+# Author:: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
+# Copyright:: (C) 2006-2007 Giuseppe Bilotta
+# License:: GPL v2
+#
 # Add a bunch of topic manipulation features
-# NOTE: topic separator is defined by the global symbol SEPARATOR
-
-SEPARATOR=" | "
 
 class TopicPlugin < Plugin
   def initialize
     super
-    @addtopic = /(?:topic(?:append|add)|(?:append|add)topic)/
-    @prependtopic = /(?:topicprepend|prependtopic)/
-    @addtopicat = /(?:(?:addtopic|topicadd)at)/
-    @deltopic = /(?:deltopic|topicdel)/
+    @separator = "|" # default separator
   end
 
   def help(plugin, topic="")
     case plugin
     when "topic"
       case topic
-      when @addtopic
-       return "#{topic} <text> => add <text> at the end the topic"
-      when @prependtopic
-       return "#{topic} <text> => add <text> at the beginning of the topic"
-      when @addtopicat
-       return "#{topic} <num> <text> => add <text> at position <num> of the topic"
-      when @deltopic
-       return "#{topic} <num> => remove section <num> from the topic"
-      when "learntopic"
-       return "learntopic => remembers the topic for later"
-      when "resumetopic"
-       return "resumetopic => resets the topic to the latest remembered one"
-      when "settopic"
-       return "settopic <text> => sets the topic to <text>"
+      when "add"
+        return "topic add <text> => add <text> at the end the topic"
+      when "prepend"
+        return "topic prepend <text> => add <text> at the beginning of the topic"
+      when "addat"
+        return "topic addat <num> <text> => add <text> at position <num> of the topic"
+      when "del", "delete"
+        return "topic del <num> => remove section <num> from the topic"
+      when "replace"
+        return "topic replace <num> <text> => Replaces section <num> with <text>"
+      when "sep", "separator"
+        return "topic sep(arator) [<text>] => 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 <text> => sets the topic to <text>"
+      when "undo"
+        return "topic undo => undoes the latest change to the topic"
       else
-       return "topic commands: addtopic, prependtopic, addtopicat, deltopic, learntopic, resumetopic, settopic"
+        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> <command> " + \
+               "for private addressing"
       end
-    when "learntopic"
-      return "learntopic => remembers the topic for later"
-    when "resumetopic"
-      return "resumetopic => resets the topic to the latest remembered one"
-    when "settopic"
-      return "settopic <text> => sets the topic to <text>"
     end
   end
 
-  def listen(m)
-    return unless m.kind_of?(PrivMessage) && m.public?
-    command = m.message.dup
-    debug command
-    if m.address? || command.gsub!(/^!/, "")
-      case command
-      when /^#{@addtopic}\s+(.*)\s*/
-       txt=$1
-       debug txt
-       if @bot.auth.allow?("topic", m.source, m.replyto)
-         topicappend(m, txt)
-       end
-      when /^#{@prependtopic}\s+(.*)\s*/
-       txt=$1
-       debug txt
-       if @bot.auth.allow?("topic", m.source, m.replyto)
-         topicaddat(m, 0, txt)
-       end
-      when /^#{@addtopicat}\s+(-?\d+)\s+(.*)\s*/
-       num=$1.to_i - 1
-       num += 1 if num < 0
-       txt=$2
-       debug txt
-       if @bot.auth.allow?("topic", m.source, m.replyto)
-         topicaddat(m, num, txt)
-       end
-      when /^#{@deltopic}\s+(-?\d+)\s*/
-       num=$1.to_i - 1
-       num += 1 if num < 0
-       debug num
-       if @bot.auth.allow?("topic", m.source, m.replyto)
-         topicdel(m, num)
-       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, num, txt)
-    channel = m.channel.downcase
-    topic = @bot.channels[m.channel].topic.to_s
-    topicarray = topic.split(SEPARATOR)
+  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(SEPARATOR)
-    @bot.topic channel, newtopic
+    newtopic = topicarray.join(" #{sep} ")
+    changetopic(m, ch, newtopic)
+  end
+
+  def topicappend(m, ch, txt)
+    topicaddat(m, ch, -1, txt)
   end
 
-  def topicappend(m, txt)
-    channel = m.channel.downcase
-    topic = @bot.channels[m.channel].topic.to_s
-    topicarray = topic.split(SEPARATOR)
-    topicarray << txt
-    newtopic = topicarray.join(SEPARATOR)
-    @bot.topic channel, newtopic
+  def topicprepend(m, ch, txt)
+    topicaddat(m, ch, 0, txt)
   end
 
-  def topicdel(m, num)
-    channel = m.channel.downcase
-    topic = @bot.channels[m.channel].topic.to_s
-    topicarray = topic.split(SEPARATOR)
+  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(SEPARATOR)
-    @bot.topic channel, newtopic
-  end
-
-  def learntopic(m, param)
-    return if !@bot.auth.allow?("learntopic", m.source, m.replyto)
-    channel = m.channel.downcase
-    debug channel
-    topic = @bot.channels[m.channel].topic.to_s
-    @registry[channel] = topic
-    @bot.say channel, "Ok"
-  end
-
-  def resumetopic(m, param)
-    return if !@bot.auth.allow?("resumetopic", m.source, m.replyto)
-    channel = m.channel.downcase
-    debug "Channel: #{channel}"
-    if @registry.has_key?(channel)
-      topic = @registry[channel]
-      debug "Channel: #{channel}, topic: #{topic}"
-      @bot.topic channel, topic
+    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
-      @bot.say channel, "Non ricordo nulla"
+      data = Hash.new
     end
+    data[:topic] = topic
+    @registry[k] = data
+    m.okay
   end
 
-  def settopic(m, param)
-    return if !@bot.auth.allow?("topic", m.source, m.replyto)
-    channel = m.channel.downcase
-    debug "Channel: #{channel}"
-    @bot.topic channel, param[:text].to_s
+  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.register 'topic'
-plugin.map 'settopic *text', :action => 'settopic'
-plugin.map 'resumetopic'
-plugin.map 'learntopic'
+
+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)
+