- Fixed forgetting to import "showActualGameMessage"
	- Changed filename "launchPrivateChat" to "showPrivateChat.js"
	- Fixed bug on buttons "private" and "game"
Global
	- Reorganize folders
This commit is contained in:
Kum1ta
2024-08-04 23:21:07 +02:00
parent cbdce2f62a
commit 28793464ca
33 changed files with 74 additions and 1228 deletions

View File

@ -1,121 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# User.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/03 15:54:14 by edbernar #+# #+# #
# Updated: 2024/08/04 15:55:15 by edbernar ### ########.fr #
# #
# **************************************************************************** #
import websockets
import asyncio
import json
connected_clients = []
class User():
debugMode = True
websocket = None
username = ""
token = ""
id = -1
def __init__(self, websocket):
if (self.debugMode):
print("\033[42m|------ New user Connected ------|\033[1;0m")
self.websocket = websocket
connected_clients.append(self)
def __del__(self):
if (self.debugMode):
print("\033[43m|------ User disconnected -------|\033[1;0m")
print("User :", self.username)
print("Id :", self.id)
connected_clients.remove(self)
async def sendError(self, message, code, error=None):
try:
jsonVar = {"type": "error", "content": message, "code": code}
self.printDebug(jsonVar, 2, error)
await self.websocket.send(json.dumps(jsonVar))
except:
if (self.debugMode):
print("\033[0;31m|------ Error in sendError ------|\033[0;0m")
async def send(self, content):
try:
if (type(content) == dict):
self.printDebug(content, 1)
await self.websocket.send(json.dumps(content))
else:
self.printDebug(json.loads(content), 1)
await self.websocket.send(content)
except Exception as e:
if (self.debugMode):
print("\033[0;31m|--------- Error in send --------|\033[0;0m")
print("Error message :", e)
async def verifyToken(self, token):
try:
if (self.token != token or self.token == ""):
await self.sendError("Invalid token", 9001)
return False
return True
except:
if (self.debugMode):
print("\033[0;31m|----- Error in verifyToken -----|\033[0;0m")
def printDebug(self, request, typeRequest, error=None):
try:
if (self.debugMode and typeRequest == 0):
print("\033[0;34m|----- New received request -----|\033[0;0m")
print("User :", self.username)
print("Token :", self.token)
print("Id :", self.id)
try:
print("Var type :", type(request["type"]))
print("Type :", request["type"])
except:
pass
try:
print("Content type :", request["content"])
except:
pass
elif (self.debugMode and typeRequest == 1):
print("\033[0;32m|------- New sent request -------|\033[0;0m")
print("To :", self.username)
print("Id :", self.id)
try:
print("Var type :", type(request["type"]))
print("Type :", request["type"])
except:
pass
try:
print("Content :", request["content"])
except:
pass
if ("type" not in request or "content" not in request):
print("Warning : not usual json format")
elif (self.debugMode and typeRequest == 2):
print("\033[0;31m|------------- Error ------------|\033[0;0m")
print("User :", self.username)
print("Token :", self.token)
print("Id :", self.id)
print("Error message :", request["content"])
print("Error code :", request["code"])
if (error != None):
print("Error python :", error)
print("File :", error.__traceback__.tb_frame.f_globals["__file__"])
print("Line :", error.__traceback__.tb_lineno)
except:
print("\033[0;31m|------ Error in printDebug -----|\033[0;0m")
async def close(self):
try:
await self.websocket.close()
except:
pass

View File

