fix: PushNotificationSender теперь использует WebPushDevice из django-push-notifications

- Удален импорт несуществующего web_push_models.py
- Используется WebPushDevice напрямую из библиотеки
- Добавлена деактивация устройств при ошибках
- Улучшено логирование отправки
This commit is contained in:
lizerk 2026-03-09 16:13:03 +03:00
parent fd9b36c1c9
commit d12efde0d2
2 changed files with 38 additions and 35 deletions

View File

@ -407,6 +407,5 @@ class UserChannelPreferences(models.Model):
return now >= self.dnd_start_time or now <= self.dnd_end_time
# === Переэкспорт моделей которые остаются без изменений ===
from .web_push_models import WebPushSubscription # noqa: F401, E402
# === Web Push устройства управляются через django-push-notifications ===
# Используйте: from push_notifications.models import WebPushDevice

View File

@ -1,7 +1,7 @@
"""
Web Push отправитель для browser push notifications
"""
from django.conf import settings
from push_notifications.models import WebPushDevice
from .base import BaseNotificationSender
@ -31,19 +31,16 @@ class PushNotificationSender(BaseNotificationSender):
True если отправлено успешно, False иначе
"""
try:
from push_notifications.models import WebPushDevice
from ..web_push_models import WebPushSubscription
user = notification.recipient
# Получаем активные подписки
subscriptions = WebPushSubscription.objects.filter(
# Получаем активные устройства через django-push-notifications
devices = WebPushDevice.objects.filter(
user=user,
is_active=True
active=True
)
if not subscriptions.exists():
self.log_skip(notification, "no active push subscriptions")
if not devices.exists():
self.log_skip(notification, "no active push devices")
return False
# Формируем данные для push
@ -51,45 +48,52 @@ class PushNotificationSender(BaseNotificationSender):
title = f'{actor_str} {notification.verb}'
body = notification.description or ''
push_data = {
# django-push-notifications использует другой формат
message = {
'head': title,
'body': body,
'icon': '/static/img/logo.png',
'url': notification.action_url or '/',
'tag': f'notification-{notification.id}',
'requireInteraction': False,
'data': {
'notification_id': notification.id,
'verb': notification.verb,
}
}
sent_count = 0
# Отправляем через django-push-notifications
for sub in subscriptions:
failed_count = 0
# Отправляем через все устройства пользователя
for device in devices:
try:
# Используем push_notifications для отправки
device = WebPushDevice.objects.filter(
registration_id=sub.endpoint
).first()
if device:
device.send_message(
message=push_data,
extra={
'notification_id': notification.id
}
)
sent_count += 1
self.logger.debug(f"Push отправлен на device {device.id}")
except Exception as e:
self.logger.error(
f"Ошибка отправки push на subscription {sub.id}: {e}"
device.send_message(message)
sent_count += 1
self.logger.debug(
f"Push отправлен на device {device.id} ({device.browser})"
)
continue
except Exception as e:
failed_count += 1
self.logger.error(
f"Ошибка отправки push на device {device.id}: {e}"
)
# Деактивируем устройство если ошибка
if "expired" in str(e).lower() or "unregistered" in str(e).lower():
device.active = False
device.save()
self.logger.info(f"Device {device.id} деактивирован")
if sent_count > 0:
self.log_success(notification, f"{sent_count} devices")
if failed_count > 0:
self.logger.warning(
f"Push отправлен частично: {sent_count} успешно, "
f"{failed_count} ошибок"
)
return True
else:
self.log_skip(notification, "no successful sends")
self.log_skip(notification, f"no successful sends ({failed_count} failures)")
return False
except ImportError: