File size: 7,121 Bytes
f2982ed
 
 
c516766
11a0fda
30dd21c
f2982ed
5a6637a
977ee64
 
 
 
 
cc64d31
30dd21c
 
977ee64
11a0fda
5a6637a
11a0fda
56007d7
 
11a0fda
977ee64
f2982ed
543461d
1aa845c
11a0fda
 
 
977ee64
1aa845c
f2982ed
11a0fda
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f2982ed
977ee64
11a0fda
f2982ed
 
11a0fda
f2982ed
 
65d5c85
5a6637a
851155e
5a6637a
f2982ed
5a6637a
65d5c85
5a6637a
 
f2982ed
 
5a6637a
851155e
977ee64
 
 
5a6637a
 
f2982ed
 
 
 
5a6637a
f2982ed
a12404a
f2982ed
65d5c85
f2982ed
11a0fda
851155e
f2982ed
977ee64
11a0fda
3507446
65d5c85
f2982ed
d839f1e
 
977ee64
0ce64c2
 
 
 
 
 
 
 
30dd21c
c516766
 
f7e740d
c516766
 
 
 
 
 
 
f2982ed
11a0fda
 
65d5c85
977ee64
 
65d5c85
9e14a7d
 
b4ee5dd
f2982ed
 
 
 
 
 
 
 
 
 
8fb4d94
f2982ed
 
851155e
 
5a6637a
977ee64
f2982ed
360e845
11a0fda
 
f2982ed
b4ee5dd
 
 
 
 
342ad24
 
 
cc64d31
342ad24
cc64d31
9040fe2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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()