Chat Online Status in NiceDay

Muhammad Yusuf
NiceDay Development
5 min readApr 1, 2019

I’d like to walk you through a feature development in our app NiceDay and I thought a nice example of a complex feature to share would be enabling chat online status in our product.

We want to leverage online status in our product to improve the user experience, namely when a client wants to interact with one of the professionals. The feature is easy to describe: it boils down to showing the online availability of a professional to the clients and vice versa, but implementing it with an external chat service (Ejabberd) and a custom Django backend for authentication can be quite tricky.

To enable this feature, we decided to leverage Roster items in the Ejabberd chat server which we can create directly from our Django backend when a user connection is created.

Ejabberd API Configuration

To enable this feature, we decided to leverage Ejabberd’s internal REST API. This allows us to control behaviour in the Ejabberd chat server using REST-based methods. To do this, we first created an internal admin user with permission restricted to only exactly the API calls we needed. We follow a strict privacy first development lifecycle, which means every API/admin gets access only on a need-to-know basis.

To enable Ejabberd APIs, in the listen section of the Ejabberd configuration, we set up mod_http_api to be accessible through /api endpoint, as you can see in the snippet below:

listen:
-
port: 9999
ip: "::"
module: ejabberd_http
request_handlers:
"/api": mod_http_api

Implementation in our Django Backend

We implemented this as an external service within our Django backend which belongs to the Django package system. We wrapped this external service with helper functions so that the other apps could make use of this Ejabberd Django app when required for other features as well.

These are the standard payloads we used to interact with add_rosteritem and delete_rosteritem API calls that we required to create/remove rosters.

POST /api/add_rosteritem
{
"localuser": "user1",
"localserver": "myserver.com",
"user": "user2",
"server": "myserver.com",
"nick": "User 2",
"group": "Friends",
"subs": "both"
}
HTTP/1.1 200 OK
""
POST /api/delete_rosteritem
{
"localuser": "user1",
"localserver": "myserver.com",
"user": "user2",
"server": "myserver.com"
}
HTTP/1.1 200 OK
""

When a client and a professional establish a connection with each other, a roster item is created which can be used by the app (using XMPP) to poll the presence of a user in the roster and make online status visible in the app and on the web portal. Ejabberd itself has a capability for handling duplication whenever someone performs multiple add_roster_item operation.

Roster Item is a basic functionality used by Presence API from Ejabberd for showing online status of a user of XMPP.

SDK Specification

Since we handle logic related to adding/removing Roster in the backend, responsibility of our SDK is only to provide the app and the web portal with the following capabilities:

  • Sending availability status of the user.
  • Receiving availability statuses of the user’s contacts.

We utilise the following availability status types supported by Ejabberd:

Send Initial Presence

Send the following XML to the server to tell that the user is available:

<presence/>

By sending this, the user will be seen as online (or available) by their contacts.

Without sending this, the user won’t get an update on the availability status of their contact.

Send Availability Status

We utilise this when a user wants to be seen as away, busy, or appear offline. This will send the following XML to the server to tell the user availability status.

<presence to='juliet@example.com'>
<show>away</show>
<status>Having a spot of tea</status>
</presence>

Subscribe to User Presence Change

The subscription is responsible for a callback upon the arrival of a contact availability. XML of the following format will be received when a contact’s availability status has changed:

<presence from="alice@wonderland.lit/rabbithole"
to="sister@realworld.lit">
</presence>

The SDK is also responsible for converting this XML to a TypeScript type that can be consumed by the app and the portal portal.

Implementation in the NiceDay app

We defined the behaviour of this feature in the app as described below:

  • The app will send initial presence to broadcast its available status once it is connected to the chat server.
  • The server will automatically broadcast unavailable status once the app is no longer connected to the chat server (currently the app disconnects from the chat server once it gets sent to the background or killed by the user).

When a contact is online, the app will show “Online” text below the name of the contact in the chat room.

Implementation in the web portal

The server automatically sets the web portal user’s availability status based on whether the user is connected to the chat server or not. We also provide the user with an ability to change their status manually. The user can choose from online, away, busy and appear offline statuses.

In some particular cases, the web portal automatically sets the user’s availability status. After a period of inactivity, we set the user’s availability status to away and when the user is in a video call, we set their availability status to busy.

The user may log in to more than one portal instances (e.g open the portal in another tab or in a different browser on another computer). To make their availability status consistent, we sync the statuses between those instances. So if the user sets their availability status to away in one portal instance, the same status will be passed on to all the other existing portal instances.

Conclusion

It is easier to interact with Ejabberd through the Ejabberd API. In this case we enabled the Roster Item operation through its API while keeping the service secure enough and ensuring that we grant permission to the APIs strictly on a need-to-know basis.

References

--

--