From 74191bbfa4e49d95073eeee979f8fc21d68290d5 Mon Sep 17 00:00:00 2001 From: N-Pex Date: Wed, 29 Nov 2017 15:05:56 +0100 Subject: [PATCH] Get both moderators and members Also, make sure room creation happens in the right order. --- .../Controllers/XMPP/OTRXMPPRoomManager.m | 94 ++++++++++++++----- .../Controllers/XMPP/OTRXMPPRoomYapStorage.m | 22 +---- .../Yap Storage/OTRXMPPRoomOccupant.swift | 34 +++++++ 3 files changed, 105 insertions(+), 45 deletions(-) diff --git a/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomManager.m b/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomManager.m index 5ee3e11e5..0d32b56de 100644 --- a/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomManager.m +++ b/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomManager.m @@ -80,6 +80,11 @@ - (NSString *)joinRoom:(XMPPJID *)jid withNickname:(NSString *)name subject:(NSS NSString* accountId = self.xmppStream.tag; NSString *databaseRoomKey = [OTRXMPPRoom createUniqueId:accountId jid:jid.bare]; __block NSString *nickname = name; + + // Already joined? Can happen if we have auto-join bookmarks. + if (room && room.isJoined) { + return databaseRoomKey; + } if (!room) { OTRXMPPRoomYapStorage *storage = [[OTRXMPPRoomYapStorage alloc] initWithDatabaseConnection:self.databaseConnection]; @@ -356,47 +361,86 @@ - (void)xmppMUC:(XMPPMUC *)sender roomJID:(XMPPJID *)roomJID didReceiveInvitatio - (void) xmppRoom:(XMPPRoom *)room didFetchMembersList:(NSArray *)items { DDLogInfo(@"Fetched members list: %@", items); + [self xmppRoom:room addOccupantItems:items]; +} + +- (void)xmppRoom:(XMPPRoom *)room didFetchModeratorsList:(NSArray *)items { + DDLogInfo(@"Fetched moderators list: %@", items); + [self xmppRoom:room addOccupantItems:items]; +} + +- (void) xmppRoom:(XMPPRoom *)room addOccupantItems:(NSArray *)items { NSString *accountId = room.xmppStream.tag; [self.databaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) { [items enumerateObjectsUsingBlock:^(NSXMLElement *item, NSUInteger idx, BOOL * _Nonnull stop) { NSString *jidString = [item attributeStringValueForName:@"jid"]; XMPPJID *jid = [XMPPJID jidWithString:jidString]; - if (!jid) { return; } + NSString *affiliation = [item attributeStringValueForName:@"affiliation"]; + + // jid and affiliation MUST be included + if (!jid || !affiliation) { return; } + // Make sure occupant object exists/is created OTRXMPPRoomOccupant *occupant = [OTRXMPPRoomOccupant occupantWithJid:jid realJID:jid roomJID:room.roomJID accountId:accountId createIfNeeded:YES transaction:transaction]; + occupant.affiliation = [RoomOccupantAffiliationHelper affiliationWithString:affiliation]; + + // Role MAY be included, so get that if it's there + NSString *role = [item attributeStringValueForName:@"role"]; + if (role) { + occupant.role = [RoomOccupantRoleHelper roleWithString:role]; + } + [occupant saveWithTransaction:transaction]; }]; }]; } -- (void)xmppRoomDidJoin:(XMPPRoom *)sender -{ +- (void)xmppRoomDidCreate:(XMPPRoom *)sender { + [self.roomsToConfigure removeObject:sender.roomJID.bare]; + [sender fetchConfigurationForm]; +} + +- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(DDXMLElement *)configForm { + [sender configureRoomUsingOptions:[[self class] defaultRoomConfiguration]]; +} + +- (void)xmppRoom:(XMPPRoom *)sender didConfigure:(XMPPIQ *)iqResult { + //Set Room Subject + NSString *subject = [self.tempRoomSubject objectForKey:sender.roomJID.bare]; + if (subject) { + [self.tempRoomSubject removeObjectForKey:sender.roomJID.bare]; + [sender changeRoomSubject:subject]; + } + + //Invite buddies + NSArray *buddyUniqueIds = [self.inviteDictionary objectForKey:sender.roomJID.bare]; + if (buddyUniqueIds) { + [self.inviteDictionary removeObjectForKey:sender.roomJID.bare]; + [self inviteBuddies:buddyUniqueIds toRoom:sender]; + } + + // Fetch member list. Ideally this would be done after the invites above have been sent to the network, but the messages pass all kinds of async delegates before they are actually sent, so unfortunately we can't wait for that. [self performBlockAsync:^{ - //Configure room if we are the creator - if ([self.roomsToConfigure containsObject:sender.roomJID.bare]) { - [self.roomsToConfigure removeObject:sender.roomJID.bare]; - [sender configureRoomUsingOptions:[[self class] defaultRoomConfiguration]]; - - //Set Room Subject - NSString *subject = [self.tempRoomSubject objectForKey:sender.roomJID.bare]; - if (subject) { - [self.tempRoomSubject removeObjectForKey:sender.roomJID.bare]; - [sender changeRoomSubject:subject]; - } - } - - //Invite buddies - NSArray *buddyUniqueIds = [self.inviteDictionary objectForKey:sender.roomJID.bare]; - if (buddyUniqueIds) { - [self.inviteDictionary removeObjectForKey:sender.roomJID.bare]; - [self inviteBuddies:buddyUniqueIds toRoom:sender]; - } - - //Fetch member list - [sender fetchMembersList]; + [sender fetchMembersList]; + [sender fetchModeratorsList]; }]; } +- (void)xmppRoomDidJoin:(XMPPRoom *)sender +{ + // Older prosody servers have a bug where they consider all room as already + // existing, so the status 201 is never sent. + if ([self.roomsToConfigure containsObject:sender.roomJID.bare]) { + [self xmppRoomDidCreate:sender]; + } else { + // Fetch member list + [self performBlockAsync:^{ + [sender fetchMembersList]; + [sender fetchModeratorsList]; + }]; + } +} + - (void)xmppRoomDidLeave:(XMPPRoom *)sender { NSString *databaseRoomKey = [OTRXMPPRoom createUniqueId:self.xmppStream.tag jid:[sender.roomJID bare]]; [self.databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) { diff --git a/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomYapStorage.m b/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomYapStorage.m index 458cfe39d..9bde50bee 100644 --- a/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomYapStorage.m +++ b/ChatSecure/Classes/Controllers/XMPP/OTRXMPPRoomYapStorage.m @@ -195,28 +195,10 @@ - (void)handlePresence:(XMPPPresence *)presence room:(XMPPRoom *)room { occupant.roomName = [presenceJID resource]; // Role - if ([buddyRole isEqualToString:@"moderator"]) { - occupant.role = RoomOccupantRoleModerator; - } else if ([buddyRole isEqualToString:@"participant"]) { - occupant.role = RoomOccupantRoleParticipant; - } else if ([buddyRole isEqualToString:@"visitor"]) { - occupant.role = RoomOccupantRoleVisitor; - } else { - occupant.role = RoomOccupantRoleNone; - } + occupant.role = [RoomOccupantRoleHelper roleWithString:buddyRole]; // Affiliation - if ([buddyAffiliation isEqualToString:@"owner"]) { - occupant.affiliation = RoomOccupantAffiliationOwner; - } else if ([buddyAffiliation isEqualToString:@"admin"]) { - occupant.affiliation = RoomOccupantAffiliationAdmin; - } else if ([buddyAffiliation isEqualToString:@"member"]) { - occupant.affiliation = RoomOccupantAffiliationMember; - } else if ([buddyAffiliation isEqualToString:@"outcast"]) { - occupant.affiliation = RoomOccupantAffiliationOutcast; - } else { - occupant.affiliation = RoomOccupantAffiliationNone; - } + occupant.affiliation = [RoomOccupantAffiliationHelper affiliationWithString:buddyAffiliation]; [occupant saveWithTransaction:transaction]; }]; } diff --git a/ChatSecure/Classes/Model/Yap Storage/OTRXMPPRoomOccupant.swift b/ChatSecure/Classes/Model/Yap Storage/OTRXMPPRoomOccupant.swift index 28bb3d219..0b400837f 100644 --- a/ChatSecure/Classes/Model/Yap Storage/OTRXMPPRoomOccupant.swift +++ b/ChatSecure/Classes/Model/Yap Storage/OTRXMPPRoomOccupant.swift @@ -32,6 +32,22 @@ import CocoaLumberjack } } +// Helper class to create from string, callable from obj-c +@objc public class RoomOccupantRoleHelper: NSObject { + @objc public static func role(withString role:String) -> RoomOccupantRole { + switch role { + case "moderator": + return RoomOccupantRole.moderator + case "participant": + return RoomOccupantRole.participant + case "visitor": + return RoomOccupantRole.visitor + default: + return RoomOccupantRole.none + } + } +} + @objc public enum RoomOccupantAffiliation:Int { case none = 0 case outcast = 1 @@ -47,6 +63,24 @@ import CocoaLumberjack } } +// Helper class to create from string, callable from obj-c +@objc public class RoomOccupantAffiliationHelper: NSObject { + @objc public static func affiliation(withString affiliation:String) -> RoomOccupantAffiliation { + switch affiliation { + case "owner": + return RoomOccupantAffiliation.owner + case "admin": + return RoomOccupantAffiliation.admin + case "member": + return RoomOccupantAffiliation.member + case "outcast": + return RoomOccupantAffiliation.outcast + default: + return RoomOccupantAffiliation.none + } + } +} + open class OTRXMPPRoomOccupant: OTRYapDatabaseObject, YapDatabaseRelationshipNode { @objc open static let roomEdgeName = "OTRRoomOccupantEdgeName"