From c2fbbfb93c40e0d2f809a5646661bf385fccff03 Mon Sep 17 00:00:00 2001 From: overtake Date: Tue, 6 Jun 2017 16:21:25 +0300 Subject: [PATCH 1/4] fixes --- TelegramCore/ChannelAdmins.swift | 3 ++- TelegramCore/ChannelMembers.swift | 1 + TelegramCore/ChannelParticipants.swift | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/TelegramCore/ChannelAdmins.swift b/TelegramCore/ChannelAdmins.swift index a6b5a6f53f..d26ebfc619 100644 --- a/TelegramCore/ChannelAdmins.swift +++ b/TelegramCore/ChannelAdmins.swift @@ -20,6 +20,7 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC var items: [RenderedChannelParticipant] = [] var peers: [PeerId: Peer] = [:] + var status:[PeerId: Peer] for user in users { let peer = TelegramUser(user: user) peers[peer.id] = peer @@ -27,7 +28,7 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer)) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: <#PeerPresence?#>)) } } diff --git a/TelegramCore/ChannelMembers.swift b/TelegramCore/ChannelMembers.swift index 00c4866345..a489c6e6e3 100644 --- a/TelegramCore/ChannelMembers.swift +++ b/TelegramCore/ChannelMembers.swift @@ -32,6 +32,7 @@ public func channelMembers(account: Account, peerId: PeerId, filter: ChannelMemb case let .channelParticipants(_, participants, users): var peers: [PeerId: Peer] = [:] for user in users { + let peer = TelegramUser(user: user) peers[peer.id] = peer } diff --git a/TelegramCore/ChannelParticipants.swift b/TelegramCore/ChannelParticipants.swift index ec3d20edec..e788e564d0 100644 --- a/TelegramCore/ChannelParticipants.swift +++ b/TelegramCore/ChannelParticipants.swift @@ -12,10 +12,11 @@ import Foundation public struct RenderedChannelParticipant: Equatable { public let participant: ChannelParticipant public let peer: Peer - - public init(participant: ChannelParticipant, peer: Peer) { + public let status: PeerPresence? + public init(participant: ChannelParticipant, peer: Peer, status: PeerPresence?) { self.participant = participant self.peer = peer + self.status = status } public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool { From ef2035cd748110b018acfd67cff6eb2c7a17dee0 Mon Sep 17 00:00:00 2001 From: overtake Date: Fri, 9 Jun 2017 05:57:18 +0300 Subject: [PATCH 2/4] - admins reform --- TelegramCore.xcodeproj/project.pbxproj | 6 + TelegramCore/ApiGroupOrChannel.swift | 2 +- TelegramCore/CachedChannelParticipants.swift | 3 +- TelegramCore/ChannelAdminEventLogs.swift | 184 ++++++++++++++++++ TelegramCore/ChannelAdmins.swift | 10 +- TelegramCore/ChannelBlacklist.swift | 7 +- TelegramCore/ChannelMembers.swift | 8 +- TelegramCore/ChannelParticipants.swift | 9 +- TelegramCore/PeerAdmins.swift | 4 +- TelegramCore/TelegramChannel.swift | 10 + .../UpdateCachedChannelParticipants.swift | 1 + 11 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 TelegramCore/ChannelAdminEventLogs.swift diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index 2e4135d28a..33442a7e16 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ C205FEA91EB3B75900455808 /* ExportMessageLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C205FEA71EB3B75900455808 /* ExportMessageLink.swift */; }; C22EE61B1E67418000334C38 /* ToggleChannelSignatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */; }; C22EE61C1E67418000334C38 /* ToggleChannelSignatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */; }; + C230BEB61EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */; }; + C230BEB71EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */; }; C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */; }; C2366C841E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */; }; C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C851E4F403C0097CCFF /* AddressNames.swift */; }; @@ -545,6 +547,7 @@ /* Begin PBXFileReference section */ C205FEA71EB3B75900455808 /* ExportMessageLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportMessageLink.swift; sourceTree = ""; }; C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToggleChannelSignatures.swift; sourceTree = ""; }; + C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdminEventLogs.swift; sourceTree = ""; }; C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupReturnAndLeft.swift; sourceTree = ""; }; C2366C851E4F403C0097CCFF /* AddressNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressNames.swift; sourceTree = ""; }; C2366C881E4F40480097CCFF /* SupportPeerId.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportPeerId.swift; sourceTree = ""; }; @@ -1387,6 +1390,7 @@ D0F3A8A71E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift */, C23BC3861E9BE3CA00D79F92 /* ImportContact.swift */, C205FEA71EB3B75900455808 /* ExportMessageLink.swift */, + C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */, ); name = Peers; sourceTree = ""; @@ -1633,6 +1637,7 @@ D03B0D6B1D631A9D00955575 /* Phonebook.swift in Sources */, D0AAD1A81E32602500D5B9DE /* AutoremoveTimeoutMessageAttribute.swift in Sources */, C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */, + C230BEB61EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */, D03B0D3D1D6319E200955575 /* Fetch.swift in Sources */, D0DF0C931D81AD09008AEB01 /* MessageUtils.swift in Sources */, D03B0D681D631A8B00955575 /* RecentPeers.swift in Sources */, @@ -1916,6 +1921,7 @@ D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */, D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */, D0E23DD61E8042F500B9B6D2 /* FeaturedStickerPack.swift in Sources */, + C230BEB71EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */, D00DBBDB1E64E67E00DB5485 /* UpdateSecretChat.swift in Sources */, D0448C921E251F96005A61A7 /* SecretChatEncryption.swift in Sources */, D00BDA1D1EE5952A00C64C5E /* TelegramChannelBannedRights.swift in Sources */, diff --git a/TelegramCore/ApiGroupOrChannel.swift b/TelegramCore/ApiGroupOrChannel.swift index 6a9d84d35e..3038fbbf6f 100644 --- a/TelegramCore/ApiGroupOrChannel.swift +++ b/TelegramCore/ApiGroupOrChannel.swift @@ -5,7 +5,7 @@ import Foundation import Postbox #endif -private func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMediaImageRepresentation] { +func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMediaImageRepresentation] { var telegramPhoto: [TelegramMediaImageRepresentation] = [] switch photo { case let .chatPhoto(photoSmall, photoBig): diff --git a/TelegramCore/CachedChannelParticipants.swift b/TelegramCore/CachedChannelParticipants.swift index ca6094b0de..f680a85ef7 100644 --- a/TelegramCore/CachedChannelParticipants.swift +++ b/TelegramCore/CachedChannelParticipants.swift @@ -136,6 +136,7 @@ public final class CachedChannelParticipants: Coding, Equatable { } } + extension ChannelParticipant { init(apiParticipant: Api.ChannelParticipant) { switch apiParticipant { @@ -149,7 +150,7 @@ extension ChannelParticipant { self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: TelegramChannelBannedRights(apiBannedRights: bannedRights)) case let .channelParticipantAdmin(flags, userId, _, promotedBy, date, adminRights): self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChannelAdminRights(apiAdminRights: adminRights), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: promotedBy), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil) - case let .channelParticipantSelf(_, userId, date): + case let .channelParticipantSelf(userId, _, date): self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: nil) } } diff --git a/TelegramCore/ChannelAdminEventLogs.swift b/TelegramCore/ChannelAdminEventLogs.swift new file mode 100644 index 0000000000..3a61dc99f9 --- /dev/null +++ b/TelegramCore/ChannelAdminEventLogs.swift @@ -0,0 +1,184 @@ + +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + + +public typealias AdminLogEventId = Int64 + +public struct AdminLogEvent { + public let id: AdminLogEventId + public let peerId:PeerId + public let date:Int32 + public let action: AdminLogEventAction +} + +public struct AdminLogEventsResult { + public let peerId: PeerId + public let peers:[PeerId: Peer] + public let events:[AdminLogEvent] +} + +public enum AdminLogEventAction { + case changeTitle(prev: String, new: String) + case changeAbout(prev: String, new: String) + case changeUsername(prev: String, new: String) + case changePhoto(prev: [TelegramMediaImageRepresentation], new: [TelegramMediaImageRepresentation]) + case toggleInvites(Bool) + case toggleSignatures(Bool) + case updatePinned(Message) + case editMessage(prev: Message, new:Message) + case deleteMessage(Message) + case participantJoin + case participantLeave + case participantInvite(RenderedChannelParticipant) + case participantToggleBan(prev: RenderedChannelParticipant, new: RenderedChannelParticipant) + case participantToggleAdmin(prev: RenderedChannelParticipant, new: RenderedChannelParticipant) +} + +public enum ChannelAdminLogEventError { + case generic +} + +public struct AdminLogEventsFlags : OptionSet { + public var rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + public init() { + self.rawValue = 0 + } + public static let join = AdminLogEventsFlags(rawValue: 1 << 0) + public static let leave = AdminLogEventsFlags(rawValue: 1 << 1) + public static let invite = AdminLogEventsFlags(rawValue: 1 << 2) + public static let ban = AdminLogEventsFlags(rawValue: 1 << 3) + public static let unban = AdminLogEventsFlags(rawValue: 1 << 4) + public static let kick = AdminLogEventsFlags(rawValue: 1 << 5) + public static let unkick = AdminLogEventsFlags(rawValue: 1 << 6) + public static let promote = AdminLogEventsFlags(rawValue: 1 << 7) + public static let demote = AdminLogEventsFlags(rawValue: 1 << 8) + public static let info = AdminLogEventsFlags(rawValue: 1 << 9) + public static let settings = AdminLogEventsFlags(rawValue: 1 << 10) + public static let pinnedMessages = AdminLogEventsFlags(rawValue: 1 << 11) + public static let editMessages = AdminLogEventsFlags(rawValue: 1 << 12) + public static let deleteMessages = AdminLogEventsFlags(rawValue: 1 << 13) + + public static var all:AdminLogEventsFlags { + return [.join, .leave, .invite, .ban, .unban, .kick, .unkick, .promote, .demote, .info, .settings, .pinnedMessages, .editMessages, .deleteMessages] + } +} + +private func boolFromApiValue(_ value: Api.Bool) -> Bool { + switch value { + case .boolFalse: + return false + case .boolTrue: + return true + } +} + +public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminLogEventId, minId:AdminLogEventId, limit:Int32 = 100, query:String = "", filter:AdminLogEventsFlags? = nil, admins:[PeerId]? = nil) -> Signal { + + return account.postbox.modify { modifier -> (Peer?, [Peer]?) in + return (modifier.getPeer(peerId), admins?.flatMap {modifier.getPeer($0)}) + } |> mapError {return .generic} |> mapToSignal { (peer, admins) -> Signal in + + if let peer = peer, let inputChannel = apiInputChannel(peer) { + let inputAdmins = admins?.flatMap {apiInputUser($0)} + + var flags:Int32 = 0 + var eventsFilter:Api.ChannelAdminLogEventsFilter? = nil + if let filter = filter { + flags += Int32(1 << 0) + eventsFilter = Api.ChannelAdminLogEventsFilter.channelAdminLogEventsFilter(flags: Int32(filter.rawValue)) + } + if let _ = inputAdmins { + flags += Int32(1 << 1) + } + return account.network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query, eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> map { result in + + switch result { + case let .adminLogResults(apiEvents, apiChats, apiUsers): + let peers = (apiChats.flatMap {parseTelegramGroupOrChannel(chat: $0)} + apiUsers.flatMap {TelegramUser(user: $0)}).reduce([:], { current, peer -> [PeerId : Peer] in + var current = current + current[peer.id] = peer + return current + }) + + var events:[AdminLogEvent] = [] + + for event in apiEvents { + switch event { + case let .channelAdminLogEvent(id, date, userId, apiAction): + var action: AdminLogEventAction? + switch apiAction { + case let .channelAdminLogEventActionChangeTitle(prev, new): + action = .changeTitle(prev: prev, new: new) + case let .channelAdminLogEventActionChangeAbout(prev, new): + action = .changeAbout(prev: prev, new: new) + case let .channelAdminLogEventActionChangeUsername(prev, new): + action = .changeUsername(prev: prev, new: new) + case let .channelAdminLogEventActionChangePhoto(prev, new): + action = .changePhoto(prev: imageRepresentationsForApiChatPhoto(prev), new: imageRepresentationsForApiChatPhoto(new)) + case let .channelAdminLogEventActionToggleInvites(new): + action = .toggleInvites(boolFromApiValue(new)) + case let .channelAdminLogEventActionToggleSignatures(new): + action = .toggleSignatures(boolFromApiValue(new)) + case let .channelAdminLogEventActionUpdatePinned(new): + if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) { + action = .updatePinned(rendered) + } + case let .channelAdminLogEventActionEditMessage(prev, new): + if let prev = StoreMessage(apiMessage: prev), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new), let newRendered = locallyRenderedMessage(message: new, peers: peers) { + action = .editMessage(prev: prevRendered, new: newRendered) + } + case let .channelAdminLogEventActionDeleteMessage(message): + if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) { + action = .deleteMessage(rendered) + } + case .channelAdminLogEventActionParticipantJoin: + action = .participantJoin + case .channelAdminLogEventActionParticipantLeave: + action = .participantLeave + case let .channelAdminLogEventActionParticipantInvite(participant): + let participant = ChannelParticipant(apiParticipant: participant) + + if let peer = peers[participant.peerId] { + action = .participantInvite(RenderedChannelParticipant(participant: participant, peer: peer)) + } + case let .channelAdminLogEventActionParticipantToggleBan(prev, new): + let prevParticipant = ChannelParticipant(apiParticipant: prev) + let newParticipant = ChannelParticipant(apiParticipant: new) + + if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] { + action = .participantToggleBan(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer)) + } + case let .channelAdminLogEventActionParticipantToggleAdmin(prev, new): + let prevParticipant = ChannelParticipant(apiParticipant: prev) + let newParticipant = ChannelParticipant(apiParticipant: new) + + if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] { + action = .participantToggleAdmin(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer)) + } + } + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + if let action = action { + events.append(AdminLogEvent(id: id, peerId: peerId, date: date, action: action)) + } + } + } + return AdminLogEventsResult(peerId: peerId, peers: peers, events: events) + } + + } |> mapError {_ in return .generic} + } + + return .complete() + } +} diff --git a/TelegramCore/ChannelAdmins.swift b/TelegramCore/ChannelAdmins.swift index d26ebfc619..5331d00f84 100644 --- a/TelegramCore/ChannelAdmins.swift +++ b/TelegramCore/ChannelAdmins.swift @@ -20,16 +20,20 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC var items: [RenderedChannelParticipant] = [] var peers: [PeerId: Peer] = [:] - var status:[PeerId: Peer] + var status:[PeerId: PeerPresence] = [:] for user in users { let peer = TelegramUser(user: user) peers[peer.id] = peer + if let presence = TelegramUserPresence(apiUser: user) { + status[peer.id] = presence + } } - + for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: <#PeerPresence?#>)) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) } + } return account.postbox.modify { modifier -> [RenderedChannelParticipant] in diff --git a/TelegramCore/ChannelBlacklist.swift b/TelegramCore/ChannelBlacklist.swift index 85af787ecc..c92350102e 100644 --- a/TelegramCore/ChannelBlacklist.swift +++ b/TelegramCore/ChannelBlacklist.swift @@ -19,15 +19,20 @@ public func channelBlacklist(account: Account, peerId: PeerId) -> Signal<[Render switch result { case let .channelParticipants(_, participants, users): var peers: [PeerId: Peer] = [:] + var status:[PeerId: PeerPresence] = [:] for user in users { let peer = TelegramUser(user: user) peers[peer.id] = peer + if let presence = TelegramUserPresence(apiUser: user) { + status[peer.id] = presence + } } for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer)) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) } + } } return items diff --git a/TelegramCore/ChannelMembers.swift b/TelegramCore/ChannelMembers.swift index a489c6e6e3..95df854c6a 100644 --- a/TelegramCore/ChannelMembers.swift +++ b/TelegramCore/ChannelMembers.swift @@ -31,16 +31,20 @@ public func channelMembers(account: Account, peerId: PeerId, filter: ChannelMemb switch result { case let .channelParticipants(_, participants, users): var peers: [PeerId: Peer] = [:] + var status:[PeerId: PeerPresence] = [:] for user in users { - let peer = TelegramUser(user: user) peers[peer.id] = peer + if let presence = TelegramUserPresence(apiUser: user) { + status[peer.id] = presence + } } for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer)) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) } + } } return items diff --git a/TelegramCore/ChannelParticipants.swift b/TelegramCore/ChannelParticipants.swift index e788e564d0..0ca519eeaf 100644 --- a/TelegramCore/ChannelParticipants.swift +++ b/TelegramCore/ChannelParticipants.swift @@ -13,13 +13,20 @@ public struct RenderedChannelParticipant: Equatable { public let participant: ChannelParticipant public let peer: Peer public let status: PeerPresence? - public init(participant: ChannelParticipant, peer: Peer, status: PeerPresence?) { + public init(participant: ChannelParticipant, peer: Peer, status: PeerPresence? = nil) { self.participant = participant self.peer = peer self.status = status } public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool { + if let lhsStatus = lhs.status, let rhsStatus = rhs.status { + if !lhsStatus.isEqual(to: rhsStatus) { + return false + } + } else if (lhs.status != nil) != (rhs.status != nil) { + return false + } return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer) } } diff --git a/TelegramCore/PeerAdmins.swift b/TelegramCore/PeerAdmins.swift index 3092aeb3fa..bd2f9fb5d7 100644 --- a/TelegramCore/PeerAdmins.swift +++ b/TelegramCore/PeerAdmins.swift @@ -116,11 +116,11 @@ public enum AddPeerAdminError { case addMemberError(AddPeerMemberError) } -public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal { +public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId, adminRightsFlags:TelegramChannelAdminRightsFlags? = nil) -> Signal { return account.postbox.modify { modifier -> Signal in if let peer = modifier.getPeer(peerId), let adminPeer = modifier.getPeer(adminId), let inputUser = apiInputUser(adminPeer) { if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) { - return account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: [.canChangeInfo, .canPostMessages, .canEditMessages, .canDeleteMessages, .canBanUsers, .canInviteUsers, .canChangeInviteLink, .canPinMessages]).apiAdminRights)) + return account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: adminRightsFlags ?? [.canChangeInfo, .canPostMessages, .canEditMessages, .canDeleteMessages, .canBanUsers, .canInviteUsers, .canChangeInviteLink, .canPinMessages]).apiAdminRights)) |> map { [$0] } |> `catch` { error -> Signal<[Api.Updates], AddPeerAdminError> in if error.errorDescription == "USER_NOT_PARTICIPANT" { diff --git a/TelegramCore/TelegramChannel.swift b/TelegramCore/TelegramChannel.swift index b49d7969a8..a0a2820612 100644 --- a/TelegramCore/TelegramChannel.swift +++ b/TelegramCore/TelegramChannel.swift @@ -271,4 +271,14 @@ public extension TelegramChannel { return false } } + + public func hasBannedRights(_ flags: TelegramChannelBannedRightsFlags) -> Bool { + if self.flags.contains(.isCreator) { + return false + } else if let bannedRights = self.bannedRights { + return flags.isSubset(of: bannedRights.flags) + } else { + return false + } + } } diff --git a/TelegramCore/UpdateCachedChannelParticipants.swift b/TelegramCore/UpdateCachedChannelParticipants.swift index 2c6da02b30..def1f657bf 100644 --- a/TelegramCore/UpdateCachedChannelParticipants.swift +++ b/TelegramCore/UpdateCachedChannelParticipants.swift @@ -34,6 +34,7 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: modifier.updatePeerPresences(peerPresences) let parsedParticipants = CachedChannelParticipants(apiParticipants: participants) + modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in if let currentData = currentData as? CachedChannelData { return currentData.withUpdatedTopParticipants(parsedParticipants) From 707608391a4f4609a9924938b93c85c54bd1a02c Mon Sep 17 00:00:00 2001 From: overtake Date: Fri, 9 Jun 2017 14:27:16 +0300 Subject: [PATCH 3/4] changes --- TelegramCore/ChannelAdminEventLogs.swift | 12 +++++++++--- TelegramCore/PeerAdmins.swift | 9 ++++++--- TelegramCore/TelegramChannelAdminRights.swift | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/TelegramCore/ChannelAdminEventLogs.swift b/TelegramCore/ChannelAdminEventLogs.swift index 3a61dc99f9..9db681ea89 100644 --- a/TelegramCore/ChannelAdminEventLogs.swift +++ b/TelegramCore/ChannelAdminEventLogs.swift @@ -30,7 +30,7 @@ public enum AdminLogEventAction { case changePhoto(prev: [TelegramMediaImageRepresentation], new: [TelegramMediaImageRepresentation]) case toggleInvites(Bool) case toggleSignatures(Bool) - case updatePinned(Message) + case updatePinned(Message?) case editMessage(prev: Message, new:Message) case deleteMessage(Message) case participantJoin @@ -131,9 +131,15 @@ public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminL case let .channelAdminLogEventActionToggleSignatures(new): action = .toggleSignatures(boolFromApiValue(new)) case let .channelAdminLogEventActionUpdatePinned(new): - if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) { - action = .updatePinned(rendered) + switch new { + case .messageEmpty: + action = .updatePinned(nil) + default: + if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) { + action = .updatePinned(rendered) + } } + case let .channelAdminLogEventActionEditMessage(prev, new): if let prev = StoreMessage(apiMessage: prev), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new), let newRendered = locallyRenderedMessage(message: new, peers: peers) { action = .editMessage(prev: prevRendered, new: newRendered) diff --git a/TelegramCore/PeerAdmins.swift b/TelegramCore/PeerAdmins.swift index bd2f9fb5d7..90391b4bc9 100644 --- a/TelegramCore/PeerAdmins.swift +++ b/TelegramCore/PeerAdmins.swift @@ -116,11 +116,14 @@ public enum AddPeerAdminError { case addMemberError(AddPeerMemberError) } -public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId, adminRightsFlags:TelegramChannelAdminRightsFlags? = nil) -> Signal { +public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId, adminRightsFlags:TelegramChannelAdminRightsFlags = []) -> Signal { return account.postbox.modify { modifier -> Signal in if let peer = modifier.getPeer(peerId), let adminPeer = modifier.getPeer(adminId), let inputUser = apiInputUser(adminPeer) { + + let defaultRights:TelegramChannelAdminRightsFlags = [.canChangeInfo, .canPostMessages, .canEditMessages, .canDeleteMessages, .canBanUsers, .canInviteUsers, .canChangeInviteLink, .canPinMessages] + if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) { - return account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: adminRightsFlags ?? [.canChangeInfo, .canPostMessages, .canEditMessages, .canDeleteMessages, .canBanUsers, .canInviteUsers, .canChangeInviteLink, .canPinMessages]).apiAdminRights)) + return account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: adminRightsFlags.isEmpty ? defaultRights : adminRightsFlags).apiAdminRights)) |> map { [$0] } |> `catch` { error -> Signal<[Api.Updates], AddPeerAdminError> in if error.errorDescription == "USER_NOT_PARTICIPANT" { @@ -131,7 +134,7 @@ public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId, admi |> mapError { error -> AddPeerAdminError in return .addMemberError(error) } - |> then(account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: [.canChangeInfo, .canPostMessages, .canEditMessages, .canDeleteMessages, .canBanUsers, .canInviteUsers, .canChangeInviteLink, .canPinMessages]).apiAdminRights)) + |> then(account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: TelegramChannelAdminRights(flags: adminRightsFlags.isEmpty ? defaultRights : adminRightsFlags).apiAdminRights)) |> mapError { error -> AddPeerAdminError in return .generic } diff --git a/TelegramCore/TelegramChannelAdminRights.swift b/TelegramCore/TelegramChannelAdminRights.swift index 103137c795..fb5c38b21b 100644 --- a/TelegramCore/TelegramChannelAdminRights.swift +++ b/TelegramCore/TelegramChannelAdminRights.swift @@ -24,7 +24,7 @@ public struct TelegramChannelAdminRightsFlags: OptionSet { public static let canInviteUsers = TelegramChannelAdminRightsFlags(rawValue: 1 << 5) public static let canChangeInviteLink = TelegramChannelAdminRightsFlags(rawValue: 1 << 6) public static let canPinMessages = TelegramChannelAdminRightsFlags(rawValue: 1 << 7) - public static let canAddAdmins = TelegramChannelAdminRightsFlags(rawValue: 1 << 8) + public static let canAddAdmins = TelegramChannelAdminRightsFlags(rawValue: 1 << 9) public static var groupSpecific: TelegramChannelAdminRightsFlags = [ .canChangeInfo, From acaf6f359d320ee2dba66bfe054890f98220fe6f Mon Sep 17 00:00:00 2001 From: overtake Date: Tue, 13 Jun 2017 21:47:29 +0300 Subject: [PATCH 4/4] no message --- TelegramCore/ChannelAdminEventLogs.swift | 9 ++-- TelegramCore/ChannelAdmins.swift | 2 +- TelegramCore/ChannelBlacklist.swift | 64 +++++++++++++++++++++--- TelegramCore/ChannelMembers.swift | 2 +- TelegramCore/ChannelParticipants.swift | 11 ++-- 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/TelegramCore/ChannelAdminEventLogs.swift b/TelegramCore/ChannelAdminEventLogs.swift index 9db681ea89..1c943eeb80 100644 --- a/TelegramCore/ChannelAdminEventLogs.swift +++ b/TelegramCore/ChannelAdminEventLogs.swift @@ -69,7 +69,10 @@ public struct AdminLogEventsFlags : OptionSet { public static let editMessages = AdminLogEventsFlags(rawValue: 1 << 12) public static let deleteMessages = AdminLogEventsFlags(rawValue: 1 << 13) - public static var all:AdminLogEventsFlags { + public static var all:[AdminLogEventsFlags] { + return [.join, .leave, .invite, .ban, .unban, .kick, .unkick, .promote, .demote, .info, .settings, .pinnedMessages, .editMessages, .deleteMessages] + } + public static var flags:AdminLogEventsFlags { return [.join, .leave, .invite, .ban, .unban, .kick, .unkick, .promote, .demote, .info, .settings, .pinnedMessages, .editMessages, .deleteMessages] } } @@ -83,7 +86,7 @@ private func boolFromApiValue(_ value: Api.Bool) -> Bool { } } -public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminLogEventId, minId:AdminLogEventId, limit:Int32 = 100, query:String = "", filter:AdminLogEventsFlags? = nil, admins:[PeerId]? = nil) -> Signal { +public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminLogEventId, minId:AdminLogEventId, limit:Int32 = 100, query:String? = nil, filter:AdminLogEventsFlags? = nil, admins:[PeerId]? = nil) -> Signal { return account.postbox.modify { modifier -> (Peer?, [Peer]?) in return (modifier.getPeer(peerId), admins?.flatMap {modifier.getPeer($0)}) @@ -101,7 +104,7 @@ public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminL if let _ = inputAdmins { flags += Int32(1 << 1) } - return account.network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query, eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> map { result in + return account.network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query ?? "", eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> map { result in switch result { case let .adminLogResults(apiEvents, apiChats, apiUsers): diff --git a/TelegramCore/ChannelAdmins.swift b/TelegramCore/ChannelAdmins.swift index 5331d00f84..fbc0cadee1 100644 --- a/TelegramCore/ChannelAdmins.swift +++ b/TelegramCore/ChannelAdmins.swift @@ -31,7 +31,7 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, presence: status[peer.id])) } } diff --git a/TelegramCore/ChannelBlacklist.swift b/TelegramCore/ChannelBlacklist.swift index 81123f751d..a263a29843 100644 --- a/TelegramCore/ChannelBlacklist.swift +++ b/TelegramCore/ChannelBlacklist.swift @@ -42,7 +42,7 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, presence: status[peer.id])) } } @@ -55,24 +55,74 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha } |> switchToLatest } -public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Signal<[RenderedChannelParticipant], NoError> { +public struct ChannelBlacklist { + public let banned:[RenderedChannelParticipant] + public let restricted:[RenderedChannelParticipant] + public init(banned:[RenderedChannelParticipant], restricted: [RenderedChannelParticipant]) { + self.banned = banned + self.restricted = restricted + } + public var isEmpty: Bool { + return banned.isEmpty && restricted.isEmpty + } + public func withRemovedPeerId(_ memberId:PeerId) -> ChannelBlacklist { + var updatedRestricted = restricted + var updatedBanned = banned + + for i in 0 ..< updatedBanned.count { + if updatedBanned[i].peer.id == memberId { + updatedBanned.remove(at: i) + break + } + } + for i in 0 ..< updatedRestricted.count { + if updatedRestricted[i].peer.id == memberId { + updatedRestricted.remove(at: i) + break + } + } + return ChannelBlacklist(banned: updatedBanned, restricted: updatedRestricted) + } + + public func withRemovedParticipant(_ participant:RenderedChannelParticipant) -> ChannelBlacklist { + let updated = self.withRemovedPeerId(participant.participant.peerId) + var updatedRestricted = updated.restricted + var updatedBanned = updated.banned + + if case .member(_, _, _, let maybeBanInfo) = participant.participant, let banInfo = maybeBanInfo { + if banInfo.flags.contains(.banReadMessages) { + updatedBanned.insert(participant, at: 0) + } else { + if !banInfo.flags.isEmpty { + updatedRestricted.insert(participant, at: 0) + } + } + } + + + return ChannelBlacklist(banned: updatedBanned, restricted: updatedRestricted) + } +} + +public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Signal { return combineLatest(fetchChannelBlacklist(account: account, peerId: peerId, filter: .restricted), fetchChannelBlacklist(account: account, peerId: peerId, filter: .banned)) - |> map { restricted, banned -> [RenderedChannelParticipant] in - var result: [RenderedChannelParticipant] = [] + |> map { restricted, banned in + var r: [RenderedChannelParticipant] = [] + var b: [RenderedChannelParticipant] = [] var peerIds = Set() for participant in restricted { if !peerIds.contains(participant.peer.id) { peerIds.insert(participant.peer.id) - result.append(participant) + r.append(participant) } } for participant in banned { if !peerIds.contains(participant.peer.id) { peerIds.insert(participant.peer.id) - result.append(participant) + b.append(participant) } } - return result + return ChannelBlacklist(banned: b, restricted: r) } } diff --git a/TelegramCore/ChannelMembers.swift b/TelegramCore/ChannelMembers.swift index 95df854c6a..bf4bdd33a5 100644 --- a/TelegramCore/ChannelMembers.swift +++ b/TelegramCore/ChannelMembers.swift @@ -42,7 +42,7 @@ public func channelMembers(account: Account, peerId: PeerId, filter: ChannelMemb for participant in CachedChannelParticipants(apiParticipants: participants).participants { if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, status: status[peer.id])) + items.append(RenderedChannelParticipant(participant: participant, peer: peer, presence: status[peer.id])) } } diff --git a/TelegramCore/ChannelParticipants.swift b/TelegramCore/ChannelParticipants.swift index 6375164b6a..1be9eb8143 100644 --- a/TelegramCore/ChannelParticipants.swift +++ b/TelegramCore/ChannelParticipants.swift @@ -12,23 +12,24 @@ import Foundation public struct RenderedChannelParticipant: Equatable { public let participant: ChannelParticipant public let peer: Peer - public let status: PeerPresence? - public init(participant: ChannelParticipant, peer: Peer, status: PeerPresence? = nil) { + public let presence: PeerPresence? + public init(participant: ChannelParticipant, peer: Peer, presence: PeerPresence? = nil) { self.participant = participant self.peer = peer - self.status = status + self.presence = presence } public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool { - if let lhsStatus = lhs.status, let rhsStatus = rhs.status { + if let lhsStatus = lhs.presence, let rhsStatus = rhs.presence { if !lhsStatus.isEqual(to: rhsStatus) { return false } - } else if (lhs.status != nil) != (rhs.status != nil) { + } else if (lhs.presence != nil) != (rhs.presence != nil) { return false } return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer) } + } func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signal {