lizerk d9a8e71e3a refactor(notifications): сделать приложение полностью самодостаточным
Проблема:
- Service Worker файл (sw.js) находился в корне backend/
- Hardcoded пути к иконкам в sw.js и push.py (/static/img/logo-192.png)
- Функция serve_service_worker() в главном urls.py проекта
- Зависимость от project-specific структуры
- Невозможность переиспользовать приложение без изменений

Решение:
Service Worker на месте:
- backend/notifications/static/notifications/sw.js
- backend/notifications/views.py - serve_service_worker()
- backend/notifications/urls.py - добавлен endpoint sw.js
- backend/eusrr_backend/urls.py - импорт view из notifications

Удаление hardcoded путей:
- sw.js: убрана константа icon='/static/img/logo-192.png'
- senders/push.py: убран hardcoded 'icon': '/static/img/logo.png'
- config.py: добавлены PUSH_DEFAULT_ICON, PUSH_DEFAULT_BADGE (None = browser default)
- README.md: документация по настройке через NOTIFICATIONS_CONFIG

Изменения:
- Создан: notifications/views.py с serve_service_worker()
- Создан: notifications/static/notifications/sw.js
- Изменен: notifications/urls.py - добавлен path('sw.js')
- Изменен: notifications/config.py - настройки иконок
- Изменен: notifications/senders/push.py - использование config
- Изменен: notifications/README.md - документация
- Упрощен: eusrr_backend/urls.py - удалена функция, добавлен импорт
- Удалены: backend/sw.js, backend/static/sw.js, backend/communications/sw.js

Преимущества:
- ✅ Полностью автономное приложение
- ✅ Нет зависимостей от структуры проекта
- ✅ Конфигурируемые иконки через settings.py
- ✅ Browser defaults если иконки не указаны
- ✅ Легко переносить между проектами
- ✅ Единообразие архитектуры (SRP)

Верификация:
- python manage.py check - успешно
2026-03-10 13:58:53 +03:00

143 lines
4.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.

"""
Централизованная конфигурация модуля notifications
Все настройки вынесены в один файл для удобства переиспользования.
Значения можно переопределить в settings.py проекта через NOTIFICATIONS_CONFIG.
"""
from django.conf import settings
# Базовая конфигурация по умолчанию
DEFAULT_CONFIG = {
# === Каналы доставки ===
'CHANNELS_ENABLED': {
'email': True,
'push': True,
'websocket': True,
},
# === Email настройки ===
'EMAIL_RATE_LIMIT': '10/m', # 10 писем в минуту
'EMAIL_MAX_RETRIES': 3,
'EMAIL_RETRY_DELAY': 300, # 5 минут в секундах
'EMAIL_DEFAULT_FREQUENCY': 'instant', # instant, daily, weekly, disabled
# === Push настройки ===
'PUSH_RATE_LIMIT': '50/m', # 50 push в минуту
'PUSH_MAX_RETRIES': 2,
'PUSH_RETRY_DELAY': 60, # 1 минута в секундах
'PUSH_DEFAULT_ICON': None, # URL иконки по умолчанию (None = browser default)
'PUSH_DEFAULT_BADGE': None, # URL badge по умолчанию (None = без badge)
# === WebSocket настройки ===
'WEBSOCKET_MAX_RETRIES': 1,
'WEBSOCKET_RETRY_DELAY': 5, # 5 секунд
# === Digest настройки ===
'DIGEST_DAILY_TIME': '09:00', # Время отправки дейли дайджеста
'DIGEST_WEEKLY_DAY': 'monday', # День недели для weekly дайджеста
'DIGEST_WEEKLY_TIME': '09:00',
# === Общие настройки ===
'SITE_NAME': 'My Site', # Название сайта для email
'DEFAULT_FROM_EMAIL': None, # None = использовать settings.DEFAULT_FROM_EMAIL
'NOTIFICATION_MAX_AGE_DAYS': 90, # Храним уведомления 90 дней
'UNREAD_NOTIFICATIONS_LIMIT': 100, # Максимум непрочитанных для показа
# === DND режим ===
'DND_ENABLED': True, # Включить поддержку "Не беспокоить"
'DND_SILENT_CHANNELS': ['websocket'], # В DND только silent websocket
}
def get_config():
"""
Получить конфигурацию модуля.
Объединяет DEFAULT_CONFIG с пользовательскими настройками из settings.NOTIFICATIONS_CONFIG
Returns:
dict: Итоговая конфигурация
Usage:
from notifications.config import get_config
config = get_config()
rate_limit = config['EMAIL_RATE_LIMIT']
"""
config = DEFAULT_CONFIG.copy()
# Обновляем из settings проекта
user_config = getattr(settings, 'NOTIFICATIONS_CONFIG', {})
config.update(user_config)
return config
def get(key, default=None):
"""
Получить конкретную настройку по ключу
Args:
key: Ключ настройки
default: Значение по умолчанию если не найдено
Returns:
Значение настройки
Usage:
from notifications.config import get
rate_limit = get('EMAIL_RATE_LIMIT', '10/m')
"""
config = get_config()
return config.get(key, default)
# Удобные алиасы для часто используемых настроек
def email_rate_limit():
"""Получить rate limit для email"""
return get('EMAIL_RATE_LIMIT')
def email_max_retries():
"""Получить максимум retry для email"""
return get('EMAIL_MAX_RETRIES')
def email_retry_delay():
"""Получить задержку retry для email"""
return get('EMAIL_RETRY_DELAY')
def push_rate_limit():
"""Получить rate limit для push"""
return get('PUSH_RATE_LIMIT')
def push_max_retries():
"""Получить максимум retry для push"""
return get('PUSH_MAX_RETRIES')
def push_retry_delay():
"""Получить задержку retry для push"""
return get('PUSH_RETRY_DELAY')
def websocket_max_retries():
"""Получить максимум retry для websocket"""
return get('WEBSOCKET_MAX_RETRIES')
def websocket_retry_delay():
"""Получить задержку retry для websocket"""
return get('WEBSOCKET_RETRY_DELAY')
def site_name():
"""Получить название сайта"""
return get('SITE_NAME') or getattr(settings, 'SITE_NAME', 'My Site')
def from_email():
"""Получить from email"""
return get('DEFAULT_FROM_EMAIL') or settings.DEFAULT_FROM_EMAIL