From d9f9245ad30cf0bb493be07cc05bb7ed5d672a3f Mon Sep 17 00:00:00 2001 From: kou Date: Fri, 18 Jun 2004 16:13:01 +0000 Subject: * sample/rss/tdiary_plugin/rss-recent.rb: added more information. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6474 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 + sample/rss/tdiary_plugin/rss-recent.rb | 171 +++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6138281a9c..2b4fa6f925 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sat Jun 19 01:10:12 2004 Kouhei Sutou + + * sample/rss/tdiary_plugin/rss-recent.rb: added more information. + Fri Jun 18 23:12:22 2004 Nobuyoshi Nakada * eval.c (proc_save_safe_level, rb_set_safe_level, safe_setter): limit diff --git a/sample/rss/tdiary_plugin/rss-recent.rb b/sample/rss/tdiary_plugin/rss-recent.rb index 103d3358b0..8ba8ed0b52 100644 --- a/sample/rss/tdiary_plugin/rss-recent.rb +++ b/sample/rss/tdiary_plugin/rss-recent.rb @@ -7,20 +7,20 @@ # cache_time: cache time(second) of RSS(60*60) # # -# Copyright (c) 2003 Kouhei Sutou +# Copyright (c) 2003-2004 Kouhei Sutou # Distributed under the GPL # require "rss/rss" RSS_RECENT_FIELD_SEPARATOR = "\0" -RSS_RECENT_VERSION = "0.0.2" -RSS_RECENT_CONTENT_TYPE = { +RSS_RECENT_ENTRY_SEPARATOR = "\1" +RSS_RECENT_VERSION = "0.0.4" +RSS_RECENT_HTTP_HEADER = { "User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " << - "Using RSS parser version is #{::RSS::VERSION}." + "Using RSS parser version is #{::RSS::VERSION}.", } - def rss_recent(url, max=5, cache_time=3600) cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}" @@ -29,20 +29,26 @@ def rss_recent(url, max=5, cache_time=3600) return '' unless test(?r, cache_file) rv = "
    \n" - File.open(cache_file) do |f| - max.to_i.times do - title = f.gets(RSS_RECENT_FIELD_SEPARATOR) - break if title.nil? - rv << '
  • ' - link = f.gets(RSS_RECENT_FIELD_SEPARATOR) - unless link.nil? - rv << %Q!! - end - rv << CGI::escapeHTML(title.chomp(RSS_RECENT_FIELD_SEPARATOR)) - rv << '' unless link.nil? - rv << "
  • \n" - end + + i = 0 + rss_recent_read_from_cache(cache_file).each do |title, url, time| + break if i >= max + next if title.nil? + rv << '
  • ' + rv << %Q[] + unless url.nil? + rv << %Q[] + end + rv << CGI::escapeHTML(title) + rv << '' unless url.nil? + rv << "(#{rss_recent_modified(time)})" + rv << %Q[] + rv << "
  • \n" + i += 1 end + rv << "
