Abcver='$Id: abc.rb,v 1.6 2005-04-23 02:00:11+09 waka Exp waka $'.split(" ")[2]
# http://www.double-red.net/
=begin
nDiary filter
abc.rb(Amazon Bk1 Collaboration)
bk1(http://www.bk1.co.jp) から書誌情報と書影を取得(ファイルダウンロード)、
amazon_shop フィルタ取得情報で書影がない時に書影を補完、表示する。
具体的な動作
(1)amazon_shop キーの (@ISBN:isbn) に反応。
(2)amazon_shop フィルタ動作前に bk1 から簡単な書誌情報と画像を(存在していれば)ダウンロードする。
(3)amazon_shop フィルタ動作後、amazon からの取得情報内に書影がない場合(2)の書影で補完、表示。
なお、一歩さん(http://ippo.s5.xrea.com/ndiary/)謹製の
bookstore_x (http://ippo.s5.xrea.com/ndiary/inlink.html) を常用していて、
bk1 ダウンロード書影ファイルすでに存在している場合、新規取得せずにそっちを使用します(たぶん)。
設定方法(bookstore_x 常用している方は(2)以外特に設定しなくていいはず)
※必ず FILTER = 'abc' は FILTER = 'amazon_shop' の前に記述する事!!!!
(1)ndiary.conf の設定
# bookstore_x と共有できる設定
CACHE_DIRECTORY = '/hoge/foo/ndiary/log/bookcache/' #キャッシュファイル格納場所
PROXY = 'proxy.hoge.com:8080' # プロキシ(使用していない場合は記述しない)
# bk1の画像利用(ダウンロード)指定(画像格納フォルダ)
BOOKSTORE_BK1_IMAGE = '/hoge/foo/bar/img/bk1img/' # ダウンロード位置(必須)
BOOKSTORE_BK1_IMAGEURL = './' # リンク位置(htmlにはこちらが記述される)(必須)
BOOKSTORE_BK1_ID = 'p-waka54821' # bk1 ブリーダー ID(適宜)
# abc 独自設定(適宜)
# amazon / bk1 への商品直接リンクテンプレート。記述なければデフォルト表示。
#ABC_LINK_DECORATE = '["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"]'
# 例
ABC_LINK_DECORATE = '<-isbn>: 【["bk1","bk1 へのリンク","<-title>(bk1)"]】【["amz","amazon へのリンク","<-title>(amazon)"]】'
# ["A,"B","C"] A: bk1 or amz
# B,C: B
# B,C: では以下のキーワードも定義可能。
# <-isbn>: 商品の ISBN
# <-isbn_nodash>: 商品の '-' なし ISBN(4-123-45678-9 = > 4123456789)
# <-title>: 商品の(bk1 における)タイトル
# <-bk1id>: bk1 ブリーダー ID
# <-amzid>: amazon アソシエイト ID
(2)キャッシュディレクトリ(bk1_light)作成(必須)
(1)で設定した CACHE_DIRECTORY を作成、
さらにその下に 'bk1_light' というディレクトリを作成する。
(例)
CACHE_DIRECTORY = '/hoge/foo/ndiary/log/bookcache/'
の場合、
/hoge/foo/ndiary/log/bookcache/bk1_light
を作成する。
(3))ruby ライブラリを準備する(必須)
webagent (一歩さんところから取得下さい)
http://ippo.s5.xrea.com/ndiary/user/lib/webagent.rb
cookie (一歩さんのところから取得下さい)
http://ippo.s5.xrea.com/ndiary/user/lib/cookie.rb
image_size
http://raa.ruby-lang.org/list.rhtml?name=image_size
yaml (ruby 1.8.x では標準)
=end
class Module
def attr_my_accessorbk1(name)
module_eval %{
def #{name.id2name}()
get_bk1data
@#{name.id2name}
end
}
end
end
class Bk1Light
attr_accessor :urlSite, :searchUrl
attr_accessor :isbn
attr_accessor :expire
attr_accessor :diary_day
attr_accessor :cached_day, :cache_dir, :cache_file
attr_accessor :image_dir, :image_download
attr_accessor :image_width, :image_height
attr_my_accessorbk1 :image_url
attr_my_accessorbk1 :bibid
attr_my_accessorbk1 :product_url
attr_my_accessorbk1 :local_img
attr_my_accessorbk1 :title
def initialize
@expire = 0 # 0だと存在するキャッシュを必ず使用
@image_download = false
@urlSite = 'http://www.bk1.co.jp/'
@diary_day = Time.now
@cached_day = Time.now
@flag = false
@title = nil
@local_img = nil
@image_url = nil
@image_width = nil
@image_height = nil
@media = nil
@product_url = nil
@cache_dir = ""
@cache_file = ""
end
def load_cache
begin
if @flag or
(File::directory?(@cache_dir.to_s) and File::readable?(@cache_dir + @cache_file) and
File::mtime(@cache_dir + @cache_file).to_i < Time::now.to_i - 3600 * 24 * @expire and
@expire != 0) then
return
end
rescue
puts "cache_file= " + @cache_file.to_s
puts $!
end
@flag = true
read_cache
end
def read_cache
cache_file = File.join(@cache_dir, @cache_file)
if /\.txt/i =~ @cache_file then
return unless FileTest.exist?(cache_file)
cache = File.open(cache_file,mode="r")
cache.read.to_a.each{|line|
@title = $1.tosjis if /^title\t(.+?)$/ =~ line
@bibid = $1 if /^id\t(.+?)$/ =~ line
@isbn = $1 if /^isbn\t(.+?)$/ =~ line
}
cache.close
else
unless FileTest.exist?(cache_file) then
@flag = nil
return
end
cache = File.open(cache_file,mode="r")
str = YAML::load(cache)
@title = str["商品タイトル"]
@product_url = str["商品URL"]
@image_url = str["画像URL"]
@image_width = str["画像幅"]
@image_height = str["画像高さ"]
@media = str["メディア"]
@diary_day = str["日記記載日"]
@cached_day = str["キャッシュした時間"]
@isbn = str["ISBN"]
@bibid = str["BIBID"]
@local_img = str["ローカル画像"]
# 2005/4/10 bk1 リニューアル
@product_url = @product_url.to_s.gsub(/cgi-bin.+?$/,"product/#{@bibid}")
cache.close
end
end
def save_cache
return unless File::directory?(@cache_dir.to_s)
cache_file = File.join(@cache_dir, @cache_file)
str = Hash[\
"商品タイトル",@title,\
"商品URL",@product_url,\
"画像URL",@image_url,\
"画像幅",@image_width,\
"画像高さ",@image_height,\
"メディア",@media,\
"日記記載日",@diary_day,\
"キャッシュした時間",@cached_day,\
"ISBN",@isbn,\
"BIBID",@bibid,\
"ローカル画像",@local_img,\
"FilterVersion",Abcver\
]
cache = File.open(cache_file,mode="w")
cache.write(str.to_yaml)
cache.close
end
def get_bk1data
load_cache
return if @flag
@searchUrl = @urlSite + "search/search.asp?"
@searchUrl << "kywd=#{@isbn}"
puts "CHK; get #{@searchUrl}"
agent = WebAgent.new()
agent.uri = @searchUrl
getstart = Time.now
begin
agent.get()
puts " Time: #{Time.now - getstart}(sec)"
rescue
puts " Time Out: #{Time.now - getstart}(sec)"
return false
end
body = agent.body
bibid = Array.new
body.scan(%r||){
bibid << $1 unless $1.nil?
}
@bibid = bibid.first
if @bibid.to_s.empty?
save_cache
return
end
body.scan(%r|src="/(bookimages/.*#{@bibid}.+?_s.jpg)"|){
@image_url = $1.gsub(/_s/,"") unless $1.nil?
}
body.scan(%r|#{@bibid}">(.+?)|){
@title = $1.to_s
}
@product_url = @urlSite + "product/#{@bibid}"
@image_url = File.join(@urlSite,@image_url)
if @local_img.to_s.empty? then
if @image_download
do_image_download
end
end
@title = @title.tosjis
# if @bibid.to_s.empty? then
if @title.to_s.empty? then
read_cache
else
save_cache
@flag = true
end
end
def do_image_download
image_file_name = File.join(@image_dir, "isbn#{@isbn.to_s.delete('-').downcase}.jpg")
unless FileTest.exist?(image_file_name) then
begin
agent = WebAgent.new()
puts "CHK; get #{@image_url}"
agent.uri = @image_url
agent.get()
fp = open(image_file_name, 'wb')
fp.puts agent.body
fp.close
rescue
# timeout: no image
end
end
if FileTest.exist?(image_file_name) then
if FileTest.size(image_file_name) < 1000 then # ファイルサイズが 1000 byte 以下はファイル無し
get_image_size
@local_img = ""
else
@local_img = "isbn#{@isbn.to_s.delete('-').downcase}.jpg"
end
end
end
def get_image_size
image_file_name = File.join(@image_dir, "isbn#{@isbn.to_s.delete('-').downcase}.jpg")
if FileTest.exist?(image_file_name) then
image = ImageSize.new(open(image_file_name,"r").read)
@image_width, @image_height = image.get_width.to_i, image.get_height.to_i
end
end
end
class Filter
def abc(str, type)
$:<< @diary.config['USER_LIB_DIRECTORY']
begin
require 'cookie'
require 'webagent'
require 'image_size'
require 'yaml'
rescue LoadError
puts $!
end
tagend = @diary.isXHTML ? ' />' : '>'
bk1id, amzid = '', ''
unless @diary.config['BOOKSTORE_BK1_ID'].to_s.empty?
bk1id = @diary.config['BOOKSTORE_BK1_ID']
end
unless @diary.config['BOOKSTORE_AMAZON_ID'].to_s.empty?
amzid = @diary.config['BOOKSTORE_AMAZON_ID']
amzid = amzid
end
startFlagStr = "bk1_lightFlagStart"
endFlagStr = "bk1_lightFlagEnd"
case type
when :P, :UL, :DL
str.gsub!(/\(@ISBN:(.+?)(\/.+?)?\)/){
isbn = $1.to_s
tmptemplate = $2.to_s
bk1Light = Bk1Light.new
bk1Light.isbn = isbn
title = ""
product_url = ""
# bookstore_x のキャッシュをロードする
bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1')
bk1Light.cache_file = "isbn#{isbn.delete('-').downcase}.txt"
unless @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty? then
bk1Light.image_download = true
bk1Light.image_dir = @diary.config['BOOKSTORE_BK1_IMAGE']
end
title = bk1Light.title.to_s
product_url = bk1Light.urlSite + "search/search.asp?kywd=#{bk1Light.isbn}"
if title.to_s.empty? then
bk1Light = Bk1Light.new
bk1Light.isbn = isbn
bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1_light')
bk1Light.cache_file = isbn
unless @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty? then
bk1Light.image_download = true
bk1Light.image_dir = @diary.config['BOOKSTORE_BK1_IMAGE']
end
title = bk1Light.title.to_s
product_url = bk1Light.product_url.to_s
end
retstr = ""
unless title.to_s.empty? then
bk1link = product_url.gsub(/\.$/,"") + "/?partnerid=" + bk1id + "/"
amzlink = %Q'http://www.amazon.co.jp/exec/obidos/ASIN/#{isbn.delete("-")}/#{amzid}/ref=nosim'
# abc リンクテンプレート使用
if @diary.config['ABC_LINK_DECORATE'].to_s.empty? then
amzbk1link= %Q'ISBN: #{bk1Light.isbn}【bk1】【amazon】'
else
abcdecorate = @diary.config['ABC_LINK_DECORATE'].to_s.gsub(/<-isbn>/,"#{bk1Light.isbn}").gsub(/<-title>/,"#{bk1Light.title}").gsub(/<-isbn_nodash>/,"#{bk1Light.isbn.delete("-")}").gsub(/<-bk1id>/,bk1id).gsub(/<-amzid>/,amzid)
# [bk1,amz]decorate = ["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"]
bk1decorate = abcdecorate.scan(/\["(bk1)","(.+?)","(.+?)"\]/).flatten
amzdecorate = abcdecorate.scan(/\["(amz)","(.+?)","(.+?)"\]/).flatten
amzbk1link = abcdecorate.to_s.gsub(/\["bk1.+?"\]/,%Q'#{bk1decorate[1]}').gsub(/\["amz.+?"\]/,%Q'#{amzdecorate[1]}')
end
# amazon_shop マイナー機能の一時的テンプレートロード時はスキップ
unless tmptemplate.to_s.empty? then
retstr = %Q'(@ISBN:#{isbn}#{tmptemplate})#{amzbk1link}'
else
retstr = %Q|(@ISBN:#{bk1Light.isbn})#{amzbk1link}|
end
else
amzlink = %Q'http://www.amazon.co.jp/exec/obidos/ASIN/#{isbn.delete("-")}/#{amzid}/ref=nosim'
# abc リンクテンプレート使用
if @diary.config['ABC_LINK_DECORATE'].to_s.empty? then
amzbk1link= %Q'ISBN: #{bk1Light.isbn}【bk1】【amazon】'
else
abcdecorate = @diary.config['ABC_LINK_DECORATE'].to_s.gsub(/<-isbn>/,"#{bk1Light.isbn}").gsub(/<-title>/,"#{bk1Light.title}").gsub(/<-isbn_nodash>/,"#{bk1Light.isbn.delete("-")}").gsub(/<-bk1id>/,bk1id).gsub(/<-amzid>/,amzid)
# [bk1,amz]decorate = ["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"]
bk1decorate = abcdecorate.scan(/\["(bk1)","(.+?)","(.+?)"\]/).flatten
amzdecorate = abcdecorate.scan(/\["(amz)","(.+?)","(.+?)"\]/).flatten
amzbk1link = abcdecorate.to_s.gsub(/\["bk1.+?"\]/,%Q'#{bk1decorate[1]}').gsub(/\["amz.+?"\]/,%Q'#{amzdecorate[1]}')
end
retstr = %Q|(@ISBN:#{isbn})#{amzbk1link}|
end
retstr + ""
}
when :AFTER_ONEDAY
unless @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty?
image_dir = @diary.config['BOOKSTORE_BK1_IMAGE']
image_url = @diary.config['BOOKSTORE_BK1_IMAGEURL']
w,h = nil, nil
str.gsub!(/(.+?)/mi){
isbn = $1.to_s
body = $2.to_s
bk1Light = Bk1Light.new
bk1Light.isbn = isbn
title = ""
product_url = ""
# bookstore_x のキャッシュをロードする
bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1')
bk1Light.cache_file = "isbn#{isbn.delete('-').downcase}.txt"
title = bk1Light.title.to_s
product_url = bk1Light.urlSite + "search/search.asp?kywd=#{bk1Light.isbn}"
if title.to_s.empty? then
bk1Light = Bk1Light.new
bk1Light.isbn = isbn
bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1_light')
bk1Light.cache_file = isbn
title = bk1Light.title.to_s
product_url = bk1Light.product_url.to_s
end
bk1link = product_url.gsub(/\.$/,"") + "/?partnerid=" + bk1id + "/"
image_file = bk1Light.local_img
if bk1Light.image_width.to_s.empty? || bk1Light.image_height.to_s.empty? then
bk1Light.image_dir = image_dir
bk1Light.get_image_size
bk1Light.save_cache
end
image_width = " width=#{bk1Light.image_width}" unless bk1Light.image_width.to_s.empty?
image_height = " height=#{bk1Light.image_height}" unless bk1Light.image_height.to_s.empty?
if FileTest.exist?(File.join(image_dir,image_file)) and FileTest.file?(File.join(image_dir,image_file))
# ↓ファイルサイズが 1000 byte 以下はファイル取得失敗している(= 画像無し)とみなす
unless FileTest.size(File.join(image_dir,image_file)) < 1000 then
linkstr = %Q!
!
unless @diary.config['NO_IMAGE_FILE'].to_s.empty?
no_image_file = @diary.config['NO_IMAGE_FILE'].to_s
body.gsub!(/#{no_image_file}/,linkstr)
else
body.gsub!(%r'No Image
'mi,linkstr)
end
end
end
body
}
end
end
end
end