etienne apprend à coder pitié

This commit is contained in:
AdrienLSH 2024-05-14 08:16:21 +02:00
parent c4dc5b4e39
commit e2d56cff85
9 changed files with 126 additions and 170 deletions

View File

@ -1,40 +1,41 @@
from django.db import models
from django.db.models import IntegerField
from django.db.models import Model, IntegerField, ForeignKey, CharField, CASCADE
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.contrib import admin
# Create your models here.
class ChatChannelModel(models.Model):
def create(self, users_id: [int]):
class ChatChannelModel(Model):
def create(self, members: [User]):
self.save()
for user_id in users_id:
ChatMemberModel(channel_id = self.pk, member_id = user_id).save()
return self.pk
for member in members:
ChatMemberModel(channel=self, member=member).save()
return self
def get_members_id(self):
return [member_channel.member_id for member_channel in ChatMemberModel.objects.filter(channel_id = self.pk)]
def get_members(self):
return [member_channel.member for member_channel in ChatMemberModel.objects.filter(channel=self)]
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 ChatMemberModel(Model):
member = ForeignKey(User, on_delete=CASCADE)
channel = ForeignKey(ChatChannelModel, on_delete=CASCADE)
class ChatMessageModel(models.Model):
channel_id = IntegerField(primary_key=False)
author_id = IntegerField(primary_key=False)
content = models.CharField(max_length=255)
@receiver(post_delete, sender=ChatMemberModel)
def delete_channel_when_member_deleted(sender, instance, **kwargs):
print(sender, instance)
class ChatMessageModel(Model):
channel = ForeignKey(ChatChannelModel, on_delete=CASCADE)
author = ForeignKey(User, on_delete=CASCADE)
content = 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
class AskModel(models.Model):
class AskModel(Model):
asker_id = IntegerField(primary_key=False)
asked_id = IntegerField(primary_key=False)
# return if the asker ask the asked to play a game
def is_asked(self, asker_id, asked_id):
return AskModel.objects.get(asker_id=asker_id, asked_id=asked_id) != None
return AskModel.objects.get(asker_id=asker_id, asked_id=asked_id) is not None

View File

@ -1,17 +1,19 @@
from rest_framework import serializers
from django.utils.translation import gettext as _
from django.contrib.auth.models import User
from profiles.models import ProfileModel
from ..models import ChatChannelModel, ChatMessageModel
class ChatChannelSerializer(serializers.ModelSerializer):
members_id = serializers.ListField(child=serializers.IntegerField())
members_id = serializers.ListField(child=serializers.IntegerField(), required=True, write_only=True)
messages = serializers.SerializerMethodField()
class Meta:
model = ChatChannelModel
fields = ["members_id", "pk"]
fields = ["members_id", "id", 'messages']
def validate_members_id(self, value):
members_id: [int] = value
@ -19,14 +21,20 @@ class ChatChannelSerializer(serializers.ModelSerializer):
raise serializers.ValidationError(_('There is not enough members to create the channel.'))
if len(set(members_id)) != len(members_id):
raise serializers.ValidationError(_('Duplicate in members list.'))
if self.context.get('user').pk not in members_id:
raise serializers.ValidationError(_('You are trying to create a group chat without you.'))
for member_id in members_id:
if not ProfileModel.objects.filter(pk=member_id).exists():
if not User.objects.filter(pk=member_id).exists():
raise serializers.ValidationError(_(f"The profile {member_id} doesn't exist."))
return members_id
def get_messages(self, obj: ChatChannelModel):
messages = ChatMessageModel.objects.filter(channel=obj).order_by('time')
return ChatMessageSerializer(messages, many=True).data
class ChatMessageSerializer(serializers.Serializer):
class ChatMessageSerializer(serializers.ModelSerializer):
class Meta:
model = ChatMessageModel
fields = ["channel_id", "author_id", "content", "time"]
fields = ["channel", "author", "content", "time"]

View File

@ -1,6 +1,4 @@
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import chat
from .views import ask

View File