\n" rv @@ -52,21 +58,27 @@ class InvalidResourceError < StandardError; end def rss_recent_cache_rss(url, cache_file, cache_time) - begin - raise if Time.now > File.mtime(cache_file) + cache_time - rescue + cached_time = nil + cached_time = File.mtime(cache_file) if File.exist?(cache_file) + + if cached_time.nil? or Time.now > cached_time + cache_time + require 'time' + require 'open-uri' require 'net/http' require 'uri/generic' require 'rss/parser' require 'rss/1.0' require 'rss/2.0' + require 'rss/dublincore' begin - ur = URI.parse(url) + uri = URI.parse(url) - raise URI::InvalidURIError if ur.scheme != "http" + raise URI::InvalidURIError if uri.scheme != "http" - rss_source = rss_recent_fetch_rss(ur) + rss_source = rss_recent_fetch_rss(uri, cached_time) + + raise InvalidResourceError if rss_source.nil? # parse RSS rss = ::RSS::Parser.parse(rss_source, false) @@ -78,8 +90,11 @@ def rss_recent_cache_rss(url, cache_file, cache_time) rescue ::RSS::UnknownConversionMethodError end - tlary = rss.items.collect{|item| [item.title, item.link]} - rss_recent_write_to_cache(cache_file, tlary) + rss_infos = rss.items.collect do |item| + rss_recent_pubDate_to_dc_date(item) + [item.title, item.link, item.dc_date] + end + rss_recent_write_to_cache(cache_file, rss_infos) rescue URI::InvalidURIError rss_recent_write_to_cache(cache_file, [['Invalid URI', url]]) @@ -90,29 +105,107 @@ def rss_recent_cache_rss(url, cache_file, cache_time) end -def rss_recent_fetch_rss(uri) - rss = '' +def rss_recent_fetch_rss(uri, cache_time) + rss = nil begin - Net::HTTP.start(uri.host, uri.port || 80) do |http| - path = uri.path - path << "?#{uri.query}" if uri.query - req = http.request_get(path) - raise InvalidResourceError unless req.code == "200" - rss << req.body + uri.open(rss_recent_http_header(cache_time)) do |f| + case f.status.first + when "200" + rss = f.read + # STDERR.puts "Got RSS of #{uri}" + when "304" + # not modified + # STDERR.puts "#{uri} does not modified" + else + raise InvalidResourceError + end end - rescue TimeoutError, SocketError + rescue TimeoutError, SocketError, StandardError, + SecurityError # occured in redirect raise InvalidResourceError end rss end -def rss_recent_write_to_cache(cache_file, array_of_titles_and_links) +def rss_recent_http_header(cache_time) + header = RSS_RECENT_HTTP_HEADER.dup + if cache_time.respond_to?(:rfc2822) + header["If-Modified-Since"] = cache_time.rfc2822 + end + header +end + +def rss_recent_write_to_cache(cache_file, rss_infos) File.open(cache_file, 'w') do |f| f.flock(File::LOCK_EX) - array_of_titles_and_links.each do |title, link| - f << "#{title}#{RSS_RECENT_FIELD_SEPARATOR}" - f << "#{link}#{RSS_RECENT_FIELD_SEPARATOR}" + rss_infos.each do |info| + f << info.join(RSS_RECENT_FIELD_SEPARATOR) + f << RSS_RECENT_ENTRY_SEPARATOR end f.flock(File::LOCK_UN) end end + +def rss_recent_read_from_cache(cache_file) + require 'time' + infos = [] + File.open(cache_file) do |f| + while info = f.gets(RSS_RECENT_ENTRY_SEPARATOR) + info = info.chomp(RSS_RECENT_ENTRY_SEPARATOR) + infos << info.split(RSS_RECENT_FIELD_SEPARATOR) + end + end + infos.collect do |title, url, time| + [ + rss_recent_convert(title), + rss_recent_convert(url), + rss_recent_convert(time) {|time| Time.parse(time)}, + ] + end +end + +def rss_recent_convert(str) + if str.nil? or str.empty? + nil + else + if block_given? + yield str + else + str + end + end +end + +# from RWiki +def rss_recent_modified(t) + return '-' unless t + dif = (Time.now - t).to_i + dif = dif / 60 + return "#{dif}m" if dif <= 60 + dif = dif / 60 + return "#{dif}h" if dif <= 24 + dif = dif / 24 + return "#{dif}d" +end + +# from RWiki +def rss_recent_modified_class(t) + return 'dangling' unless t + dif = (Time.now - t).to_i + dif = dif / 60 + return "modified-hour" if dif <= 60 + dif = dif / 60 + return "modified-today" if dif <= 24 + dif = dif / 24 + return "modified-month" if dif <= 30 + return "modified-year" if dif <= 365 + return "modified-old" +end + +def rss_recent_pubDate_to_dc_date(target) + if target.respond_to?(:pubDate) + class << target + alias_method(:dc_date, :pubDate) + end + end +end -- cgit v1.2.3