Message notification and sending

This commit is contained in:
Eduardo Silva 2024-04-16 16:07:48 -03:00
parent dfb4285ab3
commit 034bc7057b
9 changed files with 182 additions and 3 deletions

105
message_center/functions.py Normal file
View file

@ -0,0 +1,105 @@
import datetime
from router_manager.models import Router
from .models import MessageChannel, Notification, MessageSettings, Message
from backup_data.models import RouterBackup
import requests
from django.utils import timezone
def send_notification_message(message: Message):
message_settings, _ = MessageSettings.objects.get_or_create(name='message_settings')
if message.status != 'pending':
return
if message.retry_count > message_settings.max_retry:
message.status = 'failed'
message.completed = timezone.now()
message.save()
return
message_response = {'status': 'pending', 'error_message': '', 'error_status_code': 0}
if message.channel.channel_type == 'callmebot':
url = f'https://api.callmebot.com/whatsapp.php?phone={message.channel.destination}&text={message.message}&apikey={message.channel.token}'
elif message.channel.channel_type == 'telegram':
url = f'https://api.telegram.org/bot{message.channel.token}/sendMessage?chat_id={message.channel.destination}&text={message.message}'
else:
message_response['status'] = 'failed'
message_response['error_message'] = 'Failed to send message: Invalid channel type'
message_response['error_status_code'] = 0
if message_response['status'] == 'pending':
try:
response = requests.get(url)
if response.status_code == 200:
message_response['status'] = 'sent'
else:
message_response['status'] = 'failed'
message_response['error_message'] = response.text
message_response['error_status_code'] = response.status_code
except:
message_response['status'] = 'failed'
message_response['error_message'] = 'Failed to send message: Request exception'
message_response['error_status_code'] = 0
if message_response['status'] == 'sent':
message.status = 'sent'
message.completed = timezone.now()
message.save()
else:
message.retry_count += 1
message.error_message = message_response['error_message']
message.error_status_code = message_response['error_status_code']
message.next_retry = timezone.now() + datetime.timedelta(seconds=message_settings.retry_interval)
message.save()
return
def notify_router_status_update(router: Router):
message_channel_list = MessageChannel.objects.filter(enabled=True)
message_settings, _ = MessageSettings.objects.get_or_create(name='message_settings')
if message_settings.concatenate_status_change:
if router.routerstatus.status_online:
if message_channel_list.filter(status_change_online=True):
Notification.objects.create(notification_type='status_online', router=router)
else:
if message_channel_list.filter(status_change_offline=True):
Notification.objects.create(notification_type='status_offline', router=router)
else:
if router.routerstatus.status_online:
for message_channel in message_channel_list.filter(status_change_online=True):
Message.objects.create(
channel=message_channel,
subject='Router status change: Online',
message=f'Router {router.name} ({router.address}) is now online'
)
else:
for message_channel in message_channel_list.filter(status_change_offline=True):
Message.objects.create(
channel=message_channel,
subject='Router status change: Offline',
message=f'Router {router.name} ({router.address}) is now offline'
)
return
def notify_backup_fail(router_backup: RouterBackup):
message_settings, _ = MessageSettings.objects.get_or_create(name='message_settings')
message_channel_list = MessageChannel.objects.filter(enabled=True, backup_fail=True)
if not message_channel_list:
return
if message_settings.concatenate_backup_fails:
Notification.objects.create(notification_type='backup_fail', router=router_backup.router, router_backup=router_backup)
else:
error_message = f'Backup {router_backup.id} failed for router {router_backup.router.name} ({router_backup.router.address})'
if router_backup.error_message:
error_message += f'\n\nError message: {router_backup.error_message}'
for message_channel in message_channel_list:
Message.objects.create(
channel=message_channel,
subject=f'Backup failed: {router_backup.id}',
message=error_message
)
return

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-16 18:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('message_center', '0002_alter_messagechannel_channel_type'),
]
operations = [
migrations.AddField(
model_name='message',
name='error_status_code',
field=models.IntegerField(blank=True, null=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-16 18:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('message_center', '0003_message_error_status_code'),
]
operations = [
migrations.AddField(
model_name='message',
name='next_retry',
field=models.DateTimeField(blank=True, null=True),
),
]

View file

@ -35,6 +35,9 @@ class MessageChannel(models.Model):
created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
def __str__(self):
return self.name + ' (' + self.channel_type + ')'
class Message(models.Model):
channel = models.ForeignKey(MessageChannel, on_delete=models.CASCADE)
@ -44,7 +47,9 @@ class Message(models.Model):
('pending', 'Pending'), ('sent', 'Sent'), ('failed', 'Failed'),
), default='pending')
retry_count = models.IntegerField(default=0)
next_retry = models.DateTimeField(blank=True, null=True)
error_message = models.TextField(blank=True, null=True)
error_status_code = models.IntegerField(blank=True, null=True)
completed = models.DateTimeField(blank=True, null=True)
updated = models.DateTimeField(auto_now=True)

View file

@ -1,9 +1,34 @@
from django.shortcuts import render, redirect
from django.http import JsonResponse, Http404
from django.shortcuts import render, redirect, Http404, get_object_or_404
from django.contrib import messages
from router_manager.models import Router
from user_manager.models import UserAcl
from .forms import MessageSettingsForm, MessageChannelForm
from .models import Notification, MessageChannel, Message, MessageSettings
from django.contrib.auth.decorators import login_required
from django.conf import settings
from .functions import notify_router_status_update, notify_backup_fail, send_notification_message
from backup_data.models import RouterBackup
def view_debug_test_messages(request):
if not settings.DEBUG:
raise Http404
data = {'status': 'success'}
router = None
router_backup = None
if request.GET.get('router_uuid'):
router = get_object_or_404(Router, uuid=request.GET.get('router_uuid'))
print(f'Creating test message for router {router.name}')
notify_router_status_update(router)
elif request.GET.get('backup_id'):
router_backup = get_object_or_404(RouterBackup, id=request.GET.get('backup_id'))
notify_backup_fail(router_backup)
else:
for message in Message.objects.filter(status='pending'):
send_notification_message(message)
return JsonResponse(data)
@login_required()