How NodeBB uses Socket.IO to write a real-time message board

How NodeBB uses Socket.IO to write a real-time message board

·

7 min read

NodeBB is one amazing off-the-shelve community platform for your onboarding requirements. Be it a brand community or a board for flawless product support to your customers – this solution is built perfectly for everything you need for forum management.

such as:

  • Real-time interactions through private chats and message rooms;
  • Topics and replies for information-broadcasting;
  • Instant notifications to keep users engaged.

This article was originally posted at: https://www.quod.ai/post/how-nodebb-uses-socket-io-to-write-a-real-time-message-board

This GDPR-compliant next-gen community platform utilizes web sockets to enable interactive communication. As NodeBB has Node.js in its core, Socket.IO is a suitable pick for it. This library enables bi-directional communication in real-time and lets the browser & server communicate on the basis of events.

In this article, we will explain how NodeBB uses Socket.IO for its feature-rich real-time message board module in the community platform solution.

How NodeBB uses Socket.IO to write message boards?

Loading the real-time message board

SocketModules.chats.loadRoom = async function (socket, data) {
    if (!data || !data.roomId) {
        throw new Error('[[error:invalid-data]]');
    }


    return await Messaging.loadRoom(socket.uid, data);
};

View Modules.js in context at Quod AI

Line 1: The first step to using a message-board is, loading the chat rooms and rendering the list of previous chats. After initiation through Line 1, Socket.IO checks all the existing chats and the restrictions added for them. As per that, it loads the list of chats in the real-time message board. If there is no data or invalid data ID, an error message will be returned. Users will be able to click on each of the chats and open the chat window in NodeBB due to this.

Initiating a New Private Chat

SocketModules.chats.hasPrivateChat = async function (socket, uid) {
    if (socket.uid <= 0 || uid <= 0) {
        throw new Error('[[error:invalid-data]]');
    }
    return await Messaging.hasPrivateChat(socket.uid, uid);
};

View Modules.js in context at Quod AI

Line 1: When someone chooses a user to start a chat, NodeBB uses Socket.IO to check if the user already has a private chat for the current request. On clicking a link that could trigger a private chat, Socket.IO fetches and returns messaging data, e.g., the chat room icon/user display picture, old messages, user names (for chat rooms) with their names as disabled or enabled, option to send messages (or disabled chat), etc. If there exist previous messages, it loads the existing messages in the chat box. At this stage, the message board also accesses the restrictions and opens/disables the private chat option for the selected user, or the chat room of users.

Chat room creation (New) and management

SocketModules.chats.newRoom = async function (socket, data) {
    if (!data) {
        throw new Error('[[error:invalid-data]]');
    }


    if (rateLimitExceeded(socket)) {
        throw new Error('[[error:too-many-messages]]');
    }


    const canChat = await privileges.global.can('chat', socket.uid);
    if (!canChat) {
        throw new Error('[[error:no-privileges]]');
    }
    await Messaging.canMessageUser(socket.uid, data.touid);
    return await Messaging.newRoom(socket.uid, [data.touid]);
};

View Modules.js in context at Quod AI

Line 1: The function in line 1 is responsible for the new chat room’s creation. When a new chat room is created, the admin must add a few details such as chat room name, chat room icon, and member list. If the admin has not added any member during the room creation or added itself only, it will see an error message and the chat room will not be created. Regarding the users with restrictions related to chat room/admin, there will be error messages, telling the reason why the selected user(s) is not added to the chat room.

Line 10: All the users will be assigned access rights and privileges, as set by the chat room admin. The same are being validated at line 10. Allowed users will be able to send messages in the room and perform operations as per their user role in the chat room. For example, administrators will be able to add/remove users from the chat room.

This all is taken care of by Socket.IO in NodeBB.

SocketModules.chats.leave = async function (socket, roomid) {
    if (!socket.uid || !roomid) {
        throw new Error('[[error:invalid-data]]');
    }


    await Messaging.leaveRoom([socket.uid], roomid);
};

View Modules.js in context at Quod AI

Line 2: Hare, it is checked if the ‘leave chat room’ request is legit or not. At this point, the following aspects are validated through Socket.IO:

  • If the user has already left the chat room or if the user is not a part of the chat room;
  • If the user is the only administrator of the chat room;
  • If the invalid input is given to leave the chat room;