@ -1,48 +1,31 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions, status
from rest_framework import permissions
from rest_framework.authentication import SessionAuthentication
from django.http import HttpRequest
from django.contrib.auth import login
from django.db.models import QuerySet
from django.core import serializers
from django.contrib.auth.models import User
from ..models import ChatChannelModel, ChatMemberModel
from ..serializers import ChatChannelSerializer
from ..models import ChatChannelModel, ChatMemberModel, ChatMessageModel
from ..serializers.chat import ChatChannelSerializer, ChatMessageSerializer
class ChannelView(APIView):
queryset = ChatChannelModel.objects
serializer_class = ChatChannelSerializer
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def post(self, request):
serializer = self.serializer_class(data = request.data)
serializer = self.serializer_class(data=request.data, context={'user': request.user})
serializer.is_valid(raise_exception=True)
data: dict = serializer.validated_data
members_id = serializer.validated_data.get('members_id')
member_list = [User.objects.get(pk=member_id) for member_id in members_id]
members_id = data.get("members_id")
if members_id == None:
return Response({"detail": "members_id is None."}, status = status.HTTP_400_BAD_REQUEST)
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)
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)
new_channel_id = ChatChannelModel().create(members_id)
return Response({'channel_id': new_channel_id}, status=status.HTTP_201_CREATED)
for member_channel in ChatMemberModel.objects.filter(member=member_list[0]):
channel: ChatChannelModel = member_channel.channel
if set(channel.get_members()) == set(member_list):
break
else:
channel = ChatChannelModel().create(member_list)
return Response(self.serializer_class(channel).data)

View File

@ -1,9 +1,15 @@
import { Account } from "./Account.js";
import { MatchMaking } from "./Matchmaking.js";
import { Profiles } from "./Profiles.js";
import { Channels } from './chat/Channels.js';
import { MyProfile } from "./MyProfile.js";
<<<<<<< Updated upstream
import { Channel } from "./chat/Channel.js";
||||||| Stash base
import { Tourmanents } from "./tournament/Tournaments.js";
import { Channel } from "./chat/Channel.js";
=======
import { Tourmanents } from "./tournament/Tournaments.js";
>>>>>>> Stashed changes
import Notice from "./Notice.js";
import LanguageManager from './LanguageManager.js';
@ -50,16 +56,6 @@ class Client
*/
this._logged = undefined;
/**
* @type {Channels}
*/
this.channels = new Channels(this);
/**
* @type {Channel}
*/
this.channel = undefined;
/**
* @type {Notice}
*/

View File

