import Foundation import Postbox import SwiftSignalKit import TelegramApi import MtProtoKit import SyncCore public func reportPeer(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId) { if let peer = peer as? TelegramSecretChat { return account.network.request(Api.functions.messages.reportEncryptedSpam(peer: Api.InputEncryptedChat.inputEncryptedChat(chatId: peer.id.id, accessHash: peer.accessHash))) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) } |> mapToSignal { result -> Signal in return account.postbox.transaction { transaction -> Void in if result != nil { transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in if let current = current as? CachedUserData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedGroupData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedChannelData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else { return current } }) } } } } else if let inputPeer = apiInputPeer(peer) { return account.network.request(Api.functions.messages.reportSpam(peer: inputPeer)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) } |> mapToSignal { result -> Signal in return account.postbox.transaction { transaction -> Void in if result != nil { transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in if let current = current as? CachedUserData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedGroupData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedChannelData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else { return current } }) } } } } else { return .complete() } } else { return .complete() } } |> switchToLatest } public enum ReportReason: Equatable { case spam case fake case violence case porno case childAbuse case copyright case irrelevantLocation case custom } private extension ReportReason { var apiReason: Api.ReportReason { switch self { case .spam: return .inputReportReasonSpam case .fake: return .inputReportReasonFake case .violence: return .inputReportReasonViolence case .porno: return .inputReportReasonPornography case .childAbuse: return .inputReportReasonChildAbuse case .copyright: return .inputReportReasonCopyright case .irrelevantLocation: return .inputReportReasonGeoIrrelevant case let .custom: return .inputReportReasonOther } } } public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { return account.network.request(Api.functions.account.reportPeer(peer: inputPeer, reason: reason.apiReason, message: message)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { _ -> Signal in return .complete() } } else { return .complete() } } |> switchToLatest } public func reportPeerMessages(account: Account, messageIds: [MessageId], reason: ReportReason, message: String) -> Signal { return account.postbox.transaction { transaction -> Signal in let groupedIds = messagesIdsGroupedByPeerId(messageIds) let signals = groupedIds.values.compactMap { ids -> Signal? in guard let peerId = ids.first?.peerId, let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else { return nil } return account.network.request(Api.functions.messages.report(peer: inputPeer, id: ids.map { $0.id }, reason: reason.apiReason, message: message)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { _ -> Signal in return .complete() } } return combineLatest(signals) |> mapToSignal { _ -> Signal in return .complete() } } |> switchToLatest } public func reportSupergroupPeer(account: Account, peerId: PeerId, memberId: PeerId, messageIds: [MessageId]) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputChannel(peer), let memberPeer = transaction.getPeer(memberId), let inputMember = apiInputUser(memberPeer) { return account.network.request(Api.functions.channels.reportSpam(channel: inputPeer, userId: inputMember, id: messageIds.map({$0.id}))) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { _ -> Signal in return .complete() } } else { return .complete() } } |> switchToLatest } public func dismissPeerStatusOptions(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in if let current = current as? CachedUserData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(PeerStatusSettings(flags: [])) } else if let current = current as? CachedGroupData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedChannelData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else if let current = current as? CachedSecretChatData { var peerStatusSettings = current.peerStatusSettings ?? PeerStatusSettings() peerStatusSettings.flags = [] return current.withUpdatedPeerStatusSettings(peerStatusSettings) } else { return current } }) if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { return account.network.request(Api.functions.messages.hidePeerSettingsBar(peer: inputPeer)) |> `catch` { _ -> Signal in return .single(.boolFalse) } |> mapToSignal { _ -> Signal in return .complete() } } else { return .complete() } } |> switchToLatest } public func reportRepliesMessage(account: Account, messageId: MessageId, deleteMessage: Bool, deleteHistory: Bool, reportSpam: Bool) -> Signal { if messageId.namespace != Namespaces.Message.Cloud { return .complete() } var flags: Int32 = 0 if deleteMessage { flags |= 1 << 0 } if deleteHistory { flags |= 1 << 1 } if reportSpam { flags |= 1 << 2 } return account.network.request(Api.functions.contacts.blockFromReplies(flags: flags, msgId: messageId.id)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) } |> mapToSignal { updates -> Signal in if let updates = updates { account.stateManager.addUpdates(updates) } return .complete() } }