In these cases, the user will receive an error message and won’t be able to leave the chat room.

Deleting Messages

it('should error out if a message is deleted again', (done) => {
            socketModules.chats.delete({ uid: fooUid }, { messageId: mid, roomId: roomId }, (err) => {
                assert.strictEqual('[[error:chat-deleted-already]]', err.message);
                done();
            });
        });

View Messaging.js in context at Quod AI

Line 1: From this line, the code for message deletion starts in the messaging.js file. During message deletion for all, Socket.IO checks if the user is trying to delete the already deleted messages.

  • If so, an error message will be displayed.
  • If not, the visibility for selected messages, messages, or the whole chat will be checked. The Socket.IO module will make the messages hidden for everyone. So, no one will be able to view the messages.

While deleting the message(s) for self, the above will happen for the user making this request. In the NodeBB community, users and admins can restore the messages too.

Blocking a User/Leaving a chat room

When a user blocks another person or leaves a chat room, the chat window in the real-time message board will be disabled from sending/receiving messages through Socket.IO in the NodeBB community. Line 732-762 has the code for this in the test/messaging.js file.

Socket Event Listeners

messages.addSocketListeners = function () {
        socket.removeListener('event:chats.edit', onChatMessageEdited);
        socket.on('event:chats.edit', onChatMessageEdited);


        socket.removeListener('event:chats.delete', onChatMessageDeleted);
        socket.on('event:chats.delete', onChatMessageDeleted);


        socket.removeListener('event:chats.restore', onChatMessageRestored);
        socket.on('event:chats.restore', onChatMessageRestored);
    };

View Messaging.js in context at Quod AI

Line 1: From this line, starts the function that updates the deletion, restoration and editing of messages in the real-time. Socket event listeners are used for this purpose.

Receiving Messages and Read/Unread Message Marker and Counter

socket.onAny((event, ...args) => {
        const payload = { data: [event].concat(args) };
        onMessage(socket, payload);
    });

View Index.js in context at Quod AI

Line 3: When the message arrives, it triggers the onMessage event in the real-time. With this the new message is added for the recipient to read and counters/message-status-markers are updated. Socket.IO uses a way to distinguish read and unread messages. When a message is read by recipient(s) on the message board, it is marked ‘read’. For unread messages, the unread-message counter is shown for each chat.

Handling Restrictions and Invalid Inputs

For each user, there is a list of restrictions they have added. This may include the blocked users and parameters in settings.

When someone tries to initiate an action related to real-time messaging through NodeBB, Socket.IO is used for validating the inputs and confirming that there is no conflict in proceeding with the instruction.

For example: If a user is creating a Chat room and is trying to add someone who has blocked that user, there will be an error message. The selected person won’t be added to the chat room in this case.

Also, if a user is trying to add himself or herself to the chat room, the Socket.IO module returns an error.

Initiating or taking forward a private chat also requires that:

  • Both the users in conversation haven’t blocked each other;
  • Both users have active accounts with no messaging-related restrictions;

When do you need the Build-in Real-time Chat Functionality for your Community?

NodeBB message boards can be utilized for:

  • Discussions among teams regarding different projects;
  • To accept and address customers’ queries;
  • To let the community member discuss open-source projects;
  • To enable a seamless communication mode for the whole organization.

Is Socket.IO capable enough for your real-time message board?

Yes, Socket.IO is a reliable and secure choice for speedy communication. So, it is generally the best pick for real-time messaging and notifications. It works for all standard browsers, devices, and platforms. Overall, Socket.IO makes the best choice for the real-time message board in your NodeBB community.

The Final Words

NodeBB uses Socket.IO for event-based communications in the community. Be it notifications or message boards, the platform utilizes this technology to ensure instant and reliable communication. If you are thinking of using a ready-made message board with multiple other capabilities for your community, NodeBB can be considered. Check out source code on Quod AI repository: https://beta.quod.ai/github/NodeBB/NodeBB

Quod AI is code search and navigation on steroids. We turn code into documentation that developers actually use. Do follow us on twitter @quod_ai for updates on our product and DEVs community content. Check our app at: beta.quod.ai