ball now bounces on walls, the speed of the ball now increase when it bounce anywhere (or take a jumper)

This commit is contained in:
2024-09-27 03:57:43 +02:00
parent 3f68bad744
commit 6fd802a788
10 changed files with 266 additions and 165 deletions

View File

@ -6,7 +6,7 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/13 16:20:58 by tomoron #+# #+# # # Created: 2024/09/13 16:20:58 by tomoron #+# #+# #
# Updated: 2024/09/25 17:08:55 by tomoron ### ########.fr # # Updated: 2024/09/27 03:54:50 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -33,7 +33,7 @@ class Game:
wallsPos = [ wallsPos = [
{ "type":2, "pos": {"x": 1, "y": 0, "z": 1}, "isUp": False}, { "type":2, "pos": {"x": 1, "y": 0, "z": 1}, "isUp": False},
{ "type":2, "pos": {"x": 1, "y": 0, "z": 1}, "isUp": True}, { "type":2, "pos": {"x": 1, "y": 0, "z": 1}, "isUp": True},
{ "type":2, "pos": {"x": -1, "y": 0, "z": 1}, "isUp": False}, { "type":2, "pos": {"x": -1, "y": 0, "z": 1}, "isUp": False},
{ "type":2, "pos": {"x": -1, "y": 0, "z": 1}, "isUp": True} { "type":2, "pos": {"x": -1, "y": 0, "z": 1}, "isUp": True}
] ]
jumpersPos = [ jumpersPos = [
@ -56,8 +56,11 @@ class Game:
{id: 6, 'color': None, 'texture': '/static/img/skin/3.jpg'}, {id: 6, 'color': None, 'texture': '/static/img/skin/3.jpg'},
{id: 7, 'color': None, 'texture': '/static/img/skin/4.jpg'}, {id: 7, 'color': None, 'texture': '/static/img/skin/4.jpg'},
] ]
wallLength = 1
wallWidth = 0.05
bounceSpeedIncrease = 0.2
def __init__(self, socket, withBot, skinId): def __init__(self, socket, withBot, skinId = 0, opponent = None):
self.p1 = None self.p1 = None
self.p2 = None self.p2 = None
self.p1Ready = False self.p1Ready = False
@ -76,8 +79,16 @@ class Game:
self.obstacles = [] self.obstacles = []
self.lastWin = 2 self.lastWin = 2
self.p1Skin = 0
self.p2Skin = 0
self.opponentLock = opponent
if(withBot): if(withBot):
self.join(socket) self.join(socket, skinId)
elif(opponent != None):
self.join(socket, skinId)
#send invite to oponnent
else: else:
while(Game.waitingForPlayerLock): while(Game.waitingForPlayerLock):
time.sleep(0.05) time.sleep(0.05)
@ -85,9 +96,9 @@ class Game:
if(Game.waitingForPlayer == None): if(Game.waitingForPlayer == None):
Game.waitingForPlayer = self Game.waitingForPlayer = self
socket.sync_send({"type":"game","content":{"action":0}}) socket.sync_send({"type":"game","content":{"action":0}})
self.join(socket) self.join(socket, skinId)
else: else:
Game.waitingForPlayer.join(socket) Game.waitingForPlayer.join(socket, skinId)
Game.waitingForPlayer = None Game.waitingForPlayer = None
Game.waitingForPlayerLock = False Game.waitingForPlayerLock = False
@ -98,25 +109,39 @@ class Game:
def genObstacles(self): def genObstacles(self):
for x in Game.wallsPos: for x in Game.wallsPos:
if random.randint(1, 100) < 0: if random.randint(1, 100) < 50:
self.obstacles.append(x) self.obstacles.append(x)
i = 0 i = 0
while(i < len(Game.jumpersPos)): down = False
up = False
while(i < len(Game.jumpersPos) - 2):
if(random.randint(1, 100) < 50): if(random.randint(1, 100) < 50):
self.obstacles.append(Game.jumpersPos[i]) self.obstacles.append(Game.jumpersPos[i])
i+=1 down = True
i+=1 else:
self.obstacles.append(Game.jumpersPos[i + 1])
up = True
i+=2
if not down:
self.obstacles.append(Game.jumperPos[i])
if not up:
self.obstacles.append(Game.jumperPos[i + 1])
self.p1.sync_send({"type":"game", "content":{"action":7, "content":self.obstacles}}) self.p1.sync_send({"type":"game", "content":{"action":7, "content":self.obstacles}})
self.obstaclesInvLength() self.obstaclesInvLength()
self.p2.sync_send({"type":"game", "content":{"action":7, "content":self.obstacles}}) self.p2.sync_send({"type":"game", "content":{"action":7, "content":self.obstacles}})
self.obstaclesInvLength() self.obstaclesInvLength()
def join(self, socket): def join(self, socket, skin):
try: try:
if(self.p1 == None): if(self.p1 == None):
self.p1 = socket self.p1 = socket
self.p1Skin = skin
else: else:
if(self.opponentLock != socket.id):
socket.sendError("You are not invited to this game", 9013)
return;
self.p2 = socket self.p2 = socket
self.p2Skin = skin
socket.game = self socket.game = self
if(self.p2 != None and self.p1 != None): if(self.p2 != None and self.p1 != None):
self.p1.sync_send({"type":"game", "content":{"action":1,"id":self.p2.id,"username":self.p2.username}}) self.p1.sync_send({"type":"game", "content":{"action":1,"id":self.p2.id,"username":self.p2.username}})
@ -192,15 +217,12 @@ class Game:
if(disc < 0): if(disc < 0):
return None return None
res = (((-b) + math.sqrt(disc)) / ( 2 * a )) + (((-b) - math.sqrt(disc)) / ( 2 * a )) res = (((-b) + math.sqrt(disc)) / ( 2 * a )) + (((-b) - math.sqrt(disc)) / ( 2 * a ))
print("res : ", res/2)
return(res / 2) return(res / 2)
def check_jumper_colision(self, jumper): def check_jumper_colision(self, jumper):
jpos = (jumper["pos"]["x"], jumper["pos"]["z"]) jpos = (jumper["pos"]["x"], jumper["pos"]["z"])
pos1 = self.ballPos["pos"] pos1 = self.ballPos["pos"]
pos2 = self.ballPos["pos"][0] +self.ballVel[0], self.ballPos["pos"][1] + self.ballVel[1] pos2 = self.ballPos["pos"][0] +self.ballVel[0], self.ballPos["pos"][1] + self.ballVel[1]
print(pos1)
print(pos2)
slope = 0 slope = 0
if(pos1[0] - pos2[0] == 0): if(pos1[0] - pos2[0] == 0):
slope=100000 slope=100000
@ -214,27 +236,59 @@ class Game:
c = (((-jpos[0]) ** 2) + (((-jpos[1]) + offset) ** 2)) - (Game.jumperRadius ** 2) c = (((-jpos[0]) ** 2) + (((-jpos[1]) + offset) ** 2)) - (Game.jumperRadius ** 2)
return(self.solve_quadratic(a, b ,c)) return(self.solve_quadratic(a, b ,c))
def check_wall_colision(self, wall):
wpos = wall["pos"]["x"]
pos1 = self.ballPos["pos"]
pos2 = self.ballPos["pos"][0] +self.ballVel[0], self.ballPos["pos"][1] + self.ballVel[1]
slope = 0
if(abs(pos1[1]) <= (Game.wallWidth / 2) + Game.ballRadius):
print("inside")
return(None)
if(pos1[0] - pos2[0] == 0):
slope=100000
else:
slope = (pos1[1] - pos2[1])/(pos1[0] - pos2[0])
offset = pos1[1] - (slope * pos1[0])
if(slope == 0):
return(None)
wallSide = (Game.wallWidth / 2) + Game.ballRadius
if(pos1[1] < 0):
wallSide *= -1
hitPos = (wallSide - offset) / slope
print(f'{hitPos=}')
relPos = wpos - hitPos
print("relative position : ", relPos)
print("max colision : ", (Game.wallLength / 2) + Game.ballRadius)
if(abs(relPos) < (Game.wallLength / 2) + Game.ballRadius):
return(hitPos)
print("not in wall 1")
return(None)
def check_collision_obstacles(self): def check_collision_obstacles(self):
min_time = -1 min_time = -1
for x in self.obstacles: for x in self.obstacles:
if x["isUp"] != self.ballPos["up"]: if x["isUp"] != self.ballPos["up"]:
continue continue
pos = None
if x["type"] == 1: if x["type"] == 1:
pos = self.check_jumper_colision(x) pos = self.check_jumper_colision(x)
if(pos == None): elif x["type"] == 2:
print("no colision") pos = self.check_wall_colision(x)
continue if(pos == None):
print("pos :", pos) continue
print("ballPos :", self.ballPos["pos"][0]) dist = pos - self.ballPos["pos"][0]
dist = pos - self.ballPos["pos"][0] time = 0
print("dist : ", dist) if(self.ballVel[0] != 0):
time = dist / (self.ballVel[0]) time = dist / self.ballVel[0]
if(time > 0): else:
if(min_time == -1): time = -1
min_time = time if(time > 0):
else: if(min_time == -1):
min_time = (min(min_time, time)) min_time = time
print("time :",time) else:
min_time = (min(min_time, time))
return(min_time) return(min_time)
def getTimeUntilColision(self, limitNeg, limitPos, position, velocity): def getTimeUntilColision(self, limitNeg, limitPos, position, velocity):
@ -259,9 +313,6 @@ class Game:
def getPlayerDistance(self, player, ballPos): def getPlayerDistance(self, player, ballPos):
playerPos = player["pos"] playerPos = player["pos"]
print("Player pos : ", playerPos)
print("chose player :", 2 if ballPos[1] < 0 else 1)
print("ball position :", ballPos[0])
return(playerPos - ballPos[0]) return(playerPos - ballPos[0])
async def scoreGoal(self, player): async def scoreGoal(self, player):
@ -281,14 +332,35 @@ class Game:
def checkJumpersDistance(self, ballPos): def checkJumpersDistance(self, ballPos):
for i in range(0, len(self.obstacles)): for i in range(0, len(self.obstacles)):
if(self.obstacles[i]["type"] != 1):
continue;
if(self.obstacles[i]["isUp"] != self.ballPos["up"]): if(self.obstacles[i]["isUp"] != self.ballPos["up"]):
continue continue
if(self.twoPointsDistance((self.obstacles[i]["pos"]["x"], self.obstacles[i]["pos"]["z"]), ballPos) < Game.jumperRadius): if(self.twoPointsDistance((self.obstacles[i]["pos"]["x"], self.obstacles[i]["pos"]["z"]), ballPos) < Game.jumperRadius):
self.p1.sync_send({"type":"game", "content":{"action":8,"id":i}}) self.p1.sync_send({"type":"game", "content":{"action":8,"id":i}})
self.p2.sync_send({"type":"game", "content":{"action":8,"id":i}}) self.p2.sync_send({"type":"game", "content":{"action":8,"id":i}})
self.ballPos["up"] = not self.ballPos["up"] self.ballPos["up"] = not self.ballPos["up"]
def checkWallsColision(self, ballPos):
for i in range(0, len(self.obstacles)):
if(self.obstacles[i]["type"] != 2):
continue;
if(self.obstacles[i]["isUp"] != self.ballPos["up"]):
continue;
if(abs(ballPos[1]) < (Game.wallWidth / 2) + Game.ballRadius):
if(abs(self.obstacles[i]["pos"]["x"] - ballPos[0]) < (Game.wallLength / 2) + Game.ballRadius):
print("not in wall 2")
return(True)
return(False)
def increaseSpeed(self):
x = self.ballVel[0] + (Game.bounceSpeedIncrease * (self.ballVel[0] / self.speed))
y = self.ballVel[1] + (Game.bounceSpeedIncrease * (self.ballVel[1] / self.speed))
self.ballVel = (x, y)
self.speed += Game.bounceSpeedIncrease
async def updateBall(self): async def updateBall(self):
print("AAAAAAAAAAAAAAAAAAAAAAA update")
now = time.time() now = time.time()
delta = now - self.lastUpdate delta = now - self.lastUpdate
currentBallPos = self.ballPos["pos"] currentBallPos = self.ballPos["pos"]
@ -305,19 +377,22 @@ class Game:
if(newBallPos[1] > 0): if(newBallPos[1] > 0):
velZ = -velZ velZ = -velZ
else: else:
print("distance :", playerDistance)
self.lastWin = 1 if newBallPos[1] < 0 else 2 self.lastWin = 1 if newBallPos[1] < 0 else 2
await self.scoreGoal(1 if newBallPos[1] < 0 else 2) await self.scoreGoal(1 if newBallPos[1] < 0 else 2)
return; return;
elif(newBallPos[0] <= Game.limits["left"] or newBallPos[0] >= Game.limits["right"]): elif(newBallPos[0] <= Game.limits["left"] or newBallPos[0] >= Game.limits["right"]):
velX = -velX velX = -velX
elif(self.checkWallsColision(newBallPos)):
velZ = -velZ
self.checkJumpersDistance(newBallPos) self.checkJumpersDistance(newBallPos)
self.ballVel = (velX, velZ) self.ballVel = (velX, velZ)
self.increaseSpeed()
self.lastUpdate = now self.lastUpdate = now
self.ballPos["pos"] = newBallPos self.ballPos["pos"] = newBallPos
self.sendNewBallInfo() self.sendNewBallInfo()
def prepareGame(self, stop = False): def prepareGame(self, stop = False):
self.speed = Game.startSpeed
self.ballPos = {"pos":(0, 0), "up": False} self.ballPos = {"pos":(0, 0), "up": False}
if(stop): if(stop):
self.ballVel = (0, 0) self.ballVel = (0, 0)
@ -333,6 +408,7 @@ class Game:
async def gameLoop(self): async def gameLoop(self):
self.started = True self.started = True
self.sendPlayers({"action":2}) self.sendPlayers({"action":2})
self.prepareGame(True)
await asyncio.sleep(3) await asyncio.sleep(3)
self.prepareGame() self.prepareGame()
while(not self.end): while(not self.end):

