ForcePilot/backend/package/yuxi/channels/adapters/googlechat/target.py
Kris 87fc26cd15 refactor(googlechat): 整理并优化Google Chat适配器代码
- 调整依赖导入顺序与清理冗余空行
- 修复setup wizard步骤存储逻辑
- 新增消息编辑/转发标记、卡片控件支持
- 完善目标校验、媒体上传、配对存储功能
- 优化流式响应与错误处理逻辑
- 增强SSRF防护与配置灵活性
- 新增/扩展内置命令与卡片处理能力
- 调整媒体大小限制与类型参数
2026-05-13 16:09:31 +08:00

108 lines
3.2 KiB
Python

from __future__ import annotations
import re
from typing import Any
_CHANNEL_PREFIXES = ("googlechat:", "gchat:", "google-chat:")
_VALID_GC_RESOURCE_PREFIXES = frozenset({"spaces/", "users/"})
_MESSAGES_SUFFIX_RE = re.compile(r"/messages/[^/]+$")
def strip_message_suffix(target: str) -> tuple[str, bool]:
stripped = _MESSAGES_SUFFIX_RE.sub("", target)
return stripped, stripped != target
def detect_deprecated_target(target: str) -> str | None:
cleaned = _strip_channel_prefix(target)
for prefix in _VALID_GC_RESOURCE_PREFIXES:
if cleaned.startswith(prefix):
return None
return f"Target '{target}' does not use a valid Google Chat resource prefix (spaces/ or users/)"
def normalize_googlechat_target(target: str) -> dict[str, Any]:
if not target:
return {"raw": target, "type": "unknown"}
target = _strip_channel_prefix(target)
if "@" in target and not target.startswith(("spaces/", "users/")):
target = _convert_email_to_user(target)
if target.startswith("spaces/"):
parts = target.removeprefix("spaces/").split("/")
space_id = parts[0]
thread_key = parts[2] if len(parts) > 2 and parts[1] == "threads" else None
return {
"raw": target,
"type": "thread" if thread_key else "space",
"space_id": space_id,
"space_name": f"spaces/{space_id}",
"thread_key": thread_key,
"full_target": target,
}
if target.startswith("users/"):
user_id = target.removeprefix("users/")
cleaned = user_id.removeprefix("user:")
return {
"raw": target,
"type": "user",
"user_id": cleaned,
"user_name": f"users/{cleaned}",
"full_target": target,
}
if target.startswith("user:"):
user_id = target.removeprefix("user:")
return {
"raw": target,
"type": "user",
"user_id": user_id,
"user_name": f"users/{user_id}",
"full_target": f"users/{user_id}",
}
return {"raw": target, "type": "unknown"}
def is_googlechat_user_target(target: str) -> bool:
target = _strip_channel_prefix(target)
return target.startswith("users/") or target.startswith("user:")
def is_googlechat_space_target(target: str) -> bool:
target = _strip_channel_prefix(target)
return target.startswith("spaces/")
def resolve_targets(inputs: list[str], kind: str | None = None) -> list[dict[str, Any]]:
results: list[dict[str, Any]] = []
for target in inputs:
normalized = normalize_googlechat_target(target)
target_type = normalized.get("type", "unknown")
if kind and target_type != kind:
continue
results.append(normalized)
return results
def _strip_channel_prefix(target: str) -> str:
for prefix in _CHANNEL_PREFIXES:
if target.lower().startswith(prefix):
return target[len(prefix) :]
return target
def _convert_email_to_user(email: str) -> str:
email_match = re.match(r"^[\w.+-]+@[\w-]+\.[\w.-]+$", email)
if email_match:
return f"users/{email}"
return f"users/{email}"