From 52e34f94bd846bb8b0e2a2ac092d68b7bb3abcb1 Mon Sep 17 00:00:00 2001 From: SlyK182 <60148777+SlyK182@users.noreply.github.com> Date: Wed, 7 Jul 2021 11:45:54 +0200 Subject: [PATCH] Added publisher coordinator (#33) * Added publisher coordinator, emptied __init__ file * Lesser refactoring to coordinator methods * PublisherCoordinatorResult: status turned from str to PublicationStatus * Better usage of reporting classes to manage results * Lesser fix to Telegram _validate_response method --- mobilizon_bots/publishers/__init__.py | 45 ---------- mobilizon_bots/publishers/coordinator.py | 105 +++++++++++++++++++++++ mobilizon_bots/publishers/telegram.py | 8 +- 3 files changed, 112 insertions(+), 46 deletions(-) create mode 100644 mobilizon_bots/publishers/coordinator.py diff --git a/mobilizon_bots/publishers/__init__.py b/mobilizon_bots/publishers/__init__.py index 5263ce5..e69de29 100644 --- a/mobilizon_bots/publishers/__init__.py +++ b/mobilizon_bots/publishers/__init__.py @@ -1,45 +0,0 @@ -from typing import Iterable - -from .abstract import AbstractPublisher -from .exceptions import PublisherError - - -def run(publishers: Iterable[AbstractPublisher]) -> dict: - invalid_credentials, invalid_event, invalid_msg = [], [], [] - for p in publishers: - if not p.are_credentials_valid(): - invalid_credentials.append(p) - if not p.is_event_valid(): - invalid_event.append(p) - if not p.is_message_valid(): - invalid_msg.append(p) - if invalid_credentials or invalid_event or invalid_msg: - # TODO: consider to use exceptions or data class if necessary - return { - "status": "fail", - "description": "Validation failed for at least 1 publisher", - "invalid_credentials": invalid_credentials, - "invalid_event": invalid_event, - "invalid_msg": invalid_msg, - } - - failed_publishers, successful_publishers = [], [] - for p in publishers: - try: - p.post() - except PublisherError: - failed_publishers.append(p) - else: - successful_publishers.append(p) - - if failed_publishers: - return { - "status": "fail", - "description": "Posting failed for at least 1 publisher", - "failed_publishers": failed_publishers, - "successful_publishers": successful_publishers, - } - return { - "status": "success", - "description": "https://www.youtube.com/watch?v=2lHgmC6PBBE", - } diff --git a/mobilizon_bots/publishers/coordinator.py b/mobilizon_bots/publishers/coordinator.py new file mode 100644 index 0000000..dc95b49 --- /dev/null +++ b/mobilizon_bots/publishers/coordinator.py @@ -0,0 +1,105 @@ +from dataclasses import dataclass, field + +from mobilizon_bots.config.config import settings +from mobilizon_bots.config.publishers import get_active_publishers +from mobilizon_bots.event.event import MobilizonEvent, PublicationStatus +from .exceptions import PublisherError +from .abstract import AbstractPublisher +from .telegram import TelegramPublisher + +KEY2CLS = {"telegram": TelegramPublisher} + + +@dataclass +class PublisherReport: + status: PublicationStatus + reason: str + publisher: AbstractPublisher + event: MobilizonEvent + + +@dataclass +class PublisherCoordinatorReport: + reports: list = field(default_factory=[]) + + @property + def successful(self): + return all(r.status == PublicationStatus.COMPLETED for r in self.reports) + + +class PublisherCoordinator: + def __init__(self, event: MobilizonEvent): + self.publishers = tuple( + KEY2CLS[pn](event) for pn in get_active_publishers(settings) + ) + + def run(self) -> PublisherCoordinatorReport: + invalid_credentials, invalid_event, invalid_msg = self._validate() + if invalid_credentials or invalid_event or invalid_msg: + return PublisherCoordinatorReport( + reports=invalid_credentials + invalid_event + invalid_msg + ) + + failed_publishers = self._post() + if failed_publishers: + return PublisherCoordinatorReport(reports=failed_publishers) + + return PublisherCoordinatorReport( + reports=[ + PublisherReport( + status=PublicationStatus.COMPLETED, + reason="", + publisher=p, + event=p.event, + ) + for p in self.publishers + ], + ) + + def _post(self): + failed_publishers = [] + for p in self.publishers: + try: + p.post() + except PublisherError as e: + failed_publishers.append( + PublisherReport( + status=PublicationStatus.FAILED, + reason=repr(e), + publisher=p, + event=p.event, + ) + ) + return failed_publishers + + def _validate(self): + invalid_credentials, invalid_event, invalid_msg = [], [], [] + for p in self.publishers: + if not p.are_credentials_valid(): + invalid_credentials.append( + PublisherReport( + status=PublicationStatus.FAILED, + reason="Invalid credentials", + publisher=p, + event=p.event, + ) + ) + if not p.is_event_valid(): + invalid_event.append( + PublisherReport( + status=PublicationStatus.FAILED, + reason="Invalid event", + publisher=p, + event=p.event, + ) + ) + if not p.is_message_valid(): + invalid_msg.append( + PublisherReport( + status=PublicationStatus.FAILED, + reason="Invalid message", + publisher=p, + event=p.event, + ) + ) + return invalid_credentials, invalid_event, invalid_msg diff --git a/mobilizon_bots/publishers/telegram.py b/mobilizon_bots/publishers/telegram.py index 3536fe7..99993f4 100644 --- a/mobilizon_bots/publishers/telegram.py +++ b/mobilizon_bots/publishers/telegram.py @@ -57,7 +57,13 @@ class TelegramPublisher(AbstractPublisher): self._log_error("No text was found", raise_error=InvalidEvent) def _validate_response(self, res): - res.raise_for_status() + try: + res.raise_for_status() + except requests.exceptions.HTTPError as e: + self._log_error( + f"Server returned invalid data: {str(e)}", + raise_error=InvalidResponse, + ) try: data = res.json()