no message

This commit is contained in:
Peter 2018-05-20 23:10:26 +02:00
parent 1bd781669c
commit ec6c3b451d
11 changed files with 385 additions and 233 deletions

View File

@ -386,8 +386,6 @@
D08CAA881ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */; };
D08CAA8C1ED81EDF0000FDA8 /* Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */; };
D08CAA8D1ED81EDF0000FDA8 /* Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */; };
D08D7E8120A0F3E10005D80C /* GroupPeerMembers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08D7E8020A0F3E10005D80C /* GroupPeerMembers.swift */; };
D08D7E8220A0F3E10005D80C /* GroupPeerMembers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08D7E8020A0F3E10005D80C /* GroupPeerMembers.swift */; };
D08F4A661E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
@ -922,7 +920,6 @@
D08CAA831ED8164B0000FDA8 /* Localization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localization.swift; sourceTree = "<group>"; };
D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizationInfo.swift; sourceTree = "<group>"; };
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localizations.swift; sourceTree = "<group>"; };
D08D7E8020A0F3E10005D80C /* GroupPeerMembers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupPeerMembers.swift; sourceTree = "<group>"; };
D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdDataTypes.swift; sourceTree = "<group>"; };
@ -1790,7 +1787,6 @@
D0C44B601FC616E200227BE0 /* SearchGroupMembers.swift */,
D0F8C39C20178B9B00236FC5 /* GroupFeedPeers.swift */,
D018EE042045E95000CBB130 /* CheckPeerChatServiceActions.swift */,
D08D7E8020A0F3E10005D80C /* GroupPeerMembers.swift */,
);
name = Peers;
sourceTree = "<group>";
@ -2092,7 +2088,6 @@
D0F3A8A21E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift in Sources */,
D01C7ED61EF5E468008305F1 /* ProxySettings.swift in Sources */,
D049EAE81E44B67100A2CD3A /* RecentPeerItem.swift in Sources */,
D08D7E8120A0F3E10005D80C /* GroupPeerMembers.swift in Sources */,
D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */,
C2E064681ECEEF0A00387BB8 /* TelegramMediaInvoice.swift in Sources */,
D0448C9F1E27F5EB005A61A7 /* Random.swift in Sources */,
@ -2448,7 +2443,6 @@
D01A21A71F38CDC700DDA104 /* SynchronizeSavedStickersOperation.swift in Sources */,
D0E68776207534CA0064BDB2 /* Api0.swift in Sources */,
D00C7CEC1E37A8540080C3D5 /* SetSecretChatMessageAutoremoveTimeoutInteractively.swift in Sources */,
D08D7E8220A0F3E10005D80C /* GroupPeerMembers.swift in Sources */,
D048B4AD20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift in Sources */,
D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */,
D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */,

View File

