4
# はてなブックマーク (http://b.hatena.ne.jp/) のコメントを該当セクションに貼り付けるtDiaryプラグイン
5
# 改造版rss_recent Version 0.0.5i2と共に使用する
8
# Author: ishinao <ishinao@ishinao.net>
11
add_section_leave_proc do |date, index|
12
td_url = "http://tdiary.ishinao.net/#{date.strftime('%Y%m%d')}.html%23p#{'%02d' % index}"
13
hb_url = "http://b.hatena.ne.jp/entry/#{td_url}"
14
rss_url = "http://b.hatena.ne.jp/entry/rss/#{td_url}"
16
template_head = %Q[<div class="section">\n<h4>このセクションに対する<a href="#{CGI.escapeHTML(hb_url)}">はてブ</a></h4>\n<ul class="hb_footer">\n]
17
template_list = '<li><span class="date">#{time.strftime("%Y年%m月%d日")}</span> <span class="hatenaid"><a href="#{CGI.escapeHTML(url)}">#{CGI.escapeHTML(title)}</a></span> <span class="comment">#{CGI.escapeHTML(description.to_s)}</span></li>'
18
template_foot = "</ul>\n</div>\n"
21
if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d')
22
cache_time = 3600 * 12;
24
hb_footer4sec(rss_url, 50, cache_time, template_head, template_list, template_foot)
27
# rss-recent.rb: RSS recent plugin
29
# rss_recnet: show recnet list from RSS
30
# parameters (default):
32
# max: max of list itmes(5)
33
# cache_time: cache time(second) of RSS(60*60)
34
# template_head: rendering header part
35
# template_list: rendering RSS item part(with loop)
36
# template_foot: rendering footer part
38
# Copyright (c) 2003-2004 Kouhei Sutou <kou@cozmixng.org>
39
# Distributed under the GPL
41
# Modified using template string and content:encoded
42
# Version 0.0.5i2 by ishinao <ishinao@ishinao.net>
47
RSS_RECENT_FIELD_SEPARATOR = "\0"
48
RSS_RECENT_ENTRY_SEPARATOR = "\1"
49
RSS_RECENT_VERSION = "0.0.5i2"
50
RSS_RECENT_HTTP_HEADER = {
51
"User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " <<
52
"Using RSS parser version is #{::RSS::VERSION}.",
55
def hb_footer4sec(url, max = 5, cache_time = 3600, \
56
template_head = "<ul>\n", \
57
template_list = '<li><span class="#{hb_footer4sec_modified_class(time)}"><a href="#{CGI.escapeHTML(url)}" title="#{CGI.escapeHTML(title)}">#{CGI::escapeHTML(title)}</a></span></li>\n', \
58
template_foot = "</ul>\n")
61
cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}"
63
hb_footer4sec_cache_rss(url, cache_file, cache_time.to_i)
65
return '' unless test(?r, cache_file)
70
hb_footer4sec_read_from_cache(cache_file).each do |title, url, time, content, description|
72
next if (url.nil? or title.nil?)
73
rv << eval('%Q[' + template_list + ']')
86
class InvalidResourceError < StandardError; end
88
def hb_footer4sec_cache_rss(url, cache_file, cache_time)
91
cached_time = File.mtime(cache_file) if File.exist?(cache_file)
93
if cached_time.nil? or Time.now > cached_time + cache_time
101
require 'rss/dublincore'
102
require 'rss/content'
107
raise URI::InvalidURIError if uri.scheme != "http"
109
rss_source = hb_footer4sec_fetch_rss(uri, cached_time)
111
raise InvalidResourceError if rss_source.nil?
114
rss = ::RSS::Parser.parse(rss_source, false)
115
raise ::RSS::Error if rss.nil?
119
rss.output_encoding = @conf.charset || charset
120
rescue ::RSS::UnknownConversionMethodError
123
rss_infos = rss.items.collect do |item|
124
hb_footer4sec_pubDate_to_dc_date(item)
125
[item.title, item.link, item.dc_date, item.content_encoded, item.description]
127
hb_footer4sec_write_to_cache(cache_file, rss_infos)
129
rescue URI::InvalidURIError
130
hb_footer4sec_write_to_cache(cache_file, [['Invalid URI', url]])
131
rescue InvalidResourceError, ::RSS::Error
132
# hb_footer4sec_write_to_cache(cache_file, [['Invalid Resource', url]])
133
# when cannot get valid RSS, use old cache
139
def hb_footer4sec_fetch_rss(uri, cache_time)
142
uri.open(hb_footer4sec_http_header(cache_time)) do |f|
146
# STDERR.puts "Got RSS of #{uri}"
149
# STDERR.puts "#{uri} does not modified"
151
raise InvalidResourceError
154
rescue TimeoutError, SocketError, StandardError,
155
SecurityError # occured in redirect
156
raise InvalidResourceError
161
def hb_footer4sec_http_header(cache_time)
162
header = RSS_RECENT_HTTP_HEADER.dup
163
if cache_time.respond_to?(:rfc2822)
164
header["If-Modified-Since"] = cache_time.rfc2822
169
def hb_footer4sec_write_to_cache(cache_file, rss_infos)
170
File.open(cache_file, 'w') do |f|
171
f.flock(File::LOCK_EX)
172
rss_infos.each do |info|
173
f << info.join(RSS_RECENT_FIELD_SEPARATOR)
174
f << RSS_RECENT_ENTRY_SEPARATOR
176
f.flock(File::LOCK_UN)
180
def hb_footer4sec_read_from_cache(cache_file)
183
File.open(cache_file) do |f|
184
while info = f.gets(RSS_RECENT_ENTRY_SEPARATOR)
185
info = info.chomp(RSS_RECENT_ENTRY_SEPARATOR)
186
infos << info.split(RSS_RECENT_FIELD_SEPARATOR)
189
infos.collect do |title, url, time, content, description|
191
hb_footer4sec_convert(title),
192
hb_footer4sec_convert(url),
193
hb_footer4sec_convert(time) {|time| Time.parse(time)},
194
hb_footer4sec_convert(content),
195
hb_footer4sec_convert(description),
200
def hb_footer4sec_convert(str)
201
if str.nil? or str.empty?
213
def hb_footer4sec_modified(t)
215
dif = (Time.now - t).to_i
217
return "#{dif}m" if dif <= 60
219
return "#{dif}h" if dif <= 24
225
def hb_footer4sec_modified_class(t)
226
return 'dangling' unless t
227
dif = (Time.now - t).to_i
229
return "modified-hour" if dif <= 60
231
return "modified-today" if dif <= 24
233
return "modified-month" if dif <= 30
234
return "modified-year" if dif <= 365
235
return "modified-old"
238
def hb_footer4sec_pubDate_to_dc_date(target)
239
if target.respond_to?(:pubDate)
241
alias_method(:dc_date, :pubDate)