@ -1,61 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# main.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/03 08:10:40 by edbernar #+# #+# #
# Updated: 2024/08/04 14:31:26 by edbernar ### ########.fr #
# #
# **************************************************************************** #
from typeRequets.getPrivateListMessage import getPrivateListMessage
from typeRequets.getPrivateListUser import getPrivateListUser
from typeRequets.sendPrivateMessage import sendPrivateMessage
from typeRequets.login import login
from Class.User import User
import websockets
import asyncio
import json
# Todo :
# - verifier que l'utilisateur n'est pas déjà connecté pour éviter les doublons
typeRequest = ["login", "get_private_list_user", "get_private_list_message", "send_private_message"]
functionRequest = [login, getPrivateListUser, getPrivateListMessage, sendPrivateMessage]
async def handler(websocket, path):
if (path != "/"):
await websocket.sendError("Invalid path", 9003)
await websocket.close()
return
userClass = User(websocket)
try:
async for resquet in userClass.websocket:
try:
jsonRequest = json.loads(resquet)
except json.JSONDecodeError:
await userClass.sendError("Invalid JSON", 9002)
continue
try:
userClass.printDebug(jsonRequest, 0)
if (jsonRequest["type"] in typeRequest):
if jsonRequest["type"] == "login":
await functionRequest[typeRequest.index(jsonRequest["type"])](userClass, jsonRequest["content"])
else:
if (await userClass.verifyToken(jsonRequest["token"]) == False):
continue
await functionRequest[typeRequest.index(jsonRequest["type"])](userClass, jsonRequest["content"])
else:
await userClass.sendError("Invalid type", 9004)
except Exception as e:
await userClass.sendError("Invalid request", 9005, e)
except websockets.ConnectionClosed:
pass
await userClass.close()
start_server = websockets.serve(handler, "localhost", 8000, subprotocols=['123456'])
asyncio.get_event_loop().run_until_complete(start_server)
print("Server started")
asyncio.get_event_loop().run_forever()

View File

@ -1,69 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# getPrivateListMessage.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/03 22:53:14 by edbernar #+# #+# #
# Updated: 2024/08/03 23:43:09 by edbernar ### ########.fr #
# #
# **************************************************************************** #
import random
listMessage = {
"type": "private_list_message",
"content": [
{
"from": 0,
"content": "",
"date": "10:05 31/07/2024"
},
{
"from": 0,
"content": "",
"date": "10:05 31/07/2024"
},
{
"from": 0,
"content": "",
"date": "10:06 31/07/2024"
},
{
"from": 0,
"content": "",
"date": "10:06 31/07/2024"
},
{
"from": 0,
"content": "",
"date": "10:45 31/07/2024"
},
{
"from": 0,
"content": "",
"date": "10:46 31/07/2024"
}
]
}
def generate_random_string():
char = "abcdefghijklmnopqrstuvwxyz 123456789"
string = ""
for i in range(20):
string += char[random.randint(0, len(char) - 1)]
return string
async def getPrivateListMessage(userClass, content):
# |TOM| Requete pour avoir la liste des messages privés grace à l'id de l'utilisateur
copyListMessage = listMessage.copy()
for message in copyListMessage["content"]:
if (random.randint(1, 10) % 2 == 0):
message["from"] = 4561268
else:
message["from"] = content["id"]
message["content"] = generate_random_string()
await userClass.send(copyListMessage)

View File

@ -1,61 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# getPrivateListUser.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/03 15:10:23 by edbernar #+# #+# #
# Updated: 2024/08/04 14:00:44 by edbernar ### ########.fr #
# #
# **************************************************************************** #
import websockets
import asyncio
import json
data = [
{
"name": "Nessundorma",
"status": "online",
"pfp": "https://wallpapers-clan.com/wp-content/uploads/2023/05/cool-pfp-02.jpg",
"id": 145564
},
{
"name": "Succotash",
"status": "offline",
"pfp": "https://i.pinimg.com/200x/28/75/96/287596f98304bf1adc2c411619ae8fef.jpg",
"id": 256981
},
{
"name": "Astropower",
"status": "online",
"pfp": "https://ashisheditz.com/wp-content/uploads/2024/03/cool-anime-pfp-demon-slayer-HD.jpg",
"id": 301547
},
{
"name": "Assaultive",
"status": "offline",
"pfp": "https://i1.sndcdn.com/artworks-1Li0JIJrQGlojD3y-AEiNkw-t500x500.jpg",
"id": 432448
},
{
"name": "Redshock",
"status": "offline",
"pfp": "https://cdn.pfps.gg/pfps/7094-boy-pfp.png",
"id": 543211
},
{
"name": "Parley",
"status": "offline",
"pfp": "https://pbs.twimg.com/media/EscE6ckU0AA-Uhe.png",
"id": 654123
},
]
async def getPrivateListUser(userClass, content=None):
# |TOM| Faire une requête à la base de données pour récupérer la liste des
# utilisateurs qui doivent apparaitre dans la liste du chat privé
# (ceux qui ont eu conversation avec l'utilisateur)
# Si user existe pas, faire ça : await userClass.sendError("User not found", 9008)
await userClass.send({"type": "private_list_user", "content": data})

