754214692e
- 新增 ai_enabled/ai_api_key/ai_base_url/ai_model 等配置项,通过 .env 管理 - 新增 app/services/ai_analyzer.py — DeepSeek API 调用 + 详情页正文提取 - 新增 extract_page_content() 从详情页抓取正文供 AI 分析 - Announcement 模型新增 ai_relevant / ai_analysis 字段 - 流水线集成 AI 分析步骤(关键词匹配后、通知前) - AI 标记为可承接的项目额外发送 markdown 着重通知 - 创建 alembic 迁移版本 6e8f4c2d1b0a
79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
from typing import Any
|
|
|
|
from app.config import settings
|
|
from app.wechat.client import WeChatClient
|
|
|
|
|
|
class NotificationService:
|
|
def __init__(self):
|
|
self.client = WeChatClient()
|
|
|
|
async def send(self, announcements: list[dict[str, Any]]) -> int:
|
|
if not settings.wechat_enabled:
|
|
return 0
|
|
if not announcements:
|
|
return 0
|
|
|
|
sent = 0
|
|
for ann in announcements:
|
|
try:
|
|
# 发送普通 textcard
|
|
title = ann.get("title", "")
|
|
if len(title) > 128:
|
|
title = title[:125] + "..."
|
|
|
|
purchase_name = ann.get("purchase_name", "")
|
|
if len(purchase_name) > 25:
|
|
purchase_name = purchase_name[:22] + "..."
|
|
|
|
pub_date = ann.get("publish_date")
|
|
time_str = pub_date.strftime("%Y-%m-%d %H:%M") if pub_date else "时间未知"
|
|
|
|
source_name = ann.get("source_name", "")
|
|
|
|
description = f"{source_name} | {purchase_name} | {time_str}"
|
|
|
|
url = ann.get("content_url", "")
|
|
|
|
if await self.client.send_textcard(title, description, url):
|
|
sent += 1
|
|
|
|
# AI 标记为可承接的,额外发送着重通知
|
|
ai_result = ann.get("ai_result")
|
|
if ai_result and ai_result.get("is_relevant"):
|
|
await self._send_ai_emphasis(ann, ai_result)
|
|
|
|
except Exception:
|
|
continue
|
|
|
|
return sent
|
|
|
|
async def _send_ai_emphasis(
|
|
self, ann: dict[str, Any], ai_result: dict[str, Any]
|
|
) -> bool:
|
|
"""发送 AI 分析的着重通知(markdown 格式)"""
|
|
title = ann.get("title", "")
|
|
purchase_name = ann.get("purchase_name", "")
|
|
pub_date = ann.get("publish_date")
|
|
time_str = pub_date.strftime("%Y-%m-%d %H:%M") if pub_date else "时间未知"
|
|
url = ann.get("content_url", "")
|
|
|
|
reason = ai_result.get("reason", "")
|
|
business_type = ai_result.get("business_type", "")
|
|
|
|
# 企业微信 markdown 格式
|
|
md = (
|
|
f"{settings.ai_analysis_title}\n"
|
|
f"---\n"
|
|
f"**标题:** [{title}]({url})\n"
|
|
f"> 采购人:{purchase_name}\n"
|
|
f"> 发布时间:{time_str}\n\n"
|
|
f"**🤖 AI 分析:**\n"
|
|
f"> {reason}\n\n"
|
|
f"**🏷 业务分类:** {business_type}\n"
|
|
f"---\n"
|
|
f"[📄 查看公告原文]({url})"
|
|
)
|
|
|
|
return await self.client.send_markdown(md)
|