From 28dbbddea20455ad06177d6245dacbe1446be3a3 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 25 Feb 2017 20:33:35 +0300 Subject: [PATCH] no message --- TelegramCore.xcodeproj/project.pbxproj | 18 ++ TelegramCore/AccountViewTracker.swift | 2 +- TelegramCore/AddPeerMember.swift | 2 +- TelegramCore/BlockedPeers.swift | 45 ++++ TelegramCore/CachedChannelData.swift | 108 +++++--- TelegramCore/CachedGroupData.swift | 53 ++-- TelegramCore/CachedUserData.swift | 59 +++-- TelegramCore/PeerReportStatus.swift | 8 + TelegramCore/RemovePeerMember.swift | 3 +- TelegramCore/ReportPeer.swift | 47 ++++ .../UpdateCachedChannelParticipants.swift | 37 --- TelegramCore/UpdateCachedPeerData.swift | 244 ++++++++++++++---- 12 files changed, 455 insertions(+), 171 deletions(-) create mode 100644 TelegramCore/BlockedPeers.swift create mode 100644 TelegramCore/PeerReportStatus.swift create mode 100644 TelegramCore/ReportPeer.swift diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index a335e56d69..a999a2f534 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -66,6 +66,12 @@ D02ABC841E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC831E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift */; }; D02ABC851E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC831E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift */; }; D03121021DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */; }; + D033FEB01E61EB0200644997 /* PeerReportStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEAF1E61EB0200644997 /* PeerReportStatus.swift */; }; + D033FEB11E61EB0200644997 /* PeerReportStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEAF1E61EB0200644997 /* PeerReportStatus.swift */; }; + D033FEB31E61F3C000644997 /* ReportPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB21E61F3C000644997 /* ReportPeer.swift */; }; + D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB21E61F3C000644997 /* ReportPeer.swift */; }; + D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB51E61F3F900644997 /* BlockedPeers.swift */; }; + D033FEB71E61F3F900644997 /* BlockedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB51E61F3F900644997 /* BlockedPeers.swift */; }; D03B0CB91D62233400955575 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CB81D62233400955575 /* Either.swift */; }; D03B0CBB1D62233C00955575 /* MergeLists.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBA1D62233C00955575 /* MergeLists.swift */; }; D03B0CBD1D62234300955575 /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBC1D62234300955575 /* Regex.swift */; }; @@ -431,6 +437,9 @@ D02ABC801E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedCloudChatRemoveMessagesOperations.swift; sourceTree = ""; }; D02ABC831E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizePinnedCloudChatsOperations.swift; sourceTree = ""; }; D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramPeerNotificationSettings.swift; sourceTree = ""; }; + D033FEAF1E61EB0200644997 /* PeerReportStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerReportStatus.swift; sourceTree = ""; }; + D033FEB21E61F3C000644997 /* ReportPeer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReportPeer.swift; sourceTree = ""; }; + D033FEB51E61F3F900644997 /* BlockedPeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockedPeers.swift; sourceTree = ""; }; D03B0CB81D62233400955575 /* Either.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Either.swift; sourceTree = ""; }; D03B0CBA1D62233C00955575 /* MergeLists.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergeLists.swift; sourceTree = ""; }; D03B0CBC1D62234300955575 /* Regex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = ""; }; @@ -778,6 +787,7 @@ D0B843841DA6EDC4005F29E1 /* CachedChannelData.swift */, D0B844521DAC0773005F29E1 /* TelegramUserPresence.swift */, D00D97C61E32901700E5C2B6 /* PeerInputActivity.swift */, + D033FEAF1E61EB0200644997 /* PeerReportStatus.swift */, ); name = Peers; sourceTree = ""; @@ -1069,6 +1079,8 @@ D0E305A91E5BA02D00D7A3A2 /* ChannelBlacklist.swift */, D0E305A61E5B5CBE00D7A3A2 /* PeerAdmins.swift */, D0613FD61E606B3B00202CDB /* ConvertGroupToSupergroup.swift */, + D033FEB21E61F3C000644997 /* ReportPeer.swift */, + D033FEB51E61F3F900644997 /* BlockedPeers.swift */, ); name = Peers; sourceTree = ""; @@ -1278,6 +1290,7 @@ D0FA8BB01E1FEC7E001E855B /* SecretChatEncryptionConfig.swift in Sources */, D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */, D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */, + D033FEB01E61EB0200644997 /* PeerReportStatus.swift in Sources */, D050F2511E4A59C200988324 /* JoinLink.swift in Sources */, D07827C91E02F59C00071108 /* InstantPage.swift in Sources */, D07827CB1E02F5B200071108 /* RichText.swift in Sources */, @@ -1375,6 +1388,7 @@ D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */, D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */, D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */, + D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */, D00C7CCC1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */, D09BB6B41DB02C2B00A905C0 /* PendingMessageManager.swift in Sources */, D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */, @@ -1419,6 +1433,7 @@ D02ABC841E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift in Sources */, D03B0CD71D62245300955575 /* TelegramGroup.swift in Sources */, D0B8438C1DA7CF50005F29E1 /* BotInfo.swift in Sources */, + D033FEB31E61F3C000644997 /* ReportPeer.swift in Sources */, D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */, D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */, D03B0CE21D62249B00955575 /* InlineBotMessageAttribute.swift in Sources */, @@ -1465,6 +1480,7 @@ C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */, D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */, D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */, + D033FEB11E61EB0200644997 /* PeerReportStatus.swift in Sources */, D050F26C1E4A5B6D00988324 /* UpdatePeers.swift in Sources */, D050F26D1E4A5B6D00988324 /* CreateGroup.swift in Sources */, D050F26E1E4A5B6D00988324 /* RemovePeerChat.swift in Sources */, @@ -1562,6 +1578,7 @@ D0DC35521DE36908000195EB /* ChatContextResult.swift in Sources */, D0F7AB301DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */, D073CE6D1DCBCF17007511FD /* InlineBotMessageAttribute.swift in Sources */, + D033FEB71E61F3F900644997 /* BlockedPeers.swift in Sources */, D0448C9A1E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */, D050F2611E4A5AE700988324 /* PrivacySettings.swift in Sources */, D0B8440F1DAB91CD005F29E1 /* Either.swift in Sources */, @@ -1606,6 +1623,7 @@ D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */, D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */, D0FA8BBA1E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */, + D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */, D0FA8BAE1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */, D0FA8BB41E201B02001E855B /* ProcessSecretChatIncomingEncryptedOperations.swift in Sources */, D0B844101DAB91CD005F29E1 /* MergeLists.swift in Sources */, diff --git a/TelegramCore/AccountViewTracker.swift b/TelegramCore/AccountViewTracker.swift index a72323b3d6..35fe72cb49 100644 --- a/TelegramCore/AccountViewTracker.swift +++ b/TelegramCore/AccountViewTracker.swift @@ -231,7 +231,7 @@ public final class AccountViewTracker { if dataUpdated { if let account = self.account { - context.disposable.set(fetchAndUpdateCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox).start()) + context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), fetchAndUpdateCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox)).start()) } } } diff --git a/TelegramCore/AddPeerMember.swift b/TelegramCore/AddPeerMember.swift index e7a0ef9844..a27b9f6207 100644 --- a/TelegramCore/AddPeerMember.swift +++ b/TelegramCore/AddPeerMember.swift @@ -38,7 +38,7 @@ public func addPeerMember(account: Account, peerId: PeerId, memberId: PeerId) -> if !found { updatedParticipants.append(.member(id: memberId, invitedBy: account.peerId, invitedAt: timestamp)) } - return CachedGroupData(participants: CachedGroupParticipants(participants: updatedParticipants, version: participants.version), exportedInvitation: cachedData.exportedInvitation, botInfos: cachedData.botInfos) + return cachedData.withUpdatedParticipants(CachedGroupParticipants(participants: updatedParticipants, version: participants.version)) } else { return cachedData } diff --git a/TelegramCore/BlockedPeers.swift b/TelegramCore/BlockedPeers.swift new file mode 100644 index 0000000000..6c67b76df3 --- /dev/null +++ b/TelegramCore/BlockedPeers.swift @@ -0,0 +1,45 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +public func requestUpdatePeerIsBlocked(account: Account, peerId: PeerId, isBlocked: Bool) -> Signal { + return account.postbox.modify { modifier -> Signal in + if let peer = modifier.getPeer(peerId), let inputUser = apiInputUser(peer) { + let signal: Signal + if isBlocked { + signal = account.network.request(Api.functions.contacts.block(id: inputUser)) + } else { + signal = account.network.request(Api.functions.contacts.unblock(id: inputUser)) + } + return signal + |> map { Optional($0) } + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { result -> Signal in + return account.postbox.modify { modifier -> Void in + if result != nil { + modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in + let previous: CachedUserData + if let current = current as? CachedUserData { + previous = current + } else { + previous = CachedUserData() + } + return previous.withUpdatedIsBlocked(isBlocked) + }) + } + } + } + } else { + return .complete() + } + } |> switchToLatest +} diff --git a/TelegramCore/CachedChannelData.swift b/TelegramCore/CachedChannelData.swift index 936206f790..ba377d7bf4 100644 --- a/TelegramCore/CachedChannelData.swift +++ b/TelegramCore/CachedChannelData.swift @@ -91,16 +91,32 @@ public final class CachedChannelData: CachedPeerData { public let exportedInvitation: ExportedInvitation? public let botInfos: [CachedPeerBotInfo] public let topParticipants: CachedChannelParticipants? + public let reportStatus: PeerReportStatus + public let pinnedMessageId: MessageId? public let peerIds: Set - init(flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], topParticipants: CachedChannelParticipants?) { + init() { + self.flags = [] + self.about = nil + self.participantsSummary = CachedChannelParticipantsSummary(memberCount: nil, adminCount: nil, bannedCount: nil) + self.exportedInvitation = nil + self.botInfos = [] + self.topParticipants = nil + self.reportStatus = .unknown + self.pinnedMessageId = nil + self.peerIds = Set() + } + + init(flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], topParticipants: CachedChannelParticipants?, reportStatus: PeerReportStatus, pinnedMessageId: MessageId?) { self.flags = flags self.about = about self.participantsSummary = participantsSummary self.exportedInvitation = exportedInvitation self.botInfos = botInfos self.topParticipants = topParticipants + self.reportStatus = reportStatus + self.pinnedMessageId = pinnedMessageId var peerIds = Set() if let topParticipants = topParticipants { @@ -114,12 +130,36 @@ public final class CachedChannelData: CachedPeerData { self.peerIds = peerIds } - func withUpdatedTopParticipants(_ topParticipants: CachedChannelParticipants?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: topParticipants) + func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData { + return CachedChannelData(flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedAbout(_ about: String?) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) } func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedTopParticipants(_ topParticipants: CachedChannelParticipants?) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedReportStatus(_ reportStatus: PeerReportStatus) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: reportStatus, pinnedMessageId: self.pinnedMessageId) + } + + func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: pinnedMessageId) } public init(decoder: Decoder) { @@ -130,6 +170,13 @@ public final class CachedChannelData: CachedPeerData { self.botInfos = decoder.decodeObjectArrayWithDecoderForKey("b") as [CachedPeerBotInfo] var peerIds = Set() self.topParticipants = decoder.decodeObjectForKey("p", decoder: { CachedChannelParticipants(decoder: $0) }) as? CachedChannelParticipants + self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))! + if let pinnedMessagePeerId = (decoder.decodeInt64ForKey("pm.p") as Int64?), let pinnedMessageNamespace = (decoder.decodeInt32ForKey("pm.n") as Int32?), let pinnedMessageId = (decoder.decodeInt32ForKey("pm.i") as Int32?) { + self.pinnedMessageId = MessageId(peerId: PeerId(pinnedMessagePeerId), namespace: pinnedMessageNamespace, id: pinnedMessageId) + } else { + self.pinnedMessageId = nil + } + if let topParticipants = self.topParticipants { for participant in topParticipants.participants { peerIds.insert(participant.peerId) @@ -161,6 +208,16 @@ public final class CachedChannelData: CachedPeerData { } else { encoder.encodeNil(forKey: "p") } + encoder.encodeInt32(self.reportStatus.rawValue, forKey: "r") + if let pinnedMessageId = self.pinnedMessageId { + encoder.encodeInt64(pinnedMessageId.peerId.toInt64(), forKey: "pm.p") + encoder.encodeInt32(pinnedMessageId.namespace, forKey: "pm.n") + encoder.encodeInt32(pinnedMessageId.id, forKey: "pm.i") + } else { + encoder.encodeNil(forKey: "pm.p") + encoder.encodeNil(forKey: "pm.n") + encoder.encodeNil(forKey: "pm.i") + } } public func isEqual(to: CachedPeerData) -> Bool { @@ -192,41 +249,14 @@ public final class CachedChannelData: CachedPeerData { return false } + if other.reportStatus != self.reportStatus { + return false + } + + if other.pinnedMessageId != self.pinnedMessageId { + return false + } + return true } - - func withUpdatedAbout(_ about: String?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants) - } - - func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants) - } -} - -extension CachedChannelData { - convenience init?(apiChatFull: Api.ChatFull) { - switch apiChatFull { - case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, _, pinnedMsgId): - var channelFlags = CachedChannelFlags() - if (flags & (1 << 3)) != 0 { - channelFlags.insert(.canDisplayParticipants) - } - if (flags & (1 << 6)) != 0 { - channelFlags.insert(.canChangeUsername) - } - var botInfos: [CachedPeerBotInfo] = [] - for botInfo in apiBotInfos { - switch botInfo { - case let .botInfo(userId, _, _): - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) - let parsedBotInfo = BotInfo(apiBotInfo: botInfo) - botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) - } - } - self.init(flags: channelFlags, about: about, participantsSummary: CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: kickedCount), exportedInvitation: ExportedInvitation(apiExportedInvite: apiExportedInvite), botInfos: botInfos, topParticipants: nil) - case .chatFull: - return nil - } - } } diff --git a/TelegramCore/CachedGroupData.swift b/TelegramCore/CachedGroupData.swift index 9afe5de4e2..50f06d805b 100644 --- a/TelegramCore/CachedGroupData.swift +++ b/TelegramCore/CachedGroupData.swift @@ -33,13 +33,24 @@ public final class CachedGroupData: CachedPeerData { public let participants: CachedGroupParticipants? public let exportedInvitation: ExportedInvitation? public let botInfos: [CachedPeerBotInfo] + public let reportStatus: PeerReportStatus public let peerIds: Set - public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo]) { + init() { + self.participants = nil + self.exportedInvitation = nil + self.botInfos = [] + self.reportStatus = .unknown + self.peerIds = Set() + } + + public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], reportStatus: PeerReportStatus) { self.participants = participants self.exportedInvitation = exportedInvitation self.botInfos = botInfos + self.reportStatus = reportStatus + var peerIds = Set() if let participants = participants { for participant in participants.participants { @@ -57,6 +68,8 @@ public final class CachedGroupData: CachedPeerData { self.participants = participants self.exportedInvitation = decoder.decodeObjectForKey("i", decoder: { ExportedInvitation(decoder: $0) }) as? ExportedInvitation self.botInfos = decoder.decodeObjectArrayWithDecoderForKey("b") as [CachedPeerBotInfo] + self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))! + var peerIds = Set() if let participants = participants { for participant in participants.participants { @@ -82,6 +95,7 @@ public final class CachedGroupData: CachedPeerData { encoder.encodeNil(forKey: "i") } encoder.encodeObjectArray(self.botInfos, forKey: "b") + encoder.encodeInt32(self.reportStatus.rawValue, forKey: "r") } public func isEqual(to: CachedPeerData) -> Bool { @@ -89,31 +103,22 @@ public final class CachedGroupData: CachedPeerData { return false } - return self.participants == other.participants && self.exportedInvitation == other.exportedInvitation && self.botInfos == other.botInfos + return self.participants == other.participants && self.exportedInvitation == other.exportedInvitation && self.botInfos == other.botInfos && self.reportStatus == other.reportStatus + } + + func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData { + return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, reportStatus: self.reportStatus) } func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedGroupData { - return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos) - } -} - -extension CachedGroupData { - convenience init?(apiChatFull: Api.ChatFull) { - switch apiChatFull { - case let .chatFull(_, apiParticipants, _, _, apiExportedInvite, apiBotInfos): - var botInfos: [CachedPeerBotInfo] = [] - for botInfo in apiBotInfos { - switch botInfo { - case let .botInfo(userId, _, _): - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) - let parsedBotInfo = BotInfo(apiBotInfo: botInfo) - botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) - } - } - self.init(participants: CachedGroupParticipants(apiParticipants: apiParticipants), exportedInvitation: ExportedInvitation(apiExportedInvite: apiExportedInvite), botInfos: botInfos) - break - case .channelFull: - return nil - } + return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, reportStatus: self.reportStatus) + } + + func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedGroupData { + return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, reportStatus: self.reportStatus) + } + + func withUpdatedReportStatus(_ reportStatus: PeerReportStatus) -> CachedGroupData { + return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, reportStatus: reportStatus) } } diff --git a/TelegramCore/CachedUserData.swift b/TelegramCore/CachedUserData.swift index 19ad6a3b69..f3b6fe2782 100644 --- a/TelegramCore/CachedUserData.swift +++ b/TelegramCore/CachedUserData.swift @@ -8,17 +8,34 @@ import Foundation public final class CachedUserData: CachedPeerData { public let about: String? public let botInfo: BotInfo? + public let reportStatus: PeerReportStatus + public let isBlocked: Bool + public let commonGroupCount: Int32 public let peerIds = Set() - init(about: String?, botInfo: BotInfo?) { + init() { + self.about = nil + self.botInfo = nil + self.reportStatus = .unknown + self.isBlocked = false + self.commonGroupCount = 0 + } + + init(about: String?, botInfo: BotInfo?, reportStatus: PeerReportStatus, isBlocked: Bool, commonGroupCount: Int32) { self.about = about self.botInfo = botInfo + self.reportStatus = reportStatus + self.isBlocked = isBlocked + self.commonGroupCount = commonGroupCount } public init(decoder: Decoder) { self.about = decoder.decodeStringForKey("a") self.botInfo = decoder.decodeObjectForKey("bi") as? BotInfo + self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))! + self.isBlocked = decoder.decodeInt32ForKey("b") != 0 + self.commonGroupCount = decoder.decodeInt32ForKey("cg") } public func encode(_ encoder: Encoder) { @@ -32,6 +49,9 @@ public final class CachedUserData: CachedPeerData { } else { encoder.encodeNil(forKey: "bi") } + encoder.encodeInt32(self.reportStatus.rawValue, forKey: "r") + encoder.encodeInt32(self.isBlocked ? 1 : 0, forKey: "b") + encoder.encodeInt32(self.commonGroupCount, forKey: "cg") } public func isEqual(to: CachedPeerData) -> Bool { @@ -39,21 +59,26 @@ public final class CachedUserData: CachedPeerData { return false } - return other.about == self.about && other.botInfo == self.botInfo - } -} - -extension CachedUserData { - convenience init(apiUserFull: Api.UserFull) { - switch apiUserFull { - case let .userFull(_, _, about, _, _, _, apiBotInfo, commonChatsCount): - let botInfo: BotInfo? - if let apiBotInfo = apiBotInfo { - botInfo = BotInfo(apiBotInfo: apiBotInfo) - } else { - botInfo = nil - } - self.init(about: about, botInfo: botInfo) - } + return other.about == self.about && other.botInfo == self.botInfo && self.reportStatus == other.reportStatus && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount + } + + func withUpdatedAbout(_ about: String?) -> CachedUserData { + return CachedUserData(about: about, botInfo: self.botInfo, reportStatus: self.reportStatus, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount) + } + + func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: botInfo, reportStatus: self.reportStatus, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount) + } + + func withUpdatedReportStatus(_ reportStatus: PeerReportStatus) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, reportStatus: reportStatus, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount) + } + + func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, reportStatus: self.reportStatus, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount) + } + + func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, reportStatus: self.reportStatus, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount) } } diff --git a/TelegramCore/PeerReportStatus.swift b/TelegramCore/PeerReportStatus.swift new file mode 100644 index 0000000000..77d8d8ceb6 --- /dev/null +++ b/TelegramCore/PeerReportStatus.swift @@ -0,0 +1,8 @@ +import Foundation + +public enum PeerReportStatus: Int32 { + case unknown + case none + case canReport + case didReport +} diff --git a/TelegramCore/RemovePeerMember.swift b/TelegramCore/RemovePeerMember.swift index da53f8386a..4310b3ba18 100644 --- a/TelegramCore/RemovePeerMember.swift +++ b/TelegramCore/RemovePeerMember.swift @@ -33,7 +33,8 @@ public func removePeerMember(account: Account, peerId: PeerId, memberId: PeerId) break } } - return CachedGroupData(participants: CachedGroupParticipants(participants: updatedParticipants, version: participants.version), exportedInvitation: cachedData.exportedInvitation, botInfos: cachedData.botInfos) + + return cachedData.withUpdatedParticipants(CachedGroupParticipants(participants: updatedParticipants, version: participants.version)) } else { return cachedData } diff --git a/TelegramCore/ReportPeer.swift b/TelegramCore/ReportPeer.swift new file mode 100644 index 0000000000..809e6b884e --- /dev/null +++ b/TelegramCore/ReportPeer.swift @@ -0,0 +1,47 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +public func reportPeer(account: Account, peerId: PeerId) -> Signal { + return account.postbox.modify { modifier -> Signal in + if let peer = modifier.getPeer(peerId) { + if let _ = peer as? TelegramSecretChat { + return .complete() + } else if let inputPeer = apiInputPeer(peer) { + return account.network.request(Api.functions.messages.reportSpam(peer: inputPeer)) + |> map { Optional($0) } + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { result -> Signal in + return account.postbox.modify { modifier -> Void in + if result != nil { + modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in + if let current = current as? CachedUserData { + return current.withUpdatedReportStatus(.didReport) + } else if let current = current as? CachedGroupData { + return current.withUpdatedReportStatus(.didReport) + } else if let current = current as? CachedChannelData { + return current.withUpdatedReportStatus(.didReport) + } else { + return current + } + }) + } + } + } + } else { + return .complete() + } + } else { + return .complete() + } + } |> switchToLatest +} diff --git a/TelegramCore/UpdateCachedChannelParticipants.swift b/TelegramCore/UpdateCachedChannelParticipants.swift index 2e0a7e1fd4..2c6da02b30 100644 --- a/TelegramCore/UpdateCachedChannelParticipants.swift +++ b/TelegramCore/UpdateCachedChannelParticipants.swift @@ -42,47 +42,10 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: } }) } - /*switch result { - case let .chatFull(fullChat, chats, users): - switch fullChat { - case let .channelFull(_, _, _, _, _, _, readInboxMaxId, readOutboxMaxId, unreadCount, _, notifySettings, _, _, _, _, _): - modifier.updatePeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) - case .chatFull: - break - } - - if let cachedChannelData = CachedChannelData(apiChatFull: fullChat) { - var peers: [Peer] = [] - var peerPresences: [PeerId: PeerPresence] = [:] - for chat in chats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers.append(groupOrChannel) - } - } - for user in users { - let telegramUser = TelegramUser(user: user) - peers.append(telegramUser) - if let presence = TelegramUserPresence(apiUser: user) { - peerPresences[telegramUser.id] = presence - } - } - - updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in - return updated - }) - - modifier.updatePeerPresences(peerPresences) - - modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in - return cachedChannelData.withUpdatedTopParticipants((currentData as? CachedChannelData)?.topParticipants) - }) - } - }*/ } } } else { return .complete() } } - return .never() } diff --git a/TelegramCore/UpdateCachedPeerData.swift b/TelegramCore/UpdateCachedPeerData.swift index ec1db43794..5f4cff8134 100644 --- a/TelegramCore/UpdateCachedPeerData.swift +++ b/TelegramCore/UpdateCachedPeerData.swift @@ -7,6 +7,74 @@ import Foundation import SwiftSignalKit #endif +func fetchAndUpdateSupplementalCachedPeerData(peerId: PeerId, network: Network, postbox: Postbox) -> Signal { + return postbox.modify { modifier -> Signal in + if let peer = modifier.getPeer(peerId), let inputPeer = apiInputPeer(peer) { + let cachedData = modifier.getPeerCachedData(peerId: peerId) + + if let cachedData = cachedData as? CachedUserData { + if cachedData.reportStatus != .unknown { + return .complete() + } + } else if let cachedData = cachedData as? CachedGroupData { + if cachedData.reportStatus != .unknown { + return .complete() + } + } else if let cachedData = cachedData as? CachedChannelData { + if cachedData.reportStatus != .unknown { + return .complete() + } + } + + return network.request(Api.functions.messages.getPeerSettings(peer: inputPeer)) + |> retryRequest + |> mapToSignal { peerSettings -> Signal in + let reportStatus: PeerReportStatus + switch peerSettings { + case let .peerSettings(flags): + reportStatus = (flags & (1 << 0) != 0) ? .canReport : .none + } + + return postbox.modify { modifier -> Void in + modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in + switch peerId.namespace { + case Namespaces.Peer.CloudUser: + let previous: CachedUserData + if let current = current as? CachedUserData { + previous = current + } else { + previous = CachedUserData() + } + return previous.withUpdatedReportStatus(reportStatus) + case Namespaces.Peer.CloudGroup: + let previous: CachedGroupData + if let current = current as? CachedGroupData { + previous = current + } else { + previous = CachedGroupData() + } + return previous.withUpdatedReportStatus(reportStatus) + case Namespaces.Peer.CloudChannel: + let previous: CachedChannelData + if let current = current as? CachedChannelData { + previous = current + } else { + previous = CachedChannelData() + } + return previous.withUpdatedReportStatus(reportStatus) + default: + break + } + return current + }) + } + } + } else { + return .complete() + } + } |> switchToLatest +} + func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Postbox) -> Signal { return postbox.loadedPeerWithId(peerId) |> mapToSignal { peer -> Signal in @@ -16,16 +84,31 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos |> mapToSignal { result -> Signal in return postbox.modify { modifier -> Void in switch result { - - case let .userFull(_, user, _, _, _, notifySettings, _, commonChatCount): + case let .userFull(_, user, _, _, _, notifySettings, _, _): let telegramUser = TelegramUser(user: user) updatePeers(modifier: modifier, peers: [telegramUser], update: { _, updated -> Peer in return updated }) modifier.updatePeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) } - modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, _ in - return CachedUserData(apiUserFull: result) + modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, current in + let previous: CachedUserData + if let current = current as? CachedUserData { + previous = current + } else { + previous = CachedUserData() + } + switch result { + case let .userFull(flags, _, about, _, _, _, apiBotInfo, commonChatsCount): + let botInfo: BotInfo? + if let apiBotInfo = apiBotInfo { + botInfo = BotInfo(apiBotInfo: apiBotInfo) + } else { + botInfo = nil + } + let isBlocked = (flags & (1 << 0)) != 0 + return previous.withUpdatedAbout(about).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(commonChatsCount).withUpdatedIsBlocked(isBlocked) + } }) } } @@ -43,31 +126,53 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos break } - if let cachedGroupData = CachedGroupData(apiChatFull: fullChat) { - var peers: [Peer] = [] - var peerPresences: [PeerId: PeerPresence] = [:] - for chat in chats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers.append(groupOrChannel) + switch fullChat { + case let .chatFull(_, apiParticipants, _, _, apiExportedInvite, apiBotInfos): + var botInfos: [CachedPeerBotInfo] = [] + for botInfo in apiBotInfos { + switch botInfo { + case let .botInfo(userId, _, _): + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + let parsedBotInfo = BotInfo(apiBotInfo: botInfo) + botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) + } } - } - for user in users { - let telegramUser = TelegramUser(user: user) - peers.append(telegramUser) - if let presence = TelegramUserPresence(apiUser: user) { - peerPresences[telegramUser.id] = presence + let participants = CachedGroupParticipants(apiParticipants: apiParticipants) + let exportedInvitation = ExportedInvitation(apiExportedInvite: apiExportedInvite) + + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } } - } - - updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in - return updated - }) - - modifier.updatePeerPresences(peerPresences) - - modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, _ in - return cachedGroupData - }) + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } + + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in + return updated + }) + + modifier.updatePeerPresences(peerPresences) + + modifier.updatePeerCachedData(peerIds: [peerId], update: { _, current in + let previous: CachedGroupData + if let current = current as? CachedGroupData { + previous = current + } else { + previous = CachedGroupData() + } + + return previous.withUpdatedParticipants(participants).withUpdatedExportedInvitation(exportedInvitation).withUpdatedBotInfos(botInfos) + }) + case .channelFull: + break } } } @@ -80,37 +185,74 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos switch result { case let .chatFull(fullChat, chats, users): switch fullChat { - case let .channelFull(_, _, _, _, _, _, readInboxMaxId, readOutboxMaxId, unreadCount, _, notifySettings, _, _, _, _, _): + case let .channelFull(_, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _): modifier.updatePeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) case .chatFull: break } - if let cachedChannelData = CachedChannelData(apiChatFull: fullChat) { - var peers: [Peer] = [] - var peerPresences: [PeerId: PeerPresence] = [:] - for chat in chats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers.append(groupOrChannel) + switch fullChat { + case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, _, pinnedMsgId): + var channelFlags = CachedChannelFlags() + if (flags & (1 << 3)) != 0 { + channelFlags.insert(.canDisplayParticipants) } - } - for user in users { - let telegramUser = TelegramUser(user: user) - peers.append(telegramUser) - if let presence = TelegramUserPresence(apiUser: user) { - peerPresences[telegramUser.id] = presence + if (flags & (1 << 6)) != 0 { + channelFlags.insert(.canChangeUsername) } - } - - updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in - return updated - }) - - modifier.updatePeerPresences(peerPresences) - - modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in - return cachedChannelData.withUpdatedTopParticipants((currentData as? CachedChannelData)?.topParticipants) - }) + var botInfos: [CachedPeerBotInfo] = [] + for botInfo in apiBotInfos { + switch botInfo { + case let .botInfo(userId, _, _): + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + let parsedBotInfo = BotInfo(apiBotInfo: botInfo) + botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) + } + } + + var pinnedMessageId: MessageId? + if let pinnedMsgId = pinnedMsgId { + pinnedMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: pinnedMsgId) + } + + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } + } + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } + + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in + return updated + }) + + modifier.updatePeerPresences(peerPresences) + + modifier.updatePeerCachedData(peerIds: [peerId], update: { _, current in + let previous: CachedChannelData + if let current = current as? CachedChannelData { + previous = current + } else { + previous = CachedChannelData() + } + + return previous.withUpdatedFlags(channelFlags) + .withUpdatedAbout(about) + .withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: kickedCount)) + .withUpdatedExportedInvitation(ExportedInvitation(apiExportedInvite: apiExportedInvite)) + .withUpdatedBotInfos(botInfos) + .withUpdatedPinnedMessageId(pinnedMessageId) + }) + case .chatFull: + break } } }