This commit is contained in:
overtake 2017-06-09 14:27:28 +03:00
commit e9093ccf99
7 changed files with 167 additions and 36 deletions

View File

@ -700,6 +700,15 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu
let message = modifier.getMessage(id)
if let message = message {
if let channel = message.peers[message.id.peerId] as? TelegramChannel {
switch channel.participationStatus {
case .kicked, .left:
return (nil, false)
case .member:
break
}
}
var foundReadState = false
var isUnread = true
if let readState = modifier.getCombinedPeerReadState(id.peerId) {

View File

@ -24,28 +24,35 @@ public struct CachedChannelParticipantsSummary: Coding, Equatable {
public let memberCount: Int32?
public let adminCount: Int32?
public let bannedCount: Int32?
public let kickedCount: Int32?
init(memberCount: Int32?, adminCount: Int32?, bannedCount: Int32?) {
init(memberCount: Int32?, adminCount: Int32?, bannedCount: Int32?, kickedCount: Int32?) {
self.memberCount = memberCount
self.adminCount = adminCount
self.bannedCount = bannedCount
self.kickedCount = kickedCount
}
public init(decoder: Decoder) {
if let memberCount = decoder.decodeOptionalInt32ForKey("p.m") {
self.memberCount = memberCount
} else {
self.memberCount = 0
self.memberCount = nil
}
if let adminCount = decoder.decodeOptionalInt32ForKey("p.a") {
self.adminCount = adminCount
} else {
self.adminCount = 0
self.adminCount = nil
}
if let bannedCount = decoder.decodeOptionalInt32ForKey("p.b") {
self.bannedCount = bannedCount
} else {
self.bannedCount = 0
self.bannedCount = nil
}
if let kickedCount = decoder.decodeOptionalInt32ForKey("p.k") {
self.kickedCount = kickedCount
} else {
self.kickedCount = nil
}
}
@ -65,22 +72,31 @@ public struct CachedChannelParticipantsSummary: Coding, Equatable {
} else {
encoder.encodeNil(forKey: "p.b")
}
if let kickedCount = self.kickedCount {
encoder.encodeInt32(kickedCount, forKey: "p.k")
} else {
encoder.encodeNil(forKey: "p.k")
}
}
public static func ==(lhs: CachedChannelParticipantsSummary, rhs: CachedChannelParticipantsSummary) -> Bool {
return lhs.memberCount == rhs.memberCount && lhs.adminCount == rhs.adminCount && lhs.bannedCount == rhs.bannedCount
return lhs.memberCount == rhs.memberCount && lhs.adminCount == rhs.adminCount && lhs.bannedCount == rhs.bannedCount && lhs.kickedCount == rhs.kickedCount
}
public func withUpdatedMemberCount(_ memberCount: Int32?) -> CachedChannelParticipantsSummary {
return CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: self.adminCount, bannedCount: self.bannedCount)
return CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: self.adminCount, bannedCount: self.bannedCount, kickedCount: self.kickedCount)
}
public func withUpdatedAdminCount(_ adminCount: Int32?) -> CachedChannelParticipantsSummary {
return CachedChannelParticipantsSummary(memberCount: self.memberCount, adminCount: adminCount, bannedCount: self.bannedCount)
return CachedChannelParticipantsSummary(memberCount: self.memberCount, adminCount: adminCount, bannedCount: self.bannedCount, kickedCount: self.kickedCount)
}
public func withUpdatedBannedCount(_ bannedCount: Int32?) -> CachedChannelParticipantsSummary {
return CachedChannelParticipantsSummary(memberCount: self.memberCount, adminCount: self.adminCount, bannedCount: bannedCount)
return CachedChannelParticipantsSummary(memberCount: self.memberCount, adminCount: self.adminCount, bannedCount: bannedCount, kickedCount: self.kickedCount)
}
public func withUpdatedKickedCount(_ kickedCount: Int32?) -> CachedChannelParticipantsSummary {
return CachedChannelParticipantsSummary(memberCount: self.memberCount, adminCount: self.adminCount, bannedCount: self.bannedCount, kickedCount: kickedCount)
}
}
@ -99,7 +115,7 @@ public final class CachedChannelData: CachedPeerData {
init() {
self.flags = []
self.about = nil
self.participantsSummary = CachedChannelParticipantsSummary(memberCount: nil, adminCount: nil, bannedCount: nil)
self.participantsSummary = CachedChannelParticipantsSummary(memberCount: nil, adminCount: nil, bannedCount: nil, kickedCount: nil)
self.exportedInvitation = nil
self.botInfos = []
self.topParticipants = nil

View File

@ -9,10 +9,22 @@ import Foundation
import MtProtoKitDynamic
#endif
public func channelBlacklist(account: Account, peerId: PeerId) -> Signal<[RenderedChannelParticipant], NoError> {
private enum ChannelBlacklistFilter {
case restricted
case banned
}
private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: ChannelBlacklistFilter) -> Signal<[RenderedChannelParticipant], NoError> {
return account.postbox.modify { modifier -> Signal<[RenderedChannelParticipant], NoError> in
if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 100))
let apiFilter: Api.ChannelParticipantsFilter
switch filter {
case .restricted:
apiFilter = .channelParticipantsBanned(q: "")
case .banned:
apiFilter = .channelParticipantsKicked(q: "")
}
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100))
|> retryRequest
|> map { result -> [RenderedChannelParticipant] in
var items: [RenderedChannelParticipant] = []
@ -43,25 +55,105 @@ public func channelBlacklist(account: Account, peerId: PeerId) -> Signal<[Render
} |> switchToLatest
}
public func removeChannelBlacklistedPeer(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, NoError> {
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.kickFromChannel(channel: inputChannel, userId: inputUser, kicked: .boolFalse))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
account.stateManager.addUpdates(result)
return account.postbox.modify { modifier -> Void in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData, let bannedCount = cachedData.participantsSummary.bannedCount {
return cachedData.withUpdatedParticipantsSummary(cachedData.participantsSummary.withUpdatedBannedCount(max(bannedCount - 1, 0)))
} else {
return cachedData
}
})
}
public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Signal<[RenderedChannelParticipant], NoError> {
return combineLatest(fetchChannelBlacklist(account: account, peerId: peerId, filter: .restricted), fetchChannelBlacklist(account: account, peerId: peerId, filter: .banned))
|> map { restricted, banned -> [RenderedChannelParticipant] in
var result: [RenderedChannelParticipant] = []
var peerIds = Set<PeerId>()
for participant in restricted {
if !peerIds.contains(participant.peer.id) {
peerIds.insert(participant.peer.id)
result.append(participant)
}
} else {
return .complete()
}
for participant in banned {
if !peerIds.contains(participant.peer.id) {
peerIds.insert(participant.peer.id)
result.append(participant)
}
}
return result
}
} |> switchToLatest
}
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChannelBannedRights) -> Signal<Void, 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))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
return account.postbox.modify { modifier -> Void in
modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
var updatedData = cachedData
var wasKicked = false
var wasBanned = false
var wasMember = false
if let currentParticipant = currentParticipant {
switch currentParticipant {
case .creator:
break
case let .member(_, _, _, banInfo):
if let banInfo = banInfo {
if banInfo.flags.contains(.banReadMessages) {
wasKicked = true
} else if !banInfo.flags.isEmpty {
wasBanned = true
}
}
wasMember = true
}
}
var isKicked = false
var isBanned = false
if rights.flags.contains(.banReadMessages) {
isKicked = true
} else if !rights.flags.isEmpty {
isBanned = true
}
let isMember = !wasKicked && !rights.flags.contains(.banReadMessages)
if isKicked != wasKicked {
if let kickedCount = updatedData.participantsSummary.kickedCount {
updatedData = updatedData.withUpdatedParticipantsSummary(updatedData.participantsSummary.withUpdatedKickedCount(max(0, kickedCount + (isKicked ? 1 : -1))))
}
}
if isBanned != wasBanned {
if let bannedCount = updatedData.participantsSummary.bannedCount {
updatedData = updatedData.withUpdatedParticipantsSummary(updatedData.participantsSummary.withUpdatedBannedCount(max(0, bannedCount + (isBanned ? 1 : -1))))
}
}
if isMember != wasMember {
if let memberCount = updatedData.participantsSummary.memberCount {
updatedData = updatedData.withUpdatedParticipantsSummary(updatedData.participantsSummary.withUpdatedMemberCount(max(0, memberCount + (isMember ? 1 : -1))))
}
if !isMember, let topParticipants = updatedData.topParticipants {
var updatedParticipants = topParticipants.participants
if let index = updatedParticipants.index(where: { $0.peerId == memberId }) {
updatedParticipants.remove(at: index)
updatedData = updatedData.withUpdatedTopParticipants(CachedChannelParticipants(participants: updatedParticipants))
}
}
}
return updatedData
} else {
return cachedData
}
})
}
}
} else {
return .complete()
}
} |> switchToLatest
}
}

