]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/rss.rb
hangman: IRCify HTML in definitions
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / rss.rb
index 8004cb122f8375da61c12c989846a20915343eaa..cabc8272f23ab7e77f24d576554a2beae84ead27 100644 (file)
@@ -174,6 +174,14 @@ module ::RSS
       :dc_creator => %w{dc_creator}
     }.each { |name, chain| def_bang name, chain }
 
+    def categories!
+      return nil unless self.respond_to? :categories
+      cats = categories.map do |c|
+        blank2nil { c.content rescue c rescue nil }
+      end.compact
+      cats.empty? ? nil : cats
+    end
+
     protected
     def blank2nil(&block)
       x = yield
@@ -331,10 +339,43 @@ class RSSFeedsPlugin < Plugin
 
   # Auxiliary method used to collect two lines for rss output filters,
   # running substitutions against DataStream _s_ optionally joined
-  # with hash _h_
+  # with hash _h_.
+  #
+  # For substitutions, *_wrap keys can be used to alter the content of
+  # other nonempty keys. If the value of *_wrap is a String, it will be
+  # put before and after the corresponding key; if it's an Array, the first
+  # and second elements will be used for wrapping; if it's nil, no wrapping
+  # will be done (useful to override a default wrapping).
+  #
+  # For example:
+  # :handle_wrap => '::'::
+  #   will wrap s[:handle] by prefixing and postfixing it with '::'
+  # :date_wrap => [nil, ' :: ']::
+  #   will put ' :: ' after s[:date]
   def make_stream(line1, line2, s, h={})
     ss = s.merge(h)
-    DataStream.new([line1, line2].compact.join("\n") % ss, ss)
+    subs = {}
+    wraps = {}
+    ss.each do |k, v|
+      kk = k.to_s.chomp!('_wrap')
+      if kk
+        nk = kk.intern
+        case v
+        when String
+          wraps[nk] = ss[nk].wrap_nonempty(v, v)
+        when Array
+          wraps[nk] = ss[nk].wrap_nonempty(*v)
+        when nil
+          # do nothing
+        else
+          warning "ignoring #{v.inspect} wrapping of unknown class"
+        end
+      else
+        subs[k] = v
+      end
+    end
+    subs.merge! wraps
+    DataStream.new([line1, line2].compact.join("\n") % subs, ss)
   end
 
   # Auxiliary method used to define rss output filters
@@ -344,13 +385,31 @@ class RSSFeedsPlugin < Plugin
 
   # Define default output filters (rss types), and load custom ones.
   # Custom filters are looked for in the plugin's default filter locations
-  # and in rss/types under botclass.
+  # and in rss/types.rb under botclass.
   # Preferably, the rss_type method should be used in these files, e.g.:
   #   rss_type :my_type do |s|
   #     line1 = "%{handle} and some %{author} info"
   #     make_stream(line1, nil, s)
   #   end
-  # to define the new type 'my_type'
+  # to define the new type 'my_type'. The keys available in the DataStream
+  # are:
+  # item::
+  #   the actual rss item
+  # handle::
+  #   the item handle
+  # date::
+  #   the item date
+  # title::
+  #   the item title
+  # desc, link, category, author::
+  #   the item description, link, category, author
+  # at::
+  #   the string ' @ ' if the item has both an title and a link
+  # handle_wrap, date_wrap, title_wrap, ...::
+  #   these keys can be defined to wrap the corresponding elements if they
+  #   are nonempty. By default handle is wrapped with '::', date has a ' ::'
+  #   appended and title is enbolden
+  #
   def define_filters
     @outkey ||= :"rss.out"
 
@@ -982,50 +1041,43 @@ class RSSFeedsPlugin < Plugin
       return seconds
   end
 
+  def make_date(obj)
+    if obj.kind_of? Time
+      obj.strftime("%Y/%m/%d %H:%M")
+    else
+      obj.to_s
+    end
+  end
+
   def printFormattedRss(feed, item, options={})
     # debug item
     opts = {
       :places => feed.watchers,
-      :handle => feed.handle.empty? ? "" : "::#{feed.handle}:: ",
+      :handle => feed.handle,
       :date => false,
       :announce_method => @bot.config['rss.announce_method']
     }.merge options
 
-    date = String.new
-
     places = opts[:places]
-    handle = opts[:handle].to_s
     announce_method = opts[:announce_method]
 
+    handle = opts[:handle].to_s
+
+    date = \
     if opts[:date]
       if item.respond_to?(:updated)
-        if item.updated.content.class <= Time
-          date = item.updated.content.strftime("%Y/%m/%d %H:%M")
-        else
-          date = item.updated.content.to_s
-        end
+        make_date(item.updated.content)
       elsif item.respond_to?(:source) and item.source.respond_to?(:updated)
-        if item.source.updated.content.class <= Time
-          date = item.source.updated.content.strftime("%Y/%m/%d %H:%M")
-        else
-          date = item.source.updated.content.to_s
-        end
+        make_date(item.source.updated.content)
       elsif item.respond_to?(:pubDate)
-        if item.pubDate.class <= Time
-          date = item.pubDate.strftime("%Y/%m/%d %H:%M")
-        else
-          date = item.pubDate.to_s
-        end
+        make_date(item.pubDate)
       elsif item.respond_to?(:date)
-        if item.date.class <= Time
-          date = item.date.strftime("%Y/%m/%d %H:%M")
-        else
-          date = item.date.to_s
-        end
+        make_date(item.date)
       else
-        date = "(no date)"
+        "(no date)"
       end
-      date << " :: "
+    else
+      String.new
     end
 
     tit_opt = {}
@@ -1039,7 +1091,7 @@ class RSSFeedsPlugin < Plugin
       # visible in the URL anyway
       # TODO make this optional?
       base_title.sub!(/^Changeset \[([\da-f]{40})\]:/) { |c| "(git commit)"} if feed.type == 'trac'
-      title = "#{Bold}#{base_title.ircify_html(tit_opt)}#{Bold}"
+      title = base_title.ircify_html(tit_opt)
     end
 
     desc_opt = {}
@@ -1068,6 +1120,7 @@ class RSSFeedsPlugin < Plugin
     link = item.link!
     link.strip! if link
 
+    categories = item.categories!
     category = item.category! || item.dc_subject!
     category.strip! if category
     author = item.dc_creator! || item.author!
@@ -1081,9 +1134,19 @@ class RSSFeedsPlugin < Plugin
     key = @bot.global_filter_name(feed.type, @outkey)
     key = @bot.global_filter_name(:default, @outkey) unless @bot.has_filter?(key)
 
-    output = @bot.filter(key, :item => item, :handle => handle, :date => date,
-                         :title => title, :desc => desc, :link => link,
-                         :category => category, :author => author, :at => at)
+    stream_hash = {
+      :item => item,
+      :handle => handle,
+      :handle_wrap => ['::', ':: '],
+      :date => date,
+      :date_wrap => [nil, ' :: '],
+      :title => title,
+      :title_wrap => Bold,
+      :desc => desc, :link => link,
+      :categories => categories,
+      :category => category, :author => author, :at => at
+    }
+    output = @bot.filter(key, stream_hash)
 
     return output if places.empty?