ForcePilot/backend/package/yuxi/channels/adapters/msteams/group_mgmt.py
Kris 939f1ba82a refactor(msteams): 整理代码结构并新增多项功能
本次提交对Microsoft Teams适配器代码进行了多维度优化与新增:
1.  调整多处导入顺序,优化代码可读性
2.  新增media_tools工具模块,提供媒体相关辅助函数
3.  新增thread_history模块,实现对话历史拉取与缓存功能
4.  新增connection_modes模块,支持webhook/websocket/polling三种连接模式
5.  扩展security.py与tool_policy.py,新增通配符配置校验与三级策略解析
6.  新增feedback会话记录功能
7.  为sent_message_cache添加自动清理任务
8.  优化normalizer模块,新增引用、编辑消息解析与线程上下文注入
9.  重构file_upload的SSRF防护逻辑,复用公共校验工具
10. 修复多处导入顺序与代码排版问题
11. 为消息发送添加断路器保护与异步去重锁
2026-05-13 16:12:31 +08:00

80 lines
2.1 KiB
Python

"""Microsoft Teams 群组管理。
addParticipant / removeParticipant / renameGroup 操作。
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from .graph import GraphClient
from yuxi.utils.logging_config import logger
async def add_participant(
client: GraphClient,
chat_id: str,
user_id: str,
role: str = "member",
) -> dict[str, Any]:
path = f"/chats/{chat_id}/members"
data = {
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": [role],
"user@odata.bind": f"https://graph.microsoft.com/v1.0/users('{user_id}')",
}
result = await client._request_with_retry("POST", path, json_data=data)
if "error" not in result:
logger.info(f"MSTeams participant added: {user_id} to {chat_id}")
return result
async def remove_participant(
client: GraphClient,
chat_id: str,
membership_id: str,
) -> dict[str, Any]:
path = f"/chats/{chat_id}/members/{membership_id}"
result = await client._request_with_retry("DELETE", path)
if "error" not in result:
logger.info(f"MSTeams participant removed: {membership_id} from {chat_id}")
return result
async def rename_group(
client: GraphClient,
chat_id: str,
new_name: str,
) -> dict[str, Any]:
path = f"/chats/{chat_id}"
data = {"topic": new_name}
result = await client._request_with_retry("PATCH", path, json_data=data)
if "error" not in result:
logger.info(f"MSTeams group renamed: {chat_id} -> {new_name}")
return result
async def list_members(
client: GraphClient,
chat_id: str,
) -> list[dict[str, Any]]:
path = f"/chats/{chat_id}/members"
result = await client._request_with_retry("GET", path)
if "error" in result:
return []
return result.get("value", [])
async def get_member_info(
client: GraphClient,
chat_id: str,
user_id: str,
) -> dict[str, Any] | None:
members = await list_members(client, chat_id)
for member in members:
if member.get("userId", "") == user_id:
return member
return None