Web拍手作成
Web拍手とは?
web拍手CGI公式サイトを御覧ください。
これの簡易版をRubyで作ってみたいと思います。
Web拍手サンプル
基本設計
以下の画面を作成します。
- 拍手画面(メッセージの送信フォーム有/無を切替える)
- ログ表示画面
- エラー画面
拍手ボタンを押された時(mode=clap)→拍手画面(送信フォーム有り)
拍手画面からメッセージを頂いた時(mode=clap)→拍手画面(送信フォーム無し)
それ以外→ログ表示画面
という流れにします。
メインロジック
require 'cgi'
require 'htmltemplate'
def clap( cgi )
#拍手画面を出力(後述)
end
def log( cgi )
#ログ出力画面を出力(後述)
end
def error( message )
#エラー出力画面を出力
message
end
cgi = CGI.new()
cgi.out do
#モードによって処理を分岐
case cgi['mode'].first
when 'clap'
#mode=clap の時は拍手画面
clap(cgi)
else
#それ以外はログ表示画面
log(cgi)
end.gsub( /\n+/, "\n" )
end
CGIのパラメータ「mode」による条件分岐です。
拍手画面
テンプレートのHTMLファイルを用意します。
(clap.html)
HTTPのリファラで、拍手されたページを判断して、ログファイル(clap.log)に追記して画面のHTMLを返します。
<!-- message_begin -->と<!-- message_end -->の間がメッセージ送信フォームです。
html = HTMLTemplate.open("clap.html")
referer = CGI::escapeHTML( cgi['referer'].first ? cgi['referer'].first : cgi.referer )
html.gsub!("(\tREFERER\t)", referer)
#サイト外の拍手はとりあえず無効に
return error( "外部URLは無効です。" ) if referer !~ /^http:\/\/#{ENV['SERVER_NAME']}/
msg = cgi['message'].first
#メッセージがある時は送信フォームを表示しない
#メッセージがない時は送信フォームを表示する
html.block("message") do |block|
msg ? "" : block.to_s
end
#ログファイルに出力
File.open("clap.log", "a") do |file|
file.puts( [Time.now.strftime("%Y/%m\t%d\t%w\t%H"), referer.to_s, CGI::escapeHTML(msg.to_s).gsub(/\t/," ")].join("\t") )
end
#HTMLを返す
html.to_s
end
ログ出力画面
テンプレートのHTMLファイルを用意します。
(log.html)
ログファイル(clap.log)を解析して画面のHTMLを返します。
とりあえず、年月、日、時間、曜日、ページ、メッセージを出力してみましょう。
html = HTMLTemplate.open("log.html")
currentmonth = CGI.escapeHTML( cgi['month'].first || Time.now.strftime("%Y/%m") )
month = Hash.new(0)
day = []
hour = []
wday = []
msgs = []
pages = Hash.new(0)
size = 0
File.open("clap.log","r") do |file|
file.each do |line|
m, d, w, h, page, msg = line.chomp.split(/\t/)
month[m] += 1
if m == currentmonth
day[d.to_i] = day[d.to_i].to_i + 1
wday[w.to_i] = wday[w.to_i].to_i + 1
hour[h.to_i] = hour[h.to_i].to_i + 1
pages[page] = pages[page].to_i + 1
msgs.push( [page, msg] ) if msg
end
size += 1
end
end
# 年月単位のログ出力
html.block("monthly") do |block|
month.keys.sort.reverse.collect do |key|
val = month[key]
tmpl = block.dup
tmpl.gsub!("(\tmonth\t)", key)
tmpl.gsub!("(\tcount\t)", val)
tmpl.gsub!("(\twidth\t)", val*100/size)
tmpl.to_s
end
end
# 日単位のログ出力
html.block("daily") do |block|
(1...day.size).collect do |i|
tmpl = block.dup
tmpl.gsub!("(\tday\t)", i)
tmpl.gsub!("(\tcount\t)", day[i].to_i)
tmpl.gsub!("(\theight\t)", day[i].to_i*5)
tmpl.to_s
end
end
# 時間単位のログ出力
html.block("hourly") do |block|
(0...24).collect do |i|
tmpl = block.dup
tmpl.gsub!("(\thour\t)", i)
tmpl.gsub!("(\tcount\t)", hour[i].to_i)
tmpl.gsub!("(\theight\t)", hour[i].to_i*5)
tmpl.to_s
end
end
# 曜日単位のログ出力
html.block("weekly") do |block|
(0...7).collect do |i|
tmpl = block.dup
tmpl.gsub!("(\tweek\t)", ["日","月","火","水","木","金","土"][i])
tmpl.gsub!("(\tcount\t)", wday[i].to_i)
tmpl.gsub!("(\theight\t)", wday[i].to_i*5)
tmpl.to_s
end
end
# ページ単位のログ出力
html.block("page") do |block|
pages.to_a.sort{|a,b| b[1] <=> a[1]}.collect do |page|
tmpl = block.dup
tmpl.gsub!("(\tpage\t)", page[0])
tmpl.gsub!("(\tcount\t)", page[1])
tmpl.gsub!("(\twidth\t)", page[1]*100/month[currentmonth])
end
end
# メッセージ一覧の出力
html.block("message") do |block|
msgs.each do |msg|
tmpl = block.dup
tmpl.gsub!("(\tpage\t)", msg[0])
tmpl.gsub!("(\tmessage\t)", msg[1])
end
end
html.to_s
end
終わりに
以上でもっともシンプルなWeb拍手のCGIは完成です。
各HTMLファイルを好みに合わせてデザインすればより素晴らしいものになるでしょう。
プログラム自体もとても簡単にできているので色々いじってみると面白いと思います。
利用/改良などは自由に行っていただいてかまいません。
もし素晴らしい派生物ができた際は連絡いただけるとうれしいです。