Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

Creating an IM system - best scenario?

Avatar

Employee

Hi,

We are planning on adding an Instant Messaging feature to an application used by two kind of users : customers and agents.

The goal is to allow text/audio/video chat (possibly with the three options simultaneously but most likely with either text or audio+video) with the following use cases:

  • Agent (1 or 2) <-> Customer (one-one or two-one)
  • Agent <-> Agent (multiple users)
  • Multiple opened chat session for a given user (mutiple windows similar to gmail)

We also need to display a list of users (both online and offline + capabilities (mic,webcam)) -> should we leverage some kind of main room for this as well?

So far we have identified three possible scenarios to achieve this:

  • One Room per chat/conversion : the user would need to create a new room from a template and send the url to other recipients (through a global message bus, maybe a global/general room). This also implies having multiple session opened as a user can have multiple one-one conversations
  • Create only  one room and use groupNames to manage the privacy of a conversation  but that seems to create one collectionNode per groupName and I’m not  sure how that will scale on the long run.
  • The  last option would be to send everything to a single collectionNode (like in  the simpleChatModel) and simply rely on the  recipiendIDs to manage the  privacy but that seems a bit overcomplicated to manage a conversation  with multiple users as we would first need to share the list of members for a given chat.

Would you guys have ideas or recommendations around this or maybe an Instant Messaging exemple?

Thanks,

Nicolas

1 Accepted Solution

Avatar

Correct answer by
Former Community Member

Hi Nicolas,

I think there are 2 aspects to what you're planning :

1) A lobby system with buddy-style presence for "rendez-vous" to the private

conversations

2) Private rooms that are used for the actual conversations

For 1), you'll want to use UserManager.anonymousPresence - this means that

not every person logged into the lobby will be able to see each other;

rather, only people who have broadcast their presence to the room on purpose

(so that everyone can see them) or with pre-defined relationships (such as

from a buddy list) will be seen. Anonymous presence greatly increases the

scale of our rooms into the thousands of connections. Secondly, you can use

UserManager.myBuddyList for each user who is connecting - assign a list of

userIDs that the current user should notify when he arrives.

For 2), when a private conversation needs to happen, have the initiator

request a new room from your server. Your server can validate the request,

and use the server integration libraries to create a new LCCS room, and

return the URL to the initiator. From there, the initiator can privately

message the URL to the person they're inviting (within some node in the

lobby room through which messages with recipientIDs can be used).

I think it's fine to have multiple sessions open at once from the client

(for example, the client would likely stay connected to the lobby the whole

time so that presence is reflected). So I definitely recommend the first

option you presented, with the addition of a general lobby room for generic

presence and rendez-vous. In this way you get the benefits of a centralized

presence system with the scale of private chats happening within their own

rooms.

This is definitely an area we on the product team are looking to document

further - we've rather quietly added the UserManager functionality above,

and have been planning out sample lobby systems to share. We're heads-down

in a release that's coming out very soon , but once that's done, we'll

start to get some more samples together on this topic.

hope that helps - let us know if we can answer any further questions.

thanks

nigel

View solution in original post

11 Replies

Avatar

Correct answer by
Former Community Member

Hi Nicolas,

I think there are 2 aspects to what you're planning :

1) A lobby system with buddy-style presence for "rendez-vous" to the private

conversations

2) Private rooms that are used for the actual conversations

For 1), you'll want to use UserManager.anonymousPresence - this means that

not every person logged into the lobby will be able to see each other;

rather, only people who have broadcast their presence to the room on purpose

(so that everyone can see them) or with pre-defined relationships (such as

from a buddy list) will be seen. Anonymous presence greatly increases the

scale of our rooms into the thousands of connections. Secondly, you can use

UserManager.myBuddyList for each user who is connecting - assign a list of

userIDs that the current user should notify when he arrives.

For 2), when a private conversation needs to happen, have the initiator

request a new room from your server. Your server can validate the request,

and use the server integration libraries to create a new LCCS room, and

return the URL to the initiator. From there, the initiator can privately

message the URL to the person they're inviting (within some node in the

lobby room through which messages with recipientIDs can be used).

I think it's fine to have multiple sessions open at once from the client

(for example, the client would likely stay connected to the lobby the whole

time so that presence is reflected). So I definitely recommend the first

option you presented, with the addition of a general lobby room for generic

presence and rendez-vous. In this way you get the benefits of a centralized

presence system with the scale of private chats happening within their own

rooms.

This is definitely an area we on the product team are looking to document

further - we've rather quietly added the UserManager functionality above,

and have been planning out sample lobby systems to share. We're heads-down

in a release that's coming out very soon , but once that's done, we'll

start to get some more samples together on this topic.

hope that helps - let us know if we can answer any further questions.

thanks

nigel

Avatar

Employee

Hi Nigel,

Thanks for the detailed answer, we're definately going for scenario 1 then but I just have one more question regarding the buddy list:

We want to add a feature where we can display the chat capabilities for each user (WebCam available, mic...) and display this on the contact list. So we were thinking on using the registerCustomUserField but the documentation specifies that only the room owner can register a property. Is it possible to change this on a room template and is this option be the appropriate one to implement the above mentionned feature?

One more thing, is the UserID persistant on the LCCS sever? i.e if I login/logout in several rooms/applications, will my UserID always be the same?

Thanks

Nicolas

Message was edited by: Nicolas Yuen

Avatar

Former Community Member

Hi ,

Yes, the registerCustomField is currently on an owner level permission as we believe the use case is, any user shouldn't be able to mess up with your user parameters. When you create an userField, it creates an associated node and our framework permits node creation only at the owner level.

You can always use roomconsole to create the user fields in advance.

