mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
218 lines
9.6 KiB
Swift
218 lines
9.6 KiB
Swift
import Foundation
|
|
import Postbox
|
|
import SwiftSignalKit
|
|
import TelegramApi
|
|
import MtProtoKit
|
|
|
|
public struct SendAsPeer: Equatable {
|
|
public let peer: Peer
|
|
public let subscribers: Int32?
|
|
public let isPremiumRequired: Bool
|
|
|
|
public init(peer: Peer, subscribers: Int32?, isPremiumRequired: Bool) {
|
|
self.peer = peer
|
|
self.subscribers = subscribers
|
|
self.isPremiumRequired = isPremiumRequired
|
|
}
|
|
|
|
public static func ==(lhs: SendAsPeer, rhs: SendAsPeer) -> Bool {
|
|
return lhs.peer.isEqual(rhs.peer) && lhs.subscribers == rhs.subscribers && lhs.isPremiumRequired == rhs.isPremiumRequired
|
|
}
|
|
}
|
|
|
|
public final class CachedSendAsPeers: Codable {
|
|
public let peerIds: [PeerId]
|
|
public let premiumRequiredPeerIds: Set<PeerId>
|
|
public let timestamp: Int32
|
|
|
|
public init(peerIds: [PeerId], premiumRequiredPeerIds: Set<PeerId>, timestamp: Int32) {
|
|
self.peerIds = peerIds
|
|
self.premiumRequiredPeerIds = premiumRequiredPeerIds
|
|
self.timestamp = timestamp
|
|
}
|
|
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
|
|
|
self.peerIds = (try container.decode([Int64].self, forKey: "peerIds")).map(PeerId.init)
|
|
self.premiumRequiredPeerIds = Set((try container.decodeIfPresent([Int64].self, forKey: "premiumRequiredPeerIds") ?? []).map(PeerId.init))
|
|
self.timestamp = try container.decode(Int32.self, forKey: "timestamp")
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.container(keyedBy: StringCodingKey.self)
|
|
|
|
try container.encode(self.peerIds.map { $0.toInt64() }, forKey: "peerIds")
|
|
try container.encode(Array(self.premiumRequiredPeerIds).map { $0.toInt64() }, forKey: "premiumRequiredPeerIds")
|
|
try container.encode(self.timestamp, forKey: "timestamp")
|
|
}
|
|
}
|
|
|
|
func _internal_cachedPeerSendAsAvailablePeers(account: Account, peerId: PeerId) -> Signal<[SendAsPeer], NoError> {
|
|
let key = ValueBoxKey(length: 8)
|
|
key.setInt64(0, value: peerId.toInt64())
|
|
return account.postbox.transaction { transaction -> ([SendAsPeer], Int32)? in
|
|
let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key))?.get(CachedSendAsPeers.self)
|
|
if let cached = cached {
|
|
var peers: [SendAsPeer] = []
|
|
for peerId in cached.peerIds {
|
|
if let peer = transaction.getPeer(peerId) {
|
|
var subscribers: Int32?
|
|
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData {
|
|
subscribers = cachedData.participantsSummary.memberCount
|
|
}
|
|
peers.append(SendAsPeer(peer: peer, subscribers: subscribers, isPremiumRequired: cached.premiumRequiredPeerIds.contains(peer.id)))
|
|
}
|
|
}
|
|
return (peers, cached.timestamp)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|> mapToSignal { cachedPeersAndTimestamp -> Signal<[SendAsPeer], NoError> in
|
|
let initialSignal: Signal<[SendAsPeer], NoError>
|
|
if let (cachedPeers, _) = cachedPeersAndTimestamp {
|
|
initialSignal = .single(cachedPeers)
|
|
} else {
|
|
initialSignal = .complete()
|
|
}
|
|
return initialSignal
|
|
|> then(_internal_peerSendAsAvailablePeers(accountPeerId: account.peerId, network: account.network, postbox: account.postbox, peerId: peerId)
|
|
|> mapToSignal { peers -> Signal<[SendAsPeer], NoError> in
|
|
return account.postbox.transaction { transaction -> [SendAsPeer] in
|
|
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
|
var premiumRequiredPeerIds = Set<PeerId>()
|
|
for peer in peers {
|
|
if peer.isPremiumRequired {
|
|
premiumRequiredPeerIds.insert(peer.peer.id)
|
|
}
|
|
}
|
|
if let entry = CodableEntry(CachedSendAsPeers(peerIds: peers.map { $0.peer.id }, premiumRequiredPeerIds: premiumRequiredPeerIds, timestamp: currentTimestamp)) {
|
|
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key), entry: entry)
|
|
}
|
|
return peers
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
func _internal_peerSendAsAvailablePeers(accountPeerId: PeerId, network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[SendAsPeer], NoError> {
|
|
return postbox.transaction { transaction -> Peer? in
|
|
return transaction.getPeer(peerId)
|
|
}
|
|
|> mapToSignal { peer -> Signal<[SendAsPeer], NoError> in
|
|
guard let peer = peer else {
|
|
return .single([])
|
|
}
|
|
guard let inputPeer = apiInputPeer(peer) else {
|
|
return .single([])
|
|
}
|
|
|
|
if let channel = peer as? TelegramChannel {
|
|
if case .group = channel.info {
|
|
} else if case let .broadcast(info) = channel.info {
|
|
if !info.flags.contains(.messagesShouldHaveProfiles) {
|
|
return .single([])
|
|
}
|
|
}
|
|
} else {
|
|
return .single([])
|
|
}
|
|
|
|
return network.request(Api.functions.channels.getSendAs(peer: inputPeer))
|
|
|> map(Optional.init)
|
|
|> `catch` { _ -> Signal<Api.channels.SendAsPeers?, NoError> in
|
|
return .single(nil)
|
|
}
|
|
|> mapToSignal { result -> Signal<[SendAsPeer], NoError> in
|
|
guard let result = result else {
|
|
return .single([])
|
|
}
|
|
switch result {
|
|
case let .sendAsPeers(sendAsPeers, chats, _):
|
|
return postbox.transaction { transaction -> [SendAsPeer] in
|
|
var subscribers: [PeerId: Int32] = [:]
|
|
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
|
|
|
var premiumRequiredPeerIds = Set<PeerId>()
|
|
for sendAsPeer in sendAsPeers {
|
|
if case let .sendAsPeer(flags, peer) = sendAsPeer, (flags & (1 << 0)) != 0 {
|
|
premiumRequiredPeerIds.insert(peer.peerId)
|
|
}
|
|
}
|
|
for chat in chats {
|
|
if let groupOrChannel = parsedPeers.get(chat.peerId) {
|
|
switch chat {
|
|
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _):
|
|
if let participantsCount = participantsCount {
|
|
subscribers[groupOrChannel.id] = participantsCount
|
|
}
|
|
case let .chat(_, _, _, _, participantsCount, _, _, _, _, _):
|
|
subscribers[groupOrChannel.id] = participantsCount
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
updatePeers(transaction: transaction, accountPeerId: accountPeerId,peers: parsedPeers)
|
|
|
|
var peers: [Peer] = []
|
|
for chat in chats {
|
|
if let peer = transaction.getPeer(chat.peerId) {
|
|
peers.append(peer)
|
|
}
|
|
}
|
|
return peers.map { SendAsPeer(peer: $0, subscribers: subscribers[$0.id], isPremiumRequired: premiumRequiredPeerIds.contains($0.id)) }
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public enum UpdatePeerSendAsPeerError {
|
|
case generic
|
|
}
|
|
|
|
func _internal_updatePeerSendAsPeer(account: Account, peerId: PeerId, sendAs: PeerId) -> Signal<Never, UpdatePeerSendAsPeerError> {
|
|
return account.postbox.transaction { transaction -> (Api.InputPeer, Api.InputPeer)? in
|
|
if let peer = transaction.getPeer(peerId), let sendAsPeer = transaction.getPeer(sendAs), let inputPeer = apiInputPeer(peer), let sendAsInputPeer = apiInputPeerOrSelf(sendAsPeer, accountPeerId: account.peerId) {
|
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
|
|
if let cachedData = cachedData as? CachedChannelData {
|
|
return cachedData.withUpdatedSendAsPeerId(sendAs)
|
|
} else {
|
|
return cachedData
|
|
}
|
|
})
|
|
|
|
return (inputPeer, sendAsInputPeer)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|> castError(UpdatePeerSendAsPeerError.self)
|
|
|> mapToSignal { result in
|
|
guard let (inputPeer, sendAsInputPeer) = result else {
|
|
return .fail(.generic)
|
|
}
|
|
return account.network.request(Api.functions.messages.saveDefaultSendAs(peer: inputPeer, sendAs: sendAsInputPeer))
|
|
|> mapError { _ -> UpdatePeerSendAsPeerError in
|
|
return .generic
|
|
}
|
|
|> mapToSignal { result -> Signal<Never, UpdatePeerSendAsPeerError> in
|
|
return account.postbox.transaction { transaction in
|
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
|
|
if let cachedData = cachedData as? CachedChannelData {
|
|
return cachedData.withUpdatedSendAsPeerId(sendAs)
|
|
} else {
|
|
return cachedData
|
|
}
|
|
})
|
|
}
|
|
|> castError(UpdatePeerSendAsPeerError.self)
|
|
|> ignoreValues
|
|
}
|
|
}
|
|
}
|