# show my hot-entry in Hatena::Bookmark
#
# usage:
# <%= my_hotentry %>
#
# Copyright (c) MATSUOKA Kohei
# Distributed under the GPL
#
require 'uri'
require 'open-uri'
require 'rexml/document'
require 'pstore'
require 'timeout'
# 人気の日記のソート順(新着順: eid, 注目順: hot, 人気順: count)
@conf ||= {}
@conf['my_hotentry.sort'] ||= 'hot'
class MyHotEntry
def initialize(dbfile)
@dbfile = dbfile
end
# 人気の日記の一覧を返す
def entries
r = nil
PStore.new(@dbfile).transaction(true) do |db|
r = db[:entries]
end
r || []
end
# 人気の日記一覧を取得する
def update(base_url, options = {})
options[:title] ||= ''
options[:sort] ||= 'eid'
options[:threshold] ||= 3
# RSSを取得
rss = nil
rss_url = 'http://b.hatena.ne.jp/entrylist?mode=rss&url='
rss_url << URI.escape(base_url, /[^-.!~*'()\w]/n)
rss_url << "&sort=#{options[:sort]}&threshold=#{options[:threshold]}"
begin
Timeout.timeout(5) do
# convert Tempfile to String because REXML can't accept Tempfile
open(rss_url) do |f|
rss = REXML::Document.new(f.readlines.join("\n"))
end
end
rescue TimeoutError => e
return
end
# RDF/itemが空ならDBを更新しない (たまにitemが空のデータが返るため)
return if rss.elements['rdf:RDF/item'].nil?
# キャッシュに格納する
PStore.new(@dbfile).transaction do |db|
db[:entries] = []
rss.elements.each('rdf:RDF/item') do |item|
url = item.elements['link'].text
title = item.elements['title'].text
# リンク先のタイトルからサイト名と日付を取り除く
title.sub!(/(?: - )?#{options[:html_title]}(?: - )?/, '')
title.sub!(/\(\d{4}-\d{2}-\d{2}\)/, '')
db[:entries].push({ :url => url, :title => title })
end
end
end
end
# キャッシュファイルのパスを取得する
def my_hotentry_dbfile
cache_dir = "#{@cache_path}/hatena"
Dir::mkdir(cache_dir) unless File::directory?(cache_dir)
"#{cache_dir}/my_hotentry.dat"
end
# 人気の日記一覧を表示する
def my_hotentry(count = 5)
dbfile = my_hotentry_dbfile
hotentry = MyHotEntry.new(dbfile)
r = %Q|
|
r << %Q|\n|
end
# 人気の日記一覧を更新する
def my_hotentry_update
dbfile = my_hotentry_dbfile
hotentry = MyHotEntry.new(dbfile)
hotentry.update(@conf.base_url,
:html_title => @conf.html_title,
:sort => @conf['my_hotentry.sort'])
end
if __FILE__ == $0
# コマンドラインから実行した場合
# tdiary.conf に base_url を設定しないと動作しない
begin
require 'tdiary'
rescue LoadError
STDERR.puts "tdiary.rb not found."
STDERR.puts "please execute in tdiary base directory"
exit 1
end
cgi = CGI::new
@conf = TDiary::Config::new(cgi)
@cache_path = @conf.cache_path || "#{@conf.data_path}cache"
my_hotentry_update
puts my_hotentry
else
# 人気の日記一覧を取得する (日記更新時)
add_update_proc do
# ツッコミ時は実行しない
if @mode == 'append' or @mode == 'replace'
begin
my_hotentry_update
rescue
end
end
end
end