]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/slashdot.rb
Initial implementation of proper caching based on last-modified and etag HTTP headers
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / slashdot.rb
1 require 'rexml/document'
2 require 'uri/common'
3
4 class SlashdotPlugin < Plugin
5   include REXML
6   def help(plugin, topic="")
7     "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.)"
8   end
9   
10   def search_slashdot(m, params)
11    max = params[:limit].to_i
12    search = params[:search].to_s
13
14     begin
15       xml = @bot.httputil.get_cached(URI.parse("http://slashdot.org/search.pl?content_type=rss&query=#{URI.escape(search)}"))
16     rescue URI::InvalidURIError, URI::BadURIError => e
17       m.reply "illegal search string #{search}"
18       return
19     end
20     unless xml
21       m.reply "search for #{search} failed"
22       return
23     end
24     debug xml.inspect
25     begin
26       doc = Document.new xml
27     rescue REXML::ParseException => e
28       warning e.inspect
29       m.reply "couldn't parse output XML: #{e.class}"
30       return
31     end
32     unless doc
33       m.reply "search for #{search} failed"
34       return
35     end
36     debug doc.inspect
37     max = 8 if max > 8
38     done = 0
39     doc.elements.each("*/item") {|e|
40       desc = e.elements["title"].text
41       desc.gsub!(/(.{150}).*/, '\1..')
42       reply = sprintf("%s | %s", e.elements["link"].text, desc)
43       m.reply reply
44       done += 1
45       break if done >= max
46     }
47     unless done > 0
48       m.reply "search for #{search} failed"
49     end
50   end
51   
52   def slashdot(m, params)
53     debug params.inspect
54     max = params[:limit].to_i
55     debug "max is #{max}"
56     xml = @bot.httputil.get_cached(URI.parse("http://slashdot.org/slashdot.xml"))
57     unless xml
58       m.reply "slashdot news parse failed"
59       return
60     end
61     doc = Document.new xml
62     unless doc
63       m.reply "slashdot news parse failed (invalid xml)"
64       return
65     end
66     done = 0
67     oneline = false
68     if max < 0
69       max = (0 - max)
70       oneline = true
71     end
72     max = 8 if max > 8
73     matches = Array.new
74     doc.elements.each("*/story") {|e|
75       matches << [ e.elements["title"].text, 
76                    e.elements["author"].text, 
77                    e.elements["time"].text.gsub(/\d{4}-(\d{2})-(\d{2})/, "\\2/\\1").gsub(/:\d\d$/, "") ]
78       done += 1
79       break if done >= max
80     } 
81     if oneline
82       m.reply matches.collect{|mat| mat[0]}.join(" | ")
83     else
84       matches.each {|mat|
85         m.reply sprintf("%36s | %8s | %8s", mat[0][0,36], mat[1][0,8], mat[2])
86       }
87     end
88   end
89 end
90 plugin = SlashdotPlugin.new
91 plugin.map 'slashdot search :limit *search', :action => 'search_slashdot',
92            :defaults => {:limit => 4}, :requirements => {:limit => /^-?\d+$/}
93 plugin.map 'slashdot :limit', :defaults => {:limit => 4},
94                               :requirements => {:limit => /^-?\d+$/}