Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

amitrajitsarkar/Chat-Backend

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
35 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chat Backend

A WebSocket-driven chat backend using Socket.IO, Express, TypeScript, MongoDB, and Redis.
Designed to handle real-time direct messaging with persistent storage, rate limiting, content moderation, and cached message history.


📋 Table of Contents


Features

  • Real-time Messaging: Instant bidirectional communication using Socket.IO
  • Direct Messaging (DM): Private one-on-one chat rooms
  • Message Persistence: All messages stored in MongoDB for chat history
  • Online Presence: Track and broadcast online users
  • Rate Limiting: Prevent spam with automatic message throttling (3 messages/minute)
  • Content Moderation: Automatic filtering of inappropriate content
  • Message History API: Retrieve past messages via REST endpoint
  • Redis-backed Caching: Reduce repeated MongoDB reads for chat history queries
  • Typing Indicators: Real-time visual feedback when a user is composing a message
  • Read Receipts: Track and update the delivery and read status of messages
  • TypeScript: Full type safety across client, server, and shared types
  • CLI Client: Command-line interface for testing and demonstration

Architecture

System Overview

┌─────────────────┐
│  Client A       │──┐
│  (Socket.IO)    │  │
└─────────────────┘  │
                     ├──► ┌──────────────────┐      ┌─────────────┐
┌─────────────────┐  │    │  Backend Server  │──────│  MongoDB    │
│  Client B       │──┤    │  (Express +      │      │  (Messages) │
│  (Socket.IO)    │  │    │   Socket.IO)     │      └─────────────┘
└─────────────────┘  │    └──────────────────┘
                     │
┌─────────────────┐  │
│  Client C       │──┘
│  (Socket.IO)    │
└─────────────────┘

Message Flow

Client A
  └─ emit("dm-message", text)
       │
       ▼
    Backend
       ├─ Validate & Rate Limit
       ├─ Save to MongoDB
       └─ io.to(room).emit("dm-message", message)
            │
            ▼
         Client A + Client B
            └─ on("dm-message") → Display message

Tech Stack

Server

  • Node.js with TypeScript
  • Express - HTTP server and REST API
  • Socket.IO - WebSocket communication
  • Redis - query caching
  • MongoDB with Mongoose(ORM) - Message persistence
  • dotenv - Environment configuration
  • CORS - Cross-origin resource sharing

Client

  • Socket.IO Client - WebSocket client library
  • TypeScript - Type-safe client code
  • Node.js readline - CLI interface

Shared

  • TypeScript - Shared type definitions between client and server

Project Structure

.
├── README.md
├── client
│   ├── cli.ts
│   ├── package-lock.json
│   ├── package.json
│   ├── test.ts
│   ├── tsconfig.json
│   └── utils
├── packages
│   ├── package-lock.json
│   └── shared
│       ├── dist
│       │   ├── index.d.ts
│       │   └── types
│       │       ├── historyMessage.d.ts
│       │       └── socket.d.ts
│       ├── package.json
│       ├── src
│       │   ├── index.ts
│       │   └── types
│       │       ├── historyMessage.ts
│       │       └── socket.ts
│       └── tsconfig.json
└── server
    ├── package-lock.json
    ├── package.json
    ├── src
    │   ├── config
    │   │   └── dbConnection.ts
    │   ├── controller
    │   │   └── msgHistory.controller.ts
    │   ├── index.ts
    │   ├── model
    │   │   └── chat.ts
    │   ├── routes
    │   │   └── messageHistory.route.ts
    │   ├── service
    │   │   └── messageHistory.service.ts
    │   ├── sockets
    │   │   ├── deliveryMsg.ts
    │   │   ├── disconnect.ts
    │   │   ├── dmMessages.ts
    │   │   ├── index.ts
    │   │   ├── presence.state.ts
    │   │   ├── readMsg.ts
    │   │   ├── setUsername.ts
    │   │   ├── startDm.ts
    │   │   └── typeIndicator.ts
    │   ├── tsconfig.json
    │   └── utils
    │       ├── roomId.ts
    │       └── time.ts
    └── test
        ├── client-test-1.ts
        ├── client-test-2.ts
        ├── client-test-3.ts
        └── client-test-4.ts

Getting Started

Prerequisites

  • Node.js (v16 or higher)
  • MongoDB (local or MongoDB Atlas)
  • npm or yarn

Installation

  1. Clone the repository

    git clone https://github.com/Amitrajit007/Chat-Backend.git
    cd Chat-backend
  2. Install server dependencies

    cd server
    npm install
  3. Install client dependencies

    cd ../client
    npm install
  4. Install shared package dependencies

    cd ../packages/shared
    npm install
    npm run build  # Compile TypeScript types

Configuration

Create a .env file in the server/ directory:

PORT=5000
Atlas_URI=mongodb://localhost:27017/chat-app
# Or use MongoDB Atlas:
# Atlas_URI=mongodb+srv://username:password@cluster.mongodb.net/chat-app

Running the Application

  1. Start the server

    cd server
    npm run dev

    Server will run on http://localhost:5000

  2. Start client instances (in separate terminals)

    # Terminal 1 - User "alice" chatting with "bob"
    cd client
    npx ts-node cli.ts alice bob
    
    # Terminal 2 - User "bob" chatting with "alice"
    npx ts-node cli.ts bob alice

🔌 Socket Events

Client → Server

Event Payload Description
set-username string Set the username for the connected socket
start-dm string Start a DM session with target user
dm-message string Send a message in the current DM room

Server → Client

Event Payload Description
online-users string[] Broadcast list of currently online users
dm-message ChatMessage Receive a message in the DM room
dm-error string | ChatMessage Error notification (rate limit, moderation, etc.)

