chore: harden runtime checks and split websocket inbound/outbound flows

This commit is contained in:
2026-03-02 18:17:09 +08:00
parent 89eb94486d
commit e1ce17f2aa
7 changed files with 481 additions and 23 deletions

View File

@@ -9,6 +9,7 @@
import asyncio
import os
import json
import logging
from datetime import datetime, date, timedelta
from typing import Optional
@@ -16,6 +17,7 @@ import httpx
from dotenv import load_dotenv
load_dotenv()
logger = logging.getLogger("cs_agent")
WECHAT_WEBHOOK = os.getenv("WECHAT_WEBHOOK", "")
SUMMARY_EMAIL = os.getenv("SUMMARY_EMAIL", "") # 收摘要的邮箱
@@ -130,7 +132,7 @@ async def _ai_summary(raw_text: str) -> str:
async def _send_wechat(content: str):
"""推送到企业微信群机器人markdown 格式,单条 ≤4096 字节自动分段)"""
if not WECHAT_WEBHOOK:
print("[DailySummary] 未配置 WECHAT_WEBHOOK跳过推送")
logger.info("[DailySummary] 未配置 WECHAT_WEBHOOK跳过推送")
return
# 企业微信单条 markdown 限 4096 字节,超长自动分段
@@ -148,11 +150,11 @@ async def _send_wechat(content: str):
resp = await client.post(WECHAT_WEBHOOK, json=payload)
data = resp.json()
if data.get("errcode") == 0:
print(f"[DailySummary] 企业微信推送成功(第{i+1}段)")
logger.info("[DailySummary] 企业微信推送成功(第%s段)", i + 1)
else:
print(f"[DailySummary] 企业微信推送失败: {data}")
logger.warning("[DailySummary] 企业微信推送失败: %s", data)
except Exception as e:
print(f"[DailySummary] 企业微信推送异常: {e}")
logger.exception("[DailySummary] 企业微信推送异常: %s", e)
# ──────────────────────────────────────────
@@ -178,9 +180,9 @@ def _send_email(subject: str, body: str):
s.starttls()
s.login(email_sender.smtp_user, email_sender.smtp_password)
s.sendmail(email_sender.smtp_user, [SUMMARY_EMAIL], msg.as_string())
print(f"[DailySummary] 日报邮件已发送至 {SUMMARY_EMAIL}")
logger.info("[DailySummary] 日报邮件已发送至 %s", SUMMARY_EMAIL)
except Exception as e:
print(f"[DailySummary] 日报邮件发送失败: {e}")
logger.exception("[DailySummary] 日报邮件发送失败: %s", e)
# ──────────────────────────────────────────
@@ -244,7 +246,7 @@ async def send_daily_summary(target_date: str = ""):
if not target_date:
target_date = datetime.now().strftime("%Y-%m-%d")
print(f"[DailySummary] 开始生成 {target_date} 日报...")
logger.info("[DailySummary] 开始生成 %s 日报...", target_date)
raw_text = _build_stats_text(target_date)
ai_text = await _ai_summary(raw_text)
@@ -258,7 +260,7 @@ async def send_daily_summary(target_date: str = ""):
email_body = f"{ai_text}\n\n{'='*40}\n\n{raw_text}"
_send_email(title, email_body)
print(f"[DailySummary] 日报推送完成")
logger.info("[DailySummary] 日报推送完成")
return ai_text
@@ -268,7 +270,7 @@ async def send_daily_summary(target_date: str = ""):
async def scheduler():
"""每天 SEND_HOUR:SEND_MINUTE 触发日报"""
print(f"[DailySummary] 定时日报已启动,发送时间 {SEND_HOUR:02d}:{SEND_MINUTE:02d}")
logger.info("[DailySummary] 定时日报已启动,发送时间 %02d:%02d", SEND_HOUR, SEND_MINUTE)
sent_today: Optional[str] = None # 记录已发日期,防重复
while True:
@@ -280,7 +282,7 @@ async def scheduler():
try:
await send_daily_summary(today)
except Exception as e:
print(f"[DailySummary] 日报生成出错: {e}")
logger.exception("[DailySummary] 日报生成出错: %s", e)
# 每 30 秒检查一次
await asyncio.sleep(30)
@@ -294,5 +296,5 @@ if __name__ == "__main__":
import sys
target = sys.argv[1] if len(sys.argv) > 1 else ""
result = asyncio.run(send_daily_summary(target))
print("\n=== AI 摘要 ===")
print(result)
logger.info("\n=== AI 摘要 ===")
logger.info(result)

View File

@@ -4,12 +4,14 @@
"""
import asyncio
import os
import logging
from datetime import datetime
import httpx
from dotenv import load_dotenv
load_dotenv()
logger = logging.getLogger("cs_agent")
_last_push: dict[tuple[str, str], tuple[str, str, float]] = {}
@@ -38,6 +40,7 @@ def _get_recent_conversation(customer_id: str, acc_id: str, last_n: int = 8) ->
from db.chat_log_db import get_recent_conversation
return get_recent_conversation(customer_id, acc_id, limit=last_n)
except Exception:
logger.debug("[WechatChatLog] 获取近期对话失败,返回空列表", exc_info=True)
return []
@@ -68,7 +71,7 @@ async def push_chat_to_wechat(
return
_last_push[key] = ((customer_msg or ""), (reply_msg or ""), now)
except Exception:
pass
logger.debug("[WechatChatLog] 去重检查异常,忽略本次去重", exc_info=True)
reply_msg = _truncate(reply_msg, 300)
ts = datetime.now().strftime("%H:%M")
shop = acc_id or "未知店铺"
@@ -109,11 +112,11 @@ async def push_chat_to_wechat(
)
data = resp.json()
if data.get("errcode") == 0:
pass # 成功静默
return
else:
print(f"[WechatChatLog] 推送失败: {data}")
logger.warning("[WechatChatLog] 推送失败: %s", data)
except Exception as e:
print(f"[WechatChatLog] 推送异常: {e}")
logger.exception("[WechatChatLog] 推送异常: %s", e)
async def send_morning_startup():
@@ -129,14 +132,14 @@ async def send_morning_startup():
webhook,
json={"msgtype": "markdown", "markdown": {"content": content}},
)
print(f"[WechatChatLog] 早8点启动消息已发送")
logger.info("[WechatChatLog] 早8点启动消息已发送")
except Exception as e:
print(f"[WechatChatLog] 启动消息发送失败: {e}")
logger.exception("[WechatChatLog] 启动消息发送失败: %s", e)
async def morning_startup_scheduler():
"""每天 8:00 发送启动消息"""
print("[WechatChatLog] 早8点启动消息定时任务已启动")
logger.info("[WechatChatLog] 早8点启动消息定时任务已启动")
sent_today = None
while True:
now = datetime.now()