View File

@ -1,108 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# login.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/03 08:10:38 by edbernar #+# #+# #
# Updated: 2024/08/04 15:51:04 by edbernar ### ########.fr #
# #
# **************************************************************************** #
import requests
import json
# Les requêtes de login peuvent être de 3 types:
# <-- {"type" : "login", "content" : {"type": "byToken", "token": "123456"}}
# <-- {"type" : "login", "content" : {"type": "byPass", "mail": "aaa@a.com", "pass": "dasd"}}
# <-- {"type" : "login", "content" : {"type": "by42", "token": "1dsa23dsa456"}}
# --> {"type" : "login", "content" : {"username": "". "token": "", "id": 0}}
userList = [
{
"username": "Nexalith",
"token": "IDSNCSDAd465sd13215421",
"mail": "eddy@ediwor.fr",
"password": "ABC123",
"id": 9999999
},
{
"username": "user2",
"token": "789123",
"mail": "bb@bb.fr",
"password": "DEF456",
"id": 2
},
{
"username": "user3",
"token": "456789",
"mail": "cc@cc,fr",
"password": "GHI789",
"id": 3
}
]
async def loginByToken(userClass, content):
# |TOM| Requete pour savoir si le token est valide
for user in userList:
if (user["token"] == content["token"]):
jsonVar = {"type": "login", "content": {"username": user["username"], "token": user["token"], "id": user["id"]}}
userClass.username = jsonVar["content"]["username"]
userClass.token = jsonVar["content"]["token"]
userClass.id = jsonVar["content"]["id"]
await userClass.send(jsonVar)
return
jsonVar = {"type": "error", "content": "Invalid token", "code": 9001}
await userClass.send(json.dumps(jsonVar))
async def loginByPass(userClass, content):
# |TOM| Requete pour savoir si le mail et le mot de passe sont valides
# et créer un token si celui-ci n'existe pas
for user in userList:
if (user["mail"] == content["mail"] and user["password"] == content["password"]):
jsonVar = {"type": "login", "content": {"username": user["username"], "token": user["token"], "id": user["id"]}}
userClass.username = jsonVar["content"]["username"]
userClass.token = jsonVar["content"]["token"]
userClass.id = jsonVar["content"]["id"]
await userClass.send(jsonVar)
return
await userClass.send({"type": "error", "content": "Invalid username or password", "code": 9007})
async def verifyToken42(token42):
url = "https://api.intra.42.fr/v2/me"
headers = {
"Authorization": f"Bearer {token42}"
}
response = requests.get(url, headers=headers)
# |Eddy| Regarder ce que renvoie la requete quand elle est valide pour savoir qui rechercher
# dans la base de données
return (response.status_code == 200)
async def loginBy42(userClass, content):
# |TOM| Requete pour récuperer les informations de l'utilisateur selon l'intra de la personne
# et créer un token si celui-ci n'existe pas
for user in userList:
if (await verifyToken42(content["token42"])):
jsonVar = {"type": "login", "content": {"username": user["username"], "token": user["token"], "id": user["id"]}}
await userClass.send(json.dumps(jsonVar))
return
jsonVar = {"type": "error", "content": "Invalid 42 token", "code": 9008}
await userClass.send(json.dumps(jsonVar))
async def login(userClass, content):
# |TOM| Faire 3 types de requêtes:
# - byToken: Récupérer les informations de l'utilisateur en fonction de son token
# - byPass: Récupérer les informations de l'utilisateur en fonction de mail et de son mot de passe
# - by42: Récupérer les informations de l'utilisateur en fonction de son token42 (qui sera different du token)
try:
if (content["type"] == "byToken"):
await loginByToken(userClass, content)
elif (content["type"] == "byPass"):
await loginByPass(userClass, content)
elif (content["type"] == "by42"):
await loginBy42(userClass, content)
else:
await userClass.sendError("Invalid login type", 9006)
except Exception as e:
await userClass.sendError("Invalid request", 9005, e)

View File

