feat: Implement basic and city command handlers for the bot, including user identity binding and unbinding.
This commit is contained in:
+69
-23
@@ -8,6 +8,51 @@ from src.bot.observability import CommandTrace
|
|||||||
from src.bot.runtime_coordinator import RuntimeStatus, render_runtime_status_html
|
from src.bot.runtime_coordinator import RuntimeStatus, render_runtime_status_html
|
||||||
|
|
||||||
|
|
||||||
|
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_command_head(head: str, name: str) -> bool:
|
||||||
|
base = f"/{name}"
|
||||||
|
return head == base or head.startswith(f"{base}@")
|
||||||
|
|
||||||
|
|
||||||
|
def _is_basic_command_text(text: str | None) -> bool:
|
||||||
|
head = _normalized_command_head(text)
|
||||||
|
return (
|
||||||
|
_is_command_head(head, "start")
|
||||||
|
or _is_command_head(head, "help")
|
||||||
|
or _is_command_head(head, "id")
|
||||||
|
or _is_command_head(head, "top")
|
||||||
|
or _is_command_head(head, "diag")
|
||||||
|
or _is_command_head(head, "bind")
|
||||||
|
or _is_command_head(head, "unbind")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BasicCommandHandler:
|
class BasicCommandHandler:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -20,29 +65,30 @@ class BasicCommandHandler:
|
|||||||
self.runtime_status_provider = runtime_status_provider
|
self.runtime_status_provider = runtime_status_provider
|
||||||
|
|
||||||
def register(self) -> None:
|
def register(self) -> None:
|
||||||
@self.bot.message_handler(commands=["start", "help"])
|
@self.bot.message_handler(
|
||||||
def _start_help(message):
|
content_types=["text"],
|
||||||
self.handle_start_help(message)
|
func=lambda message: _is_basic_command_text(getattr(message, "text", None)),
|
||||||
|
)
|
||||||
@self.bot.message_handler(commands=["id"])
|
def _basic(message):
|
||||||
def _id(message):
|
head = _normalized_command_head(getattr(message, "text", None))
|
||||||
self.handle_id(message)
|
if _is_command_head(head, "start") or _is_command_head(head, "help"):
|
||||||
|
self.handle_start_help(message)
|
||||||
@self.bot.message_handler(commands=["top"])
|
return
|
||||||
def _top(message):
|
if _is_command_head(head, "id"):
|
||||||
self.handle_top(message)
|
self.handle_id(message)
|
||||||
|
return
|
||||||
@self.bot.message_handler(commands=["diag"])
|
if _is_command_head(head, "top"):
|
||||||
def _diag(message):
|
self.handle_top(message)
|
||||||
self.handle_diag(message)
|
return
|
||||||
|
if _is_command_head(head, "diag"):
|
||||||
@self.bot.message_handler(commands=["bind"])
|
self.handle_diag(message)
|
||||||
def _bind(message):
|
return
|
||||||
self.handle_bind(message)
|
if _is_command_head(head, "bind"):
|
||||||
|
self.handle_bind(message)
|
||||||
@self.bot.message_handler(commands=["unbind"])
|
return
|
||||||
def _unbind(message):
|
if _is_command_head(head, "unbind"):
|
||||||
self.handle_unbind(message)
|
self.handle_unbind(message)
|
||||||
|
return
|
||||||
|
|
||||||
def handle_start_help(self, message: Any) -> None:
|
def handle_start_help(self, message: Any) -> None:
|
||||||
trace = CommandTrace("/start", message)
|
trace = CommandTrace("/start", message)
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ def _normalized_command_head(text: str | None) -> str:
|
|||||||
|
|
||||||
def _is_city_command_text(text: str | None) -> bool:
|
def _is_city_command_text(text: str | None) -> bool:
|
||||||
head = _normalized_command_head(text)
|
head = _normalized_command_head(text)
|
||||||
return head == "/city" or head.startswith("/city@")
|
return (
|
||||||
|
head == "/city"
|
||||||
|
or head.startswith("/city@")
|
||||||
|
or head == "/pwcity"
|
||||||
|
or head.startswith("/pwcity@")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CityCommandHandler:
|
class CityCommandHandler:
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ def _normalized_command_head(text: str | None) -> str:
|
|||||||
|
|
||||||
def _is_deb_command_text(text: str | None) -> bool:
|
def _is_deb_command_text(text: str | None) -> bool:
|
||||||
head = _normalized_command_head(text)
|
head = _normalized_command_head(text)
|
||||||
return head == "/deb" or head.startswith("/deb@")
|
return (
|
||||||
|
head == "/deb"
|
||||||
|
or head.startswith("/deb@")
|
||||||
|
or head == "/pwdeb"
|
||||||
|
or head.startswith("/pwdeb@")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DebCommandHandler:
|
class DebCommandHandler:
|
||||||
|
|||||||
+3
-3
@@ -145,15 +145,15 @@ class BotIOLayer:
|
|||||||
return (
|
return (
|
||||||
"🚀 <b>PolyWeather 天气查询机器人</b>\n\n"
|
"🚀 <b>PolyWeather 天气查询机器人</b>\n\n"
|
||||||
"可用指令:\n"
|
"可用指令:\n"
|
||||||
f"/city [城市名] - 查询城市天气预测与实测 (消耗 {CITY_QUERY_COST} 积分)\n"
|
f"/city [城市名] 或 /pwcity [城市名] - 查询城市天气预测与实测 (消耗 {CITY_QUERY_COST} 积分)\n"
|
||||||
f"/deb [城市名] - 查看 DEB 融合预测准确率 (消耗 {DEB_QUERY_COST} 积分)\n"
|
f"/deb [城市名] 或 /pwdeb [城市名] - 查看 DEB 融合预测准确率 (消耗 {DEB_QUERY_COST} 积分)\n"
|
||||||
"/top - 查看积分排行榜\n"
|
"/top - 查看积分排行榜\n"
|
||||||
"/id - 获取当前聊天的 Chat ID\n\n"
|
"/id - 获取当前聊天的 Chat ID\n\n"
|
||||||
"/diag - 查看 Bot 启动诊断\n\n"
|
"/diag - 查看 Bot 启动诊断\n\n"
|
||||||
"/bind - 绑定 Supabase 账号(可选)\n"
|
"/bind - 绑定 Supabase 账号(可选)\n"
|
||||||
"/unbind - 解除当前 Telegram 与网页账号绑定\n\n"
|
"/unbind - 解除当前 Telegram 与网页账号绑定\n\n"
|
||||||
"🔐 <i>/city 与 /deb 仅限官方群成员使用。</i>\n\n"
|
"🔐 <i>/city 与 /deb 仅限官方群成员使用。</i>\n\n"
|
||||||
"示例: <code>/city 伦敦</code>\n"
|
"示例: <code>/city 伦敦</code> 或 <code>/pwcity 伦敦</code>\n"
|
||||||
f"💡 <i>提示: 每日签到(有效发言满 {MESSAGE_MIN_LENGTH} 字)获得 <b>{MESSAGE_POINTS}</b> 积分,"
|
f"💡 <i>提示: 每日签到(有效发言满 {MESSAGE_MIN_LENGTH} 字)获得 <b>{MESSAGE_POINTS}</b> 积分,"
|
||||||
f"每日上限 {MESSAGE_DAILY_CAP} 分。</i>"
|
f"每日上限 {MESSAGE_DAILY_CAP} 分。</i>"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user