View File

@ -36,9 +36,10 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
let admins = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 0))
let members = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 0))
let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 0))
return combineLatest(admins, members, banned)
|> mapToSignal { admins, members, banned -> Signal<Void, MTRpcError> in
let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsBanned(q: ""), offset: 0, limit: 0))
let kicked = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 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 {
@ -57,7 +58,12 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
case let .channelParticipants(count, _, _):
bannedCount = count
}
return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount))
let kickedCount: Int32
switch kicked {
case let .channelParticipants(count, _, _):
kickedCount = count
}
return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount, kickedCount: kickedCount))
}
return current
})

View File

@ -202,7 +202,7 @@ public enum UpdatePeerAdminRightsError {
case addMemberError(AddPeerMemberError)
}
private func fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
func fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
return account.postbox.modify { modifier -> Signal<ChannelParticipant?, NoError> in
if let peer = modifier.getPeer(peerId), let adminPeer = modifier.getPeer(participantId), let inputUser = apiInputUser(adminPeer) {
if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {

View File

@ -64,6 +64,14 @@ func messageContentToUpload(network: Network, postbox: Postbox, transformOutgoin
} 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))
} else if let map = media as? TelegramMediaMap {
let input: Api.InputMedia
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 ?? "")
} else {
input = .inputMediaGeoPoint(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude))
}
return .ready(.media(input))
} else {
return .ready(.text(text))
}

View File

@ -246,7 +246,7 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos
return previous.withUpdatedFlags(channelFlags)
.withUpdatedAbout(about)
.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: kickedCount))
.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: bannedCount, kickedCount: kickedCount))
.withUpdatedExportedInvitation(ExportedInvitation(apiExportedInvite: apiExportedInvite))
.withUpdatedBotInfos(botInfos)
.withUpdatedPinnedMessageId(pinnedMessageId)