feat: implement runway observations dashboard panel, add telegram alert utility, and create city payload service

This commit is contained in:
2569718930@qq.com
2026-05-15 15:37:25 +08:00
parent 5e8548999a
commit b45010a92e
3 changed files with 9 additions and 4 deletions
@@ -148,7 +148,7 @@ export function RunwayObservationsPanel() {
async () => { async () => {
await Promise.allSettled( await Promise.allSettled(
RUNWAY_OBSERVATION_CITIES.map((city) => RUNWAY_OBSERVATION_CITIES.map((city) =>
ensureCityDetail(city.key, false, "panel"), ensureCityDetail(city.key, true, "panel"),
), ),
); );
}, },
+7 -3
View File
@@ -502,6 +502,7 @@ MARKET_MONITOR_CITIES = [
_FUNCTION_HASHTAGS = { _FUNCTION_HASHTAGS = {
"runway": "#跑道观测", "runway": "#跑道观测",
"airport": "#机场观测",
"market": "#市场监控", "market": "#市场监控",
"trade": "#交易机会", "trade": "#交易机会",
} }
@@ -714,10 +715,10 @@ def _build_airport_status_message(
and latest_temp - max_so_far >= 0.3) and latest_temp - max_so_far >= 0.3)
flag = " \U0001f536" if new_high else "" flag = " \U0001f536" if new_high else ""
has_runway = bool(runway_pairs and runway_temps and len(runway_pairs) == len(runway_temps))
hashtag_line = _build_telegram_hashtag_line( hashtag_line = _build_telegram_hashtag_line(
"runway", "runway" if has_runway else "airport",
city=city, city=city,
station=airport_icao,
) )
lines = [hashtag_line, header + flag, ""] lines = [hashtag_line, header + flag, ""]
runway_shown = False runway_shown = False
@@ -1020,6 +1021,7 @@ def _run_market_monitor_cycle(bot: Any, chat_ids: List[str]) -> bool:
sent_any = False sent_any = False
try: try:
from web.app import _analyze from web.app import _analyze
from web.services.city_payloads import build_city_market_scan_payload
except Exception as exc: except Exception as exc:
logger.warning("market monitor push skipped: analyze import failed: {}", exc) logger.warning("market monitor push skipped: analyze import failed: {}", exc)
return False return False
@@ -1027,9 +1029,11 @@ def _run_market_monitor_cycle(bot: Any, chat_ids: List[str]) -> bool:
for city in MARKET_MONITOR_CITIES: for city in MARKET_MONITOR_CITIES:
try: try:
city_weather = _analyze(city) city_weather = _analyze(city)
market = city_weather.get("market_scan") or {} scan_payload = build_city_market_scan_payload(city_weather)
market = scan_payload.get("market_scan") or {}
if not market.get("available"): if not market.get("available"):
continue continue
city_weather["market_scan"] = market
message = _build_market_monitor_message(city, city_weather) message = _build_market_monitor_message(city, city_weather)
for chat_id in chat_ids: for chat_id in chat_ids:
try: try:
+1
View File
@@ -265,6 +265,7 @@ def build_city_detail_payload(
"center_station_candidate": data.get("center_station_candidate"), "center_station_candidate": data.get("center_station_candidate"),
"airport_vs_network_delta": data.get("airport_vs_network_delta"), "airport_vs_network_delta": data.get("airport_vs_network_delta"),
"airport_current": data.get("airport_current") or {}, "airport_current": data.get("airport_current") or {},
"amos": data.get("amos") or {},
"nearby_source": data.get("nearby_source") or ("mgm" if str(data.get("name") or "").lower() in TURKISH_MGM_CITIES else "metar_cluster"), "nearby_source": data.get("nearby_source") or ("mgm" if str(data.get("name") or "").lower() in TURKISH_MGM_CITIES else "metar_cluster"),
"ai_analysis": data.get("ai_analysis") or "", "ai_analysis": data.get("ai_analysis") or "",
"errors": {}, "errors": {},