Get list of users from OpenFire server - xmpp

I'm currently trying to make a Strophe based javascript script to get the list of available users in an OpenFire server (live refreshing needed). I don't care if I have to create a group, room or whatever it's called (anyway, the server will be running for only a small group of users, everyone connected to eachother), but I want to be able to make the server give such a list.
How can I do this? I've read that I need to use muc extension, but I can't seem to find it anywhere...

Problem solved! I had to add the users I was working with to a group and eachtime a user leaves or enters the room OpenFire notifies the other users of the room with a presence stanza wrapped inside a body tag most of the times. This makes Strophe to not identify those presence stanzas very well, so I had to overwrite the xmlInput function from the Strophe connection to get every single xml stanza that I get from the server.
conn.xmlInput = onXmlInput;
function onXmlInput(data) {
Strophe.forEachChild(data, "presence", function(child) {
var from = child.getAttribute('from');
from = from.substring(0, from.indexOf('#'));
//'type' will contain "unavailable" when offline and no attribute 'type' when online
if (!child.hasAttribute('type')) {
addUser(from);
} else {
deleteUser(from);
}
});
}

Related

Smack MultiUserChatManager creates not joinable room

I am using Smack 4.1.1 as Gradle dependency in mine Android project.
I have successfully established connection with mine local OpenFire server.
But I have an issue while creating temporary room from Android client.
final MultiUserChat multiUserChat = userChatManager.getMultiUserChat(roomId);  
try {  
multiUserChat.create(connection.getUser());  
LOG.debug("room created");  
} catch (XMPPException.XMPPErrorException | SmackException e) {  
LOG.error("create room error:{}", e);  
}  
try{  
multiUserChat.sendConfigurationForm(new Form(DataForm.Type.submit));   
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException e) {  
LOG.error("sending room configurations error:{}", e);  
}   
The most great thing is that I can see that room was created in OpenFire admin panel and get room information from another client.
try {  
MultiUserChatManager userChatManager = MultiUserChatManager.getInstanceFor(connection);  
RoomInfo info = userChatManager.getRoomInfo(roomId);  
LOG.debug("room has {} occupants", info.getOccupantsCount());  
joinToExistingRoom(roomId);  
} catch (XMPPException.XMPPErrorException e) {  
LOG.error("join room error:{}", e);  
final XMPPError.Condition condition = e.getXMPPError().getCondition();  
if (condition == XMPPError.Condition.item_not_found) {  
LOG.error("room does not exist error:{}", e);  
createRoom(roomId);  
}  
}  
But while trying to join room from second client I receive XMPPError: recipient-unavailable - wait.
Snippet of mine joinRoom method:
final MultiUserChat multiUserChat = userChatManager.getMultiUserChat(roomId);  
try {  
multiUserChat.join(connection.getUser());  
LOG.debug("joined to room:{}", roomId);  
} catch (SmackException.NoResponseException  
| XMPPException.XMPPErrorException  
| SmackException.NotConnectedException e) {  
LOG.error("error joining room {}", e);  
}  
So I am catching error joining room org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError:recipient-unavailable - wait
So the question is what can be wrong?
I also tried creating submitForm from createAnswerForm() method. But the result is the same.
One solution I have found to make it work is to send persistantroom as true in Answer of configuration form. But this method creates persistent room, though I need this room to be destroyed after all attendees leave room.
Maybe it is a simple problem, but now I do not know how to solve this issue.
Help will be appreciated a lot.
Thanks in advance.
The create() method documentation states that:
Creates the room according to some default configuration, assign the requesting user as the room owner, and add the owner to the room but not allow anyone else to enter the room (effectively "locking" the room). The requesting user will join the room under the specified nickname as soon as the room has been created.
To create an "Instant Room", that means a room with some default configuration that is available for immediate access, the room's owner should send an empty form after creating the room.
Try to send configuration form this way:
multiUserChat.create(connection.getUser())
Form form = new Form(DataForm.Type.submit);
multiUserChat.sendConfigurationForm(form);
See also muc extension documentation

How to replace auto generated easyrtc id with your applications username in easyrtc application