@ -1,35 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# sendPrivateMessage.py :+: :+: :+: #
# +:+ +:+ +:+ #
# By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2024/08/04 13:44:11 by edbernar #+# #+# #
# Updated: 2024/08/04 15:48:24 by edbernar ### ########.fr #
# #
# **************************************************************************** #
from datetime import datetime
async def sendPrivateMessage(userClass, content):
# |Tom| Requete pour vérifier si l'user existe
# Si user existe pas, faire ça : await userClass.sendError("User not found", 9008)
# Sinon l'ajouter à la base de données
# |Eddy| Si user existe, envoyer le message privé aux deux personnes concernées
# sachant que le receveur doit être connecté. Dans le cas contraire, uniquement
# l'envoyeur recevra le message.
try:
time = content["time"]
time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S.%fZ")
time = time.strftime("%H:%M %d/%m/%Y")
jsonVar = {"type": "new_private_message", "content": {
"from": content["from"],
"channel": content["to"],
"content": content["content"],
"date": time
}}
await userClass.send(jsonVar)
except Exception as e:
await userClass.sendError("Invalid message sent", 9009, e)

View File

@ -22,12 +22,6 @@
<h2>X</h2>
</div>
</div>
<div id="buttonTypeChatHome">
<h2 id="selected">Private</h2>
<h2>Game</h2>
</div>
<div id="messageListChatHome">
</div>
</div>
</body>
</html>

View File

@ -6,48 +6,76 @@
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/04 19:19:10 by edbernar #+# #+# */
/* Updated: 2024/08/04 19:49:19 by edbernar ### ########.fr */
/* Updated: 2024/08/04 23:10:18 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import { infoPanel } from "../typeResponse/typePrivateListMessage.js";
import { showActualGameMessage } from "./showActualGameMessage.js";
import { showListUser } from "./showUserList.js";
/*
Todo (Eddy) :
- add a function to "New conversation +"
- game message when game will be implemented
- fix the bug on button "private" and "game"
*/
function addDefaultButton()
{
const newDiv = document.createElement("div");
const newPrivateButton = document.createElement("h2");
const newGameButton = document.createElement("h2");
const divMessageListChatHome = document.createElement("div");
newDiv.setAttribute("id", "buttonTypeChatHome");
newPrivateButton.textContent = "Private";
newGameButton.textContent = "Game";
newPrivateButton.setAttribute("id", "selected");
newDiv.appendChild(newPrivateButton);
newDiv.appendChild(newGameButton);
document.getElementById("chatDiv").appendChild(newDiv);
divMessageListChatHome.setAttribute("id", "messageListChatHome");
document.getElementById("chatDiv").appendChild(divMessageListChatHome);
newPrivateButton.addEventListener("click", async () => {
newGameButton.removeAttribute("id");
newPrivateButton.setAttribute("id", "selected");
await showListUser();
});
newGameButton.addEventListener("click", () => {
newPrivateButton.removeAttribute("id");
newGameButton.setAttribute("id", "selected");
showActualGameMessage();
});
}
function removeButtonIfExist()
{
const divButtonTypeChatHome = document.getElementById("buttonTypeChatHome");
if (divButtonTypeChatHome)
{
divButtonTypeChatHome.remove();
document.getElementById("messageListChatHome").remove();
}
}
function liveChat()
{
const chatButton = document.getElementById("chatButton");
const chatDiv = document.getElementById("chatDiv");
const topChatHomeCross = document.getElementById("topChatCross");
const privateButtonChatHome = document.getElementById("buttonTypeChatHome").getElementsByTagName("h2")[0];
const gameButtonChatHome= document.getElementById("buttonTypeChatHome").getElementsByTagName("h2")[1];
chatButton.addEventListener("click", async () => {
chatDiv.style.display = "flex";
gameButtonChatHome.removeAttribute("id");
privateButtonChatHome.setAttribute("id", "selected");
removeButtonIfExist();
addDefaultButton();
await showListUser();
});
topChatHomeCross.addEventListener("click", () => {
chatDiv.style.display = "none";
infoPanel.isOpen = false;
});
privateButtonChatHome.addEventListener("click", async () => {
gameButtonChatHome.removeAttribute("id");
privateButtonChatHome.setAttribute("id", "selected");
await showListUser();
});
gameButtonChatHome.addEventListener("click", () => {
privateButtonChatHome.removeAttribute("id");
gameButtonChatHome.setAttribute("id", "selected");
showActualGameMessage();
});
}
export { liveChat };

