Files
PolyWeather/src/bot/handlers/deb.py
T

116 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
from typing import Any
from loguru import logger
from src.bot.command_guard import CommandGuard
from src.bot.io_layer import BotIOLayer
from src.bot.observability import CommandTrace
from src.bot.services.deb_command_service import DebCommandService
from src.bot.settings import DEB_QUERY_COST
def _normalized_command_head(text: str | None) -> str:
raw = str(text or "")
for marker in (
"\ufeff",
"\u200b",
"\u200c",
"\u200d",
"\u200e",
"\u200f",
"\u2060",
"\u2066",
"\u2067",
"\u2068",
"\u2069",
"\u202a",
"\u202b",
"\u202c",
"\u202d",
"\u202e",
):
raw = raw.replace(marker, "")
raw = raw.strip()
if raw[:1] in {"", "", "", "", ""}:
raw = "/" + raw[1:]
return raw.split(maxsplit=1)[0].lower() if raw else ""
def _is_deb_command_text(text: str | None) -> bool:
head = _normalized_command_head(text)
return head == "/deb" or head.startswith("/deb@")
class DebCommandHandler:
def __init__(
self,
bot: Any,
guard: CommandGuard,
deb_service: DebCommandService,
io_layer: BotIOLayer,
):
self.bot = bot
self.guard = guard
self.deb_service = deb_service
self.io_layer = io_layer
def register(self) -> None:
@self.bot.message_handler(
func=lambda message: _is_deb_command_text(getattr(message, "text", None)),
content_types=["text"],
)
def _deb(message):
self.handle(message)
def handle(self, message: Any) -> None:
trace = CommandTrace("/deb", message)
try:
parts = (message.text or "").split(maxsplit=1)
if len(parts) < 2:
trace.set_status("bad_request", "missing_city")
self.io_layer.send_query_message(
message,
"❌ 用法: <code>/deb ankara</code>",
parse_mode="HTML",
)
return
city_input = parts[1].strip().lower()
city_name = self.deb_service.resolve_city(city_input)
if not self.deb_service.has_history(city_name):
trace.set_status("bad_request", "history_missing")
self.io_layer.send_query_message(
message,
f"❌ 暂无 {city_name} 的历史数据。",
parse_mode="HTML",
)
return
if not self.guard.ensure_access_and_points(message, DEB_QUERY_COST, "/deb"):
trace.set_status("blocked", "guard_rejected")
return
report_result = self.deb_service.build_report(city_name, DEB_QUERY_COST)
if not report_result.ok:
trace.set_status("failed", report_result.error or "deb_report_failed")
self.io_layer.send_query_message(
message,
f"❌ 查询失败: {report_result.error}",
)
return
self.io_layer.send_query_message(
message,
str(report_result.report),
parse_mode="HTML",
)
trace.set_status("ok", city_name)
except Exception as exc:
trace.set_status("failed", "unexpected_error")
logger.exception("查询 /deb 失败")
self.io_layer.send_query_message(message, f"❌ 查询失败: {exc}")
finally:
trace.emit()