LINE-ROBOT / app.py
cwadayi's picture
Update app.py
d761501 verified
raw
history blame
4.71 kB
import os
from flask import Flask, request, abort
from linebot.v3 import WebhookHandler
from linebot.v3.exceptions import InvalidSignatureError
from linebot.v3.messaging import (
Configuration, ApiClient, MessagingApi,
ReplyMessageRequest, TextMessage
)
from linebot.v3.webhooks import MessageEvent, TextMessageContent
import requests
import pandas as pd
from datetime import datetime, timedelta
# --- 環境變數 ---
CHANNEL_ACCESS_TOKEN = os.getenv('CHANNEL_ACCESS_TOKEN')
CHANNEL_SECRET = os.getenv('CHANNEL_SECRET')
# --- Flask & LINE Bot 初始化 ---
app = Flask(__name__)
configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(CHANNEL_SECRET)
# --- ✨✨✨ 新增的歡迎頁面路由 ✨✨✨ ---
@app.route("/", methods=['GET'])
def home():
# 當有人用瀏覽器訪問根網址時,回傳這段 HTML 訊息
return """
<html>
<head>
<title>LINE Bot Server</title>
<style>
body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f2f5; margin: 0; }
.container { text-align: center; padding: 40px; background-color: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
h1 { color: #1dcd00; }
p { color: #333; font-size: 1.2em; }
.status { font-weight: bold; color: #28a745; }
</style>
</head>
<body>
<div class="container">
<h1>✓ LINE Bot Server is Running</h1>
<p>This is the backend service for the Earthquake Alert Bot.</p>
<p>The service is <span class="status">active</span> and listening for webhook events from LINE.</p>
</div>
</body>
</html>
"""
# --- 地震查詢核心邏輯 (與之前相同) ---
USGS_API_BASE_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query"
def fetch_earthquake_data_for_line():
"""查詢過去 24 小時內規模 5.0 以上的地震,並回傳格式化的文字。"""
now = datetime.now()
yesterday = now - timedelta(days=1)
params = {
"format": "geojson",
"starttime": yesterday.strftime('%Y-%m-%d'),
"endtime": now.strftime('%Y-%m-%d'),
"minmagnitude": 5.0,
"limit": 10,
"orderby": "time"
}
try:
response = requests.get(USGS_API_BASE_URL, params=params, timeout=15)
response.raise_for_status()
data = response.json()
features = data.get('features', [])
if not features:
return "✅ 過去24小時內,全球無規模 5.0 以上的顯著地震。"
reply_text = f"🚨 近 24 小時全球顯著地震 (M≥5.0):\n{'-'*20}\n"
for feature in features:
prop = feature['properties']
mag = prop['mag']
place = prop['place']
event_time = datetime.fromtimestamp(prop['time'] / 1000).strftime('%H:%M')
reply_text += f"震級: {mag:.1f} | 時間: {event_time} (UTC)\n地點: {place}\n\n"
return reply_text.strip()
except requests.exceptions.RequestException as e:
return f"❌ 查詢失敗,無法連接到 USGS 伺服器: {e}"
except Exception as e:
return f"❌ 處理資料時發生未知錯誤: {e}"
# --- Flask Webhook 路由 (與之前相同) ---
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
app.logger.info("Invalid signature. Please check your channel secret.")
abort(400)
return 'OK'
# --- LINE 訊息處理 (與之前相同) ---
@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
user_message = event.message.text
reply_text = ""
if "地震" in user_message or "quake" in user_message.lower():
reply_text = fetch_earthquake_data_for_line()
elif "你好" in user_message or "hi" in user_message.lower():
reply_text = "👋 你好!我是地震查詢機器人,試著傳送「地震」來查詢最新資訊吧!"
else:
return
with ApiClient(configuration) as api_client:
line_bot_api = MessagingApi(api_client)
line_bot_api.reply_message_with_http_info(
ReplyMessageRequest(
reply_token=event.reply_token,
messages=[TextMessage(text=reply_text)]
)
)