|
3 | 3 | from celery import shared_task
|
4 | 4 | from django.contrib.auth import get_user_model
|
5 | 5 | from django.contrib.contenttypes.models import ContentType
|
| 6 | +from django.contrib.sites.models import Site |
| 7 | +from django.core.cache import cache |
6 | 8 | from django.db.models import Q
|
7 | 9 | from django.db.utils import OperationalError
|
| 10 | +from django.template.loader import render_to_string |
8 | 11 | from django.utils import timezone
|
| 12 | +from django.utils.translation import gettext as _ |
9 | 13 |
|
| 14 | +from openwisp_notifications import settings as app_settings |
10 | 15 | from openwisp_notifications import types
|
11 | 16 | from openwisp_notifications.swapper import load_model, swapper_load_model
|
| 17 | +from openwisp_notifications.utils import send_notification_email |
| 18 | +from openwisp_utils.admin_theme.email import send_email |
12 | 19 | from openwisp_utils.tasks import OpenwispCeleryTask
|
13 | 20 |
|
14 | 21 | User = get_user_model()
|
@@ -201,3 +208,83 @@ def delete_ignore_object_notification(instance_id):
|
201 | 208 | Deletes IgnoreObjectNotification object post it's expiration.
|
202 | 209 | """
|
203 | 210 | IgnoreObjectNotification.objects.filter(id=instance_id).delete()
|
| 211 | + |
| 212 | + |
| 213 | +@shared_task(base=OpenwispCeleryTask) |
| 214 | +def send_batched_email_notifications(instance_id): |
| 215 | + """ |
| 216 | + Sends a summary of notifications to the specified email address. |
| 217 | + """ |
| 218 | + if not instance_id: |
| 219 | + return |
| 220 | + |
| 221 | + cache_key = f'email_batch_{instance_id}' |
| 222 | + cache_data = cache.get(cache_key, {'pks': []}) |
| 223 | + |
| 224 | + if not cache_data['pks']: |
| 225 | + return |
| 226 | + |
| 227 | + display_limit = app_settings.EMAIL_BATCH_DISPLAY_LIMIT |
| 228 | + unsent_notifications_query = Notification.objects.filter( |
| 229 | + id__in=cache_data['pks'] |
| 230 | + ).order_by('-timestamp') |
| 231 | + notifications_count = unsent_notifications_query.count() |
| 232 | + current_site = Site.objects.get_current() |
| 233 | + email_id = cache_data.get('email_id') |
| 234 | + unsent_notifications = [] |
| 235 | + |
| 236 | + # Send individual email if there is only one notification |
| 237 | + if notifications_count == 1: |
| 238 | + notification = unsent_notifications.first() |
| 239 | + send_notification_email(notification) |
| 240 | + else: |
| 241 | + # Show the amount of notifications according to configured display limit |
| 242 | + for notification in unsent_notifications_query[:display_limit]: |
| 243 | + url = notification.data.get('url', '') if notification.data else None |
| 244 | + if url: |
| 245 | + notification.url = url |
| 246 | + elif notification.target: |
| 247 | + notification.url = notification.redirect_view_url |
| 248 | + else: |
| 249 | + notification.url = None |
| 250 | + |
| 251 | + unsent_notifications.append(notification) |
| 252 | + |
| 253 | + starting_time = ( |
| 254 | + cache_data.get('start_time') |
| 255 | + .strftime('%B %-d, %Y, %-I:%M %p') |
| 256 | + .lower() |
| 257 | + .replace('am', 'a.m.') |
| 258 | + .replace('pm', 'p.m.') |
| 259 | + ) + ' UTC' |
| 260 | + |
| 261 | + context = { |
| 262 | + 'notifications': unsent_notifications[:display_limit], |
| 263 | + 'notifications_count': notifications_count, |
| 264 | + 'site_name': current_site.name, |
| 265 | + 'start_time': starting_time, |
| 266 | + } |
| 267 | + |
| 268 | + extra_context = {} |
| 269 | + if notifications_count > display_limit: |
| 270 | + extra_context = { |
| 271 | + 'call_to_action_url': f"https://{current_site.domain}/admin/#notifications", |
| 272 | + 'call_to_action_text': _('View all Notifications'), |
| 273 | + } |
| 274 | + context.update(extra_context) |
| 275 | + |
| 276 | + html_content = render_to_string('emails/batch_email.html', context) |
| 277 | + plain_text_content = render_to_string('emails/batch_email.txt', context) |
| 278 | + notifications_count = min(notifications_count, display_limit) |
| 279 | + |
| 280 | + send_email( |
| 281 | + subject=f'[{current_site.name}] {notifications_count} new notifications since {starting_time}', |
| 282 | + body_text=plain_text_content, |
| 283 | + body_html=html_content, |
| 284 | + recipients=[email_id], |
| 285 | + extra_context=extra_context, |
| 286 | + ) |
| 287 | + |
| 288 | + unsent_notifications_query.update(emailed=True) |
| 289 | + Notification.objects.bulk_update(unsent_notifications_query, ['emailed']) |
| 290 | + cache.delete(cache_key) |
0 commit comments