Statistics
| Branch: | Tag: | Revision:

chatsecureios / ChatSecure / Classes / Model / Yap Storage / OTRXMPPRoomOccupant.swift @ 74191bbf

History | View | Annotate | Download (7.26 KB)

1
//
2
//  OTRXMPPRoomOccupant.swift
3
//  ChatSecure
4
//
5
//  Created by David Chiles on 10/19/15.
6
//  Copyright © 2015 Chris Ballinger. All rights reserved.
7
//
8

    
9
import Foundation
10
import YapDatabase
11
import Mantle
12
import CocoaLumberjack
13

    
14
@objc public enum RoomOccupantRole:Int {
15
    case none = 0
16
    case participant = 1
17
    case moderator = 2
18
    case visitor = 3
19
    
20
    public func canModifySubject() -> Bool {
21
        switch self {
22
        case .moderator: return true // TODO - Check muc#roomconfig_changesubject, participants may be allowed to change subject based on config!
23
        default: return false
24
        }
25
    }
26
    
27
    public func canInviteOthers() -> Bool {
28
        switch self {
29
        case .moderator: return true // TODO - participants may be allowed
30
        default: return false
31
        }
32
    }
33
}
34

    
35
// Helper class to create from string, callable from obj-c
36
@objc public class RoomOccupantRoleHelper: NSObject {
37
    @objc public static func role(withString role:String) -> RoomOccupantRole {
38
        switch role {
39
        case "moderator":
40
            return RoomOccupantRole.moderator
41
        case "participant":
42
            return RoomOccupantRole.participant
43
        case "visitor":
44
            return RoomOccupantRole.visitor
45
        default:
46
            return RoomOccupantRole.none
47
        }
48
    }
49
}
50

    
51
@objc public enum RoomOccupantAffiliation:Int {
52
    case none = 0
53
    case outcast = 1
54
    case member = 2
55
    case admin = 3
56
    case owner = 4
57
    
58
    public func isOwner() -> Bool {
59
        switch self {
60
        case .owner: return true
61
        default: return false
62
        }
63
    }
64
}
65

    
66
// Helper class to create from string, callable from obj-c
67
@objc public class RoomOccupantAffiliationHelper: NSObject {
68
    @objc public static func affiliation(withString affiliation:String) -> RoomOccupantAffiliation {
69
        switch affiliation {
70
        case "owner":
71
            return RoomOccupantAffiliation.owner
72
        case "admin":
73
            return RoomOccupantAffiliation.admin
74
        case "member":
75
            return RoomOccupantAffiliation.member
76
        case "outcast":
77
            return RoomOccupantAffiliation.outcast
78
        default:
79
            return RoomOccupantAffiliation.none
80
        }
81
    }
82
}
83

    
84
open class OTRXMPPRoomOccupant: OTRYapDatabaseObject, YapDatabaseRelationshipNode {
85
    
86
    @objc open static let roomEdgeName = "OTRRoomOccupantEdgeName"
87
    
88
    @objc open var available = false
89
    
90
    /** This is the JID of the participant as it's known in the room i.e. baseball_chat@conference.dukgo.com/user123 */
91
    @objc open var jid:String?
92
    
93
    /** This is the name your known as in the room. Seems to be username without domain */
94
    @objc open var roomName:String?
95
    
96
    /** This is the role of the occupant in the room */
97
    @objc open var role:RoomOccupantRole = .none
98

    
99
    /** This is the affiliation of the occupant in the room */
100
    @objc open var affiliation:RoomOccupantAffiliation = .none
101

    
102
    /**When given by the server we get the room participants reall JID*/
103
    @objc open var realJID:String?
104

    
105
    @objc open var buddyUniqueId:String?
106
    @objc open var roomUniqueId:String?
107
    
108
    @objc open func avatarImage() -> UIImage {
109
        return OTRImages.avatarImage(withUniqueIdentifier: self.uniqueId, avatarData: nil, displayName: roomName ?? realJID ?? jid, username: self.realJID)
110
    }
111
    
112
    //MARK: YapDatabaseRelationshipNode Methods
113
    open func yapDatabaseRelationshipEdges() -> [YapDatabaseRelationshipEdge]? {
114
        if let roomID = self.roomUniqueId {
115
            let relationship = YapDatabaseRelationshipEdge(name: OTRXMPPRoomOccupant.roomEdgeName, sourceKey: self.uniqueId, collection: OTRXMPPRoomOccupant.collection, destinationKey: roomID, collection: OTRXMPPRoom.collection, nodeDeleteRules: YDB_NodeDeleteRules.deleteSourceIfDestinationDeleted)
116
            return [relationship]
117
        }
118
        return nil
119
    }
120
    
121
    // MARK: Helper Functions
122

    
123
    @objc open func buddy(with transaction: YapDatabaseReadTransaction) -> OTRXMPPBuddy? {
124
        if let buddyUniqueId = self.buddyUniqueId {
125
            return OTRXMPPBuddy.fetchObject(withUniqueID: buddyUniqueId, transaction: transaction)
126
        }
127
        return nil
128
    }
129
    
130
}
131

    
132
public extension OTRXMPPRoomOccupant {
133
    /**
134
     * jid is the occupant's room JID
135
     * roomJID is the JID of the room itself
136
     * realJID is only available for non-anonymous rooms
137
     * createIfNeeded=true will return a new unsaved object if it's not found
138
     */
139
    @objc public static func occupant(jid: XMPPJID,
140
                               realJID: XMPPJID?,
141
                               roomJID: XMPPJID,
142
                               accountId: String,
143
                               createIfNeeded: Bool,
144
                               transaction: YapDatabaseReadTransaction) -> OTRXMPPRoomOccupant? {
145
        guard let indexTransaction = transaction.ext(SecondaryIndexName.roomOccupants) as? YapDatabaseSecondaryIndexTransaction else {
146
            DDLogError("Error looking up OTRXMPPRoomOccupant via SecondaryIndex")
147
            return nil
148
        }
149
        let roomUniqueId = OTRXMPPRoom.createUniqueId(accountId, jid: roomJID.bare)
150
        var matchingOccupants: [OTRXMPPRoomOccupant] = []
151
        
152
        var parameters: [String] = [roomUniqueId]
153
        var queryString = "Where \(RoomOccupantIndexColumnName.roomUniqueId) == ? AND ("
154
        parameters.append(jid.full)
155
        queryString.append("\(RoomOccupantIndexColumnName.jid) == ?")
156
        if let realJID = realJID {
157
            parameters.append(realJID.bare)
158
            queryString.append(" OR \(RoomOccupantIndexColumnName.realJID) == ?")
159
        }
160
        queryString.append(")")
161
        
162
        let query = YapDatabaseQuery(string: queryString, parameters: parameters)
163
        let success = indexTransaction.enumerateKeysAndObjects(matching: query) { (collection, key, object, stop) in
164
            if let matchingOccupant = object as? OTRXMPPRoomOccupant {
165
                matchingOccupants.append(matchingOccupant)
166
            }
167
        }
168
        if !success {
169
            DDLogError("Error looking up OTRXMPPRoomOccupant with query \(query)")
170
            return nil
171
        }
172
        if matchingOccupants.count > 1 {
173
            DDLogWarn("WARN: More than one OTRXMPPRoomOccupant matching query \(query): \(matchingOccupants)")
174
        }
175
        var occupant: OTRXMPPRoomOccupant? = matchingOccupants.first
176
        var didCreate = false
177
        
178
        if occupant == nil,
179
            createIfNeeded {
180
            occupant = OTRXMPPRoomOccupant()!
181
            occupant?.jid = jid.full
182
            occupant?.realJID = realJID?.bare
183
            occupant?.roomUniqueId = roomUniqueId
184
            didCreate = true
185
        }
186
        
187
        // While we're at it, match room occupant with a buddy on our roster if possible
188
        // This should probably be moved elsewhere
189
        if let existingOccupant = occupant,
190
            let realJID = existingOccupant.realJID,
191
            let jid = XMPPJID(string: realJID),
192
            existingOccupant.buddyUniqueId == nil,
193
            let buddy = OTRXMPPBuddy.fetchBuddy(jid: jid, accountUniqueId: accountId, transaction: transaction) {
194
            if !didCreate {
195
                occupant = existingOccupant.copy() as? OTRXMPPRoomOccupant
196
            }
197
            occupant?.buddyUniqueId = buddy.uniqueId
198
        }
199
        
200
        return occupant
201
    }
202
}