COBOL技術者の憂鬱

COBOLプログラマは不在にしています

ソースコード公開(その2)

昨日はバッチ部分を掲載したので、今日はオンライン部分ですね。
オンライン部分は、大きく以下の4つの部分に分かれています。

  • トップページを表示する部分(リスト6)
  • 検索結果一覧を表示する部分(リスト7)
  • 検索結果詳細を表示する部分(リスト8)
  • Rimoと連携する部分(リスト9、10)


さてと、これでRetroTube内で動いている全てのプログラムのソースコードを公開したことになりますが、ちょっとコードを読める方であれば、シンプルな仕組みで動いていることに驚かれたのではないでしょうか?
てっきりRailsを使ったDBアプリだと勘違いされていた方もいらっしゃると思いますが、そのような小難しいことは一切やっていないのです。
ひたすら移送と分岐と繰り返しの羅列なので、このままCOBOLでリメイクできそうな気がしますね。
では、何故Rubyで書いたのかと興味深く思われた方は、是非雑誌の方の記事を参照していただきたいです。


今後も暇を見ては(RetroTubeの)改良を続けていくつもりですが、既に別のサービスの開発に取り掛かっているところなので、徐々にそちらの方へ注力していくことになると思います。
そちらの方もご期待ください。




【リスト6】index.cgi

#!/usr/local/bin/ruby
print "Content-type: text/html\n\n"

#####################################
#【RetroTube】トップページ表示プログラム
#####################################

require "csv"

#ここからHTML生成
#HTMLヘッダ
print '<html><head>
          <title>RetroTube</title>
          <meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
          <meta http-equiv="Content-Style-Type" content="text/css">
          <link rel="alternate" type="application/rss+xml" title="RetroTube RSS" href="http://www.retro-tube.com/rss.rdf">
          <link rel="stylesheet" type="text/css" href="title.css">
          </head><body>'

#開発者
print '<p class="header">This service is created by
          <a href="http://d.hatena.ne.jp/quill3/" target="_blank" class="cursor">quill3</a>.
          </p><br>'

#ロゴ
print '<div align=center>
          <img src="logo.gif" alt="RetroTube">
          <br><br>'

#検索フォーム
print '<form action="search.cgi" method="GET">
          <select name="year">'
for i in 1976..2004
  print '<option>' + i.to_s + '</option>'
end
print '</select>
          年の
            <select name="category">
            <option value="music">邦楽</option>
            <option value="anime">アニメ</option>
            <option value="movie_j">邦画</option>
            <option value="movie_a">洋画</option>
          </select>

          <input type="submit" value="YouTube検索">
          </form>'

print '</div><br><br>'

#新着動画
print '<h4>新着動画
          <a href="http://rssicon20.com/rss.php?u=http%3A%2F%2Fwww.retro-tube.com%2F&s=1">
          <img src="rsslogo.gif" alt="RSS" title="RSS" align="absmiddle" border="0" style="margin-left:5px"></a></h4>'

csv = CSV.open('compare.csv', 'r')
csv.each { |line|
  print '<div class="video" ><p><a href="detail.cgi?movieid=' + line[3] + '&category=' + line[6] + '" target="_blank"><img src="' + line[4] + 
           '" alt="' + line[2] + ' - ' + line[1] + '" title="' + line[2] + ' - ' + line[1] + '" class="video-thumbnail"/></a></p>
           <p><a href="detail.cgi?movieid=' + line[3] + '&category=' + line[6] + '" target="_blank" class="cursor">' + line[2] + '</a></p>
           <p><a href="detail.cgi?movieid=' + line[3] + '&category=' + line[6] + '" target="_blank" class="cursor">' + line[1] + '</a></p>
           </div>'
  }

#Google Analytics
print '<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
          <script type="text/javascript">_uacct = "UA-568420-2";urchinTracker();</script>'

print '</body></html>'


【リスト7】search.cgi

#!/usr/local/bin/ruby
print "Content-type: text/html\n\n"

#####################################
#【RetroTube】検索結果一覧表示プログラム
#####################################

require "cgi-lib"
require "kconv"
require "csv"

#他ページからの入力パラメータ(年代とカテゴリ)
input = CGI.new
inputyear = input["year"]
inputcategory = input["category"]

#カテゴリ表示用クラス
class ShowCategory
  def initialize(parm_category)
    @categorytable = [["music","邦楽"],
                              ["anime","アニメ"],
                              ["movie_j","邦画"],
                              ["movie_a","洋画"]]
    @categorytable.each { |elem|
      if parm_category == elem[0]
        @category = elem[1]
        break
      end
    }
  end  
  def show
    print @category
  end
  def select
    @categorytable.each { |elem|
      print '<option'
      if @category == elem[1]
        print ' selected="selected"'
      end
      print ' value="' + elem[0] + '">' + elem[1] + '</option>'
    }
  end
