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
Related
I want to get offline user (friend) status:
My code is working fine when user is online, so i am getting user status but when he goes offline user.primaryResource.presence.status gives nil value.
XMPPUserCoreDataStorageObject *user = [[self fetchedResultsController] objectAtIndexPath:indexPath];
NSLog(#"Status: %#",user.primaryResource.presence.status);
After user goes offline i check the XMPPResourceCoreDataStorageObject table for particular jidStr its give me zero objects means when user goes offline its remove the ResourcesObject of that user.
So, there is any possibility to get a status of that user.
You check the source code of XMPPUserCoreDataStorageObject
- (void)updateWithPresence:(XMPPPresence *)presence streamBareJidStr:(NSString *)streamBareJidStr
{
XMPPResourceCoreDataStorageObject *resource =
(XMPPResourceCoreDataStorageObject *)[self resourceForJID:[presence from]];
if ([[presence type] isEqualToString:#"unavailable"] || [presence isErrorPresence])
{
if (resource)
{
[self removeResourcesObject:resource];
[[self managedObjectContext] deleteObject:resource];
}
}
else
{
if (resource)
{
[resource updateWithPresence:presence];
}
else
{
XMPPResourceCoreDataStorageObject *newResource;
newResource = [XMPPResourceCoreDataStorageObject insertInManagedObjectContext:[self managedObjectContext]
withPresence:presence
streamBareJidStr:streamBareJidStr];
[self addResourcesObject:newResource];
}
}
[self recalculatePrimaryResource];
}
You can see the resource will be removed if offline.
For myself, I check user.primaryResource?.presence?.type() == "available" as online, other cases as offline. (Assume user is the XMPPUserCoreDataStorageObject you got from db)
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"];
}
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?
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
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