Web拍手作成

Web拍手とは?

web拍手CGI公式サイトを御覧ください。
これの簡易版をRubyで作ってみたいと思います。

Web拍手サンプル

ログ画面
拍手する

基本設計

以下の画面を作成します。

拍手ボタンを押された時(mode=clap)→拍手画面(送信フォーム有り)
拍手画面からメッセージを頂いた時(mode=clap)→拍手画面(送信フォーム無し)
それ以外→ログ表示画面
という流れにします。

メインロジック

#!/usr/bin/ruby -Ke
  
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 -->の間がメッセージ送信フォームです。

def clap( cgi )
  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を返します。
とりあえず、年月、日、時間、曜日、ページ、メッセージを出力してみましょう。

def log( cgi )
  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ファイルを好みに合わせてデザインすればより素晴らしいものになるでしょう。
プログラム自体もとても簡単にできているので色々いじってみると面白いと思います。

利用/改良などは自由に行っていただいてかまいません。
もし素晴らしい派生物ができた際は連絡いただけるとうれしいです。

スポンサード リンク

トラックバック

トラックバックURL
https://linux-life.net/tb/program/ruby/cgidoc/webclap/
Linux Life 〜 No linux, No life 〜
プログラミング > Ruby > CGI入門 > Web拍手作成