|
@@ -26,6 +26,7 @@ from enum import Enum
|
|
|
from typing import Any, Callable, Dict, List, Optional, Union
|
|
from typing import Any, Callable, Dict, List, Optional, Union
|
|
|
|
|
|
|
|
import lark_oapi as lark
|
|
import lark_oapi as lark
|
|
|
|
|
+import requests
|
|
|
from lark_oapi.api.contact.v3 import GetUserRequest, GetUserResponse
|
|
from lark_oapi.api.contact.v3 import GetUserRequest, GetUserResponse
|
|
|
from lark_oapi.api.im.v1 import (
|
|
from lark_oapi.api.im.v1 import (
|
|
|
CreateMessageRequest, CreateMessageRequestBody,
|
|
CreateMessageRequest, CreateMessageRequestBody,
|
|
@@ -842,11 +843,48 @@ class FeishuClient:
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
if not self._bot_open_id:
|
|
if not self._bot_open_id:
|
|
|
- # 如果没有缓存机器人 open_id,假设有 mention 就是 @了机器人
|
|
|
|
|
- return len(mentions) > 0
|
|
|
|
|
|
|
+ try:
|
|
|
|
|
+ self._load_bot_open_id()
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ logger.exception("获取机器人 open_id 失败,拒绝处理群聊 mention")
|
|
|
|
|
+ return False
|
|
|
|
|
|
|
|
return any(m.id.open_id == self._bot_open_id for m in mentions)
|
|
return any(m.id.open_id == self._bot_open_id for m in mentions)
|
|
|
|
|
|
|
|
|
|
+ def _load_bot_open_id(self) -> str:
|
|
|
|
|
+ """从飞书查询当前应用机器人的 open_id。"""
|
|
|
|
|
+ token_response = requests.post(
|
|
|
|
|
+ f"{self.domain.value}/open-apis/auth/v3/tenant_access_token/internal/",
|
|
|
|
|
+ json={"app_id": self.app_id, "app_secret": self.app_secret},
|
|
|
|
|
+ timeout=10,
|
|
|
|
|
+ )
|
|
|
|
|
+ token_response.raise_for_status()
|
|
|
|
|
+ token_payload = token_response.json()
|
|
|
|
|
+ if int(token_payload.get("code") or 0) != 0:
|
|
|
|
|
+ raise RuntimeError(
|
|
|
|
|
+ f"获取 tenant_access_token 失败: {token_payload.get('msg')}"
|
|
|
|
|
+ )
|
|
|
|
|
+ tenant_access_token = str(
|
|
|
|
|
+ token_payload.get("tenant_access_token") or ""
|
|
|
|
|
+ ).strip()
|
|
|
|
|
+ if not tenant_access_token:
|
|
|
|
|
+ raise RuntimeError("飞书未返回 tenant_access_token")
|
|
|
|
|
+
|
|
|
|
|
+ bot_response = requests.get(
|
|
|
|
|
+ f"{self.domain.value}/open-apis/bot/v3/info",
|
|
|
|
|
+ headers={"Authorization": f"Bearer {tenant_access_token}"},
|
|
|
|
|
+ timeout=10,
|
|
|
|
|
+ )
|
|
|
|
|
+ bot_response.raise_for_status()
|
|
|
|
|
+ bot_payload = bot_response.json()
|
|
|
|
|
+ if int(bot_payload.get("code") or 0) != 0:
|
|
|
|
|
+ raise RuntimeError(f"获取机器人信息失败: {bot_payload.get('msg')}")
|
|
|
|
|
+ bot_open_id = str((bot_payload.get("bot") or {}).get("open_id") or "").strip()
|
|
|
|
|
+ if not bot_open_id:
|
|
|
|
|
+ raise RuntimeError("飞书机器人信息缺少 open_id")
|
|
|
|
|
+ self._bot_open_id = bot_open_id
|
|
|
|
|
+ return bot_open_id
|
|
|
|
|
+
|
|
|
def _strip_bot_mention(self, text: str, mentions: List) -> str:
|
|
def _strip_bot_mention(self, text: str, mentions: List) -> str:
|
|
|
"""去除 @机器人 的文本"""
|
|
"""去除 @机器人 的文本"""
|
|
|
result = text
|
|
result = text
|