I am developing one application using easyrtc tool with wavemaker tool.For a new user easy rtc provides automatically created easyrtc id.
In the chat window the random id are shown..i want to replace these ids with applications username..
I have find one solution where we have to set easyrtc.setUsername("") in client js file before calling easyrtc.connect function..
But this not solves the problem...
any help would be appriciated
Now, you can do it easyer, use this function:
easyrtc.idToName(easyrtcid)
Their is no easy way to solve this. However, it is possible using a mixture of server-side and client-side events to pass/receive user metadata when connected/disconnected. Here is a simple way to achieve this:
When a client connects to the server send user metadata via sendServerMessage on the connected event listener via client-side library. The server then receives the message from the client and stores the metadata about the user with that particular easyrtcid in a central location (ex. redis). The message sent to the server can be a json object with user metadata in a structured format. See details on connecting and sending a message to the server here: easyRTC Client-Side Documentation
When a client disconnects from the server remove their information from the data store using the onDisconnect event on the server side. This event provides a connectionObj which includes the easyrtcid of the user who disconnected. Use this identifier to remove the user from the datastore. You could also call generateRoomList() on the connectionObj to remove the user by easyrtcid and room from your datastore. You can read about the connection object here: connectionObj easyRTC documentation
Here is some example code of how to do this:
// Client-Side Javascript Code (Step 1)
easyrtc.connect('easyrtc.appname', function(easyrtcid){
// When we are connected we tell the server who we are by sending a message
// with our user metadata. This way we can store it so other users can
// access it.
easyrtc.sendServerMessage('newConnection', {name: 'John Smith'},
function(type, data){
// Message Was Successfully Sent to Server and a response was received
// with a the data available in the (data) variable.
}, function(code, message) {
// Something went wrong with sending the message... To be safe you
// could disconnect the client so you don't end up with an orphaned
// user with no metadata.
}
}, function(code, message) {
// Unable to connect! Notify the user something went wrong...
}
Here is how things would work on the server-side (node.js)
// Server-Side Javascript Code (Step 2)
easyrtc.events.on('disconnect', function(connectionObj, next){
connectionObj.generateRoomList(function(err, rooms){
for (room in rooms) {
// Remove the client from any data storage by room if needed
// Use "room" for room identifier and connectionObj.getEasyrtcid() to
// get the easyrtcid for the disconnected user.
}
});
// Send all other message types to the default handler. DO NOT SKIP THIS!
// If this is not in place then no other handlers will be called for the
// event. The client-side occupancy changed event depends on this.
easyrtc.events.emitDefault("disconnect", connectionObj, next);
});
Redis is a great way to keep track of the users connected if using rooms. You can use an hash style object with the first key being the room and each sub key/value being the users easyrtcid with a JSON hash of the metadata stored as it's value. It would have to be serialized to a string FYI and de-serialized on the lookup but this is simple using Javascript using the JSON.stringify and JSON.parse methods.
To detect occupancy changes in your application you could add a event listener to the easyrtc.setRoomOccupantListener method on the client-side and then when this event is fired send another message to the server to get all the users connected to it from the datastore.You would have to listen for a separate message on the server-side and return the users in the store deserialized back to the client. However, depending on your application this may or may not be needed.

Swift and Parse for messaging app?

I'm relativily new to databases and Parse, but I'm trying to set up an app that can recieve and send messages between users. I've managed to set up the sign up and log in process, now I need to get the devices communicating.
Do anynone have any idea how to make this happen? I can imagine you'll have to create PFObjects with ID's and classes with some user-details so that only the two users communicating can send and retrieve messages to each other.
Any suggestions on how to set this up would be very appreciated.
Sure enough there are huge ways to setup communication between devices. But it totally depends on your communication needs.
For example, if you need "real time" communication,
like peer-2-peer, then you need to start looking for external service, such as PubNub, because you can't do that with Parse.
If you are trying to build some chat like app, then you can go with manually refreshing and
push notifications.
So, to do what you want you need to create message object and setup ACL for it
PFObject *groupMessage = [PFObject objectWithClassName:#"Message"];
PFACL *groupACL = [PFACL ACL];
// userList is an NSArray with the users we are sending this message to.
for (PFUser *user in userList) {
[groupACL setReadAccess:YES forUser:user];
[groupACL setWriteAccess:YES forUser:user];
}
groupMessage.ACL = groupACL;
[groupMessage saveInBackground];
So, here we've added ACL(access control list) rule for our message, to allow all users from userList access that message.
Also, don't forget to include additional information for message like 'recipient', 'sender' etc to be able to create queries using it. For example, to retrieve all messages send from concrete user.

XMPP Smack chat using openfire

Few questions around getting Chat working with Smack (3.2.1)/Openfire(3.7.1Alpha).
I am currently testing it using a unit test. My unit test creates a connection, creates account, logs in, adds a new user to its roster, attempts to send a chat message to the new user and eventually deletes the users. Apart from my confusions around getting chat to work, others seem to work (verified using openfire admin dashboard).
A. When I do the following
public void sendChatMessage(String sender, String receiver, String message) {
Chat chat = chatManager.createChat(receiver, messageListener);
chat.sendMessage(message);
}
Current connection is of the 'sender' (i.e. sender is logged in) and my attempt is to send a message to 'receiver'. When I get callback in my listener, message.getFrom() returns the 'receiver' and message.getBody() returns null. I am obviously trying to send a message on behalf of 'sender' to 'receiver'. What am I missing?
B. My 'sender' and 'receiver' are simply unique 'usernames' (without
any #domain) and my server is simply 'localhost'.
connection = new XMPPConnection("localhost");
Do I need to modify the 'receiver' to be of different value to make it a valid JID (there are no errors at the moment)? What if I change my server (& the openfire server configurations)?
C. I am assuming there will always be one XMPPConnection per user? Is this correct?
D.
XMPPConnection.DEBUG_ENABLED = true;
When I have XMPPConnection in debug mode, a new window opens up, however, it is tied with my IDE. How can I have it not tied to the ide so I can look into the logs while trying to debug the code?

openfire get online users

I'm using OpenFire server for instant messaging and JSJaC JavaScript library on the client. I'm new in XMPP technology.
What I want is on load I want to send a list of users and receive status for each. Something like
$(function(){
var UserList = ["Isis", "Jackob", "Oybek"];
con.send(UserList, OnComplete);
});
function OnComplete(myList){
for (el in myList)
if (el.IsOnline) {
// Do DOM Stuff
}
}
Is it possible?
I've been looking for the documentation, examples and other similar responses but didn't find anyting.
You can't query for presence. You can subscribe to presence. If you send your own presence in, the server will send you the current presence of everyone you have subscribed to, as well as every change they make to their presence from there on in. There's no way to tell when you're "done" getting presence, because you're never done. Just set up a callback to do something interesting whenever you get a presence change from the person you are subscribed to, and you'll be in good shape:
con.registerHandler('presence_in', function(p) {
var from = p.getFromJID()
// do something interesting with p, from, etc.
});