]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/slashdot.rb
plugin(oxford): fix empty service result see #37
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / slashdot.rb
index 1a70de08c4ceb8091a1c6e4b8ee1a19384b3ab70..2c4a23618b8c91d8f551f53e2dd13b855c9befb5 100644 (file)
@@ -1,45 +1,96 @@
+#-- vim:sw=2:et
+#++
+#
+# :title: Slashdot plugin for rbot
+
 require 'rexml/document'
-require 'uri/common'
 
 class SlashdotPlugin < Plugin
   include REXML
   def help(plugin, topic="")
     "slashdot search <string> [<max>=4] => search slashdot for <string>, slashdot [<max>=4] => return up to <max> slashdot headlines (use negative max to return that many headlines, but all on one line.)"
   end
-  
-  def search_slashdot(m, params)
-   max = params[:limit].to_i
-   search = params[:search].to_s
 
-    begin
-      xml = @bot.httputil.get(URI.parse("http://slashdot.org/search.pl?content_type=rss&query=#{URI.escape(search)}"))
-    rescue URI::InvalidURIError, URI::BadURIError => e
-      m.reply "illegal search string #{search}"
-      return
+  # This method defines a filter for /. pages. It's needed because the generic
+  # summarization grabs a comment, not the actual article.
+  #
+  # This filter relies on Hpricot being available, since REXML isn't too
+  # happy with the /. pages
+  def slashdot_filter(s)
+    return nil unless defined? Hpricot
+    loc = Utils.check_location(s, /slashdot\.org/)
+    return nil unless loc
+    h = Hpricot(s[:text])
+    # If we have no title tag in a head tag, return as this is not
+    # a /. page (it's probably a Slashdot RSS
+    ht = h/"head/title"
+    return nil if ht.empty?
+    title = ht.first.to_html.ircify_html
+    arts = (h/"div.article")
+    return nil if arts.empty?
+    if arts.length > 1
+      tits = []
+      arts.each { |el|
+        # see if the div tag with generaltitle class is present
+        artitle = (el/"div.generaltitle").first
+        if artitle
+          tits << artitle.to_html.ircify_html
+          next
+        end
+        # otherwise, check for skin+datitle a tags
+        datitle = (el/"a.datitle").first
+        next unless datitle
+        skin = (el/"a.skin").first
+        artitle = [
+          skin ? skin.innerHTML.ircify_html : nil,
+          datitle.innerHTML.ircify_html
+        ].compact.join(" ")
+        tits << artitle
+      }
+      content = tits.join(" | ")
+    else
+      det = (arts.first/"div.details").first.to_html.ircify_html
+      body = (arts.first/"div.body").first.to_html.ircify_html
+      content = [det, body].join(' ')
+    end
+    return {:title => title, :content => content}
+  end
+
+  def initialize
+    super
+    if defined? Hpricot
+      @bot.register_filter(:slashdot, :htmlinfo) { |s| slashdot_filter(s) }
     end
+  end
+
+  def search_slashdot(m, params)
+    max = params[:limit].to_i
+    search = params[:search].to_s
+
+    xml = @bot.httputil.get("http://slashdot.org/search.pl?content_type=rss&query=#{CGI.escape(search)}")
     unless xml
       m.reply "search for #{search} failed"
       return
     end
-    puts xml.inspect
+    debug xml.inspect
     begin
       doc = Document.new xml
-    rescue REXML::ParseException => e
-      puts e
-      m.reply "couldn't parse output XML: #{e.class}"
+    rescue REXML::ParseException => err
+      warning err.inspect
+      m.reply "couldn't parse output XML: #{err.class}"
       return
     end
     unless doc
       m.reply "search for #{search} failed"
       return
     end
-    puts doc.inspect
+    debug doc.inspect
     max = 8 if max > 8
     done = 0
     doc.elements.each("*/item") {|e|
       desc = e.elements["title"].text
       desc.gsub!(/(.{150}).*/, '\1..')
-      reply = sprintf("%s | %s", e.elements["link"].text, desc)
+      reply = sprintf("%s | %s", e.elements["link"].text, desc.ircify_html)
       m.reply reply
       done += 1
       break if done >= max
@@ -48,12 +99,12 @@ class SlashdotPlugin < Plugin
       m.reply "search for #{search} failed"
     end
   end
-  
+
   def slashdot(m, params)
-    puts params.inspect
+    debug params.inspect
     max = params[:limit].to_i
-    puts "max is #{max}"
-    xml = @bot.httputil.get(URI.parse("http://slashdot.org/slashdot.xml"))
+    debug "max is #{max}"
+    xml = @bot.httputil.get('http://slashdot.org/slashdot.xml')
     unless xml
       m.reply "slashdot news parse failed"
       return
@@ -72,12 +123,12 @@ class SlashdotPlugin < Plugin
     max = 8 if max > 8
     matches = Array.new
     doc.elements.each("*/story") {|e|
-      matches << [ e.elements["title"].text, 
-                   e.elements["author"].text, 
+      matches << [ e.elements["title"].text,
+                   e.elements["author"].text,
                    e.elements["time"].text.gsub(/\d{4}-(\d{2})-(\d{2})/, "\\2/\\1").gsub(/:\d\d$/, "") ]
       done += 1
       break if done >= max
-    } 
+    }
     if oneline
       m.reply matches.collect{|mat| mat[0]}.join(" | ")
     else