XMPPFramework
XMPPFramework copied to clipboard
Exit Particular member/owner from Groupchat/Room using XMPP in iOS
Currently i am making chat application.
I will implement Group chat exit same like Whats app.
For example, I am group owner and after some time i will leave from Group.After i leaving from group any one member of the Group assign as a Group owner.
For that i applied following code :
1st fetch all members in the groupchat and then all members left groupchat manually but it also not working. `NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/muc#admin"];
NSXMLElement *item = [NSXMLElement elementWithName:@"item"];
[item addAttributeWithName:@"affiliation" stringValue:@"member"];
[item addAttributeWithName:@"jid" stringValue:@"jid to remove"];
[query addChild:item];
XMPPIQ *RemoveUser = [[XMPPIQ alloc] initWithType:@"set" to:[XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@",dialuser2,kSIPDomain]] elementID:@"some random id" child:query];
[SharedAppDelegate.xmppStream sendElement:RemoveUser];`
so any one have code or related information then please help me.
Thank you.
How to Create Group Chat(MUC) in IOS . I am developing a chat app in iOS. In XMPP server (Ejabberd in this case,I have enabled MUC ). I have registered a user and now trying to create a chatroom using an registered user. but its not created ChatRoom(groupName) in server and not added to roster list . can you please @help me.
Hello shravanteegala , I used following methods for create group.
1)For create Group (Only create group with name)
xmppRoomStorage = [[XMPPRoomMemoryStorage alloc] init];
NSString* roomID;
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString] ;
guid = strGroupName;
createdGroupName=[strGroupName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// NSString *strUrl = [NSString stringWithFormat:@"conference.%@", kSIPDomain]; NSString *strUrl = [NSString stringWithFormat:@"conference.%@", @“192.168.1.80”]; //put your server url after “conference” NSString *uniqueRoomJid = [NSString stringWithFormat:@"%@@%@", strGroupName,strUrl]; roomID = uniqueRoomJid;
//Never remove "conference" keyword from here
XMPPJID * roomJID = [XMPPJID jidWithString:roomID];
NSLog(@"myJID is-->%@",[[self xmppStream] myJID].full);
xmppRoom= [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:self.xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:[[self xmppStream] myJID].full
history:nil
password:nil];
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
(2) if room create successfully then call following method. Using this method invite members in group. Here(contactNo_arr is array of members which you want to invite for group)
-
(void)xmppRoomDidCreate:(XMPPRoom *)sender {
NSLog(@"Room created"); for(int j=0;j<[contactNo_arr count];j++) { // NSString *newjid=[NSString stringWithFormat:@"%@@%@",[contactNo_arr objectAtIndex:j],kSIPDomain]; [xmppRoom editRoomPrivileges:@[[XMPPRoom itemWithAffiliation:@"member" jid:[XMPPJID jidWithString:[contactNo_arr objectAtIndex:j]]]]]; [xmppRoom inviteUser:[XMPPJID jidWithString:[contactNo_arr objectAtIndex:j]] withMessage:@"join this room"]; }
} (3) After invite members call following method. -(void)xmppRoomDidJoin:(XMPPRoom *)sender { NSLog(@"Room joined"); [sender fetchConfigurationForm]; [sender fetchMembersList]; } (4) Created Room configuration.
-
(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"]]; } else if ([var isEqualToString:@"muc#roomconfig_roomname"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:createdGroupName]]; // group name
} else if ([var isEqualToString:@"muc#roomconfig_publicroom"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"0"]]; } else if ([var isEqualToString:@"muc#roomconfig_whois"]) { [field removeChildAtIndex:0]; [field insertChild:[NSXMLElement elementWithName:@"value" stringValue:@"anyone"] atIndex:0]; } else if ([var isEqualToString:@"muc#roomconfig_allow_subscription"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]]; } else if ([var isEqualToString:@"muc#roomconfig_membersonly"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]]; } else if([var isEqualToString:@"muc#roomconfig_getmemberlist"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"moderator"]]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"participant"]]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"visitor"]]; } else if ([var isEqualToString:@"muc#roomconfig_moderatedroom"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]]; } else if ([var isEqualToString:@"public_list"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]]; } else if ([var isEqualToString:@"muc#roomconfig_allowinvites"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]]; } else if ([var isEqualToString:@"muc#roomconfig_changesubject"]) { [field removeChildAtIndex:0]; [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"true"]]; }
} [sender configureRoomUsingOptions:newConfig];
} (5) if room not created successfully and any problem in configuration then call following method.
-
(void)xmppRoom:(XMPPRoom *)sender didNotConfigure:(XMPPIQ *)iqResult{
NSLog(@"didNotConfigure: %@",iqResult.debugDescription);
} (6) if room created successfully and without any problem in configuration then call following method.
- (void)xmppRoom:(XMPPRoom *)sender didConfigure:(XMPPIQ *)iqResult { NSLog(@"room configuration >>> %@",iqResult); }
Thank you.
Hi shraddha-patel-1891. Create Group and rename and Add users to Group is working fine. But,How to delete specific user from Room(Group)owner is mine . in my Chat Application. Please help me.
Hi shravanteegala i have same problem, not remove specific member from the group.so if i will found any solution then give you and meanwhile you will get any solution then please help me.
Thank You.
Hey there! I'm trying to do that too, remove a specific user from the Room. The only solution I thought of so far is sending a message and having the receiver call the XMPPRoom.leave() method.
Hey victorlsn, Thank you for giving me solution.i think you are right.i will implement your solution but if possible then provide me steps or code snippet for leave room. Thank you.
Sorry, Shraddha, I still didn't implement it. But as soon as I'm done I'll post my step-by-step here.
You can follow XEP-0045.
Hi
I am able to create group and invite member successfully.
Now if member try to get group's admin then it give below error Error:- "Moderator privileges required" Any idea?
Hello harddik , i add code for get member ,owner and admin . Please put this code in your code. ` func GetMemembersofGroup(jidofRoom:String) { let iq = DDXMLElement.element(withName: "iq") as! DDXMLElement iq.addAttribute(withName: "to", stringValue: jidofRoom) iq.addAttribute(withName: "id", stringValue: generateBoundaryString()) iq.addAttribute(withName: "type", stringValue: "get")
let query = DDXMLElement.element(withName: "query") as! DDXMLElement
query.addAttribute(withName: "xmlns", stringValue: "http://jabber.org/protocol/muc#admin")
let item = DDXMLElement.element(withName: "item") as! DDXMLElement
item.addAttribute(withName: "affiliation", stringValue: "member")
// item.addAttribute(withName: "role", stringValue: "moderator")
// let item1 = DDXMLElement.element(withName: "item") as! DDXMLElement
// item1.addAttribute(withName: "affiliation", stringValue: "owner")
//
// let item2 = DDXMLElement.element(withName: "item") as! DDXMLElement
// item2.addAttribute(withName: "affiliation", stringValue: "admin")
query.addChild(item)
// query.addChild(item1)
// query.addChild(item2)
iq.addChild(query)
self.xmppStream?.send(iq)
self.getOwnerofGroup(Roomjid: jidofRoom)
}
func getOwnerofGroup(Roomjid:String)
{
let iq = DDXMLElement.element(withName: "iq") as! DDXMLElement
iq.addAttribute(withName: "to", stringValue: Roomjid)
iq.addAttribute(withName: "id", stringValue: generateBoundaryString())
iq.addAttribute(withName: "type", stringValue: "get")
let query = DDXMLElement.element(withName: "query") as! DDXMLElement
query.addAttribute(withName: "xmlns", stringValue: "http://jabber.org/protocol/muc#admin")
let item = DDXMLElement.element(withName: "item") as! DDXMLElement
item.addAttribute(withName: "affiliation", stringValue: "owner")
query.addChild(item)
iq.addChild(query)
self.xmppStream?.send(iq)
self.getAdminofGroup(jidofRoom: Roomjid )
}
func getAdminofGroup(jidofRoom:String)
{
let iq = DDXMLElement.element(withName: "iq") as! DDXMLElement
iq.addAttribute(withName: "to", stringValue: jidofRoom)
iq.addAttribute(withName: "id", stringValue: generateBoundaryString())
iq.addAttribute(withName: "type", stringValue: "get")
let query = DDXMLElement.element(withName: "query") as! DDXMLElement
query.addAttribute(withName: "xmlns", stringValue: "http://jabber.org/protocol/muc#admin")
let item = DDXMLElement.element(withName: "item") as! DDXMLElement
item.addAttribute(withName: "affiliation", stringValue: "admin")
query.addChild(item)
iq.addChild(query)
self.xmppStream?.send(iq)
}`
GetMemembersofGroup() func called after Group connect.
if any query then let us know.
thank you
Hi all,
Can anyone share the full code for MUC with Openfire server?
Hello jaiminadon, Can you please give me detail answer or explanation?
Hello shraddha-patel-1891, Tell me one thing you implement MUCSUB functionality and subscribe user according to "https://docs.ejabberd.im/developer/xmpp-clients-bots/proposed-extensions/muc-sub/" this documents? Because we used that method for remove member form group.
Hello hardik, i have not used MUCSUB but i have used xmpp default room methods.have you any solution related to this then please help me. thank you.
yes when ever you remove any member form particular room you need to pass one message into group with different subject like "Leave room".
Now all group member get this message and remove that member from their local DB.
And admin can set affiliation none for that member.
Below is the sample code for set affiliation.
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/muc#admin"];
NSXMLElement *item = [NSXMLElement elementWithName:@"item"];
[item addAttributeWithName:@"affiliation" stringValue:@"none"];
[item addAttributeWithName:@"jid" stringValue:"Member JID"];
[query addChild:item];
XMPPIQ *RemoveUser = [[XMPPIQ alloc] initWithType:@"set" to:[XMPPJID jidWithString:[Utils ReceiverJabberd]] elementID:@"XYZ" child:query ];
[xmppStream sendElement:RemoveUser];
And i think if you not used MUCSUB then offline message also not displaying.
Thank you, Hardik for replay. yes, Hardik not get an offline message in a group, in Group message display after connecting group. we have lots of problem in group chat and Also not get a push notification when user not online. First, i referred chat secure code but in this so many things.So now I developed an app for a sketch.
Thank you.
Yess,
Use MUCSUB protocol all problems for group almost resolved.
and for push notification i already answer.
Thank you hardik
Hi All,
am trying to implement delete group feature for Openfire MUC with XMPPFramework, so please can anyone share the implementation code for delete group and if delete the group how other group members will get to know about group delete.
Hi Shravanteegala,
can you please share your group chats development code...
@shraddha-patel-1891 Hi, did you worked on Multicasting for sending one message to all of your roster contacts if you did please give me some idea?
@reddydayakar06 Before deleting the group just send one message to all of the group members to group deleting message
After that, you can execute the following code
XMPPJID roomJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.*****.com",self.groupJID]]; XMPPRoomCoreDataStorage *roomMemory=[JRXMPPTool sharedInstance].xmppRoomCoreDataStorage; XMPPRoom *room1 = [[XMPPRoom alloc] initWithRoomStorage:roomMemory jid:roomJID dispatchQueue:dispatch_get_main_queue()]; [room1 activate:[JRXMPPTool sharedInstance].xmppStream]; [room1 destroyRoom]; [room1 deactivate]; [room1 removeDelegate:self]; room1 = nil;
Note : Only Admin can delete the group
@HardikKardani I am using above code in my chat application it's working well. can you tell me is there any other way to delete the MUC Group or what is the problem if I use the above code?
@HardikKardani Hello, we have used mod_sub and how to create a group and invite member in the group? please share code snippet or doc link. if possible share it quickly because its urgent for me. Thank you
@shraddha-patel-1891
You have to create group using XMPPRoom after creating group just subscribe it for MUC_SUB.
@HardikKardani Thank you for the reply, I add below the line for subscribing :
Constants.appDelegate.xmppMucSub?.supported(by:Constants.appDelegate.xmppRoom!)
after that called muc_sub delegate method : func xmppMUCSub(_ sender: XMPPMUCSub, serviceSupportedBy room: XMPPJID) { print("service supported by room-->(room) sender iss-->(sender)") xmppMucSub?.subscribe(to: room, nick: xmppStream?.myJID?.full, password: nil)
}
Now how to join a room and start sending and receiving the message. Also how to fetch room history?
I refer below link for join muc room but not successful.
https://xmpp.org/extensions/xep-0045.html#enter-muc
You have any idea then please help me.
@shraddha-patel-1891
Need More description like you implement muc_sub delegate methods or not? and implement xmpp room delegate method or not?
@HardikKardani Yes i implement all muc_sub delegates and all xmpp Room delegate.
@shraddha-patel-1891
If you implement all delegate methods then i think after creating room you just have to invite other members and sorry but i think here i can't explain you all logic properly. You can directly share your sample code so i will check it
@HardikKardani thanks for the reply first I will try my self if not done then I will share my code.
@HardikKardani Hello Hardik , I fetch chat history using following code but not get.
`
let iQ = DDXMLElement.element(withName: "iq") as! DDXMLElement
iQ.addAttribute(withName: "type", stringValue: "set")
iQ.addAttribute(withName: "id", stringValue: generateBoundaryString())
let query = DDXMLElement.element(withName: "query") as! DDXMLElement
query.addAttribute(withName: "xmlns", stringValue: "urn:xmpp:mam:2")
query.addAttribute(withName: "queryid", stringValue: "c8u20eaatt")
let x = DDXMLElement.element(withName: "x") as! DDXMLElement
x.addAttribute(withName: "xmlns", stringValue: "jabber:x:data")
x.addAttribute(withName: "type", stringValue: "submit")
let field = DDXMLElement.element(withName: "field") as! DDXMLElement
field.addAttribute(withName: "var", stringValue: "FORM_TYPE")
field.addAttribute(withName: "type", stringValue: "hidden")
let value = DDXMLElement.element(withName: "value") as! DDXMLElement
value.stringValue = "urn:xmpp:mam:2"
field.addChild(value)
let field1 = DDXMLElement.element(withName: "field") as! DDXMLElement
field1.addAttribute(withName: "var", stringValue: "with")
let value1 = DDXMLElement.element(withName: "value") as! DDXMLElement
value1.stringValue = jid
field1.addChild(value1)
let field2 = DDXMLElement.element(withName: "field") as! DDXMLElement
field2.addAttribute(withName: "var", stringValue: "end") //start
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let strdate = dateFormatter.string(from: currentDate)
let value2 = DDXMLElement.element(withName: "value") as! DDXMLElement
value2.stringValue = strdate//"2018-07-26T00:00:00.000Z"
field2.addChild(value2)
x.addChild(field)
x.addChild(field1)
x.addChild(field2)
let set = DDXMLElement.element(withName: "set") as! DDXMLElement
set.addAttribute(withName: "xmlns", stringValue: "http://jabber.org/protocol/rsm")
let max = DDXMLElement.element(withName: "max") as! DDXMLElement
max.stringValue = String(format: "%d", arguments: [maxhistorycounter])
set.addChild(max)
query.addChild(x)
query.addChild(set)
iQ.addChild(query)
self.xmppStream?.send(iQ)`
In jid passed room jid like [email protected]/91878787 can you please help me for get chat history? we are using mod_mam for fetch chat history.
Thank you
@shraddha-patel-1891
You fetch chat history for getting offline message?
@HardikKardani No I tried to fetch entire group chat history. For example, I login in android device and doing chat iosgrp after 2 3 days log out from the app or delete the app from android device and now the same login in ios device and tried to chat with iosgrp but first I required to fetch to entire room history.
@shraddha-patel-1891
I think during joining room you directly get the chat history using below code.
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage jid:roomJid dispatchQueue:dispatch_get_main_queue()];
[room activate:xmppStream];
[room addDelegate:self delegateQueue:dispatch_get_main_queue()];
NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
[history addAttributeWithName:@"maxstanzas" stringValue:@"0"]; // Set the number of history messages
[room joinRoomUsingNickname:xmppStream.myJID.user history:history]; // Password is set to empty
i used above code for getting chat history while joining room. here you can pass max and min date also but did't chat with that.
@HardikKardani thank you hardik i will check
@HardikKardani
after subscribe room every time call below method
func xmppMUCSub(_ sender: XMPPMUCSub, serviceNotSupportedBy room: XMPPJID) { print("service not supported by room-->\(room)sender is-->\(sender.description)") }
so any idea about this?
any configuration missing in room creation?
my room configuration is :
`public func xmppRoom(_ sender: XMPPRoom, didFetchConfigurationForm configForm: DDXMLElement)
{
print("didFetchConfigurationForm")
let newForm = configForm.copy() as! DDXMLElement
for field in newForm.elements(forName: "field")
{
if let _var = field.attributeStringValue(forName: "var")
{
switch _var
{
case "muc#roomconfig_persistentroom":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "muc#roomconfig_roomname":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name : "value", stringValue :groupname))
case "muc#roomconfig_publicroom":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "0"))
case "muc#roomconfig_whois":
field.removeChild(at: 0)
field.insertChild(DDXMLElement(name: "value", stringValue: "anyone"), at: 0)
case "muc#roomconfig_allow_subscription":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "muc#roomconfig_membersonly":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "muc#roomconfig_getmemberlist":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "moderator"))
field.addChild(DDXMLElement(name: "value", stringValue: "participant"))
field.addChild(DDXMLElement(name: "value", stringValue: "visitor"))
case "muc#roomconfig_moderatedroom":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "public_list":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "muc#roomconfig_allowinvites":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "1"))
case "muc#roomconfig_changesubject":
field.removeChild(at: 0)
field.addChild(DDXMLElement(name: "value", stringValue: "true"))
// other configures
default:
break
}
}
}
sender.configureRoom(usingOptions: newForm)
}`
@shraddha-patel-1891
looks like issue in your server configuration file.
@HardikKardani hello hardik ,my backend team given following .yml content for muc can you please check it and if any missing in mod_muc then please ask me.
attached.yml file
Thank you ejabberd.txt
@shraddha-patel-1891
Under mod_muc you have to set below configuration
default_room_options:
allow_subscription: true
mam: true
@HardikKardani i enable above.Now below methods called:
func xmppMUCSub(_ sender: XMPPMUCSub, didReceive message: XMPPMessage) func xmppStream(_ sender: XMPPStream, didReceive message: XMPPMessage) func xmppRoom(_ sender: XMPPRoom, didReceive message: XMPPMessage, fromOccupant occupantJID: XMPPJID)
Above 3 methods called in all 3 methods get the same message. sometimes called only 2nd method 1st and 3 rd method not called.
have you faced this kind of issue?
thank you
@shraddha-patel-1891
Now MUCSub successfully configured and works perfectly. Yes i also face same issue you have to manage it not possible to share solution here..
@HardikKardani Thank you for giving me a solution.
@HardikKardani Hello, I am using ejabberd version 16.01 and I'm only able to fetch latest 20 messages in a group chat. I also modified the ejabberd.yaml
file to have mam enabled, but still having this same issue.
Here's my ejabberd.yaml
configuration: https://gist.github.com/Vishal-sol/120f2b51c239185d84d1caf717e15c35
Hello @Vishal-sol
i am not able to see your .yaml file and for message please create new question.
Thanks.