Regarding your displaying them on contact list, this is perfectly possible. You can either subclass our UserItemRenderer class under rosterClasses and make the roster item display customized to your needs OR you can build your own roster and item renderer

Hope this helps

Thanks

Hironmay Basu

Avatar

Employee

I've been trying to use the myBuddyList + anonymous presence feature but it doesn't seem to work as I hoped.

I was expecting to only see users from myBuddyList on the roster  but here is the behaviour I get:

  • I can see every user that logged in later on in a room but without their custom status
  • People who joined later only see themselves unless other users update their user settings

I there a way to tweek the buddyList feature to get the same behaviour as a regular room (not anonymous) but only display/receive info from a restricted set of users?

Thanks,

Avatar

Employee

Hi Nicolas,

Can you please share your code, as I would like to know how you are setting your buddyList.

In the case of second scenario, "People who joined later only see themselves unless other users update their user settings" - Thats how anonymous presence is intended to work. Anonymous presence is lazy loading of all users in the room. A users info is updated if the user performs some activity (like updating his user settings).

In my opinion myBuddyList + anonymous presence alone cant help your usecase. As Nigel mentioned, have all the users enter a lobby room. Once a user and his buddies have arrived, you can request the server for a new room and transfer the users to the new room. So for scenario one of maintaining a lobby you might have to use myBuddyList + anonymous presence. For sceanario two of transferring the buddies and his user you might have to use server-to-server API's.

I will post you more information if I have a better approach.

Thanks

Arun

Avatar

Former Community Member

Hi Nicholas,

Just to make sure we're talking about the same thing, myBuddyList is the

set of users who will be able to see me. In order to see other users, they

have to have me on their buddyLists. Is that the case here? It could be that

there's some bug here, but I think we should be ok.

nigel

Avatar

Employee

Hi guys,

Inddeed, I only want to display users in my BuddyList for the lobbyroom. I 'm creating a connectSession and :

  • set the userManager.myBuddyList = [LCCS_USER_ID2] for LCCS_USER_ID1.
  • set the userManager.myBuddyList = [LCCS_USER_ID1] for LCCS_USER_ID2.

I also tried to set the buddyList on the synchronizationChange event but the result is the same.

The result I'm seeing is that no matter what I change I can still see users who are not on my buddyList when they join the lobby.

I would expect the userManager.userCollection to only contain LCCS_USERID_1 and LCCS_USERID_2 even if there is 100 users in the lobbyroom.

Maybe there is something to change at the user level to specify that one must remain anonymous but I couldn't find the appropriate property in the doc.

Also it seems expected that you don't see people on your buddyList in the roster (unless they updated their status) if you joined a room afterwards, does this imply that you need to manually fetch the userDescriptor of each member of your buddyList once you've synchronized?

Thanks,

Nicolas

Avatar

Employee

Hi Nicolas,

I was trying to test the scenario you mentioned. What you are doing seems to be right.

Let me break the issues you have

1) You see users not in your "myBuddyList" in your lobby. There are two possibilites
    a) UserManager.anonymousPresence is not set
    b) Users after entering the lobby are doing something (like sending a chat message) that forces all the other users to fetch the userDescriptor, and so you see other unintended users in your lobby.

Can you please use the dev console (from SDKNavigator) to ensure that anonymous presence is turned on. Also please double check if users are doing something that broadcasts their presence to every one.

2) Not seeing users who are in your buddylist.
    We found a bug at our end. I have attached both the swc and the src file that fixes the issue. Thanks a million for finding the bug and sincerely apologize for the inconvenience.
   
Please do let us know if you need any assitance, and we would be happy to help you.  Also I can take a look into issue one, if I know what a user is doing on entering the looby. 
   
Thanks
Arun

Avatar

Employee

Hi Arun,

Thanks for the patch. Regarding issue 1), users are indeed broadcasting a custom status on the customFields property when they enter the lobby (so we fall in the 1b use-case then):

private function fieldRegisterHandler(event:UserEvent = null):void
        {
            if ( userManager.isSynchronized)
            {
                userManager.setCustomUserField( userManager.myUserID, CUSTOM_STATUS_FIELD, STATUS_AVAILABLE);
            }
        }

This indeed seems to force every users to fetch the userDescriptor (note that anonymousPresence was enabled), is there a way to disable this? I added a filter function on a ListCollectionView created on top of the userManager.userCollection in the meantime so this is not really a blocker.

I'll try the patch tomorrow morning.

PS, I'm using the simpleChat component and it seems that the autoscroll feature doesn't work for me (I'm using Flex 4.1 so maybe this is related). I removed the _detachedScrolling Timer and changed the onHTMLChange function:

protected function onHtmlTextChange(p_event:Event):void
        {
                _history.verticalScrollPosition = _history.maxVerticalScrollPosition;
        }

It's a bit brutal but it works for me.

Thanks for the help!

Avatar

Employee

Thanks Nicolas,

I am looking into this issue. I will update you soon about this scenario.

Sincerely

Arun

Avatar

Employee

Hi Nicolas,

Thanks again for your patience. As mentioned earlier Anonymous presence is lazy loading of all users. So anonymousPresence was truned off for customFields, so that a user who sets a customField broadcasts his userId's.[Was a bit greedy about lazy loading]. We fixed this for you, and I have attached a patch again.

Also thanks for reporting an issue with SimpleChat on Flex 4.1. We will take a look.

Sincerely
Arun

The following has evaluated to null or missing: ==> liqladmin("SELECT id, value FROM metrics WHERE id = 'net_accepted_solutions' and user.id = '${acceptedAnswer.author.id}'").data.items [in template "analytics-container" at line 83, column 41] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign answerAuthorNetSolutions = li... [in template "analytics-container" at line 83, column 5] ----