end

show_category = ShowCategory.new(inputcategory) 

#ここからHTML生成

#HTMLヘッダ
print '<html><head>
          <title>RetroTube : ' + inputyear + '年の'
show_category.show
print '</title>
         <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
         <meta http-equiv="Content-Style-Type" content="text/css">
         <link rel="stylesheet" type="text/css" href="basic.css">
         </head><body>'

#ロゴ
print '<a href="http://www.retro-tube.com/">
          <img src="logo.gif" alt="RetroTube" width=250 border="0"></a>'

#検索フォーム
print '<form action="search.cgi" method="GET">
          <select name="year">'
for i in 1976..2004
  if i.to_s == inputyear
    print '<option selected="selected">' + inputyear + '</option>'
  else
    print '<option>' + i.to_s + '</option>'
  end
end
print '</select>
          年の
          <select name="category">'

show_category.select

print '</select>

          <input type="submit" value="YouTube検索">
          </form>'

#前後の年代へのリンク
print '<div align=right>'
beforeyear = inputyear.to_i - 1
nextyear = inputyear.to_i + 1
if beforeyear >= 1976
  print '<a href="search.cgi?year=' + beforeyear.to_s + '&category=' + inputcategory + '">'
  print '<' + beforeyear.to_s + '年</a>&nbsp;&nbsp;'
end
if nextyear <= 2004
  print '<a href="search.cgi?year=' + nextyear.to_s + '&category=' + inputcategory + '">'
  print nextyear.to_s + '年></a>'
end
print '</div>'

#検索結果動画一覧
print '<h3>' + inputyear + '年の'
show_category.show
print '<a href="remo.cgi?year=' + inputyear + '&category=' + inputcategory + '" target="_blank"><img src="show_rimo.gif"'
print ' alt="Rimo" title="Rimo" align="absmiddle" height="25" border="0" style="margin-left:10px"></a>'
print '</h3>'

csv = CSV.open(inputcategory + '.csv', 'r')
csv.each { |line|
  if line[0] == inputyear
    print '<div class="video" ><p><a href="detail.cgi?movieid=' + line[3] + '&category=' + inputcategory + '" target="_blank"><img src="' + line[4] +
             '" alt="' + line[2] + ' - ' + line[1] + '" title="' + line[2] + ' - ' + line[1] +'" class="video-thumbnail"/></a></p>'
    print '<p><a href="detail.cgi?movieid=' + line[3] + '&category=' + inputcategory + '" target="_blank" class="cursor">' + line [2]
#アニメだけはOPとEDの区別を表示する(特殊ロジック)
    if inputcategory == "anime"
      if line[6] != "NA"
        print ' ' + line[6]
      end
    end
#ここまで特殊ロジック
    print '</a></p>'
    print '<p><a href="detail.cgi?movieid=' + line[3] + '&category=' + inputcategory + '" target="_blank" class="cursor">' + line [1] + '</a></p>'
    print '</div>'
  end
  }

#開発者
print '<p class="footer"><br>This service is created by
          <a href="http://d.hatena.ne.jp/quill3/"  target="_blank" class="cursor">quill3</a>.</p>'

#Google Analytics
print '<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
          <script type="text/javascript">_uacct = "UA-568420-2";urchinTracker();</script>'

print '</body></html>'


【リスト8】detail.cgi

#!/usr/local/bin/ruby
print "Content-type: text/html\n\n"

#####################################
#【RetroTube】検索結果詳細表示プログラム
#####################################

require "cgi-lib"
require "kconv"
require "csv"
require "net/http"

##AmazonAPIアクセス用ライブラリ
require "amazon/search"
include Amazon::Search
assoc_id = "retr-22"
dev_token = "0Z2TJZWAYA1T2ZNW4482"

#他ページからの入力パラメータ(動画IDとカテゴリ)
input = CGI.new
inputmovieid = input["movieid"]
inputcategory = input["category"]

#動画IDとカテゴリを使用して、検索結果一覧から対象動画を引き当てる
csv = CSV.open(inputcategory + '.csv', 'r')
csv.each { |line|
  if line[3] == inputmovieid
    $tyear = line[0]
    $tartist = line[1]
    $ttitle = line[2]
    $tmovieid = line[3]
    if inputcategory == "anime"
      if line[6] == "NA"
        $show_title = line[2]
      else
        $show_title = line[2] + " " + line[6]
      end
    else
      $show_title = line[2]
    end
    break
  end
  }

#ここからHTML生成

