Update API

This commit is contained in:
Ilya Laktyushin
2024-04-04 02:41:40 +04:00
parent e110ebefbc
commit 06d5377bd4
29 changed files with 425 additions and 687 deletions

View File

@@ -8,13 +8,11 @@ private class AdMessagesHistoryContextImpl {
enum CodingKeys: String, CodingKey {
case opaqueId
case messageType
case displayAvatar
case title
case text
case textEntities
case media
case target
case messageId
case startParam
case url
case buttonText
case sponsorInfo
case additionalInfo
@@ -26,147 +24,14 @@ private class AdMessagesHistoryContextImpl {
case recommended = 1
}
enum Target: Equatable, Codable {
enum DecodingError: Error {
case generic
}
enum CodingKeys: String, CodingKey {
case peer
case invite
case webPage
case botApp
}
struct Invite: Equatable, Codable {
enum CodingKeys: String, CodingKey {
case title
case joinHash
case nameColor
case image
case peer
}
var title: String
var joinHash: String
var nameColor: PeerNameColor?
var image: TelegramMediaImage?
var peer: Peer?
init(title: String, joinHash: String, nameColor: PeerNameColor?, image: TelegramMediaImage?, peer: Peer?) {
self.title = title
self.joinHash = joinHash
self.nameColor = nameColor
self.image = image
self.peer = peer
}
static func ==(lhs: Invite, rhs: Invite) -> Bool {
if lhs.title != rhs.title {
return false
}
if lhs.joinHash != rhs.joinHash {
return false
}
if lhs.nameColor != rhs.nameColor {
return false
}
if lhs.image != rhs.image {
return false
}
if !arePeersEqual(lhs.peer, rhs.peer) {
return false
}
return true
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.title = try container.decode(String.self, forKey: .title)
self.joinHash = try container.decode(String.self, forKey: .joinHash)
self.nameColor = try container.decodeIfPresent(Int32.self, forKey: .nameColor).flatMap { PeerNameColor(rawValue: $0) }
self.image = (try container.decodeIfPresent(Data.self, forKey: .image)).flatMap { data in
return TelegramMediaImage(decoder: PostboxDecoder(buffer: MemoryBuffer(data: data)))
}
self.peer = (try container.decodeIfPresent(Data.self, forKey: .peer)).flatMap { data in
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Peer
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.title, forKey: .title)
try container.encode(self.joinHash, forKey: .joinHash)
try container.encodeIfPresent(self.nameColor?.rawValue, forKey: .nameColor)
try container.encodeIfPresent(self.image.flatMap { image in
let encoder = PostboxEncoder()
image.encode(encoder)
return encoder.makeData()
}, forKey: .image)
try container.encodeIfPresent(self.peer.flatMap { peer in
let encoder = PostboxEncoder()
encoder.encodeRootObject(peer)
return encoder.makeData()
}, forKey: .peer)
}
}
struct WebPage: Equatable, Codable {
var title: String
var url: String
var photo: TelegramMediaImage?
}
case peer(PeerId)
case invite(Invite)
case webPage(WebPage)
case botApp(PeerId, BotApp)
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let botApp = try container.decodeIfPresent(BotApp.self, forKey: .botApp), let peer = try container.decodeIfPresent(Int64.self, forKey: .peer) {
self = .botApp(PeerId(peer), botApp)
} else if let peer = try container.decodeIfPresent(Int64.self, forKey: .peer) {
self = .peer(PeerId(peer))
} else if let invite = try container.decodeIfPresent(Invite.self, forKey: .invite) {
self = .invite(invite)
} else if let webPage = try container.decodeIfPresent(WebPage.self, forKey: .webPage) {
self = .webPage(webPage)
} else {
throw DecodingError.generic
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .peer(peerId):
try container.encode(peerId.toInt64(), forKey: .peer)
case let .invite(invite):
try container.encode(invite, forKey: .invite)
case let .webPage(webPage):
try container.encode(webPage, forKey: .webPage)
case let .botApp(peerId, botApp):
try container.encode(peerId.toInt64(), forKey: .peer)
try container.encode(botApp, forKey: .botApp)
}
}
}
public let opaqueId: Data
public let messageType: MessageType
public let displayAvatar: Bool
public let title: String
public let text: String
public let textEntities: [MessageTextEntity]
public let media: [Media]
public let target: Target
public let messageId: MessageId?
public let startParam: String?
public let buttonText: String?
public let url: String
public let buttonText: String
public let sponsorInfo: String?
public let additionalInfo: String?
public let canReport: Bool
@@ -174,27 +39,23 @@ private class AdMessagesHistoryContextImpl {
public init(
opaqueId: Data,
messageType: MessageType,
displayAvatar: Bool,
title: String,
text: String,
textEntities: [MessageTextEntity],
media: [Media],
target: Target,
messageId: MessageId?,
startParam: String?,
buttonText: String?,
url: String,
buttonText: String,
sponsorInfo: String?,
additionalInfo: String?,
canReport: Bool
) {
self.opaqueId = opaqueId
self.messageType = messageType
self.displayAvatar = displayAvatar
self.title = title
self.text = text
self.textEntities = textEntities
self.media = media
self.target = target
self.messageId = messageId
self.startParam = startParam
self.url = url
self.buttonText = buttonText
self.sponsorInfo = sponsorInfo
self.additionalInfo = additionalInfo
@@ -212,8 +73,7 @@ private class AdMessagesHistoryContextImpl {
self.messageType = .sponsored
}
self.displayAvatar = try container.decodeIfPresent(Bool.self, forKey: .displayAvatar) ?? false
self.title = try container.decode(String.self, forKey: .title)
self.text = try container.decode(String.self, forKey: .text)
self.textEntities = try container.decode([MessageTextEntity].self, forKey: .textEntities)
@@ -222,10 +82,8 @@ private class AdMessagesHistoryContextImpl {
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media
}
self.target = try container.decode(Target.self, forKey: .target)
self.messageId = try container.decodeIfPresent(MessageId.self, forKey: .messageId)
self.startParam = try container.decodeIfPresent(String.self, forKey: .startParam)
self.buttonText = try container.decodeIfPresent(String.self, forKey: .buttonText)
self.url = try container.decode(String.self, forKey: .url)
self.buttonText = try container.decode(String.self, forKey: .buttonText)
self.sponsorInfo = try container.decodeIfPresent(String.self, forKey: .sponsorInfo)
self.additionalInfo = try container.decodeIfPresent(String.self, forKey: .additionalInfo)
@@ -238,7 +96,7 @@ private class AdMessagesHistoryContextImpl {
try container.encode(self.opaqueId, forKey: .opaqueId)
try container.encode(self.messageType.rawValue, forKey: .messageType)
try container.encode(self.displayAvatar, forKey: .displayAvatar)
try container.encode(self.title, forKey: .title)
try container.encode(self.text, forKey: .text)
try container.encode(self.textEntities, forKey: .textEntities)
@@ -249,10 +107,8 @@ private class AdMessagesHistoryContextImpl {
}
try container.encode(mediaData, forKey: .media)
try container.encode(self.target, forKey: .target)
try container.encodeIfPresent(self.messageId, forKey: .messageId)
try container.encodeIfPresent(self.startParam, forKey: .startParam)
try container.encodeIfPresent(self.buttonText, forKey: .buttonText)
try container.encode(self.url, forKey: .url)
try container.encode(self.buttonText, forKey: .buttonText)
try container.encodeIfPresent(self.sponsorInfo, forKey: .sponsorInfo)
try container.encodeIfPresent(self.additionalInfo, forKey: .additionalInfo)
@@ -267,6 +123,9 @@ private class AdMessagesHistoryContextImpl {
if lhs.messageType != rhs.messageType {
return false
}
if lhs.title != rhs.title {
return false
}
if lhs.text != rhs.text {
return false
}
@@ -281,13 +140,7 @@ private class AdMessagesHistoryContextImpl {
return false
}
}
if lhs.target != rhs.target {
return false
}
if lhs.messageId != rhs.messageId {
return false
}
if lhs.startParam != rhs.startParam {
if lhs.url != rhs.url {
return false
}
if lhs.buttonText != rhs.buttonText {
@@ -308,17 +161,6 @@ private class AdMessagesHistoryContextImpl {
func toMessage(peerId: PeerId, transaction: Transaction) -> Message? {
var attributes: [MessageAttribute] = []
let target: AdMessageAttribute.MessageTarget
switch self.target {
case let .peer(peerId):
target = .peer(id: peerId, message: self.messageId, startParam: self.startParam)
case let .invite(invite):
target = .join(title: invite.title, joinHash: invite.joinHash, peer: invite.peer.flatMap(EnginePeer.init))
case let .webPage(webPage):
target = .webPage(title: webPage.title, url: webPage.url)
case let .botApp(peerId, botApp):
target = .botApp(peerId: peerId, app: botApp, startParam: self.startParam)
}
let mappedMessageType: AdMessageAttribute.MessageType
switch self.messageType {
case .sponsored:
@@ -326,7 +168,7 @@ private class AdMessagesHistoryContextImpl {
case .recommended:
mappedMessageType = .recommended
}
attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, displayAvatar: self.displayAvatar && !self.canReport, target: target, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport))
attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, url: self.url, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport))
if !self.textEntities.isEmpty {
let attribute = TextEntitiesMessageAttribute(entities: self.textEntities)
attributes.append(attribute)
@@ -338,81 +180,35 @@ private class AdMessagesHistoryContextImpl {
messagePeers[peer.id] = peer
}
let author: Peer
switch self.target {
case let .peer(peerId), let .botApp(peerId, _):
if let peer = transaction.getPeer(peerId) {
author = peer
} else {
return nil
}
case let .invite(invite):
author = TelegramChannel(
id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)),
accessHash: nil,
title: invite.title,
username: nil,
photo: [],
creationDate: 0,
version: 0,
participationStatus: .left,
info: .broadcast(TelegramChannelBroadcastInfo(flags: [])),
flags: [],
restrictionInfo: nil,
adminRights: nil,
bannedRights: nil,
defaultBannedRights: nil,
usernames: [],
storiesHidden: nil,
nameColor: invite.nameColor,
backgroundEmojiId: nil,
profileColor: nil,
profileBackgroundEmojiId: nil,
emojiStatus: nil,
approximateBoostLevel: nil
)
case let .webPage(webPage):
author = TelegramChannel(
id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)),
accessHash: nil,
title: webPage.title,
username: nil,
photo: webPage.photo?.representations ?? [],
creationDate: 0,
version: 0,
participationStatus: .left,
info: .broadcast(TelegramChannelBroadcastInfo(flags: [])),
flags: [],
restrictionInfo: nil,
adminRights: nil,
bannedRights: nil,
defaultBannedRights: nil,
usernames: [],
storiesHidden: nil,
nameColor: .blue,
backgroundEmojiId: nil,
profileColor: nil,
profileBackgroundEmojiId: nil,
emojiStatus: nil,
approximateBoostLevel: nil
)
}
let author: Peer = TelegramChannel(
id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)),
accessHash: nil,
title: self.title,
username: nil,
photo: [],
creationDate: 0,
version: 0,
participationStatus: .left,
info: .broadcast(TelegramChannelBroadcastInfo(flags: [])),
flags: [],
restrictionInfo: nil,
adminRights: nil,
bannedRights: nil,
defaultBannedRights: nil,
usernames: [],
storiesHidden: nil,
nameColor: .blue,
backgroundEmojiId: nil,
profileColor: nil,
profileBackgroundEmojiId: nil,
emojiStatus: nil,
approximateBoostLevel: nil
)
messagePeers[author.id] = author
let messageHash = (self.text.hashValue &+ 31 &* peerId.hashValue) &* 31 &+ author.id.hashValue
let messageStableVersion = UInt32(bitPattern: Int32(truncatingIfNeeded: messageHash))
var media: [Media] = self.media
if media.isEmpty {
if case let .invite(invite) = self.target, let image = invite.image {
media.append(image)
} else if self.displayAvatar && self.canReport, let profileImage = author.smallProfileImage {
media.append(TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [profileImage], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []))
}
}
return Message(
stableId: 0,
stableVersion: messageStableVersion,
@@ -431,7 +227,7 @@ private class AdMessagesHistoryContextImpl {
author: author,
text: self.text,
attributes: attributes,
media: media,
media: self.media,
peers: messagePeers,
associatedMessages: SimpleDictionary<MessageId, Message>(),
associatedMessageIds: [],
@@ -612,100 +408,30 @@ private class AdMessagesHistoryContextImpl {
for message in messages {
switch message {
case let .sponsoredMessage(flags, randomId, fromId, chatInvite, chatInviteHash, channelPost, startParam, webPage, botApp, message, entities, buttonText, sponsorInfo, additionalInfo):
case let .sponsoredMessage(flags, randomId, url, title, message, entities, photo, buttonText, sponsorInfo, additionalInfo):
var parsedEntities: [MessageTextEntity] = []
if let entities = entities {
parsedEntities = messageTextEntitiesFromApiEntities(entities)
}
let isRecommended = (flags & (1 << 5)) != 0
var displayAvatar = (flags & (1 << 6)) != 0
let canReport = (flags & (1 << 12)) != 0
var target: CachedMessage.Target?
if let fromId = fromId {
if let botApp = botApp, let app = BotApp(apiBotApp: botApp) {
target = .botApp(fromId.peerId, app)
} else {
target = .peer(fromId.peerId)
}
} else if let webPage = webPage {
switch webPage {
case let .sponsoredWebPage(_, url, siteName, photo):
let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) }
target = .webPage(CachedMessage.Target.WebPage(title: siteName, url: url, photo: photo))
}
} else if let chatInvite = chatInvite, let chatInviteHash = chatInviteHash {
switch chatInvite {
case let .chatInvite(flags, title, _, photo, participantsCount, participants, nameColor):
let image = telegramMediaImageFromApiPhoto(photo)
let flags: ExternalJoiningChatState.Invite.Flags = .init(isChannel: (flags & (1 << 0)) != 0, isBroadcast: (flags & (1 << 1)) != 0, isPublic: (flags & (1 << 2)) != 0, isMegagroup: (flags & (1 << 3)) != 0, requestNeeded: (flags & (1 << 6)) != 0, isVerified: (flags & (1 << 7)) != 0, isScam: (flags & (1 << 8)) != 0, isFake: (flags & (1 << 9)) != 0)
let _ = flags
let _ = participantsCount
let _ = participants
target = .invite(CachedMessage.Target.Invite(
title: title,
joinHash: chatInviteHash,
nameColor: PeerNameColor(rawValue: nameColor),
image: displayAvatar ? image : nil,
peer: nil
))
displayAvatar = false
case let .chatInvitePeek(chat, _):
if let peer = parseTelegramGroupOrChannel(chat: chat) {
target = .invite(CachedMessage.Target.Invite(
title: peer.debugDisplayTitle,
joinHash: chatInviteHash,
nameColor: peer.nameColor,
image: nil,
peer: displayAvatar ? peer : nil
))
}
displayAvatar = false
case let .chatInviteAlready(chat):
if let peer = parseTelegramGroupOrChannel(chat: chat) {
target = .invite(CachedMessage.Target.Invite(
title: peer.debugDisplayTitle,
joinHash: chatInviteHash,
nameColor: peer.nameColor,
image: nil,
peer: displayAvatar ? peer : nil
))
}
displayAvatar = false
}
}
// else if let botApp = app.flatMap({ BotApp(apiBotApp: $0) }) {
// target = .botApp(botApp)
// }
var messageId: MessageId?
if let fromId = fromId, let channelPost = channelPost {
messageId = MessageId(peerId: fromId.peerId, namespace: Namespaces.Message.Cloud, id: channelPost)
}
let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) }
if let target = target {
parsedMessages.append(CachedMessage(
opaqueId: randomId.makeData(),
messageType: isRecommended ? .recommended : .sponsored,
displayAvatar: displayAvatar,
text: message,
textEntities: parsedEntities,
media: [],
target: target,
messageId: messageId,
startParam: startParam,
buttonText: buttonText,
sponsorInfo: sponsorInfo,
additionalInfo: additionalInfo,
canReport: canReport
))
}
parsedMessages.append(CachedMessage(
opaqueId: randomId.makeData(),
messageType: isRecommended ? .recommended : .sponsored,
title: title,
text: message,
textEntities: parsedEntities,
media: photo.flatMap { [$0] } ?? [],
url: url,
buttonText: buttonText,
sponsorInfo: sponsorInfo,
additionalInfo: additionalInfo,
canReport: canReport
))
}
}