ForcePilot/backend/package/yuxi/channel/extensions/freshdesk/pairing.py
Kris 3e861d6cd1 feat(freshdesk): 新增Freshdesk/Freshchat渠道插件
实现完整的Freshdesk和Freshchat集成支持,包含会话守卫、错误定义、消息去重、配置管理、webhook处理、出站消息发送、状态监控、安全校验、配对功能和流式回复支持
2026-05-21 10:47:20 +08:00

50 lines
1.4 KiB
Python

import logging
import random
import string
import time
logger = logging.getLogger(__name__)
CODE_TTL_SECONDS = 600
CODE_LENGTH = 6
MAX_GENERATE_PER_PEER_PER_MINUTE = 3
class FreshdeskPairing:
def __init__(self):
self._codes: dict[str, tuple[str, float]] = {}
self._gen_timestamps: dict[str, list[float]] = {}
async def generate_code(self, peer_id: str) -> str | None:
now = time.time()
timestamps = self._gen_timestamps.setdefault(peer_id, [])
timestamps[:] = [ts for ts in timestamps if now - ts < 60]
if len(timestamps) >= MAX_GENERATE_PER_PEER_PER_MINUTE:
logger.warning("Pairing code rate limited for peer %s", peer_id)
return None
code = "".join(random.choices(string.digits, k=CODE_LENGTH))
self._codes[peer_id] = (code, now + CODE_TTL_SECONDS)
timestamps.append(now)
return code
async def verify(self, peer_id: str, code: str) -> bool:
now = time.time()
entry = self._codes.get(peer_id)
if entry is None:
return False
saved_code, expires_at = entry
if now > expires_at:
del self._codes[peer_id]
return False
return saved_code == code
def cleanup(self):
now = time.time()
expired = [k for k, (_, exp) in self._codes.items() if now > exp]
for k in expired:
del self._codes[k]