11 Commits

Author SHA1 Message Date
072944c503 game: add: config 2023-12-28 15:21:02 +01:00
5db03a3c69 tournament: fix 2023-12-28 15:20:25 +01:00
231622a2c2 game: init: consumer 2023-12-28 12:02:39 +01:00
f11af8336a game: init: class 2023-12-28 12:01:52 +01:00
2e8eebc788 game: allow any to get game data 2023-12-28 11:34:18 +01:00
bfc58e74a9 game: add: retrive view 2023-12-28 11:33:06 +01:00
4739afbaf0 block: fix: .exists() 2023-12-28 11:32:49 +01:00
9f7b813292 chat: fix and opti 2023-12-27 16:14:39 +01:00
cfb14be945 Merge branch 'Chatte' into server 2023-12-27 09:59:19 +01:00
4fd6616786 add block option 2023-12-20 23:48:52 +01:00
57ed6165ea bug issue; rewrite all messages 2023-12-19 12:42:46 +01:00
32 changed files with 470 additions and 159 deletions

View File

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

View File

@ -1,20 +1,25 @@
import json
from channels.generic.websocket import WebsocketConsumer from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync 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 time
import json
class ChatConsumer(WebsocketConsumer): class ChatConsumer(WebsocketConsumer):
def connect(self): def connect(self):
channel_id : str = self.scope['path'].split('/')[3]
self.room_group_name = 'chat' + channel_id
user = self.scope["user"] user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated): if (user.is_anonymous or not user.is_authenticated):
return 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 return
if (self.channel_layer == None): if (self.channel_layer == None):
@ -29,26 +34,40 @@ class ChatConsumer(WebsocketConsumer):
def receive(self, text_data=None, bytes_data=None): def receive(self, text_data=None, bytes_data=None):
if text_data == None: if text_data == None:
return return
text_data_json = json.loads(text_data)
message = text_data_json['message']
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"] user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated): if (user.is_anonymous or not user.is_authenticated):
return 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 return
if (self.channel_layer == None): if (self.channel_layer == None):
return return
print(message) message_time: int = int(time.time() * 1000)
if (len(receivers_id) == 1 and
BlockModel.objects.filter(blocker=user.pk, blocked=receivers_id[0]) or
BlockModel.objects.filter(blocker=receivers_id[0], blocked=user.pk)
):
return
message_time : int = int(time.time() * 1000)
async_to_sync(self.channel_layer.group_send)( async_to_sync(self.channel_layer.group_send)(
self.room_group_name, self.room_group_name,
{ {
@ -59,22 +78,17 @@ class ChatConsumer(WebsocketConsumer):
} }
) )
new_message = MessageModel() new_message = ChatMessageModel(channel_id = channel_id, author_id = user.pk, content = message, time = message_time).save()
new_message.channel_id = channel_id
new_message.author_id = user.pk
new_message.content = message
new_message.time = message_time
new_message.save()
def chat_message(self, event): def chat_message(self, event):
channel_id : int = int(self.scope['path'].split('/')[3])
user = self.scope["user"] user = self.scope["user"]
if (user.is_anonymous or not user.is_authenticated): if (user.is_anonymous or not user.is_authenticated):
return 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 return
self.send(text_data=json.dumps({ self.send(text_data=json.dumps({

View File

@ -4,21 +4,28 @@ from django.contrib.auth.models import User
from django.contrib import admin from django.contrib import admin
# Create your models here. # Create your models here.
class ChannelModel(models.Model): class ChatChannelModel(models.Model):
pass
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) member_id = IntegerField(primary_key=False)
channel_id = IntegerField(primary_key=False) channel_id = IntegerField(primary_key=False)
def __str__(self): def __str__(self):
return "member_id: " + str(self.member_id) + ", channel_id: " + str(self.channel_id) 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) channel_id = IntegerField(primary_key=False)
author_id = IntegerField(primary_key=False) author_id = IntegerField(primary_key=False)
content = models.CharField(max_length=255) content = models.CharField(max_length=255)
time = IntegerField(primary_key=False) time = IntegerField(primary_key=False)
def __str__(self): 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 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: class Meta:
model = ChannelModel model = ChatChannelModel
fields = [] 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 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. # 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 from . import views
urlpatterns = [ urlpatterns = [
path("<int:pk>", views.ChatView.as_view(), name="chat_page"), path("", views.ChannelView.as_view(), name="chats_page"),
path("", views.ChatsView.as_view(), name="chats_page"),
] ]

View File

@ -1,79 +1,45 @@
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response 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 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 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,) permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,) 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)
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): def post(self, request):
data: dict = request.data serializer = self.serializer_class(data = request.data)
users_id = request.data.get("users_id", [])
if len(users_id) < 2: serializer.is_valid(raise_exception=True)
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)
for user_id1 in users_id: data: dict = serializer.validated_data
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()
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() for member_channel in ChatMemberModel.objects.filter(member_id = members_id[0]):
new_member.channel_id = new_channel.pk channel_id: int = member_channel.channel_id
new_member.member_id = user_id if not ChatChannelModel.objects.filter(pk = channel_id).exists():
new_member.save() 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) new_channel_id = ChatChannelModel().create(members_id)
return Response({'channel_id': new_channel_id}, 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)