@ -1031,30 +1031,6 @@ public extension Api {
})
}
public static func editMessage(flags: Int32, peer: Api.InputPeer, id: Int32, message: String?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, geoPoint: Api.InputGeoPoint?) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) {
let buffer = Buffer()
buffer.appendInt32(97630429)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(id, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 13) != 0 {geoPoint!.serialize(buffer, true)}
return (FunctionDescription({return "(messages.editMessage flags: \(flags), peer: \(peer), id: \(id), message: \(String(describing: message)), replyMarkup: \(String(describing: replyMarkup)), entities: \(String(describing: entities)), geoPoint: \(String(describing: geoPoint)))"}), buffer, { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
public static func editInlineBotMessage(flags: Int32, id: Api.InputBotInlineMessageID, message: String?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) {
let buffer = Buffer()
buffer.appendInt32(319564933)
@ -1800,6 +1776,31 @@ public extension Api {
})
}
public static func editMessage(flags: Int32, peer: Api.InputPeer, id: Int32, message: String?, media: Api.InputMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, geoPoint: Api.InputGeoPoint?) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) {
let buffer = Buffer()
buffer.appendInt32(-1073683256)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(id, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 13) != 0 {geoPoint!.serialize(buffer, true)}
return (FunctionDescription({return "(messages.editMessage flags: \(flags), peer: \(peer), id: \(id), message: \(String(describing: message)), media: \(String(describing: media)), replyMarkup: \(String(describing: replyMarkup)), entities: \(String(describing: entities)), geoPoint: \(String(describing: geoPoint)))"}), buffer, { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
public static func getStickers(emoticon: String, hash: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Stickers?) {
let buffer = Buffer()
buffer.appendInt32(71126828)

View File

@ -132,15 +132,36 @@ public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Si
}
}
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChannelBannedRights) -> Signal<Void, NoError> {
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChannelBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> {
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|> mapToSignal { currentParticipant -> Signal<Void, NoError> in
return account.postbox.modify { modifier -> Signal<Void, NoError> in
if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer), let memberPeer = modifier.getPeer(memberId), let inputUser = apiInputUser(memberPeer) {
return account.network.request(Api.functions.channels.editBanned(channel: inputChannel, userId: inputUser, bannedRights: rights.apiBannedRights))
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
return account.postbox.modify { modifier -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer), let _ = modifier.getPeer(account.peerId), let memberPeer = modifier.getPeer(memberId), let inputUser = apiInputUser(memberPeer) {
let updatedParticipant: ChannelParticipant
if let currentParticipant = currentParticipant, case let .member(_, invitedAt, _, currentBanInfo) = currentParticipant {
let banInfo: ChannelParticipantBannedInfo?
if let rights = rights, !rights.flags.isEmpty {
banInfo = ChannelParticipantBannedInfo(rights: rights, restrictedBy: currentBanInfo?.restrictedBy ?? account.peerId, isMember: currentBanInfo?.isMember ?? true)
} else {
banInfo = nil
}
updatedParticipant = ChannelParticipant.member(id: memberId, invitedAt: invitedAt, adminInfo: nil, banInfo: banInfo)
} else {
let banInfo: ChannelParticipantBannedInfo?
if let rights = rights, !rights.flags.isEmpty {
banInfo = ChannelParticipantBannedInfo(rights: rights, restrictedBy: account.peerId, isMember: false)
} else {
banInfo = nil
}
updatedParticipant = ChannelParticipant.member(id: memberId, invitedAt: Int32(Date().timeIntervalSince1970), adminInfo: nil, banInfo: banInfo)
}
let effectiveRights: TelegramChannelBannedRights = rights ?? TelegramChannelBannedRights(flags: [], untilDate: 0)
return account.network.request(Api.functions.channels.editBanned(channel: inputChannel, userId: inputUser, bannedRights: effectiveRights.apiBannedRights))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
return account.postbox.modify { modifier -> Void in
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
return account.postbox.modify { modifier -> (ChannelParticipant?, RenderedChannelParticipant) in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
var updatedData = cachedData
@ -166,13 +187,13 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
var isKicked = false
var isBanned = false
if rights.flags.contains(.banReadMessages) {
if effectiveRights.flags.contains(.banReadMessages) {
isKicked = true
} else if !rights.flags.isEmpty {
} else if !effectiveRights.flags.isEmpty {
isBanned = true
}
let isMember = !wasKicked && !rights.flags.contains(.banReadMessages)
let isMember = !wasKicked && !effectiveRights.flags.contains(.banReadMessages)
if isKicked != wasKicked {
if let kickedCount = updatedData.participantsSummary.kickedCount {
@ -206,6 +227,18 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
return cachedData
}
})
var peers: [PeerId: Peer] = [:]
var presences: [PeerId: PeerPresence] = [:]
peers[memberPeer.id] = memberPeer
if let presence = modifier.getPeerPresence(peerId: memberPeer.id) {
presences[memberPeer.id] = presence
}
if case let .member(_, _, _, maybeBanInfo) = updatedParticipant, let banInfo = maybeBanInfo {
if let peer = modifier.getPeer(banInfo.restrictedBy) {
peers[peer.id] = peer
}
}
return (currentParticipant, RenderedChannelParticipant(participant: updatedParticipant, peer: memberPeer, peers: peers, presences: presences))
}
}
} else {

View File

@ -9,50 +9,82 @@ import Foundation
import MtProtoKitDynamic
#endif
public enum ChannelMembersFilter {
case none
public enum ChannelMembersCategoryFilter {
case all
case search(String)
}
public func channelMembers(postbox: Postbox, network: Network, peerId: PeerId, filter: ChannelMembersFilter = .none) -> Signal<[RenderedChannelParticipant], NoError> {
public enum ChannelMembersCategory {
case recent(ChannelMembersCategoryFilter)
case admins
case restricted(ChannelMembersCategoryFilter)
case banned(ChannelMembersCategoryFilter)
}
public func channelMembers(postbox: Postbox, network: Network, peerId: PeerId, category: ChannelMembersCategory = .recent(.all), offset: Int32 = 0, limit: Int32 = 64) -> Signal<[RenderedChannelParticipant], NoError> {
return postbox.modify { modifier -> Signal<[RenderedChannelParticipant], NoError> in
if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
let apiFilter: Api.ChannelParticipantsFilter
switch filter {
case .none:
apiFilter = .channelParticipantsRecent
case let .search(query):
apiFilter = .channelParticipantsSearch(q: query)
}
return network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100, hash: 0))
|> retryRequest
|> map { result -> [RenderedChannelParticipant] in
var items: [RenderedChannelParticipant] = []
switch result {
case let .channelParticipants(_, participants, users):
var peers: [PeerId: Peer] = [:]
var presences:[PeerId: PeerPresence] = [:]
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
if let presence = TelegramUserPresence(apiUser: user) {
presences[peer.id] = presence
}
}
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
if let peer = peers[participant.peerId] {
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences))
}
}
case .channelParticipantsNotModified:
break
switch category {
case let .recent(filter):
switch filter {
case .all:
apiFilter = .channelParticipantsRecent
case let .search(query):
apiFilter = .channelParticipantsSearch(q: query)
}
case .admins:
apiFilter = .channelParticipantsAdmins
case let .restricted(filter):
switch filter {
case .all:
apiFilter = .channelParticipantsBanned(q: "")
case let .search(query):
apiFilter = .channelParticipantsBanned(q: query)
}
case let .banned(filter):
switch filter {
case .all:
apiFilter = .channelParticipantsKicked(q: "")
case let .search(query):
apiFilter = .channelParticipantsKicked(q: query)
}
}
return network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: offset, limit: limit, hash: 0))
|> retryRequest
|> mapToSignal { result -> Signal<[RenderedChannelParticipant], NoError> in
return postbox.modify { modifier -> [RenderedChannelParticipant] in
var items: [RenderedChannelParticipant] = []
switch result {
case let .channelParticipants(_, participants, users):
var peers: [PeerId: Peer] = [:]
var presences: [PeerId: PeerPresence] = [:]
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
if let presence = TelegramUserPresence(apiUser: user) {
presences[peer.id] = presence
}
}
updatePeers(modifier: modifier, peers: Array(peers.values), update: { _, updated in
return updated
})
modifier.updatePeerPresences(presences)
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
if let peer = peers[participant.peerId] {
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences))
}
}
case .channelParticipantsNotModified:
break
}
return items
}
return items
}
} else {
return .single([])
}
} |> switchToLatest
} |> switchToLatest
}

