From 838a325c7e55b44d741134cb00863badd860990d Mon Sep 17 00:00:00 2001 From: shuyi320 Date: Thu, 21 Nov 2024 16:02:33 -0500 Subject: [PATCH] chatroom --- backend/database/models/chatRoomModel.js | 27 ++++++++ backend/database/models/messageModel.js | 20 +++--- backend/database/models/userInfo.js | 35 +++++++--- backend/index.js | 52 +++++++-------- backend/routes/api.chat.js | 14 +--- backend/routes/api.chatRoom.js | 31 +++++++++ backend/routes/api.users.js | 83 ++++++++++++------------ 7 files changed, 166 insertions(+), 96 deletions(-) create mode 100644 backend/database/models/chatRoomModel.js create mode 100644 backend/routes/api.chatRoom.js diff --git a/backend/database/models/chatRoomModel.js b/backend/database/models/chatRoomModel.js new file mode 100644 index 0000000..229d70a --- /dev/null +++ b/backend/database/models/chatRoomModel.js @@ -0,0 +1,27 @@ +import { Schema, model } from "mongoose"; + +const chatRoomModel = new Schema({ + roomId: String, + users: [String], + createdAt: { type: Date, default: Date.now() } +}); + +const chatRoom = model("chat", chatRoomModel); + + +export async function createChatRoom(data) { + const result = await chatRoom.create(data) + return result; +} + + +export async function getAllChatRooms(userId) { + const data = await chatRoom.findAll({ + users: { $eq: userId } + }) + if (!data) return null + return data; +} + + + diff --git a/backend/database/models/messageModel.js b/backend/database/models/messageModel.js index 31edde8..49d4e81 100644 --- a/backend/database/models/messageModel.js +++ b/backend/database/models/messageModel.js @@ -1,30 +1,28 @@ import { Schema, model } from "mongoose"; const messageModel = new Schema({ - chatId: String, + roomId: String, senderId: String, message: String, createdAt: { type: Date, default: Date.now() } }); -const chat = model("chat", messageModel); +const messages = model("chat", messageModel); -export async function create(data) { - const result = await chat.create(data) - return result; +export async function sendMessage(data) { + const message = await messages.create(data) + return message; } -export async function getChat(chatID) { - const data = await chat.findAll({ - chatID: { $eq: chatID } +export async function getMessages(roomId) { + const data = await messages.findAll({ + roomId: { $eq: roomId } }).sort({"createdAt": 1}) if (!data) return null return data; } -export async function update(id, data) { - return await chat.updateOne({ chatID: id }, data); -} + diff --git a/backend/database/models/userInfo.js b/backend/database/models/userInfo.js index 69e9f3e..47fc459 100644 --- a/backend/database/models/userInfo.js +++ b/backend/database/models/userInfo.js @@ -1,9 +1,10 @@ import { Schema, model } from "mongoose"; const userModel = new Schema({ - userID: String, - petPreference: String, - recommendedPets: [String] + userId: String, + petPreference: Object, + favoritePets: [String], + friends: { type: [String], default: [] } }); const users = model("users", userModel); @@ -15,12 +16,30 @@ export async function create(data) { export async function findAll() { return await users.find() } -export async function getUserByID(userID) { - const data = await users.findOne({ - userID, +export async function getUserByName(userName) { + const user = await users.findOne({ + userName, }) - if (!data) return null - return data; + if (!user) return null + return user; +} +export async function getUserById(userId) { + const user = await users.findOne({ + userId, + }) + if (!user) return null + return user; +} +export function getFriends(userId) { + const friends = users.findOne({ + userId: userId, + }).projection({ friends}) + return friends; +} + +export function addFriend(user, friend) { + user.friends.push(friend.userId) + } // export async function addPetToUser(userID, petID) { diff --git a/backend/index.js b/backend/index.js index 56786fe..5485cc9 100644 --- a/backend/index.js +++ b/backend/index.js @@ -14,7 +14,7 @@ import { authMiddleware } from './middleware/auth.middleware.js'; import { rateLimit } from 'express-rate-limit' import { createServer } from 'http'; import { Server } from 'socket.io'; -import { create } from './database/models/messageModel.js' +import { sendMessage } from './database/models/messageModel.js' const port = process.env.PORT || 3001; @@ -53,11 +53,11 @@ const io = new Server(server, { // Handle socket connection io.on('connection', (socket) => { - const users = {}; //Map userId to socket.id - socket.on('connected', async (userId) => { - users[userId] = socket.id; - console.log('User connected:', userId); - }) + // const users = {}; //Map userId to socket.id + // socket.on('connected', async (userId) => { + // users[userId] = socket.id; + // console.log('User connected:', userId); + // }) // Listen for incoming messages from client-side socket.on('room message', async (data, callback) => { @@ -65,7 +65,7 @@ io.on('connection', (socket) => { console.log('Received message data:', data); // Save message to the database - const newMessage = await create({ + const newMessage = await sendMessage({ chatId: data.chatId, senderId: data.senderId, message: data.message, @@ -84,25 +84,25 @@ io.on('connection', (socket) => { } }); - socket.on("private message", async (data, to) => { - recipientSocketId = users[to] - // Save message to the database - const newMessage = await create({ - chatId: data.chatId, - senderId: data.senderId, - message: data.message, - }); - //send message to specific user - if (recipientSocketId) { - socket.to(recipientSocketId).to(socket.id).emit("private message", { - newMessage, - to, - }); - console.log(`Message sent to ${to}: ${content}`) - }else { - console.log(`User ${recipientUserId} is not connected`); - } - }); +// socket.on("private message", async (data, to) => { +// recipientSocketId = users[to] +// // Save message to the database +// const newMessage = await create({ +// chatId: data.chatId, +// senderId: data.senderId, +// message: data.message, +// }); +// //send message to specific user +// if (recipientSocketId) { +// socket.to(recipientSocketId).to(socket.id).emit("private message", { +// newMessage, +// to, +// }); +// console.log(`Message sent to ${to}: ${content}`) +// }else { +// console.log(`User ${recipientUserId} is not connected`); +// } +// }); // Handle disconnection diff --git a/backend/routes/api.chat.js b/backend/routes/api.chat.js index 5374127..01cb7f3 100644 --- a/backend/routes/api.chat.js +++ b/backend/routes/api.chat.js @@ -1,21 +1,13 @@ import { Router } from "express"; -import { getChat, create, update } from "../database/models/messageModel.js"; +import { getMessages, sendMessage, update } from "../database/models/messageModel.js"; const router = Router(); -router.post("/", async (req, res) => { - try { - await create(req.body) - res.json("success!") - } catch (error) { - res.status(500).send({ message: error.message }) - } -}); router.get('/:id', async (req, res) => { try { const id = req.params.id - const chat = await getChat(id) + const chat = await getMessages(id) res.json(chat) } catch (error) { res.status(500).send({ message: error.message }) @@ -25,7 +17,7 @@ router.get('/:id', async (req, res) => { router.put('/:id', async (req, res) => { try { const id = req.params.id - const chat = await getChat(id) + const chat = await getMessages(id) chat.messages.push(req.body) const result = await update(id, chat) res.json(result) diff --git a/backend/routes/api.chatRoom.js b/backend/routes/api.chatRoom.js new file mode 100644 index 0000000..3b5011c --- /dev/null +++ b/backend/routes/api.chatRoom.js @@ -0,0 +1,31 @@ +import { Router } from "express"; +import { createChatRoom, getAllChatRooms } from "../database/models/chatRoomModel.js"; + +const router = Router(); + +router.post('/', async (req, res) => { + try { + const result = await createChatRoom(req.body) + console.log('Room Created: ', result) + res.status(200).json(result) + } catch (error) { + res.status(400).json("Error Creating ChatRoom: ", error) + } +}) + +router.get('/:userId', async (req, res) => { + try { + const { userId } = req.params; + const chatRooms = await getAllChatRooms(userId) + if (!chatRooms) { + return res.status(404).json({ error: "Chat Room Not Found" }) + } + return res.status(200).json(chatRooms); + + } catch (error) { + console.log(error) + return res.status(400).json({ error: error.message }) + } +}) + +export default router; \ No newline at end of file diff --git a/backend/routes/api.users.js b/backend/routes/api.users.js index 21277cb..4db7770 100644 --- a/backend/routes/api.users.js +++ b/backend/routes/api.users.js @@ -1,54 +1,57 @@ import { Router } from "express"; import { createClerkClient } from '@clerk/backend' -import { getUserByID, create } from "../database/models/userInfo.js" +import { getUserByID, getUserByName, getFriends, addFriend, create } from "../database/models/userInfo.js" const router = Router(); -// return a users list -router.get('/', async (req, res) => { - const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }) - try { - // Fetch all users from Clerk - const response = await clerkClient.users.getUserList() - const users = response.data - // Optionally format the user data as needed - console.log('users:', users); - const userList = users.map(user => ({ - id: user.id, - email: user.emailAddresses[0]?.emailAddress, - username: user.username, - createdAt: user.createdAt, - firstName: user.firstName, - lastName: user.lastName, - roles: user, - })); - - res.json(userList); - } catch (error) { - console.error('Error fetching user list:', error); - res.status(500).json({ message: 'Failed to fetch user list' }); - } -}); - - -//check if the user exits in the db -router.get('/:userID', async (req, res) => { - const userID = req.params.userID - const response = await getUserByID(userID) - if (!response) { - res.json(false) - } else { - res.json(true) - } +router.get('/:userName', async (req, res) => { + const { userName } = req.params + const user = await getUserByName(userName) + if (!user) + return res.status(404).json({ error: 'User not found' }); + + return res.status(200).json({ user }); }) -router.post('/:userID', async(req,res)=>{ +router.post('/', async (req, res) => { + const data = req.body; try { - await create(req.body) - res.json("success!") + await create(data) + res.json("User saved to database!") } catch (error) { res.status(500).send({ message: error.message }) } }) +router.post('/addFriend', async (req, res) => { + try { + const { userId, friendId } = req.body; + console.log(`Request to add friend: ${userId} -> ${friendId}`); + + if (userId === friendId) { + return res.status(422).json({ error: "You can't friend yourself." }); + } + + const user = await getUserByID(userId); // This should work if User is defined correctly + const friend = await getUserByID(friendId); + + if (!user || !friend) { + return res.status(404).json({ error: "User or friend not found." }); + } + + const existingFriendship = getFriends(userId); + + if (existingFriendship.contains(friendId)) { + return res.status(422).json({ error: "Friendship already exists." }); + } + + addFriend(user, friend); + + return res.status(200).json({ message: "Friend added successfully.", friendId }); + } catch (error) { + console.error(error); + res.status(400).json({ error: error.message }); + } +}) + export default router; \ No newline at end of file