Accepting chatroom invitation - ios

I'm able to create a MUC using XMPPFramework and send user invitation requests to join that room by using the code below.
// Creating
AppDelegate *dele =(AppDelegate *) [[UIApplication sharedApplication]delegate];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:dele jid:[XMPPJID jidWithString:self.roomName] dispatchQueue:dispatch_get_main_queue()];
[xmppRoom addDelegate:dele delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:dele.xmppStream];
[xmppRoom joinRoomUsingNickname:self.myNick history:nil];
// Inviting
[xmppRoom inviteUser:[XMPPJID jidWithString:#"abc#host"] withMessage:#"Come Join me"];
How does a user "abc" know that he has received an invitation and how can he react to it either by accepting or declining?
I could not find any class in XMPPFramework which directly deal with chat room invitation.
My research says that whenever a user receives an chatroom invitation, xmmppStream's delegate method is called:
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
In that message, I check whether the it contains NSXMLElement with name "invite", and if it contains then i send a callback to the user. Then i create chatroom with the same name as the name of the chatroom from which user received invitation and enter that newly created room. It works fine but quiet lengthy and not quiet efficient.
I want to know if there is a class in XMPPFramework available here which could handle chat room invitation separately. For instance, detecting, accepting, and declining of room invitations.
My code for extracting room name:
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSXMLElement * x = [message elementForName:#"x" xmlns:XMPPMUCUserNamespace];
NSXMLElement * invite = [x elementForName:#"invite"];
NSXMLElement * decline = [x elementForName:#"decline"];
NSXMLElement * directInvite = [message elementForName:#"x" xmlns:#"jabber:x:conference"];
NSString *msg = [[message elementForName:#"body"]stringValue];
NSString *from = [[[message attributeForName:#"from"]stringValue];
if (invite || directInvite)
{
[self createAndEnterRoom:from Message:msg];
return;
}
[self.delegate newMessageRecieved:msg];
}

For room invitations and declines, implement XMPPMUCDelegate and its methods -xmppMUC:didReceiveRoomInvitation: and -xmppMUC:didReceiveRoomInvitationDecline:.
To get the room JID, invoke [message from];
To join the room, instantiate an XMPPRoom and invoke -joinRoomUsingNickname:history:.
Then have your room delegate class implement XMPPRoomDelegate, and implement some of the delegate methods to handle receiving messages in the room.
It looks like there isn't at present a more automatic way to respond to invitations.
Update: The delegate callbacks now receive the room JID as a parameter, clarifying the semantics a bit.
- (void)xmppMUC:(XMPPMUC *)sender roomJID:(XMPPJID *) roomJID didReceiveInvitation:(XMPPMessage *)message;
- (void)xmppMUC:(XMPPMUC *)sender roomJID:(XMPPJID *) roomJID didReceiveInvitationDecline:(XMPPMessage *)message;

just add below code
if ([presenceType isEqualToString:#"subscribe"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"localhost"]];
NSLog(#"presence user wants to subscribe %#",presenceFromUser);
[xmppRoster acceptPresenceSubscriptionRequestFrom:[presence from] andAddToRoster:YES];
//For reject button
// [xmppRoster rejectPresenceSubscriptionRequestFrom:[tmpPresence from]];
}
inside the method
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence ;
method

Related

XMPP muc room left once user offline iOS

I am creating room with Xmmp open fire ,first time its working fine
and if group admin go to offline then all member left room ,when
come to online not join the room . how to rejoin the room ? !
This is how XMPP Multi-User Chat works. Multi-User Chat specification is presence-based. When you are offline, you are not an occupant of the room.
After creating room set your XMPP Room persistent using below code...
-(void)xmppRoomDidJoin:(XMPPRoom *)sender {
NSLog("I did join.");
[sender fetchConfigurationForm];
}
-(void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm {
NSXMLElement *newConfig = [configForm copy];
NSArray *fields = [newConfig elementsForName:#"field"];
for (NSXMLElement *field in fields) {
NSString *var = [field attributeStringValueForName:#"var"];
// Make Room Persistent
if ([var isEqualToString:#"muc#roomconfig_persistentroom"]) {
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
}
[sender configureRoomUsingOptions:newConfig];
}
that time if room owner is offline that time XMPP Room is exist with all member

Not able to receive XMPPPubsub events to node subscribers

I am developing an app like RSS Feeds. I want users to get feeds without calling any web service. I read out some documents and got a solution of using XMPP where XMPPPubsub gives us that functionality to send an event notification to all subscribers.
In XMPPPubsub Owner creates a node and other users who want to get event notification subscribes to that node.
Set up XMPPPubsub
XMPPJID *serviceJID =[XMPPJID jidWithString:[NSString stringWithFormat:#"pubsub.%#",HOST_NAME]];
_xmppPubSub = [[XMPPPubSub alloc]initWithServiceJID:serviceJID dispatchQueue:dispatch_get_main_queue()];
[_xmppPubSub addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppPubSub activate:_xmppStream];
Creation of Node
- (void)createNodeWithName:(NSString*)nodeName withCompletionHandler:(CreateNodeCompletionHandler)completionBlock{
_createNodeCompletionHandler = completionBlock;
[_xmppPubSub createNode:nodeName withOptions:#{#"pubsub#title":nodeName,#"pubsub#deliver_notifications":#"1",#"pubsub#deliver_payloads":#"0",#"pubsub#persist_items":#"1",#"pubsub#notify_sub":#"1",#"pubsub#subscribe":#"1",#"pubsub#send_last_published_item":#"When a new subscription is processed and whenever a subscriber comes online",#"pubsub#access_model":#"open",#"pubsub#presence_based_delivery":#"1",#"pubsub#publish_model":#"open"}];
}
User who wants to have events must subscribe to node
- (void)subScribeToNode:(NSString*)nodeName withCompletionHandler:(SubscribeNodeCompletionHandler)completionBlock{
_subscribeNodeCompletionHandler = completionBlock;
[_xmppPubSub subscribeToNode:nodeName withJID:_xmppStream.myJID options: #{ #"pubsub#deliver" : #(YES),
#"pubsub#digest" : #(YES),
#"pubsub#include_body" : #(YES),
#"pubsub#show-values" : #[ #"chat", #"online", #"away" ] }];
}
Publish the event to node
- (void)sendMessage:(NSString*)message ToNode:(NSString*)node{
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:message];
NSXMLElement *messageBody = [NSXMLElement elementWithName:#"message"];
[messageBody setXmlns:#"jabber:client"];
[messageBody addChild:body];
[_xmppPubSub publishToNode:node entry:messageBody withItemID:nil options:#{#"pubsub#access_model":#"open"}];
}
All is working well Users are able to subscribe to a node. We are able to create the Node. When we get our subscriber nodes, it also returns all the nodes. The events that we published are also there in Database and if I retrieve events by code it also returns all of them.
But the issue is the subscribers are not able to get its notification in didReceiveMessage so subscribers are not getting notified of events.
No logs in below functions
- (void)xmppPubSub:(XMPPPubSub *)sender didReceiveMessage:(XMPPMessage *)message{
NSLog(#" -----We Just Received message wooo hooo whow owowhwo -----");
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq{
return YES;
}
Please guide me through this what I am doing wrong in it.
Thanks in Advance.
Client should indicate he wishes to receive notifications, as described in XEP-0060
In XMPPFramework you need to implement XMPPCapabilitiesDelegate and add younodename+notify to client capabilities. E.g. in your XMPPModule you need the following:
- (BOOL)activate:(XMPPStream *)aXmppStream
{
if ([super activate:aXmppStream])
{
[xmppStream autoAddDelegate:self delegateQueue:moduleQueue toModulesOfClass:[XMPPCapabilities class]];
return YES;
}
return NO;
}
- (NSArray *)myFeaturesForXMPPCapabilities:(XMPPCapabilities *)sender
{
return #["myprotocolnode+notify"];
}

Users are not Accepting Invitation in XMPPRoom

In my application if i am sending invitation to other user then moderator and all user who got the request will join the room but if another user will send the request to all then moderator of previous room is not getting invitation.
For Example:
user 1 will send invitation for Room 1 to user 2 and user 3 then all three are in Room 1.
if User 2 will send invitation for Room 2 to User 1 and User 3 then User 1 will is not getting invitation.
And also if User 3 will send invitation for Room 3 then User 3 only be present in Room and all other two are not getting invitation too.
In my application i am inviting other user with this request
XMPPRoomMemoryStorage * _roomMemory = [[XMPPRoomMemoryStorage alloc]init];
NSString* roomID = [NSString stringWithFormat:#"RoomName#conference.openfire id"];
XMPPJID * roomJID = [XMPPJID jidWithString:roomID];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:_roomMemory jid:roomJID dispatchQueue:dispatch_get_main_queue()];
[xmppRoom addDelegate:_roomMemory delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom joinRoomUsingNickname:[NSString stringWithFormat:#"%#",strCureentUserName] history:nil];
//.........inviting the Friend.......
for (int i=0; i<[arrUserName count];i++) {
[xmppRoom inviteUser:[XMPPJID jidWithString:[NSString stringWithFormat:#"Invite user's ID"]] withMessage:#"Come Join me in this room"];
}
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
and other user gets invitation here
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSXMLElement * x = [message elementForName:#"x" xmlns:XMPPMUCUserNamespace];
NSXMLElement * invite = [x elementForName:#"invite"];
NSXMLElement * decline = [x elementForName:#"decline"];
NSXMLElement * directInvite = [message elementForName:#"x" xmlns:#"jabber:x:conference"];
NSString *msg1 = [[message elementForName:#"body"]stringValue];
NSString *from1 = [[message attributeForName:#"from"]stringValue];
if (invite || directInvite)
{
NSLog(#"come in invite method of if condition");
[self createAndEnterRoom:from1 Message:msg1];
return;
}
How to get invitation from all user all the time.
Any kind of help is welcomed...
Thanks in Advance.
I'm actually working on it, I use XMPPMUC delegate (MUC stands for MultiUserChat)
Delegate has this method :
-(void)xmppMUC:(XMPPMUC *)sender roomJID:(XMPPJID *)roomJID didReceiveInvitation:(XMPPMessage *)message
{
}
I haven't done this yet, but I guess that you could search on this...
I think you made mistake while inviting users.You just use an array of user to invite other peoples that's fine but invitation must be sent when this XMPPRooms's delegate method call
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
/**
* You can read from an array containing participants in a for-loop
* and send multiple invites in the same way here
*/
[sender inviteUser:[XMPPJID jidWithString:#"arpan"] withMessage:#"Greetings!"];
}
Just use XMPPRoomdelegates in proper way to invite user.Refer thins link for delegates..
XMPPFramework - How to create a MUC room and invite users?

MUC How-to with XMPPFramework

I am developing an iOS XMPP chat app that utilizes Robbie Hanson's XMPPFramework.
The most important functionalities have been implemented - sending and receiving messages. Basically, I've built a basic functional chat app already, with a little eye candy of course.
Now, the problem I have is regarding MUC. The codes I saw from other websites show that there is a method initWithRoomName in XMPPRoom. However, this method is absent in the git repo I cloned. So, what is the alternative to this? Or, if there is none, how do I go about creating rooms using XMPPFramework?
Thanks.
Below is how I got my own problem solved. Note that this solution does not involve XMPPRoom at all. First, I created a method that, depending on the situation, either creates or enters a room. (Per XMPP documentation, the XML request for creating is the same is the same as the one you would send to enter a room; that is, if the room has does not exist yet when you enter it, the service will create it for you.)
Here we go. This is the method that creates/enters a room. What this method does is send a presence to the room which you intend to create/enter. If you are the first to enter a room and the room has not been created yet, you automatically become its owner and moderator.
- (void)createOrEnterRoom:(NSString *)roomName
{
//here we enter a room, or if the room does not yet exist, this method creates it
//per XMPP documentation: "If the room does not yet exist, the service SHOULD create the room"
//this method accepts an argument which is what you would baptize the room you wish created
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
NSString *room = [roomName stringByAppendingString:#"#conference.jabber.com/iMac"];
[presence addAttributeWithName:#"to" stringValue:room];
NSXMLElement *x = [NSXMLElement elementWithName:#"x" xmlns:#"http://jabber.org/protocol/muc"];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"maxstanzas" stringValue:#"50"];
[x addChild:history];
[presence addChild:x];
[[self xmppStream] sendElement:presence];
}
Next, in the AppDelegate where XMPPStream methods are declared we filter the XML response we receive in the didReceivePresence method by checking the status code sent by the server. If the status code is 201, bingo! The room creation went just fine. Status codes other than 201 mean different things, but let's focus on 201 for our purpose.
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
NSXMLElement *x = [presence elementForName:#"x" xmlns:#"http://jabber.org/protocol/muc#user"];
for (NSXMLElement *status in [x elementsForName:#"status"])
{
switch ([status attributeIntValueForName:#"code"])
{
case 201: [self notifyRoomCreationOk:room];
}
}
}
Then, we tell the server that what we are creating a room of the type "instant," which means that we will send an IQ element telling it room defaults. notifyRoomCreationOk is a delegate method called in a different view when the room creation succeeds, after all I have to record the room in a text file to make it persistent so that the next time I open the app the room I created before will be visible. In my notifyRoomCreationOk method, I have sendDefaultRoomConfig which, basically, describes what is stated in the first sentence of this paragraph.
-(void)sendDefaultRoomConfig:(NSString *)room
{
NSXMLElement *x = [NSXMLElement elementWithName:#"x" xmlns:#"jabber:x:data"];
[x addAttributeWithName:#"type" stringValue:#"submit"];
NSXMLElement *query = [NSXMLElement elementWithName:#"query" xmlns:#"http://jabber.org/protocol/muc#owner"];
[query addChild:x];
XMPPIQ *iq = [XMPPIQ iq];
[iq addAttributeWithName:#"id" stringValue:[NSString stringWithFormat:#"inroom-cr%#", room]];
[iq addAttributeWithName:#"to" stringValue:room];
[iq addAttributeWithName:#"type" stringValue:#"set"];
[iq addChild:query];
[[self xmppStream ] sendElement:iq];
}
Make sure that you have XMPPStream enabled on the views that call the above methods, otherwise, these won't work. That's all there is to it. Have fun XMPP-ing!
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomName:#"user101#conference.jabber.org/room" nickName:#"room"];
[room createOrJoinRoom];
[room sendInstantRoomConfig];
[room setInvitedUser:#"ABC#jabber.org"];
[room activate:[self xmppStream]];
[room inviteUser:jid1 withMessage:#"hello please join."];
[room sendMessage:#"HELLO"];
the user ABC#jabber.org should receive the invite message
Your post is old, however now I would do it like this:
- (void)createRoomWithJid:(XMPPJID*)roomJID
{
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:self.xmppRoomHybridStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:self.xmppStream];
[xmppRoom joinRoomUsingNickname:self.xmppStream.myJID.user
history:nil
password:nil];
}
Create chat room by given below code using XMPPFRAMWORK.
let roomStorage: XMPPRoomMemoryStorage = XMPPRoomMemoryStorage()
/**
* Remember to add 'conference' in your JID like this:
* e.g. uniqueRoomJID#conference.yourserverdomain
*/
let roomJID: XMPPJID = XMPPJID.jidWithString("chatRoom_name#conference.myhostname")
let xmppRoom: XMPPRoom = XMPPRoom(roomStorage: roomStorage,
jid: roomJID,
dispatchQueue: dispatch_get_main_queue())
xmppRoom.activate(SKxmpp.manager().xmppStream)
xmppRoom.addDelegate(self, delegateQueue: dispatch_get_main_queue())
xmppRoom.joinRoomUsingNickname(SKxmpp.manager().xmppStream.myJID.user, history: nil, password: nil)
xmppRoom.fetchConfigurationForm()

XMPPFramework - How to create a MUC room and invite users?

I am using Robbiehanson's iOS XMPPFramework. I am trying to create a MUC room and invite a user to the group chat room but it is not working.
I am using the following code:
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomName:#"user101#conference.jabber.org/room" nickName:#"room"];
[room createOrJoinRoom];
[room sendInstantRoomConfig];
[room setInvitedUser:#"ABC#jabber.org"];
[room activate:[self xmppStream]];
[room inviteUser:jid1 withMessage:#"hello please join."];
[room sendMessage:#"HELLO"];
The user ABC#jabber.org should receive the invite message but nothing is happening.
Any help will be appreciated. :)
After exploring various solutions, I've decided to compile and share my implementation here:
Create an XMPP Room:
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc] init];
/**
* Remember to add 'conference' in your JID like this:
* e.g. uniqueRoomJID#conference.yourserverdomain
*/
XMPPJID *roomJID = [XMPPJID jidWithString:#"chat#conference.shakespeare"];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[self appDelegate].xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:[self appDelegate].xmppStream.myJID.user
history:nil
password:nil];
Check if room is successfully created in this delegate:
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
Check if you've joined the room in this delegate:
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
After room is created, fetch room configuration form:
- (void)xmppRoomDidJoin:(XMPPRoom *)sender {
[sender fetchConfigurationForm];
}
Configure your room
/**
* Necessary to prevent this message:
* "This room is locked from entry until configuration is confirmed."
*/
- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm
{
NSXMLElement *newConfig = [configForm copy];
NSArray *fields = [newConfig elementsForName:#"field"];
for (NSXMLElement *field in fields)
{
NSString *var = [field attributeStringValueForName:#"var"];
// Make Room Persistent
if ([var isEqualToString:#"muc#roomconfig_persistentroom"]) {
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
}
[sender configureRoomUsingOptions:newConfig];
}
References: XEP-0045: Multi-User Chat, Implement Group Chat
Invite users
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
/**
* You can read from an array containing participants in a for-loop
* and send multiple invites in the same way here
*/
[sender inviteUser:[XMPPJID jidWithString:#"keithoys"] withMessage:#"Greetings!"];
}
There, you've created a XMPP multi-user/group chat room, and invited a user. :)
I have the feeling that the first thing to do after alloc-init is to attach it to your xmppStream, so it can use xmppStream to send/receive messages.
More exactly:
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomName:#"user101#conference.jabber.org/room" nickName:#"room"];
[room activate:[self xmppStream]];
//other things (create/config/...)
Check the latest XMPPMUCLight & XMPPRoomLight its similar to Whatsapp and other today's trends social app rooms that don't get destroyed or members kicked when offline or no one in room.
Refer this documentation & mod from MongooseIM

Resources