File size: 3,915 Bytes
f1e04a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
925fff4
 
f1e04a3
925fff4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1e04a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
925fff4
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
# app.py
# 首先匯入 config,以設定環境變數
import config

from flask import Flask, request, abort, send_from_directory
from linebot.v3 import WebhookHandler
from linebot.v3.exceptions import InvalidSignatureError
from linebot.v3.messaging import (
    Configuration, ApiClient, MessagingApi,
    ReplyMessageRequest
)
from linebot.v3.webhooks import MessageEvent, TextMessageContent

# 匯入指令處理器
from command_handler import process_message

# ------------------------------------------------------------------------------
# Flask & LINE Bot 設定
# ------------------------------------------------------------------------------
app = Flask(__name__)
line_config = Configuration(access_token=config.CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(config.CHANNEL_SECRET)

# ------------------------------------------------------------------------------
# Web 伺服器路由
# ------------------------------------------------------------------------------
@app.route("/", methods=["GET"])
def home():
    """[修改] 渲染一個簡潔的機器人狀態首頁。"""
    return """
<!doctype html>
<html lang="zh-Hant">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>LINE Bot Server Status</title>
    <style>
        body {
            background-color: #0f1115;
            color: #e6e8ef;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            text-align: center;
        }
        .container {
            padding: 2rem;
        }
        h1 {
            font-size: 2.2rem;
            margin-bottom: 1rem;
            color: #ffffff;
        }
        .status-ok {
            color: #22c55e; /* Green */
        }
        p {
            font-size: 1.1rem;
            color: #9aa4b2;
            line-height: 1.6;
            max-width: 600px;
        }
        .active {
            font-weight: bold;
            color: #22c55e; /* Green */
        }
    </style>
</head>
<body>
    <div class="container">
        <h1><span class="status-ok">✓</span> LINE Bot Server is Running</h1>
        <p>This is the backend service for the Earthquake Alert Bot.</p>
        <p>The service is <span class="active">active</span> and listening for webhook events from LINE.</p>
    </div>
</body>
</html>
"""

@app.route("/healthz")
def healthz():
    """健康檢查端點。"""
    return "ok"

@app.route("/static/<path:filename>")
def serve_static(filename):
    """提供靜態檔案(例如,生成的地圖)。"""
    return send_from_directory(config.STATIC_DIR, filename)

# ------------------------------------------------------------------------------
# LINE Webhook 處理器
# ------------------------------------------------------------------------------
@app.route("/callback", methods=["POST"])
def callback():
    """處理來自 LINE 平台的傳入 Webhooks。"""
    signature = request.headers.get("X-Line-Signature")
    body = request.get_data(as_text=True)
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return "OK"

@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
    """
    處理來自使用者的文字訊息並回覆。
    所有邏輯都委派給 command_handler。
    """
    base_url = request.url_root.rstrip("/")
    reply_messages = process_message(event.message.text, base_url)
    
    with ApiClient(line_config) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_api.reply_message_with_http_info(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=reply_messages
            )
        )