Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import re | |
| import os | |
| import base64 | |
| import time | |
| from datetime import datetime, timedelta, timezone | |
| # 設定 | |
| SUPPORT_URL = "https://github.com/X1288664/LINE-Log-Manager-for-Hugging-face/blob/main/README.md" | |
| HELP_URL = "https://github.com/X1288664/LINE-Log-Manager-for-Hugging-face/blob/Q%26A/README.md" | |
| COPYRIGHT_URL = "https://github.com/X1288664/LINE-Log-Manager-for-Hugging-face/blob/copyright/README.md" | |
| CONTACT_URL = "https://forms.gle/mAUj1CdhufHFbiWs7" | |
| TS_URL = "https://github.com/X1288664/LINE-Log-Manager-for-Hugging-face/blob/troubleshooting/README.md" | |
| MANUAL_URL = "https://youtu.be/j2GJtO5BydA" | |
| JST = timezone(timedelta(hours=9)) | |
| def load_log_file(file, progress=gr.Progress()): | |
| """ログファイルを読み込む(プログレスバー付き)""" | |
| if not file: | |
| return None, "エラー(FILE-001): ファイルが選択されていません。" | |
| if not file.name.endswith(".txt"): | |
| return None, "エラー(FILE-005): TXTファイルを選択してください。" | |
| try: | |
| with open(file.name, "r", encoding="utf-8") as f: | |
| content = f.readlines() | |
| for _ in progress.tqdm(range(1, 101), desc="ログファイルを読み込み中..."): | |
| time.sleep(0.01) | |
| return content, None | |
| except Exception as e: | |
| return None, f"エラー(FILE-002): ファイルの読み込みに失敗しました ({str(e)})" | |
| def extract_date_range_logs(lines, start_date, end_date): | |
| """指定された日付範囲のログを抽出""" | |
| results = [] | |
| current_date = None | |
| for line in lines: | |
| date_match = re.match(r"(\d{4}/\d{1,2}/\d{1,2})", line) | |
| if date_match: | |
| try: | |
| current_date = datetime.strptime(date_match.group(1), "%Y/%m/%d") | |
| except ValueError: | |
| continue # 無効な日付フォーマットはスキップ | |
| if current_date and start_date <= current_date < end_date: | |
| results.append(line.strip()) | |
| return results | |
| def search_logs(file, keyword, year, month, day, progress=gr.Progress()): | |
| """ログ検索(プログレスバー付き)""" | |
| log_lines, error = load_log_file(file) | |
| if error: | |
| return "", error, None | |
| if not log_lines: | |
| return "", "エラー(FILE-003): ファイルが空です。", None | |
| is_word_search = bool(keyword.strip()) | |
| is_date_search = year != "----" and month != "----" and day != "----" | |
| if is_word_search and is_date_search: | |
| return "", "エラー(SEARCH-001): ワード検索と日付検索は同時に行えません。", None | |
| search_condition = "検索条件: なし" | |
| results = [] | |
| if is_word_search: | |
| search_condition = f"検索条件: ワード[{keyword}]" | |
| for line in progress.tqdm(log_lines, desc="検索中..."): | |
| if keyword in line: | |
| results.append(f"- {line.strip()}") | |
| elif is_date_search: | |
| try: | |
| search_date = f"{year}/{month}/{day}" | |
| start_date = datetime.strptime(search_date, "%Y/%m/%d") | |
| end_date = start_date + timedelta(days=1) | |
| search_condition = f"検索条件: 日付[{search_date}]" | |
| results = extract_date_range_logs(log_lines, start_date, end_date) | |
| results = [f"- {line.strip()}" for line in results] | |
| except ValueError: | |
| return "", "エラー(SEARCH-002): 無効な日付形式です。", None | |
| formatted_results = "\n".join(results) if results else "エラー(SEARCH-003): 一致する結果が見つかりませんでした。" | |
| return formatted_results, f"{len(results)} 件の結果が見つかりました。", search_condition | |
| def generate_download_link(results, search_condition, progress=gr.Progress()): | |
| """エクスポート処理(プログレスバー付き)""" | |
| if not results: | |
| return "エラー(EXPORT-001): エクスポートするデータがありません。" | |
| execution_time = datetime.now(JST).strftime("%Y%m%d_%H%M%S") | |
| JPN_date = datetime.now(JST).strftime("%Y/%m/%d %H:%M:%S") | |
| if "ワード" in search_condition: | |
| condition_text = search_condition.replace("検索条件: ワード[", "").replace("]", "").replace(" ", "_") | |
| elif "日付" in search_condition: | |
| condition_text = search_condition.replace("検索条件: 日付[", "").replace("]", "").replace("/", "_") | |
| else: | |
| condition_text = "検索条件なし" | |
| file_name = f"{execution_time}_LINE-Log-Manager-search-Export-{condition_text}.txt" | |
| file_content = ( | |
| "プログラム名: LINEログマネージャー\n" | |
| f"検索実行日: {JPN_date}\n" | |
| f"{search_condition}\n" | |
| f"ヒット件数: {len(results.splitlines())} 件\n" | |
| + "-" * 40 + "\n" | |
| + results + "\n" | |
| ) | |
| encoded_file = base64.b64encode(file_content.encode()).decode() | |
| for _ in progress.tqdm(range(1, 101), desc="エクスポート処理中..."): | |
| time.sleep(0.01) | |
| href = f'<a href="data:text/plain;base64,{encoded_file}" download="{file_name}">結果をダウンロード</a>' | |
| return href | |
| with gr.Blocks() as demo: | |
| gr.HTML("<h1>LINEログマネージャー</h1>") | |
| gr.Markdown(f"使い方は[こちら]({MANUAL_URL})") | |
| file_input = gr.File(label="ログファイルをアップロード") | |
| search_word = gr.Textbox(label="ユーザー検索ワード") | |
| year = gr.Dropdown(choices=["----"] + [str(y) for y in range(2020, 2041)], value="----", label="年") | |
| month = gr.Dropdown(choices=["----"] + [str(m) for m in range(1, 13)], value="----", label="月") | |
| day = gr.Dropdown(choices=["----"] + [str(d) for d in range(1, 32)], value="----", label="日") | |
| search_button = gr.Button("検索") | |
| result_table = gr.Textbox(label="検索結果", interactive=False, lines=10) | |
| result_message = gr.Textbox(label="ステータス", interactive=False) | |
| search_condition_state = gr.State() | |
| export_button = gr.Button("TXTをエクスポートする") | |
| export_output = gr.HTML() | |
| export_status = gr.Textbox(label="エクスポートメッセージ", interactive=False) | |
| search_button.click(search_logs, inputs=[file_input, search_word, year, month, day], outputs=[result_table, result_message, search_condition_state]) | |
| export_button.click(generate_download_link, inputs=[result_table, search_condition_state], outputs=[export_output]) | |
| gr.Markdown(f"[📖 ヘルプページ]({HELP_URL})") | |
| gr.Markdown(f"[⚠ トラブルシューティング]({TS_URL})") | |
| gr.Markdown(f"[❓ 問い合わせフォーム]({CONTACT_URL})") | |
| gr.Markdown(f"[🛠 サポート]({SUPPORT_URL})") | |
| gr.Markdown(f"[© コピーライト&作成者情報]({COPYRIGHT_URL})") | |
| gr.Markdown("---") | |
| gr.Markdown("This project code was partially generated with assistance from [OpenAI's ChatGPT.](https://chatgpt.com/)") | |
| gr.Markdown("This Application is Confidential.") | |
| gr.Markdown("パヤ爺/Studio MARX,2025. All rights reserved.") | |
| gr.Markdown("---") | |
| gr.Markdown("LINE Log Manager Hugging Face Edition Ver.2.1.0") | |
| demo.launch() | |