chat: fix and opti

This commit is contained in:
starnakin 2023-12-27 16:14:39 +01:00
parent cfb14be945
commit 9f7b813292
10 changed files with 144 additions and 116 deletions

View File

@ -1,6 +1,6 @@
from django.contrib import admin
from .models import ChannelModel, MemberModel, MessageModel
from .models import ChatChannelModel, ChatMemberModel, ChatMessageModel
admin.site.register(ChannelModel)
admin.site.register(MemberModel)
admin.site.register(MessageModel)
admin.site.register(ChatChannelModel)
admin.site.register(ChatMemberModel)
admin.site.register(ChatMessageModel)

View File

@ -1,21 +1,25 @@
import json
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
from .models import MemberModel, MessageModel
from .models import ChatMemberModel, ChatMessageModel
from profiles.models import BlockModel
import time
import json
class ChatConsumer(WebsocketConsumer):
def connect(self):
channel_id : str = self.scope['path'].split('/')[3]
self.room_group_name = 'chat' + channel_id
user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated):
return
if MemberModel.objects.filter(member_id=user.pk, channel_id=int(channel_id)).count() != 1:
channel_id : int = int(self.scope['url_route']['kwargs']['chat_id'])
self.room_group_name = f'chat{channel_id}'
if ChatMemberModel.objects.filter(member_id=user.pk, channel_id=int(channel_id)).count() != 1:
return
if (self.channel_layer == None):
@ -30,27 +34,33 @@ class ChatConsumer(WebsocketConsumer):
def receive(self, text_data=None, bytes_data=None):
if text_data == None:
return
text_data_json = json.loads(text_data)
message = text_data_json['message']
receivers_id = text_data_json['receivers_id']
print(text_data)
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated):
return
if MemberModel.objects.filter(member_id=user.pk, channel_id=channel_id).count() != 1:
text_data_json: dict = json.loads(text_data)
message = text_data_json.get('message')
if (message is None):
return
receivers_id = text_data_json.get('receivers_id')
if (receivers_id is None):
return
channel_id : int = int(self.scope['url_route']['kwargs']['chat_id'])
if ChatMemberModel.objects.filter(member_id = user.pk, channel_id = channel_id).count() != 1:
return
if (self.channel_layer == None):
return
message_time : int = int(time.time() * 1000)
message_time: int = int(time.time() * 1000)
if (len(receivers_id) == 1 and
BlockModel.objects.filter(blocker=user.pk, blocked=receivers_id[0]) or
@ -68,22 +78,17 @@ class ChatConsumer(WebsocketConsumer):
}
)
new_message = MessageModel()
new_message.channel_id = channel_id
new_message.author_id = user.pk
new_message.content = message
new_message.time = message_time
new_message.save()
new_message = ChatMessageModel(channel_id = channel_id, author_id = user.pk, content = message, time = message_time).save()
def chat_message(self, event):
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated):
return
if MemberModel.objects.filter(member_id=user.pk, channel_id=channel_id).count() != 1:
channel_id : int = int(self.scope['url_route']['kwargs']['chat_id'])
if ChatMemberModel.objects.filter(member_id = user.pk, channel_id = channel_id).count() != 1:
return
self.send(text_data=json.dumps({

View File

@ -4,21 +4,28 @@ from django.contrib.auth.models import User
from django.contrib import admin
# Create your models here.
class ChannelModel(models.Model):
pass
class ChatChannelModel(models.Model):
def create(self, users_id: [int]):
self.save()
for user_id in users_id:
ChatMemberModel(channel_id = self.pk, member_id = user_id).save()
class MemberModel(models.Model):
def get_members_id(self):
return [member_channel.member_id for member_channel in ChatMemberModel.objects.filter(channel_id = self.pk)]
class ChatMemberModel(models.Model):
member_id = IntegerField(primary_key=False)
channel_id = IntegerField(primary_key=False)
def __str__(self):
return "member_id: " + str(self.member_id) + ", channel_id: " + str(self.channel_id)
class MessageModel(models.Model):
class ChatMessageModel(models.Model):
channel_id = IntegerField(primary_key=False)
author_id = IntegerField(primary_key=False)
content = models.CharField(max_length=255)
time = IntegerField(primary_key=False)
def __str__(self):
return "author_id: " + str(self.author_id) + ", channel_id: " + str(self.channel_id) + ", content: " + self.content
return "author_id: " + str(self.author_id) + ", channel_id: " + str(self.channel_id) + ", content: " + self.content

View File

@ -1,8 +1,30 @@
from rest_framework import serializers
from .models import ChannelModel
class ChannelSerializer(serializers.ModelSerializer):
from profiles.models import ProfileModel
from .models import ChatChannelModel, ChatMessageModel
class ChatChannelSerializer(serializers.ModelSerializer):
members_id = serializers.ListField(child = serializers.IntegerField())
class Meta:
model = ChannelModel
fields = []
model = ChatChannelModel
fields = ["members_id", "pk"]
def validate_members_id(self, value):
members_id: [int] = value
if len(members_id) < 2:
raise serializers.ValidationError('Not enought members to create the channel')
if len(set(members_id)) != len(members_id):
raise serializers.ValidationError('Same member')
for member_id in members_id:
if not ProfileModel.objects.filter(pk = member_id).exists():
raise serializers.ValidationError(f"The profile {member_id} doesn't exists.")
return members_id
class ChatMessageSerializer(serializers.Serializer):
class Meta:
model = ChatMessageModel
fields = ["channel_id", "author_id", "content", "time"]

View File

@ -1,3 +1,30 @@
from django.test import TestCase
from django.test.client import Client
from django.http import HttpResponse, HttpRequest
from django.contrib.auth.models import User
# Create your tests here.
class ChatTest(TestCase):
def setUp(self):
self.client = Client()
self.username='bozo1'
self.password='password'
self.user: User = User.objects.create_user(username=self.username, password=self.password)
self.dest: User = User.objects.create_user(username="bozo2", password=self.password)
self.url = "/api/chat/"
def test_create_chat(self):
self.client.login(username=self.username, password=self.password)
response: HttpResponse = self.client.post(self.url + str(self.user.pk), {"members_id": [self.user.pk, self.dest.pk]})
response_dict: dict = eval(response.content)
self.assertDictEqual(response_dict, {})
def test_create_chat_unlogged(self):
response: HttpResponse = self.client.post(self.url + str(self.user.pk), {"members_id": [self.user.pk, self.dest.pk]})
response_dict: dict = eval(response.content)
self.assertDictEqual(response_dict, {'detail': 'Authentication credentials were not provided.'})

View File

@ -5,6 +5,5 @@ from django.conf.urls.static import static
from . import views
urlpatterns = [
path("<int:pk>", views.ChatView.as_view(), name="chat_page"),
path("", views.ChatsView.as_view(), name="chats_page"),
path("", views.ChannelView.as_view(), name="chats_page"),
]

View File

@ -1,79 +1,45 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, status
from rest_framework import permissions, status
from rest_framework.authentication import SessionAuthentication
from .models import ChannelModel, MemberModel, MessageModel
from django.http import HttpRequest
from django.contrib.auth import login
from django.db.models import QuerySet
from django.core import serializers
class ChatView(APIView):
from .models import ChatChannelModel, ChatMemberModel, ChatMessageModel
from .serializers import ChatChannelSerializer, ChatMessageSerializer
class ChannelView(APIView):
queryset = ChatChannelModel.objects
serializer_class = ChatChannelSerializer
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request, pk):
if (ChannelModel.objects.filter(pk=pk)):
return Response({'channel_id': pk}, status=status.HTTP_200_OK)
else:
return Response("Channel doesn't exist", status=status.HTTP_404_NOT_FOUND)
authentication_classes = (SessionAuthentication,)
def delete(self, request, pk):
ChannelModel.objects.filter(pk=pk).delete()
MessageModel.objects.filter(pk=pk).delete()
MemberModel.objects.filter(pk=pk).delete()
return Response({'channel_id': pk}, status=status.HTTP_200_OK)
class ChatsView(APIView):
def post(self, request):
data: dict = request.data
users_id = request.data.get("users_id", [])
if len(users_id) < 2:
return Response('Not enought members to create the channel', status=status.HTTP_400_BAD_REQUEST)
if users_id[0] == users_id[1]:
return Response('Same member', status=status.HTTP_400_BAD_REQUEST)
serializer = self.serializer_class(data = request.data)
serializer.is_valid(raise_exception=True)
for user_id1 in users_id:
for member1 in MemberModel.objects.filter(member_id=user_id1):
for user_id2 in users_id:
if user_id1 == user_id2:
continue
for member2 in MemberModel.objects.filter(member_id=user_id2):
if (member1.channel_id == member2.channel_id):
messages = MessageModel.objects.filter(channel_id=member1.channel_id).order_by("time")
messages = serializers.serialize("json", messages)
return Response({'channel_id': member1.channel_id, 'messages':messages}, status=status.HTTP_200_OK)
new_channel = ChannelModel()
new_channel.save()
data: dict = serializer.validated_data
for user_id in users_id:
members_id = data.get("members_id")
if self.request.user.pk not in members_id:
return Response({"detail": "You are trying to create a chat group without you."}, status = status.HTTP_400_BAD_REQUEST)
new_member = MemberModel()
new_member.channel_id = new_channel.pk
new_member.member_id = user_id
new_member.save()
for member_channel in ChatMemberModel.objects.filter(member_id = members_id[0]):
channel_id: int = member_channel.channel_id
if not ChatChannelModel.objects.filter(pk = channel_id).exists():
continue
channel: ChatChannelModel = ChatChannelModel.objects.get(pk = channel_id)
if set(channel.get_members_id()) == set(members_id):
messages = ChatMessageModel.objects.filter(channel_id = channel_id).order_by("time")
messages = serializers.serialize("json", messages)
return Response({'channel_id': channel_id, 'messages': messages}, status=status.HTTP_200_OK)
return Response({'channel_id': new_channel.pk}, status=status.HTTP_201_CREATED)
def delete(self, request):
data: dict = request.data
users_id = request.data.get("users_id", [])
#print(list(MemberModel.objects.all()))
for user_id1 in users_id:
for member1 in MemberModel.objects.filter(member_id=user_id1):
for user_id2 in users_id:
if user_id1 == user_id2:
break
for member2 in MemberModel.objects.filter(member_id=user_id2):
if (member1.channel_id == member2.channel_id):
MessageModel.objects.filter(channel_id=member1.channel_id).delete()
member1.delete()
member2.delete()
ChannelModel.objects.get(pk=member1.channel_id).delete()
return Response("Channel removed", status=status.HTTP_200_OK)
return Response("Channel doesn't exist", status=status.HTTP_404_NOT_FOUND)
new_channel_id = ChatChannelModel().create(members_id)
return Response({'channel_id': new_channel_id}, status=status.HTTP_201_CREATED)

View File

@ -35,7 +35,9 @@ class Channel {
this.chatSocket.close();
}
updateMessages(messages) {
updateMessages(messages)
{
console.log(messages);
messages = JSON.parse(messages);
let new_messages = [];

View File

@ -6,18 +6,18 @@ class Channels {
this.client = client;
}
async createChannel(users_id, reload) {
async createChannel(members_id, reload) {
let null_id = false;
users_id.forEach(user_id => {
if (user_id == null)
members_id.forEach(member_id => {
if (member_id == null)
null_id = true;
});
if (null_id)
return console.log(users_id, "createChannel error, null id;");
return console.log(members_id, "createChannel error, null id;");
let response = await this.client._post("/api/chat/", {
users_id:users_id
members_id:members_id
});
let data = await response.json();
@ -28,12 +28,13 @@ class Channels {
let messages = undefined;
if (exit_code == 200)
messages = data.messages;
return new Channel(this.client, data.channel_id, users_id, messages, reload);
return new Channel(this.client, data.channel_id, members_id, messages, reload);
}
async deleteChannel(users_id) {
async deleteChannel(members_id) {
let response = await this.client._delete("/api/chat/", {
users_id:users_id
members_id:members_id
});
let data = await response.json();

View File

@ -27,7 +27,6 @@ class TournamentSerializer(serializers.ModelSerializer):
if (value < 2):
raise serializers.ValidationError("The numbers of players must be greather than 2.")
return value
def validate_nb_players_by_game(self, value: int):
if (value < 2):
raise serializers.ValidationError("The numbers of players by game must be greather than 2.")