View File

@ -13,8 +13,8 @@ public struct RenderedChannelParticipant: Equatable {
public let participant: ChannelParticipant
public let peer: Peer
public let peers: [PeerId: Peer]
public let presences:[PeerId: PeerPresence]
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer] = [:], presences:[PeerId : PeerPresence] = [:]) {
public let presences: [PeerId: PeerPresence]
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer] = [:], presences: [PeerId: PeerPresence] = [:]) {
self.participant = participant
self.peer = peer
self.peers = peers
@ -34,47 +34,47 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsBanned(q: ""), offset: 0, limit: 0, hash: 0))
let kicked = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 0, hash: 0))
return combineLatest(admins, members, banned, kicked)
|> mapToSignal { admins, members, banned, kicked -> Signal<Void, MTRpcError> in
return account.postbox.modify { modifier -> Void in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
let adminCount: Int32
switch admins {
case let .channelParticipants(count, _, _):
adminCount = count
case .channelParticipantsNotModified:
assertionFailure()
adminCount = 0
}
let memberCount: Int32
switch members {
case let .channelParticipants(count, _, _):
memberCount = count
case .channelParticipantsNotModified:
assertionFailure()
memberCount = 0
}
let bannedCount: Int32
switch banned {
case let .channelParticipants(count, _, _):
bannedCount = count
case .channelParticipantsNotModified:
assertionFailure()
bannedCount = 0
}
let kickedCount: Int32
switch kicked {
case let .channelParticipants(count, _, _):
kickedCount = count
case .channelParticipantsNotModified:
assertionFailure()
kickedCount = 0
}
return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount, kickedCount: kickedCount))
|> mapToSignal { admins, members, banned, kicked -> Signal<Void, MTRpcError> in
return account.postbox.modify { modifier -> Void in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
let adminCount: Int32
switch admins {
case let .channelParticipants(count, _, _):
adminCount = count
case .channelParticipantsNotModified:
assertionFailure()
adminCount = 0
}
return current
})
} |> mapError { _ -> MTRpcError in return MTRpcError(errorCode: 0, errorDescription: "") }
let memberCount: Int32
switch members {
case let .channelParticipants(count, _, _):
memberCount = count
case .channelParticipantsNotModified:
assertionFailure()
memberCount = 0
}
let bannedCount: Int32
switch banned {
case let .channelParticipants(count, _, _):
bannedCount = count
case .channelParticipantsNotModified:
assertionFailure()
bannedCount = 0
}
let kickedCount: Int32
switch kicked {
case let .channelParticipants(count, _, _):
kickedCount = count
case .channelParticipantsNotModified:
assertionFailure()
kickedCount = 0
}
return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount, kickedCount: kickedCount))
}
return current
})
} |> mapError { _ -> MTRpcError in return MTRpcError(errorCode: 0, errorDescription: "") }
}
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()

