mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Update API
This commit is contained in:
@@ -2472,6 +2472,21 @@ public extension Api.functions.channels {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.channels {
|
||||||
|
static func getChannelRecommendations(channelId: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Chats>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-873707987)
|
||||||
|
channelId.serialize(buffer, true)
|
||||||
|
return (FunctionDescription(name: "channels.getChannelRecommendations", parameters: [("channelId", String(describing: channelId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.messages.Chats?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.messages.Chats
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.channels {
|
public extension Api.functions.channels {
|
||||||
static func getChannels(id: [Api.InputChannel]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Chats>) {
|
static func getChannels(id: [Api.InputChannel]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Chats>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ public struct Namespaces {
|
|||||||
public static let storySendAsPeerIds: Int8 = 29
|
public static let storySendAsPeerIds: Int8 = 29
|
||||||
public static let cachedChannelBoosts: Int8 = 31
|
public static let cachedChannelBoosts: Int8 = 31
|
||||||
public static let displayedMessageNotifications: Int8 = 32
|
public static let displayedMessageNotifications: Int8 = 32
|
||||||
|
public static let recommendedChannels: Int8 = 33
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UnorderedItemList {
|
public struct UnorderedItemList {
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case setSameChatWallpaper(wallpaper: TelegramWallpaper)
|
case setSameChatWallpaper(wallpaper: TelegramWallpaper)
|
||||||
case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, months: Int32)
|
case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, months: Int32)
|
||||||
case giveawayLaunched
|
case giveawayLaunched
|
||||||
|
case joinedChannel
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||||
@@ -209,6 +210,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)), months: decoder.decodeInt32ForKey("months", orElse: 0))
|
self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)), months: decoder.decodeInt32ForKey("months", orElse: 0))
|
||||||
case 37:
|
case 37:
|
||||||
self = .giveawayLaunched
|
self = .giveawayLaunched
|
||||||
|
case 38:
|
||||||
|
self = .joinedChannel
|
||||||
default:
|
default:
|
||||||
self = .unknown
|
self = .unknown
|
||||||
}
|
}
|
||||||
@@ -401,6 +404,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
encoder.encodeInt32(months, forKey: "months")
|
encoder.encodeInt32(months, forKey: "months")
|
||||||
case .giveawayLaunched:
|
case .giveawayLaunched:
|
||||||
encoder.encodeInt32(37, forKey: "_rawValue")
|
encoder.encodeInt32(37, forKey: "_rawValue")
|
||||||
|
case .joinedChannel:
|
||||||
|
encoder.encodeInt32(38, forKey: "_rawValue")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import Foundation
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramApi
|
||||||
|
import MtProtoKit
|
||||||
|
|
||||||
|
final class CachedRecommendedChannels: Codable {
|
||||||
|
public let peerIds: [EnginePeer.Id]
|
||||||
|
public let isHidden: Bool
|
||||||
|
|
||||||
|
public init(peerIds: [EnginePeer.Id], isHidden: Bool) {
|
||||||
|
self.peerIds = peerIds
|
||||||
|
self.isHidden = isHidden
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
|
self.peerIds = try container.decode([Int64].self, forKey: "l").map(EnginePeer.Id.init)
|
||||||
|
self.isHidden = try container.decode(Bool.self, forKey: "h")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
|
try container.encode(self.peerIds.map { $0.toInt64() }, forKey: "l")
|
||||||
|
try container.encode(self.isHidden, forKey: "h")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func entryId(peerId: EnginePeer.Id) -> ItemCacheEntryId {
|
||||||
|
let cacheKey = ValueBoxKey(length: 8)
|
||||||
|
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||||
|
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.recommendedChannels, key: cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_requestRecommendedChannels(account: Account, peerId: EnginePeer.Id) -> Signal<Never, NoError> {
|
||||||
|
return account.postbox.transaction { transaction -> Peer? in
|
||||||
|
guard let channel = transaction.getPeer(peerId) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if let entry = transaction.retrieveItemCacheEntry(id: entryId(peerId: peerId))?.get(CachedRecommendedChannels.self), !entry.peerIds.isEmpty {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> mapToSignal { channel in
|
||||||
|
guard let inputChannel = channel.flatMap(apiInputChannel) else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
return account.network.request(Api.functions.channels.getChannelRecommendations(channelId: inputChannel))
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
|
return account.postbox.transaction { transaction -> [EnginePeer] in
|
||||||
|
let chats: [Api.Chat]
|
||||||
|
let parsedPeers: AccumulatedPeers
|
||||||
|
switch result {
|
||||||
|
case let .chats(apiChats):
|
||||||
|
chats = apiChats
|
||||||
|
case let .chatsSlice(_, apiChats):
|
||||||
|
chats = apiChats
|
||||||
|
}
|
||||||
|
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||||
|
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
||||||
|
var peers: [EnginePeer] = []
|
||||||
|
for chat in chats {
|
||||||
|
if let peer = transaction.getPeer(chat.peerId) {
|
||||||
|
peers.append(EnginePeer(peer))
|
||||||
|
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _) = chat, let participantsCount = participantsCount {
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
|
||||||
|
var current = current as? CachedChannelData ?? CachedChannelData()
|
||||||
|
var participantsSummary = current.participantsSummary
|
||||||
|
|
||||||
|
participantsSummary.memberCount = participantsCount
|
||||||
|
|
||||||
|
current = current.withUpdatedParticipantsSummary(participantsSummary)
|
||||||
|
return current
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let entry = CodableEntry(CachedRecommendedChannels(peerIds: peers.map(\.id), isHidden: false)) {
|
||||||
|
transaction.putItemCacheEntry(id: entryId(peerId: peerId), entry: entry)
|
||||||
|
}
|
||||||
|
return peers
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct RecommendedChannels {
|
||||||
|
public struct Channel {
|
||||||
|
public let peer: EnginePeer
|
||||||
|
public let subscribers: Int32
|
||||||
|
}
|
||||||
|
|
||||||
|
public let channels: [Channel]
|
||||||
|
public let isHidden: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_recommendedChannels(account: Account, peerId: EnginePeer.Id) -> Signal<RecommendedChannels?, NoError> {
|
||||||
|
let key = PostboxViewKey.cachedItem(entryId(peerId: peerId))
|
||||||
|
return account.postbox.combinedView(keys: [key])
|
||||||
|
|> mapToSignal { views -> Signal<RecommendedChannels?, NoError> in
|
||||||
|
guard let cachedChannels = (views.views[key] as? CachedItemView)?.value?.get(CachedRecommendedChannels.self) else {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
return account.postbox.transaction { transaction -> RecommendedChannels? in
|
||||||
|
var channels: [RecommendedChannels.Channel] = []
|
||||||
|
for peerId in cachedChannels.peerIds {
|
||||||
|
if let peer = transaction.getPeer(peerId), let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData {
|
||||||
|
channels.append(RecommendedChannels.Channel(peer: EnginePeer(peer), subscribers: cachedData.participantsSummary.memberCount ?? 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RecommendedChannels(channels: channels, isHidden: cachedChannels.isHidden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_toggleRecommendedChannelsHidden(account: Account, peerId: EnginePeer.Id, hidden: Bool) -> Signal<Never, NoError> {
|
||||||
|
return account.postbox.transaction { transaction in
|
||||||
|
if let cachedChannels = transaction.retrieveItemCacheEntry(id: entryId(peerId: peerId))?.get(CachedRecommendedChannels.self) {
|
||||||
|
if let entry = CodableEntry(CachedRecommendedChannels(peerIds: cachedChannels.peerIds, isHidden: hidden)) {
|
||||||
|
transaction.putItemCacheEntry(id: entryId(peerId: peerId), entry: entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
@@ -77,6 +77,11 @@ func _internal_joinChannel(account: Account, peerId: PeerId, hash: String?) -> S
|
|||||||
|> castError(JoinChannelError.self)
|
|> castError(JoinChannelError.self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|> afterCompleted {
|
||||||
|
if hash == nil {
|
||||||
|
let _ = _internal_requestRecommendedChannels(account: account, peerId: peerId).startStandalone()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1240,6 +1240,14 @@ public extension TelegramEngine {
|
|||||||
public func applyChannelBoost(peerId: EnginePeer.Id, slots: [Int32]) -> Signal<MyBoostStatus?, NoError> {
|
public func applyChannelBoost(peerId: EnginePeer.Id, slots: [Int32]) -> Signal<MyBoostStatus?, NoError> {
|
||||||
return _internal_applyChannelBoost(account: self.account, peerId: peerId, slots: slots)
|
return _internal_applyChannelBoost(account: self.account, peerId: peerId, slots: slots)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func recommendedChannels(peerId: EnginePeer.Id) -> Signal<RecommendedChannels?, NoError> {
|
||||||
|
return _internal_recommendedChannels(account: self.account, peerId: peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func toggleRecommendedChannelsHidden(peerId: EnginePeer.Id, hidden: Bool) -> Signal<Never, NoError> {
|
||||||
|
return _internal_toggleRecommendedChannelsHidden(account: self.account, peerId: peerId, hidden: hidden)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -903,6 +903,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
case .giveawayLaunched:
|
case .giveawayLaunched:
|
||||||
let resultTitleString = strings.Notification_GiveawayStarted(compactAuthorName)
|
let resultTitleString = strings.Notification_GiveawayStarted(compactAuthorName)
|
||||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
|
case .joinedChannel:
|
||||||
|
attributedString = NSAttributedString(string: strings.Notification_ChannelJoinedByYou, font: titleBoldFont, textColor: primaryTextColor)
|
||||||
case .unknown:
|
case .unknown:
|
||||||
attributedString = nil
|
attributedString = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var joinMessage: Message?
|
var joinMessage: Message?
|
||||||
if case let .peer(peerId) = location, case let cachedData = cachedData as? CachedChannelData, let invitedOn = cachedData?.invitedOn {
|
if case let .peer(peerId) = location, case let cachedData = cachedData as? CachedChannelData, let invitedOn = cachedData?.invitedOn {
|
||||||
joinMessage = Message(
|
joinMessage = Message(
|
||||||
stableId: UInt32.max - 1000,
|
stableId: UInt32.max - 1000,
|
||||||
stableVersion: 0,
|
stableVersion: 0,
|
||||||
@@ -80,6 +80,32 @@ func chatHistoryEntriesForView(
|
|||||||
associatedThreadInfo: nil,
|
associatedThreadInfo: nil,
|
||||||
associatedStories: [:]
|
associatedStories: [:]
|
||||||
)
|
)
|
||||||
|
} else if let peer = channelPeer as? TelegramChannel, case .broadcast = peer.info, case .member = peer.participationStatus {
|
||||||
|
joinMessage = Message(
|
||||||
|
stableId: UInt32.max - 1000,
|
||||||
|
stableVersion: 0,
|
||||||
|
id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Local, id: 0),
|
||||||
|
globallyUniqueId: nil,
|
||||||
|
groupingKey: nil,
|
||||||
|
groupInfo: nil,
|
||||||
|
threadId: nil,
|
||||||
|
timestamp: peer.creationDate,
|
||||||
|
flags: [.Incoming],
|
||||||
|
tags: [],
|
||||||
|
globalTags: [],
|
||||||
|
localTags: [],
|
||||||
|
forwardInfo: nil,
|
||||||
|
author: channelPeer,
|
||||||
|
text: "",
|
||||||
|
attributes: [],
|
||||||
|
media: [TelegramMediaAction(action: .joinedChannel)],
|
||||||
|
peers: SimpleDictionary<PeerId, Peer>(),
|
||||||
|
associatedMessages: SimpleDictionary<MessageId, Message>(),
|
||||||
|
associatedMessageIds: [],
|
||||||
|
associatedMedia: [:],
|
||||||
|
associatedThreadInfo: nil,
|
||||||
|
associatedStories: [:]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingGroupStableIds: [UInt32] = []
|
var existingGroupStableIds: [UInt32] = []
|
||||||
|
|||||||
Reference in New Issue
Block a user