View File

@ -0,0 +1,95 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# fieldsVerif.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/09/27 02:22:43 by tomoron #+# #+# #
# Updated: 2024/09/27 03:34:11 by tomoron ### ########.fr #
# #
# **************************************************************************** #
import re
from .models import User
mail_pattern = "^((?!\\.)[\\w\\-_.]*[^.])(@\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$"
def usernameValid(username, socket=None):
err = None
code = 0
if (username.find(' ') != -1):
err = "Username must not contain spaces"
code = 9015
elif (len(username) < 3):
err = "Username must be at least 3 characters long"
code = 9016
elif (len(username) > 20):
err = "Username must be at most 20 characters long"
code = 9017
elif (not all(c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" for c in username)):
err = "Username must contain only letters and numbers"
code = 9018
elif (User.objects.filter(username=username).exists()):
err = "Username already used"
code = 9023
if(err and socket != None):
socket.sendError(err, code)
return(err == None)
def passwordValid(password, socket=None):
password_pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"
err = None
code = 0
if (len(password) < 8):
err = "Password must be at least 8 characters long"
code = 9019
# elif (password.find(content["username"]) != -1):
# err = "Password must not contain the username"
# code = 9021
elif (not bool(re.match(password_pattern, password))):
err = "Password must contain at least one lowercase letter, one uppercase letter and one special character"
code = 9020
if(err and socket != None):
socket.sendError(err, code)
return(err == None)
def discordValid(user, socket=None):
discord_pattern = "^[a-zA-Z0-9_.]{0,32}$"
err = None
code = 0
if (len(user) > 32):
err = "Discord username must be at most 32 characters long"
code = 9024
elif (not bool(re.match(discord_pattern, user))):
err = "Discord username must between 2 and 32 letters, numbers, underscores or points"
code = 9025
elif (len(user) == 1):
err = "Discord username must be at least 2 characters long"
code = 9026
if(err and socket != None):
socket.sendError(err, code)
return(err == None)
def mailValid(mail, socket=None):
mail_pattern = "^((?!\\.)[\\w\\-_.]*[^.])(@\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$"
err = None
code = 0
if (not bool(re.match(mail_pattern, mail))):
err = "Invalid mail"
code = 9014
if (User.objects.filter(mail=mail).exists()):
err = "Mail already used"
code = 9022
if(err and socket != None):
socket.sendError(err, code)
return(err == None)

View File

@ -6,28 +6,21 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/24 17:26:12 by edbernar #+# #+# # # Created: 2024/09/24 17:26:12 by edbernar #+# #+# #
# Updated: 2024/09/24 17:32:09 by edbernar ### ########.fr # # Updated: 2024/09/27 03:40:12 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from ..models import User from ..models import User
from ..utils import genString
from random import randint from random import randint
import base64 import base64
import json import json
def genereateRandomName():
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
len = 50
name = "a"
for i in range(0, len):
name += chars[randint(0, 61)]
return name
@sync_to_async @sync_to_async
def changeBanner(socket, content): def changeBanner(socket, content):
while True: while True:
generate_name = genereateRandomName() generate_name = genString(50)
if (not User.objects.filter(banner=f"/banner/{generate_name}.jpg").exists()): if (not User.objects.filter(banner=f"/banner/{generate_name}.jpg").exists()):
break break
user = User.objects.get(id=socket.id) user = User.objects.get(id=socket.id)
@ -35,4 +28,4 @@ def changeBanner(socket, content):
user.save() user.save()
with open(f"/var/www/djangoserver/banner/{generate_name}.jpg", "wb") as image_file: with open(f"/var/www/djangoserver/banner/{generate_name}.jpg", "wb") as image_file:
image_file.write(base64.b64decode(content["img"])) image_file.write(base64.b64decode(content["img"]))
socket.sync_send(json.dumps({"type": "change_pfp", "content": {'banner': user.banner}})) socket.sync_send(json.dumps({"type": "change_pfp", "content": {'banner': user.banner}}))

View File

@ -6,28 +6,21 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/23 23:35:41 by edbernar #+# #+# # # Created: 2024/09/23 23:35:41 by edbernar #+# #+# #
# Updated: 2024/09/24 15:53:26 by edbernar ### ########.fr # # Updated: 2024/09/27 03:37:33 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from ..models import User from ..models import User
from ..utils import genString
from random import randint from random import randint
import base64 import base64
import json import json
def genereateRandomName():
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
len = 50
name = "a"
for i in range(0, len):
name += chars[randint(0, 61)]
return name
@sync_to_async @sync_to_async
def changePfp(socket, content): def changePfp(socket, content):
while True: while True:
generate_name = genereateRandomName() generate_name = genString(50)
if (not User.objects.filter(pfp=f"/pfp/{generate_name}.jpg").exists()): if (not User.objects.filter(pfp=f"/pfp/{generate_name}.jpg").exists()):
break break
user = User.objects.get(id=socket.id) user = User.objects.get(id=socket.id)
@ -35,4 +28,4 @@ def changePfp(socket, content):
user.save() user.save()
with open(f"/var/www/djangoserver/pfp/{generate_name}.jpg", "wb") as image_file: with open(f"/var/www/djangoserver/pfp/{generate_name}.jpg", "wb") as image_file:
image_file.write(base64.b64decode(content["img"])) image_file.write(base64.b64decode(content["img"]))
socket.sync_send(json.dumps({"type": "change_pfp", "content": {'pfp': user.pfp}})) socket.sync_send(json.dumps({"type": "change_pfp", "content": {'pfp': user.pfp}}))

View File

@ -6,96 +6,54 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/25 23:28:49 by edbernar #+# #+# # # Created: 2024/09/25 23:28:49 by edbernar #+# #+# #
# Updated: 2024/09/26 14:56:22 by edbernar ### ########.fr # # Updated: 2024/09/27 03:23:10 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from ..models import User from ..models import User
from ..fieldsVerif import usernameValid, passwordValid, discordValid
import hashlib import hashlib
import json import json
import re
mail_pattern = "^((?!\\.)[\\w\\-_.]*[^.])(@\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$"
password_pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"
discord_pattern = "^[a-zA-Z0-9_.]{0,32}$"
@sync_to_async @sync_to_async
def changePrivateInfo(socket, content): def changePrivateInfo(socket, content):
try: try:
data = [] user = User.objects.get(id=socket.id)
if (content.get("username")): if ("delete" in content):
data.append("username")
if (content.get("new_password")):
data.append("new_password")
if (content.get("discord")):
data.append("discord")
if (content.get("delete")):
data.append("delete")
if (len(data) != 1):
socket.sendError("You must provide exactly one field to update", 9028)
return
if (content.get("delete")):
user = User.objects.get(id=socket.id)
user.delete() user.delete()
socket.scope["session"].delete() socket.scope["session"].delete()
socket.sync_send(json.dumps({"type": "change_private_info", "content": "Successfully deleted."})) socket.sync_send(json.dumps({"type": "change_private_info", "content": "Successfully deleted."}))
socket.close() socket.close()
return return;
if (content.get("username")): elif ("username" in content):
if (content["username"].find(' ') != -1): if (not usernameValid(content.get("username"), socket)):
socket.sendError("Username must not contain spaces", 9015)
return return
if (len(content["username"]) < 3):
socket.sendError("Username must be at least 3 characters long", 9016)
return
if (len(content["username"]) > 20):
socket.sendError("Username must be at most 20 characters long", 9017)
return
if (not all(c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" for c in content["username"])):
socket.sendError("Username must contain only letters and numbers", 9018)
return
if (User.objects.filter(username=content["username"]).exists()):
socket.sendError("Username already used", 9023)
return
if (content.get("new_password")):
if (not content.get("old_password")):
raise Exception("Old password is required")
if (len(content["new_password"]) < 8):
socket.sendError("Password must be at least 8 characters long", 9019)
return
if (content["new_password"].find(str(content.get("username"))) != -1):
socket.sendError("Password must not contain the username", 9021)
return
if (not bool(re.match(password_pattern, content["password"]))):
socket.sendError("Password must contain at least one lowercase letter, one uppercase letter and one special character", 9020)
if (not bool(re.match(password_pattern, content["new_password"]))):
return
if (content.get("discord")):
if (len(content["discord"]) > 32):
socket.sendError("Discord must be at most 32 characters long", 9024)
return
if (not bool(re.match(discord_pattern, content["discord"]))):
socket.sendError("Discord must contain only letters, numbers and underscores or points", 9025)
return
user = User.objects.get(id=socket.id)
if (content.get("username")):
user.username = content["username"] user.username = content["username"]
socket.username = content["username"] socket.username = content["username"]
socket.scope["session"]['username'] = content["username"] socket.scope["session"]['username'] = content["username"]
if (content.get("new_password")): elif ("new_password" in content):
if (not passwordValid(content.get("new_password"), socket)):
return
if (not content.get("old_password")):
socket.sendError("You must provide your current password to change it",9030)
return
if (hashlib.md5((user.mail + content["old_password"]).encode()).hexdigest() != user.password): if (hashlib.md5((user.mail + content["old_password"]).encode()).hexdigest() != user.password):
socket.sendError("Invalid password", 9029) socket.sendError("Invalid password", 9029)
return return
user.password = hashlib.md5((user.mail + content["new_password"]).encode()).hexdigest() user.password = hashlib.md5((user.mail + content["new_password"]).encode()).hexdigest()
if (content.get("discord")): elif ("discord" in content):
if (content["discord"] != ""): if (not discordValid(content.get("discord"), socket)):
user.discord_username = content["discord"] return
else: if (content["discord"] == ""):
user.discord_username = None user.discord_username = None
else:
user.discord_username = content["discord"]
else:
socket.sendError("You must provide a field to update", 9028)
return;
user.save() user.save()
socket.scope["session"].save() socket.scope["session"].save()
socket.sync_send(json.dumps({"type": "change_private_info", "content": "Successfully updated."})) socket.sync_send(json.dumps({"type": "change_private_info", "content": "Successfully updated."}))
except Exception as e: except Exception as e:
socket.sendError("An unknown error occured", 9027, e) socket.sendError("An unknown error occured", 9027, e)

View File

@ -6,7 +6,7 @@
# By: marvin <marvin@student.42.fr> +#+ +:+ +#+ # # By: marvin <marvin@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/08/09 08:08:00 by edbernar #+# #+# # # Created: 2024/08/09 08:08:00 by edbernar #+# #+# #
# Updated: 2024/09/22 18:58:55 by marvin ### ########.fr # # Updated: 2024/09/27 03:37:05 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -16,15 +16,14 @@ from ..data import ICLOUD_USER, ICLOUD_PASS, SERVER_URL
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email.mime.image import MIMEImage from email.mime.image import MIMEImage
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from ..fieldsVerif import mailValid, usernameValid, passwordValid
from ..utils import genString
import smtplib import smtplib
import random import random
import re import re
import json import json
import hashlib import hashlib
mail_pattern = "^((?!\\.)[\\w\\-_.]*[^.])(@\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$"
password_pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$"
allowed_char_username = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
URLMAIL = SERVER_URL + "/verify?token=" URLMAIL = SERVER_URL + "/verify?token="
@sync_to_async @sync_to_async
@ -34,40 +33,16 @@ def createAccount(socket, content):
socket.sendError("Already logged in", 9012) socket.sendError("Already logged in", 9012)
return; return;
try: try:
if (not bool(re.match(mail_pattern, content["mail"]))): if(not mailValid(content["mail"], socket)):
socket.sendError("Invalid mail", 9014)
return return
if (content["username"].find(' ') != -1): if(not usernameValid(content["username"], socket)):
socket.sendError("Username must not contain spaces", 9015)
return return
if (len(content["username"]) < 3): if(not passwordValid(content["password"], socket)):
socket.sendError("Username must be at least 3 characters long", 9016)
return
if (len(content["username"]) > 20):
socket.sendError("Username must be at most 20 characters long", 9017)
return
if (not all(c in allowed_char_username for c in content["username"])):
socket.sendError("Username must contain only letters and numbers", 9018)
return
if (len(content["password"]) < 8):
socket.sendError("Password must be at least 8 characters long", 9019)
return
if (not bool(re.match(password_pattern, content["password"]))):
socket.sendError("Password must contain at least one lowercase letter, one uppercase letter and one special character", 9020)
return
if (content["password"].find(content["username"]) != -1):
socket.sendError("Password must not contain the username", 9021)
return
if (User.objects.filter(mail=content["mail"]).exists()):
socket.sendError("Mail already used", 9022)
return
if (User.objects.filter(username=content["username"]).exists()):
socket.sendError("Username already used", 9023)
return return
password = hashlib.md5((content["mail"] + content["password"]).encode()).hexdigest() password = hashlib.md5((content["mail"] + content["password"]).encode()).hexdigest()
new_user = User.objects.create(username=content["username"], mail=content["mail"], password=password) new_user = User.objects.create(username=content["username"], mail=content["mail"], password=password)
new_user.save() new_user.save()
verif_str = gen_string(200) verif_str = genString(200)
MailVerify.objects.create(uid=new_user, token=verif_str).save() MailVerify.objects.create(uid=new_user, token=verif_str).save()
print("send") print("send")
socket.sync_send(json.dumps({"type": "create_account", "content": "Account created"})) socket.sync_send(json.dumps({"type": "create_account", "content": "Account created"}))
@ -175,7 +150,3 @@ def sendVerifMail(verif_str, mail, username):
except Exception as e: except Exception as e:
print(f"Erreur lors de l'envoi de l'e-mail : {e}") print(f"Erreur lors de l'envoi de l'e-mail : {e}")
return(0) return(0)
def gen_string(length):
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return(''.join(random.choice(letters) for i in range(length)))

View File

@ -6,7 +6,7 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/11 17:07:08 by tomoron #+# #+# # # Created: 2024/09/11 17:07:08 by tomoron #+# #+# #
# Updated: 2024/09/25 09:23:02 by edbernar ### ########.fr # # Updated: 2024/09/27 02:12:40 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -16,5 +16,5 @@ async def start(socket, content):
if(socket.game != None): if(socket.game != None):
socket.sendError("Game already started", 9102) socket.sendError("Game already started", 9102)
return; return;
Game(socket, content.get("with_bot", False), content.get("skinId", 0)) Game(socket, content.get("with_bot", False), content.get("skinId", 0), content.get("opponent", None))

View File

@ -6,25 +6,23 @@
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ # # By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/09/18 07:26:07 by edbernar #+# #+# # # Created: 2024/09/18 07:26:07 by edbernar #+# #+# #
# Updated: 2024/09/18 08:20:44 by edbernar ### ########.fr # # Updated: 2024/09/27 03:48:39 by tomoron ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from ..models import User from ..models import User
from django.db.models import Q
import json import json
@sync_to_async @sync_to_async
def searchUser(socket, content): def searchUser(socket, content):
try: try:
users = User.objects.filter(username__contains=content["username"]) users = User.objects.filter(Q(username__contains=content["username"]) & ~Q(id=socket.id))[:10]
userList = [] userList = []
for user in users: for user in users:
if (user.id != socket.id and user.mail_verified): userList.append((user.username, user.id, user.pfp))
userList.append((user.username, user.id, user.pfp)) socket.sync_send({"type":"search_user", "content":userList})
if len(userList) >= 10:
break
socket.sync_send({"type":"search_user", "content":userList if userList else []})
except Exception as e: except Exception as e:
socket.sendError("An unknown error occured", 9027, e) socket.sendError("An unknown error occured", 9027, e)
return return

View File

@ -0,0 +1,15 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# utils.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: tomoron <tomoron@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/09/27 03:36:08 by tomoron #+# #+# #
# Updated: 2024/09/27 03:36:42 by tomoron ### ########.fr #
# #
# **************************************************************************** #
def genString(length):
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return(''.join(random.choice(letters) for i in range(length)))

View File

@ -31,7 +31,9 @@
- 9027 : An unknown error occured - 9027 : An unknown error occured
- 9028 : You must provide exactly one field to update - 9028 : You must provide exactly one field to update
- 9029 : Invalid password - 9029 : Invalid password
- 9030 : You must provide your current password to it
- 9100 : Action out of range - 9100 : Action out of range
- 9101 : No game started - 9101 : No game started
- 9102 : Game already started - 9102 : Game already started
- 9103 : You are not invited to this game