View : 0

12/04/2026 18:18pm

EP.43 Adding Pinned Messages Feature in WebSocket Chat

EP.43 Adding Pinned Messages Feature in WebSocket Chat

Why Have a Pinned Messages Feature?

Pinned Messages are a feature that allows users to save important messages for later reference, offering several benefits:

  • Preservation of Important Messages: Keeps crucial information from getting lost in high-volume conversations.
  • Announcement Channel: Serves as a way to highlight important announcements for groups or teams.
  • Easier Access to Important Information: Allows users to quickly find and access key messages.

Structure of the Pinned Messages System in WebSocket Chat

  1. WebSocket Server: Handles the reception and transmission of pinned message statuses.
  2. Database: Stores data about the messages that have been pinned.
  3. Frontend (Client-Side): Displays the list of pinned messages to users.

Adding the Pinned Messages Feature to the WebSocket Server

1. Upgrade the WebSocket Server to Support Pinned Messages

File: websocket_server.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "sync"

    "github.com/gorilla/websocket"
)

type PinnedMessage struct {
    MessageID int    `json:"messageID"`
    RoomID    int    `json:"roomID"`
    PinnedBy  string `json:"pinnedBy"`
}

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool { return true },
}

var (
    clients   = make(map[*websocket.Conn]bool)
    pinned    = make(map[int]PinnedMessage)
    broadcast = make(chan PinnedMessage)
    mu        sync.Mutex
)

func handleConnections(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()
    clients[conn] = true

    for {
        var pinnedMsg PinnedMessage
        err := conn.ReadJSON(&pinnedMsg)
        if err != nil {
            delete(clients, conn)
            break
        }
        broadcast <- pinnedMsg
    }
}

func handleMessages() {
    for {
        pinnedMsg := <-broadcast
        mu.Lock()
        pinned[pinnedMsg.MessageID] = pinnedMsg
        mu.Unlock()
        
        for client := range clients {
            err := client.WriteJSON(pinnedMsg)
            if err != nil {
                client.Close()
                delete(clients, client)
            }
        }
    }
}

func main() {
    http.HandleFunc("/ws", handleConnections)
    go handleMessages()
    fmt.Println("WebSocket Server Running on Port 8080")
    http.ListenAndServe(":8080", nil)
}

2. Adding Pinned Messages Functionality in the Frontend (Client-Side)

File: client.js

const socket = new WebSocket("ws://localhost:8080/ws");
const pinnedContainer = document.getElementById("pinned-messages");

socket.onmessage = (event) => {
    const data = JSON.parse(event.data);
    if (data.messageID) {
        const pinnedElement = document.createElement("p");
        pinnedElement.innerText = `Pinned Message: ${data.messageID} by ${data.pinnedBy}`;
        pinnedContainer.appendChild(pinnedElement);
    }
};

function pinMessage(messageID) {
    socket.send(JSON.stringify({ roomID: 1, messageID, pinnedBy: "JohnDoe" }));
}

Displaying Pinned Messages on the UI

File: index.html

<div id="pinned-messages"></div>
<button onclick="pinMessage(1)">Pin Message 1</button>

3. Testing the System

  1. Run the WebSocket Server
go run websocket_server.go
  1. Open Multiple Browser Tabs and Pin Messages
  2. Observe Results at WebSocket Server and UI

Challenge!

Try adding an Unpin Messages feature, allowing users to remove the pin from messages they no longer want to keep pinned.


Next EP

In EP.44, we will add a Feature to Display the Number of Online Users in the WebSocket Chat! 🚀