├── routes ├── messagesroute.js └── userroutes.js ├── model ├── mesasgemodel.js ├── reportmodel.js └── usermodel.js ├── package.json ├── controllers ├── reportcontroller.js ├── messagescontroller.js └── usercontroller.js ├── index.js └── README.md /routes/messagesroute.js: -------------------------------------------------------------------------------- 1 | const {addmessage,getallmessage,deletemessage} =require("../controllers/messagescontroller") 2 | 3 | 4 | const router=require("express").Router() 5 | 6 | router.post("/addmsg",addmessage) 7 | router.post("/getmsg",getallmessage) 8 | router.delete("/:currentchat",deletemessage) 9 | 10 | 11 | module.exports=router -------------------------------------------------------------------------------- /model/mesasgemodel.js: -------------------------------------------------------------------------------- 1 | const mongoose=require("mongoose") 2 | 3 | const messageschema=new mongoose.Schema({ 4 | message:{ 5 | text:{ 6 | type:String, 7 | required:true, 8 | }, 9 | }, 10 | users:Array, 11 | sender:{ 12 | type:mongoose.Schema.Types.ObjectId, 13 | ref:"user", 14 | required:true, 15 | } 16 | }, 17 | { 18 | timestamps:true 19 | } 20 | ) 21 | 22 | module.exports=mongoose.model("messages",messageschema) -------------------------------------------------------------------------------- /routes/userroutes.js: -------------------------------------------------------------------------------- 1 | const {signup, login, getallusers, deleteuser, liveconnections} =require("../controllers/usercontroller") 2 | const {report} =require("../controllers/reportcontroller") 3 | 4 | 5 | const router=require("express").Router() 6 | 7 | router.post("/signup",signup) 8 | router.post("/login",login) 9 | router.post("/report",report) 10 | router.get('/allusers/:id',getallusers) 11 | router.get('/connections',liveconnections) 12 | router.delete('/:username', deleteuser) 13 | module.exports=router -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon index.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^5.1.0", 14 | "body-parser": "^1.20.1", 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.0.3", 17 | "express": "^4.18.2", 18 | "mongoose": "^6.8.4", 19 | "nodemon": "^2.0.20", 20 | "socket.io": "^4.6.0", 21 | "socket.io-client": "^4.6.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /model/reportmodel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const reportschema = new mongoose.Schema({ 4 | reportsenderusername: { 5 | type: String, 6 | required: true 7 | }, 8 | reportrecieverusername: { 9 | type: String, 10 | required: true 11 | }, 12 | reportsenderid: { 13 | type: String, 14 | required: true 15 | }, 16 | reportreceiverid: { 17 | type: String, 18 | required: true 19 | }, 20 | reportreason: { 21 | type: String, 22 | required: true 23 | } 24 | }, 25 | { 26 | timestamps:true 27 | } 28 | ); 29 | 30 | module.exports = mongoose.model('Reports', reportschema); 31 | -------------------------------------------------------------------------------- /controllers/reportcontroller.js: -------------------------------------------------------------------------------- 1 | const reportmodel = require("../model/reportmodel") 2 | 3 | 4 | 5 | module.exports.report=async (req,res,next)=>{ 6 | try{ 7 | const {reportsenderusername, 8 | reportrecieverusername, 9 | reportsenderid, 10 | reportreceiverid, 11 | reportreason,}=req.body 12 | const data=await reportmodel.create({ 13 | reportsenderusername, 14 | reportrecieverusername, 15 | reportsenderid, 16 | reportreceiverid, 17 | reportreason, 18 | }) 19 | if(data ) return res.json({msg:"messae added"}) 20 | return res.json({ msg:"failed to add msg"}) 21 | } 22 | catch(ex){ 23 | next(ex) 24 | } 25 | } -------------------------------------------------------------------------------- /model/usermodel.js: -------------------------------------------------------------------------------- 1 | const mongoose=require("mongoose") 2 | 3 | const userschema=new mongoose.Schema({ 4 | username:{ 5 | type:String, 6 | required:true, 7 | min:5, 8 | max:20, 9 | unique:true 10 | }, 11 | email:{ 12 | type:String, 13 | required:true, 14 | unique:true, 15 | max:34, 16 | },password:{ 17 | type:String, 18 | required:true, 19 | unique:true, 20 | max:20, 21 | },photo:{ 22 | type:String, 23 | }, 24 | blocked: { 25 | type: Boolean, 26 | default: false 27 | } 28 | } 29 | , 30 | { 31 | timestamps:true 32 | } 33 | ) 34 | 35 | module.exports=mongoose.model("users",userschema) -------------------------------------------------------------------------------- /controllers/messagescontroller.js: -------------------------------------------------------------------------------- 1 | const messagemodel = require("../model/mesasgemodel") 2 | 3 | 4 | module.exports.addmessage=async (req,res,next)=>{ 5 | try{ 6 | const {from,to,message}=req.body 7 | const data=await messagemodel.create({ 8 | message:{text:message}, 9 | users:[from,to], 10 | sender:from, 11 | }) 12 | if(data ) return res.json({msg:"messae added"}) 13 | return res.json({ msg:"failed to add msg"}) 14 | }catch(ex){ 15 | next(ex) 16 | } 17 | 18 | } 19 | 20 | 21 | 22 | module.exports.getallmessage=async (req,res,next)=>{ 23 | try{ 24 | const{from,to}=req.body 25 | const messages=await messagemodel 26 | .find({ 27 | users:{ 28 | $all:[from,to] 29 | } 30 | }) 31 | .sort({updatedAt:1}) 32 | const projectedmessages=messages.map((msg)=>{ 33 | return{ 34 | fromself:msg.sender.toString()===from, 35 | message:msg.message.text, 36 | msgtime:msg.createdAt.toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric' }), 37 | } 38 | }) 39 | res.json(projectedmessages) 40 | }catch(ex){ 41 | next(ex) 42 | } 43 | } 44 | 45 | module.exports.deletemessage=async (req,next)=>{ 46 | try{ 47 | const receiver = req.params.currentchat; 48 | console.log(receiver) 49 | await messagemodel.deleteMany({users: receiver}); 50 | }catch(ex){ 51 | next(ex) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const express=require("express") 4 | const cors=require("cors") 5 | const mongoose=require("mongoose") 6 | const bodyParser = require('body-parser'); 7 | const Userroutes=require("./routes/userroutes") 8 | const socket=require("socket.io") 9 | const messageroute=require("./routes/messagesroute") 10 | 11 | const app=express() 12 | require("dotenv").config() 13 | 14 | app.use(bodyParser.json({ limit: "200mb" })); 15 | app.use(bodyParser.urlencoded({ limit: "200mb", extended: true, parameterLimit: 1000000 })); 16 | app.use(cors()) 17 | app.use(express.json()); 18 | 19 | 20 | app.use("/api/auth",Userroutes) 21 | app.use("/api/messages",messageroute) 22 | 23 | 24 | 25 | const PORT=process.env.PORT || 5000 26 | 27 | /*const dburl='mongodb://0.0.0.0:27017/chat'*/ 28 | /*const dburl='mongodb+srv://PRADEEP123:'+encodeURIComponent('password')+'@cluster0.x5jbf4w.mongodb.net/chat?retryWrites=true&w=majority'*/ 29 | const dburl=process.env.db_url 30 | 31 | 32 | mongoose.connect(dburl, { 33 | useNewUrlParser: true, 34 | useUnifiedTopology: true 35 | }); 36 | 37 | mongoose.connection.on('connected', () => { 38 | console.log('Successfully connected to MongoDB'); 39 | 40 | mongoose.connection.db.command({ serverStatus: 1 }, (err, result) => { 41 | if (err) throw err; 42 | console.log(`Number of live connections: ${result.connections.current}`); 43 | }); 44 | }); 45 | 46 | 47 | 48 | 49 | 50 | const server=app.listen(process.env.PORT,()=>{ 51 | console.log(`server started at port ${PORT}`) 52 | }) 53 | 54 | const io =socket(server,{ 55 | cors:{ 56 | origin:"https://piehost.com", 57 | Credentials:true, 58 | } 59 | }) 60 | 61 | global.onlineUsers=new Map() 62 | 63 | io.on("connection",(socket)=>{ 64 | global.chatSocket=socket 65 | socket.on("add-user",(userId)=>{ 66 | onlineUsers.set(userId,socket.id) 67 | }) 68 | socket.on("send-msg",(data)=>{ 69 | const sendUserSocket=onlineUsers.get(data.to) 70 | if(sendUserSocket){ 71 | socket.to(sendUserSocket).emit("msg-recieve",data.message) 72 | } 73 | }) 74 | }) 75 | -------------------------------------------------------------------------------- /controllers/usercontroller.js: -------------------------------------------------------------------------------- 1 | const User=require("../model/usermodel") 2 | const bcrypt=require("bcrypt") 3 | const mongoose = require('mongoose'); 4 | 5 | let db; 6 | 7 | mongoose.connection.on('connected', () => { 8 | db = mongoose.connection.db; 9 | }); 10 | 11 | 12 | 13 | module.exports.signup=async (req,res,next)=>{ 14 | try{ 15 | const {username,email,password,photo}=req.body 16 | const usernamecheck=await User.findOne({username}) 17 | if(usernamecheck) 18 | return res.json({msg:"username already used",status:false}) 19 | const emailcheck=await User.findOne({email}) 20 | if(emailcheck) 21 | return res.json({msg:"Entered Email is already registered",status:false}) 22 | const hashedpassword=await bcrypt.hash(password,10) 23 | const user=await User.create({ 24 | email, 25 | username, 26 | password:hashedpassword, 27 | photo, 28 | }) 29 | delete user.password 30 | return res.json({status:true,user}) 31 | } 32 | catch(ex){ 33 | next(ex) 34 | } 35 | } 36 | 37 | module.exports.login=async (req,res,next)=>{ 38 | try{ 39 | const {username,email,password}=req.body 40 | 41 | const user=await User.findOne({$or: [{ email }, { username }]}) 42 | if(!user) 43 | return res.json({msg:"This username is not registered! note: username and email are case sensitive",status:false}) 44 | 45 | const mail=await User.findOne({email}) 46 | if(!mail) 47 | return res.json({msg:"this email is not registered note: username and email are case sensitive",status:false}) 48 | 49 | const ispassswordvalid=await bcrypt.compare(password,user.password) 50 | const isPasswordValidWithEmail = await bcrypt.compare(password, user.password); 51 | const isPasswordValidWithUsername = await bcrypt.compare(password, mail.password); 52 | 53 | if(!isPasswordValidWithEmail && isPasswordValidWithUsername){ 54 | return res.json({msg:"Username is not registered with this email",status:false}) 55 | } 56 | if(isPasswordValidWithEmail && !isPasswordValidWithUsername) 57 | return res.json({msg:"Email is not registered with this username",status:false}) 58 | if(!isPasswordValidWithEmail && !isPasswordValidWithUsername) 59 | return res.json({msg:"Wrong Password",status:false}) 60 | delete user.password 61 | 62 | return res.json({status:true,user}) 63 | } 64 | catch(ex){ 65 | next(ex) 66 | } 67 | } 68 | 69 | 70 | module.exports.getallusers=async (req,res,next)=>{ 71 | try{ 72 | const users=await User.find({_id:{$ne:req.params.id}}).select([ 73 | "email", 74 | "username", 75 | "id", 76 | "photo", 77 | "createdAt" 78 | ]) 79 | return res.json(users) 80 | }catch(ex){ 81 | next(ex) 82 | } 83 | } 84 | 85 | module.exports.deleteuser=async (req,res,next)=>{ 86 | try{ 87 | const users=await User.deleteOne({ username: req.params.username }) 88 | return res.json(users) 89 | }catch(ex){ 90 | next(ex) 91 | } 92 | } 93 | 94 | 95 | module.exports.liveconnections=async (req,res,next)=>{ 96 | try{ 97 | if (!db) { 98 | return res.status(500).json({ error: 'Database connection not ready' }); 99 | } 100 | 101 | db.command({ serverStatus: 1 }, (err, result) => { 102 | if (err) throw err; 103 | res.json({ connectionCount: result.connections.current }); 104 | }); 105 | }catch(ex){ 106 | next(ex) 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Chat Nexus Logo 3 | 4 |

