4
# はてなブックマーク (http://b.hatena.ne.jp/) のコメントを該当日付に貼り付けるtDiaryプラグイン
5
# 改造版rss_recent Version 0.0.5i2と共に使用する
8
# Author: ishinao <ishinao@ishinao.net>
11
add_body_leave_proc(Proc.new do |date|
12
if @mode == 'day' or @mode == 'latest'
13
diary = @diaries[date.strftime('%Y%m%d')]
16
diary.each_section do |para|
17
td_url = "http://tdiary.ishinao.net/#{date.strftime('%Y%m%d')}.html%23p#{'%02d' % pnum}"
18
hb_url = "http://b.hatena.ne.jp/entry/#{td_url}"
19
rss_url = "http://b.hatena.ne.jp/entry/rss/#{td_url}"
21
template_head = %Q[<div class="section">\n<h3><a href="#{CGI.escapeHTML(hb_url)}">はてなブックマークの反応</a></h3>\n<ul class="hb_footer">\n]
22
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>'
23
template_foot = "</ul>\n</div>\n"
26
if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d')
27
cache_time = 3600 * 12;
29
hbsrc << hb_footer(rss_url, 50, cache_time, template_head, template_list, template_foot)
38
# rss-recent.rb: RSS recent plugin
40
# rss_recnet: show recnet list from RSS
41
# parameters (default):
43
# max: max of list itmes(5)
44
# cache_time: cache time(second) of RSS(60*60)
45
# template_head: rendering header part
46
# template_list: rendering RSS item part(with loop)
47
# template_foot: rendering footer part
49
# Copyright (c) 2003-2004 Kouhei Sutou <kou@cozmixng.org>
50
# Distributed under the GPL
52
# Modified using template string and content:encoded
53
# Version 0.0.5i2 by ishinao <ishinao@ishinao.net>
58
RSS_RECENT_FIELD_SEPARATOR = "\0"
59
RSS_RECENT_ENTRY_SEPARATOR = "\1"
60
RSS_RECENT_VERSION = "0.0.5i2"
61
RSS_RECENT_HTTP_HEADER = {
62
"User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " <<
63
"Using RSS parser version is #{::RSS::VERSION}.",
66
def hb_footer(url, max = 5, cache_time = 3600, \
67
template_head = "<ul>\n", \
68
template_list = '<li><span class="#{hb_footer_modified_class(time)}"><a href="#{CGI.escapeHTML(url)}" title="#{CGI.escapeHTML(title)}">#{CGI::escapeHTML(title)}</a></span></li>\n', \
69
template_foot = "</ul>\n")
72
cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}"
74
hb_footer_cache_rss(url, cache_file, cache_time.to_i)
76
return '' unless test(?r, cache_file)
81
hb_footer_read_from_cache(cache_file).each do |title, url, time, content, description|
83
next if (url.nil? or title.nil?)
84
rv << eval('%Q[' + template_list + ']')
97
class InvalidResourceError < StandardError; end
99
def hb_footer_cache_rss(url, cache_file, cache_time)
102
cached_time = File.mtime(cache_file) if File.exist?(cache_file)
104
if cached_time.nil? or Time.now > cached_time + cache_time
108
require 'uri/generic'
112
require 'rss/dublincore'
113
require 'rss/content'
118
raise URI::InvalidURIError if uri.scheme != "http"
120
rss_source = hb_footer_fetch_rss(uri, cached_time)
122
raise InvalidResourceError if rss_source.nil?
125
rss = ::RSS::Parser.parse(rss_source, false)
126
raise ::RSS::Error if rss.nil?
130
rss.output_encoding = @conf.charset || charset
131
rescue ::RSS::UnknownConversionMethodError
134
rss_infos = rss.items.collect do |item|
135
hb_footer_pubDate_to_dc_date(item)
136
[item.title, item.link, item.dc_date, item.content_encoded, item.description]
138
hb_footer_write_to_cache(cache_file, rss_infos)
140
rescue URI::InvalidURIError
141
hb_footer_write_to_cache(cache_file, [['Invalid URI', url]])
142
rescue InvalidResourceError, ::RSS::Error
143
# hb_footer_write_to_cache(cache_file, [['Invalid Resource', url]])
144
# when cannot get valid RSS, use old cache
150
def hb_footer_fetch_rss(uri, cache_time)
153
uri.open(hb_footer_http_header(cache_time)) do |f|
157
# STDERR.puts "Got RSS of #{uri}"
160
# STDERR.puts "#{uri} does not modified"
162
raise InvalidResourceError
165
rescue TimeoutError, SocketError, StandardError,
166
SecurityError # occured in redirect
167
raise InvalidResourceError
172
def hb_footer_http_header(cache_time)
173
header = RSS_RECENT_HTTP_HEADER.dup
174
if cache_time.respond_to?(:rfc2822)
175
header["If-Modified-Since"] = cache_time.rfc2822
180
def hb_footer_write_to_cache(cache_file, rss_infos)
181
File.open(cache_file, 'w') do |f|
182
f.flock(File::LOCK_EX)
183
rss_infos.each do |info|
184
f << info.join(RSS_RECENT_FIELD_SEPARATOR)
185
f << RSS_RECENT_ENTRY_SEPARATOR
187
f.flock(File::LOCK_UN)
191
def hb_footer_read_from_cache(cache_file)
194
File.open(cache_file) do |f|
195
while info = f.gets(RSS_RECENT_ENTRY_SEPARATOR)
196
info = info.chomp(RSS_RECENT_ENTRY_SEPARATOR)
197
infos << info.split(RSS_RECENT_FIELD_SEPARATOR)
200
infos.collect do |title, url, time, content, description|
202
hb_footer_convert(title),
203
hb_footer_convert(url),
204
hb_footer_convert(time) {|time| Time.parse(time)},
205
hb_footer_convert(content),
206
hb_footer_convert(description),
211
def hb_footer_convert(str)
212
if str.nil? or str.empty?
224
def hb_footer_modified(t)
226
dif = (Time.now - t).to_i
228
return "#{dif}m" if dif <= 60
230
return "#{dif}h" if dif <= 24
236
def hb_footer_modified_class(t)
237
return 'dangling' unless t
238
dif = (Time.now - t).to_i
240
return "modified-hour" if dif <= 60
242
return "modified-today" if dif <= 24
244
return "modified-month" if dif <= 30
245
return "modified-year" if dif <= 365
246
return "modified-old"
249
def hb_footer_pubDate_to_dc_date(target)
250
if target.respond_to?(:pubDate)
252
alias_method(:dc_date, :pubDate)