View File

@ -1,20 +0,0 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
#else
import Postbox
import SwiftSignalKit
#endif
public final class GroupPeerMembersContext {
private let postbox: Postbox
private let network: Network
private let peerId: PeerId
public init(postbox: Postbox, network: Network, peerId: PeerId) {
self.postbox = postbox
self.network = network
self.peerId = peerId
}
}

View File

@ -225,15 +225,34 @@ public func fetchChannelParticipant(account: Account, peerId: PeerId, participan
} |> switchToLatest
}
public func updatePeerAdminRights(account: Account, peerId: PeerId, adminId: PeerId, rights: TelegramChannelAdminRights) -> Signal<Void, UpdatePeerAdminRightsError> {
public func updatePeerAdminRights(account: Account, peerId: PeerId, adminId: PeerId, rights: TelegramChannelAdminRights) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdatePeerAdminRightsError> {
return fetchChannelParticipant(account: account, peerId: peerId, participantId: adminId)
|> mapError { error -> UpdatePeerAdminRightsError in
return .generic
}
|> mapToSignal { currentParticipant -> Signal<Void, UpdatePeerAdminRightsError> in
return account.postbox.modify { modifier -> Signal<Void, UpdatePeerAdminRightsError> in
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdatePeerAdminRightsError> in
return account.postbox.modify { modifier -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdatePeerAdminRightsError> 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) {
let updatedParticipant: ChannelParticipant
if let currentParticipant = currentParticipant, case let .member(_, invitedAt, currentAdminInfo, _) = currentParticipant {
let adminInfo: ChannelParticipantAdminInfo?
if !rights.flags.isEmpty {
adminInfo = ChannelParticipantAdminInfo(rights: rights, promotedBy: currentAdminInfo?.promotedBy ?? account.peerId, canBeEditedByAccountPeer: true)
} else {
adminInfo = nil
}
updatedParticipant = ChannelParticipant.member(id: adminId, invitedAt: invitedAt, adminInfo: adminInfo, banInfo: nil)
} else {
let adminInfo: ChannelParticipantAdminInfo?
if !rights.flags.isEmpty {
adminInfo = ChannelParticipantAdminInfo(rights: rights, promotedBy: account.peerId, canBeEditedByAccountPeer: true)
} else {
adminInfo = nil
}
updatedParticipant = ChannelParticipant.member(id: adminId, invitedAt: Int32(Date().timeIntervalSince1970), adminInfo: adminInfo, banInfo: nil)
}
return account.network.request(Api.functions.channels.editAdmin(channel: inputChannel, userId: inputUser, adminRights: rights.apiAdminRights))
|> map { [$0] }
|> `catch` { error -> Signal<[Api.Updates], UpdatePeerAdminRightsError> in
@ -253,11 +272,11 @@ public func updatePeerAdminRights(account: Account, peerId: PeerId, adminId: Pee
}
return .fail(.generic)
}
|> mapToSignal { result -> Signal<Void, UpdatePeerAdminRightsError> in
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdatePeerAdminRightsError> in
for updates in result {
account.stateManager.addUpdates(updates)
}
return account.postbox.modify { modifier -> Void in
return account.postbox.modify { modifier -> (ChannelParticipant?, RenderedChannelParticipant) in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData, let adminCount = cachedData.participantsSummary.adminCount {
var updatedAdminCount = adminCount
@ -283,6 +302,18 @@ public func updatePeerAdminRights(account: Account, peerId: PeerId, adminId: Pee
return cachedData
}
})
var peers: [PeerId: Peer] = [:]
var presences: [PeerId: PeerPresence] = [:]
peers[adminPeer.id] = adminPeer
if let presence = modifier.getPeerPresence(peerId: adminPeer.id) {
presences[adminPeer.id] = presence
}
if case let .member(_, _, maybeAdminInfo, _) = updatedParticipant, let adminInfo = maybeAdminInfo {
if let peer = modifier.getPeer(adminInfo.promotedBy) {
peers[peer.id] = peer
}
}
return (currentParticipant, RenderedChannelParticipant(participant: updatedParticipant, peer: adminPeer, peers: peers, presences: presences))
} |> mapError { _ -> UpdatePeerAdminRightsError in return .generic }
}
} else {

View File

@ -65,44 +65,48 @@ func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods
return .ready(.forward(forwardInfo))
} else if let contextResult = contextResult {
return .ready(.chatContextResult(contextResult))
} else if let media = media.first {
if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) {
if let reference = image.reference, case let .cloud(id, accessHash) = reference {
return .ready(.media(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: id, accessHash: accessHash), ttlSeconds: nil), text))
} else {
return .upload(uploadedMediaImageContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, peerId: peerId, image: image, text: text, autoremoveAttribute: autoremoveAttribute))
}
} else if let file = media as? TelegramMediaFile {
if let resource = file.resource as? CloudDocumentMediaResource {
if peerId.namespace == Namespaces.Peer.SecretChat {
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, peerId: peerId, messageId: messageId, text: text, attributes: attributes, file: file))
} else {
return .ready(.media(Api.InputMedia.inputMediaDocument(flags: 0, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash), ttlSeconds: nil), text))
}
} else {
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, peerId: peerId, messageId: messageId, text: text, attributes: attributes, file: file))
}
} else if let contact = media as? TelegramMediaContact {
let input = Api.InputMedia.inputMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName)
return .ready(.media(input, text))
} else if let map = media as? TelegramMediaMap {
let input: Api.InputMedia
if let liveBroadcastingTimeout = map.liveBroadcastingTimeout {
input = .inputMediaGeoLive(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), period: liveBroadcastingTimeout)
} else if let venue = map.venue {
input = .inputMediaVenue(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "", venueType: venue.type ?? "")
} else {
input = .inputMediaGeoPoint(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude))
}
return .ready(.media(input, text))
} else {
return .ready(.text(text))
}
} else if let media = media.first, let mediaResult = mediaContentToUpload(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, peerId: peerId, media: media, text: text, autoremoveAttribute: autoremoveAttribute, messageId: messageId, attributes: attributes) {
return mediaResult
} else {
return .ready(.text(text))
}
}
func mediaContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods: AccountAuxiliaryMethods, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, peerId: PeerId, media: Media, text: String, autoremoveAttribute: AutoremoveTimeoutMessageAttribute?, messageId: MessageId?, attributes: [MessageAttribute]) -> PendingMessageUploadContent? {
if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) {
if let reference = image.reference, case let .cloud(id, accessHash) = reference {
return .ready(.media(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: id, accessHash: accessHash), ttlSeconds: nil), text))
} else {
return .upload(uploadedMediaImageContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, peerId: peerId, image: image, text: text, autoremoveAttribute: autoremoveAttribute))
}
} else if let file = media as? TelegramMediaFile {
if let resource = file.resource as? CloudDocumentMediaResource {
if peerId.namespace == Namespaces.Peer.SecretChat {
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, peerId: peerId, messageId: messageId, text: text, attributes: attributes, file: file))
} else {
return .ready(.media(Api.InputMedia.inputMediaDocument(flags: 0, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash), ttlSeconds: nil), text))
}
} else {
return .upload(uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, peerId: peerId, messageId: messageId, text: text, attributes: attributes, file: file))
}
} else if let contact = media as? TelegramMediaContact {
let input = Api.InputMedia.inputMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName)
return .ready(.media(input, text))
} else if let map = media as? TelegramMediaMap {
let input: Api.InputMedia
if let liveBroadcastingTimeout = map.liveBroadcastingTimeout {
input = .inputMediaGeoLive(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), period: liveBroadcastingTimeout)
} else if let venue = map.venue {
input = .inputMediaVenue(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "", venueType: venue.type ?? "")
} else {
input = .inputMediaGeoPoint(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude))
}
return .ready(.media(input, text))
} else {
return nil
}
}
private enum PredownloadedResource {
case localReference(CachedSentMediaReferenceKey?)
case media(Media)

View File

@ -13,6 +13,9 @@ public func removePeerMember(account: Account, peerId: PeerId, memberId: PeerId)
if peerId.namespace == Namespaces.Peer.CloudChannel {
return updateChannelMemberBannedRights(account: account, peerId: peerId, memberId: memberId, rights: TelegramChannelBannedRights(flags: [.banReadMessages], untilDate: 0))
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
}
return account.postbox.modify { modifier -> Signal<Void, NoError> in

View File

@ -9,72 +9,146 @@ import Foundation
import MtProtoKitDynamic
#endif
public func requestEditMessage(account: Account, messageId: MessageId, text: String, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false) -> Signal<Bool, NoError> {
return account.postbox.modify { modifier -> (Peer?, SimpleDictionary<PeerId, Peer>) in
guard let message = modifier.getMessage(messageId) else {
return (nil, SimpleDictionary())
}
public enum RequestEditMessageMedia {
case keep
case update(Media)
}
if text.isEmpty {
for media in message.media {
switch media {
case _ as TelegramMediaImage, _ as TelegramMediaFile:
break
default:
return (nil, SimpleDictionary())
public enum RequestEditMessageResult {
case progress(Float)
case done(Bool)
}
public func requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false) -> Signal<RequestEditMessageResult, NoError> {
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
switch media {
case .keep:
uploadedMedia = .single(.progress(0.0)) |> then(.single(nil))
case let .update(media):
if let uploadData = mediaContentToUpload(network: account.network, postbox: account.postbox, auxiliaryMethods: account.auxiliaryMethods, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, peerId: messageId.peerId, media: media, text: "", autoremoveAttribute: nil, messageId: nil, attributes: []) {
switch uploadData {
case let .ready(content):
uploadedMedia = .single(.content(content))
case let .upload(upload):
uploadedMedia = .single(.progress(0.027)) |> then(upload)
|> map { result -> PendingMessageUploadedContentResult? in
switch result {
case let .progress(value):
return .progress(max(value, 0.027))
case let .content(content):
return .content(content)
}
}
|> `catch` { _ -> Signal<PendingMessageUploadedContentResult?, NoError> in
return .single(nil)
}
}
} else {
uploadedMedia = .single(nil)
}
}
var peers = SimpleDictionary<PeerId, Peer>()
if let entities = entities {
for peerId in entities.associatedPeerIds {
if let peer = modifier.getPeer(peerId) {
peers[peer.id] = peer
}
}
}
return (modifier.getPeer(messageId.peerId), peers)
}
|> mapToSignal { peer, associatedPeers in
if let peer = peer, let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 1 << 11
return uploadedMedia
|> mapToSignal { uploadedMediaResult -> Signal<RequestEditMessageResult, NoError> in
var pendingMediaContent: PendingMessageUploadedContent?
if let uploadedMediaResult = uploadedMediaResult {
switch uploadedMediaResult {
case let .progress(value):
return .single(.progress(value))
case let .content(content):
pendingMediaContent = content
}
}
return account.postbox.modify { modifier -> (Peer?, SimpleDictionary<PeerId, Peer>) in
guard let message = modifier.getMessage(messageId) else {
return (nil, SimpleDictionary())
}
if text.isEmpty {
for media in message.media {
switch media {
case _ as TelegramMediaImage, _ as TelegramMediaFile:
break
default:
return (nil, SimpleDictionary())
}
}
}
var peers = SimpleDictionary<PeerId, Peer>()
var apiEntities: [Api.MessageEntity]?
if let entities = entities {
apiEntities = apiTextAttributeEntities(entities, associatedPeers: associatedPeers)
flags |= Int32(1 << 3)
}
if disableUrlPreview {
flags |= Int32(1 << 1)
}
return account.network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, replyMarkup: nil, entities: apiEntities, geoPoint: nil))
|> map { result -> Api.Updates? in
return result
}
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
if error.errorDescription == "MESSAGE_NOT_MODIFIED" {
return .single(nil)
} else {
return .fail(error)
for peerId in entities.associatedPeerIds {
if let peer = modifier.getPeer(peerId) {
peers[peer.id] = peer
}
}
|> mapError { _ -> NoError in
return NoError()
}
return (modifier.getPeer(messageId.peerId), peers)
}
|> mapToSignal { peer, associatedPeers -> Signal<RequestEditMessageResult, NoError> in
if let peer = peer, let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 1 << 11
var apiEntities: [Api.MessageEntity]?
if let entities = entities {
apiEntities = apiTextAttributeEntities(entities, associatedPeers: associatedPeers)
flags |= Int32(1 << 3)
}
|> mapToSignal { result -> Signal<Bool, NoError> in
if let result = result {
account.stateManager.addUpdates(result)
return .single(true)
} else {
return .single(false)
if disableUrlPreview {
flags |= Int32(1 << 1)
}
var inputMedia: Api.InputMedia? = nil
if let pendingMediaContent = pendingMediaContent {
switch pendingMediaContent {
case let .media(media, _):
inputMedia = media
default:
break
}
}
} else {
return .single(false)
if let _ = inputMedia {
flags |= Int32(1 << 14)
}
return account.network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, geoPoint: nil))
|> map { result -> Api.Updates? in
return result
}
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
if error.errorDescription == "MESSAGE_NOT_MODIFIED" {
return .single(nil)
} else {
return .fail(error)
}
}
|> mapError { _ -> NoError in
return NoError()
}
|> mapToSignal { result -> Signal<RequestEditMessageResult, NoError> in
if let result = result {
return account.postbox.modify { modifier -> RequestEditMessageResult in
var toMedia: Media?
if let message = result.messages.first.flatMap(StoreMessage.init(apiMessage:)) {
toMedia = message.media.first
}
if case let .update(fromMedia) = media, let toMedia = toMedia {
applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: account.postbox)
}
account.stateManager.addUpdates(result)
return .done(true)
}
} else {
return .single(.done(false))
}
}
} else {
return .single(.done(false))
}
}
}
}
@ -91,7 +165,7 @@ public func requestEditLiveLocation(postbox: Postbox, network: Network, stateMan
} else {
flags |= 1 << 12
}
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: nil, replyMarkup: nil, entities: nil, geoPoint: coordinate.flatMap { Api.InputGeoPoint.inputGeoPoint(lat: $0.latitude, long: $0.longitude) }))
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: nil, media: nil, replyMarkup: nil, entities: nil, geoPoint: coordinate.flatMap { Api.InputGeoPoint.inputGeoPoint(lat: $0.latitude, long: $0.longitude) }))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)

View File

@ -33,7 +33,7 @@ public func searchGroupMembers(postbox: Postbox, network: Network, peerId: PeerI
return searchLocalGroupMembers(postbox: postbox, peerId: peerId, query: query)
|> mapToSignal { local -> Signal<[Peer], NoError> in
return .single(local)
|> then(channelMembers(postbox: postbox, network: network, peerId: peerId, filter: .search(query))
|> then(channelMembers(postbox: postbox, network: network, peerId: peerId, category: .recent(.search(query)))
|> map { participants -> [Peer] in
var result: [Peer] = local
let existingIds = Set(local.map { $0.id })