ChatMessage Type

type ChatMessage = {
  roomId: string; // Sorted usernames (e.g., "alice,bob")
    id: string; //   Message ID
    from: string; // Sender username
    text: string; // Message content
    to: string; // Recipient username
    time: string; // Formatted timestamp
}

REST API Endpoints

Get Message History

Retrieve past messages between two users.

Endpoint: GET /lastmessages

Query Parameters:

  • from (string, required) - First username
  • to (string, required) - Second username
  • limit (number, optional) - Number of messages to retrieve (default: 10 and max: 25)

Example Request:

curl "http://localhost:5000/lastmessages?from=alex&to=john&limit=3"

Example Response:

[
  {
    "_id": "45ec5a84-4d0f-4dc4-ae88-f8fe03fe7941",
    "roomId": "alex,john",
    "id": "45ec5a84-4d0f-4dc4-ae88-f8fe03fe7941",
    "from": "alex",
    "text": "i love peace",
    "to": "john",
    "time": "4/1/2026, 10:07:27 pm",
    "__v": 0
  },
  {
    "_id": "2cac0dd7-ff7e-4541-94bc-9d2a6659bb16",
    "roomId": "alex,john",
    "id": "2cac0dd7-ff7e-4541-94bc-9d2a6659bb16",
    "from": "john",
    "text": "Hello alex",
    "to": "alex",
    "time": "5/1/2026, 1:09:34 am",
    "__v": 0
  },
  {
    "_id": "70a45670-9f03-4e1c-b29f-651964ed53d6",
    "roomId": "alex,john",
    "id": "70a45670-9f03-4e1c-b29f-651964ed53d6",
    "from": "alex",
    "text": "hii",
    "to": "john",
    "time": "5/1/2026, 1:09:54 am",
    "__v": 0
  }
]

Health Check

Endpoint: GET /health

Response: OK

Server Status

Endpoint: GET /

Response:

{
  "msg": "Active @ 5000"
}

Database Schema

Message Collection

{
  roomId: String,   // Sorted usernames (e.g., "alice,bob")
  id: String,       // Message ID
  from: String,     // Sender username
  text: String,     // Message content
  to: String,       // Recipient username
  time: String,     // Formatted timestamp
}

Indexes:

  • { roomId: 1, createdAt: -1 } - Optimized for message history queries

Usage Examples

Example Console Output

Server Console:

Listening at 5000
MongoDB connected successfully
Online :  [ 'alex' ]
alex is connected in romm : dm:alexjohn
Online :  [ 'alex', 'john' ]
john is connected in romm : dm:alexjohn
Client disconnect with id:  LkSQBjXklUABPJPaAAAD
Online :  [ 'alex' ]
Client disconnect with id:  S1JIjaZJXQerzz4PAAAJ
No one is Online

John's Console:

Chatting with alex
Type messages and press Enter...

online: [ 'alex', 'You' ]
online: [ 'You' ]
online: [ 'You', 'alex' ]
alex : hii John    5/1/2026, 3:26:01 am
alex : How are you  ?    5/1/2026, 3:26:12 am
> Im fine, thanks 
You : Im fine, thanks    5/1/2026, 3:26:38 am
[READ] b9a30bdc-aadc-46b5-ab46-60cb500a8889
[DELIVERED] b9a30bdc-aadc-46b5-ab46-60cb500a8889
alex : Cool 👍    5/1/2026, 3:27:01 am

Caught Ctrl+C
Closing connection...
Disconnected

Alex's Console:

Chatting with john
Type messages and press Enter...

online: [ 'john', 'You' ]
> hii John
You : hii John    5/1/2026, 3:26:01 am
[DELIVERED] b2a328e8-0034-4635-a3ee-c79db5016afd
[READ] b2a328e8-0034-4635-a3ee-c79db5016afd
> How are you  ?
You : How are you  ?    5/1/2026, 3:26:12 am
[DELIVERED] 5d54095b-2864-4e5c-837f-533900a64912
[READ] 5d54095b-2864-4e5c-837f-533900a64912J
John : Im fine, thanks    5/1/2026, 3:26:38 am
> Cool 👍
You : Cool 👍    5/1/2026, 3:27:01 am
[DELIVERED] e587c3a8-2041-46e3-8676-b37df243faf8
[READ] e587c3a8-2041-46e3-8676-b37df243faf8
online: [ 'You' ]

Caught Ctrl+C
Closing connection...
Disconnected

Testing

Run Client 1 Test:

npm run client-test-1

Run Client 2 Test:

npm run client-test-2

Rate Limiting & Moderation

Rate Limiting

  • Limit: 5 messages per minute per user
  • Penalty: 5-second mute on exceeding limit
  • Error Message: "Too many messages. Muted for 5s."

Content Moderation

Messages containing the following keywords are automatically rejected:

  • "war"
  • "gun" These are just examples, you can add more keywords to the server\src\sockets\dmMessages.ts file.

Rejected Message Response:

Error: Message is not accepted

Implementation Details

Rate limiting is implemented per socket connection:

socket.data.rate = {
  count: 0,           // Messages sent in current window
  lastReset: Date.now(), // Window start time
  mutedUntil: 0       // Timestamp when mute expires
}

Notes

  • socket.id is a temporary identifier assigned per connection, used for debugging and logging
  • Room IDs are generated by sorting usernames alphabetically to ensure consistency (e.g., "alice,bob" regardless of who initiates)
  • Timestamps are formatted in local time: "DD/MM/YYYY, HH:MM:SS am/pm"
  • All messages are persisted to MongoDB for chat history

About

Real-time chat backend with private rooms and a CLI client.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.