root/platform/tdiary/plugin/my_hotentry.rb

Revision 15252, 4.0 kB (checked in by hsbt, 5 months ago)

add div and span.

Line 
1# show my hot-entry in Hatena::Bookmark
2#
3# usage:
4#   <%= my_hotentry %>
5#
6# Copyright (c) MATSUOKA Kohei <http://www.machu.jp/>
7# Distributed under the GPL
8#
9require 'uri'
10require 'open-uri'
11require 'rexml/document'
12require 'pstore'
13require 'timeout'
14
15# 人気の日記のソート順(新着順: eid,  注目順: hot, 人気順: count)
16@conf ||= {}
17@conf['my_hotentry.sort'] ||= 'hot'
18
19class MyHotEntry
20  def initialize(dbfile)
21    @dbfile = dbfile
22  end
23
24  # 人気の日記の一覧を返す
25  def entries
26    r = nil
27    PStore.new(@dbfile).transaction(true) do |db|
28      r = db[:entries]
29    end
30    r || []
31  end
32
33  # 人気の日記一覧を取得する
34  def update(base_url, options = {})
35    options[:title] ||= ''
36    options[:sort] ||= 'eid'
37    options[:threshold] ||= 3
38
39    # RSSを取得
40    rss = nil
41    rss_url = 'http://b.hatena.ne.jp/entrylist?mode=rss&url='
42    rss_url << URI.escape(base_url, /[^-.!~*'()\w]/n)
43    rss_url << "&sort=#{options[:sort]}&threshold=#{options[:threshold]}"
44    begin
45      timeout(5) do
46        # convert Tempfile to String because REXML can't accept Tempfile
47        open(rss_url) do |f|
48          rss = REXML::Document.new(f.readlines.join("\n"))
49        end
50      end
51    rescue TimeoutError => e
52      return
53    end
54    # RDF/itemが空ならDBを更新しない (たまにitemが空のデータが返るため)
55    return if rss.elements['rdf:RDF/item'].nil?
56
57    # キャッシュに格納する
58    PStore.new(@dbfile).transaction do |db|
59      db[:entries] = []
60      rss.elements.each('rdf:RDF/item') do |item|
61        url = item.elements['link'].text
62        title = item.elements['title'].text
63        # リンク先のタイトルからサイト名と日付を取り除く
64        title.sub!(/( - )?#{options[:html_title]}( - )?/, '')
65        title.sub!(/\(\d{4}-\d{2}-\d{2}\)/, '')
66        db[:entries].push({ :url => url, :title => title })
67      end
68    end
69  end
70end
71
72# キャッシュファイルのパスを取得する
73def my_hotentry_dbfile
74  cache_dir = "#{@cache_path}/hatena"
75  Dir::mkdir(cache_dir) unless File::directory?(cache_dir)
76  "#{cache_dir}/my_hotentry.dat"
77end
78
79# 人気の日記一覧を表示する
80def my_hotentry(count = 5)
81  dbfile = my_hotentry_dbfile
82  hotentry = MyHotEntry.new(dbfile)
83  r = %Q|<ul class="rss-recent">\n|
84  hotentry.entries[0...count].each do |entry|
85    entry_link = %Q|<a href="#{entry[:url]}">#{CGI::escapeHTML(entry[:title])}</a>|
86    escape_url = entry[:url].gsub(/#/, '%23')
87    b_image = "http://b.hatena.ne.jp/entry/image/#{escape_url}"
88    b_link  = "http://b.hatena.ne.jp/entry/#{escape_url}"
89    b_title = "このエントリを含むはてなブックマーク"
90    bookmark_link = %Q|<a href="#{b_link}" title="#{b_title}"><img border="0" src="#{b_image}"></a>|
91    r << "\t\t<li>#{entry_link} #{bookmark_link}</li>"
92  end
93  r << %Q|</ul>|
94  r << %Q|<div class="iddy"><span class="iddy-powered">\tPowered by <a href="http://b.hatena.ne.jp/entrylist?url=#{@conf.base_url}&sort=#{@conf['my_hotentry.sort']}">Hatena Bookmark</a></span></div>\n|
95end
96
97# 人気の日記一覧を更新する
98def my_hotentry_update
99  dbfile = my_hotentry_dbfile
100  hotentry = MyHotEntry.new(dbfile)
101  hotentry.update(@conf.base_url,
102                 :html_title => @conf.html_title,
103                 :sort => @conf['my_hotentry.sort'])
104end
105
106if __FILE__ == $0
107  # コマンドラインから実行した場合
108  # tdiary.conf に base_url を設定しないと動作しない
109  begin
110    require 'tdiary'
111  rescue LoadError
112    STDERR.puts "tdiary.rb not found."
113    STDERR.puts "please execute in tdiary base directory"
114    exit 1
115  end
116  cgi = CGI::new
117  @conf = TDiary::Config::new(cgi)
118  @cache_path = @conf.cache_path || "#{@conf.data_path}cache"
119  my_hotentry_update
120  puts my_hotentry
121else
122  # 人気の日記一覧を取得する (日記更新時)
123  add_update_proc do
124    # ツッコミ時は実行しない
125    if @mode == 'append' or @mode == 'replace'
126      begin
127        my_hotentry_update
128      rescue
129      end
130    end
131  end
132end
Note: See TracBrowser for help on using the browser.