ForcePilot/backend/package/yuxi/channels/adapters/imessage/rate_limiter.py
Kris 068cf70fe9 feat(imessage): 实现完整的 iMessage 适配器基础模块
新增 iMessage 通道适配器完整实现,包含:
1. 核心适配器与工具工厂导出
2. 运行时存储、反射防护、会话路由等基础组件
3. 消息信封、线程管理、回复上下文格式化
4. Tapback 表情反应处理、自定义异常体系
5. 审批按钮、联系人解析、速率限制功能
6. 文本净化、目标解析、缓存管理模块
7. 配置 schema、多账户支持、安装向导等配置模块
8. 审计日志、媒体AI处理等扩展功能
2026-05-12 00:44:44 +08:00

54 lines
1.9 KiB
Python

from __future__ import annotations
import time
class LoopRateLimiter:
"""循环速率限制:检测持续回显循环并抑制对话。
当同一会话在短时间内反复收到相同内容的消息时,
判定为回显循环,对 conversation 进行抑制。
"""
def __init__(self, max_loops: int = 5, window_s: float = 30.0, cooldown_s: float = 60.0):
self._max_loops = max_loops
self._window_s = window_s
self._cooldown_s = cooldown_s
self._counters: dict[str, list[float]] = {}
self._suppressed: dict[str, float] = {}
def check(self, conversation_key: str, content: str) -> bool:
"""返回 True 表示应该抑制此消息。"""
if conversation_key in self._suppressed:
suppressed_at = self._suppressed[conversation_key]
if time.monotonic() - suppressed_at < self._cooldown_s:
return True
del self._suppressed[conversation_key]
now = time.monotonic()
if conversation_key not in self._counters:
self._counters[conversation_key] = []
timestamps = self._counters[conversation_key]
timestamps.append(now)
timestamps[:] = [t for t in timestamps if now - t <= self._window_s]
if len(timestamps) >= self._max_loops:
self._suppressed[conversation_key] = now
self._counters.pop(conversation_key, None)
return True
return False
def is_suppressed(self, conversation_key: str) -> bool:
if conversation_key in self._suppressed:
if time.monotonic() - self._suppressed[conversation_key] < self._cooldown_s:
return True
del self._suppressed[conversation_key]
return False
def reset(self, conversation_key: str) -> None:
self._counters.pop(conversation_key, None)
self._suppressed.pop(conversation_key, None)