5 | 6 | # Chat Nexus 7 | 8 | Chat Nexus is a web-based chat application that allows users to communicate with each other in real-time. 9 |
10 |
11 | 12 | ## 🚀 Features 13 | 14 | -💬 Real-time messaging
15 | - 🔐 User Authentication (Register / Login)
16 | - 💬 Real-time messaging using Socket.io
17 | - 🗑️ Delete account
18 | - 🗑️ Delete chats
19 | - 🚩 Report users
20 | - 📥 Download profile pictures
21 | - 📋 Personalised profile tabs
22 | - 🔍 Search usernames
23 | - 🎤 Voice recognition for chat messages
24 | - 😀 Send emojis
25 | - 📜Message history
26 | 27 |
28 |
29 | 30 | ## 🛠️ Technologies 31 | 32 | Chat Nexus was built using the following technologies: 33 | 34 | - **M**ongoDB: A document-based NoSQL database used to store chat history and user data. 35 | - **E**xpress.js: A web application framework for Node.js used to build the server-side API. 36 | - **R**eact.js: A JavaScript library used to build the user interface. 37 | - **N**ode.js: A JavaScript runtime environment used to build the server-side application. 38 | - **socket.io**: A JavaScript library used for real-time, bidirectional communication between the client and server. 39 | 40 |
41 |
42 | 43 | 44 | ## 🔗 Resource Credits 45 | 46 | The following resources were used in the creation of Chat Nexus: 47 | 48 | - [icons8 bubblegum theme](https://icons8.com/illustrations/style--bubble-gum)
49 | SVGs and Icons used throughout the app the logo svg all were taken from icons8 bubblegum theme. 50 | 51 | ![Screenshot 2023-03-01 232456](https://user-images.githubusercontent.com/91087103/222222424-ef28ebbe-57ab-41d4-bbdf-3a78d8015a4c.png) 52 | 53 | - [Dribble login page](https://dribbble.com/shots/5035570-Login-page)
54 | Inspiration for the login and signup page's design and user interface. 55 | 56 | ![Screenshot 2023-01-25 202739](https://user-images.githubusercontent.com/91087103/222221618-39397bba-040e-45a0-b474-56d6eadc322b.png) 57 | 58 | - [annyang: ^2.6.1](https://www.npmjs.com/package/annyang)
59 | This package is used for voice recognition in the Chat Nexus website. The version used in this project is ^2.6.1. 60 | 61 | ![image](https://user-images.githubusercontent.com/91087103/222226483-d31775ad-9fa5-474c-bc3c-1cdc5152b1a8.png) 62 | 63 | - [emoji-picker-react](https://www.npmjs.com/package/emoji-picker-react)
64 | This package is used for the emoji picker feature in the Chat Nexus website. The version used in this project is ^3.6.5. 65 | 66 | ![image](https://user-images.githubusercontent.com/91087103/222227277-5c26ab95-e172-4961-9dfb-9235ed07fb42.png) 67 | 68 | 69 | 70 | 71 | 72 | 73 |
74 |
75 | 76 | ## 🛠️ Installation, Usage, and Configuration 77 | 78 | To install, use, and configure Chat Nexus, follow these steps: 79 | 80 | 1. Clone the repository: `git clone https://github.com/your-username/chat-nexus.git` 81 | 2. Install dependencies: `npm install` 82 | 3. Start the server: `npm start` 83 | 4. Open the app in your web browser: `http://localhost:3000` 84 | 5. Sign up for a new account or log in with an existing account. 85 | 6. Join a chat room or create a new one. 86 | 7. Start sending and receiving messages in real-time. 87 | 88 | Chat Nexus can be configured using environment variables. The following variables can be set: 89 | 90 | - `PORT`: The port number to use for the server. Default is `3000`. 91 | - `MONGODB_URI`: The URI for the MongoDB database. Default is `mongodb://localhost/chat-nexus`. 92 |
93 |
94 | 95 | ## 💻 Usage through Website Link 96 | 97 | Chat Nexus can also be accessed through the following website link: https://chatnexus.tech/ 98 | 99 | . 100 | 101 | 102 | 103 | ## ❓ FAQs 104 | 105 | Q: how many accounts chat nexus can handle?
106 | A: at present , as chat nexus is running on free database pack it can only handle about 7-10 accounts and 300 connections. 107 | but with paid database pack it will have no limits and will send and receive messages even faster 108 | 109 | 110 | Q: Does reporting users actually work?
111 | A: yes, there is a whole seperate report model which sends reporter details,reported details and reason to database. 112 | 113 |
114 | 115 | Q: Does delete account permanently delete account?
116 | A: yes, delete account permanently deletes the user from collection of users in the database with the chats. 117 | 118 |
119 | 120 | Q: why i am not able to login even after registering?
121 | A: username,email and password are case sensitive so it is possible you are registered but entering the details incorrectly 122 | 123 |
124 | 125 | Q: are all chats saved?
126 | A: Yes, Chat Nexus uses secure user authentication and stores chat history in a secure database. 127 | 128 |
129 | Q: how much did it take to complete chat nexus?
130 | A: it took around 2 months to complete chat nexus 131 | 132 | 133 |
134 | 135 | ## 📞 feedback 136 | 137 | For feedback or review for Chat Nexus, review at [feedback form](https://form.typeform.com/to/yrFOxBqF) 138 | 139 | --------------------------------------------------------------------------------