]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/rss.rb
rss: protect against nil field
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / rss.rb
index 1b12632af9969a1058ebf4af1719555d25049d6d..f7e559f7601ed86a10a1e17c26da681e25e812cf 100644 (file)
@@ -151,6 +151,28 @@ module ::RSS
     SlashModel::ELEMENTS.collect! {|name| "#{SLASH_PREFIX}_#{name}"}
   end
 
+  if self.const_defined? :Atom
+    # There are improper Atom feeds around that use the non-standard
+    # 'modified' element instead of the correct 'updated' one. Let's
+    # support it too.
+    module Atom
+      class Feed
+        class Modified < RSS::Element
+          include CommonModel
+          include DateConstruct
+        end
+        __send__("install_have_child_element",
+                 "modified", URI, nil, "modified", :content)
+
+        class Entry
+          Modified = Feed::Modified
+          __send__("install_have_child_element",
+                   "modified", URI, nil, "modified", :content)
+        end
+      end
+    end
+  end
+
   class Element
     class << self
       def def_bang(name, chain)
@@ -162,18 +184,27 @@ module ::RSS
       end
     end
 
+    # Atom categories are squashed to their label only
     {
       :link => %w{link.href link},
       :guid => %w{guid.content guid},
       :content => %w{content.content content},
       :description => %w{description.content description},
       :title => %w{title.content title},
-      :category => %w{category.content category},
+      :category => %w{category.content category.label category},
       :dc_subject => %w{dc_subject},
       :author => %w{author.name.content author.name author},
       :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.label rescue c rescue nil }
+      end.compact
+      cats.empty? ? nil : cats
+    end
+
     protected
     def blank2nil(&block)
       x = yield
@@ -300,7 +331,7 @@ class RSSFeedsPlugin < Plugin
     :desc => "Whether to display links from the text of a feed item.")
 
   # Make an  'unique' ID for a given item, based on appropriate bot options
-  # Currently only suppored is bot.config['rss.show_updated']: when false,
+  # Currently only supported is bot.config['rss.show_updated']: when false,
   # only the guid/link is accounted for.
 
   def make_uid(item)
@@ -361,7 +392,7 @@ class RSSFeedsPlugin < Plugin
           # do nothing
         else
           warning "ignoring #{v.inspect} wrapping of unknown class"
-        end
+        end unless ss[nk].nil?
       else
         subs[k] = v
       end
@@ -772,15 +803,28 @@ class RSSFeedsPlugin < Plugin
     end
     case params[:what].intern
     when :handle
-      new = params[:new].downcase
-      if @feeds.key?(new) and @feeds[new]
+      # preserve rename case, but beware of key
+      realnew = params[:new]
+      new = realnew.downcase
+      if feed.handle.downcase == new
+        if feed.handle == realnew
+          m.reply _("You want me to rename %{handle} to itself?") % {
+            :handle => feed.handle
+          }
+          return false
+        else
+          feed.mutex.synchronize do
+            feed.handle = realnew
+          end
+        end
+      elsif @feeds.key?(new) and @feeds[new]
         m.reply "There already is a feed with handle #{new}"
         return
       else
         feed.mutex.synchronize do
           @feeds[new] = feed
           @feeds.delete(handle)
-          feed.handle = new
+          feed.handle = realnew
         end
         handle = new
       end
@@ -891,8 +935,8 @@ class RSSFeedsPlugin < Plugin
       stop_watches
 
       # Read watches from list.
-      watchlist.each{ |handle, feed|
-        watchRss(feed, m)
+      watchlist.each{ |hndl, fd|
+        watchRss(fd, m)
       }
       m.okay if m
     end
@@ -919,7 +963,7 @@ class RSSFeedsPlugin < Plugin
         debug "fetching #{feed}"
 
         first_run = !feed.last_success
-        if (@bot.config['rss.announce_timeout'] > 0 &&
+        if (!first_run && @bot.config['rss.announce_timeout'] > 0 &&
            (Time.now - feed.last_success > @bot.config['rss.announce_timeout']))
           debug "#{feed} wasn't polled for too long, supressing output"
           first_run = true
@@ -1057,8 +1101,10 @@ class RSSFeedsPlugin < Plugin
 
     date = \
     if opts[:date]
-      if item.respond_to?(:updated)
+      if item.respond_to?(:updated) and item.updated
         make_date(item.updated.content)
+      elsif item.respond_to?(:modified) and item.modified
+        make_date(item.modified.content)
       elsif item.respond_to?(:source) and item.source.respond_to?(:updated)
         make_date(item.source.updated.content)
       elsif item.respond_to?(:pubDate)
@@ -1112,6 +1158,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!
@@ -1134,6 +1181,7 @@ class RSSFeedsPlugin < Plugin
       :title => title,
       :title_wrap => Bold,
       :desc => desc, :link => link,
+      :categories => categories,
       :category => category, :author => author, :at => at
     }
     output = @bot.filter(key, stream_hash)