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 """ LINE Bot Server

✓ LINE Bot Server is Running

This is the backend service for the Earthquake Alert Bot.

The service is active and listening for webhook events from LINE.

""" # --- 地震查詢核心邏輯 (與之前相同) --- 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)] ) )