View File

@ -35,7 +35,9 @@ class Channel {
this.chatSocket.close(); this.chatSocket.close();
} }
updateMessages(messages) { updateMessages(messages)
{
console.log(messages);
messages = JSON.parse(messages); messages = JSON.parse(messages);
let new_messages = []; let new_messages = [];
@ -54,13 +56,14 @@ class Channel {
return new_messages; return new_messages;
} }
async sendMessageChannel(message) { async sendMessageChannel(message, receivers_id) {
if (this.chatSocket == undefined) if (this.chatSocket == undefined)
return; return;
this.chatSocket.send(JSON.stringify({ this.chatSocket.send(JSON.stringify({
'message':message 'message':message,
'receivers_id':receivers_id,
})); }));
} }

View File

@ -6,18 +6,18 @@ class Channels {
this.client = client; this.client = client;
} }
async createChannel(users_id, reload) { async createChannel(members_id, reload) {
let null_id = false; let null_id = false;
users_id.forEach(user_id => { members_id.forEach(member_id => {
if (user_id == null) if (member_id == null)
null_id = true; null_id = true;
}); });
if (null_id) 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/", { let response = await this.client._post("/api/chat/", {
users_id:users_id members_id:members_id
}); });
let data = await response.json(); let data = await response.json();
@ -28,12 +28,13 @@ class Channels {
let messages = undefined; let messages = undefined;
if (exit_code == 200) if (exit_code == 200)
messages = data.messages; 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/", { let response = await this.client._delete("/api/chat/", {
users_id:users_id members_id:members_id
}); });
let data = await response.json(); let data = await response.json();

View File

@ -38,10 +38,11 @@ class Client
return this.logged; return this.logged;
} }
async _get(uri) async _get(uri, data)
{ {
let response = await fetch(this._url + uri, { let response = await fetch(this._url + uri, {
method: "GET", method: "GET",
body: JSON.stringify(data),
}); });
return response; return response;
} }

View File

@ -12,8 +12,9 @@ class Profile
*/ */
this.client = client; this.client = client;
this.username = username; this.username = username;
this.avatar_url = avatar_url this.avatar_url = avatar_url;
this.user_id = user_id this.user_id = user_id;
this.isBlocked = false;
} }
async init(user_id) async init(user_id)
@ -28,7 +29,21 @@ class Profile
this.user_id = response_data.user_id; this.user_id = response_data.user_id;
this.username = response_data.username; this.username = response_data.username;
this.avatar_url = response_data.avatar_url; this.avatar_url = response_data.avatar_url;
let block_response = await this.client._get("/api/profiles/block");
if (block_response.status == 404)
return
let block_data = await block_response.json();
let block_list = JSON.parse(block_data);
block_list.forEach(block => {
let blocker = block.fields.blocker;
let blocked = block.fields.blocked;
if (blocker == this.client.me.user_id && blocked == user_id)
return this.isBlocked = true;
});
} }
} }
export {Profile} export {Profile}

