// _____ _
// |_ _| |_ _ _ ___ ___ _ __ __ _
// | | | ' \| '_/ -_) -_) ' \/ _` |_
// |_| |_||_|_| \___\___|_|_|_\__,_(_)
//
// Threema iOS Client
// Copyright (c) 2018-2020 Threema GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import Foundation
class WebUpdateGroupRequest: WebAbstractMessage {
let id: Data
var members: [String]
var name: String?
var avatar: Data?
var deleteName: Bool = false
var deleteAvatar: Bool = false
var groupProxy: GroupProxy?
override init(message:WebAbstractMessage) {
let idString = message.args!["id"] as! String
id = idString.hexadecimal()!
let data = message.data as! [AnyHashable: Any?]
members = data["members"] as! [String]
name = data["name"] as? String
avatar = data["avatar"] as? Data
if data["name"] != nil {
if name == nil {
deleteName = true
}
}
if data["avatar"] != nil {
if avatar == nil {
deleteAvatar = true
} else {
let image = UIImage.init(data: avatar!)
if image!.size.width >= CGFloat(kContactImageSize) || image!.size.height >= CGFloat(kContactImageSize) {
avatar = MediaConverter.scaleImageData(to: avatar!, toMaxSize: CGFloat(kContactImageSize), useJPEG: false)
}
}
}
super.init(message: message)
}
func updateGroup(completion: @escaping () -> ()) {
ack = WebAbstractMessageAcknowledgement.init(requestId, false, nil)
DispatchQueue.main.sync {
let entityManager = EntityManager()
let conversation = entityManager.entityFetcher.conversation(forGroupId: id)
if conversation == nil {
ack!.success = false
ack!.error = "invalidGroup"
completion()
return
}
let groupProxy = GroupProxy.init(for: conversation, entityManager: entityManager)
if groupProxy == nil {
ack!.success = false
ack!.error = "invalidGroup"
completion()
return
}
self.groupProxy = groupProxy
if members.count == 0 {
ack!.success = false
ack!.error = "noMembers"
completion()
return
}
if !groupProxy!.isOwnGroup() {
ack!.success = false
ack!.error = "notAllowed"
completion()
return
}
if self.name != nil {
if self.name!.lengthOfBytes(using: .utf8) > 256 {
self.ack!.success = false
self.ack!.error = "valueTooLong"
completion()
return
}
}
var newMembers = Set()
for identity in members {
if let contact = ContactStore.shared().contact(forIdentity: identity) {
newMembers.insert(contact)
}
}
let existingMembers = groupProxy!.members as! Set
for member:Contact in existingMembers {
if !newMembers.contains(member) {
groupProxy!.adminRemoveMember(member)
}
}
for member:Contact in newMembers {
if !groupProxy!.members.contains(member) {
groupProxy!.adminAddMember(member)
}
}
if ( self.deleteName || self.name != nil ) && ( !deleteAvatar && avatar == nil ) {
entityManager.performSyncBlockAndSafe({
if self.deleteName || self.name != nil {
conversation?.groupName = self.name
}
})
if self.deleteName || self.name != nil {
DispatchQueue.main.async {
MessageSender.sendGroupRenameMessage(for: conversation, addSystemMessage: true)
}
}
self.ack!.success = true
completion()
return
} else {
let sender = GroupPhotoSender.init()
sender.start(withImageData: self.avatar, in: conversation, toMember: nil, onCompletion: {
entityManager.performSyncBlockAndSafe({
if self.deleteName || self.name != nil {
conversation?.groupName = self.name
}
if conversation?.groupImage != nil {
entityManager.entityDestroyer.deleteObject(object: conversation!.groupImage!)
conversation?.groupImage = nil
}
let dbImage = entityManager.entityCreator.imageData()
dbImage?.data = self.avatar
conversation?.groupImage = dbImage
})
if self.deleteName || self.name != nil {
DispatchQueue.main.async {
MessageSender.sendGroupRenameMessage(for: conversation, addSystemMessage: true)
}
}
self.ack!.success = true
completion()
return
}, onError: { (theError) in
self.ack!.success = false
self.ack!.error = "internalError"
completion()
return
})
}
}
}
}