Files
life-echo/api/app/adapters/sms/tencent.py
Kevin 309a051038 feat: 回忆录证据血缘与内部评测可追溯,顺带对齐本地评测台与 CI
数据库与模型:新增多版迁移(章节证据快照、对话血缘、记忆事实/时间线 lineage 等),把「成稿 ↔ 对话/记忆」的溯源信息落到表结构里。
业务链路:会话与 WS、回忆录/故事流水线、记忆写入与 enrichment 等跟着接上线索与快照;新增章节证据快照与评测侧 EvalTraceService 等模块,方便组评审用的证据包。
内部评测:自动化 run 与手工 memoir 评审共用可追溯证据;rubric/ judge 相关脚本与文档有配套调整。
app-eval-web:Memoir/实验详情里能展开看证据摘要与 evidence_trace(含对话轮次 id);Vite 代理与 development.sh 注入的 API 端口与当前默认内部评测端口一致,避免改端口后页面连错服务。
工程杂项:GitHub Actions / 仓库说明有更新;各适配器与支付/配额/plan 等多处为小改动或跟随主改动的收尾;新增/扩充了?
2026-04-08 15:37:09 +08:00

84 lines
2.8 KiB
Python

"""Tencent Cloud SMS adapter — implements SmsSender port."""
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
TencentCloudSDKException,
)
from tencentcloud.sms.v20210111 import models as sms_models
from tencentcloud.sms.v20210111 import sms_client
from app.core.logging import get_logger
logger = get_logger(__name__)
CODE_EXPIRE_MINUTES = 5
class TencentSmsSender:
def __init__(
self,
secret_id: str,
secret_key: str,
sdk_app_id: str,
sign_name: str,
template_id: str,
template_param_count: int = 2,
):
self._secret_id = secret_id
self._secret_key = secret_key
self._sdk_app_id = sdk_app_id
self._sign_name = sign_name
self._template_id = template_id
self._template_param_count = template_param_count
def send_verification_code(self, phone: str, code: str) -> bool:
if not self._secret_id or not self._secret_key:
logger.error("Tencent SMS credentials not configured")
return False
cred = credential.Credential(self._secret_id, self._secret_key)
client = sms_client.SmsClient(cred, "ap-guangzhou")
param_configs = [
[code, str(CODE_EXPIRE_MINUTES)],
[code],
]
if self._template_param_count == 1:
param_configs = [[code], [code, str(CODE_EXPIRE_MINUTES)]]
for template_params in param_configs:
try:
req = sms_models.SendSmsRequest()
req.SmsSdkAppId = self._sdk_app_id
req.SignName = self._sign_name
req.TemplateId = self._template_id
req.TemplateParamSet = template_params
req.PhoneNumberSet = [f"+86{phone}"]
resp = client.SendSms(req)
if resp.SendStatusSet and resp.SendStatusSet[0].Code == "Ok":
return True
status = resp.SendStatusSet[0] if resp.SendStatusSet else None
error_code = status.Code if status else "UNKNOWN"
if "TemplateParamSetNotMatchApprovedTemplate" in error_code:
continue
logger.error(
"SMS send failed: {} - {}",
error_code,
status.Message if status else "",
)
return False
except TencentCloudSDKException as e:
if "TemplateParamSetNotMatchApprovedTemplate" in str(e):
continue
logger.error("Tencent SMS SDK error: {}", e)
return False
except Exception as e:
logger.error("SMS send exception: {}", e)
return False
logger.error("All SMS template param configs failed")
return False