View File

@ -36,13 +36,30 @@ class Profiles
async block(user_id) { async block(user_id) {
// blocker & blocked // blocker & blocked
let response = await this.client._post("/api/block/", let response = await this.client._post("/api/profiles/block", {
[this.client.me.user_id, user_id], users_id:[this.client.me.user_id, user_id],
); });
let data = await response.json(); let data = await response.json();
console.log(response.status);
console.log(data);
return data;
} }
async deblock(user_id) {
// blocker & blocked
let response = await this.client._delete("/api/profiles/block", {
users_id:[this.client.me.user_id, user_id],
});
let data = await response.json();
console.log(response.status);
console.log(data);
return data;
}
} }
export {Profiles} export {Profiles}

View File

@ -14,33 +14,48 @@ export default class extends AbstractView {
if (profile === null) if (profile === null)
return 1; return 1;
let info = document.getElementById("info"); this.profile = await client.profiles.getProfile(this.user_id);
this.info = document.getElementById("info");
// Username // Username
let username = document.createElement("a"); let username = document.createElement("a");
username.id = "username"; username.id = "username";
username.appendChild(document.createTextNode(profile.username)); username.appendChild(document.createTextNode(this.profile.username));
info.appendChild(username); this.info.appendChild(username);
info.appendChild(document.createElement("br")); this.info.appendChild(document.createElement("br"));
// Avatar // Avatar
let avatar = document.createElement("img"); let avatar = document.createElement("img");
avatar.id = "avatar"; avatar.id = "avatar";
avatar.src = profile.avatar_url; avatar.src = this.profile.avatar_url;
info.appendChild(avatar); this.info.appendChild(avatar);
// Block option await this.blockButton();
let block = document.createElement("a");
block.id = "block";
block.addEventListener("click", async () => {
if (client.me.user_id != user.user_id) {
}
});
block.appendChild(document.createTextNode("Block"));
info.appendChild(block);
} }
async blockButton() {
// Block option
if (client.me.user_id != this.user_id) {
let block = document.getElementById("block") || document.createElement("a");
block.id = "block";
block.innerText = "";
block.onclick = async () => {
if (!this.profile.isBlocked)
await client.profiles.block(this.user_id);
else
await client.profiles.deblock(this.user_id);
this.profile = await client.profiles.getProfile(this.user_id);
this.blockButton();
};
if (this.profile.isBlocked)
block.appendChild(document.createTextNode("Deblock"));
else
block.appendChild(document.createTextNode("Block"));
this.info.appendChild(block);
}
}
async getHtml() { async getHtml() {
return ` return `
<link rel="stylesheet" href="/static/css/profile.css"> <link rel="stylesheet" href="/static/css/profile.css">

View File

@ -100,6 +100,7 @@ export default class extends AbstractView {
async chat() { async chat() {
let users = await client.profiles.all();
let logged = await client.isAuthentificate(); let logged = await client.isAuthentificate();
/*let reload = document.getElementById("messages"); /*let reload = document.getElementById("messages");
if (reload != null) if (reload != null)
@ -135,7 +136,7 @@ export default class extends AbstractView {
// les messages, réecriture seulement du dernier // les messages, réecriture seulement du dernier
let i = 0; let i = 0;
client.channel.messages.forEach((message) => { client.channel.messages.forEach((message) => {
if (messages[i] == null || message != messages.children[i].innerText) { if (messages.children[i] == null || message.content != messages.children[i].innerText) {
let text = document.createElement("p"); let text = document.createElement("p");
text.appendChild(document.createTextNode(message.content)); text.appendChild(document.createTextNode(message.content));
if (message.author_id == client.me.user_id) if (message.author_id == client.me.user_id)
@ -158,21 +159,25 @@ export default class extends AbstractView {
chat_input.maxLength=255; chat_input.maxLength=255;
chat.appendChild(chat_input); chat.appendChild(chat_input);
chat_input.addEventListener("keydown", async () => { chat_input.onkeydown = async () => {
if (event.keyCode == 13 && client.channel != undefined) { if (event.keyCode == 13 && client.channel != undefined) {
//let chat_input = document.getElementById("input_chat"); //let chat_input = document.getElementById("input_chat");
let chat_text = chat_input.value; let chat_text = chat_input.value;
await client.channel.sendMessageChannel(chat_text) let receivers_id = [];
client.channel.members_id.forEach((member_id) => {
if (member_id != client.me.user_id)
receivers_id.push(users.filter(user => user.user_id == member_id)[0].user_id);
});
await client.channel.sendMessageChannel(chat_text, receivers_id)
// Reset // Reset
chat_input.value = ""; chat_input.value = "";
} }
}); };
} }
// nom des membres du chat // nom des membres du chat
let users = await client.profiles.all();
let members = document.createElement("h2"); let members = document.createElement("h2");
members.id = "members"; members.id = "members";
let usernames = ""; let usernames = "";

9
games/config.py Normal file
View File

@ -0,0 +1,9 @@
PADDLE_SPEED_MAX = 1
PADDLE_SIZE_HEIGHT = 10
PADDLE_SIZE_WIDTH = 100
PADDLE_RAIL = PADDLE_SIZE_WIDTH * 5
BALL_SPEED_INC = 1
BALL_SPEED_START = 1
BALL_SIZE = 4

42
games/consumers.py Normal file
View File

@ -0,0 +1,42 @@
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth.models import User
from games.models import GameModel
import json
from .models import game_room_manager
class GameWebSocket(AsyncWebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.channel_name = "games"
self.group_name = "games"
def connect(self):
self.user: User = self.scope["user"]
if (self.user.is_anonymous or not self.user.is_authenticated):
return
self.channel_layer.group_add(self.group_name, self.channel_name)
self.game_id = int(self.scope['url_route']['kwargs']['game_id'])
self.room = game_room_manager.get(self.game_id)
if (self.room is None):
self.member.send("Tournament not found")
self.disconnect(1017)
self.room.append(self.member)
def receive(self, text_data: str = None, bytes_data: bytes = None):
self.member.receive(text_data, bytes_data)
def disconnect(self, close_code):
member = self.room.get_member_by_socket(self)
if (member is not None):
self.room.remove(self.member, close_code)

View File

@ -1,5 +1,9 @@
from django.db import models from django.db import models
from .objects.GameRoomManager import GameRoomManager
from channels.generic.websocket import AsyncWebsocketConsumer
# Create your models here. # Create your models here.
class GameModel(models.Model): class GameModel(models.Model):
@ -18,4 +22,6 @@ class GameModel(models.Model):
class GameMembersModel(models.Model): class GameMembersModel(models.Model):
game_id = models.IntegerField() game_id = models.IntegerField()
player_id = models.IntegerField() player_id = models.IntegerField()
game_room_manager: GameRoomManager = GameRoomManager()

View File

@ -0,0 +1,17 @@
from channels.generic.websocket import AsyncWebsocketConsumer
from transcendence.abstract.AbstractRoomMember import AbstractRoomMember
class GameMember(AbstractRoomMember):
def __init__(self, user_id: int, socket: AsyncWebsocketConsumer):
super().__init__(user_id, socket)
self.is_a_player = False
def receive(self, data: dict):
if (not self.is_a_player):
self.send("You are not a player.")
return
def send_ball(self, ball):
pass

View File

@ -0,0 +1,9 @@
from transcendence.abstract.AbstractRoom import AbstractRoom
from .GameRoomManager import GameRoomManager
class GameRoom(AbstractRoom):
def __init__(self, game_room_manager: GameRoomManager, game_id: int):
super().__init__(game_room_manager)
self.game_id = game_id

View File

@ -0,0 +1,18 @@
from transcendence.abstract.AbstractRoomManager import AbstractRoomManager
from ..models import GameModel
class GameRoomManager(AbstractRoomManager):
def get(self, game_id: int):
for room in self._room_list:
if (room.game_id == game_id):
return room
if (GameModel.objects.filter(pk = tournament_id).exists()):
room = TournamentRoom(self, game_id)
self.append(room)
return room
return None

6
games/routing.py Normal file
View File

@ -0,0 +1,6 @@
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/tournaments/(?P<tournament_id>\d+)$', consumers.TournamentWebConsumer.as_asgi())
]

View File

@ -21,4 +21,5 @@ class GameSerializer(serializers.ModelSerializer):
return "waiting" return "waiting"
def get_players_id(self, instance: GameModel): def get_players_id(self, instance: GameModel):
players_id = [player_game.member_id for player_game in GameMembersModel.objects.filter(game_id=instance.pk)] players_id = [player_game.player_id for player_game in GameMembersModel.objects.filter(game_id = instance.pk)]
return players_id

11
games/urls.py Normal file
View File

@ -0,0 +1,11 @@
from django.urls import path, re_path
from django.conf import settings
from django.conf.urls.static import static
from .viewset import GameViewSet
from .views import GameConfigView
urlpatterns = [
path("<int:pk>", GameViewSet.as_view({"get": "retrieve"}), name="game_page"),
path("", GameConfigView.as_view(), name = "game_config")
]

View File

@ -1,3 +1,23 @@
from django.shortcuts import render from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions, status
# Create your views here. from django.http import HttpRequest
from . import config
class GameConfigView(APIView):
permission_classes = (permissions.AllowAny,)
def get(self, request):
config_data = {
"BALL_SIZE": config.BALL_SIZE,
"PADDLE_SPEED_MAX": config.PADDLE_SPEED_MAX,
"PADDLE_SIZE_HEIGHT": config.PADDLE_SIZE_HEIGHT,
"PADDLE_SIZE_WIDTH": config.PADDLE_SIZE_WIDTH,
"PADDLE_RAIL": config.PADDLE_RAIL,
"BALL_SPEED_INC": config.BALL_SPEED_INC,
"BALL_SPEED_START": config.BALL_SPEED_START
}
return Response(config_data, status = status.HTTP_200_OK)

27
games/viewset.py Normal file
View File

@ -0,0 +1,27 @@
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import permissions, status
from rest_framework.authentication import SessionAuthentication
from django.http import HttpRequest
from django.db.models import QuerySet
from .models import GameModel
from .serializers import GameSerializer
# Create your views here.
class GameViewSet(viewsets.ModelViewSet):
queryset = GameModel.objects
serializer_class = GameSerializer
permission_classes = (permissions.AllowAny,)
authentication_classes = (SessionAuthentication,)
def retrieve(self, request: HttpRequest, pk):
if (not self.queryset.filter(pk = pk).exists()):
return Response({"detail": "Game not found."}, status=status.HTTP_404_NOT_FOUND)
game = self.queryset.get(pk=pk)
return Response(self.serializer_class(game).data, status=status.HTTP_200_OK)

View File

@ -1,6 +1,7 @@
from django.contrib import admin from django.contrib import admin
from .models import ProfileModel from .models import ProfileModel, BlockModel
# Register your models here. # Register your models here.
admin.site.register(ProfileModel) admin.site.register(ProfileModel)
admin.site.register(BlockModel)

View File

@ -9,5 +9,7 @@ urlpatterns = [
path("me", viewsets.MyProfileViewSet.as_view({'patch': 'partial_update', 'get': 'retrieve'}), name="my_profile_page"), path("me", viewsets.MyProfileViewSet.as_view({'patch': 'partial_update', 'get': 'retrieve'}), name="my_profile_page"),
path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve'}), name="profile_page"), path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve'}), name="profile_page"),
path("", viewsets.ProfileViewSet.as_view({'get': 'list'}), name="profiles_list"), path("", viewsets.ProfileViewSet.as_view({'get': 'list'}), name="profiles_list"),
path("block", views.BlockView.as_view(), name="block_page"), path("block", views.BlocksView.as_view(), name="block_page"),
path("block/<int:pk>", views.BlockView.as_view(), name="block_page"),
] + static("/static/avatars/", document_root="./avatars") ] + static("/static/avatars/", document_root="./avatars")

View File

@ -2,17 +2,65 @@ from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import authentication, permissions, status from rest_framework import authentication, permissions, status
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.renderers import JSONRenderer
from django.core import serializers from django.core import serializers
from .models import BlockModel
class BlockView(APIView): class BlockView(APIView):
permission_classes = (permissions.IsAuthenticated,) permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,) authentication_classes = (SessionAuthentication,)
def post(self, request, pk):
pass
def get(self, request, pk): def get(self, request, pk):
pass block = BlockModel.objects.filter(pk=pk)
if (block.exists()):
return Response(serializers.serialize("json", block), status=status.HTTP_200_OK)
else:
return Response("Not Found", status=status.HTTP_404_NOT_FOUND)
def delete(self, request, pk):
pass class BlocksView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
blocks = BlockModel.objects.filter(blocker=request.user.pk)
if (blocks):
return Response(serializers.serialize("json", BlockModel.objects.filter(blocker=request.user.pk)), status=status.HTTP_200_OK)
else:
return Response({}, status=status.HTTP_404_NOT_FOUND)
def post(self, request):
data: dict = request.data
users_id = request.data.get("users_id", None)
if (users_id == None):
return Response({"Error"}, status=status.HTTP_400_BAD_REQUEST)
if (BlockModel.objects.filter(blocker=users_id[0], blocked=users_id[1])):
return Response({"Already Exist"}, status=status.HTTP_409_CONFLICT)
new_block = BlockModel()
new_block.blocker = users_id[0]
new_block.blocked = users_id[1]
new_block.save()
return Response({"block_id": new_block.pk}, status=status.HTTP_201_CREATED)
def delete(self, request):
data: dict = request.data
users_id = request.data.get("users_id", None)
if (users_id == None):
return Response({"Error"}, status=status.HTTP_400_BAD_REQUEST)
block = BlockModel.objects.filter(blocker=users_id[0], blocked=users_id[1])
print(list(block))
if (block.count() > 1):
return Response("Not normal >:[", status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if (not block):
return Response("Don't exist", status=status.HTTP_404_NOT_FOUND)
block.delete()
return Response("Deleted", status=status.HTTP_200_OK)

View File

@ -2,5 +2,5 @@ from django.urls import re_path
from . import consumers from . import consumers
websocket_urlpatterns = [ websocket_urlpatterns = [
re_path(r'ws/tournaments/(?P<tournament_id>\d+)$', consumers.TournamentWebConsumer.as_asgi()) re_path(r'ws/games/(?P<game_id>\d+)$', consumers.TournamentWebConsumer.as_asgi())
] ]

View File

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

View File

@ -14,6 +14,7 @@ from channels.auth import AuthMiddlewareStack
import chat.routing import chat.routing
import matchmaking.routing import matchmaking.routing
import tournament.routing import tournament.routing
import games.routing
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
@ -25,7 +26,8 @@ application = ProtocolTypeRouter({
URLRouter( URLRouter(
chat.routing.websocket_urlpatterns + chat.routing.websocket_urlpatterns +
matchmaking.routing.websocket_urlpatterns + matchmaking.routing.websocket_urlpatterns +
tournament.routing.websocket_urlpatterns tournament.routing.websocket_urlpatterns +
games.routing.websocket_urlpatterns
) )
) )
}) })

View File

@ -23,5 +23,6 @@ urlpatterns = [
path('api/accounts/', include('accounts.urls')), path('api/accounts/', include('accounts.urls')),
path('api/chat/', include('chat.urls')), path('api/chat/', include('chat.urls')),
path('api/tournaments/', include('tournament.urls')), path('api/tournaments/', include('tournament.urls')),
path('api/games/', include('games.urls')),
path('', include('frontend.urls')), path('', include('frontend.urls')),
] ]