+#-- vim:sw=2:et
+#++
+#
+# :title: Slashdot plugin for rbot
+
require 'rexml/document'
class SlashdotPlugin < Plugin
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
-
+
+ # 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
debug xml.inspect
begin
doc = Document.new xml
- rescue REXML::ParseException => e
- warning e.inspect
- 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"
end
end
-
+
def slashdot(m, params)
debug params.inspect
max = params[:limit].to_i
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