lizerk e1be95fbe4 refactor: Базовый класс для всех отправителей уведомлений
Создана объектно-ориентированная архитектура для отправителей:

Новая структура:
- BaseNotificationSender - абстрактный базовый класс
- EmailNotificationSender(BaseNotificationSender)
- WebSocketNotificationSender(BaseNotificationSender)
- PushNotificationSender(BaseNotificationSender)

Преимущества:
✅ Единый интерфейс send() для всех каналов
✅ can_send() - проверка возможности отправки
✅ Унифицированное логирование (log_success, log_error, log_skip)
✅ Легко расширять новыми каналами
✅ Переиспользуемость кода

Изменения:
- notifications/senders/base.py - базовый класс
- notifications/senders/email.py - email отправитель (упрощен)
- notifications/senders/websocket.py - WebSocket отправитель
- notifications/senders/push.py - Web Push отправитель
- notifications/channels.py - обновлен для использования классов

Старые функции send_* сохранены для обратной совместимости (deprecated)
2026-03-09 16:04:48 +03:00

76 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Базовый класс для всех отправителей уведомлений
"""
from abc import ABC, abstractmethod
from typing import Optional
import logging
logger = logging.getLogger(__name__)
class BaseNotificationSender(ABC):
"""
Абстрактный базовый класс для отправителей уведомлений.
Все отправители должны наследоваться от этого класса и реализовать метод send().
"""
def __init__(self):
self.logger = logging.getLogger(self.__class__.__name__)
@abstractmethod
def send(self, notification, **kwargs) -> bool:
"""
Отправляет уведомление через конкретный канал.
Args:
notification: Объект Notification
**kwargs: Дополнительные параметры для канала
Returns:
True если отправлено успешно, False иначе
"""
pass
def can_send(self, notification, user_preferences) -> bool:
"""
Проверяет, можно ли отправить уведомление через этот канал.
Args:
notification: Объект Notification
user_preferences: UserChannelPreferences
Returns:
True если можно отправлять, False иначе
"""
return True
def log_success(self, notification, recipient: str):
"""Логирует успешную отправку"""
self.logger.info(
f"✅ Уведомление отправлено: "
f"notification_id={notification.id}, "
f"recipient={recipient}, "
f"channel={self.__class__.__name__}"
)
def log_error(self, notification, error: Exception, recipient: Optional[str] = None):
"""Логирует ошибку отправки"""
self.logger.error(
f"❌ Ошибка отправки: "
f"notification_id={notification.id}, "
f"recipient={recipient}, "
f"channel={self.__class__.__name__}, "
f"error={type(error).__name__}: {error}",
exc_info=True
)
def log_skip(self, notification, reason: str):
"""Логирует пропуск отправки"""
self.logger.debug(
f"⏭️ Отправка пропущена: "
f"notification_id={notification.id}, "
f"channel={self.__class__.__name__}, "
f"reason={reason}"
)