mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-03 11:21:06 +00:00
Merge commit '11eba885a4cf6dd7e379cebbf7343965a15c8a2c'
# Conflicts: # TelegramCore/ChannelParticipants.swift
This commit is contained in:
commit
0100756ebf
@ -11,6 +11,8 @@
|
|||||||
C205FEA91EB3B75900455808 /* ExportMessageLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C205FEA71EB3B75900455808 /* ExportMessageLink.swift */; };
|
C205FEA91EB3B75900455808 /* ExportMessageLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C205FEA71EB3B75900455808 /* ExportMessageLink.swift */; };
|
||||||
C22EE61B1E67418000334C38 /* ToggleChannelSignatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */; };
|
C22EE61B1E67418000334C38 /* ToggleChannelSignatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */; };
|
||||||
C22EE61C1E67418000334C38 /* 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 */; };
|
C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */; };
|
||||||
C2366C841E4F3EAA0097CCFF /* 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 */; };
|
C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C851E4F403C0097CCFF /* AddressNames.swift */; };
|
||||||
@ -551,6 +553,7 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportMessageLink.swift; sourceTree = "<group>"; };
|
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportMessageLink.swift; sourceTree = "<group>"; };
|
||||||
C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToggleChannelSignatures.swift; sourceTree = "<group>"; };
|
C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToggleChannelSignatures.swift; sourceTree = "<group>"; };
|
||||||
|
C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdminEventLogs.swift; sourceTree = "<group>"; };
|
||||||
C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupReturnAndLeft.swift; sourceTree = "<group>"; };
|
C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupReturnAndLeft.swift; sourceTree = "<group>"; };
|
||||||
C2366C851E4F403C0097CCFF /* AddressNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressNames.swift; sourceTree = "<group>"; };
|
C2366C851E4F403C0097CCFF /* AddressNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressNames.swift; sourceTree = "<group>"; };
|
||||||
C2366C881E4F40480097CCFF /* SupportPeerId.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportPeerId.swift; sourceTree = "<group>"; };
|
C2366C881E4F40480097CCFF /* SupportPeerId.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportPeerId.swift; sourceTree = "<group>"; };
|
||||||
@ -1407,6 +1410,7 @@
|
|||||||
D0F3A8A71E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift */,
|
D0F3A8A71E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift */,
|
||||||
C23BC3861E9BE3CA00D79F92 /* ImportContact.swift */,
|
C23BC3861E9BE3CA00D79F92 /* ImportContact.swift */,
|
||||||
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */,
|
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */,
|
||||||
|
C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */,
|
||||||
);
|
);
|
||||||
name = Peers;
|
name = Peers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1653,6 +1657,7 @@
|
|||||||
D03B0D6B1D631A9D00955575 /* Phonebook.swift in Sources */,
|
D03B0D6B1D631A9D00955575 /* Phonebook.swift in Sources */,
|
||||||
D0AAD1A81E32602500D5B9DE /* AutoremoveTimeoutMessageAttribute.swift in Sources */,
|
D0AAD1A81E32602500D5B9DE /* AutoremoveTimeoutMessageAttribute.swift in Sources */,
|
||||||
C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */,
|
C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */,
|
||||||
|
C230BEB61EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */,
|
||||||
D03B0D3D1D6319E200955575 /* Fetch.swift in Sources */,
|
D03B0D3D1D6319E200955575 /* Fetch.swift in Sources */,
|
||||||
D0DF0C931D81AD09008AEB01 /* MessageUtils.swift in Sources */,
|
D0DF0C931D81AD09008AEB01 /* MessageUtils.swift in Sources */,
|
||||||
D03B0D681D631A8B00955575 /* RecentPeers.swift in Sources */,
|
D03B0D681D631A8B00955575 /* RecentPeers.swift in Sources */,
|
||||||
@ -1940,6 +1945,7 @@
|
|||||||
D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */,
|
D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */,
|
||||||
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */,
|
D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */,
|
||||||
D0E23DD61E8042F500B9B6D2 /* FeaturedStickerPack.swift in Sources */,
|
D0E23DD61E8042F500B9B6D2 /* FeaturedStickerPack.swift in Sources */,
|
||||||
|
C230BEB71EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */,
|
||||||
D00DBBDB1E64E67E00DB5485 /* UpdateSecretChat.swift in Sources */,
|
D00DBBDB1E64E67E00DB5485 /* UpdateSecretChat.swift in Sources */,
|
||||||
D0448C921E251F96005A61A7 /* SecretChatEncryption.swift in Sources */,
|
D0448C921E251F96005A61A7 /* SecretChatEncryption.swift in Sources */,
|
||||||
D00BDA1D1EE5952A00C64C5E /* TelegramChannelBannedRights.swift in Sources */,
|
D00BDA1D1EE5952A00C64C5E /* TelegramChannelBannedRights.swift in Sources */,
|
||||||
|
@ -5,7 +5,7 @@ import Foundation
|
|||||||
import Postbox
|
import Postbox
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMediaImageRepresentation] {
|
func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMediaImageRepresentation] {
|
||||||
var telegramPhoto: [TelegramMediaImageRepresentation] = []
|
var telegramPhoto: [TelegramMediaImageRepresentation] = []
|
||||||
switch photo {
|
switch photo {
|
||||||
case let .chatPhoto(photoSmall, photoBig):
|
case let .chatPhoto(photoSmall, photoBig):
|
||||||
|
@ -136,6 +136,7 @@ public final class CachedChannelParticipants: Coding, Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension ChannelParticipant {
|
extension ChannelParticipant {
|
||||||
init(apiParticipant: Api.ChannelParticipant) {
|
init(apiParticipant: Api.ChannelParticipant) {
|
||||||
switch apiParticipant {
|
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))
|
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):
|
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)
|
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)
|
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
193
TelegramCore/ChannelAdminEventLogs.swift
Normal file
193
TelegramCore/ChannelAdminEventLogs.swift
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
|
||||||
|
#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]
|
||||||
|
}
|
||||||
|
public static var flags: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? = nil, filter:AdminLogEventsFlags? = nil, admins:[PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
|
||||||
|
|
||||||
|
return account.postbox.modify { modifier -> (Peer?, [Peer]?) in
|
||||||
|
return (modifier.getPeer(peerId), admins?.flatMap {modifier.getPeer($0)})
|
||||||
|
} |> mapError {return .generic} |> mapToSignal { (peer, admins) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> 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):
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
@ -20,15 +20,20 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC
|
|||||||
var items: [RenderedChannelParticipant] = []
|
var items: [RenderedChannelParticipant] = []
|
||||||
|
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
|
var status:[PeerId: PeerPresence] = [:]
|
||||||
for user in users {
|
for user in users {
|
||||||
let peer = TelegramUser(user: user)
|
let peer = TelegramUser(user: user)
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
|
if let presence = TelegramUserPresence(apiUser: user) {
|
||||||
|
status[peer.id] = presence
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
||||||
if let peer = peers[participant.peerId] {
|
if let peer = peers[participant.peerId] {
|
||||||
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers))
|
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presence: status[peer.id]))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.postbox.modify { modifier -> [RenderedChannelParticipant] in
|
return account.postbox.modify { modifier -> [RenderedChannelParticipant] in
|
||||||
|
@ -31,15 +31,20 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha
|
|||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(_, participants, users):
|
case let .channelParticipants(_, participants, users):
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
|
var status:[PeerId: PeerPresence] = [:]
|
||||||
for user in users {
|
for user in users {
|
||||||
let peer = TelegramUser(user: user)
|
let peer = TelegramUser(user: user)
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
|
if let presence = TelegramUserPresence(apiUser: user) {
|
||||||
|
status[peer.id] = presence
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
||||||
if let peer = peers[participant.peerId] {
|
if let peer = peers[participant.peerId] {
|
||||||
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers))
|
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presence: status[peer.id]))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
@ -50,24 +55,77 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha
|
|||||||
} |> switchToLatest
|
} |> 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<ChannelBlacklist, NoError> {
|
||||||
return combineLatest(fetchChannelBlacklist(account: account, peerId: peerId, filter: .restricted), fetchChannelBlacklist(account: account, peerId: peerId, filter: .banned))
|
return combineLatest(fetchChannelBlacklist(account: account, peerId: peerId, filter: .restricted), fetchChannelBlacklist(account: account, peerId: peerId, filter: .banned))
|
||||||
|> map { restricted, banned -> [RenderedChannelParticipant] in
|
|> map { restricted, banned in
|
||||||
var result: [RenderedChannelParticipant] = []
|
var r: [RenderedChannelParticipant] = []
|
||||||
|
var b: [RenderedChannelParticipant] = []
|
||||||
var peerIds = Set<PeerId>()
|
var peerIds = Set<PeerId>()
|
||||||
for participant in restricted {
|
for participant in restricted {
|
||||||
if !peerIds.contains(participant.peer.id) {
|
if !peerIds.contains(participant.peer.id) {
|
||||||
peerIds.insert(participant.peer.id)
|
peerIds.insert(participant.peer.id)
|
||||||
result.append(participant)
|
r.append(participant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for participant in banned {
|
for participant in banned {
|
||||||
if !peerIds.contains(participant.peer.id) {
|
if !peerIds.contains(participant.peer.id) {
|
||||||
peerIds.insert(participant.peer.id)
|
peerIds.insert(participant.peer.id)
|
||||||
result.append(participant)
|
b.append(participant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return ChannelBlacklist(banned: b, restricted: r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,15 +31,20 @@ public func channelMembers(account: Account, peerId: PeerId, filter: ChannelMemb
|
|||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(_, participants, users):
|
case let .channelParticipants(_, participants, users):
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
|
var status:[PeerId: PeerPresence] = [:]
|
||||||
for user in users {
|
for user in users {
|
||||||
let peer = TelegramUser(user: user)
|
let peer = TelegramUser(user: user)
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
|
if let presence = TelegramUserPresence(apiUser: user) {
|
||||||
|
status[peer.id] = presence
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
||||||
if let peer = peers[participant.peerId] {
|
if let peer = peers[participant.peerId] {
|
||||||
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers))
|
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presence: status[peer.id]))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
|
@ -13,18 +13,21 @@ public struct RenderedChannelParticipant: Equatable {
|
|||||||
public let participant: ChannelParticipant
|
public let participant: ChannelParticipant
|
||||||
public let peer: Peer
|
public let peer: Peer
|
||||||
public let peers: [PeerId: Peer]
|
public let peers: [PeerId: Peer]
|
||||||
public let peerPresences: [PeerId: PeerPresence]
|
public let presence:PeerPresence?
|
||||||
|
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer] = [:], presence: PeerPresence? = nil) {
|
||||||
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer], peerPresences: [PeerId: PeerPresence]) {
|
|
||||||
self.participant = participant
|
self.participant = participant
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.peers = peers
|
self.peers = peers
|
||||||
self.peerPresences = peerPresences
|
self.presence = presence
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool {
|
public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool {
|
||||||
if lhs.participant != rhs.participant {
|
if let lhsPresence = lhs.presence, let rhsPresence = rhs.presence {
|
||||||
|
if !lhsPresence.isEqual(to: rhsPresence) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if(lhs.presence != nil) != (rhs.presence != nil) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer)
|
return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer)
|
||||||
}
|
}
|
||||||
|
@ -116,11 +116,14 @@ public enum AddPeerAdminError {
|
|||||||
case addMemberError(AddPeerMemberError)
|
case addMemberError(AddPeerMemberError)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal<Void, AddPeerAdminError> {
|
public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId, adminRightsFlags:TelegramChannelAdminRightsFlags = []) -> Signal<Void, AddPeerAdminError> {
|
||||||
return account.postbox.modify { modifier -> Signal<Void, AddPeerAdminError> in
|
return account.postbox.modify { modifier -> Signal<Void, AddPeerAdminError> in
|
||||||
if let peer = modifier.getPeer(peerId), let adminPeer = modifier.getPeer(adminId), let inputUser = apiInputUser(adminPeer) {
|
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) {
|
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.isEmpty ? defaultRights : adminRightsFlags).apiAdminRights))
|
||||||
|> map { [$0] }
|
|> map { [$0] }
|
||||||
|> `catch` { error -> Signal<[Api.Updates], AddPeerAdminError> in
|
|> `catch` { error -> Signal<[Api.Updates], AddPeerAdminError> in
|
||||||
if error.errorDescription == "USER_NOT_PARTICIPANT" {
|
if error.errorDescription == "USER_NOT_PARTICIPANT" {
|
||||||
@ -131,7 +134,7 @@ public func addPeerAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> S
|
|||||||
|> mapError { error -> AddPeerAdminError in
|
|> mapError { error -> AddPeerAdminError in
|
||||||
return .addMemberError(error)
|
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
|
|> mapError { error -> AddPeerAdminError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|
@ -19,21 +19,27 @@ public func removeRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Sign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func recentlySearchedPeers(postbox: Postbox) -> Signal<[Peer], NoError> {
|
public func recentlySearchedPeers(postbox: Postbox) -> Signal<[RenderedPeer], NoError> {
|
||||||
return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)])
|
return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)])
|
||||||
//|> take(1)
|
|> mapToSignal { view -> Signal<[RenderedPeer], NoError> in
|
||||||
|> mapToSignal { view -> Signal<[Peer], NoError> in
|
return postbox.modify { modifier -> [RenderedPeer] in
|
||||||
return postbox.modify { modifier -> [Peer] in
|
var result: [RenderedPeer] = []
|
||||||
var peers: [Peer] = []
|
|
||||||
if let view = view.views[.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)] as? OrderedItemListView {
|
if let view = view.views[.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)] as? OrderedItemListView {
|
||||||
for item in view.items {
|
for item in view.items {
|
||||||
let peerId = RecentPeerItemId(item.id).peerId
|
let peerId = RecentPeerItemId(item.id).peerId
|
||||||
if let peer = modifier.getPeer(peerId) {
|
if let peer = modifier.getPeer(peerId) {
|
||||||
peers.append(peer)
|
var peers = SimpleDictionary<PeerId, Peer>()
|
||||||
|
peers[peer.id] = peer
|
||||||
|
if let associatedPeerId = peer.associatedPeerId {
|
||||||
|
if let associatedPeer = modifier.getPeer(associatedPeerId) {
|
||||||
|
peers[associatedPeer.id] = associatedPeer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.append(RenderedPeer(peerId: peer.id, peers: peers))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return peers
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,4 +271,14 @@ public extension TelegramChannel {
|
|||||||
return false
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public final class TelegramUser: Peer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var indexName: PeerIndexNameRepresentation {
|
public var indexName: PeerIndexNameRepresentation {
|
||||||
return .personName(first: self.firstName ?? "", last: self.lastName ?? "", addressName: self.username)
|
return .personName(first: self.firstName ?? "", last: self.lastName ?? "", addressName: self.username, phoneNumber: self.phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
public let associatedPeerId: PeerId? = nil
|
public let associatedPeerId: PeerId? = nil
|
||||||
|
@ -34,6 +34,7 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox:
|
|||||||
modifier.updatePeerPresences(peerPresences)
|
modifier.updatePeerPresences(peerPresences)
|
||||||
|
|
||||||
let parsedParticipants = CachedChannelParticipants(apiParticipants: participants)
|
let parsedParticipants = CachedChannelParticipants(apiParticipants: participants)
|
||||||
|
|
||||||
modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in
|
modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in
|
||||||
if let currentData = currentData as? CachedChannelData {
|
if let currentData = currentData as? CachedChannelData {
|
||||||
return currentData.withUpdatedTopParticipants(parsedParticipants)
|
return currentData.withUpdatedTopParticipants(parsedParticipants)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user