#HTMLヘッダ
print '<html><head>
        <title>RetroTube : ['
case inputcategory
when "music"
  print '邦楽'
when "anime"
  print 'アニメ'
when "movie_j"
  print '邦画'
when "movie_a"
  print '洋画'
end
print '] ' + $show_title + ' - ' + $tartist + ' (' + $tyear +')'
print '</title>
         <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
         <meta http-equiv="Content-Style-Type" content="text/css">
         <link rel="stylesheet" type="text/css" href="basic.css">
         </head><body>'

#ロゴ
print '<a href="http://www.retro-tube.com/">
         <img src="logo.gif" alt="RetroTube" width=250 border="0"></a>'

#大見出し
print'<h3>' + $show_title + ' - ' + $tartist + ' (' + $tyear + ')</h3>'

#対象動画を埋め込みで表示
print'<div class="movieinfo">
        <object width="425" height="350">
        <param name="movie" value="http://www.youtube.com/v/' + $tmovieid + '"></param>
        <param name="wmode" value="transparent"></param>
        <embed src="http://www.youtube.com/v/' + $tmovieid + '" type="application/x-shockwave-flash" 
          wmode="transparent" width="425" height="350"></embed>
        </object>
       </div>'

#Wikipedia情報の表示(simpleAPIを使用して情報取得)
address = "wikipedia.simpleapi.net"
case inputcategory
when "music"
  path = "/api?keyword=" + Kconv.toutf8($tartist) + "&output=html"
when "anime","movie_j","movie_a"
  path = "/api?keyword=" + Kconv.toutf8($ttitle) + "&output=html"
end
convpath = path.gsub(' ','%20')
body = Net::HTTP.get( address , convpath ) 
sjisbody = Kconv.tosjis(body)
convbody = sjisbody.gsub('Wikipedia:<a href=','Wikipedia:<a target="_blank" href=')
print '<div class="wikiinfo">' + convbody + '</div>'

#Amazon広告の表示(AmazonAPIアクセス用ライブラリ使用)
request = Request.new(dev_token, assoc_id, "jp", false)
print '<br><br><div class="amazonad">'
case inputcategory
when "music"
  k = 1
  request.artist_search(Kconv.toutf8($tartist),"music",HEAVY) do |product|
    j = 1
    product.artists.each { |temp|
      if temp.upcase == Kconv.toutf8($tartist).upcase
        print '<div class="adspace">'
        print '<a href="' + product.url + '" target="_blank">
                <img src="' + product.image_url_medium + '" alt="thumbnail" style="float:left; margin: 0 15px 10px 10px; padding: 0;border:none;">
                </a>'
        print '<dl style="margin-bottom:0.5em; text-align:left; min-height: 168px;font-size:12px;line-height:16px;">'
        print '<dt><a href="' + product.url + '" target="_blank">' + Kconv.tosjis(product.product_name) + '</a></dt>'
        print '<dd>'
        i = 1
        product.artists.each { |temp2|
          print Kconv.tosjis(temp2) + '  ' 
          i += 1
          if i > 3 #表示するアーティストの数
            break
          end
        }
        print '</dd>'
        print '<dd>' + Kconv.tosjis(product.manufacturer) + '  ' + Kconv.tosjis(product.release_date) + '</dd><br>'
        if product.our_price != nil
          print '<dd>価格 : <strong>' + Kconv.tosjis(product.our_price) + '</strong></dd>'
        end
        print '<dd>(' + Kconv.tosjis(product.availability) + ')</dd><br>'
        print '<dd><a href="' + product.url + '" target="_blank">Ads by Amazon.co.jp</a></dd>'
        print '</dl></div>'
        k += 1
        break
      end
      j += 1
      if j > 3 #検索精度(この数字が少ないほど精度が高い)
        break
      end
    }
    if k > 2 #表示する商品の数
      break
    end
  end
when "anime","movie_j","movie_a"
begin
  j = 1
  if inputcategory == "anime"
    searchword = Kconv.toutf8($ttitle)
  else
    searchword = Kconv.toutf8($ttitle) + " " + Kconv.toutf8($tartist)
  end
  request.keyword_search(searchword,"dvd",HEAVY) do |product|
    print '<div class="adspace">'
    if product.image_url_medium != nil
      print '<a href="' + product.url + '" target="_blank">
              <img src="' + product.image_url_medium + '" alt="thumbnail" style="float:left; margin: 0 15px 10px 10px; padding: 0;border:none;">
              </a>'
    end
    print '<dl style="margin-bottom:0.5em; text-align:left; min-height: 168px;font-size:12px;line-height:16px;">'
    print '<dt><a href="' + product.url + '" target="_blank">' + Kconv.tosjis(product.product_name) + '</a></dt>'
    print '<dd>'
    i = 1
    if product.starring != nil
      product.starring.each { |temp2|
        print Kconv.tosjis(temp2) + '  ' 
        i += 1
        if i > 3 #表示する出演者の数
          break
        end
        }
    end
    print '</dd>'
    print '<dd>' + Kconv.tosjis(product.manufacturer) + '  ' + Kconv.tosjis(product.release_date) + '</dd><br>'
    if product.our_price != nil
      print '<dd>価格 : <strong>' + Kconv.tosjis(product.our_price) + '</strong></dd>'
    end
    print '<dd>(' + Kconv.tosjis(product.availability) + ')</dd><br>'
    print '<dd><a href="' + product.url + '" target="_blank">Ads by Amazon.co.jp</a></dd>'
    print '</dl></div>'
    j += 1
    if j > 2 #表示する商品の数
      break
    end
  end
rescue
end
end

print '</div>'

#関連動画表示
case inputcategory
when "music"
  print '<h4>' + $tartist + 'の曲一覧</h4>'
when "anime"
  print '<h4>' + $tartist + ' 製作アニメ一覧</h4>'
when "movie_j","movie_a"
  print '<h4>' + $tartist + ' 監督作品一覧</h4>'
end
scsv = CSV.open(inputcategory + '.csv', 'r')
scsv.each { |sline|
  if $tartist == sline[1]
    print '<div class="video" >'
    print '<p><a href="detail.cgi?movieid=' + sline[3] + '&category=' + inputcategory + '" >
            <img src="' + sline[4] + '" alt="' + sline[1] + ' - ' + sline[2] + 
            '" title="' + sline[1] + ' - ' + sline[2] +'" class="video-thumbnail"/></a></p>'
    print '<p><a href="detail.cgi?movieid=' + sline[3] + '&category=' + inputcategory + '" class="cursor">' + sline[2]
    if inputcategory == "anime"
      if sline[6] != "NA"
        print ' ' + sline[6]
      end
    end
    print '</a></p>'
    print '<p><a href="detail.cgi?movieid=' + sline[3] + '&category=' + inputcategory + '" class="cursor">' + sline[0] + '</a></p>'
    print '</div>'
  end
  }

#開発者
print '<p class="footer"><br>This service is created by
         <a href="http://d.hatena.ne.jp/quill3/"  target="_blank" class="cursor">quill3</a>.</p>'

#Google Analytics
print '<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
         <script type="text/javascript">_uacct = "UA-568420-2";urchinTracker();</script>'

print '</body></html>'


【リスト9】remo.cgi

#!/usr/local/bin/ruby

#####################################
#【RetroTube】Rimo動画連続再生リクエスト用プログラム
#####################################

require "cgi-lib"
require "net/http"

#他ページからの入力パラメータ(年代とカテゴリ)
input = CGI.new
inputyear = input["year"] 
inputcategory = input["category"] 

#RimoAPIコール(Rimoへ動画一覧を渡し、連続再生をリクエストする)
remoch_url = 'http%3A%2F%2Fwww.retro-tube.com%2Fremoch.cgi%3Fyear%3D' + inputyear + '%26category%3D' + inputcategory
address = "rimo.tv"
path = "/channel/xml?url=" + remoch_url
body = Net::HTTP.get( address , path )

#Rimoの動画連続再生ページへリダイレクト
remoch_url = "http://www.retro-tube.com/remoch.cgi?year=" + inputyear + "&category=" + inputcategory
print "Location: http://rimo.tv/#/channel?url=" + remoch_url + "\n\n"


【リスト10】remoch.cgi

#!/usr/local/bin/ruby
print "Content-type: text/html\n\n"

#####################################
#【RetroTube】Rimoリクエスト用動画一覧生成プログラム
#####################################

require "cgi-lib"
require "csv"

#他ページからの入力パラメータ(年代とカテゴリ)
input = CGI.new
inputyear = input["year"] 
inputcategory = input["category"] 

#ここからHTML生成

#HTMLヘッダ
print '<html><head><title>RetroTube : ' + inputyear + '年の'
case inputcategory
when "music"
  print '邦楽'
when "anime"
  print 'アニメ'
when "movie_j"
  print '邦画'
when "movie_a"
  print '洋画'
end
print '</title><meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"></head><body>'

#ロゴ
print '<a href="http://www.retro-tube.com/"><img src="logo.gif" alt="RetroTube" width=250 border="0"></a>'

#連続再生対象動画の一覧を生成
csv = CSV.open(inputcategory + '.csv', 'r')
csv.each { |line|
                if line[0] == inputyear
                  print '<br><a href="http://www.youtube.com/watch?v=' + line[3] + '">' + line[2] + '</a>'
                end
              }
print '</body></html>'