You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

474 lines
18 KiB
Python

from channels.generic.websocket import WebsocketConsumer
from .models import *
import json
from django.template.loader import render_to_string
from asgiref.sync import async_to_sync
from django.shortcuts import get_object_or_404
import requests
from django.forms.models import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
class OsitcomVisitor(WebsocketConsumer):
def connect(self):
async_to_sync(self.channel_layer.group_add)(
'ositcom_visitors', self.channel_name
)
self.accept()
self.visitor = None
def disconnect(self, close_code):
if self.visitor:
self.current_log.left_date = datetime.now()
self.current_log.save()
async_to_sync(self.channel_layer.group_discard)(
'ositcom_visitors', self.channel_name
)
def receive(self, text_data):
text_data_json = json.loads(text_data)
event_type = text_data_json.get('event_type')
if event_type == 'visitor_ping':
session_id = text_data_json.get('session_id')
if Visitor.objects.filter(session_id=session_id).last():
self.visitor = Visitor.objects.filter(session_id=session_id).last()
else:
self.visitor = Visitor.objects.create(
session_id = session_id,
ip_address = text_data_json.get('client_ip'),
country = text_data_json.get('client_country'),
)
self.current_log = VisitorLog.objects.create(
visitor = self.visitor,
referrer = text_data_json.get('referrer'),
url = text_data_json.get('url'),
visit_date = datetime.now()
)
class OsitcomChatRoom(WebsocketConsumer):
def connect(self):
self.domain = 'https://osina.ositcom.com'
self.session_id = self.scope['url_route']['kwargs']['session_id']
self.visitor = Visitor.objects.filter(session_id=self.session_id).last()
if self.scope['url_route']['kwargs'].get('chat_id'): #Case where admin is accessing a specific conversation between the conversations of this visior
self.chat_room = get_object_or_404(ChatRoom, id=self.scope['url_route']['kwargs'].get('chat_id'))
else:
chat_room_guest = ChatRoomGuest.objects.filter(visitor=self.visitor).last() #Case where the visitor will always acesss his last conversation
if chat_room_guest:
self.chat_room = chat_room_guest.room
else:
self.chat_room = None
if self.chat_room:
self.group = f"{self.session_id}_{self.chat_room.id}"
else:
self.group = self.session_id
async_to_sync(self.channel_layer.group_add)(
self.group, self.channel_name
)
self.accept()
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
self.group, self.channel_name
)
def receive(self, text_data):
text_data_json = json.loads(text_data)
event_type = text_data_json.get('event_type')
if event_type == 'load_chat':
self.client_type = text_data_json.get('client_type')
event = {
'reconnecting' : text_data_json.get('reconnecting')
}
self.load_chat_handler(event)
if event_type == 'start_conversation':
chat_room = ChatRoom.objects.create(
name=f"Support: {self.session_id}",
date_created = datetime.now()
)
if text_data_json.get('guest_name'):
self.visitor.name = text_data_json.get('guest_name')
self.visitor.save()
if text_data_json.get('guest_mobile_number'):
self.visitor.mobile_number = text_data_json.get('guest_mobile_number')
self.visitor.save()
chat_room_guest = ChatRoomGuest.objects.create(
room=chat_room,
visitor=self.visitor
)
self.chat_room = chat_room
self.group = f"{self.session_id}_{self.chat_room.id}"
event = {
'type': 'start_conversation_handler',
'chat_room_id': chat_room.id
}
async_to_sync(self.channel_layer.group_discard)(
self.group, self.channel_name
)
async_to_sync(self.channel_layer.group_add)(
self.group, self.channel_name
)
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
if event_type == 'typing':
event = {
'type': 'typing_handler',
'user_id': text_data_json.get('user_id'),
'typing_status': text_data_json.get('typing_status')
}
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
if event_type == 'send_message':
if text_data_json.get('user_id'):
member = get_object_or_404(User, id=text_data_json.get('user_id'))
else:
member = None
chat_message = ChatMessage.objects.create(
member = member,
room = self.chat_room,
content= text_data_json.get('message'),
date_sent = datetime.now()
)
event = {
'type': 'send_message_handler',
'chat_message_id': chat_message.id
}
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
if event_type == 'uploaded_file':
if text_data_json.get('user_id'):
member = get_object_or_404(User, id=text_data_json.get('user_id'))
else:
member = None
message = ChatMessage.objects.create(
member = member,
room = self.chat_room,
date_sent = datetime.now()
)
message_attachment = ChatMessageAttachment.objects.create(
message = message,
attachment = text_data_json.get('path'),
)
event = {
'type': 'uploaded_file_handler',
'message_attachment_id': message_attachment.id,
'file_type': text_data_json.get('file_type'),
'file_name': text_data_json.get('file_name'),
}
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
if event_type == 'update_read_messages' and self.chat_room:
latest_unread_message = None
number_of_unread = 0
if text_data_json.get('user_id'):
member = get_object_or_404(User, id=text_data_json.get('user_id'))
guest = None
if text_data_json.get('chat_state') == 'open':
messages = ChatMessage.objects.filter(room=self.chat_room).exclude(member=member)
for message in messages:
seen_message = ChatMessageSeen.objects.filter(
message=message,
member=member
).exists()
if not seen_message:
ChatMessageSeen.objects.create(
message=message,
member=member,
seen_date = datetime.now()
)
number_of_unread = 0
else:
number_of_unread = ChatMessage.objects.filter(room=self.chat_room).exclude(member = member, chatmessageseen__member=member).count()
latest_unread_message = ChatMessage.objects.filter(room=self.chat_room).exclude(chatmessageseen__member=member).last()
else:
member = None
guest = self.chat_room.chatroomguest
if text_data_json.get('chat_state') == 'open':
messages = ChatMessage.objects.filter(room=self.chat_room).exclude(member=None)
for message in messages:
seen_message = ChatMessageSeen.objects.filter(
message=message,
guest=guest
).exists()
if not seen_message:
ChatMessageSeen.objects.create(
message=message,
guest=guest,
seen_date = datetime.now()
)
number_of_unread = 0
else:
number_of_unread = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).count()
latest_unread_message = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).last()
event = {
'type': 'update_read_messages_handler',
'number_of_unread': number_of_unread,
'latest_unread_message_id': latest_unread_message.id if latest_unread_message else None
}
self.update_read_messages_handler(event)
if event_type == 'end_chat':
event = {
'type': 'end_chat_handler',
'user_id': text_data_json.get('user_id')
}
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
if event_type == 'submit_review':
if ChatRoomReview.objects.filter(room=self.chat_room).last():
review = ChatRoomReview.objects.filter(room=self.chat_room).last()
if text_data_json.get('reaction'):
review.reaction = text_data_json.get('reaction')
if text_data_json.get('details'):
review.details = text_data_json.get('details')
review.save()
else:
review = ChatRoomReview.objects.create(
room = self.chat_room,
reaction = text_data_json.get('reaction'),
details = text_data_json.get('details'),
)
event = {
'type': 'submit_review_handler',
'review_id': review.id
}
async_to_sync(self.channel_layer.group_send)(
self.group, event
)
def load_chat_handler(self, event):
if self.chat_room:
chat_room = self.chat_room
chat_room_messages = ChatMessage.objects.filter(room=chat_room).order_by('date_sent')
review = ChatRoomReview.objects.filter(room=chat_room).last()
else:
chat_room = None
chat_room_messages = None
review = None
context = {
'chat_room': chat_room,
'chat_room_messages': chat_room_messages,
'review': review,
'domain': self.domain
}
if self.client_type == 'mobile_admin':
chat_room_data = model_to_dict(chat_room)
chat_room_messages_data = []
for message in chat_room_messages:
message_data = model_to_dict(message)
attachment = getattr(message, 'chatmessageattachment', None)
if attachment:
message_data['attachment'] = {
'attachment': attachment.attachment,
'is_image': attachment.is_image(),
'file_name': attachment.file_name,
}
else:
message_data['attachment'] = None
chat_room_messages_data.append(message_data)
self.send(text_data=json.dumps({
'event_type': 'load_chat',
'chat_room_data': chat_room_data,
'chat_room_messages_data': chat_room_messages_data,
}, cls=DjangoJSONEncoder))
elif self.client_type == 'website_admin':
html = render_to_string("chat_templates/chat-room.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'load_chat',
'html': html,
}))
else:
if event.get('reconnecting') == 'False': #Connecting for the first time
html = render_to_string("chat-widget.html", context=context)
else:
if chat_room:
if chat_room.date_terminated:
html = render_to_string("ended-chat.html", context=context)
else:
html = render_to_string("chat-room.html", context=context)
else:
html = render_to_string("start-chat.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'load_chat',
'html': html,
}))
def start_conversation_handler(self, event):
chat_room = get_object_or_404(ChatRoom, id=event['chat_room_id'])
context = {
'chat_room': chat_room,
'session_id':self.session_id,
'domain': self.domain
}
if self.client_type == 'mobile_admin':
self.send(text_data=json.dumps({
'event_type': 'start_conversation',
'context': context,
}))
else:
html = render_to_string("chat-room.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'start_conversation',
'html': html,
}))
def typing_handler(self, event):
if event.get('typing_status') == 'typing':
if event.get('user_id'):
member = get_object_or_404(User, id=event.get('user_id'))
else:
member = None
context = {
'member': member,
'domain': self.domain
}
html = render_to_string("partials/typing.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'typing',
'html': html,
}))
else:
self.send(text_data=json.dumps({
'event_type': 'stopped_typing',
}))
def send_message_handler(self, event):
chat_message = get_object_or_404(ChatMessage, id=event['chat_message_id'])
context = {
'chat_message': chat_message,
'domain': self.domain
}
if self.client_type == 'mobile_admin':
chat_message_data = model_to_dict(chat_message)
self.send(text_data=json.dumps({
'event_type': 'send_message',
'chat_message_data': chat_message_data,
},cls=DjangoJSONEncoder))
elif self.client_type == 'website_admin':
html = render_to_string("chat_templates/partials/message.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'send_message',
'html': html,
}))
else:
html = render_to_string("partials/message.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'send_message',
'user': chat_message.member.id if chat_message.member else None,
'html': html,
}))
def uploaded_file_handler(self, event):
message_attachment = get_object_or_404(ChatMessageAttachment, id=event['message_attachment_id'])
context = {
'message_attachment': message_attachment,
'file_type': event['file_type'],
'domain': self.domain
}
if self.client_type == 'mobile_admin':
message_attachment_data = model_to_dict(message_attachment)
self.send(text_data=json.dumps({
'event_type': 'uploaded_file',
'message_attachment_data': message_attachment_data,
'user': message_attachment.message.member.id if message_attachment.message.member else None,
'file_type': event['file_type']
},cls=DjangoJSONEncoder))
else:
html = render_to_string("partials/message-attachment.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'uploaded_file',
'file_name': event['file_name'],
'user': message_attachment.message.member.id if message_attachment.message.member else None,
'html': html,
}))
def update_read_messages_handler(self, event):
latest_unread_message_id = event.get('latest_unread_message_id')
if latest_unread_message_id:
latest_unread_message = get_object_or_404(ChatMessage, id=latest_unread_message_id)
context = {
'number_of_unread' : event['number_of_unread'],
'latest_unread_message': latest_unread_message,
'domain': self.domain
}
html = render_to_string("partials/unread-messages.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'update_read_messages',
'html': html,
}))
else:
latest_unread_message = None
def end_chat_handler(self, event):
if event['user_id']:
member = get_object_or_404(User, id=event['user_id'])
else:
member = None
self.chat_room.date_terminated = datetime.now()
self.chat_room.terminated_by = member
self.chat_room.save()
context = {
'chat_room': self.chat_room,
'chat_room_messages': ChatMessage.objects.filter(room=self.chat_room).order_by('date_sent'),
'domain': self.domain
}
html = render_to_string("ended-chat.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'ended_chat',
'html': html,
}))
def submit_review_handler(self, event):
review = get_object_or_404(ChatRoomReview, id=event['review_id'])
context = {
'review': review,
'chat_room': self.chat_room,
}
html = render_to_string("partials/submitted-review.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'submit_review',
'html': html,
}))