mirror of
https://github.com/stardrophere/InsightRadar.git
synced 2026-06-06 00:00:05 +08:00
backend 去ai化
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
# 定时推送调度服务
|
||||
# 由 APScheduler 每分钟调用,检查当前时刻是否有用户需要接收推送,
|
||||
# 如匹配则生成摘要邮件并发送,同时写入 DeliveryHistory 防重复。
|
||||
# 推送优先级:有关键词且匹配 → 个性化简报;无关键词或无匹配 → 默认热点快报
|
||||
import logging
|
||||
import os
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
@@ -34,7 +30,7 @@ from app.utils.email_utils import send_html_email
|
||||
|
||||
logger = logging.getLogger("delivery_service")
|
||||
|
||||
# delivery_service 日志单独写文件
|
||||
|
||||
_delivery_log_dir = Path(__file__).resolve().parents[2] / "logs"
|
||||
_delivery_log_dir.mkdir(parents=True, exist_ok=True)
|
||||
_delivery_log_file = _delivery_log_dir / "delivery_check.log"
|
||||
@@ -51,6 +47,8 @@ if not logger.handlers:
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.propagate = False
|
||||
|
||||
# AI辅助生成:deepseek-v3-2,2026年3月20日
|
||||
|
||||
# 推送时间窗口:实际执行时刻与设定时间的最大容差(分钟)
|
||||
DELIVERY_WINDOW_MINUTES = int(os.getenv("DELIVERY_WINDOW_MINUTES", 2))
|
||||
# 同一用户两次推送之间的最小间隔(分钟)
|
||||
@@ -64,13 +62,10 @@ DEFAULT_MODE_HOURS = int(os.getenv("DEFAULT_MODE_HOURS", 24))
|
||||
# 用户时区无效时的兜底时区
|
||||
DEFAULT_FALLBACK_TIMEZONE = os.getenv("DEFAULT_FALLBACK_TIMEZONE", "Asia/Shanghai")
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 默认热点事件容器(无关键词时使用)
|
||||
# ==========================================
|
||||
@dataclass
|
||||
class _DefaultEventItem:
|
||||
"""
|
||||
默认热点事件容器
|
||||
无关键词订阅或关键词无匹配时的默认热点包装器,
|
||||
接口与 MatchedEventResult 保持一致,方便统一传给模板。
|
||||
"""
|
||||
@@ -81,10 +76,6 @@ class _DefaultEventItem:
|
||||
tags: list[str] = field(default_factory=list)
|
||||
is_default: bool = True
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 时区工具
|
||||
# ==========================================
|
||||
def _time_to_minutes(t: dt_time) -> int:
|
||||
return t.hour * 60 + t.minute
|
||||
|
||||
@@ -125,10 +116,10 @@ def _ensure_aware(dt: datetime) -> datetime:
|
||||
return dt.replace(tzinfo=timezone.utc)
|
||||
return dt
|
||||
|
||||
# AI辅助生成结束
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 数据库查询辅助
|
||||
# ==========================================
|
||||
def _should_skip_by_interval(db: Session, user_id: int) -> bool:
|
||||
"""检查用户是否仍在冷却期内,避免短时间内重复推送"""
|
||||
row = (
|
||||
@@ -297,9 +288,9 @@ def _record_delivery(
|
||||
db.commit()
|
||||
|
||||
|
||||
# ==========================================
|
||||
# AI辅助生成:deepseek-v3-2,2026年3月20日
|
||||
|
||||
# 推送准备
|
||||
# ==========================================
|
||||
@dataclass
|
||||
class _PendingPush:
|
||||
"""暂存需要发送邮件的信息,便于在 async 上下文中发送。"""
|
||||
@@ -309,6 +300,7 @@ class _PendingPush:
|
||||
html_body: str
|
||||
event_ids: list[int]
|
||||
|
||||
# AI生成结束
|
||||
|
||||
def _prepare_user_push(db: Session, user: AppUser, schedule: UserDeliverySchedule) -> _PendingPush | None:
|
||||
"""
|
||||
@@ -331,7 +323,6 @@ def _prepare_user_push(db: Session, user: AppUser, schedule: UserDeliverySchedul
|
||||
|
||||
pushed_ids = _get_already_pushed_event_ids(db, user_id)
|
||||
|
||||
# 决策:有关键词且有匹配 → 匹配模式;否则 → 默认热点模式
|
||||
items: list = []
|
||||
is_default = False
|
||||
|
||||
@@ -361,7 +352,6 @@ def _prepare_user_push(db: Session, user: AppUser, schedule: UserDeliverySchedul
|
||||
logger.info(f"用户 {user_id} 默认热点无可推送内容,跳过")
|
||||
return None
|
||||
|
||||
# 批量加载平台数据(来源名、标题、URL、排名)
|
||||
event_ids = [item.event.id for item in items]
|
||||
platforms_map = _load_event_platforms(db, event_ids)
|
||||
|
||||
@@ -383,9 +373,6 @@ def _prepare_user_push(db: Session, user: AppUser, schedule: UserDeliverySchedul
|
||||
)
|
||||
|
||||
|
||||
# ==========================================
|
||||
# 调度主入口
|
||||
# ==========================================
|
||||
async def check_and_deliver() -> None:
|
||||
"""
|
||||
定时推送主入口,由 APScheduler 每分钟调用。
|
||||
@@ -412,7 +399,6 @@ async def check_and_deliver() -> None:
|
||||
if not user:
|
||||
continue
|
||||
|
||||
# 将 UTC 转为用户本地时间,判断是否落在推送窗口内
|
||||
user_current = _user_local_time(now, user.timezone)
|
||||
if not _is_within_window(schedule.delivery_time, user_current):
|
||||
continue
|
||||
@@ -422,7 +408,6 @@ async def check_and_deliver() -> None:
|
||||
if pending is None:
|
||||
continue
|
||||
|
||||
# 异步按优先级尝试各邮件渠道
|
||||
sent = False
|
||||
for target_email in pending.email_targets:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user