#!/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

[エラー] ログファイルを読み込めませんでしたよ! [^v^]/

\n" print "戻る\n" % G_THIS_NAME return # リンクしないモードでログをHTMLに [mLog,mWhatsNew] = FormLog('nolink',m_array_Data) # 閲覧室のHTML表示 mLog = """

過去ログ閲覧君

最高%d件毎表\示 戻る
前のページ次のページ
%s
前のページ次のページ
""" % (G_MAX_NUM_OF_OLD_NETA_PER_FILE,G_THIS_NAME,G_THIS_NAME,mBefore,G_THIS_NAME,mNext,mLog,G_THIS_NAME,mBefore,G_THIS_NAME,mNext) print mLog def WriteRes(): #-------- --------- --------- --------- --------- # レスをファイルに記録 #-------- --------- --------- --------- --------- 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 mErrMessage = mWriteFlag = "" m_array_Log = [] m_array_Res = [] m_array_NewLog = [] [mErr,m_array_Log] = LoadFromFile (G_LOG_FILE) # ファイルを読み込めなかった場合のメッセージ処理 if mErr: mErrMessage = mErrMessage + "

[エラー] メインログファイルを読み込めませんでしたよ! [^v^]/

\n" # ファイル書き込み用のログデータ作成ルーチン for current in m_array_Log: current = string.rstrip(current) # ひとつのスレッドを読み込み m_array_Res = string.split(current,",") # Perlにおけるshift3回分のエミュレーション [mNo,mNeta,mTime] = m_array_Res[0:3] m_array_Res[0:3] = [] # ネタ番号が見つかったら if mNo == gForm["no"].value: # 最大レス数になってたら書き込めないように if (len(m_array_Res) + 1) > G_MAX_NUM_OF_RES: mErrMessage = mErrMessage + "

[エラー] これ以上レスはつけられませんよ! [^v^]/

\n" mWriteFlag = 0 break # レスの追加とフラグ処理 m_array_Res.append(gForm["res"].value) # ふむ、それをPerlではpushと言うな mBuf = string.join(m_array_Res,",") # ふむ、それをPerlではjoinと言うな m_array_NewLog.append("%s,%s,%s,%s\n" % (mNo,mNeta,G_TIME_NOW,mBuf)) mWriteFlag = 1 else: m_array_NewLog.append(current+"\n") # レス先のネタ番号が存在してレス追加してたらファイルに書き込み if mWriteFlag: mErr = WriteToFile (G_LOG_FILE,"w",m_array_NewLog) else: # ネタ番号が存在しなかった場合のエラーメッセージ mErrMessage = mErrMessage + "

[エラー] 指定されたネタ番号には書き込めませんでしたよ! [^v^]/

\n" # ファイルを書き込めなかった場合のメッセージ処理 if mErr: mErrMessage = mErrMessage + "

[エラー] メインログファイルに書き込めませんでしたよ! [^v^]/

\n" # エラーがあったら"0% 無事、登録されました。"に if mErrMessage: mMessage = "0% 無事、登録されました。" else: mMessage = "99.9% 無事、登録されました。" print """ %s たぶん2秒後に自動的に戻ります

%s

ここをクリックして下さい。


""" % (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 + "

[エラー] メインログファイルを読み込めませんでしたよ! [^v^]/

\n" # 指定された番号のネタを探す for current in m_array_Log: current = string.rstrip(current) # ひとつのスレッドを読み込み m_array_Res = string.split(current,",") [mNo,mNeta,mTime] = m_array_Res[0:3] m_array_Res[0:3] = [] # ネタ番号が見つかったらおしまい if mNo == gForm["no"].value: mFindFlag = 1 break # ネタ番号が見つかったらレス画面表示 if mFindFlag: print """

ネタフリは %s だったようです。

ゲンキダセヨ [^v^]/

レス

戻る """ % (mNeta,G_THIS_NAME,gForm["no"].value,G_THIS_NAME) else: # レスするネタ番号が見つからなかった場合の表示 print """ %s

[エラー] ネタ番号が見つかりませんでしたよ! [^v^]/

戻る """ % (mErrMessage,G_THIS_NAME) def DispIntroduce(): #-------- --------- --------- --------- --------- # 自己紹介表示 #-------- --------- --------- --------- --------- 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 # フォームからコメント取得 mIntroduce = gForm["comment"].value # タイトル設定 mTitle = "自己紹介" # 改行コマンドの処理 mIntroduce = re.sub("(?i)%%BR","
",mIntroduce) mIntroduce = re.sub("(?i)%%P","

",mIntroduce) print """

%s

%s
戻る
""" % (mTitle,mIntroduce,G_THIS_NAME) def WriteNeta(): #-------- --------- --------- --------- --------- # ネタフリをファイルに記録 #-------- --------- --------- --------- --------- 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 = mErr2 = mErr3 = "" m_array_Data = m_array_Tail = m_array_NewData = mCnt = [] # ログファイル読み込み [mErr,m_array_Data] = LoadFromFile(G_LOG_FILE) # ネタ番号カウンタ読み込み [mErr2,mCnt] = LoadFromFile(G_NETA_COUNT_FILE) mCnt = string.atoi(mCnt[0]) if mErr or mErr2: # 読み込みエラー処理 print "

[ エラー ] ログファイルを読み込めませんでしたよ! [^v^]/

\n" mMmessage = "0% 無事、登録されました。" else: # ネタカウンタをひとつ増やしカウントファイルに書き込み mCnt = mCnt + 1 mErr = WriteToFile(G_NETA_COUNT_FILE,"w",mCnt) if mErr: # ネタカウンタ書き込みエラー処理 print "

[ エラー ] ネタカウントファイルに書き込めませんでしたよ! [^v^]/

\n" mMmessage = "0% 無事、登録されました。" else: # ログデータの先頭に新規ネタフリ追加 mBuf = "%s,%s,%s\n" % (mCnt,gForm["neta"].value,G_TIME_NOW) m_array_Data.insert(0,mBuf) # 最大数を超えたネタを m_array_Tail に格納 m_array_NewData[0:G_MAX_NUM_OF_NETA] = m_array_Data[0:G_MAX_NUM_OF_NETA] m_array_Tail = m_array_Data[G_MAX_NUM_OF_NETA:] # m_array_Tail にネタが入っていて過去ログ保存機能が有効になっていたら if G_SAVE_OLD_LOGS and m_array_Tail: mLogIndex = len(m_array_Tail) - 1 m_array_Tail.reverse() for current in m_array_Tail: # ネタカウントを元に保存するファイル番号を計算 mFileName = int ((mCnt - G_MAX_NUM_OF_NETA - mLogIndex) / G_MAX_NUM_OF_OLD_NETA_PER_FILE) # 過去ログファイルに追可保存 m_array_Buf = [current] mErr3 = WriteToFile("%s/%s.txt" % (G_OLD_LOGS_DIR,mFileName), "a", m_array_Buf) mLogIndex = mLogIndex - 1 # ログ書き込み mErr = WriteToFile(G_LOG_FILE,"w",m_array_NewData) if mErr or mErr3: # 書き込みエラー処理 print "

[ エラー ] ログファイルに書き込めませんでしたよ! [^v^]/

\n" mMmessage = "0% 無事、登録されました。" else: mMmessage = "99.9% 無事、登録されました。" print """ たぶん2秒後に自動的に戻ります

%s

ここをクリックして下さい。


""" % (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