Statistics
| Branch: | Tag: | Revision:

chatsecureios / ChatSecure / Classes / Model / Yap Storage / OTRXMPPRoomOccupant.swift @ 80684e32

History | View | Annotate | Download (6.15 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
@objc public enum RoomOccupantAffiliation:Int {
36
    case none = 0
37
    case outcast = 1
38
    case member = 2
39
    case admin = 3
40
    case owner = 4
41
    
42
    public func isOwner() -> Bool {
43
        switch self {
44
        case .owner: return true
45
        default: return false
46
        }
47
    }
48
}
49

    
50
open class OTRXMPPRoomOccupant: OTRYapDatabaseObject, YapDatabaseRelationshipNode {
51
    
52
    @objc open static let roomEdgeName = "OTRRoomOccupantEdgeName"
53
    
54
    @objc open var available = false
55
    
56
    /** This is the JID of the participant as it's known in the room i.e. baseball_chat@conference.dukgo.com/user123 */
57
    @objc open var jid:String?
58
    
59
    /** This is the name your known as in the room. Seems to be username without domain */
60
    @objc open var roomName:String?
61
    
62
    /** This is the role of the occupant in the room */
63
    @objc open var role:RoomOccupantRole = .none
64

    
65
    /** This is the affiliation of the occupant in the room */
66
    @objc open var affiliation:RoomOccupantAffiliation = .none
67

    
68
    /**When given by the server we get the room participants reall JID*/
69
    @objc open var realJID:String?
70

    
71
    @objc open var buddyUniqueId:String?
72
    @objc open var roomUniqueId:String?
73
    
74
    @objc open func avatarImage() -> UIImage {
75
        return OTRImages.avatarImage(withUniqueIdentifier: self.uniqueId, avatarData: nil, displayName: roomName ?? realJID ?? jid, username: self.realJID)
76
    }
77
    
78
    //MARK: YapDatabaseRelationshipNode Methods
79
    open func yapDatabaseRelationshipEdges() -> [YapDatabaseRelationshipEdge]? {
80
        if let roomID = self.roomUniqueId {
81
            let relationship = YapDatabaseRelationshipEdge(name: OTRXMPPRoomOccupant.roomEdgeName, sourceKey: self.uniqueId, collection: OTRXMPPRoomOccupant.collection, destinationKey: roomID, collection: OTRXMPPRoom.collection, nodeDeleteRules: YDB_NodeDeleteRules.deleteSourceIfDestinationDeleted)
82
            return [relationship]
83
        }
84
        return nil
85
    }
86
    
87
    // MARK: Helper Functions
88

    
89
    @objc open func buddy(with transaction: YapDatabaseReadTransaction) -> OTRXMPPBuddy? {
90
        if let buddyUniqueId = self.buddyUniqueId {
91
            return OTRXMPPBuddy.fetchObject(withUniqueID: buddyUniqueId, transaction: transaction)
92
        }
93
        return nil
94
    }
95
    
96
}
97

    
98
public extension OTRXMPPRoomOccupant {
99
    /**
100
     * jid is the occupant's room JID
101
     * roomJID is the JID of the room itself
102
     * realJID is only available for non-anonymous rooms
103
     * createIfNeeded=true will return a new unsaved object if it's not found
104
     */
105
    @objc public static func occupant(jid: XMPPJID,
106
                               realJID: XMPPJID?,
107
                               roomJID: XMPPJID,
108
                               accountId: String,
109
                               createIfNeeded: Bool,
110
                               transaction: YapDatabaseReadTransaction) -> OTRXMPPRoomOccupant? {
111
        guard let indexTransaction = transaction.ext(SecondaryIndexName.roomOccupants) as? YapDatabaseSecondaryIndexTransaction else {
112
            DDLogError("Error looking up OTRXMPPRoomOccupant via SecondaryIndex")
113
            return nil
114
        }
115
        let roomUniqueId = OTRXMPPRoom.createUniqueId(accountId, jid: roomJID.bare)
116
        var matchingOccupants: [OTRXMPPRoomOccupant] = []
117
        
118
        var parameters: [String] = [roomUniqueId]
119
        var queryString = "Where \(RoomOccupantIndexColumnName.roomUniqueId) == ? AND ("
120
        parameters.append(jid.full)
121
        queryString.append("\(RoomOccupantIndexColumnName.jid) == ?")
122
        if let realJID = realJID {
123
            parameters.append(realJID.bare)
124
            queryString.append(" OR \(RoomOccupantIndexColumnName.realJID) == ?")
125
        }
126
        queryString.append(")")
127
        
128
        let query = YapDatabaseQuery(string: queryString, parameters: parameters)
129
        let success = indexTransaction.enumerateKeysAndObjects(matching: query) { (collection, key, object, stop) in
130
            if let matchingOccupant = object as? OTRXMPPRoomOccupant {
131
                matchingOccupants.append(matchingOccupant)
132
            }
133
        }
134
        if !success {
135
            DDLogError("Error looking up OTRXMPPRoomOccupant with query \(query)")
136
            return nil
137
        }
138
        if matchingOccupants.count > 1 {
139
            DDLogWarn("WARN: More than one OTRXMPPRoomOccupant matching query \(query): \(matchingOccupants)")
140
        }
141
        var occupant: OTRXMPPRoomOccupant? = matchingOccupants.first
142
        var didCreate = false
143
        
144
        if occupant == nil,
145
            createIfNeeded {
146
            occupant = OTRXMPPRoomOccupant()!
147
            occupant?.jid = jid.full
148
            occupant?.realJID = realJID?.bare
149
            occupant?.roomUniqueId = roomUniqueId
150
            didCreate = true
151
        }
152
        
153
        // While we're at it, match room occupant with a buddy on our roster if possible
154
        // This should probably be moved elsewhere
155
        if let existingOccupant = occupant,
156
            let realJID = existingOccupant.realJID,
157
            let jid = XMPPJID(string: realJID),
158
            existingOccupant.buddyUniqueId == nil,
159
            let buddy = OTRXMPPBuddy.fetchBuddy(jid: jid, accountUniqueId: accountId, transaction: transaction) {
160
            if !didCreate {
161
                occupant = existingOccupant.copy() as? OTRXMPPRoomOccupant
162
            }
163
            occupant?.buddyUniqueId = buddy.uniqueId
164
        }
165
        
166
        return occupant
167
    }
168
}