0
@@ -3,97 +3,153 @@ require 'net/http'
0
- c = File.join(CACHE_DIR, uri.tr(':/','_'))
0
+ def fetch_rss(uri, cache_time)
0
+ c = File.join(ActionController::Base.page_cache_directory, uri.tr(':/','_'))
0
+ if (cached_feed = feed_for(IO.read(c)) rescue nil)
0
+ return cached_feed if File.mtime(c) > (Time.now - cache_time)
0
since = File.mtime(c).httpdate
0
since = "1970-01-01 00:00:00"
0
- http = Net::HTTP.start(u.host, u.port)
0
- answer = http.get("#{u}", { "If-Modified-Since" => since })
0
+ http = Net::HTTP.start(u.host, u.port)
0
+ answer = http.get("#{u.path}", { "If-Modified-Since" => since })
0
+ feed = feed_for(answer.body)
0
- File.new(c, 'w').write(answer.body)
0
+ File.open(c,'w+') { |fp| fp << answer.body }
0
+ r
aise StandardError, "#{answer.code} #{answer.message}"0
- FeedParser::Feed.new(fetch(uri))
0
+ FeedParser::Feed.new(str)
0
- tag "feed:items" do |tag|
0
- attr = tag.attr.symbolize_keys
0
- items = fetch_rss(attr[:url]).items
0
- items = items.slice(0,attr[:limit].to_i)
0
- tag.locals.item = item
0
- tag "feed:title" do |tag|
0
- tag "feed:link" do |tag|
0
- options = tag.attr.dup
0
- attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
0
- attributes = " #{attributes}" unless attributes.empty?
0
- href = tag.locals.item.link
0
- text = tag.double? ? tag.expand : tag.locals.item.title
0
- %{<a href="#{href}"#{attributes}>#{text}</a>}
0
+ # feed:items tag attributes
0
+ # =========================
0
+ # url: URL of the feed. No relative URLs, must be absolute.
0
+ # cache_time: length of time to cache the feed before seeing if it's been updated
0
+ # order: works just like SQL 'ORDER BY' clauses, e.g. order='creator date desc'
0
+ # orders first by creator ascending, then date descending
0
+ # limit: only return the first x items (after any ordering)
0
+ tag "feed:items" do |tag|
0
+ attr = tag.attr.symbolize_keys
0
+ items = fetch_rss(attr[:url], attr[:cache_time].to_i || 900).items
0
+ return "<!-- RssReader error: #{$!} -->"
0
+ (tokens = attr[:order].split.map {|t| t.downcase}.reverse).each_index do |i|
0
+ if ['title','link','content','date','creator'].include? t
0
+ items.sort! {|x,y| (tokens[i-1] == 'desc') ? (y.send(t) <=> x.send(t)) : (x.send(t) <=> y.send(t)) }
0
+ items = items.slice(0,attr[:limit].to_i)
0
+ items.each_index do |i|
0
+ tag.locals.item = items[i]
0
+ tag.locals.last_item = items[i-1] if i > 0
0
+ #Contents of feed:header tag block are only rendered if item.send(attr[:for])
0
+ #is different from the last item. E.g. use like this in an ordered-by-creator feed:
0
+ # <r:feed:header for="creator">
0
+ # <h2><r:feed:creator /></h2>
0
+ # for='date' chunks by days (i.e. not hours or seconds, thankfully)
0
+ tag "feed:header" do |tag|
0
+ attr = tag.attr.symbolize_keys
0
+ grouping = attr[:for] || 'date'
0
+ unless tag.locals.last_item
0
+ if ['title','link','content','creator'].include? grouping
0
+ tag.expand if tag.locals.item.send(grouping) != tag.locals.last_item.send(grouping)
0
+ elsif grouping == 'date'
0
+ tag.expand if tag.locals.item.send(grouping).strftime("%j%Y") != tag.locals.last_item.send(grouping).strftime("%j%Y")
0
+ tag "feed:title" do |tag|
0
- tag "feed:content" do |tag|
0
- attr = tag.attr.symbolize_keys
0
- result = tag.locals.item.content
0
- l = tag.locals.item.content.size()
0
- maxl = attr[:max_length].to_i
0
- result = tag.locals.item.content[0..maxl] + ' ...'
0
+ tag "feed:link" do |tag|
0
+ options = tag.attr.dup
0
+ attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
0
+ attributes = " #{attributes}" unless attributes.empty?
0
+ href = tag.locals.item.link
0
+ text = tag.double? ? tag.expand : tag.locals.item.title
0
+ %{<a href="#{href}"#{attributes}>#{text}</a>}
0
- if result and attr[:no_html]
0
- result = result.gsub(/<[^>]+>/, '')
0
+ # feed:content tag attributes
0
+ # ===========================
0
+ # max_length: no-nonsense truncation
0
+ # no_p: takes out just the enclosing <p></p> tags that FeedParser puts in
0
+ # no_html: takes out *all* html
0
+ tag "feed:content" do |tag|
0
+ attr = tag.attr.symbolize_keys
0
+ result = tag.locals.item.content
0
+ l = tag.locals.item.content.size()
0
+ maxl = attr[:max_length].to_i
0
+ result = tag.locals.item.content[0..maxl] + ' ...'
0
+ result = result.gsub(/\A<p>(.*)<\/p>\z/m,'\1') if attr[:no_p]
0
+ result = result.gsub(/<[^>]+>/, '') if attr[:no_html]
0
- tag "feed:date" do |tag|
0
- # Could change this default format string to '%b %d' if you prefer
0
- format = (tag.attr['format'] || '%A, %B %d, %Y')
0
- if date = tag.locals.item.date
0
+ tag "feed:date" do |tag|
0
+ # Could change this default format string to '%b %d' if you prefer
0
+ format = (tag.attr['format'] || '%A, %B %d, %Y')
0
+ if date = tag.locals.item.date
0
- tag "feed:creator" do |tag|
0
- tag.locals.item.creator
0
+ tag "feed:creator" do |tag|
0
+ tag.locals.item.creator
Comments
No one has commented yet.