X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=data%2Frbot%2Fplugins%2Frss.rb;h=882a15fbd7c3a5c80c426814044a23d5cfa0f30d;hb=1ea3decbbacd73bf93f52f3ce392914cc924df4f;hp=1bc9b16ecf2e2e007c9f097d8157563edd9a9338;hpb=8bf39f3bca63676117b8174ecb0d394507940570;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/data/rbot/plugins/rss.rb b/data/rbot/plugins/rss.rb index 1bc9b16e..882a15fb 100644 --- a/data/rbot/plugins/rss.rb +++ b/data/rbot/plugins/rss.rb @@ -1,7 +1,12 @@ +#-- vim:sw=2:et +#++ +# # RSS feed plugin for RubyBot # (c) 2004 Stanislav Karchebny # (c) 2005 Ian Monroe # (c) 2005 Mark Kretschmann +# (c) 2006 Giuseppe Bilotta +# # Licensed under MIT License. require 'rss/parser' @@ -54,19 +59,28 @@ class ::RssBlob end def watched_by?(who) - @watchers.include?(who) + # We need to check bot 'who' itself and the String form, because rss + # watches added before the new Irc framework represented watchers as + # Strings whereas they are now Channels. + # + @watchers.include?(who) || @watchers.include?(who.to_s) end def add_watch(who) if watched_by?(who) return nil end - @watchers << who unless watched_by?(who) + # TODO FIXME? should we just store watchers as Strings instead? + # This should then be @watchers << who.downcase + @watchers << who return who end def rm_watch(who) + # See comment to watched_by? + # @watchers.delete(who) + @watchers.delete(who.to_s) end def to_a @@ -94,7 +108,7 @@ class RSSFeedsPlugin < Plugin BotConfig.register BotConfigIntegerValue.new('rss.thread_sleep', :default => 300, :validate => Proc.new{|v| v > 30}, - :desc => "How many characters to use of a RSS item text") + :desc => "How many seconds to sleep before checking RSS feeds again") @@watchThreads = Hash.new @@mutex = Mutex.new @@ -110,6 +124,10 @@ class RSSFeedsPlugin < Plugin rewatch_rss end + def name + "rss" + end + def watchlist @feeds.select { |h, f| f.watched? } end @@ -136,7 +154,7 @@ class RSSFeedsPlugin < Plugin def help(plugin,topic="") case topic when "show" - "rss show #{Bold}handle#{Bold} [#{Bold}limit#{Bold}] : show #{Bold}limit#{Bold} (default: 5, max: 15) entries from rss #{Bold}handle#{Bold}" + "rss show #{Bold}handle#{Bold} [#{Bold}limit#{Bold}] : show #{Bold}limit#{Bold} (default: 5, max: 15) entries from rss #{Bold}handle#{Bold}; #{Bold}limit#{Bold} can also be in the form a..b, to display a specific range of items" when "list" "rss list [#{Bold}handle#{Bold}] : list all rss feeds (matching #{Bold}handle#{Bold})" when "watched" @@ -174,27 +192,55 @@ class RSSFeedsPlugin < Plugin def show_rss(m, params) handle = params[:handle] - limit = params[:limit].to_i - limit = 15 if limit > 15 - limit = 1 if limit <= 0 + lims = params[:limit].to_s.match(/(\d+)(?:..(\d+))?/) + debug lims.to_a.inspect + if lims[2] + ll = [[lims[1].to_i-1,lims[2].to_i-1].min, 0].max + ul = [[lims[1].to_i-1,lims[2].to_i-1].max, 14].min + rev = lims[1].to_i > lims[2].to_i + else + ll = 0 + ul = [[lims[1].to_i-1, 1].max, 14].min + rev = false + end + feed = @feeds.fetch(handle, nil) unless feed m.reply "I don't know any feeds named #{handle}" return end - m.reply("Please wait, querying...") + + m.reply "lemme fetch it..." title = items = nil @@mutex.synchronize { title, items = fetchRss(feed, m) } return unless items - m.reply("Channel : #{title}") - # TODO: optional by-date sorting if dates present - items[0...limit].reverse.each do |item| + + # We sort the feeds in freshness order (newer ones first) + items = freshness_sort(items) + disp = items[ll..ul] + disp.reverse! if rev + + m.reply "Channel : #{title}" + disp.each do |item| printFormattedRss(feed, item, {:places=>[m.replyto],:handle=>nil,:date=>true}) end end + def itemDate(item,ex=nil) + return item.pubDate if item.respond_to?(:pubDate) + return item.date if item.respond_to?(:date) + return ex + end + + def freshness_sort(items) + notime = Time.at(0) + items.sort { |a, b| + itemDate(b, notime) || 0 <=> itemDate(a, notime) || 0 + } + end + def list_rss(m, params) wanted = params[:handle] reply = String.new @@ -335,7 +381,7 @@ class RSSFeedsPlugin < Plugin return feed end - def rewatch_rss(m=nil) + def rewatch_rss(m=nil, params=nil) kill_threads # Read watches from list. @@ -378,7 +424,8 @@ class RSSFeedsPlugin < Plugin } if dispItems.length > 0 debug "Found #{dispItems.length} new items in #{feed}" - dispItems.each { |item| + # When displaying watched feeds, publish them from older to newer + dispItems.reverse.each { |item| @@mutex.synchronize { printFormattedRss(feed, item) } @@ -410,7 +457,24 @@ class RSSFeedsPlugin < Plugin if opts places = opts[:places] if opts.key?(:places) handle = opts[:handle].to_s if opts.key?(:handle) - date = item.pubDate.strftime("%Y/%m/%d %H.%M.%S") + " :: " if (opts.key?(:date) && opts[:date] && item.pubDate) + if opts.key?(:date) && opts[:date] + if item.respond_to?(:pubDate) + if item.pubDate.class <= Time + date = item.pubDate.strftime("%Y/%m/%d %H.%M.%S") + else + date = item.pubDate.to_s + end + elsif item.respond_to?(:date) + if item.date.class <= Time + date = item.date.strftime("%Y/%m/%d %H.%M.%S") + else + date = item.date.to_s + end + else + date = "(no date)" + end + date += " :: " + end end title = "#{Bold}#{item.title.chomp.riphtml}#{Bold}" if item.title desc = item.description.gsub(/\s+/,' ').strip.riphtml.shorten(@bot.config['rss.text_max']) if item.description @@ -440,7 +504,9 @@ class RSSFeedsPlugin < Plugin def fetchRss(feed, m=nil) begin # Use 60 sec timeout, cause the default is too low - xml = @bot.httputil.get_cached(feed.url,60,60) + # Do not use get_cached for RSS until we have proper cache handling + # xml = @bot.httputil.get_cached(feed.url,60,60) + xml = @bot.httputil.get(feed.url,60,60) rescue URI::InvalidURIError, URI::BadURIError => e report_problem("invalid rss feed #{feed.url}", e, m) return @@ -503,7 +569,7 @@ plugin = RSSFeedsPlugin.new plugin.map 'rss show :handle :limit', :action => 'show_rss', - :requirements => {:limit => /^\d+$/}, + :requirements => {:limit => /^\d+(?:\.\.\d+)?$/}, :defaults => {:limit => 5} plugin.map 'rss list :handle', :action => 'list_rss', @@ -533,5 +599,6 @@ plugin.map 'rss unwatch :handle', :action => 'unwatch_rss' plugin.map 'rss rmwatch :handle', :action => 'unwatch_rss' -plugin.map 'rss rewatch :handle', +plugin.map 'rss rewatch', :action => 'rewatch_rss' +