ForcePilot/backend/package/yuxi/channels/adapters/msteams/runtime.py
Kris bd60c15df0 feat(msteams): 新增完整的 Microsoft Teams 适配器模块
实现了 Teams 机器人所需的全功能组件,包括:
- 基础命令解析与帮助卡片生成
- 租户验证与访问控制
- 自定义 UA 与媒体工具
- 消息分块、批注处理与会话管理
- 防抖、缓存与配置路由能力
- 投票、配对、审计与运行时状态管理
- TTS 语音合成与卡片构建工具
- 群组管理与权限控制逻辑
2026-05-12 00:46:44 +08:00

134 lines
4.4 KiB
Python

"""Microsoft Teams 运行时状态管理。
全局单例模式,管理 MSTeams 适配器的运行时状态,
支持多模块间共享连接状态、速率限制器和流管理器。
"""
from __future__ import annotations
import threading
from dataclasses import dataclass, field
from typing import Any
@dataclass
class MSTeamsRuntime:
"""Microsoft Teams 适配器运行时全局状态。
线程安全,支持读/写锁保护关键状态。
"""
app_id: str = ""
tenant_id: str = ""
connected: bool = False
connected_at: float = 0.0
service_url: str = "https://smba.trafficmanager.net/emea"
streaming_mode: str = "block"
feedback_enabled: bool = True
feedback_reflection: bool = False
sso_enabled: bool = False
max_media_size_mb: int = 100
rate_limit_ops_per_second: float = 5
dm_policy: str = "open"
group_policy: str = "open"
pending_uploads_count: int = 0
active_streams_count: int = 0
active_sessions_count: int = 0
metadata: dict[str, Any] = field(default_factory=dict)
_lock: threading.RLock = field(default_factory=threading.RLock, repr=False)
def update(self, **kwargs: Any) -> None:
with self._lock:
for key, value in kwargs.items():
if hasattr(self, key):
setattr(self, key, value)
self.metadata.setdefault("last_updated", 0)
def set_connected(self, app_id: str = "", tenant_id: str = "") -> None:
import time
with self._lock:
self.app_id = app_id or self.app_id
self.tenant_id = tenant_id or self.tenant_id
self.connected = True
self.connected_at = time.monotonic()
def set_disconnected(self) -> None:
with self._lock:
self.connected = False
self.connected_at = 0
def increment_pending_uploads(self, delta: int = 1) -> int:
with self._lock:
self.pending_uploads_count += delta
return self.pending_uploads_count
def decrement_pending_uploads(self, delta: int = 1) -> int:
with self._lock:
self.pending_uploads_count = max(0, self.pending_uploads_count - delta)
return self.pending_uploads_count
def increment_active_streams(self, delta: int = 1) -> int:
with self._lock:
self.active_streams_count += delta
return self.active_streams_count
def decrement_active_streams(self, delta: int = 1) -> int:
with self._lock:
self.active_streams_count = max(0, self.active_streams_count - delta)
return self.active_streams_count
def get_snapshot(self) -> dict[str, Any]:
with self._lock:
return {
"app_id": self.app_id[:12] + "..." if self.app_id else "",
"tenant_id": self.tenant_id[:12] + "..." if self.tenant_id else "",
"connected": self.connected,
"connected_at": self.connected_at,
"service_url": self.service_url,
"streaming_mode": self.streaming_mode,
"feedback_enabled": self.feedback_enabled,
"feedback_reflection": self.feedback_reflection,
"sso_enabled": self.sso_enabled,
"max_media_size_mb": self.max_media_size_mb,
"rate_limit_ops_per_second": self.rate_limit_ops_per_second,
"dm_policy": self.dm_policy,
"group_policy": self.group_policy,
"pending_uploads_count": self.pending_uploads_count,
"active_streams_count": self.active_streams_count,
"active_sessions_count": self.active_sessions_count,
**self.metadata,
}
_runtime: MSTeamsRuntime | None = None
_runtime_lock = threading.Lock()
def get_msteams_runtime() -> MSTeamsRuntime:
"""获取 MSTeams 全局运行时单例。"""
global _runtime
if _runtime is None:
with _runtime_lock:
if _runtime is None:
_runtime = MSTeamsRuntime()
return _runtime
def set_msteams_runtime(runtime: MSTeamsRuntime) -> None:
"""设置 MSTeams 全局运行时单例(用于注入替换)。"""
global _runtime
with _runtime_lock:
_runtime = runtime
def reset_msteams_runtime() -> None:
"""重置 MSTeams 全局运行时。"""
global _runtime
with _runtime_lock:
_runtime = MSTeamsRuntime()