@ -1,10 +1,10 @@
import {Message} from "./Message.js";
class Channel {
constructor(client, channel_id, members_id, messages, reload) {
constructor(client, channel, members, messages, reload) {
this.client = client;
this.channel_id = channel_id;
this.members_id = members_id;
this.channel = channel;
this.members = members;
this.messages = [];
if (messages != undefined)
this.updateMessages(messages);
@ -13,16 +13,18 @@ class Channel {
}
// reload = function to use when we receive a message
async connect(reload) {
let url = `${window.location.protocol[4] === 's' ? 'wss' : 'ws'}://${window.location.host}/ws/chat/${this.channel_id}`;
connect(reload) {
const url = location.origin.replace('http', 'ws') +
'/ws/chat/' +
this.channel;
this.chatSocket = new WebSocket(url);
this.chatSocket.onmessage = (event) =>{
let data = JSON.parse(event.data);
this.messages.push(new Message(
this.channel_id,
data.author_id,
this.channel,
data.author,
data.content,
data.time,
));
@ -31,28 +33,22 @@ class Channel {
};
}
async disconnect() {
disconnect() {
this.chatSocket.close();
}
updateMessages(messages)
{
messages = JSON.parse(messages);
let new_messages = [];
this.messages = [];
messages.forEach((message) => {
message = message.fields;
new_messages.push(new Message(
message.channel_id,
message.author_id,
this.messages.push(new Message(
message.channel,
message.author,
message.content,
message.time,
));
});
//console.log(new_messages);
this.messages = new_messages;
return new_messages;
}
async sendMessageChannel(message, receivers_id) {
@ -65,19 +61,6 @@ class Channel {
'receivers_id':receivers_id,
}));
}
async deleteChannel() {
let response = await this.client._delete("/api/chat/" + this.channel_id, {
});
let data = await response.json();
return data;
}
async sendInvite() {
}
}
export {Channel};

View File

@ -1,6 +1,6 @@
import {Channel} from "./Channel.js";
class Channels {
export default class Channels {
constructor(client) {
this.client = client;
this.channel = undefined;
@ -8,32 +8,16 @@ class Channels {
async createChannel(members_id, reload) {
let response = await this.client._post("/api/chat/", {
const response = await this.client._post("/api/chat/", {
members_id:members_id
});
if (response.status >= 300)
return undefined;
let data = await response.json();
const data = await response.json();
console.log(data)
let messages;
if (response.status == 200)
messages = data.messages;
this.channel = new Channel(this.client, data.channel_id, members_id, messages, reload);
return this.channel;
this.channel = new Channel(this.client, data.id, members_id, data.messages, reload);
}
async deleteChannel(members_id) {
let response = await this.client._delete("/api/chat/", {
members_id:members_id
});
let data = await response.json();
return data;
}
}
export {Channels};

View File

@ -1,7 +1,7 @@
class Message {
constructor(channel_id, author_id, content, time) {
this.channel_id = channel_id;
this.author_id = author_id;
constructor(channel, author, content, time) {
this.channel = channel;
this.author = author;
this.content = content;
this.time = time;
}

View File

@ -1,35 +1,37 @@
import AbstractView from "./abstracts/AbstractView.js";
import { client, lang } from "../index.js";
import {Message} from "../api/chat/Message.js";
import Channels from '../api/chat/Channels.js'
export default class extends AbstractView {
constructor(params) {
super(params, 'SearchWindowTitle');
this.channelManager = new Channels(client);
}
async postInit() {
this.profiles = await client.profiles.all();
this.logged = await client.isAuthenticated();
this.logged = await client.isAuthenticated();
this.profiles = await client.profiles.all();
document.getElementById('username-input').oninput = () => this.display_users(this.logged, this.profiles);
let search = document.getElementById("input_user");
if (search != undefined)
search.oninput = () => this.display_users();
let chat_input = document.getElementById("input_chat");
this.last_add_chat = undefined;
this.display_users();
this.display_chat();
}
async display_users() {
let search = document.getElementById("input_user").value.toLowerCase();
const search = document.getElementById("username-input").value.toLowerCase();
let list_users = document.getElementById('list_users');
let list_users = document.getElementById('user-list');
list_users.innerHTML = "";
this.profiles.filter(user => user.username.toLowerCase().startsWith(search) == true).forEach(async (user) => {
@ -69,23 +71,23 @@ export default class extends AbstractView {
let add_chat = document.createElement("a");
add_chat.id = "add_chat_off";
add_chat.onclick = async () => {
if (client.channels.channel != undefined) {
if (this.channelManager.channel != undefined) {
// Permet de savoir si c'est le même channel
// Check to know if it's the same channel
client.channels.channel.members_id.forEach((member_id) => {
this.channelManager.channel.members_id.forEach((member_id) => {
if (member_id == user.id)
client.channels.channel = undefined;
this.channelManager.channel = undefined;
});
if (client.channels.channel == undefined) {
if (this.channelManager.channel == undefined) {
add_chat.id = "add_chat_off";
this.last_add_chat = undefined;
return await this.hide_chat();
}
await client.channels.channel.disconnect();
await this.channelManager.channel.disconnect();
}
client.channels.channel = await client.channels.createChannel([client.me.id , user.id], () => this.reload_display_messages());
await this.channelManager.createChannel([client.me.id , user.id], () => this.reload_display_messages());
this.display_chat();
if (this.last_add_chat != undefined)
this.last_add_chat.id = "add_chat_off";
@ -141,7 +143,7 @@ export default class extends AbstractView {
document.getElementById(reload).remove();
});
if (client.channels.channel === undefined || this.logged === false)
if (this.channelManager.channel === undefined || this.logged === false)
return ;
let chats = document.getElementById("chats");
@ -159,19 +161,19 @@ export default class extends AbstractView {
let messages = await this.display_messages(chat);
// Input pour rentrer un message
let chat_input = document.getElementById("input_chat") || document.createElement("input");
chat_input.id="input_chat";
let chat_input = document.getElementById("chat-input") || document.createElement("input");
chat_input.id="chat_input";
chat_input.type="text";
chat_input.name="message";
chat_input.placeholder="message bozo";
chat_input.maxLength=255;
chat.appendChild(chat_input);
let members_id = client.channels.channel.members_id;
let members_id = this.channelManager.channel.members_id;
chat_input.onkeydown = async () => {
if (event.keyCode == 13 && client.channels.channel != undefined) {
//let chat_input = document.getElementById("input_chat");
if (event.keyCode == 13 && this.channelManager.channel != undefined) {
//let chat_input = document.getElementById("chat-input");
let chat_text = chat_input.value;
let receivers_id = [];
@ -179,7 +181,7 @@ export default class extends AbstractView {
if (member_id != client.me.id)
receivers_id.push(this.profiles.filter(user => user.id == member_id)[0].id);
});
await client.channels.channel.sendMessageChannel(chat_text, receivers_id);
await this.channelManager.channel.sendMessageChannel(chat_text, receivers_id);
// Reset
chat_input.value = "";
}
@ -190,7 +192,7 @@ export default class extends AbstractView {
// Scroll to the bottom of messages
messages.scrollTop = messages.scrollHeight;
this.display_invite();
// this.display_invite();
}
@ -202,12 +204,13 @@ export default class extends AbstractView {
chat.appendChild(messages);
// les messages, réecriture seulement du dernier
client.channels.channel.messages.forEach((message) => {
this.channelManager.channel.messages.forEach((message) => {
let text = document.createElement("p");
let date = new Date(message.time);
text.title = date.toLocaleString("fr-FR");
text.appendChild(document.createTextNode(message.content));
text.id = message.author_id === client.me.id ? "you" : "other";
console.log(message.author, client.me.id)
text.id = message.author === client.me.id ? "you" : "other";
messages.appendChild(text);
});
@ -219,13 +222,13 @@ export default class extends AbstractView {
let messages = document.getElementById("messages");
let i = 0;
client.channels.channel.messages.forEach((message) => {
this.channelManager.channel.messages.forEach((message) => {
if (messages.children[i] == null || message.content != messages.children[i].innerText) {
let text = document.createElement("p");
let date = new Date(message.time);
text.title = date.toLocaleString("fr-FR");
text.appendChild(document.createTextNode(message.content));
text.id = message.author_id === client.me.id ? "you" : "other";
text.id = message.author === client.me.id ? "you" : "other";
messages.appendChild(text);
}
@ -237,7 +240,7 @@ export default class extends AbstractView {
async display_members(chat) {
let members_id = client.channels.channel.members_id;
let members_id = this.channelManager.channel.members_id;
let members = document.createElement("h2");
members.id = "members";
@ -263,7 +266,7 @@ export default class extends AbstractView {
if (chat == undefined)
return ;
let members_id = client.channels.channel.members_id;
let members_id = this.channelManager.channel.members_id;
let others = members_id.filter(id => id !== client.me.id);
let invite = document.getElementById("invite") || document.createElement("button");
@ -325,9 +328,9 @@ export default class extends AbstractView {
}
async leavePage() {
if (client.channels.channel != undefined)
client.channels.channel.disconnect();
client.channels.channel = undefined;
if (this.channelManager.channel != undefined)
this.channelManager.channel.disconnect();
this.channelManager.channel = undefined;
}
@ -337,8 +340,8 @@ export default class extends AbstractView {
<div id="chats">
<div id="users">
<input id="input_user" type="text" name="message" placeholder="userbozo"/>
<ul id="list_users">
<input id="username-input" type="text" name="message" placeholder="userbozo"/>
<ul id='user-list'>
</ul>
</div>
</div>