diff --git a/backend/src/index.ts b/backend/src/index.ts index cd19cb9..8614484 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -3,6 +3,7 @@ import mongoose from "mongoose"; import { router as roomRoutes } from "./routes/roomRoutes.js"; import { router as messageRoutes } from "./routes/messageRoutes.js"; import { router as userRoutes } from "./routes/userRoutes.js"; +import { router as SingleUser } from "./routes/single_user.js"; import { app, server } from "./routes/socket.js"; import { log } from "./utils/log.js"; import cors from "cors"; @@ -21,6 +22,7 @@ app.use(bodyParser.json()); app.use("/rooms", roomRoutes); app.use("/messages", messageRoutes); app.use("/user", userRoutes); +app.use("/single_user", SingleUser); server.listen(process.env.PORT || 4000, () => { log("SERVER RUNNING"); diff --git a/backend/src/models/single_user.ts b/backend/src/models/single_user.ts new file mode 100644 index 0000000..44d5548 --- /dev/null +++ b/backend/src/models/single_user.ts @@ -0,0 +1,30 @@ +import { Schema, model, Document, Model } from "mongoose"; + +interface ISingleUser extends Document { + username: string; + socketId: string; +} + +interface ISingleUserModel extends Model { + findAll(): Promise; +} + +const singleUserSchema = new Schema({ + username: { type: String, required: true, unique: true }, + socketId: { type: String, required: true }, +}); + +singleUserSchema.statics.findAll = function (): Promise { + return this.find().exec(); +}; + +singleUserSchema.statics.findOneByUsername = function ( + socketId: string +): Promise { + return this.findOne({ socketId }).exec(); +}; + +export const SingleUser = model( + "SingleUser", + singleUserSchema +); diff --git a/backend/src/routes/single_user.ts b/backend/src/routes/single_user.ts new file mode 100644 index 0000000..e66c0bb --- /dev/null +++ b/backend/src/routes/single_user.ts @@ -0,0 +1,74 @@ +import express, { Request, Response } from "express"; +export const router = express.Router(); +import { SingleUser } from "../models/single_user.js"; + +router.post("/newuser", async (req: Request, res: Response) => { + const { username, socketId } = req.body; + + console.log(req.body); // Log the request body + + try { + const existingUser = await SingleUser.findOne({ + $or: [{ username }, { socketId }], + }); + if (existingUser) { + return res + .status(400) + .json({ message: "Username or SocketId already exists" }); + } + + const newUser = await SingleUser.create({ + username, + socketId, + }); + + res.status(201).json(newUser); + } catch (error: any) { + console.error(error); // Log the entire error + res.status(500).json({ message: error.message }); + } +}); + +router.get("/", async (req: Request, res: Response) => { + try { + const users = await SingleUser.find(); + res.status(200).json(users); + } catch (error: any) { + res.status(500).json({ message: error.message }); + } +}); + +router.get("/:socketId", async (req: Request, res: Response) => { + const { socketId } = req.params; + + try { + const user = await SingleUser.findOne({ socketId }); + + if (!user) { + return res.status(404).json({ message: "User not found" }); + } + + res.status(200).json(user); + } catch (error: any) { + res.status(500).json({ message: error.message }); + } +}); + +router.put("/updateusername", async (req: Request, res: Response) => { + const { socketId, newUsername } = req.body; + + try { + const user = await SingleUser.findOne({ socketId }); + + if (!user) { + return res.status(404).json({ message: "User not found" }); + } + + user.username = newUsername; + const updatedUser = await user.save(); + + res.status(200).json(updatedUser); + } catch (error: any) { + res.status(500).json({ message: error.message }); + } +}); diff --git a/backend/src/routes/socket.ts b/backend/src/routes/socket.ts index badbe3d..1900a62 100644 --- a/backend/src/routes/socket.ts +++ b/backend/src/routes/socket.ts @@ -9,7 +9,6 @@ import express from "express"; import dotenv from "dotenv"; import { User } from "../models/user.js"; - export const app = express(); app.use(cors()); dotenv.config(); @@ -24,7 +23,6 @@ const io = new Server(server, { maxHttpBufferSize: 2e7, }); -let users: { [key: string]: string } = {}; mongoose .connect( `mongodb://${process.env.MONGODB_USER}:${process.env.MONGODB_USER_PASSWORD}@mongodb:27017/${process.env.MONGO_INITDB_DATABASE}` @@ -38,7 +36,6 @@ let userNames: { [key: string]: string } = {}; io.on("connection", (socket) => { // changer de nom socket.on("change_name", ({ newName, OldName, roomId }) => { - console.log("User changed name: ", newName); userNames[socket.id] = newName; socket.emit("name_changed", newName); @@ -114,7 +111,7 @@ io.on("connection", (socket) => { io.emit("users_response", roomUsers); log(`User with ID: ${socket.id} joined room: ${roomId}`); }); - + socket.on("send_message", async (data) => { io.emit("receive_message", data); @@ -142,7 +139,7 @@ io.on("connection", (socket) => { }); socket.on("user_joined", ({ username, roomId }) => { - socket.to(roomId).emit("receive_message", { + io.emit("receive_message", { text: username + " joined the room. 🗿", socketId: "Kurama-chat", roomId: roomId, @@ -150,7 +147,7 @@ io.on("connection", (socket) => { }); }); - socket.on("leave_room", ({ username, roomId }) => { + socket.on("leave_room", async ({ username, roomId }) => { socket.leave(roomId); if (roomUsers[roomId]) { roomUsers[roomId] = roomUsers[roomId].filter((id) => id !== socket.id); @@ -163,8 +160,8 @@ io.on("connection", (socket) => { systemMessage: true, }); - io.emit("users_response", roomUsers); - log(`User with ID: ${socket.id} left room: ${roomId}`); + socket.to(roomId).emit("users_response", roomUsers); + console.log(`User with ID: ${socket.id} left room: ${roomId}`); }); socket.on("quit_room", async ({ username, roomId }) => { @@ -180,7 +177,7 @@ io.on("connection", (socket) => { systemMessage: true, }); - io.emit("users_response", roomUsers); + socket.to(roomId).emit("users_response", roomUsers); if (roomUsers[roomId] && roomUsers[roomId].length === 0) { try { @@ -194,21 +191,21 @@ io.on("connection", (socket) => { } }); - socket.on("logout", ({ username, roomId }) => { - socket.leave(roomId); + socket.on("logout", async ({ username, roomId }) => { if (roomUsers[roomId]) { roomUsers[roomId] = roomUsers[roomId].filter((id) => id !== socket.id); } io.emit("receive_message", { - text: username + " left the room. ➡️🚪", + text: username + " disconnect. ❌", socketId: "Kurama-chat", roomId: roomId, systemMessage: true, }); - io.emit("users_response", roomUsers); + socket.to(roomId).emit("users_response", roomUsers); log(`User with ID: ${socket.id} left room: ${roomId}`); + socket.leave(roomId); delete userNames[socket.id]; }); @@ -223,8 +220,8 @@ io.on("connection", (socket) => { roomId: roomId, systemMessage: true, }); + socket.to(roomId).emit("users_response", roomUsers); } } - io.emit("users_response", roomUsers); }); }); diff --git a/docker-compose.yml b/docker-compose.yml index f311137..a51ae12 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,7 +49,6 @@ services: - MONGODB_USER_PASSWORD=${MONGODB_USER_PASSWORD} - PORT=${PORT} - DEBUG=${DEBUG} - - ORIGIN_URL=${ORIGIN_URL} ports: - 4000:4000 diff --git a/frontend/src/app/chat/[roomId]/page.tsx b/frontend/src/app/chat/[roomId]/page.tsx index ee63d59..e92f092 100644 --- a/frontend/src/app/chat/[roomId]/page.tsx +++ b/frontend/src/app/chat/[roomId]/page.tsx @@ -19,6 +19,11 @@ function Page() { roomId: roomId, }); socket?.emit("join_room", roomId); + socket?.emit("change_name", { + newName: username, + OldName: username, + roomId: "", + }); }, []); return ( diff --git a/frontend/src/components/Room/AddRoomPanel.tsx b/frontend/src/components/Room/AddRoomPanel.tsx index 85174ee..7f3b1c4 100644 --- a/frontend/src/components/Room/AddRoomPanel.tsx +++ b/frontend/src/components/Room/AddRoomPanel.tsx @@ -25,7 +25,6 @@ function AddRoomPanel({ hideAddRoomPanel }: any) { return; } - // Fetch room data from server const response = await fetch( process.env.NEXT_PUBLIC_BASE_URL + `rooms/${joinId}` ); diff --git a/frontend/src/components/Room/RoomCard.tsx b/frontend/src/components/Room/RoomCard.tsx index 854baa8..8d0e789 100644 --- a/frontend/src/components/Room/RoomCard.tsx +++ b/frontend/src/components/Room/RoomCard.tsx @@ -8,12 +8,13 @@ import Avatar from "react-avatar"; import { ImExit } from "react-icons/im"; import { useSocket } from "@/contexts/SocketContext"; import { useRouter } from "next/navigation"; +import { useUser } from "@/contexts/UserContext"; function RoomCard({ room, users }: { room: IRoom; users: string[] }) { const { roomId } = useParams(); const { myRooms, setMyRooms } = useRoom(); const { socket } = useSocket(); - const username = localStorage.getItem("name"); + const { username } = useUser(); const router = useRouter(); const handleQuitRoom = () => { diff --git a/frontend/src/components/Room/RoomSideBar.tsx b/frontend/src/components/Room/RoomSideBar.tsx index 795f538..9660af3 100644 --- a/frontend/src/components/Room/RoomSideBar.tsx +++ b/frontend/src/components/Room/RoomSideBar.tsx @@ -8,25 +8,28 @@ import { BiMessageAdd } from "react-icons/bi"; import AddRoomPanel from "./AddRoomPanel"; import ThemeSwitcher from "../shared/themeswitcher"; import { useRouter } from "next/navigation"; +import { useUser } from "@/contexts/UserContext"; function RoomSideBar() { const [showAddRoomPanel, setShowAddRoomPanel] = useState(false); const { rooms, myRooms, currentRoomId, setCurrentRoomId } = useRoom(); const { socket, roomUsers } = useSocket(); const router = useRouter(); + const { username } = useUser(); const hideAddRoomPanel = () => setShowAddRoomPanel(false); const handleRoomClick = (newRoomId: string) => { - if (currentRoomId) { - socket?.emit("leave_room", currentRoomId); + if (currentRoomId !== newRoomId) { + socket?.emit("leave_room", { username: username, roomId: currentRoomId }); + } else { + console.log("No current room to leave"); } setCurrentRoomId(newRoomId); }; const logout = () => { - let username = localStorage.getItem("name"); - socket?.emit("logout", { username, currentRoomId }); + socket?.emit("logout", { username: username, roomId: currentRoomId }); router.push("/"); }; diff --git a/frontend/src/contexts/SocketContext.tsx b/frontend/src/contexts/SocketContext.tsx index a8d7d5e..bb9d530 100644 --- a/frontend/src/contexts/SocketContext.tsx +++ b/frontend/src/contexts/SocketContext.tsx @@ -39,7 +39,7 @@ export default function SocketProvider({ useEffect(() => { if (!username) { - router.replace("/"); + router.push("/"); return; } if (!socket) { @@ -55,7 +55,6 @@ export default function SocketProvider({ }); }); socket.on("users_response", (data) => setRoomUsers(data)); - socket?.emit("change_name", username); setSocket(socket); } }, []);