from __future__ import annotations import logging from django.conf import settings from review_agent.models import WorkflowNotificationRecord from .context import NotificationContext from .feishu_message_api import send_personal_message from .feishu_token import get_tenant_access_token from .message_builder import build_feishu_post_message, build_message_summary from .recipient import ResolvedFeishuTarget, resolve_configured_personal_recipient from .records import ( create_disabled_record, create_failed_record, create_success_record, existing_success_record, ) logger = logging.getLogger("review_agent.notifications.dispatcher") def dispatch_workflow_notification(context: NotificationContext) -> WorkflowNotificationRecord: existing = existing_success_record(context) if existing: return existing try: target = resolve_configured_personal_recipient() summary = build_message_summary(context, target) if not getattr(settings, "FEISHU_NOTIFY_ENABLED", False): return create_disabled_record(context, target, summary) if not target.ok: return create_failed_record( context, target, summary, error_code=target.error_code, error_message=target.error_message, ) token_result = get_tenant_access_token() if not token_result.ok: return create_failed_record( context, target, summary, error_code=token_result.error_code, error_message=token_result.error_message, ) payload = build_feishu_post_message(context, target) send_result = send_personal_message( tenant_access_token=token_result.tenant_access_token, receive_id_type=target.identifier_type, payload=payload, ) if send_result.ok: return create_success_record( context, target, summary, external_message_id=send_result.external_message_id, request_duration_ms=send_result.request_duration_ms, ) return create_failed_record( context, target, summary, error_code=send_result.error_code, error_message=send_result.error_message, request_duration_ms=send_result.request_duration_ms, ) except Exception as exc: logger.exception("Feishu notification dispatch failed", extra={"dedupe_key": context.dedupe_key}) fallback_target = ResolvedFeishuTarget( ok=False, identifier_type="missing", identifier_value="", display_name=getattr(settings, "FEISHU_DEFAULT_TARGET_NAME", "默认飞书接收人"), masked_identifier="", error_code="dispatch_exception", error_message=str(exc), ) return create_failed_record( context, fallback_target, "\n".join([context.title, *context.summary_lines]), error_code="dispatch_exception", error_message=str(exc), )