I am writing a django module that handles real time message paired with notification. So far:
a conversation can only take place between no more than 2 users.
a notification should be sent after each message.
I am currently working on getting the notifications to show up and the issue is that the notification gets rendered in the sender profile page and not in the recipient profile. I cant see where my error is
Here is what I have done: consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from .models import Chat, ChatRoom
from accounts.models import User
from asgiref.sync import sync_to_async
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from asgiref.sync import async_to_sync
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_id = self.scope['url_route']['kwargs']['room_id']
self.room_group_name = 'chat_%s' % self.room_id
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
recipient = text_data_json['recipient']
self.user_id = self.scope['user'].id
# Find room object
room = await database_sync_to_async(ChatRoom.objects.get)(pk=self.room_id)
print('ok1')
# Create new chat object
chat = Chat(
content=message,
sender=self.scope['user'],
room=room,
)
print('ok2')
await database_sync_to_async(chat.save)()
print("ok3")
# get the recipient user
recipient_user = await database_sync_to_async(User.objects.get)(id=recipient)
print("ok4")
await sync_to_async(chat.recipient.add)(recipient_user.id)
print("ok5")
await database_sync_to_async(chat.save)()
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message,
'user_id': self.user_id
})
# Send a notification to the recipient
await self.channel_layer.send(
recipient_user.username,
{
'type': 'notification',
'message': message
}
)
await self.send_notification(f'New message from {self.user_id}')
print('notification has been created')
async def chat_message(self, event):
message = event['message']
user_id = event['user_id']
await self.send(text_data=json.dumps({
'message': message,
'user_id': user_id
}))
async def send_notification(self, message):
await self.send(text_data=json.dumps({
'type': 'notification',
'message':message
}))
and here is my room.js code, which is the javascript code handling the logic to display the messages logic and the notifications:
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
console.log("data",data)
console.log("datatype",data.type)
var message_type = data.type;
console.log("message type",message_type)
if(message_type === 'notification'){
$("#notification-bar2").text(data.message);
$("#notification-bar2").show();
}
if(message_type !== 'notification'){
const messageElement = document.createElement('div')
const userId = data['user_id']
const loggedInUserId = JSON.parse(document.getElementById('user_id').textContent)
console.log(loggedInUserId)
messageElement.innerText = data.message
if (userId === loggedInUserId) {
messageElement.classList.add( 'relative', 'max-w-xl', 'px-4', 'py-2', 'text-gray-700', 'bg-gray-100','rounded', 'shadow','flex', 'justify-end','message', 'sender','block')
} else {
messageElement.classList.add('relative', 'max-w-xl', 'px-4', 'py-2', 'text-gray-700', 'bg-gray-100','rounded', 'shadow','flex', 'justify-start','message', 'receiver','block')
}
chatLog.appendChild(messageElement)
if (document.querySelector('#emptyText')) {
document.querySelector('#emptyText').remove()
}
}
};
I am super confused about why that would be, and be fresh starting with channels, there are still quite a bit of stuff that I dont understand super well, therefore any king help is greatly appreciated! I am more than happy to provide additionnal code if necessary