127 lines
4.1 KiB
Python
127 lines
4.1 KiB
Python
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass, field
|
|
from typing import List, Optional, Sequence
|
|
|
|
from mobilizon_reshare.dataclasses import PublicationNotification, EventPublication
|
|
from mobilizon_reshare.models.notification import NotificationStatus
|
|
from mobilizon_reshare.models.publication import PublicationStatus
|
|
from mobilizon_reshare.publishers import get_active_notifiers
|
|
from mobilizon_reshare.publishers.abstract import (
|
|
AbstractPlatform,
|
|
)
|
|
from mobilizon_reshare.publishers.coordinators import (
|
|
logger,
|
|
BasePublicationReport,
|
|
BaseCoordinatorReport,
|
|
)
|
|
from mobilizon_reshare.publishers.coordinators.event_publishing import (
|
|
EventPublicationReport,
|
|
)
|
|
from mobilizon_reshare.publishers.platforms.platform_mapping import (
|
|
get_notifier_class,
|
|
get_formatter_class,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class PublicationNotificationReport(BasePublicationReport):
|
|
status: NotificationStatus
|
|
notification: PublicationNotification
|
|
|
|
@property
|
|
def successful(self):
|
|
return self.status == NotificationStatus.COMPLETED
|
|
|
|
def get_failure_message(self):
|
|
if not self.reason:
|
|
logger.error("Report of failure without reason.", exc_info=True)
|
|
return (
|
|
f"Failed with status: {self.status.name}.\n"
|
|
f"Reason: {self.reason}\n"
|
|
f"Publisher: {self.notification.publisher.name}\n"
|
|
f"Publication: {self.notification.publication.id}"
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class NotifierCoordinatorReport(BaseCoordinatorReport):
|
|
reports: Sequence[PublicationNotificationReport]
|
|
notifications: Sequence[PublicationNotification] = field(default_factory=list)
|
|
|
|
|
|
class Sender:
|
|
def __init__(
|
|
self,
|
|
message: str,
|
|
publication: EventPublication,
|
|
platforms: List[AbstractPlatform] = None,
|
|
):
|
|
self.message = message
|
|
self.platforms = platforms
|
|
self.publication = publication
|
|
|
|
def send_to_all(self) -> NotifierCoordinatorReport:
|
|
reports = []
|
|
notifications = []
|
|
for platform in self.platforms:
|
|
notification = PublicationNotification(
|
|
platform, get_formatter_class(platform.name)(), self.publication
|
|
)
|
|
try:
|
|
platform.send(self.message)
|
|
report = PublicationNotificationReport(
|
|
NotificationStatus.COMPLETED, self.message, notification
|
|
)
|
|
except Exception as e:
|
|
msg = f"[{platform.name}] Failed to notify failure of message:\n{self.message}"
|
|
logger.critical(msg)
|
|
logger.exception(e)
|
|
report = PublicationNotificationReport(
|
|
NotificationStatus.FAILED, msg, notification
|
|
)
|
|
notifications.append(notification)
|
|
reports.append(report)
|
|
return NotifierCoordinatorReport(reports=reports, notifications=notifications)
|
|
|
|
|
|
class AbstractNotifiersCoordinator(ABC):
|
|
def __init__(
|
|
self, report: BasePublicationReport, notifiers: List[AbstractPlatform] = None
|
|
):
|
|
self.platforms = notifiers or [
|
|
get_notifier_class(notifier)() for notifier in get_active_notifiers()
|
|
]
|
|
self.report = report
|
|
|
|
@abstractmethod
|
|
def notify_failure(self):
|
|
pass
|
|
|
|
|
|
class PublicationFailureNotifiersCoordinator(AbstractNotifiersCoordinator):
|
|
"""
|
|
Sends a notification of a failure report to the active platforms
|
|
"""
|
|
|
|
report: EventPublicationReport
|
|
platforms: List[AbstractPlatform]
|
|
|
|
def notify_failure(self) -> Optional[NotifierCoordinatorReport]:
|
|
logger.info("Sending failure notifications")
|
|
if self.report.status == PublicationStatus.FAILED:
|
|
return Sender(
|
|
self.report.get_failure_message(),
|
|
self.report.publication,
|
|
self.platforms,
|
|
).send_to_all()
|
|
|
|
|
|
class PublicationFailureLoggerCoordinator(PublicationFailureNotifiersCoordinator):
|
|
"""
|
|
Logs a report to console
|
|
"""
|
|
|
|
def notify_failure(self):
|
|
if self.report.status == PublicationStatus.FAILED:
|
|
logger.error(self.report.get_failure_message())
|