root/platform/tdiary/plugin/hb_footer.rb

Revision 4285, 6.4 kB (checked in by hsbt, 11 months ago)

platform/tdiary/plugin/hb_footer.rb: merge rss-recent.rb.

Line 
1#
2# hb_footer.rb
3#
4# はてなブックマーク (http://b.hatena.ne.jp/) のコメントを該当日付に貼り付けるtDiaryプラグイン
5# 改造版rss_recent Version 0.0.5i2と共に使用する
6#
7# Licence: GPL
8# Author: ishinao <ishinao@ishinao.net>
9#
10
11add_body_leave_proc(Proc.new do |date|
12  if @mode == 'day' or @mode == 'latest'
13    diary = @diaries[date.strftime('%Y%m%d')]
14    pnum = 1
15    hbsrc = ''
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}"
20
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"
24
25      cache_time = 3600;
26      if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d')
27        cache_time = 3600 * 12;
28      end
29      hbsrc << hb_footer(rss_url, 50, cache_time, template_head, template_list, template_foot)
30      pnum+=1
31    end
32    hbsrc
33  else
34    ''
35  end
36end)
37
38# rss-recent.rb: RSS recent plugin
39#
40# rss_recnet: show recnet list from RSS
41#   parameters (default):
42#      url: URL of RSS
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
48#
49# Copyright (c) 2003-2004 Kouhei Sutou <kou@cozmixng.org>
50# Distributed under the GPL
51#
52# Modified using template string and content:encoded
53# Version 0.0.5i2 by ishinao <ishinao@ishinao.net>
54#
55
56require "rss/rss"
57
58RSS_RECENT_FIELD_SEPARATOR = "\0"
59RSS_RECENT_ENTRY_SEPARATOR = "\1"
60RSS_RECENT_VERSION = "0.0.5i2"
61RSS_RECENT_HTTP_HEADER = {
62        "User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " <<
63        "Using RSS parser version is #{::RSS::VERSION}.",
64}
65
66def 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")
70        url.untaint
71
72        cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}"
73
74        hb_footer_cache_rss(url, cache_file, cache_time.to_i)
75       
76        return '' unless test(?r, cache_file)
77
78        rv = template_head
79       
80        i = 0
81        hb_footer_read_from_cache(cache_file).each do |title, url, time, content, description|
82                break if i >= max
83                next if (url.nil? or title.nil?)
84                rv << eval('%Q[' + template_list + ']')
85                i += 1
86        end
87
88        rv << template_foot
89
90        if i > 0
91                rv
92        else
93                ''
94        end
95end
96
97class InvalidResourceError < StandardError; end
98
99def hb_footer_cache_rss(url, cache_file, cache_time)
100
101        cached_time = nil
102        cached_time = File.mtime(cache_file) if File.exist?(cache_file)
103
104        if cached_time.nil? or Time.now > cached_time + cache_time
105                require 'time'
106                require 'open-uri'
107                require 'net/http'
108                require 'uri/generic'
109                require 'rss/parser'
110                require 'rss/1.0'
111                require 'rss/2.0'
112                require 'rss/dublincore'
113                require 'rss/content'
114               
115                begin
116                        uri = URI.parse(url)
117
118                        raise URI::InvalidURIError if uri.scheme != "http"
119
120                        rss_source = hb_footer_fetch_rss(uri, cached_time)
121                       
122                        raise InvalidResourceError if rss_source.nil?
123
124                        # parse RSS
125                        rss = ::RSS::Parser.parse(rss_source, false)
126                        raise ::RSS::Error if rss.nil?
127
128                        # pre processing
129                        begin
130                                rss.output_encoding = @conf.charset || charset
131                        rescue ::RSS::UnknownConversionMethodError
132                        end
133
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]
137                        end
138                        hb_footer_write_to_cache(cache_file, rss_infos)
139
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
145                end
146        end
147
148end
149
150def hb_footer_fetch_rss(uri, cache_time)
151        rss = nil
152        begin
153                uri.open(hb_footer_http_header(cache_time)) do |f|
154                        case f.status.first
155                        when "200"
156                                rss = f.read
157                                # STDERR.puts "Got RSS of #{uri}"
158                        when "304"
159                                # not modified
160                                # STDERR.puts "#{uri} does not modified"
161                        else
162                                raise InvalidResourceError
163                        end
164                end
165        rescue TimeoutError, SocketError, StandardError,
166                        SecurityError # occured in redirect
167                raise InvalidResourceError
168        end
169        rss
170end
171
172def 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
176        end
177        header
178end
179
180def 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
186                end
187                f.flock(File::LOCK_UN)
188        end
189end
190
191def hb_footer_read_from_cache(cache_file)
192        require 'time'
193        infos = []
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)
198                end
199        end
200        infos.collect do |title, url, time, content, description|
201                [
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),
207                ]
208        end
209end
210
211def hb_footer_convert(str)
212        if str.nil? or str.empty?
213                nil
214        else
215                if block_given?
216                        yield str
217                else
218                        str
219                end
220        end
221end
222
223# from RWiki
224def hb_footer_modified(t)
225        return '-' unless t
226        dif = (Time.now - t).to_i
227        dif = dif / 60
228        return "#{dif}m" if dif <= 60
229        dif = dif / 60
230        return "#{dif}h" if dif <= 24
231        dif = dif / 24
232        return "#{dif}d"
233end
234
235# from RWiki
236def hb_footer_modified_class(t)
237        return 'dangling' unless t
238        dif = (Time.now - t).to_i
239        dif = dif / 60
240        return "modified-hour" if dif <= 60
241        dif = dif / 60
242        return "modified-today" if dif <= 24
243        dif = dif / 24
244        return "modified-month" if dif <= 30
245        return "modified-year" if dif <= 365
246        return "modified-old"
247end
248
249def hb_footer_pubDate_to_dc_date(target)
250        if target.respond_to?(:pubDate)
251                class << target
252                        alias_method(:dc_date, :pubDate)
253                end
254        end
255end
Note: See TracBrowser for help on using the browser.