View File

@ -6,11 +6,11 @@
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/04 19:21:55 by edbernar #+# #+# */
/* Updated: 2024/08/04 19:49:35 by edbernar ### ########.fr */
/* Updated: 2024/08/04 22:41:07 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import { sendRequest } from "../websocket";
import { sendRequest } from "../websocket.js";
function showActualGameMessage()
{
@ -20,7 +20,7 @@ function showActualGameMessage()
isInGame: false,
opponent: {
name: "Astropower",
pfp: "https://ashisheditz.com/wp-content/uploads/2024/03/cool-anime-pfp-demon-slayer-HD.jpg"
id: "301547"
},
listMessage: [
{
@ -68,8 +68,8 @@ function showActualGameMessage()
request.listMessage.forEach(element => {
divMessageListChatHome.innerHTML += `
<div class="${element.from === me ? "meMessage" : "opponentMessage"}">
<p class="content">${element.content}</p>
<p class="time">${element.date}</p>
<p class="content">${element.content}</p>
<p class="time">${element.date}</p>
</div>
`;
});

View File

@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* launchPrivateChat.js :+: :+: :+: */
/* showPrivateChat.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/04 19:17:54 by edbernar #+# #+# */
/* Updated: 2024/08/04 19:42:49 by edbernar ### ########.fr */
/* Updated: 2024/08/04 23:00:10 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
@ -15,7 +15,9 @@ import { userMeInfo } from "../typeResponse/typeLogin.js";
import { showListUser } from "./showUserList.js";
import { sendRequest } from "../websocket.js";
async function launchPrivateChat(user)
let savedButtons = [];
async function showPrivateChat(user)
{
const divMessageListChatHome = document.getElementById("messageListChatHome");
@ -29,6 +31,16 @@ async function launchPrivateChat(user)
await displayInputBar(divMessageListChatHome, user);
}
async function restoreButton()
{
const divButtonTypeChatHome = document.getElementById("buttonTypeChatHome");
divButtonTypeChatHome.innerHTML = '';
savedButtons.forEach(element => {
divButtonTypeChatHome.appendChild(element);
});
}
async function changeButton(user)
{
const divButtonTypeChatHome = document.getElementById("buttonTypeChatHome");
@ -38,8 +50,10 @@ async function changeButton(user)
h2Button = divButtonTypeChatHome.getElementsByTagName("h2");
lenh2Button = h2Button.length;
savedButtons.splice(0, savedButtons.length);
for (let i = 0; i < lenh2Button; i++) {
h2Button[i - i].remove();
savedButtons.push(h2Button[0]);
h2Button[0].remove();
}
divButtonTypeChatHome.innerHTML += `
<h2>${user.name}</h2>
@ -49,10 +63,7 @@ async function changeButton(user)
returnButton = document.getElementById("returnButton");
returnButton.style.cursor = "pointer";
returnButton.addEventListener("click", () => {
divButtonTypeChatHome.innerHTML = `
<h2 id="selected">Private</h2>
<h2>Game</h2>
`;
restoreButton();
infoPanel.isOpen = false;
showListUser();
});
@ -122,4 +133,4 @@ function sendMessage(user) {
sendRequest("send_private_message", message);
}
export { launchPrivateChat };
export { showPrivateChat };

View File

@ -6,13 +6,13 @@
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/04 19:21:10 by edbernar #+# #+# */
/* Updated: 2024/08/04 19:29:20 by edbernar ### ########.fr */
/* Updated: 2024/08/04 22:54:30 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import { waitForUserList } from "../typeResponse/typePrivateListUser.js";
import { userList } from "../typeResponse/typePrivateListUser.js";
import { launchPrivateChat } from "./launchPrivateChat.js";
import { showPrivateChat } from "./showPrivateChat.js";
import { sendRequest } from "../websocket.js";
async function showListUser() {
@ -42,7 +42,7 @@ async function showListUser() {
divUser = document.getElementsByClassName("user");
for (let i = 0; i < divUser.length; i++) {
divUser[i].addEventListener("click", async () => {
await launchPrivateChat(userList[i]);
await showPrivateChat(userList[i]);
});
}
}