#!/usr/bin/python # _/_/_/_/_/_/_/_/_/_/ にゃはぴょんCGI工房提供 _/_/_/_/_/_/_/_/_/_/ # _/ このスクリプトの改造・再配布は自由です。 _/ # _/ _/ # _/_/_/_/_/_/_/_/_/_/ http://www.tky.3web.ne.jp/~t0kagaya/lib/ _/ ######### ######### ######### ######### ######### # 涙枯れるまで泣く方がいい?? # 愛のにゃはぴょん暇潰しシステム # # CGI本体 # nami.cgi ######### ######### ######### ######### ######### import cgi # フォームデータを受け取ったりしてくれるのがあります import string # 文字列操作なメソッドがいろいろあります import time # 時間関連がいろいろです import posix # 環境変数とかとるため import posixpath # ファイル関連とか import re # 正規表現 import types # 型判別のため import urllib # URLエンコードとか ######### ######### ######### ######### ######### # 初期設定 G_TIME_NOW = time.time() # 今の時間 G_VER = '0.90.0' # このスクリプトのバージョン G_LOG_FILE = 'log.dat' # ネタレス保存用ログファイル G_OLD_LOGS_DIR = 'data' # 過去ログ保存用ディレクトリ G_NICK_LOG_FILE = 'nick.dat' # リアルタイム参加者ログファイル G_NETA_COUNT_FILE = 'cnt.dat' # ネタ数カウンタファイル G_MAX_NUM_OF_NETA = 20 # 画面に表示する(書き込み可能な)ネタの最大数 G_MAX_NUM_OF_RES = 20 # 一つのネタにつけられるレスの最大数 #G_KANJI_CODE = 'sjis' # 使われる漢字コード G_NICK_TIME_OUT = 1000 # ニックの脱落時間 G_THIS_NAME = "nami.cgi" # このCGIの名前 G_TITLE = "涙枯れるまで泣く方がいい?? Ver %s Python版" % G_VER # タイトル G_SAVE_OLD_LOGS = 1 # 過去ログを保存するかどうか(しないならコメントアウト) G_MAX_NUM_OF_OLD_NETA_PER_FILE = 50 # 一つの過去ログファイルに保存されるネタ数 ######### ######### ######### ######### ######### # ユーザー定義関数 # function ######### ######### ######### ######### ######### def LoadFromFile(file): msg = "" array_data = [] # ここはもうちょっとどうにかするべき if not (posixpath.isfile(file)): msg = " ファイル入力エラー [ ファイル名:%s ] " % file else: f = open(file,"r") array_data = f.readlines() return [msg, array_data] def WriteToFile(file,option,array_data): msg = "" #配列じゃないのがきたら配列にする if not (type(array_data) is types.ListType): array_data = [array_data] f = open(file,option) if f: for current in array_data: f.write("%s" % current) f.close() else: msg = " ファイル出力エラー [ ファイル名:%s ] " % file return msg def GetTime(times): #文字列できたらfloatに if type(times) is types.StringType: times = string.atof(times) if not times: times = time.time() ##グリニッジ標準時間で times = times + 32400 date = time.strftime("%Y/%m/%d %a %H:%M",time.gmtime(times)) #$timep = gmdate("G:i",$times) return date def ViewLogs(): #-------- --------- --------- --------- --------- # ログ閲覧モードのHTML作成表示 #-------- --------- --------- --------- --------- # my ($mCntErr,@mData,$mLog,$mWhatsNew,$mNext,$mBefore,$mErr2,$mErr,$mCnt) global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS global G_MAX_NUM_OF_OLD_NETA_PER_FILE global gForm mCntErr = mLog = mLog2 = mWhatsNew = mNext = mBefore = mErr2 = mErr = "" m_array_Data = [] mCnt = [] # ネタ番号カウンタ読み込み [mCntErr,mCnt] = LoadFromFile(G_NETA_COUNT_FILE) # 型をintに mCnt = string.atoi(mCnt[0]) # ネタ番号が指定されている場合 if gForm.has_key("no"): tmp_no = gForm["no"].value tmp_no = string.atoi(tmp_no) # 過去ログファイル番号を計算 mFileName = int ( tmp_no / G_MAX_NUM_OF_OLD_NETA_PER_FILE) # ファイル読み込み [mErr,m_array_Data] = LoadFromFile("%s/%s.txt" % (G_OLD_LOGS_DIR,mFileName)) # ネタが新しい順に並べ替え m_array_Data.reverse() # ページリンクのネタ番号設定 mNext = tmp_no - G_MAX_NUM_OF_OLD_NETA_PER_FILE mBefore = tmp_no + G_MAX_NUM_OF_OLD_NETA_PER_FILE if mNext < 1: mNext = 0 # ネタ番号が指定されていないもしくはネタ番号指定でのログ読み込みが失敗した場合 if (not gForm.has_key("no")) or (mErr): # ログファイル読み込み [mErr2,m_array_Data] = LoadFromFile(G_LOG_FILE) # ページリンクのネタ番号設定 mNext = mCnt - len(m_array_Data) mBefore = 1 # ログが読めなかった場合のエラー表示 if not m_array_Data: print "\n
ここをクリックして下さい。
""" % (G_THIS_NAME,mErrMessage,mMessage,G_THIS_NAME)
def DispResForm():
#-------- --------- --------- --------- ---------
# レス用のフォーム表示
#-------- --------- --------- --------- ---------
# my ($mErr,@mLog,$mFindFlag,$mErrMessage)
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
mErr = mFindFlag = mErrMessage = ""
#リストにしておく
m_array_Log = []
m_array_Res = []
[mErr,m_array_Log] = LoadFromFile (G_LOG_FILE)
# ファイルを読み込めなかった場合のメッセージ処理
if mErr:
mErrMessage = mErrMessage + "
",mIntroduce) print """
%s |
ここをクリックして下さい。
""" % (G_TITLE,G_VER)
def GetNickList(m1,m2):
#-------- --------- --------- --------- ---------
# ニック機能
# ニック一覧HTML = GetNickList(現在の時刻,脱落までの時間)
#-------- --------- --------- --------- ---------
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
m_array_Data = []
m_array_NewList = []
mNickList = mRefreshFlag = ""
# ニックのログファイルを読み込む
[mErr,m_array_Data] = LoadFromFile(G_NICK_LOG_FILE)
# 読み込み失敗したらエラー表示
if mErr:
return ("[エラー] 参加者ログファイルを読み込めませんでした [^v^]/\n")
# 表示用ニックリストの準備
if not m1:
m1 = time.time()
mNow = GetTime(m1)
mData = len(m_array_Data)
mNickList = mNickList + "%s (現地時間) 現在のリアルタイム参加者は %d 人らしい
""" % (G_THIS_NAME,mMmessage,G_THIS_NAME)
def FormLog(mOption,m_array_Data):
#-------- --------- --------- --------- ---------
# ログ整形
# HTMLデータ = FormLog(オプション,ログデータ)
#
#-------- --------- --------- --------- ---------
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
m_array_Res = []
m_array_WhatsNewList = {}
mLog = mWhatsNewList = ""
# ★の色変え位置
M_DIVIDE_POINT = 5
mWhatsNew = "新着|"
# ログデータをHTMLに整形してmLogに格納
for mLine in m_array_Data:
mLine = string.rstrip(mLine)
# ひとつのスレッド読み込み
m_array_Res = string.split(mLine,",")
[mNo,mNeta,mTime] = m_array_Res[0:3]
m_array_Res[0:3] = []
# 新着の作成
if not mTime:
mTime = time.time()
mTime2 = GetTime(mTime)
m_array_WhatsNewList[mTime] = "★%s ( %s ) " % (mNo,mNo,mTime2)
# オプションが'link'ならネタ番号にレス画面へのリンクを
if mOption == 'link':
mLog = mLog + "\n\n★%s\n" % (mNo,G_THIS_NAME,mNo,mNo)
else:
# オプションが無かったらリンクしない
mLog = mLog + "\n
★%s\n" % mNo
# 日付取得
if not mTime:
mTime = time.time()
mDate = GetTime(mTime)
# ネタの表示部分作成
mLog = mLog + "%s %s \n" % (mNeta,mDate)
# このネタにレスがあれば
if len(m_array_Res) > 0:
# レス数の表示部分作成
mLog = mLog + " . . *%d\n
\n"
# 新着表示部分の作成
array_tmp = m_array_WhatsNewList.keys()
array_tmp.sort()
array_tmp.reverse()
for current in array_tmp:
mWhatsNew = mWhatsNew + m_array_WhatsNewList[current]
mWhatsNew = mWhatsNew + "\n" % len(m_array_Res)
m_array_ResHTML = []
mCounter = 1
# レスの処理
for current in m_array_Res:
# M_DIVIDE_POINTで指定された数置きに★の色を変える
if mCounter % M_DIVIDE_POINT == 0:
m_array_ResHTML.append("
\n"
else:
# レスが無かった場合の処理
mLog = mLog + " . . *無\n"
mLog = mLog + "
\n"
return [mLog,mWhatsNew]
def LoadLog():
#-------- --------- --------- --------- ---------
# メイン画面に表示するログファイル読み込み
# HTMLデータ = LoadLog
#-------- --------- --------- --------- ---------
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
m_array_Data = []
[mErr,m_array_Data] = LoadFromFile(G_LOG_FILE)
if mErr:
return ("\n
[エラー] メインログファイルを読み込めませんでした [^v^]/\n")
[mLog,mWhatsNew] = FormLog("link",m_array_Data)
return [mLog,mWhatsNew]
def PrintTail():
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
print """
""" % G_VER
def PrintNetaForm(mWhatsNew):
#-------- --------- --------- --------- ---------
# ネタフリ用FORM表示
# PrintNetaForm(新着データ)
#-------- --------- --------- --------- ---------
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
print """
最大ネタ数%d, 最大レス数%d, 脱落まで%d秒
リロード|
ログ閲覧|
readme 1st|
翻訳|
注:ここでの書き込みで生じる著作権は全てフリー(自分で責任とれる範囲で自由に使ってださい)
%s
""" % (G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES,G_NICK_TIME_OUT,G_THIS_NAME,G_THIS_NAME,G_THIS_NAME,mWhatsNew,G_THIS_NAME)
def PrintHeader():
#-------- --------- --------- --------- ---------
# ヘッダー表示
#-------- --------- --------- --------- ---------
global G_TIME_NOW,G_VER,G_LOG_FILE,G_OLD_LOGS_DIR,G_NICK_LOG_FILE
global G_NETA_COUNT_FILE,G_MAX_NUM_OF_NETA,G_MAX_NUM_OF_RES
global G_KANJI_CODE,G_NICK_TIME_OUT,G_THIS_NAME,G_TITLE,G_SAVE_OLD_LOGS
global G_MAX_NUM_OF_OLD_NETA_PER_FILE
global gForm
print """
irc.friend.td.nu #nyahapyon / irc.3web.ne.jp #にゃはぴょん
\n" % (mNow,mData)
# ニックのリストを作成
for current in m_array_Data:
current = string.rstrip(current)
# 一人分のデータを読み込み各変数にいれる
[mNick, mHost, mTime] = string.split(current,"<>")[0:3]
mTime = string.atof(mTime)
# 脱落時間になってたら脱落表示してデータから削除
if (int(m1) - int(mTime)) > (int(m2)):
mLine = "★脱落?"
else:
# 制限時間内ならニックの表示と各種処理
# ニックのIPと一致したら
if posix.environ.has_key("REMOTE_HOST"):
mEnv = "REMOTE_HOST"
else:
mEnv = "REMOTE_ADDR"
if mHost == posix.environ[mEnv]:
# 最終アクセス時刻を現在のものに
mTime = m1
# ニック欄に何か入力されていたらニック更新
if gForm.has_key("nick"):
mNick = gForm["nick"].value
# フラグセット
mRefreshFlag = 1
# ファイル保存用データに格納
m_array_NewList.append("%s<>%s<>%s\n" % (mNick,mHost,mTime))
# 色ニックの処理
mIndex = len(m_array_NewList)
if mIndex == 1:
mStarColor = '#FFFF66'
mNickColor = '#FFFF99'
elif mIndex == 2:
mStarColor = '#999999'
mNickColor = '#EEEEEE'
elif mIndex == 3:
mStarColor = '#FF9966'
mNickColor = '#FFCC66'
# ニックのオマケ特殊処理
m_array_Array = []
# "|"でニックと自己紹介部分に分ける
m_array_Array = string.split(mNick,"|")
if len(m_array_Array) > 1:
[mNick] = m_array_Array[0:1]
m_array_Array[0:1] = []
mIntroduce = string.join(m_array_Array,"|")
# URLエンコード
mIntroduce = {"comment":mIntroduce}
mIntroduce = urllib.urlencode(mIntroduce);
# 自己紹介リンク
mStar = "★" % (G_THIS_NAME,mIntroduce)
else:
mStar = "★"
# 上位三名の処理
if mIndex < 4:
mLine = "%s%sさんは %d秒前\n" % (mStarColor,mStar,mNickColor,mNick,(m1 - mTime))
else:
# それ以外の参加者の処理
mLine = "%s%sさんは %d秒前\n" % (mStar,mNick,(m1 - mTime))
# 一人分のデータを表示用変数に格納
mNickList = mNickList + mLine
# ニックのリストを作成 # ここまで
# ニックデータにIPが無かった場合、参加の処理
if not mRefreshFlag:
mNickList = mNickList + "★(参加)"
if posix.environ.has_key('REMOTE_HOST'):
mNewHost = posix.environ['REMOTE_HOST']
else:
mNewHost = posix.environ['REMOTE_ADDR']
m_array_NewList.append("見学<>%s<>%s\n" % (mNewHost,m1))
# ニックデータをファイルに書き込み
mErr = WriteToFile(G_NICK_LOG_FILE, "w", m_array_NewList)
# エラー表示
if mErr:
return ("[エラー] 参加者ログファイルに書き込めませんでした[^v^]/\n")
return mNickList
######### ######### ######### ######### #########
# メインルーチン
# main routine
######### ######### ######### ######### #########
# ヘッダー表示
PrintHeader()
# フォームからデータ取得
gForm = cgi.FieldStorage()
for current in gForm.keys():
gForm[current].value = cgi.escape(gForm[current].value)
gForm[current].value = string.replace(gForm[current].value,",",",")
if not gForm:
# デフォルト処理
# ログと新着ファイル読み込み
[mLog,mWhatsNew] = LoadLog()
# 参加者リスト読み込み
mNickList = GetNickList(G_TIME_NOW,G_NICK_TIME_OUT)
# 画面表示
PrintNetaForm(mWhatsNew)
print mNickList
print mLog
else:
if gForm.has_key("mode"):
if gForm["mode"].value == 'intro':
# 自己紹介の表示
DispIntroduce()
elif gForm["mode"].value == 'res':
# レス入力画面の表示
DispResForm()
elif gForm["mode"].value == 'view':
# レス入力画面の表示
ViewLogs()
elif gForm.has_key("neta"):
# ネタをファイルに書き込み
WriteNeta()
elif gForm.has_key("res"):
# レスをファイルに書き込み
WriteRes()
else:
# デフォルト処理
# ログと新着ファイル読み込み
[mLog,mWhatsNew] = LoadLog()
# 参加者リスト読み込み
mNickList = GetNickList(G_TIME_NOW,G_NICK_TIME_OUT)
# 画面表示
PrintNetaForm(mWhatsNew)
print mNickList
print mLog
# フッター表示
PrintTail()