Spaces:
Sleeping
Sleeping
Update cwa_service.py
Browse files- cwa_service.py +22 -35
cwa_service.py
CHANGED
|
@@ -31,8 +31,9 @@ def fetch_cwa_alarm_list(limit: int = 5) -> str:
|
|
| 31 |
# ... (此函式內容不變) ...
|
| 32 |
return "\n\n".join(lines).strip()
|
| 33 |
|
| 34 |
-
# --- 顯著有感地震 (E-A0015-001)
|
| 35 |
def _parse_significant_earthquakes(obj: dict) -> pd.DataFrame:
|
|
|
|
| 36 |
records = obj.get("records") or obj.get("Records") or {}
|
| 37 |
quakes = records.get("earthquake") or records.get("Earthquake") or []
|
| 38 |
rows = []
|
|
@@ -40,8 +41,10 @@ def _parse_significant_earthquakes(obj: dict) -> pd.DataFrame:
|
|
| 40 |
ei = q.get("EarthquakeInfo") or q.get("earthquakeInfo") or {}
|
| 41 |
epic = ei.get("Epicenter") or ei.get("epicenter") or {}
|
| 42 |
mag_info = ei.get("Magnitude") or ei.get("magnitude") or ei.get("EarthquakeMagnitude") or {}
|
|
|
|
| 43 |
depth_raw = ei.get("FocalDepth") or ei.get("depth") or ei.get("Depth")
|
| 44 |
mag_raw = mag_info.get("MagnitudeValue") or mag_info.get("magnitudeValue") or mag_info.get("Value") or mag_info.get("value")
|
|
|
|
| 45 |
rows.append({
|
| 46 |
"ID": q.get("EarthquakeNo"), "Time": ei.get("OriginTime"),
|
| 47 |
"Lat": _to_float(epic.get("EpicenterLatitude") or epic.get("epicenterLatitude")),
|
|
@@ -70,6 +73,7 @@ def fetch_significant_earthquakes(days: int = 7, limit: int = 5) -> str:
|
|
| 70 |
df = _parse_significant_earthquakes(data)
|
| 71 |
if df.empty: return f"✅ 過去 {days} 天內沒有顯著有感地震報告。"
|
| 72 |
df = df.sort_values(by="Time", ascending=False).head(limit)
|
|
|
|
| 73 |
lines = [f"🚨 CWA 最新顯著有感地震 (近{days}天內):", "-" * 20]
|
| 74 |
for _, row in df.iterrows():
|
| 75 |
mag_str = f"{row['Magnitude']:.1f}" if pd.notna(row['Magnitude']) else "—"
|
|
@@ -84,52 +88,35 @@ def fetch_significant_earthquakes(days: int = 7, limit: int = 5) -> str:
|
|
| 84 |
except Exception as e:
|
| 85 |
return f"❌ 顯著地震查詢失敗:{e}"
|
| 86 |
|
| 87 |
-
|
| 88 |
# --- 最新一筆顯著地震 ---
|
| 89 |
def fetch_latest_significant_earthquake() -> dict | None:
|
| 90 |
-
"""從 CWA
|
| 91 |
if not CWA_API_KEY:
|
| 92 |
raise ValueError("錯誤:尚未設定 CWA_API_KEY Secret。")
|
| 93 |
|
| 94 |
now = datetime.now(timezone.utc)
|
| 95 |
-
time_from = (now - timedelta(days=
|
| 96 |
-
|
| 97 |
-
params = {
|
| 98 |
-
"Authorization": CWA_API_KEY,
|
| 99 |
-
"format": "JSON",
|
| 100 |
-
"timeFrom": time_from,
|
| 101 |
-
"limit": 1,
|
| 102 |
-
# [修正] 移除不支援的 sort 參數,API 預設即為時間倒序
|
| 103 |
-
# "sort": "OriginTime desc"
|
| 104 |
-
}
|
| 105 |
|
| 106 |
r = requests.get(CWA_SIGNIFICANT_API, params=params, timeout=15)
|
| 107 |
r.raise_for_status()
|
| 108 |
data = r.json()
|
| 109 |
|
| 110 |
-
|
| 111 |
-
|
|
|
|
| 112 |
return None
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
epic = q.get("Epicenter", {})
|
| 117 |
-
mag_info = ei.get("Magnitude", {})
|
| 118 |
-
|
| 119 |
-
depth_raw = ei.get("FocalDepth") or ei.get("Depth")
|
| 120 |
-
mag_raw = mag_info.get("MagnitudeValue") or mag_info.get("value") or mag_info.get("Magnitude")
|
| 121 |
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
"
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
if result["Time"]:
|
| 132 |
-
dt = pd.to_datetime(result["Time"]).tz_localize("UTC").tz_convert(TAIPEI_TZ)
|
| 133 |
-
result["TimeStr"] = dt.strftime('%Y-%m-%d %H:%M')
|
| 134 |
|
| 135 |
-
return
|
|
|
|
| 31 |
# ... (此函式內容不變) ...
|
| 32 |
return "\n\n".join(lines).strip()
|
| 33 |
|
| 34 |
+
# --- 顯著有感地震 (E-A0015-001) ---
|
| 35 |
def _parse_significant_earthquakes(obj: dict) -> pd.DataFrame:
|
| 36 |
+
"""最穩健的解析邏輯,供 /significant 和 /latest 共用"""
|
| 37 |
records = obj.get("records") or obj.get("Records") or {}
|
| 38 |
quakes = records.get("earthquake") or records.get("Earthquake") or []
|
| 39 |
rows = []
|
|
|
|
| 41 |
ei = q.get("EarthquakeInfo") or q.get("earthquakeInfo") or {}
|
| 42 |
epic = ei.get("Epicenter") or ei.get("epicenter") or {}
|
| 43 |
mag_info = ei.get("Magnitude") or ei.get("magnitude") or ei.get("EarthquakeMagnitude") or {}
|
| 44 |
+
|
| 45 |
depth_raw = ei.get("FocalDepth") or ei.get("depth") or ei.get("Depth")
|
| 46 |
mag_raw = mag_info.get("MagnitudeValue") or mag_info.get("magnitudeValue") or mag_info.get("Value") or mag_info.get("value")
|
| 47 |
+
|
| 48 |
rows.append({
|
| 49 |
"ID": q.get("EarthquakeNo"), "Time": ei.get("OriginTime"),
|
| 50 |
"Lat": _to_float(epic.get("EpicenterLatitude") or epic.get("epicenterLatitude")),
|
|
|
|
| 73 |
df = _parse_significant_earthquakes(data)
|
| 74 |
if df.empty: return f"✅ 過去 {days} 天內沒有顯著有感地震報告。"
|
| 75 |
df = df.sort_values(by="Time", ascending=False).head(limit)
|
| 76 |
+
|
| 77 |
lines = [f"🚨 CWA 最新顯著有感地震 (近{days}天內):", "-" * 20]
|
| 78 |
for _, row in df.iterrows():
|
| 79 |
mag_str = f"{row['Magnitude']:.1f}" if pd.notna(row['Magnitude']) else "—"
|
|
|
|
| 88 |
except Exception as e:
|
| 89 |
return f"❌ 顯著地震查詢失敗:{e}"
|
| 90 |
|
|
|
|
| 91 |
# --- 最新一筆顯著地震 ---
|
| 92 |
def fetch_latest_significant_earthquake() -> dict | None:
|
| 93 |
+
"""[修改] 從 CWA 獲取最新一筆顯著地震,並重用 _parse_significant_earthquakes 解析邏輯"""
|
| 94 |
if not CWA_API_KEY:
|
| 95 |
raise ValueError("錯誤:尚未設定 CWA_API_KEY Secret。")
|
| 96 |
|
| 97 |
now = datetime.now(timezone.utc)
|
| 98 |
+
time_from = (now - timedelta(days=2)).strftime("%Y-%m-%dT%H:%M:%S")
|
| 99 |
+
params = {"Authorization": CWA_API_KEY, "format": "JSON", "limit": 1}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
r = requests.get(CWA_SIGNIFICANT_API, params=params, timeout=15)
|
| 102 |
r.raise_for_status()
|
| 103 |
data = r.json()
|
| 104 |
|
| 105 |
+
# 直接調用最穩健的解析函式
|
| 106 |
+
df = _parse_significant_earthquakes(data)
|
| 107 |
+
if df.empty:
|
| 108 |
return None
|
| 109 |
|
| 110 |
+
# 將 DataFrame 的第一筆資料轉為字典
|
| 111 |
+
latest_eq_data = df.sort_values(by="Time", ascending=False).iloc[0].to_dict()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
+
# 從原始資料中手動加入圖片網址 (因為解析函式沒處理這個)
|
| 114 |
+
quakes = data.get("records", {}).get("Earthquake", [])
|
| 115 |
+
if quakes:
|
| 116 |
+
latest_eq_data["ImageURL"] = quakes[0].get("ReportImageURI")
|
| 117 |
+
|
| 118 |
+
# 格式化時間字串
|
| 119 |
+
if pd.notna(latest_eq_data.get("Time")):
|
| 120 |
+
latest_eq_data["TimeStr"] = latest_eq_data["Time"].strftime('%Y-%m-%d %H:%M')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
+
return latest_eq_data
|