Monday, January 2, 2012

Checking the presence of a user (or queue) in Sametime using JavaScript

Recently, while tracking down a potential bug in one of our Queue Manager deployments, it was decided that we needed a way to check the presence of a logged in user through the Sametime Connect Web API. For instance, while on a website an end user clicks on a ‘Live Chat’ link, they are logged into a Sametime client on their computer, so we use JavaScript to talk to that Sametime client to get a bit more information. We check with the Sametime client to see if our ‘Live Chat’ support queue (user) is online, if the Sametime client can see that user online, we will start the conversation through their installed Sametime client, if it can’t, we will launch our branded web client so the conversation can still happen.

After reading through the Sametime SDK/Connect Web API documentation fairly extensively, I determined that there was no real official or right way of doing the above on the client side with JavaScript, so we’d have to improvise a bit, piecing different parts of the API together to get it to do what we wanted. Let’s look at some code.

The first thing we needed to do was wire up some Sametime livenames. According to the documentation, livenames are a UI representation of a contact; they display the online status using a status icon, and bold coloring of the contact’s display name. To do this, we include the getStatus.js JavaScript file; this file exists inside the user’s local Sametime client, and includes a lot of utility functions to deal with livenames/presence.

<script type="text/javascript" src="http://localhost:59449/stwebapi/getStatus.js"></script>

The Sametime client listens on http://localhost:59449, so if the user currently has Sametime running, these files will exist for us to include in our HTML/JS pages.

The next step is to add some HTML links for the users which we’ll be checking presence on. For our use case, we didn’t want these links to appear on the page, we just wanted our JavaScript and the getStatus.js file provided to utilize them as needed, so I added a style=”display: none;” tag to the link to hide it. These links need to have the class=”awareness”, as that is how the getStatus.js file will pick them up when the page loads.

<a class="awareness" userId="System%20p" style="display: none;">Resolving contact, please wait....</a><br />
<a class="awareness" userId="zac" style="display: none;">Resolving contact, please wait....</a><br />
<a class="awareness" userId="test user" style="display: none;">Resolving contact, please wait....</a><br />

The userId=” {username} ” denotes the user which we are tracking presence of. In the example, we have System p (one of our test support queues), zac (my internal username), and test user (a non-existent user which will show up as offline).

After saving the file, we can access the HTML page we created. It will appear blank, but if we have Sametime running, we should be able to see some things under the covers in the browser. Using Firebug, we can see that the getStatus.js file has built up an array, called sametime_livenames, where it has stored a bunch of values about the users which we added to the page.


Now that we have these populated objects, let’s see how we can manipulate them to get a presence. In this example, we have three users; two (System p, zac) of them online, 1 (test user) that is offline. Now that we have sametime_livenames built up, we need to find the user’s presence. This took some serious digging on my part to find the differences, and good ways of doing this. I eventually settled on the fact that if the user is online, a “_properties” variable will be defined, if the user is offline, this variable doesn’t exist. Below is the Firebug output that lead me to this while testing.

sametime_livenames[0]._properties represents the first user we are tracking, System p, which is logged in.
sametime_livenames[2]._properties represents the last user we are tracking, test user, which is not logged in, and returns undefined.

So now we know what we are looking for to detect presence, but we need this to happen automatically when a user clicks a link, and have some custom logic to determine which chat client to launch, so let’s build our function to do this.

We will be using object literal notation since we don’t want our JavaScript to interfere with any other libraries the site we post to may be using.
// Detect presence of watched Sametime users
Instant.detectPresenceOfUser = function (stid) {
    user = stid.toLowerCase(); // Convert stid variable to lower case for switch statement

    switch (user) {
        // Check if STID is System p
        case 'system p':
            livename = sametime_livenames[0];

            // Check if user is logged in
            if (typeof livename._properties === "undefined") {
                return false;
            } else {
                return true;
            }
            break;
        // Check if STID is zac
        case 'zac':
            livename = sametime_livenames[1];

            // Check if user is logged in
            if (typeof livename._properties === "undefined") {
                return false;
            } else {
                return true;
            }
            break;
        // Check if STID is test user
        case 'test user':
            livename = sametime_livenames[2];

            // Check if user is logged in
            if (typeof livename._properties === "undefined") {
                return false;
            } else {
                return true;
            }
            break;
    }
};

The Instant.detectPresenceOfUser function is where we will return a true/false based on whether or not the user that we pass into the function is online or offline. The user gets passed in (ex. Instant.detectPresenceOfUser(“System p”);), the function converts it all to lower-case, and then passes it through the switch which determines what user we are looking for the presence of. Next, it checks that _properties variable, if it exists, the user is online, and the function returns true, otherwise, it returns false as it can’t see the user.

This gets bundled into our Instant.startChat function, so that we can have some logic about how we want to start the conversation. Now, if the website can’t see the user when a chat is initialized, it will launch the web client. In our case, the user may not be offline, just the site can’t see them, and the web client will bridge that gap.

Our full file of JavaScript utilities can be seen below. This includes checking whether the user is running Sametime, the presence detection function, and the function that can start a chat conversation from the web using Sametime.



No comments: