openfire.muc.MUCRoom.joinRoom() how to get MUCUser obj

Hello all,

I am trying to use this method below:

MUCRoom.joinRoom(String nickname,
String password,
HistoryRequest historyRequest,
LocalMUCUser user,
Presence presence)

I am having a problem obtaining the LocalMUCUser object.

How can I obtain this Object from a JID or a User object?

Thanks!

OK I’m back.

Any ideas?

User user = server.getUserManager().getUser(_invitor);
room.joinRoom(_roomName, null, null, user, server.getPresenceManager().getPresence(user));

Now joinRoom requires a muc.spi.LocalMUCUser and not a User object as I did above so how can I get this LocalMUCUser?

I tried casting, I looked at the MUCManager object to see if I could derive a LocalMUCUser from that…no luck.

Notice my other post:

http://www.igniterealtime.org/community/message/187120#187120

This is related I am trying to come up with a workaround for the “null is inviting you to join” issue.

I am assuming that I get this because there is no one in the room when the invites are sent out so my workaround attempt would be to create room, unlock room, have the creator join room(see above code), then send out invites to the people that the creator wanted to have join the room, thus preventing the “null is inviting you to join” issue.

Thanks for any advice.

I am running in the exact same problem as you. I want to create a “bot” plugin that will join a room and perform actions upon request. I have found that the LocalMUCUser class is protected and cannot be called to create the object. I could possibly modify the Openfire source to make it work, but I want to avoid that since it wouldn’t be Kosher and would cause headaches upgrading in the future if my changes aren’t integrated. Have you found any work arounds? If so, please post. I will do the same if I come up with a solution.

Thanks

In the future I will also work on this and see the same problem. In my opinion the

private MUCUser getChatUser(JID userjid, String roomName)

method in the org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl class should be public. A bad workaround could be to handle the MUC related actions by XMPP stanzas send to the component. But since we have a good and extensive API within the XMPP server itself I see no reasons that speaks against that. Therefore I attached a patch that should fix that. I hope it will find a way to the official openfire sources.

Best Regards
getChatUser.patch (1750 Bytes)

I successfully got it to work, your diff is on the right track, but you need to get a LocalMUCUser to join a chat. Here is what I did:

In MultiUserChatServiceImpl.java add:

/**

  • Obtain a chat user by XMPPAddress. Only returns users that are connected to this JVM.
    *
    • @param userjid The XMPPAddress of the user.
    • @param roomName name of the room to receive the packet.
    • @return The chatuser corresponding to that XMPPAddress.
      */
      public LocalMUCUser MyGetChatUser(JID userjid, String roomName) {
      if (router == null) {
      throw new IllegalStateException(“Not initialized”);
      }
      LocalMUCUser user;
      synchronized (userjid.toString().intern()) {
      user = users.get(userjid);
      if (user == null) {
      if (roomName != null) {
      // Check if the JID belong to a user hosted in another cluster node
      LocalMUCRoom localMUCRoom = rooms.get(roomName);
      if (localMUCRoom != null) {
      MUCRole occupant = localMUCRoom.getOccupantByFullJID(userjid);
      //if (occupant != null && !occupant.isLocal()) {
      // return new RemoteMUCUser(userjid, localMUCRoom);
      //}
      }
      }
      user = new LocalMUCUser(this, router, userjid);
      users.put(userjid, user);
      }
      }
      return user;
      }

In MultiUserChatService.java add:

public LocalMUCUser MyGetChatUser(JID userjid, String roomName);

Compile OpenFire and copy over the new openfire.jar to your production lib folder and restart. Then you can call MyGetChatUser to get a valid user to join a room. I have it working now! To get this in to the general release we would obviously rename the method and come up with support for clustered servers (note the commented out code).

This is great – Is this the way such a problem needs to be approached?

I’m trying to do something very similar to Aaron (I think) – I’ve got some botz who are responsible for listening for new sessions, putting various users into MUCRooms, and then I’d like the bot to join the rooms and listen and respond to other commands within the rooms.

I’m using the botz-openfire-3.4.jar for my botz – Is that what you’re doing?

Is the idea that using

MUCRoom.joinRoom(String nickname,

String password,
HistoryRequest historyRequest,
LocalMUCUser user,
Presence presence)

will put my bot in the room without making the bot send and receive an invitation the way he would if I were to use room.sendInvitation() and then receive and respond to the invitation?

I had been using room.sendInvitation(ParrotUserJID, “join meh”, room.getRole(), null); in order to invite a user…but they have to go through the process of accepting the invitation, etc.

Thanks in advance for any guidance.

I am writing my own bot that joins a group chat. I then watch for message events and have it act upon them. By joining the room my bot can send chat messages.

Hi Aaron,

I don’t know so much about the cluster support in openfire. Since there is no commercial support anymore I think some people working on that topic to get a new implementation to work.

But I don’t think you need a new method which do nearly the same. You can just use the existing one in the plugin, for example:

... MUCUser user = service.getChatUser(jid, roomName); if (user instanceof LocalMUCUser) { MUCRole room.joinRoom(nick, null, null, (LocalMUCUser) user, presence); } else { throw new IllegalStateException("No Cluster Support"); }

Hello all,

finally revisited this and glad to see there is some action on this issue.

Thanks for the help on this. I really dont want to go the route of recompiling Openfire.jar.

Here are my thoughts, let me know if this is a bad idea.

Basically the problem(“null is inviting you to join room”) lies in that room.getRole() returns null(?) as there are not yet any Occupants in this room.

My idea was to sleep the thread (after the invite was sent to the person actually creating the room) until there was a user in the room(this user would be the creator.

here is my code

//Room doesnt exist so create it.

MUCRoom room = mucService.getChatRoom(_roomName, jid);

room.unlock(room.getRole())

room.addModerator(jid, room.getRole());

//Now send an invitation to the creator and wait til he joins.
room.sendInvitation(jid, _roomName, room.getRole(), null);
while(room.getOccupantsCount() == 0){Thread.sleep(3000);}

//He finally accepted his won invitation so now he can send out his invites.
for (MUCRole role : room.getModerators()) {

//Make sure we get the role of the creator for the room he is creating.
if (role.getChatRoom().getName().equals(_roomName)) {
/*** Iterate over inviteeArray and send invitations to all ***/

for (int i = 0; i < _inviteeArray.length; i++) {

room.sendInvitation(new JID(_inviteeArray[i] + “@” + serverName), _roomName, role, null);
}
}
}

Anyway, I realize this doesnt address the inability to access a LocalMUCUser object but it seems to fix my initial problem “null is inviting you to join”.

Thoughts?

Perhaps theres a better way of waiting for the creator to join?

Perhaps this is a no no in a plugin?

Cheers!

Hi crux of the biscuit,

sorry for my delay. In my opinion your code is a workaround for the inviting problem which still needs some user interaction (the creator has to be an user who joins the room so that you can act with his role) and doesn’t fix the problem that a plugin has no possibility to join a chatroom.

My problem is that I want to implement a component which handles a chatroom completly (setup the memberlist and grant and revoke some participants the privilege to speach). This meens there should be no need for other owners or moderators in the room. Therefore my plugin has to create and join a chatroom to get the exclusive access to manage all occupants.

In my opinion the conclusion of this discussion right now is that the MUC implementation of Openfire should be fixed to get access to the Multi-User Chat API by a plugin.

I see two ways to achieve this. The first is to publish the the MUCUser (by the getChatUser patch) or to modify the design of the implementation. For this case I wrote a second patch (seperateMUCRoleAndMUCUser.patch) that seperates the MUCRole from the MUCUser, so that no user object is needed to join a chatroom. This change of the design opens the possibility of implementing the support for two (or more) in-room “sessions” (of an occupant with the same bare JID and the same room nickname) as described in XEP-0045 section nickname conflict. But this concern still needs more work.

If there are several people who would like to get this improvement of more in-room “sessions”, I would be willing to spend more time in implementing this.

Maybe there is someone who is able to create a Jira ticket for the patches and maybe another for the support of more in-room sessions.

Best Regards
getChatUser.patch (1750 Bytes)
seperateMUCRoleAndMUCUser.patch (13379 Bytes)

1 Like

I faced the same issue while trying to make a bot user join all chat rooms. There is no need to patch Openfire. I accomplished it with just the reflections api. Here is the snippet.

XMPPServer server = XMPPServer.getInstance();

MultiUserChatManager mucManager = server.getMultiUserChatManager();

MultiUserChatService mucService = mucManager.getMultiUserChatService(“servicedesk”);

try {

 if (mucService instanceof MultiUserChatServiceImpl) {

           MultiUserChatServiceImpl mucServiceImpl = (MultiUserChatServiceImpl) mucService;

           Class<? extends MultiUserChatServiceImpl> c = mucServiceImpl.getClass();

           Method m = c.getDeclaredMethod("getChatUser", new Class[] { JID.class, String.class });

           m.setAccessible(true);

           for (MUCRoom room : mucService.getChatRooms()) {

                     LocalMUCUser localMUCUser = (LocalMUCUser) m.invoke(mucServiceImpl,

                          new Object[] { getUserJID(OSDGlobals.getBotName()), room.getName() });

                     Presence p = new Presence(Presence.Type.subscribe);

                     room.joinRoom(OSDGlobals.getBotName(), null, null, localMUCUser, p);

           }

   }

} catch (IllegalAccessException e) {

} catch (IllegalArgumentException e) {

} catch (InvocationTargetException e) {

} catch (UnauthorizedException e) {

} catch (UserAlreadyExistsException e) {

} catch (RoomLockedException e) {

} catch (ForbiddenException e) {

} catch (RegistrationRequiredException e) {

} catch (ConflictException e) {

} catch (ServiceUnavailableException e) {

} catch (NotAcceptableException e) {

} catch (NoSuchMethodException e) {

} catch (SecurityException e) {

}

I have tried adding this method into botz code as well as parrotbot code as a method named join(…) and calling it as soon as the parrotbot logs in. However parrotbot is not joining any room and not responding. Note: I can dirrectly communicate with the parrotbot via spark client.
I am missing something here. Can you please help me with the following:

Where should this code snippet go, and when to call it?
Shoudn’t parrotbot be joining my fastpath workgroup first? I have it added as a member to my workgroup, but is not “active”

Can someone post a simple bot plugin code implementation that does this?

I got same issue, i dont know how to creat LocalMucUser object, can someone give me some advices? Thanks