from __future__ import annotations from dataclasses import dataclass, field from pathlib import Path from app.mail_notifier import MailNotifier from app.matrix_notifier import MatrixNotifier from app.models import NotificationDecision, ProcessorForwardEnvelope from app.notifications.formatter import NotificationFormatter @dataclass class DispatchReport: attempted: bool = False matrix_attempted: bool = False matrix_sent: bool = False matrix_event_id: str | None = None matrix_error: str | None = None matrix_image_attempted: bool = False matrix_image_sent: bool = False matrix_image_event_id: str | None = None matrix_image_mxc_uri: str | None = None matrix_image_error: str | None = None mail_attempted: bool = False mail_sent: bool = False mail_error: str | None = None errors: list[str] = field(default_factory=list) class NotificationDispatcher: def __init__( self, matrix_notifier: MatrixNotifier | None = None, mail_notifier: MailNotifier | None = None, ) -> None: self.matrix_notifier = matrix_notifier self.mail_notifier = mail_notifier async def dispatch( self, envelope: ProcessorForwardEnvelope, decision: NotificationDecision, ) -> DispatchReport: report = DispatchReport() if not decision.notify or decision.suppressed: return report report.attempted = True if "matrix" in decision.channels and self.matrix_notifier is not None: report.matrix_attempted = True matrix_body = NotificationFormatter.format_matrix_message( envelope=envelope, decision=decision, ) matrix_result = await self.matrix_notifier.send_message(matrix_body) report.matrix_sent = matrix_result.ok report.matrix_event_id = matrix_result.event_id report.matrix_error = matrix_result.error if matrix_result.error: report.errors.append(f"matrix: {matrix_result.error}") # Если есть отрисованный PNG, отправляем его вторым сообщением graph_image_path = envelope.event.graph_image_path if graph_image_path and Path(graph_image_path).exists(): report.matrix_image_attempted = True image_body = f"{envelope.event.trigger_name or 'Graph'} graph" image_result = await self.matrix_notifier.send_image( file_path=graph_image_path, body=image_body, ) report.matrix_image_sent = image_result.ok report.matrix_image_event_id = image_result.event_id report.matrix_image_mxc_uri = image_result.content_uri report.matrix_image_error = image_result.error if image_result.error: report.errors.append(f"matrix_image: {image_result.error}") if "mail" in decision.channels and self.mail_notifier is not None: report.mail_attempted = True subject = NotificationFormatter.format_mail_subject( envelope=envelope, decision=decision, ) body = NotificationFormatter.format_mail_body( envelope=envelope, decision=decision, ) attachments: list[str] = [] if envelope.event.graph_image_path: attachments.append(envelope.event.graph_image_path) mail_result = await self.mail_notifier.send_message( subject=subject, body=body, attachments=attachments, ) report.mail_sent = mail_result.ok report.mail_error = mail_result.error if mail_result.error: report.errors.append(f"mail: {mail_result.error}") return report