Update Ghostgram features

This commit is contained in:
ichmagmaus 812
2026-03-07 18:15:32 +01:00
parent 1a3303b059
commit 24a7ec39d9
902 changed files with 148302 additions and 62355 deletions
@@ -121,7 +121,8 @@ public class UnauthorizedAccount {
switch sentCode {
case .sentCodePaymentRequired:
break
case let .sentCode(_, type, phoneCodeHash, nextType, codeTimeout):
case let .sentCode(sentCodeData):
let (type, phoneCodeHash, nextType, codeTimeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
let _ = postbox.transaction({ transaction in
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
@@ -131,20 +132,22 @@ public class UnauthorizedAccount {
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: testingEnvironment, masterDatacenterId: masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
}
}).start()
case let .sentCodeSuccess(authorization):
case let .sentCodeSuccess(sentCodeSuccessData):
let authorization = sentCodeSuccessData.authorization
switch authorization {
case let .authorization(_, _, _, futureAuthToken, user):
case let .authorization(authorizationData):
let (futureAuthToken, apiUser) = (authorizationData.futureAuthToken, authorizationData.user)
let _ = postbox.transaction({ [weak self] transaction in
var syncContacts = true
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(_, _, _, _, _, syncContactsValue) = state.contents {
syncContacts = syncContactsValue
}
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42"), phone.count <= 5 {
isSupportUser = true
@@ -159,7 +162,8 @@ public class UnauthorizedAccount {
return .loggedIn
}
}).start()
case let .authorizationSignUpRequired(_, termsOfService):
case let .authorizationSignUpRequired(authorizationSignUpRequiredData):
let termsOfService = authorizationSignUpRequiredData.termsOfService
let _ = postbox.transaction({ [weak self] transaction in
if let self {
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(number, codeHash, _, _, _, syncContacts) = state.contents {
@@ -364,7 +368,8 @@ public enum TwoStepPasswordDerivation {
switch apiAlgo {
case .passwordKdfAlgoUnknown:
self = .unknown
case let .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1, salt2, g, p):
case let .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPowData):
let (salt1, salt2, g, p) = (passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPowData.salt1, passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPowData.salt2, passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPowData.g, passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPowData.p)
self = .sha256_sha256_PBKDF2_HMAC_sha512_sha256_srp(salt1: salt1.makeData(), salt2: salt2.makeData(), iterations: 100000, g: g, p: p.makeData())
}
}
@@ -375,7 +380,7 @@ public enum TwoStepPasswordDerivation {
return .passwordKdfAlgoUnknown
case let .sha256_sha256_PBKDF2_HMAC_sha512_sha256_srp(salt1, salt2, iterations, g, p):
precondition(iterations == 100000)
return .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: Buffer(data: salt1), salt2: Buffer(data: salt2), g: g, p: Buffer(data: p))
return .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(.init(salt1: Buffer(data: salt1), salt2: Buffer(data: salt2), g: g, p: Buffer(data: p)))
}
}
}
@@ -389,9 +394,11 @@ public enum TwoStepSecurePasswordDerivation {
switch apiAlgo {
case .securePasswordKdfAlgoUnknown:
self = .unknown
case let .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt):
case let .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(securePasswordKdfAlgoPBKDF2HMACSHA512iter100000Data):
let (salt) = (securePasswordKdfAlgoPBKDF2HMACSHA512iter100000Data.salt)
self = .PBKDF2_HMAC_sha512(salt: salt.makeData(), iterations: 100000)
case let .securePasswordKdfAlgoSHA512(salt):
case let .securePasswordKdfAlgoSHA512(securePasswordKdfAlgoSHA512Data):
let (salt) = (securePasswordKdfAlgoSHA512Data.salt)
self = .sha512(salt: salt.makeData())
}
}
@@ -402,9 +409,9 @@ public enum TwoStepSecurePasswordDerivation {
return .securePasswordKdfAlgoUnknown
case let .PBKDF2_HMAC_sha512(salt, iterations):
precondition(iterations == 100000)
return .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: Buffer(data: salt))
return .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(.init(salt: Buffer(data: salt)))
case let .sha512(salt):
return .securePasswordKdfAlgoSHA512(salt: Buffer(data: salt))
return .securePasswordKdfAlgoSHA512(.init(salt: Buffer(data: salt)))
}
}
}
@@ -432,7 +439,8 @@ func _internal_twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MT
return network.request(Api.functions.account.getPassword())
|> map { config -> TwoStepAuthData in
switch config {
case let .password(flags, currentAlgo, srpB, srpId, hint, emailUnconfirmedPattern, newAlgo, newSecureAlgo, secureRandom, pendingResetDate, loginEmailPattern):
case let .password(passwordData):
let (flags, currentAlgo, srpB, srpId, hint, emailUnconfirmedPattern, newAlgo, newSecureAlgo, secureRandom, pendingResetDate, loginEmailPattern) = (passwordData.flags, passwordData.currentAlgo, passwordData.srpB, passwordData.srpId, passwordData.hint, passwordData.emailUnconfirmedPattern, passwordData.newAlgo, passwordData.newSecureAlgo, passwordData.secureRandom, passwordData.pendingResetDate, passwordData.loginEmailPattern)
let hasRecovery = (flags & (1 << 0)) != 0
let hasSecureValues = (flags & (1 << 1)) != 0
@@ -497,7 +505,8 @@ public final class TelegramPasskey: Equatable {
extension TelegramPasskey {
convenience init(apiPasskey: Api.Passkey) {
switch apiPasskey {
case let .passkey(_, id, name, date, softwareEmojiId, lastUsageDate):
case let .passkey(passkeyData):
let (id, name, date, softwareEmojiId, lastUsageDate) = (passkeyData.id, passkeyData.name, passkeyData.date, passkeyData.softwareEmojiId, passkeyData.lastUsageDate)
self.init(id: id, name: name, date: date, emojiId: softwareEmojiId, lastUsageDate: lastUsageDate)
}
}
@@ -514,7 +523,8 @@ func _internal_passkeysData(network: Network) -> Signal<[TelegramPasskey], NoErr
return []
}
switch passkeys {
case let .passkeys(passkeys):
case let .passkeys(passkeysData):
let passkeys = passkeysData.passkeys
return passkeys.map { passkey in
return TelegramPasskey(apiPasskey: passkey)
}
@@ -533,9 +543,11 @@ func _internal_requestPasskeyRegistration(network: Network) -> Signal<String?, N
return nil
}
switch options {
case let .passkeyRegistrationOptions(options):
case let .passkeyRegistrationOptions(passkeyRegistrationOptionsData):
let options = passkeyRegistrationOptionsData.options
switch options {
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
return data
}
}
@@ -543,7 +555,7 @@ func _internal_requestPasskeyRegistration(network: Network) -> Signal<String?, N
}
func _internal_requestCreatePasskey(network: Network, id: String, clientData: String, attestationObject: Data) -> Signal<TelegramPasskey?, NoError> {
return network.request(Api.functions.account.registerPasskey(credential: .inputPasskeyCredentialPublicKey(id: id, rawId: id, response: .inputPasskeyResponseRegister(clientData: .dataJSON(data: clientData), attestationData: Buffer(data: attestationObject)))))
return network.request(Api.functions.account.registerPasskey(credential: .inputPasskeyCredentialPublicKey(.init(id: id, rawId: id, response: .inputPasskeyResponseRegister(.init(clientData: .dataJSON(.init(data: clientData)), attestationData: Buffer(data: attestationObject)))))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Passkey?, NoError> in
return .single(nil)
@@ -575,9 +587,11 @@ func _internal_requestPasskeyLoginData(network: Network, apiId: Int32, apiHash:
return nil
}
switch result {
case let .passkeyLoginOptions(options):
case let .passkeyLoginOptions(passkeyLoginOptionsData):
let options = passkeyLoginOptionsData.options
switch options {
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
return data
}
}
@@ -864,7 +878,7 @@ func verifyPassword(_ account: UnauthorizedAccount, password: String) -> Signal<
let kdfResult = passwordKDF(encryptionProvider: account.network.encryptionProvider, password: password, derivation: currentPasswordDerivation, srpSessionData: srpSessionData)
if let kdfResult = kdfResult {
return account.network.request(Api.functions.auth.checkPassword(password: .inputCheckPasswordSRP(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1))), automaticFloodWait: false)
return account.network.request(Api.functions.auth.checkPassword(password: .inputCheckPasswordSRP(.init(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1)))), automaticFloodWait: false)
} else {
return .fail(MTRpcError(errorCode: 400, errorDescription: "KDF_ERROR"))
}
@@ -1523,7 +1537,7 @@ public class Account {
return .complete()
} else {
return network.request(Api.functions.help.saveAppLog(events: events.map { event -> Api.InputAppEvent in
return .inputAppEvent(time: event.0, type: "", peer: 0, data: .jsonString(value: event.1))
return .inputAppEvent(.init(time: event.0, type: "", peer: 0, data: .jsonString(.init(value: event.1))))
}))
|> ignoreValues
|> `catch` { _ -> Signal<Never, NoError> in
@@ -508,7 +508,8 @@ struct AccountMutableState {
for chat in chats {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _, _, _, _):
case let .channel(channelData):
let participantsCount = channelData.participantsCount
if let participantsCount = participantsCount {
self.addOperation(.UpdateCachedPeerData(chat.peerId, { current in
var previous: CachedChannelData
@@ -572,7 +573,8 @@ struct AccountMutableState {
var presences: [PeerId: Api.UserStatus] = [:]
for user in users {
switch user {
case let .user(_, _, id, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _, _, _, _):
case let .user(userData):
let (id, status) = (userData.id, userData.status)
if let status = status {
presences[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] = status
}
@@ -215,6 +215,8 @@ private var declaredEncodables: Void = {
declareEncodable(AuthSessionInfoAttribute.self, f: { AuthSessionInfoAttribute(decoder: $0) })
declareEncodable(TranslationMessageAttribute.self, f: { TranslationMessageAttribute(decoder: $0) })
declareEncodable(TranslationMessageAttribute.Additional.self, f: { TranslationMessageAttribute.Additional(decoder: $0) })
// MARK: Swiftgram
declareEncodable(QuickTranslationMessageAttribute.self, f: { QuickTranslationMessageAttribute(decoder: $0) })
declareEncodable(SynchronizeAutosaveItemOperation.self, f: { SynchronizeAutosaveItemOperation(decoder: $0) })
declareEncodable(TelegramMediaStory.self, f: { TelegramMediaStory(decoder: $0) })
declareEncodable(SynchronizeViewStoriesOperation.self, f: { SynchronizeViewStoriesOperation(decoder: $0) })
@@ -502,7 +504,8 @@ private func cleanupAccount(networkArguments: NetworkInitializationArguments, ac
}
|> mapToSignal { result -> Signal<Void, NoError> in
switch result {
case let .loggedOut(_, futureAuthToken):
case let .loggedOut(loggedOutData):
let futureAuthToken = loggedOutData.futureAuthToken
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
@@ -44,4 +44,14 @@ public extension Message {
var deletedMessageAttribute: DeletedMessageAttribute? {
return self.attributes.first(where: { $0 is DeletedMessageAttribute }) as? DeletedMessageAttribute
}
var ghostgramIsDeleted: Bool {
if self.isDeletedButVisible {
return true
}
if AntiDeleteManager.shared.isMessageDeleted(peerId: self.id.peerId.toInt64(), messageId: self.id.id) {
return true
}
return AntiDeleteManager.shared.isMessageDeleted(text: self.text)
}
}
@@ -6,7 +6,8 @@ import TelegramApi
func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMediaImageRepresentation] {
var representations: [TelegramMediaImageRepresentation] = []
switch photo {
case let .chatPhoto(flags, photoId, strippedThumb, dcId):
case let .chatPhoto(chatPhotoData):
let (flags, photoId, strippedThumb, dcId) = (chatPhotoData.flags, chatPhotoData.photoId, chatPhotoData.strippedThumb, chatPhotoData.dcId)
let hasVideo = (flags & (1 << 0)) != 0
let smallResource: TelegramMediaResource
let fullSizeResource: TelegramMediaResource
@@ -24,12 +25,14 @@ func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMed
func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
switch chat {
case let .chat(flags, id, title, photo, participantsCount, date, version, migratedTo, adminRights, defaultBannedRights):
case let .chat(chatData):
let (flags, id, title, photo, participantsCount, date, version, migratedTo, adminRights, defaultBannedRights) = (chatData.flags, chatData.id, chatData.title, chatData.photo, chatData.participantsCount, chatData.date, chatData.version, chatData.migratedTo, chatData.adminRights, chatData.defaultBannedRights)
let left = (flags & ((1 << 1) | (1 << 2))) != 0
var migrationReference: TelegramGroupToChannelMigrationReference?
if let migratedTo = migratedTo {
switch migratedTo {
case let .inputChannel(channelId, accessHash):
case let .inputChannel(inputChannelData):
let (channelId, accessHash) = (inputChannelData.channelId, inputChannelData.accessHash)
migrationReference = TelegramGroupToChannelMigrationReference(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), accessHash: accessHash)
case .inputChannelEmpty:
break
@@ -57,11 +60,14 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
groupFlags.insert(.copyProtectionEnabled)
}
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: title, photo: imageRepresentationsForApiChatPhoto(photo), participantCount: Int(participantsCount), role: role, membership: left ? .Left : .Member, flags: groupFlags, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init(apiBannedRights:)), migrationReference: migrationReference, creationDate: date, version: Int(version))
case let .chatEmpty(id):
case let .chatEmpty(chatEmptyData):
let id = chatEmptyData.id
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .chatForbidden(id, title):
case let .chatForbidden(chatForbiddenData):
let (id, title) = (chatForbiddenData.id, chatForbiddenData.title)
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .channel(flags, flags2, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel, subscriptionUntilDate, verificationIconFileId, sendPaidMessageStars, linkedMonoforumId):
case let .channel(channelData):
let (flags, flags2, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, usernames, color, profileColor, emojiStatus, boostLevel, subscriptionUntilDate, verificationIconFileId, sendPaidMessageStars, linkedMonoforumId) = (channelData.flags, channelData.flags2, channelData.id, channelData.accessHash, channelData.title, channelData.username, channelData.photo, channelData.date, channelData.restrictionReason, channelData.adminRights, channelData.bannedRights, channelData.defaultBannedRights, channelData.usernames, channelData.color, channelData.profileColor, channelData.emojiStatus, channelData.level, channelData.subscriptionUntilDate, channelData.botVerificationIcon, channelData.sendPaidMessagesStars, channelData.linkedMonoforumId)
let isMin = (flags & (1 << 12)) != 0
let participationStatus: TelegramChannelParticipationStatus
@@ -172,7 +178,8 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
var backgroundEmojiId: Int64?
if let color = color {
switch color {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
nameColorIndex = color
backgroundEmojiId = backgroundEmojiIdValue
case .peerColorCollectible:
@@ -181,21 +188,23 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
break
}
}
var profileColorIndex: Int32?
var profileBackgroundEmojiId: Int64?
if let profileColor = profileColor {
switch profileColor {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
profileColorIndex = color
profileBackgroundEmojiId = backgroundEmojiIdValue
default:
break
}
}
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: 0, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), approximateBoostLevel: boostLevel, subscriptionUntilDate: subscriptionUntilDate, verificationIconFileId: verificationIconFileId, sendPaidMessageStars: sendPaidMessageStars.flatMap { StarsAmount(value: $0, nanos: 0) }, linkedMonoforumId: linkedMonoforumId.flatMap { PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value($0)) })
case let .channelForbidden(flags, id, accessHash, title, untilDate):
case let .channelForbidden(channelForbiddenData):
let (flags, id, accessHash, title, untilDate) = (channelForbiddenData.flags, channelForbiddenData.id, channelForbiddenData.accessHash, channelForbiddenData.title, channelForbiddenData.untilDate)
let info: TelegramChannelInfo
if (flags & Int32(1 << 8)) != 0 {
info = .group(TelegramChannelGroupInfo(flags: []))
@@ -203,7 +212,12 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
info = .broadcast(TelegramChannelBroadcastInfo(flags: []))
}
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)
var channelFlags = TelegramChannelFlags()
if (flags & (1 << 10)) != 0 {
channelFlags.insert(.isMonoforum)
}
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: channelFlags, restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)
}
}
@@ -211,7 +225,8 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
switch rhs {
case .chat, .chatEmpty, .chatForbidden, .channelForbidden:
return parseTelegramGroupOrChannel(chat: rhs)
case let .channel(flags, flags2, _, accessHash, title, username, photo, _, _, _, _, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel, subscriptionUntilDate, verificationIconFileId, sendPaidMessageStars, linkedMonoforumIdValue):
case let .channel(channelData):
let (flags, flags2, accessHash, title, username, photo, defaultBannedRights, usernames, color, profileColor, emojiStatus, boostLevel, subscriptionUntilDate, verificationIconFileId, sendPaidMessageStars, linkedMonoforumIdValue) = (channelData.flags, channelData.flags2, channelData.accessHash, channelData.title, channelData.username, channelData.photo, channelData.defaultBannedRights, channelData.usernames, channelData.color, channelData.profileColor, channelData.emojiStatus, channelData.level, channelData.subscriptionUntilDate, channelData.botVerificationIcon, channelData.sendPaidMessagesStars, channelData.linkedMonoforumId)
let isMin = (flags & (1 << 12)) != 0
if accessHash != nil && !isMin {
return parseTelegramGroupOrChannel(chat: rhs)
@@ -257,7 +272,8 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
var backgroundEmojiId: Int64?
if let color = color {
switch color {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
nameColorIndex = color
backgroundEmojiId = backgroundEmojiIdValue
case .peerColorCollectible:
@@ -266,19 +282,20 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
break
}
}
var profileColorIndex: Int32?
var profileBackgroundEmojiId: Int64?
if let profileColor = profileColor {
switch profileColor {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
profileColorIndex = color
profileBackgroundEmojiId = backgroundEmojiIdValue
default:
break
}
}
let parsedEmojiStatus = emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:))
let linkedMonoforumId = linkedMonoforumIdValue.flatMap({ PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value($0)) }) ?? lhs.linkedMonoforumId
@@ -20,17 +20,17 @@ extension PeerReference {
var inputPeer: Api.InputPeer {
switch self {
case let .user(id, accessHash):
return .inputPeerUser(userId: id, accessHash: accessHash)
return .inputPeerUser(.init(userId: id, accessHash: accessHash))
case let .group(id):
return .inputPeerChat(chatId: id)
return .inputPeerChat(.init(chatId: id))
case let .channel(id, accessHash):
return .inputPeerChannel(channelId: id, accessHash: accessHash)
return .inputPeerChannel(.init(channelId: id, accessHash: accessHash))
}
}
var inputUser: Api.InputUser? {
if case let .user(id, accessHash) = self {
return .inputUser(userId: id, accessHash: accessHash)
return .inputUser(.init(userId: id, accessHash: accessHash))
} else {
return nil
}
@@ -38,7 +38,7 @@ extension PeerReference {
var inputChannel: Api.InputChannel? {
if case let .channel(id, accessHash) = self {
return .inputChannel(channelId: id, accessHash: accessHash)
return .inputChannel(.init(channelId: id, accessHash: accessHash))
} else {
return nil
}
@@ -48,12 +48,12 @@ extension PeerReference {
func forceApiInputPeer(_ peer: Peer) -> Api.InputPeer? {
switch peer {
case let user as TelegramUser:
return Api.InputPeer.inputPeerUser(userId: user.id.id._internalGetInt64Value(), accessHash: user.accessHash?.value ?? 0)
return Api.InputPeer.inputPeerUser(.init(userId: user.id.id._internalGetInt64Value(), accessHash: user.accessHash?.value ?? 0))
case let group as TelegramGroup:
return Api.InputPeer.inputPeerChat(chatId: group.id.id._internalGetInt64Value())
return Api.InputPeer.inputPeerChat(.init(chatId: group.id.id._internalGetInt64Value()))
case let channel as TelegramChannel:
if let accessHash = channel.accessHash {
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value)
return Api.InputPeer.inputPeerChannel(.init(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value))
} else {
return nil
}
@@ -65,12 +65,12 @@ func forceApiInputPeer(_ peer: Peer) -> Api.InputPeer? {
func apiInputPeer(_ peer: Peer) -> Api.InputPeer? {
switch peer {
case let user as TelegramUser where user.accessHash != nil:
return Api.InputPeer.inputPeerUser(userId: user.id.id._internalGetInt64Value(), accessHash: user.accessHash!.value)
return Api.InputPeer.inputPeerUser(.init(userId: user.id.id._internalGetInt64Value(), accessHash: user.accessHash!.value))
case let group as TelegramGroup:
return Api.InputPeer.inputPeerChat(chatId: group.id.id._internalGetInt64Value())
return Api.InputPeer.inputPeerChat(.init(chatId: group.id.id._internalGetInt64Value()))
case let channel as TelegramChannel:
if let accessHash = channel.accessHash {
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value)
return Api.InputPeer.inputPeerChannel(.init(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value))
} else {
return nil
}
@@ -88,7 +88,7 @@ func apiInputPeerOrSelf(_ peer: Peer, accountPeerId: PeerId) -> Api.InputPeer? {
func apiInputChannel(_ peer: Peer) -> Api.InputChannel? {
if let channel = peer as? TelegramChannel, let accessHash = channel.accessHash {
return Api.InputChannel.inputChannel(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value)
return Api.InputChannel.inputChannel(.init(channelId: channel.id.id._internalGetInt64Value(), accessHash: accessHash.value))
} else {
return nil
}
@@ -96,7 +96,7 @@ func apiInputChannel(_ peer: Peer) -> Api.InputChannel? {
func apiInputUser(_ peer: Peer) -> Api.InputUser? {
if let user = peer as? TelegramUser, let accessHash = user.accessHash {
return Api.InputUser.inputUser(userId: user.id.id._internalGetInt64Value(), accessHash: accessHash.value)
return Api.InputUser.inputUser(.init(userId: user.id.id._internalGetInt64Value(), accessHash: accessHash.value))
} else {
return nil
}
@@ -104,7 +104,7 @@ func apiInputUser(_ peer: Peer) -> Api.InputUser? {
func apiInputSecretChat(_ peer: Peer) -> Api.InputEncryptedChat? {
if let chat = peer as? TelegramSecretChat {
return Api.InputEncryptedChat.inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: chat.accessHash)
return Api.InputEncryptedChat.inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: chat.accessHash))
} else {
return nil
}
@@ -7,7 +7,8 @@ extension BotMenuButton {
switch apiBotMenuButton {
case .botMenuButtonCommands, .botMenuButtonDefault:
self = .commands
case let .botMenuButton(text, url):
case let .botMenuButton(botMenuButtonData):
let (text, url) = (botMenuButtonData.text, botMenuButtonData.url)
self = .webView(text: text, url: url)
}
}
@@ -16,7 +17,8 @@ extension BotMenuButton {
extension BotAppSettings {
init(apiBotAppSettings: Api.BotAppSettings) {
switch apiBotAppSettings {
case let .botAppSettings(_, placeholder, backgroundColor, backgroundDarkColor, headerColor, headerDarkColor):
case let .botAppSettings(botAppSettingsData):
let (_, placeholder, backgroundColor, backgroundDarkColor, headerColor, headerDarkColor) = (botAppSettingsData.flags, botAppSettingsData.placeholderPath, botAppSettingsData.backgroundColor, botAppSettingsData.backgroundDarkColor, botAppSettingsData.headerColor, botAppSettingsData.headerDarkColor)
self.init(
placeholderData: placeholder.flatMap { $0.makeData() },
backgroundColor: backgroundColor,
@@ -31,7 +33,8 @@ extension BotAppSettings {
extension BotVerifierSettings {
init(apiBotVerifierSettings: Api.BotVerifierSettings) {
switch apiBotVerifierSettings {
case let .botVerifierSettings(flags, iconFileId, companyName, customDescription):
case let .botVerifierSettings(botVerifierSettingsData):
let (flags, iconFileId, companyName, customDescription) = (botVerifierSettingsData.flags, botVerifierSettingsData.icon, botVerifierSettingsData.company, botVerifierSettingsData.customDescription)
self.init(
iconFileId: iconFileId,
companyName: companyName,
@@ -45,14 +48,16 @@ extension BotVerifierSettings {
extension BotInfo {
convenience init(apiBotInfo: Api.BotInfo) {
switch apiBotInfo {
case let .botInfo(_, _, description, descriptionPhoto, descriptionDocument, apiCommands, apiMenuButton, privacyPolicyUrl, appSettings, verifierSettings):
case let .botInfo(botInfoData):
let (_, _, description, descriptionPhoto, descriptionDocument, apiCommands, apiMenuButton, privacyPolicyUrl, appSettings, verifierSettings) = (botInfoData.flags, botInfoData.userId, botInfoData.description, botInfoData.descriptionPhoto, botInfoData.descriptionDocument, botInfoData.commands, botInfoData.menuButton, botInfoData.privacyPolicyUrl, botInfoData.appSettings, botInfoData.verifierSettings)
let photo: TelegramMediaImage? = descriptionPhoto.flatMap(telegramMediaImageFromApiPhoto)
let video: TelegramMediaFile? = descriptionDocument.flatMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
var commands: [BotCommand] = []
if let apiCommands = apiCommands {
commands = apiCommands.map { command in
switch command {
case let .botCommand(command, description):
case let .botCommand(botCommandData):
let (command, description) = (botCommandData.command, botCommandData.description)
return BotCommand(text: command, description: description)
}
}
@@ -205,19 +205,25 @@ public final class CachedChannelParticipants: PostboxCoding, Equatable {
extension ChannelParticipant {
init(apiParticipant: Api.ChannelParticipant) {
switch apiParticipant {
case let .channelParticipant(_, userId, date, subscriptionUntilDate):
case let .channelParticipant(channelParticipantData):
let (_, userId, date, subscriptionUntilDate) = (channelParticipantData.flags, channelParticipantData.userId, channelParticipantData.date, channelParticipantData.subscriptionUntilDate)
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil, subscriptionUntilDate: subscriptionUntilDate)
case let .channelParticipantCreator(_, userId, adminRights, rank):
case let .channelParticipantCreator(channelParticipantCreatorData):
let (_, userId, adminRights, rank) = (channelParticipantCreatorData.flags, channelParticipantCreatorData.userId, channelParticipantCreatorData.adminRights, channelParticipantCreatorData.rank)
self = .creator(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), canBeEditedByAccountPeer: true), rank: rank)
case let .channelParticipantBanned(flags, userId, restrictedBy, date, bannedRights):
case let .channelParticipantBanned(channelParticipantBannedData):
let (flags, userId, restrictedBy, date, bannedRights) = (channelParticipantBannedData.flags, channelParticipantBannedData.peer, channelParticipantBannedData.kickedBy, channelParticipantBannedData.date, channelParticipantBannedData.bannedRights)
let hasLeft = (flags & (1 << 0)) != 0
let banInfo = ChannelParticipantBannedInfo(rights: TelegramChatBannedRights(apiBannedRights: bannedRights), restrictedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(restrictedBy)), timestamp: date, isMember: !hasLeft)
self = .member(id: userId.peerId, invitedAt: date, adminInfo: nil, banInfo: banInfo, rank: nil, subscriptionUntilDate: nil)
case let .channelParticipantAdmin(flags, userId, _, promotedBy, date, adminRights, rank: rank):
case let .channelParticipantAdmin(channelParticipantAdminData):
let (flags, userId, _, promotedBy, date, adminRights, rank) = (channelParticipantAdminData.flags, channelParticipantAdminData.userId, channelParticipantAdminData.inviterId, channelParticipantAdminData.promotedBy, channelParticipantAdminData.date, channelParticipantAdminData.adminRights, channelParticipantAdminData.rank)
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(promotedBy)), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank, subscriptionUntilDate: nil)
case let .channelParticipantSelf(_, userId, _, date, subscriptionUntilDate):
case let .channelParticipantSelf(channelParticipantSelfData):
let (_, userId, _, date, subscriptionUntilDate) = (channelParticipantSelfData.flags, channelParticipantSelfData.userId, channelParticipantSelfData.inviterId, channelParticipantSelfData.date, channelParticipantSelfData.subscriptionUntilDate)
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil, subscriptionUntilDate: subscriptionUntilDate)
case let .channelParticipantLeft(userId):
case let .channelParticipantLeft(channelParticipantLeftData):
let (userId) = (channelParticipantLeftData.peer)
self = .member(id: userId.peerId, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil, subscriptionUntilDate: nil)
}
}
@@ -6,11 +6,14 @@ import TelegramApi
extension GroupParticipant {
init(apiParticipant: Api.ChatParticipant) {
switch apiParticipant {
case let .chatParticipantCreator(userId):
case let .chatParticipantCreator(chatParticipantCreatorData):
let userId = chatParticipantCreatorData.userId
self = .creator(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)))
case let .chatParticipantAdmin(userId, inviterId, date):
case let .chatParticipantAdmin(chatParticipantAdminData):
let (userId, inviterId, date) = (chatParticipantAdminData.userId, chatParticipantAdminData.inviterId, chatParticipantAdminData.date)
self = .admin(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(inviterId)), invitedAt: date)
case let .chatParticipant(userId, inviterId, date):
case let .chatParticipant(chatParticipantData):
let (userId, inviterId, date) = (chatParticipantData.userId, chatParticipantData.inviterId, chatParticipantData.date)
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(inviterId)), invitedAt: date)
}
}
@@ -19,7 +22,8 @@ extension GroupParticipant {
extension CachedGroupParticipants {
convenience init?(apiParticipants: Api.ChatParticipants) {
switch apiParticipants {
case let .chatParticipants(_, participants, version):
case let .chatParticipants(chatParticipantsData):
let (participants, version) = (chatParticipantsData.participants, chatParticipantsData.version)
self.init(participants: participants.map { GroupParticipant(apiParticipant: $0) }, version: version)
case .chatParticipantsForbidden:
return nil
@@ -490,7 +490,8 @@ public final class ChatContextResultCollection: Equatable, Codable {
extension ChatContextResultMessage {
init(apiMessage: Api.BotInlineMessage) {
switch apiMessage {
case let .botInlineMessageMediaAuto(_, message, entities, replyMarkup):
case let .botInlineMessageMediaAuto(botInlineMessageMediaAutoData):
let (_, message, entities, replyMarkup) = (botInlineMessageMediaAutoData.flags, botInlineMessageMediaAutoData.message, botInlineMessageMediaAutoData.entities, botInlineMessageMediaAutoData.replyMarkup)
var parsedEntities: TextEntitiesMessageAttribute?
if let entities = entities, !entities.isEmpty {
parsedEntities = TextEntitiesMessageAttribute(entities: messageTextEntitiesFromApiEntities(entities))
@@ -500,7 +501,8 @@ extension ChatContextResultMessage {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
}
self = .auto(caption: message, entities: parsedEntities, replyMarkup: parsedReplyMarkup)
case let .botInlineMessageText(flags, message, entities, replyMarkup):
case let .botInlineMessageText(botInlineMessageTextData):
let (flags, message, entities, replyMarkup) = (botInlineMessageTextData.flags, botInlineMessageTextData.message, botInlineMessageTextData.entities, botInlineMessageTextData.replyMarkup)
var parsedEntities: TextEntitiesMessageAttribute?
if let entities = entities, !entities.isEmpty {
parsedEntities = TextEntitiesMessageAttribute(entities: messageTextEntitiesFromApiEntities(entities))
@@ -516,28 +518,32 @@ extension ChatContextResultMessage {
isManuallyAdded: false,
isSafe: false
), replyMarkup: parsedReplyMarkup)
case let .botInlineMessageMediaGeo(_, geo, heading, period, proximityNotificationRadius, replyMarkup):
case let .botInlineMessageMediaGeo(botInlineMessageMediaGeoData):
let (_, geo, heading, period, proximityNotificationRadius, replyMarkup) = (botInlineMessageMediaGeoData.flags, botInlineMessageMediaGeoData.geo, botInlineMessageMediaGeoData.heading, botInlineMessageMediaGeoData.period, botInlineMessageMediaGeoData.proximityNotificationRadius, botInlineMessageMediaGeoData.replyMarkup)
let media = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: proximityNotificationRadius, heading: heading)
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
if let replyMarkup = replyMarkup {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
}
self = .mapLocation(media: media, replyMarkup: parsedReplyMarkup)
case let .botInlineMessageMediaVenue(_, geo, title, address, provider, venueId, venueType, replyMarkup):
case let .botInlineMessageMediaVenue(botInlineMessageMediaVenueData):
let (_, geo, title, address, provider, venueId, venueType, replyMarkup) = (botInlineMessageMediaVenueData.flags, botInlineMessageMediaVenueData.geo, botInlineMessageMediaVenueData.title, botInlineMessageMediaVenueData.address, botInlineMessageMediaVenueData.provider, botInlineMessageMediaVenueData.venueId, botInlineMessageMediaVenueData.venueType, botInlineMessageMediaVenueData.replyMarkup)
let media = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId, venueType: venueType, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil, heading: nil)
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
if let replyMarkup = replyMarkup {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
}
self = .mapLocation(media: media, replyMarkup: parsedReplyMarkup)
case let .botInlineMessageMediaContact(_, phoneNumber, firstName, lastName, vcard, replyMarkup):
case let .botInlineMessageMediaContact(botInlineMessageMediaContactData):
let (_, phoneNumber, firstName, lastName, vcard, replyMarkup) = (botInlineMessageMediaContactData.flags, botInlineMessageMediaContactData.phoneNumber, botInlineMessageMediaContactData.firstName, botInlineMessageMediaContactData.lastName, botInlineMessageMediaContactData.vcard, botInlineMessageMediaContactData.replyMarkup)
let media = TelegramMediaContact(firstName: firstName, lastName: lastName, phoneNumber: phoneNumber, peerId: nil, vCardData: vcard.isEmpty ? nil : vcard)
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
if let replyMarkup = replyMarkup {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
}
self = .contact(media: media, replyMarkup: parsedReplyMarkup)
case let .botInlineMessageMediaInvoice(flags, title, description, photo, currency, totalAmount, replyMarkup):
case let .botInlineMessageMediaInvoice(botInlineMessageMediaInvoiceData):
let (flags, title, description, photo, currency, totalAmount, replyMarkup) = (botInlineMessageMediaInvoiceData.flags, botInlineMessageMediaInvoiceData.title, botInlineMessageMediaInvoiceData.description, botInlineMessageMediaInvoiceData.photo, botInlineMessageMediaInvoiceData.currency, botInlineMessageMediaInvoiceData.totalAmount, botInlineMessageMediaInvoiceData.replyMarkup)
var parsedFlags = TelegramMediaInvoiceFlags()
if (flags & (1 << 3)) != 0 {
parsedFlags.insert(.isTest)
@@ -550,7 +556,8 @@ extension ChatContextResultMessage {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
}
self = .invoice(media: TelegramMediaInvoice(title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), receiptMessageId: nil, currency: currency, totalAmount: totalAmount, startParam: "", extendedMedia: nil, subscriptionPeriod: nil, flags: parsedFlags, version: TelegramMediaInvoice.lastVersion), replyMarkup: parsedReplyMarkup)
case let .botInlineMessageMediaWebPage(flags, message, entities, url, replyMarkup):
case let .botInlineMessageMediaWebPage(botInlineMessageMediaWebPageData):
let (flags, message, entities, url, replyMarkup) = (botInlineMessageMediaWebPageData.flags, botInlineMessageMediaWebPageData.message, botInlineMessageMediaWebPageData.entities, botInlineMessageMediaWebPageData.url, botInlineMessageMediaWebPageData.replyMarkup)
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
if let replyMarkup = replyMarkup {
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
@@ -590,9 +597,11 @@ extension ChatContextResultMessage {
extension ChatContextResult {
init(apiResult: Api.BotInlineResult, queryId: Int64) {
switch apiResult {
case let .botInlineResult(_, id, type, title, description, url, thumb, content, sendMessage):
case let .botInlineResult(botInlineResultData):
let (_, id, type, title, description, url, thumb, content, sendMessage) = (botInlineResultData.flags, botInlineResultData.id, botInlineResultData.type, botInlineResultData.title, botInlineResultData.description, botInlineResultData.url, botInlineResultData.thumb, botInlineResultData.content, botInlineResultData.sendMessage)
self = .externalReference(ChatContextResult.ExternalReference(queryId: queryId, id: id, type: type, title: title, description: description, url: url, content: content.flatMap(TelegramMediaWebFile.init), thumbnail: thumb.flatMap(TelegramMediaWebFile.init), message: ChatContextResultMessage(apiMessage: sendMessage)))
case let .botInlineMediaResult(_, id, type, photo, document, title, description, sendMessage):
case let .botInlineMediaResult(botInlineMediaResultData):
let (_, id, type, photo, document, title, description, sendMessage) = (botInlineMediaResultData.flags, botInlineMediaResultData.id, botInlineMediaResultData.type, botInlineMediaResultData.photo, botInlineMediaResultData.document, botInlineMediaResultData.title, botInlineMediaResultData.description, botInlineMediaResultData.sendMessage)
var image: TelegramMediaImage?
var file: TelegramMediaFile?
if let photo = photo, let parsedImage = telegramMediaImageFromApiPhoto(photo) {
@@ -609,7 +618,8 @@ extension ChatContextResult {
extension ChatContextResultSwitchPeer {
init(apiSwitchPeer: Api.InlineBotSwitchPM) {
switch apiSwitchPeer {
case let .inlineBotSwitchPM(text, startParam):
case let .inlineBotSwitchPM(inlineBotSwitchPMData):
let (text, startParam) = (inlineBotSwitchPMData.text, inlineBotSwitchPMData.startParam)
self.init(text: text, startParam: startParam)
}
}
@@ -618,7 +628,8 @@ extension ChatContextResultSwitchPeer {
extension ChatContextResultWebView {
init(apiSwitchWebView: Api.InlineBotWebView) {
switch apiSwitchWebView {
case let .inlineBotWebView(text, url):
case let .inlineBotWebView(inlineBotWebViewData):
let (text, url) = (inlineBotWebViewData.text, inlineBotWebViewData.url)
self.init(text: text, url: url)
}
}
@@ -627,7 +638,8 @@ extension ChatContextResultWebView {
extension ChatContextResultCollection {
convenience init(apiResults: Api.messages.BotResults, botId: PeerId, peerId: PeerId, query: String, geoPoint: (Double, Double)?) {
switch apiResults {
case let .botResults(flags, queryId, nextOffset, switchPm, switchWebView, results, cacheTime, _):
case let .botResults(botResultsData):
let (flags, queryId, nextOffset, switchPm, switchWebView, results, cacheTime, _) = (botResultsData.flags, botResultsData.queryId, botResultsData.nextOffset, botResultsData.switchPm, botResultsData.switchWebview, botResultsData.results, botResultsData.cacheTime, botResultsData.users)
var switchPeer: ChatContextResultSwitchPeer?
if let switchPm = switchPm {
switchPeer = ChatContextResultSwitchPeer(apiSwitchPeer: switchPm)
@@ -28,19 +28,19 @@ public protocol TelegramCloudMediaResourceWithFileReference {
extension CloudFileMediaResource: TelegramCloudMediaResource, TelegramMultipartFetchableResource, TelegramCloudMediaResourceWithFileReference {
func apiInputLocation(fileReference: Data?) -> Api.InputFileLocation? {
return Api.InputFileLocation.inputFileLocation(volumeId: self.volumeId, localId: self.localId, secret: self.secret, fileReference: Buffer(data: fileReference ?? Data()))
return Api.InputFileLocation.inputFileLocation(.init(volumeId: self.volumeId, localId: self.localId, secret: self.secret, fileReference: Buffer(data: fileReference ?? Data())))
}
}
extension CloudPhotoSizeMediaResource: TelegramCloudMediaResource, TelegramMultipartFetchableResource, TelegramCloudMediaResourceWithFileReference {
func apiInputLocation(fileReference: Data?) -> Api.InputFileLocation? {
return Api.InputFileLocation.inputPhotoFileLocation(id: self.photoId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: self.sizeSpec)
return Api.InputFileLocation.inputPhotoFileLocation(.init(id: self.photoId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: self.sizeSpec))
}
}
extension CloudDocumentSizeMediaResource: TelegramCloudMediaResource, TelegramMultipartFetchableResource, TelegramCloudMediaResourceWithFileReference {
func apiInputLocation(fileReference: Data?) -> Api.InputFileLocation? {
return Api.InputFileLocation.inputDocumentFileLocation(id: self.documentId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: self.sizeSpec)
return Api.InputFileLocation.inputDocumentFileLocation(.init(id: self.documentId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: self.sizeSpec))
}
}
@@ -54,7 +54,7 @@ extension CloudPeerPhotoSizeMediaResource: TelegramMultipartFetchableResource {
flags = 1 << 0
}
if let photoId = self.photoId {
return Api.InputFileLocation.inputPeerPhotoFileLocation(flags: flags, peer: peerReference.inputPeer, photoId: photoId)
return Api.InputFileLocation.inputPeerPhotoFileLocation(.init(flags: flags, peer: peerReference.inputPeer, photoId: photoId))
} else {
return nil
}
@@ -64,7 +64,7 @@ extension CloudPeerPhotoSizeMediaResource: TelegramMultipartFetchableResource {
extension CloudStickerPackThumbnailMediaResource: TelegramMultipartFetchableResource {
func apiInputLocation(packReference: StickerPackReference) -> Api.InputFileLocation? {
if let thumbVersion = self.thumbVersion {
return Api.InputFileLocation.inputStickerSetThumb(stickerset: packReference.apiInputStickerSet, thumbVersion: thumbVersion)
return Api.InputFileLocation.inputStickerSetThumb(.init(stickerset: packReference.apiInputStickerSet, thumbVersion: thumbVersion))
} else {
return nil
}
@@ -73,12 +73,12 @@ extension CloudStickerPackThumbnailMediaResource: TelegramMultipartFetchableReso
extension CloudDocumentMediaResource: TelegramCloudMediaResource, TelegramMultipartFetchableResource, TelegramCloudMediaResourceWithFileReference {
func apiInputLocation(fileReference: Data?) -> Api.InputFileLocation? {
return Api.InputFileLocation.inputDocumentFileLocation(id: self.fileId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: "")
return Api.InputFileLocation.inputDocumentFileLocation(.init(id: self.fileId, accessHash: self.accessHash, fileReference: Buffer(data: fileReference ?? Data()), thumbSize: ""))
}
}
extension SecretFileMediaResource: TelegramCloudMediaResource, TelegramMultipartFetchableResource {
func apiInputLocation(fileReference: Data?) -> Api.InputFileLocation? {
return .inputEncryptedFileLocation(id: self.fileId, accessHash: self.accessHash)
return .inputEncryptedFileLocation(.init(id: self.fileId, accessHash: self.accessHash))
}
}
@@ -6,7 +6,8 @@ import TelegramApi
extension ExportedInvitation {
init(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite {
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, subscriptionExpired, title, pricing):
case let .chatInviteExported(chatInviteExportedData):
let (flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, subscriptionExpired, title, pricing) = (chatInviteExportedData.flags, chatInviteExportedData.link, chatInviteExportedData.adminId, chatInviteExportedData.date, chatInviteExportedData.startDate, chatInviteExportedData.expireDate, chatInviteExportedData.usageLimit, chatInviteExportedData.usage, chatInviteExportedData.requested, chatInviteExportedData.subscriptionExpired, chatInviteExportedData.title, chatInviteExportedData.subscriptionPricing)
let _ = subscriptionExpired
self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested, pricing: pricing.flatMap { StarsSubscriptionPricing(apiStarsSubscriptionPricing: $0) })
case .chatInvitePublicJoinRequests:
@@ -6,7 +6,8 @@ import TelegramApi
extension InstantPageCaption {
convenience init(apiCaption: Api.PageCaption) {
switch apiCaption {
case let .pageCaption(text, credit):
case let .pageCaption(pageCaptionData):
let (text, credit) = (pageCaptionData.text, pageCaptionData.credit)
self.init(text: RichText(apiText: text), credit: RichText(apiText: credit))
}
}
@@ -28,18 +29,22 @@ public extension InstantPageListItem {
extension InstantPageListItem {
init(apiListItem: Api.PageListItem) {
switch apiListItem {
case let .pageListItemText(text):
case let .pageListItemText(pageListItemTextData):
let text = pageListItemTextData.text
self = .text(RichText(apiText: text), nil)
case let .pageListItemBlocks(blocks):
case let .pageListItemBlocks(pageListItemBlocksData):
let blocks = pageListItemBlocksData.blocks
self = .blocks(blocks.map({ InstantPageBlock(apiBlock: $0) }), nil)
}
}
init(apiListOrderedItem: Api.PageListOrderedItem) {
switch apiListOrderedItem {
case let .pageListOrderedItemText(num, text):
case let .pageListOrderedItemText(pageListOrderedItemTextData):
let (num, text) = (pageListOrderedItemTextData.num, pageListOrderedItemTextData.text)
self = .text(RichText(apiText: text), num)
case let .pageListOrderedItemBlocks(num, blocks):
case let .pageListOrderedItemBlocks(pageListOrderedItemBlocksData):
let (num, blocks) = (pageListOrderedItemBlocksData.num, pageListOrderedItemBlocksData.blocks)
self = .blocks(blocks.map({ InstantPageBlock(apiBlock: $0) }), num)
}
}
@@ -48,7 +53,8 @@ extension InstantPageListItem {
extension InstantPageTableCell {
convenience init(apiTableCell: Api.PageTableCell) {
switch apiTableCell {
case let .pageTableCell(flags, text, colspan, rowspan):
case let .pageTableCell(pageTableCellData):
let (flags, text, colspan, rowspan) = (pageTableCellData.flags, pageTableCellData.text, pageTableCellData.colspan, pageTableCellData.rowspan)
var alignment = TableHorizontalAlignment.left
if (flags & (1 << 3)) != 0 {
alignment = .center
@@ -69,7 +75,8 @@ extension InstantPageTableCell {
extension InstantPageTableRow {
convenience init(apiTableRow: Api.PageTableRow) {
switch apiTableRow {
case let .pageTableRow(cells):
case let .pageTableRow(pageTableRowData):
let cells = pageTableRowData.cells
self.init(cells: cells.map({ InstantPageTableCell(apiTableCell: $0) }))
}
}
@@ -78,7 +85,8 @@ extension InstantPageTableRow {
extension InstantPageRelatedArticle {
convenience init(apiRelatedArticle: Api.PageRelatedArticle) {
switch apiRelatedArticle {
case let .pageRelatedArticle(_, url, webpageId, title, description, photoId, author, publishedDate):
case let .pageRelatedArticle(pageRelatedArticleData):
let (url, webpageId, title, description, photoId, author, publishedDate) = (pageRelatedArticleData.url, pageRelatedArticleData.webpageId, pageRelatedArticleData.title, pageRelatedArticleData.description, pageRelatedArticleData.photoId, pageRelatedArticleData.author, pageRelatedArticleData.publishedDate)
var posterPhotoId: MediaId?
if let photoId = photoId {
posterPhotoId = MediaId(namespace: Namespaces.Media.CloudImage, id: photoId)
@@ -93,71 +101,99 @@ extension InstantPageBlock {
switch apiBlock {
case .pageBlockUnsupported:
self = .unsupported
case let .pageBlockTitle(text):
case let .pageBlockTitle(pageBlockTitleData):
let text = pageBlockTitleData.text
self = .title(RichText(apiText: text))
case let .pageBlockSubtitle(text):
case let .pageBlockSubtitle(pageBlockSubtitleData):
let text = pageBlockSubtitleData.text
self = .subtitle(RichText(apiText: text))
case let .pageBlockAuthorDate(author, publishedDate):
case let .pageBlockAuthorDate(pageBlockAuthorDateData):
let (author, publishedDate) = (pageBlockAuthorDateData.author, pageBlockAuthorDateData.publishedDate)
self = .authorDate(author: RichText(apiText: author), date: publishedDate)
case let .pageBlockHeader(text):
case let .pageBlockHeader(pageBlockHeaderData):
let text = pageBlockHeaderData.text
self = .header(RichText(apiText: text))
case let .pageBlockSubheader(text):
case let .pageBlockSubheader(pageBlockSubheaderData):
let text = pageBlockSubheaderData.text
self = .subheader(RichText(apiText: text))
case let .pageBlockParagraph(text):
case let .pageBlockParagraph(pageBlockParagraphData):
let text = pageBlockParagraphData.text
self = .paragraph(RichText(apiText: text))
case let .pageBlockPreformatted(text, _):
case let .pageBlockPreformatted(pageBlockPreformattedData):
let text = pageBlockPreformattedData.text
self = .preformatted(RichText(apiText: text))
case let .pageBlockFooter(text):
case let .pageBlockFooter(pageBlockFooterData):
let text = pageBlockFooterData.text
self = .footer(RichText(apiText: text))
case .pageBlockDivider:
self = .divider
case let .pageBlockAnchor(name):
case let .pageBlockAnchor(pageBlockAnchorData):
let name = pageBlockAnchorData.name
self = .anchor(name)
case let .pageBlockBlockquote(text, caption):
case let .pageBlockBlockquote(pageBlockBlockquoteData):
let (text, caption) = (pageBlockBlockquoteData.text, pageBlockBlockquoteData.caption)
self = .blockQuote(text: RichText(apiText: text), caption: RichText(apiText: caption))
case let .pageBlockPullquote(text, caption):
case let .pageBlockPullquote(pageBlockPullquoteData):
let (text, caption) = (pageBlockPullquoteData.text, pageBlockPullquoteData.caption)
self = .pullQuote(text: RichText(apiText: text), caption: RichText(apiText: caption))
case let .pageBlockPhoto(flags, photoId, caption, url, webpageId):
case let .pageBlockPhoto(pageBlockPhotoData):
let (flags, photoId, caption, url, webpageId) = (pageBlockPhotoData.flags, pageBlockPhotoData.photoId, pageBlockPhotoData.caption, pageBlockPhotoData.url, pageBlockPhotoData.webpageId)
var webpageMediaId: MediaId?
if (flags & (1 << 0)) != 0, let webpageId = webpageId, webpageId != 0 {
webpageMediaId = MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId)
}
self = .image(id: MediaId(namespace: Namespaces.Media.CloudImage, id: photoId), caption: InstantPageCaption(apiCaption: caption), url: url, webpageId: webpageMediaId)
case let .pageBlockVideo(flags, videoId, caption):
case let .pageBlockVideo(pageBlockVideoData):
let (flags, videoId, caption) = (pageBlockVideoData.flags, pageBlockVideoData.videoId, pageBlockVideoData.caption)
self = .video(id: MediaId(namespace: Namespaces.Media.CloudFile, id: videoId), caption: InstantPageCaption(apiCaption: caption), autoplay: (flags & (1 << 0)) != 0, loop: (flags & (1 << 1)) != 0)
case let .pageBlockCover(cover):
case let .pageBlockCover(pageBlockCoverData):
let cover = pageBlockCoverData.cover
self = .cover(InstantPageBlock(apiBlock: cover))
case let .pageBlockEmbed(flags, url, html, posterPhotoId, w, h, caption):
case let .pageBlockEmbed(pageBlockEmbedData):
let (flags, url, html, posterPhotoId, w, h, caption) = (pageBlockEmbedData.flags, pageBlockEmbedData.url, pageBlockEmbedData.html, pageBlockEmbedData.posterPhotoId, pageBlockEmbedData.w, pageBlockEmbedData.h, pageBlockEmbedData.caption)
var dimensions: PixelDimensions?
if let w = w, let h = h {
dimensions = PixelDimensions(width: w, height: h)
}
self = .webEmbed(url: url, html: html, dimensions: dimensions, caption: InstantPageCaption(apiCaption: caption), stretchToWidth: (flags & (1 << 0)) != 0, allowScrolling: (flags & (1 << 3)) != 0, coverId: posterPhotoId.flatMap { MediaId(namespace: Namespaces.Media.CloudImage, id: $0) })
case let .pageBlockEmbedPost(url, webpageId, authorPhotoId, author, date, blocks, caption):
case let .pageBlockEmbedPost(pageBlockEmbedPostData):
let (url, webpageId, authorPhotoId, author, date, blocks, caption) = (pageBlockEmbedPostData.url, pageBlockEmbedPostData.webpageId, pageBlockEmbedPostData.authorPhotoId, pageBlockEmbedPostData.author, pageBlockEmbedPostData.date, pageBlockEmbedPostData.blocks, pageBlockEmbedPostData.caption)
self = .postEmbed(url: url, webpageId: webpageId == 0 ? nil : MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId), avatarId: authorPhotoId == 0 ? nil : MediaId(namespace: Namespaces.Media.CloudImage, id: authorPhotoId), author: author, date: date, blocks: blocks.map({ InstantPageBlock(apiBlock: $0) }), caption: InstantPageCaption(apiCaption: caption))
case let .pageBlockCollage(items, caption):
case let .pageBlockCollage(pageBlockCollageData):
let (items, caption) = (pageBlockCollageData.items, pageBlockCollageData.caption)
self = .collage(items: items.map({ InstantPageBlock(apiBlock: $0) }), caption: InstantPageCaption(apiCaption: caption))
case let .pageBlockSlideshow(items, caption):
case let .pageBlockSlideshow(pageBlockSlideshowData):
let (items, caption) = (pageBlockSlideshowData.items, pageBlockSlideshowData.caption)
self = .slideshow(items: items.map({ InstantPageBlock(apiBlock: $0) }), caption: InstantPageCaption(apiCaption: caption))
case let .pageBlockChannel(channel: apiChat):
case let .pageBlockChannel(pageBlockChannelData):
let apiChat = pageBlockChannelData.channel
self = .channelBanner(parseTelegramGroupOrChannel(chat: apiChat) as? TelegramChannel)
case let .pageBlockAudio(audioId, caption):
case let .pageBlockAudio(pageBlockAudioData):
let (audioId, caption) = (pageBlockAudioData.audioId, pageBlockAudioData.caption)
self = .audio(id: MediaId(namespace: Namespaces.Media.CloudFile, id: audioId), caption: InstantPageCaption(apiCaption: caption))
case let .pageBlockKicker(text):
case let .pageBlockKicker(pageBlockKickerData):
let text = pageBlockKickerData.text
self = .kicker(RichText(apiText: text))
case let .pageBlockTable(flags, title, rows):
case let .pageBlockTable(pageBlockTableData):
let (flags, title, rows) = (pageBlockTableData.flags, pageBlockTableData.title, pageBlockTableData.rows)
self = .table(title: RichText(apiText: title), rows: rows.map({ InstantPageTableRow(apiTableRow: $0) }), bordered: (flags & (1 << 0)) != 0, striped: (flags & (1 << 1)) != 0)
case let .pageBlockList(items):
case let .pageBlockList(pageBlockListData):
let items = pageBlockListData.items
self = .list(items: items.map({ InstantPageListItem(apiListItem: $0) }), ordered: false)
case let .pageBlockOrderedList(items):
case let .pageBlockOrderedList(pageBlockOrderedListData):
let items = pageBlockOrderedListData.items
self = .list(items: items.map({ InstantPageListItem(apiListOrderedItem: $0) }), ordered: true)
case let .pageBlockDetails(flags, blocks, title):
case let .pageBlockDetails(pageBlockDetailsData):
let (flags, blocks, title) = (pageBlockDetailsData.flags, pageBlockDetailsData.blocks, pageBlockDetailsData.title)
self = .details(title: RichText(apiText: title), blocks: blocks.map({ InstantPageBlock(apiBlock: $0) }), expanded: (flags & (1 << 0)) != 0)
case let .pageBlockRelatedArticles(title, articles):
case let .pageBlockRelatedArticles(pageBlockRelatedArticlesData):
let (title, articles) = (pageBlockRelatedArticlesData.title, pageBlockRelatedArticlesData.articles)
self = .relatedArticles(title: RichText(apiText: title), articles: articles.map({ InstantPageRelatedArticle(apiRelatedArticle: $0) }))
case let .pageBlockMap(geo, zoom, w, h, caption):
case let .pageBlockMap(pageBlockMapData):
let (geo, zoom, w, h, caption) = (pageBlockMapData.geo, pageBlockMapData.zoom, pageBlockMapData.w, pageBlockMapData.h, pageBlockMapData.caption)
switch geo {
case let .geoPoint(_, long, lat, _, _):
case let .geoPoint(geoPointData):
let (long, lat) = (geoPointData.long, geoPointData.lat)
self = .map(latitude: lat, longitude: long, zoom: zoom, dimensions: PixelDimensions(width: w, height: h), caption: InstantPageCaption(apiCaption: caption))
default:
self = .unsupported
@@ -176,7 +212,8 @@ extension InstantPage {
let url: String
let views: Int32?
switch apiPage {
case let .page(flags, pageUrl, pageBlocks, pagePhotos, pageDocuments, pageViews):
case let .page(pageData):
let (flags, pageUrl, pageBlocks, pagePhotos, pageDocuments, pageViews) = (pageData.flags, pageData.url, pageData.blocks, pageData.photos, pageData.documents, pageData.views)
url = pageUrl
blocks = pageBlocks
photos = pagePhotos
@@ -6,7 +6,8 @@ import TelegramApi
extension RestrictionRule {
convenience init(apiReason: Api.RestrictionReason) {
switch apiReason {
case let .restrictionReason(platform, reason, text):
case let .restrictionReason(restrictionReasonData):
let (platform, reason, text) = (restrictionReasonData.platform, restrictionReasonData.reason, restrictionReasonData.text)
self.init(platform: platform, reason: reason, text: text)
}
}
@@ -6,8 +6,10 @@ import TelegramApi
extension PeerGeoLocation {
init?(apiLocation: Api.ChannelLocation) {
switch apiLocation {
case let .channelLocation(geopoint, address):
if case let .geoPoint(_, longitude, latitude, _, _) = geopoint {
case let .channelLocation(channelLocationData):
let (geopoint, address) = (channelLocationData.geoPoint, channelLocationData.address)
if case let .geoPoint(geoPointData) = geopoint {
let (longitude, latitude) = (geoPointData.long, geoPointData.lat)
self.init(latitude: latitude, longitude: longitude, address: address)
} else {
return nil
@@ -5,13 +5,15 @@ import TelegramApi
extension ReactionsMessageAttribute {
func withUpdatedResults(_ reactions: Api.MessageReactions) -> ReactionsMessageAttribute {
switch reactions {
case let .messageReactions(flags, results, recentReactions, topReactors):
case let .messageReactions(messageReactionsData):
let (flags, results, recentReactions, topReactors) = (messageReactionsData.flags, messageReactionsData.results, messageReactionsData.recentReactions, messageReactionsData.topReactors)
let min = (flags & (1 << 0)) != 0
let canViewList = (flags & (1 << 2)) != 0
let isTags = (flags & (1 << 3)) != 0
var reactions = results.compactMap { result -> MessageReaction? in
switch result {
case let .reactionCount(_, chosenOrder, reaction, count):
case let .reactionCount(reactionCountData):
let (_, chosenOrder, reaction, count) = (reactionCountData.flags, reactionCountData.chosenOrder, reactionCountData.reaction, reactionCountData.count)
if let reaction = MessageReaction.Reaction(apiReaction: reaction) {
return MessageReaction(value: reaction, count: count, chosenOrder: chosenOrder.flatMap(Int.init))
} else {
@@ -23,7 +25,8 @@ extension ReactionsMessageAttribute {
if let recentReactions = recentReactions {
parsedRecentReactions = recentReactions.compactMap { recentReaction -> ReactionsMessageAttribute.RecentPeer? in
switch recentReaction {
case let .messagePeerReaction(flags, peerId, date, reaction):
case let .messagePeerReaction(messagePeerReactionData):
let (flags, peerId, date, reaction) = (messagePeerReactionData.flags, messagePeerReactionData.peerId, messagePeerReactionData.date, messagePeerReactionData.reaction)
let isLarge = (flags & (1 << 0)) != 0
let isUnseen = (flags & (1 << 1)) != 0
let isMy = (flags & (1 << 2)) != 0
@@ -37,7 +40,7 @@ extension ReactionsMessageAttribute {
} else {
parsedRecentReactions = []
}
if min {
var currentSelectedReactions: [MessageReaction.Reaction: Int] = [:]
for reaction in self.reactions {
@@ -59,7 +62,8 @@ extension ReactionsMessageAttribute {
if let topReactors {
for item in topReactors {
switch item {
case let .messageReactor(flags, peerId, count):
case let .messageReactor(messageReactorData):
let (flags, peerId, count) = (messageReactorData.flags, messageReactorData.peerId, messageReactorData.count)
topPeers.append(ReactionsMessageAttribute.TopPeer(
peerId: peerId?.peerId,
count: count,
@@ -70,7 +74,7 @@ extension ReactionsMessageAttribute {
}
}
}
return ReactionsMessageAttribute(canViewList: canViewList, isTags: isTags, reactions: reactions, recentPeers: parsedRecentReactions, topPeers: topPeers)
}
}
@@ -258,14 +262,16 @@ public func mergedMessageReactions(attributes: [MessageAttribute], isTags: Bool)
extension ReactionsMessageAttribute {
convenience init(apiReactions: Api.MessageReactions) {
switch apiReactions {
case let .messageReactions(flags, results, recentReactions, topReactors):
case let .messageReactions(messageReactionsData):
let (flags, results, recentReactions, topReactors) = (messageReactionsData.flags, messageReactionsData.results, messageReactionsData.recentReactions, messageReactionsData.topReactors)
let canViewList = (flags & (1 << 2)) != 0
let isTags = (flags & (1 << 3)) != 0
let parsedRecentReactions: [ReactionsMessageAttribute.RecentPeer]
if let recentReactions = recentReactions {
parsedRecentReactions = recentReactions.compactMap { recentReaction -> ReactionsMessageAttribute.RecentPeer? in
switch recentReaction {
case let .messagePeerReaction(flags, peerId, date, reaction):
case let .messagePeerReaction(messagePeerReactionData):
let (flags, peerId, date, reaction) = (messagePeerReactionData.flags, messagePeerReactionData.peerId, messagePeerReactionData.date, messagePeerReactionData.reaction)
let isLarge = (flags & (1 << 0)) != 0
let isUnseen = (flags & (1 << 1)) != 0
let isMy = (flags & (1 << 2)) != 0
@@ -279,12 +285,13 @@ extension ReactionsMessageAttribute {
} else {
parsedRecentReactions = []
}
var topPeers: [ReactionsMessageAttribute.TopPeer] = []
if let topReactors {
for item in topReactors {
switch item {
case let .messageReactor(flags, peerId, count):
case let .messageReactor(messageReactorData):
let (flags, peerId, count) = (messageReactorData.flags, messageReactorData.peerId, messageReactorData.count)
topPeers.append(ReactionsMessageAttribute.TopPeer(
peerId: peerId?.peerId,
count: count,
@@ -295,13 +302,14 @@ extension ReactionsMessageAttribute {
}
}
}
self.init(
canViewList: canViewList,
isTags: isTags,
reactions: results.compactMap { result -> MessageReaction? in
switch result {
case let .reactionCount(_, chosenOrder, reaction, count):
case let .reactionCount(reactionCountData):
let (_, chosenOrder, reaction, count) = (reactionCountData.flags, reactionCountData.chosenOrder, reactionCountData.reaction, reactionCountData.count)
if let reaction = MessageReaction.Reaction(apiReaction: reaction) {
return MessageReaction(value: reaction, count: count, chosenOrder: chosenOrder.flatMap(Int.init))
} else {
@@ -26,91 +26,141 @@ extension ReplyMarkupButtonAction.PeerTypes {
extension ReplyMarkupButton {
init(apiButton: Api.KeyboardButton) {
switch apiButton {
case let .keyboardButton(text):
self.init(title: text, titleWhenForwarded: nil, action: .text)
case let .keyboardButtonCallback(flags, text, data):
let memory = malloc(data.size)!
memcpy(memory, data.data, data.size)
let dataBuffer = MemoryBuffer(memory: memory, capacity: data.size, length: data.size, freeWhenDone: true)
self.init(title: text, titleWhenForwarded: nil, action: .callback(requiresPassword: (flags & (1 << 0)) != 0, data: dataBuffer))
case let .keyboardButtonRequestGeoLocation(text):
self.init(title: text, titleWhenForwarded: nil, action: .requestMap)
case let .keyboardButtonRequestPhone(text):
self.init(title: text, titleWhenForwarded: nil, action: .requestPhone)
case let .keyboardButtonSwitchInline(flags, text, query, types):
var peerTypes = ReplyMarkupButtonAction.PeerTypes()
if let types = types {
for type in types {
switch type {
case .inlineQueryPeerTypePM:
peerTypes.insert(.users)
case .inlineQueryPeerTypeBotPM:
peerTypes.insert(.bots)
case .inlineQueryPeerTypeBroadcast:
peerTypes.insert(.channels)
case .inlineQueryPeerTypeChat, .inlineQueryPeerTypeMegagroup:
peerTypes.insert(.groups)
case .inlineQueryPeerTypeSameBotPM:
break
}
case let .keyboardButton(keyboardButtonData):
let text = keyboardButtonData.text
self.init(title: text, titleWhenForwarded: nil, action: .text, style: keyboardButtonData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonCallback(keyboardButtonCallbackData):
let (flags, text, data) = (keyboardButtonCallbackData.flags, keyboardButtonCallbackData.text, keyboardButtonCallbackData.data)
let memory = malloc(data.size)!
memcpy(memory, data.data, data.size)
let dataBuffer = MemoryBuffer(memory: memory, capacity: data.size, length: data.size, freeWhenDone: true)
self.init(title: text, titleWhenForwarded: nil, action: .callback(requiresPassword: (flags & (1 << 0)) != 0, data: dataBuffer), style: keyboardButtonCallbackData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonRequestGeoLocation(keyboardButtonRequestGeoLocationData):
let text = keyboardButtonRequestGeoLocationData.text
self.init(title: text, titleWhenForwarded: nil, action: .requestMap, style: keyboardButtonRequestGeoLocationData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonRequestPhone(keyboardButtonRequestPhoneData):
let text = keyboardButtonRequestPhoneData.text
self.init(title: text, titleWhenForwarded: nil, action: .requestPhone, style: keyboardButtonRequestPhoneData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonSwitchInline(keyboardButtonSwitchInlineData):
let (flags, text, query, types) = (keyboardButtonSwitchInlineData.flags, keyboardButtonSwitchInlineData.text, keyboardButtonSwitchInlineData.query, keyboardButtonSwitchInlineData.peerTypes)
var peerTypes = ReplyMarkupButtonAction.PeerTypes()
if let types = types {
for type in types {
switch type {
case .inlineQueryPeerTypePM:
peerTypes.insert(.users)
case .inlineQueryPeerTypeBotPM:
peerTypes.insert(.bots)
case .inlineQueryPeerTypeBroadcast:
peerTypes.insert(.channels)
case .inlineQueryPeerTypeChat, .inlineQueryPeerTypeMegagroup:
peerTypes.insert(.groups)
case .inlineQueryPeerTypeSameBotPM:
break
}
}
self.init(title: text, titleWhenForwarded: nil, action: .switchInline(samePeer: (flags & (1 << 0)) != 0, query: query, peerTypes: peerTypes))
case let .keyboardButtonUrl(text, url):
self.init(title: text, titleWhenForwarded: nil, action: .url(url))
case let .keyboardButtonGame(text):
self.init(title: text, titleWhenForwarded: nil, action: .openWebApp)
case let .keyboardButtonBuy(text):
self.init(title: text, titleWhenForwarded: nil, action: .payment)
case let .keyboardButtonUrlAuth(_, text, fwdText, url, buttonId):
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: buttonId))
case let .inputKeyboardButtonUrlAuth(_, text, fwdText, url, _):
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: 0))
case let .keyboardButtonRequestPoll(_, quiz, text):
let isQuiz: Bool? = quiz.flatMap { quiz in
if case .boolTrue = quiz {
return true
} else {
return false
}
}
self.init(title: text, titleWhenForwarded: nil, action: .switchInline(samePeer: (flags & (1 << 0)) != 0, query: query, peerTypes: peerTypes), style: keyboardButtonSwitchInlineData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonUrl(keyboardButtonUrlData):
let (text, url) = (keyboardButtonUrlData.text, keyboardButtonUrlData.url)
self.init(title: text, titleWhenForwarded: nil, action: .url(url), style: keyboardButtonUrlData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonGame(keyboardButtonGameData):
let text = keyboardButtonGameData.text
self.init(title: text, titleWhenForwarded: nil, action: .openWebApp, style: keyboardButtonGameData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonBuy(keyboardButtonBuyData):
let text = keyboardButtonBuyData.text
self.init(title: text, titleWhenForwarded: nil, action: .payment, style: keyboardButtonBuyData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonUrlAuth(keyboardButtonUrlAuthData):
let (text, fwdText, url, buttonId) = (keyboardButtonUrlAuthData.text, keyboardButtonUrlAuthData.fwdText, keyboardButtonUrlAuthData.url, keyboardButtonUrlAuthData.buttonId)
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: buttonId), style: keyboardButtonUrlAuthData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .inputKeyboardButtonUrlAuth(inputKeyboardButtonUrlAuthData):
let (text, fwdText, url) = (inputKeyboardButtonUrlAuthData.text, inputKeyboardButtonUrlAuthData.fwdText, inputKeyboardButtonUrlAuthData.url)
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: 0), style: inputKeyboardButtonUrlAuthData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonRequestPoll(keyboardButtonRequestPollData):
let (quiz, text) = (keyboardButtonRequestPollData.quiz, keyboardButtonRequestPollData.text)
let isQuiz: Bool? = quiz.flatMap { quiz in
if case .boolTrue = quiz {
return true
} else {
return false
}
self.init(title: text, titleWhenForwarded: nil, action: .setupPoll(isQuiz: isQuiz))
case let .keyboardButtonUserProfile(text, userId):
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))))
case let .inputKeyboardButtonUserProfile(text, _):
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0))))
case let .keyboardButtonWebView(text, url):
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: false))
case let .keyboardButtonSimpleWebView(text, url):
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: true))
case let .keyboardButtonRequestPeer(text, buttonId, peerType, maxQuantity), let .inputKeyboardButtonRequestPeer(_, text, buttonId, peerType, maxQuantity):
let mappedPeerType: ReplyMarkupButtonRequestPeerType
switch peerType {
case let .requestPeerTypeUser(_, bot, premium):
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
isBot: bot.flatMap({ $0 == .boolTrue }),
isPremium: premium.flatMap({ $0 == .boolTrue })
))
case let .requestPeerTypeChat(flags, hasUsername, forum, userAdminRights, botAdminRights):
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
isForum: forum.flatMap({ $0 == .boolTrue }),
botParticipant: (flags & (1 << 5)) != 0,
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
case let .requestPeerTypeBroadcast(flags, hasUsername, userAdminRights, botAdminRights):
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
}
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity))
case let .keyboardButtonCopy(text, payload):
self.init(title: text, titleWhenForwarded: nil, action: .copyText(payload: payload))
}
self.init(title: text, titleWhenForwarded: nil, action: .setupPoll(isQuiz: isQuiz), style: keyboardButtonRequestPollData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonUserProfile(keyboardButtonUserProfileData):
let (text, userId) = (keyboardButtonUserProfileData.text, keyboardButtonUserProfileData.userId)
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))), style: keyboardButtonUserProfileData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .inputKeyboardButtonUserProfile(inputKeyboardButtonUserProfileData):
let text = inputKeyboardButtonUserProfileData.text
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0))), style: inputKeyboardButtonUserProfileData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonWebView(keyboardButtonWebViewData):
let (text, url) = (keyboardButtonWebViewData.text, keyboardButtonWebViewData.url)
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: false), style: keyboardButtonWebViewData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonSimpleWebView(keyboardButtonSimpleWebViewData):
let (text, url) = (keyboardButtonSimpleWebViewData.text, keyboardButtonSimpleWebViewData.url)
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: true), style: keyboardButtonSimpleWebViewData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonRequestPeer(keyboardButtonRequestPeerData):
let (text, buttonId, peerType, maxQuantity) = (keyboardButtonRequestPeerData.text, keyboardButtonRequestPeerData.buttonId, keyboardButtonRequestPeerData.peerType, keyboardButtonRequestPeerData.maxQuantity)
let mappedPeerType: ReplyMarkupButtonRequestPeerType
switch peerType {
case let .requestPeerTypeUser(requestPeerTypeUserData):
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
isBot: bot.flatMap({ $0 == .boolTrue }),
isPremium: premium.flatMap({ $0 == .boolTrue })
))
case let .requestPeerTypeChat(requestPeerTypeChatData):
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
isForum: forum.flatMap({ $0 == .boolTrue }),
botParticipant: (flags & (1 << 5)) != 0,
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
}
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity), style: keyboardButtonRequestPeerData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .inputKeyboardButtonRequestPeer(inputKeyboardButtonRequestPeerData):
let (text, buttonId, peerType, maxQuantity) = (inputKeyboardButtonRequestPeerData.text, inputKeyboardButtonRequestPeerData.buttonId, inputKeyboardButtonRequestPeerData.peerType, inputKeyboardButtonRequestPeerData.maxQuantity)
let mappedPeerType: ReplyMarkupButtonRequestPeerType
switch peerType {
case let .requestPeerTypeUser(requestPeerTypeUserData):
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
isBot: bot.flatMap({ $0 == .boolTrue }),
isPremium: premium.flatMap({ $0 == .boolTrue })
))
case let .requestPeerTypeChat(requestPeerTypeChatData):
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
isForum: forum.flatMap({ $0 == .boolTrue }),
botParticipant: (flags & (1 << 5)) != 0,
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
isCreator: (flags & (1 << 0)) != 0,
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
))
}
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity), style: inputKeyboardButtonRequestPeerData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
case let .keyboardButtonCopy(keyboardButtonCopyData):
let (text, payload) = (keyboardButtonCopyData.text, keyboardButtonCopyData.copyText)
self.init(title: text, titleWhenForwarded: nil, action: .copyText(payload: payload), style: keyboardButtonCopyData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
}
}
}
@@ -118,7 +168,8 @@ extension ReplyMarkupButton {
extension ReplyMarkupRow {
init(apiRow: Api.KeyboardButtonRow) {
switch apiRow {
case let .keyboardButtonRow(buttons):
case let .keyboardButtonRow(keyboardButtonRowData):
let buttons = keyboardButtonRowData.buttons
self.init(buttons: buttons.map { ReplyMarkupButton(apiButton: $0) })
}
}
@@ -130,7 +181,8 @@ extension ReplyMarkupMessageAttribute {
var flags = ReplyMarkupMessageFlags()
var placeholder: String?
switch apiMarkup {
case let .replyKeyboardMarkup(markupFlags, apiRows, apiPlaceholder):
case let .replyKeyboardMarkup(replyKeyboardMarkupData):
let (markupFlags, apiRows, apiPlaceholder) = (replyKeyboardMarkupData.flags, replyKeyboardMarkupData.rows, replyKeyboardMarkupData.placeholder)
rows = apiRows.map { ReplyMarkupRow(apiRow: $0) }
if (markupFlags & (1 << 0)) != 0 {
flags.insert(.fit)
@@ -145,10 +197,12 @@ extension ReplyMarkupMessageAttribute {
flags.insert(.persistent)
}
placeholder = apiPlaceholder
case let .replyInlineMarkup(apiRows):
case let .replyInlineMarkup(replyInlineMarkupData):
let apiRows = replyInlineMarkupData.rows
rows = apiRows.map { ReplyMarkupRow(apiRow: $0) }
flags.insert(.inline)
case let .replyKeyboardForceReply(forceReplyFlags, apiPlaceholder):
case let .replyKeyboardForceReply(replyKeyboardForceReplyData):
let (forceReplyFlags, apiPlaceholder) = (replyKeyboardForceReplyData.flags, replyKeyboardForceReplyData.placeholder)
if (forceReplyFlags & (1 << 1)) != 0 {
flags.insert(.once)
}
@@ -157,7 +211,8 @@ extension ReplyMarkupMessageAttribute {
}
flags.insert(.setupReply)
placeholder = apiPlaceholder
case let .replyKeyboardHide(hideFlags):
case let .replyKeyboardHide(replyKeyboardHideData):
let hideFlags = replyKeyboardHideData.flags
if (hideFlags & (1 << 2)) != 0 {
flags.insert(.personal)
}
@@ -8,35 +8,50 @@ extension RichText {
switch apiText {
case .textEmpty:
self = .empty
case let .textPlain(text):
case let .textPlain(textPlainData):
let text = textPlainData.text
self = .plain(text)
case let .textBold(text):
case let .textBold(textBoldData):
let text = textBoldData.text
self = .bold(RichText(apiText: text))
case let .textItalic(text):
case let .textItalic(textItalicData):
let text = textItalicData.text
self = .italic(RichText(apiText: text))
case let .textUnderline(text):
case let .textUnderline(textUnderlineData):
let text = textUnderlineData.text
self = .underline(RichText(apiText: text))
case let .textStrike(text):
case let .textStrike(textStrikeData):
let text = textStrikeData.text
self = .strikethrough(RichText(apiText: text))
case let .textFixed(text):
case let .textFixed(textFixedData):
let text = textFixedData.text
self = .fixed(RichText(apiText: text))
case let .textUrl(text, url, webpageId):
case let .textUrl(textUrlData):
let (text, url, webpageId) = (textUrlData.text, textUrlData.url, textUrlData.webpageId)
self = .url(text: RichText(apiText: text), url: url, webpageId: webpageId == 0 ? nil : MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId))
case let .textEmail(text, email):
case let .textEmail(textEmailData):
let (text, email) = (textEmailData.text, textEmailData.email)
self = .email(text: RichText(apiText: text), email: email)
case let .textConcat(texts):
case let .textConcat(textConcatData):
let texts = textConcatData.texts
self = .concat(texts.map({ RichText(apiText: $0) }))
case let .textSubscript(text):
case let .textSubscript(textSubscriptData):
let text = textSubscriptData.text
self = .subscript(RichText(apiText: text))
case let .textSuperscript(text):
case let .textSuperscript(textSuperscriptData):
let text = textSuperscriptData.text
self = .superscript(RichText(apiText: text))
case let .textMarked(text):
case let .textMarked(textMarkedData):
let text = textMarkedData.text
self = .marked(RichText(apiText: text))
case let .textPhone(text, phone):
case let .textPhone(textPhoneData):
let (text, phone) = (textPhoneData.text, textPhoneData.phone)
self = .phone(text: RichText(apiText: text), phone: phone)
case let .textImage(documentId, w, h):
case let .textImage(textImageData):
let (documentId, w, h) = (textImageData.documentId, textImageData.w, textImageData.h)
self = .image(id: MediaId(namespace: Namespaces.Media.CloudFile, id: documentId), dimensions: PixelDimensions(width: w, height: h))
case let .textAnchor(text, name):
case let .textAnchor(textAnchorData):
let (text, name) = (textAnchorData.text, textAnchorData.name)
self = .anchor(text: RichText(apiText: text), name: name)
}
}
@@ -81,6 +81,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
}
}
if isAnimated {
// TODO(swiftgram): refinedTag = [.photoOrVideo, .video, .gif]
refinedTag = .gif
}
if file.isAnimatedSticker {
@@ -128,27 +129,30 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
switch messsage {
case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
let chatPeerId = messagePeerId
case let .message(messageData):
let chatPeerId = messageData.peerId
return chatPeerId.peerId
case let .messageEmpty(_, _, peerId):
case let .messageEmpty(messageEmptyData):
let (_, _, peerId) = (messageEmptyData.flags, messageEmptyData.id, messageEmptyData.peerId)
if let peerId = peerId {
return peerId.peerId
} else {
return nil
}
case let .messageService(_, _, _, chatPeerId, _, _, _, _, _, _):
case let .messageService(messageServiceData):
let chatPeerId = messageServiceData.peerId
return chatPeerId.peerId
}
}
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
switch message {
case let .message(_, _, _, fromId, _, chatPeerId, savedPeerId, fwdHeader, viaBotId, viaBusinessBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .message(messageData):
let (fromId, chatPeerId, savedPeerId, fwdHeader, viaBotId, viaBusinessBotId, replyTo, media, entities) = (messageData.fromId, messageData.peerId, messageData.savedPeerId, messageData.fwdFrom, messageData.viaBotId, messageData.viaBusinessBotId, messageData.replyTo, messageData.media, messageData.entities)
let peerId: PeerId = chatPeerId.peerId
var result = [peerId]
let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId
if resolvedFromId != peerId {
@@ -157,7 +161,8 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
if let fwdHeader = fwdHeader {
switch fwdHeader {
case let .messageFwdHeader(_, fromId, _, _, _, _, savedFromPeer, _, savedFromId, _, _, _):
case let .messageFwdHeader(messageFwdHeaderData):
let (fromId, savedFromPeer, savedFromId) = (messageFwdHeaderData.fromId, messageFwdHeaderData.savedFromPeer, messageFwdHeaderData.savedFromId)
if let fromId = fromId {
result.append(fromId.peerId)
}
@@ -183,7 +188,8 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
if let media = media {
switch media {
case let .messageMediaContact(_, _, _, _, userId):
case let .messageMediaContact(messageMediaContactData):
let userId = messageMediaContactData.userId
if userId != 0 {
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)))
}
@@ -195,7 +201,8 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
if let entities = entities {
for entity in entities {
switch entity {
case let .messageEntityMentionName(_, _, userId):
case let .messageEntityMentionName(messageEntityMentionNameData):
let userId = messageEntityMentionNameData.userId
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)))
default:
break
@@ -205,7 +212,8 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
if let replyTo = replyTo {
switch replyTo {
case let .messageReplyStoryHeader(peer, _):
case let .messageReplyStoryHeader(messageReplyStoryHeaderData):
let peer = messageReplyStoryHeaderData.peer
let storyPeerId = peer.peerId
if !result.contains(storyPeerId) {
result.append(storyPeerId)
@@ -218,12 +226,13 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
return result
case .messageEmpty:
return []
case let .messageService(_, _, fromId, chatPeerId, savedPeerId, _, _, action, _, _):
case let .messageService(messageServiceData):
let (fromId, chatPeerId, savedPeerId, action) = (messageServiceData.fromId, messageServiceData.peerId, messageServiceData.savedPeerId, messageServiceData.action)
let peerId: PeerId = chatPeerId.peerId
var result = [peerId]
let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId
if resolvedFromId != peerId {
result.append(resolvedFromId)
}
@@ -234,43 +243,60 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday, .messageActionStarGiftPurchaseOffer, .messageActionStarGiftPurchaseOfferDeclined:
break
case let .messageActionChannelMigrateFrom(_, chatId):
case let .messageActionChannelMigrateFrom(messageActionChannelMigrateFromData):
let chatId = messageActionChannelMigrateFromData.chatId
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))
case let .messageActionChatAddUser(users):
case let .messageActionChatAddUser(messageActionChatAddUserData):
let users = messageActionChatAddUserData.users
for id in users {
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)))
}
case let .messageActionChatCreate(_, users):
case let .messageActionChatCreate(messageActionChatCreateData):
let users = messageActionChatCreateData.users
for id in users {
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)))
}
case let .messageActionChatDeleteUser(userId):
case let .messageActionChatDeleteUser(messageActionChatDeleteUserData):
let userId = messageActionChatDeleteUserData.userId
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)))
case let .messageActionChatJoinedByLink(inviterId):
case let .messageActionChatJoinedByLink(messageActionChatJoinedByLinkData):
let inviterId = messageActionChatJoinedByLinkData.inviterId
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(inviterId)))
case let .messageActionChatMigrateTo(channelId):
case let .messageActionChatMigrateTo(messageActionChatMigrateToData):
let channelId = messageActionChatMigrateToData.channelId
result.append(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)))
case let .messageActionGeoProximityReached(fromId, toId, _):
case let .messageActionGeoProximityReached(messageActionGeoProximityReachedData):
let (fromId, toId) = (messageActionGeoProximityReachedData.fromId, messageActionGeoProximityReachedData.toId)
result.append(fromId.peerId)
result.append(toId.peerId)
case let .messageActionInviteToGroupCall(_, userIds):
case let .messageActionInviteToGroupCall(messageActionInviteToGroupCallData):
let userIds = messageActionInviteToGroupCallData.users
for id in userIds {
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)))
}
case let .messageActionRequestedPeer(_, peers):
case let .messageActionRequestedPeer(messageActionRequestedPeerData):
let peers = messageActionRequestedPeerData.peers
result.append(contentsOf: peers.map(\.peerId))
case let .messageActionGiftCode(_, boostPeer, _, _, _, _, _, _, _):
case let .messageActionGiftCode(messageActionGiftCodeData):
let boostPeer = messageActionGiftCodeData.boostPeer
if let boostPeer = boostPeer {
result.append(boostPeer.peerId)
}
case let .messageActionPrizeStars(_, _, _, boostPeer, _):
case let .messageActionPrizeStars(messageActionPrizeStarsData):
let boostPeer = messageActionPrizeStarsData.boostPeer
result.append(boostPeer.peerId)
case let .messageActionPaymentRefunded(_, peer, _, _, _, _):
case let .messageActionPaymentRefunded(messageActionPaymentRefundedData):
let peer = messageActionPaymentRefundedData.peer
result.append(peer.peerId)
case let .messageActionConferenceCall(_, _, _, otherParticipants):
case let .messageActionConferenceCall(messageActionConferenceCallData):
let otherParticipants = messageActionConferenceCallData.otherParticipants
if let otherParticipants {
result.append(contentsOf: otherParticipants.map(\.peerId))
}
case let .messageActionNewCreatorPending(messageActionNewCreatorPending):
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionNewCreatorPending.newCreatorId)))
case let .messageActionChangeCreator(messageActionChangeCreator):
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionChangeCreator.newCreatorId)))
}
return result
@@ -279,12 +305,14 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
switch message {
case let .message(_, _, id, _, _, chatPeerId, _, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .message(messageData):
let (id, chatPeerId, replyTo) = (messageData.id, messageData.peerId, messageData.replyTo)
if let replyTo = replyTo {
let peerId: PeerId = chatPeerId.peerId
switch replyTo {
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
case let .messageReplyHeader(messageReplyHeaderData):
let (replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId) = (messageReplyHeaderData.replyToMsgId, messageReplyHeaderData.replyToPeerId, messageReplyHeaderData.replyFrom, messageReplyHeaderData.replyMedia, messageReplyHeaderData.replyToTopId, messageReplyHeaderData.quoteText, messageReplyHeaderData.quoteEntities, messageReplyHeaderData.quoteOffset, messageReplyHeaderData.todoItemId)
let _ = replyHeader
let _ = replyMedia
let _ = replyToTopId
@@ -292,7 +320,7 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
let _ = quoteEntities
let _ = quoteOffset
let _ = todoItemId
if let replyToMsgId = replyToMsgId {
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
var replyIds = ReferencedReplyMessageIds()
@@ -305,10 +333,12 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
}
case .messageEmpty:
break
case let .messageService(_, id, _, chatPeerId, _, replyHeader, _, _, _, _):
case let .messageService(messageServiceData):
let (id, chatPeerId, replyHeader) = (messageServiceData.id, messageServiceData.peerId, messageServiceData.replyTo)
if let replyHeader = replyHeader {
switch replyHeader {
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
case let .messageReplyHeader(messageReplyHeaderData):
let (replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId) = (messageReplyHeaderData.replyToMsgId, messageReplyHeaderData.replyToPeerId, messageReplyHeaderData.replyFrom, messageReplyHeaderData.replyMedia, messageReplyHeaderData.replyToTopId, messageReplyHeaderData.quoteText, messageReplyHeaderData.quoteEntities, messageReplyHeaderData.quoteOffset, messageReplyHeaderData.todoItemId)
let _ = replyHeader
let _ = replyMedia
let _ = replyToTopId
@@ -316,7 +346,7 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
let _ = quoteEntities
let _ = quoteOffset
let _ = todoItemId
if let replyToMsgId = replyToMsgId {
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
var replyIds = ReferencedReplyMessageIds()
@@ -340,7 +370,8 @@ struct ParsedMessageWebpageAttributes {
func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerId: PeerId) -> (media: Media?, expirationTimer: Int32?, nonPremium: Bool?, hasSpoiler: Bool?, webpageAttributes: ParsedMessageWebpageAttributes?, videoTimestamp: Int32?) {
if let media = media {
switch media {
case let .messageMediaPhoto(flags, photo, ttlSeconds):
case let .messageMediaPhoto(messageMediaPhotoData):
let (flags, photo, ttlSeconds) = (messageMediaPhotoData.flags, messageMediaPhotoData.photo, messageMediaPhotoData.ttlSeconds)
if let photo = photo {
if let mediaImage = telegramMediaImageFromApiPhoto(photo) {
return (mediaImage, ttlSeconds, nil, (flags & (1 << 3)) != 0, nil, nil)
@@ -348,20 +379,25 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
} else {
return (TelegramMediaExpiredContent(data: .image), nil, nil, nil, nil, nil)
}
case let .messageMediaContact(phoneNumber, firstName, lastName, vcard, userId):
case let .messageMediaContact(messageMediaContactData):
let (phoneNumber, firstName, lastName, vcard, userId) = (messageMediaContactData.phoneNumber, messageMediaContactData.firstName, messageMediaContactData.lastName, messageMediaContactData.vcard, messageMediaContactData.userId)
let contactPeerId: PeerId? = userId == 0 ? nil : PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
let mediaContact = TelegramMediaContact(firstName: firstName, lastName: lastName, phoneNumber: phoneNumber, peerId: contactPeerId, vCardData: vcard.isEmpty ? nil : vcard)
return (mediaContact, nil, nil, nil, nil, nil)
case let .messageMediaGeo(geo):
case let .messageMediaGeo(messageMediaGeoData):
let geo = messageMediaGeoData.geo
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil, heading: nil)
return (mediaMap, nil, nil, nil, nil, nil)
case let .messageMediaVenue(geo, title, address, provider, venueId, venueType):
case let .messageMediaVenue(messageMediaVenueData):
let (geo, title, address, provider, venueId, venueType) = (messageMediaVenueData.geo, messageMediaVenueData.title, messageMediaVenueData.address, messageMediaVenueData.provider, messageMediaVenueData.venueId, messageMediaVenueData.venueType)
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId, venueType: venueType, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil, heading: nil)
return (mediaMap, nil, nil, nil, nil, nil)
case let .messageMediaGeoLive(_, geo, heading, period, proximityNotificationRadius):
case let .messageMediaGeoLive(messageMediaGeoLiveData):
let (geo, heading, period, proximityNotificationRadius) = (messageMediaGeoLiveData.geo, messageMediaGeoLiveData.heading, messageMediaGeoLiveData.period, messageMediaGeoLiveData.proximityNotificationRadius)
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: proximityNotificationRadius, heading: heading)
return (mediaMap, nil, nil, nil, nil, nil)
case let .messageMediaDocument(flags, document, altDocuments, coverPhoto, videoTimestamp, ttlSeconds):
case let .messageMediaDocument(messageMediaDocumentData):
let (flags, document, altDocuments, coverPhoto, videoTimestamp, ttlSeconds) = (messageMediaDocumentData.flags, messageMediaDocumentData.document, messageMediaDocumentData.altDocuments, messageMediaDocumentData.videoCover, messageMediaDocumentData.videoTimestamp, messageMediaDocumentData.ttlSeconds)
if let document = document {
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto) {
return (mediaFile, ttlSeconds, (flags & (1 << 3)) != 0, (flags & (1 << 4)) != 0, nil, videoTimestamp)
@@ -377,7 +413,8 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
}
return (TelegramMediaExpiredContent(data: data), nil, nil, nil, nil, nil)
}
case let .messageMediaWebPage(flags, webpage):
case let .messageMediaWebPage(messageMediaWebPageData):
let (flags, webpage) = (messageMediaWebPageData.flags, messageMediaWebPageData.webpage)
if let mediaWebpage = telegramMediaWebpageFromApiWebpage(webpage) {
var webpageForceLargeMedia: Bool?
if (flags & (1 << 0)) != 0 {
@@ -385,7 +422,7 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
} else if (flags & (1 << 1)) != 0 {
webpageForceLargeMedia = false
}
return (mediaWebpage, nil, nil, nil, ParsedMessageWebpageAttributes(
forceLargeMedia: webpageForceLargeMedia,
isManuallyAdded: (flags & (1 << 3)) != 0,
@@ -396,9 +433,11 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
return (TelegramMediaUnsupported(), nil, nil, nil, nil, nil)
case .messageMediaEmpty:
break
case let .messageMediaGame(game):
case let .messageMediaGame(messageMediaGameData):
let game = messageMediaGameData.game
return (TelegramMediaGame(apiGame: game), nil, nil, nil, nil, nil)
case let .messageMediaInvoice(flags, title, description, photo, receiptMsgId, currency, totalAmount, startParam, apiExtendedMedia):
case let .messageMediaInvoice(messageMediaInvoiceData):
let (flags, title, description, photo, receiptMsgId, currency, totalAmount, startParam, apiExtendedMedia) = (messageMediaInvoiceData.flags, messageMediaInvoiceData.title, messageMediaInvoiceData.description, messageMediaInvoiceData.photo, messageMediaInvoiceData.receiptMsgId, messageMediaInvoiceData.currency, messageMediaInvoiceData.totalAmount, messageMediaInvoiceData.startParam, messageMediaInvoiceData.extendedMedia)
var parsedFlags = TelegramMediaInvoiceFlags()
if (flags & (1 << 3)) != 0 {
parsedFlags.insert(.isTest)
@@ -407,9 +446,11 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
parsedFlags.insert(.shippingAddressRequested)
}
return (TelegramMediaInvoice(title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), receiptMessageId: receiptMsgId.flatMap { MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }, currency: currency, totalAmount: totalAmount, startParam: startParam, extendedMedia: apiExtendedMedia.flatMap({ TelegramExtendedMedia(apiExtendedMedia: $0, peerId: peerId) }), subscriptionPeriod: nil, flags: parsedFlags, version: TelegramMediaInvoice.lastVersion), nil, nil, nil, nil, nil)
case let .messageMediaPoll(poll, results):
case let .messageMediaPoll(messageMediaPollData):
let (poll, results) = (messageMediaPollData.poll, messageMediaPollData.results)
switch poll {
case let .poll(id, flags, question, answers, closePeriod, _):
case let .poll(pollData):
let (id, flags, question, answers, closePeriod, _) = (pollData.id, pollData.flags, pollData.question, pollData.answers, pollData.closePeriod, pollData.closeDate)
let publicity: TelegramMediaPollPublicity
if (flags & (1 << 1)) != 0 {
publicity = .public
@@ -426,16 +467,19 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
let questionText: String
let questionEntities: [MessageTextEntity]
switch question {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
questionText = text
questionEntities = messageTextEntitiesFromApiEntities(entities)
}
return (TelegramMediaPoll(pollId: MediaId(namespace: Namespaces.Media.CloudPoll, id: id), publicity: publicity, kind: kind, text: questionText, textEntities: questionEntities, options: answers.map(TelegramMediaPollOption.init(apiOption:)), correctAnswers: nil, results: TelegramMediaPollResults(apiResults: results), isClosed: (flags & (1 << 0)) != 0, deadlineTimeout: closePeriod), nil, nil, nil, nil, nil)
}
case let .messageMediaToDo(_, todo, completions):
case let .messageMediaToDo(messageMediaToDoData):
let (todo, completions) = (messageMediaToDoData.todo, messageMediaToDoData.completions)
switch todo {
case let .todoList(apiFlags, title, list):
case let .todoList(todoListData):
let (apiFlags, title, list) = (todoListData.flags, todoListData.title, todoListData.list)
var flags: TelegramMediaTodo.Flags = []
if (apiFlags & (1 << 0)) != 0 {
flags.insert(.othersCanAppend)
@@ -443,11 +487,12 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
if (apiFlags & (1 << 1)) != 0 {
flags.insert(.othersCanComplete)
}
let todoText: String
let todoEntities: [MessageTextEntity]
switch title {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
todoText = text
todoEntities = messageTextEntitiesFromApiEntities(entities)
}
@@ -457,21 +502,25 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
}
return (TelegramMediaTodo(flags: flags, text: todoText, textEntities: todoEntities, items: list.map(TelegramMediaTodo.Item.init(apiItem:)), completions: todoCompletions), nil, nil, nil, nil, nil)
}
case let .messageMediaDice(_, value, emoticon, apiGameOutcome):
case let .messageMediaDice(messageMediaDiceData):
let (value, emoticon, apiGameOutcome) = (messageMediaDiceData.value, messageMediaDiceData.emoticon, messageMediaDiceData.gameOutcome)
var gameOutcome: TelegramMediaDice.GameOutcome?
var tonAmount: Int64?
switch apiGameOutcome {
case let .emojiGameOutcome(seed, stakeTonAmount, outcomeTonAmount):
case let .emojiGameOutcome(emojiGameOutcomeData):
let (seed, stakeTonAmount, outcomeTonAmount) = (emojiGameOutcomeData.seed, emojiGameOutcomeData.stakeTonAmount, emojiGameOutcomeData.tonAmount)
gameOutcome = TelegramMediaDice.GameOutcome(seed: seed.makeData(), tonAmount: outcomeTonAmount)
tonAmount = stakeTonAmount
default:
break
}
return (TelegramMediaDice(emoji: emoticon, tonAmount: tonAmount, value: value, gameOutcome: gameOutcome), nil, nil, nil, nil, nil)
case let .messageMediaStory(flags, peerId, id, _):
case let .messageMediaStory(messageMediaStoryData):
let (flags, peerId, id) = (messageMediaStoryData.flags, messageMediaStoryData.peer, messageMediaStoryData.id)
let isMention = (flags & (1 << 1)) != 0
return (TelegramMediaStory(storyId: StoryId(peerId: peerId.peerId, id: id), isMention: isMention), nil, nil, nil, nil, nil)
case let .messageMediaGiveaway(apiFlags, channels, countries, prizeDescription, quantity, months, stars, untilDate):
case let .messageMediaGiveaway(messageMediaGiveawayData):
let (apiFlags, channels, countries, prizeDescription, quantity, months, stars, untilDate) = (messageMediaGiveawayData.flags, messageMediaGiveawayData.channels, messageMediaGiveawayData.countriesIso2, messageMediaGiveawayData.prizeDescription, messageMediaGiveawayData.quantity, messageMediaGiveawayData.months, messageMediaGiveawayData.stars, messageMediaGiveawayData.untilDate)
var flags: TelegramMediaGiveaway.Flags = []
if (apiFlags & (1 << 0)) != 0 {
flags.insert(.onlyNewSubscribers)
@@ -485,7 +534,8 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
return (nil, nil, nil, nil, nil, nil)
}
return (TelegramMediaGiveaway(flags: flags, channelPeerIds: channels.map { PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value($0)) }, countries: countries ?? [], quantity: quantity, prize: prize, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil, nil)
case let .messageMediaGiveawayResults(apiFlags, channelId, additionalPeersCount, launchMsgId, winnersCount, unclaimedCount, winners, months, stars, prizeDescription, untilDate):
case let .messageMediaGiveawayResults(messageMediaGiveawayResultsData):
let (apiFlags, channelId, additionalPeersCount, launchMsgId, winnersCount, unclaimedCount, winners, months, stars, prizeDescription, untilDate) = (messageMediaGiveawayResultsData.flags, messageMediaGiveawayResultsData.channelId, messageMediaGiveawayResultsData.additionalPeersCount, messageMediaGiveawayResultsData.launchMsgId, messageMediaGiveawayResultsData.winnersCount, messageMediaGiveawayResultsData.unclaimedCount, messageMediaGiveawayResultsData.winners, messageMediaGiveawayResultsData.months, messageMediaGiveawayResultsData.stars, messageMediaGiveawayResultsData.prizeDescription, messageMediaGiveawayResultsData.untilDate)
var flags: TelegramMediaGiveawayResults.Flags = []
if (apiFlags & (1 << 0)) != 0 {
flags.insert(.onlyNewSubscribers)
@@ -502,9 +552,11 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
return (nil, nil, nil, nil, nil, nil)
}
return (TelegramMediaGiveawayResults(flags: flags, launchMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: launchMsgId), additionalChannelsCount: additionalPeersCount ?? 0, winnersPeerIds: winners.map { PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) }, winnersCount: winnersCount, unclaimedCount: unclaimedCount, prize: prize, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil, nil)
case let .messageMediaPaidMedia(starsAmount, apiExtendedMedia):
case let .messageMediaPaidMedia(messageMediaPaidMediaData):
let (starsAmount, apiExtendedMedia) = (messageMediaPaidMediaData.starsAmount, messageMediaPaidMediaData.extendedMedia)
return (TelegramMediaPaidContent(amount: starsAmount, extendedMedia: apiExtendedMedia.compactMap({ TelegramExtendedMedia(apiExtendedMedia: $0, peerId: peerId) })), nil, nil, nil, nil, nil)
case let .messageMediaVideoStream(flags, call):
case let .messageMediaVideoStream(messageMediaVideoStreamData):
let (flags, call) = (messageMediaVideoStreamData.flags, messageMediaVideoStreamData.call)
if let call = GroupCallReference(call) {
let kind: TelegramMediaLiveStream.Kind
if (flags & (1 << 0)) != 0 {
@@ -523,7 +575,8 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
func coodinatesFromApiMediaAreaCoordinates(_ coordinates: Api.MediaAreaCoordinates) -> MediaArea.Coordinates {
switch coordinates {
case let .mediaAreaCoordinates(_, x, y, width, height, rotation, radius):
case let .mediaAreaCoordinates(mediaAreaCoordinatesData):
let (_, x, y, width, height, rotation, radius) = (mediaAreaCoordinatesData.flags, mediaAreaCoordinatesData.x, mediaAreaCoordinatesData.y, mediaAreaCoordinatesData.w, mediaAreaCoordinatesData.h, mediaAreaCoordinatesData.rotation, mediaAreaCoordinatesData.radius)
return MediaArea.Coordinates(x: x, y: y, width: width, height: height, rotation: rotation, cornerRadius: radius)
}
}
@@ -532,22 +585,25 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
return nil
case .inputMediaAreaVenue:
return nil
case let .mediaAreaGeoPoint(_, coordinates, geo, address):
case let .mediaAreaGeoPoint(mediaAreaGeoPointData):
let (_, coordinates, geo, address) = (mediaAreaGeoPointData.flags, mediaAreaGeoPointData.coordinates, mediaAreaGeoPointData.geo, mediaAreaGeoPointData.address)
let latitude: Double
let longitude: Double
switch geo {
case let .geoPoint(_, long, lat, _, _):
case let .geoPoint(geoPointData):
let (_, long, lat, _, _) = (geoPointData.flags, geoPointData.long, geoPointData.lat, geoPointData.accessHash, geoPointData.accuracyRadius)
latitude = lat
longitude = long
case .geoPointEmpty:
latitude = 0.0
longitude = 0.0
}
var mappedAddress: MapGeoAddress?
if let address {
switch address {
case let .geoPointAddress(_, countryIso2, state, city, street):
case let .geoPointAddress(geoPointAddressData):
let (_, countryIso2, state, city, street) = (geoPointAddressData.flags, geoPointAddressData.countryIso2, geoPointAddressData.state, geoPointAddressData.city, geoPointAddressData.street)
mappedAddress = MapGeoAddress(
country: countryIso2,
state: state,
@@ -556,7 +612,7 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
)
}
}
return .venue(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), venue: MediaArea.Venue(
latitude: latitude,
longitude: longitude,
@@ -565,11 +621,13 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
queryId: nil,
resultId: nil
))
case let .mediaAreaVenue(coordinates, geo, title, address, provider, venueId, venueType):
case let .mediaAreaVenue(mediaAreaVenueData):
let (coordinates, geo, title, address, provider, venueId, venueType) = (mediaAreaVenueData.coordinates, mediaAreaVenueData.geo, mediaAreaVenueData.title, mediaAreaVenueData.address, mediaAreaVenueData.provider, mediaAreaVenueData.venueId, mediaAreaVenueData.venueType)
let latitude: Double
let longitude: Double
switch geo {
case let .geoPoint(_, long, lat, _, _):
case let .geoPoint(geoPointData):
let (_, long, lat, _, _) = (geoPointData.flags, geoPointData.long, geoPointData.lat, geoPointData.accessHash, geoPointData.accuracyRadius)
latitude = lat
longitude = long
case .geoPointEmpty:
@@ -577,7 +635,8 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
longitude = 0.0
}
return .venue(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), venue: MediaArea.Venue(latitude: latitude, longitude: longitude, venue: MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType), address: nil, queryId: nil, resultId: nil))
case let .mediaAreaSuggestedReaction(flags, coordinates, reaction):
case let .mediaAreaSuggestedReaction(mediaAreaSuggestedReactionData):
let (flags, coordinates, reaction) = (mediaAreaSuggestedReactionData.flags, mediaAreaSuggestedReactionData.coordinates, mediaAreaSuggestedReactionData.reaction)
if let reaction = MessageReaction.Reaction(apiReaction: reaction) {
var parsedFlags = MediaArea.ReactionFlags()
if (flags & (1 << 0)) != 0 {
@@ -590,13 +649,17 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
} else {
return nil
}
case let .mediaAreaUrl(coordinates, url):
case let .mediaAreaUrl(mediaAreaUrlData):
let (coordinates, url) = (mediaAreaUrlData.coordinates, mediaAreaUrlData.url)
return .link(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), url: url)
case let .mediaAreaChannelPost(coordinates, channelId, messageId):
case let .mediaAreaChannelPost(mediaAreaChannelPostData):
let (coordinates, channelId, messageId) = (mediaAreaChannelPostData.coordinates, mediaAreaChannelPostData.channelId, mediaAreaChannelPostData.msgId)
return .channelMessage(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), messageId: EngineMessage.Id(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: messageId))
case let .mediaAreaWeather(coordinates, emoji, temperatureC, color):
case let .mediaAreaWeather(mediaAreaWeatherData):
let (coordinates, emoji, temperatureC, color) = (mediaAreaWeatherData.coordinates, mediaAreaWeatherData.emoji, mediaAreaWeatherData.temperatureC, mediaAreaWeatherData.color)
return .weather(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), emoji: emoji, temperature: temperatureC, color: color)
case let .mediaAreaStarGift(coordinates, slug):
case let .mediaAreaStarGift(mediaAreaStarGiftData):
let (coordinates, slug) = (mediaAreaStarGiftData.coordinates, mediaAreaStarGiftData.slug)
return .starGift(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), slug: slug)
}
}
@@ -609,13 +672,13 @@ func apiMediaAreasFromMediaAreas(_ mediaAreas: [MediaArea], transaction: Transac
if let _ = coordinates.cornerRadius {
flags |= (1 << 0)
}
let inputCoordinates = Api.MediaAreaCoordinates.mediaAreaCoordinates(flags: flags, x: coordinates.x, y: coordinates.y, w: coordinates.width, h: coordinates.height, rotation: coordinates.rotation, radius: coordinates.cornerRadius)
let inputCoordinates = Api.MediaAreaCoordinates.mediaAreaCoordinates(.init(flags: flags, x: coordinates.x, y: coordinates.y, w: coordinates.width, h: coordinates.height, rotation: coordinates.rotation, radius: coordinates.cornerRadius))
switch area {
case let .venue(_, venue):
if let queryId = venue.queryId, let resultId = venue.resultId {
apiMediaAreas.append(.inputMediaAreaVenue(coordinates: inputCoordinates, queryId: queryId, resultId: resultId))
apiMediaAreas.append(.inputMediaAreaVenue(.init(coordinates: inputCoordinates, queryId: queryId, resultId: resultId)))
} else if let venueInfo = venue.venue {
apiMediaAreas.append(.mediaAreaVenue(coordinates: inputCoordinates, geo: .geoPoint(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil), title: venueInfo.title, address: venueInfo.address ?? "", provider: venueInfo.provider ?? "", venueId: venueInfo.id ?? "", venueType: venueInfo.type ?? ""))
apiMediaAreas.append(.mediaAreaVenue(.init(coordinates: inputCoordinates, geo: .geoPoint(.init(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil)), title: venueInfo.title, address: venueInfo.address ?? "", provider: venueInfo.provider ?? "", venueId: venueInfo.id ?? "", venueType: venueInfo.type ?? "")))
} else {
var flags: Int32 = 0
var inputAddress: Api.GeoPointAddress?
@@ -630,10 +693,10 @@ func apiMediaAreasFromMediaAreas(_ mediaAreas: [MediaArea], transaction: Transac
if let _ = address.street {
addressFlags |= (1 << 2)
}
inputAddress = .geoPointAddress(flags: addressFlags, countryIso2: address.country, state: address.state, city: address.city, street: address.street)
inputAddress = .geoPointAddress(.init(flags: addressFlags, countryIso2: address.country, state: address.state, city: address.city, street: address.street))
flags |= (1 << 0)
}
apiMediaAreas.append(.mediaAreaGeoPoint(flags: flags, coordinates: inputCoordinates, geo: .geoPoint(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil), address: inputAddress))
apiMediaAreas.append(.mediaAreaGeoPoint(.init(flags: flags, coordinates: inputCoordinates, geo: .geoPoint(.init(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil)), address: inputAddress)))
}
case let .reaction(_, reaction, flags):
var apiFlags: Int32 = 0
@@ -643,17 +706,17 @@ func apiMediaAreasFromMediaAreas(_ mediaAreas: [MediaArea], transaction: Transac
if flags.contains(.isFlipped) {
apiFlags |= (1 << 1)
}
apiMediaAreas.append(.mediaAreaSuggestedReaction(flags: apiFlags, coordinates: inputCoordinates, reaction: reaction.apiReaction))
apiMediaAreas.append(.mediaAreaSuggestedReaction(.init(flags: apiFlags, coordinates: inputCoordinates, reaction: reaction.apiReaction)))
case let .channelMessage(_, messageId):
if let transaction, let peer = transaction.getPeer(messageId.peerId), let inputChannel = apiInputChannel(peer) {
apiMediaAreas.append(.inputMediaAreaChannelPost(coordinates: inputCoordinates, channel: inputChannel, msgId: messageId.id))
apiMediaAreas.append(.inputMediaAreaChannelPost(.init(coordinates: inputCoordinates, channel: inputChannel, msgId: messageId.id)))
}
case let .link(_, url):
apiMediaAreas.append(.mediaAreaUrl(coordinates: inputCoordinates, url: url))
apiMediaAreas.append(.mediaAreaUrl(.init(coordinates: inputCoordinates, url: url)))
case let .weather(_, emoji, temperature, color):
apiMediaAreas.append(.mediaAreaWeather(coordinates: inputCoordinates, emoji: emoji, temperatureC: temperature, color: color))
apiMediaAreas.append(.mediaAreaWeather(.init(coordinates: inputCoordinates, emoji: emoji, temperatureC: temperature, color: color)))
case let .starGift(_, slug):
apiMediaAreas.append(.mediaAreaStarGift(coordinates: inputCoordinates, slug: slug))
apiMediaAreas.append(.mediaAreaStarGift(.init(coordinates: inputCoordinates, slug: slug)))
}
}
return apiMediaAreas
@@ -666,43 +729,62 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
switch entity {
case .messageEntityUnknown, .inputMessageEntityMentionName:
break
case let .messageEntityMention(offset, length):
case let .messageEntityMention(messageEntityMentionData):
let (offset, length) = (messageEntityMentionData.offset, messageEntityMentionData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Mention))
case let .messageEntityHashtag(offset, length):
case let .messageEntityHashtag(messageEntityHashtagData):
let (offset, length) = (messageEntityHashtagData.offset, messageEntityHashtagData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Hashtag))
case let .messageEntityBotCommand(offset, length):
case let .messageEntityBotCommand(messageEntityBotCommandData):
let (offset, length) = (messageEntityBotCommandData.offset, messageEntityBotCommandData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BotCommand))
case let .messageEntityUrl(offset, length):
case let .messageEntityUrl(messageEntityUrlData):
let (offset, length) = (messageEntityUrlData.offset, messageEntityUrlData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Url))
case let .messageEntityEmail(offset, length):
case let .messageEntityEmail(messageEntityEmailData):
let (offset, length) = (messageEntityEmailData.offset, messageEntityEmailData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Email))
case let .messageEntityBold(offset, length):
case let .messageEntityBold(messageEntityBoldData):
let (offset, length) = (messageEntityBoldData.offset, messageEntityBoldData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Bold))
case let .messageEntityItalic(offset, length):
case let .messageEntityItalic(messageEntityItalicData):
let (offset, length) = (messageEntityItalicData.offset, messageEntityItalicData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Italic))
case let .messageEntityCode(offset, length):
case let .messageEntityCode(messageEntityCodeData):
let (offset, length) = (messageEntityCodeData.offset, messageEntityCodeData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Code))
case let .messageEntityPre(offset, length, language):
case let .messageEntityPre(messageEntityPreData):
let (offset, length, language) = (messageEntityPreData.offset, messageEntityPreData.length, messageEntityPreData.language)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Pre(language: language)))
case let .messageEntityTextUrl(offset, length, url):
case let .messageEntityTextUrl(messageEntityTextUrlData):
let (offset, length, url) = (messageEntityTextUrlData.offset, messageEntityTextUrlData.length, messageEntityTextUrlData.url)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .TextUrl(url: url)))
case let .messageEntityMentionName(offset, length, userId):
case let .messageEntityMentionName(messageEntityMentionNameData):
let (offset, length, userId) = (messageEntityMentionNameData.offset, messageEntityMentionNameData.length, messageEntityMentionNameData.userId)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .TextMention(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)))))
case let .messageEntityPhone(offset, length):
case let .messageEntityPhone(messageEntityPhoneData):
let (offset, length) = (messageEntityPhoneData.offset, messageEntityPhoneData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .PhoneNumber))
case let .messageEntityCashtag(offset, length):
case let .messageEntityCashtag(messageEntityCashtagData):
let (offset, length) = (messageEntityCashtagData.offset, messageEntityCashtagData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Hashtag))
case let .messageEntityUnderline(offset, length):
case let .messageEntityUnderline(messageEntityUnderlineData):
let (offset, length) = (messageEntityUnderlineData.offset, messageEntityUnderlineData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Underline))
case let .messageEntityStrike(offset, length):
case let .messageEntityStrike(messageEntityStrikeData):
let (offset, length) = (messageEntityStrikeData.offset, messageEntityStrikeData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Strikethrough))
case let .messageEntityBlockquote(flags, offset, length):
case let .messageEntityBlockquote(messageEntityBlockquoteData):
let (flags, offset, length) = (messageEntityBlockquoteData.flags, messageEntityBlockquoteData.offset, messageEntityBlockquoteData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BlockQuote(isCollapsed: (flags & (1 << 0)) != 0)))
case let .messageEntityBankCard(offset, length):
case let .messageEntityBankCard(messageEntityBankCardData):
let (offset, length) = (messageEntityBankCardData.offset, messageEntityBankCardData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BankCard))
case let .messageEntitySpoiler(offset, length):
case let .messageEntitySpoiler(messageEntitySpoilerData):
let (offset, length) = (messageEntitySpoilerData.offset, messageEntitySpoilerData.length)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Spoiler))
case let .messageEntityCustomEmoji(offset, length, documentId):
case let .messageEntityCustomEmoji(messageEntityCustomEmojiData):
let (offset, length, documentId) = (messageEntityCustomEmojiData.offset, messageEntityCustomEmojiData.length, messageEntityCustomEmojiData.documentId)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .CustomEmoji(stickerPack: nil, fileId: documentId)))
}
}
@@ -712,13 +794,14 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
extension StoreMessage {
convenience init?(apiMessage: Api.Message, accountPeerId: PeerId, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
switch apiMessage {
case let .message(flags, flags2, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck, reportDeliveryUntilDate, paidMessageStars, suggestedPost, scheduledRepeatPeriod, summaryFromLanguage):
case let .message(messageData):
let (flags, flags2, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck, reportDeliveryUntilDate, paidMessageStars, suggestedPost, scheduledRepeatPeriod, summaryFromLanguage) = (messageData.flags, messageData.flags2, messageData.id, messageData.fromId, messageData.fromBoostsApplied, messageData.peerId, messageData.savedPeerId, messageData.fwdFrom, messageData.viaBotId, messageData.viaBusinessBotId, messageData.replyTo, messageData.date, messageData.message, messageData.media, messageData.replyMarkup, messageData.entities, messageData.views, messageData.forwards, messageData.replies, messageData.editDate, messageData.postAuthor, messageData.groupedId, messageData.reactions, messageData.restrictionReason, messageData.ttlPeriod, messageData.quickReplyShortcutId, messageData.effect, messageData.factcheck, messageData.reportDeliveryUntilDate, messageData.paidMessageStars, messageData.suggestedPost, messageData.scheduleRepeatPeriod, messageData.summaryFromLanguage)
var attributes: [MessageAttribute] = []
if (flags2 & (1 << 4)) != 0 {
attributes.append(PendingProcessingMessageAttribute(approximateCompletionTime: date))
}
let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId
var namespace = namespace
@@ -732,10 +815,12 @@ extension StoreMessage {
case .peerUser:
peerId = chatPeerId.peerId
authorId = resolvedFromId
case let .peerChat(chatId):
case let .peerChat(peerChatData):
let chatId = peerChatData.chatId
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId))
authorId = resolvedFromId
case let .peerChannel(channelId):
case let .peerChannel(peerChannelData):
let channelId = peerChannelData.channelId
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
authorId = resolvedFromId
}
@@ -744,7 +829,8 @@ extension StoreMessage {
if let replyTo = replyTo {
var threadMessageId: MessageId?
switch replyTo {
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
case let .messageReplyHeader(messageReplyHeaderData):
let (innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId) = (messageReplyHeaderData.flags, messageReplyHeaderData.replyToMsgId, messageReplyHeaderData.replyToPeerId, messageReplyHeaderData.replyFrom, messageReplyHeaderData.replyMedia, messageReplyHeaderData.replyToTopId, messageReplyHeaderData.quoteText, messageReplyHeaderData.quoteEntities, messageReplyHeaderData.quoteOffset, messageReplyHeaderData.todoItemId)
let isForumTopic = (innerFlags & (1 << 3)) != 0
var quote: EngineMessageReplyQuote?
@@ -800,35 +886,37 @@ extension StoreMessage {
if let replyHeader = replyHeader {
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
}
case let .messageReplyStoryHeader(peer, storyId):
case let .messageReplyStoryHeader(messageReplyStoryHeaderData):
let (peer, storyId) = (messageReplyStoryHeaderData.peer, messageReplyStoryHeaderData.storyId)
attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: peer.peerId, id: storyId)))
}
}
if threadId == nil && peerId.namespace == Namespaces.Peer.CloudChannel {
threadId = 1
}
var forwardInfo: StoreMessageForwardInfo?
if let fwdFrom = fwdFrom {
switch fwdFrom {
case let .messageFwdHeader(flags, fromId, fromName, date, channelPost, postAuthor, savedFromPeer, savedFromMsgId, savedFromId, savedFromName, savedDate, psaType):
case let .messageFwdHeader(messageFwdHeaderData):
let (flags, fromId, fromName, date, channelPost, postAuthor, savedFromPeer, savedFromMsgId, savedFromId, savedFromName, savedDate, psaType) = (messageFwdHeaderData.flags, messageFwdHeaderData.fromId, messageFwdHeaderData.fromName, messageFwdHeaderData.date, messageFwdHeaderData.channelPost, messageFwdHeaderData.postAuthor, messageFwdHeaderData.savedFromPeer, messageFwdHeaderData.savedFromMsgId, messageFwdHeaderData.savedFromId, messageFwdHeaderData.savedFromName, messageFwdHeaderData.savedDate, messageFwdHeaderData.psaType)
var forwardInfoFlags: MessageForwardInfo.Flags = []
let isImported = (flags & (1 << 7)) != 0
if isImported {
forwardInfoFlags.insert(.isImported)
}
var authorId: PeerId?
var sourceId: PeerId?
var sourceMessageId: MessageId?
if let fromId = fromId {
switch fromId {
case .peerChannel:
let peerId = fromId.peerId
sourceId = peerId
if let channelPost = channelPost {
sourceMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: channelPost)
}
@@ -836,9 +924,9 @@ extension StoreMessage {
authorId = fromId.peerId
}
}
let originalOutgoing = (flags & (1 << 11)) != 0
if let savedFromPeer = savedFromPeer, let savedFromMsgId = savedFromMsgId {
let peerId: PeerId = savedFromPeer.peerId
let messageId: MessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: savedFromMsgId)
@@ -847,7 +935,7 @@ extension StoreMessage {
if savedFromId != nil || savedFromName != nil || savedDate != nil || originalOutgoing {
attributes.append(SourceAuthorInfoMessageAttribute(originalAuthor: savedFromId?.peerId, originalAuthorName: savedFromName, orignalDate: savedDate, originalOutgoing: originalOutgoing))
}
if let authorId = authorId {
forwardInfo = StoreMessageForwardInfo(authorId: authorId, sourceId: sourceId, sourceMessageId: sourceMessageId, date: date, authorSignature: postAuthor, psaType: psaType, flags: forwardInfoFlags)
} else if let sourceId = sourceId {
@@ -1012,7 +1100,8 @@ extension StoreMessage {
if let replies = replies {
let recentRepliersPeerIds: [PeerId]?
switch replies {
case let .messageReplies(_, repliesCount, _, recentRepliers, channelId, maxId, readMaxId):
case let .messageReplies(messageRepliesData):
let (repliesCount, recentRepliers, channelId, maxId, readMaxId) = (messageRepliesData.replies, messageRepliesData.recentRepliers, messageRepliesData.channelId, messageRepliesData.maxId, messageRepliesData.readMaxId)
if let recentRepliers = recentRepliers {
recentRepliersPeerIds = recentRepliers.map { $0.peerId }
} else {
@@ -1035,11 +1124,13 @@ extension StoreMessage {
if let factCheck {
switch factCheck {
case let .factCheck(_, country, text, hash):
case let .factCheck(factCheckData):
let (_, country, text, hash) = (factCheckData.flags, factCheckData.country, factCheckData.text, factCheckData.hash)
let content: FactCheckMessageAttribute.Content
if let text, let country {
switch text {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
content = .Loaded(text: text, entities: messageTextEntitiesFromApiEntities(entities), country: country)
}
} else {
@@ -1109,39 +1200,43 @@ extension StoreMessage {
self.init(id: MessageId(peerId: peerId, namespace: namespace, id: id), customStableId: nil, globallyUniqueId: nil, groupingKey: groupingId, threadId: threadId, timestamp: date, flags: storeFlags, tags: tags, globalTags: globalTags, localTags: [], forwardInfo: forwardInfo, authorId: authorId, text: messageText, attributes: attributes, media: medias)
case .messageEmpty:
return nil
case let .messageService(flags, id, fromId, chatPeerId, savedPeerId, replyTo, date, action, reactions, ttlPeriod):
case let .messageService(messageServiceData):
let (flags, id, fromId, chatPeerId, savedPeerId, replyTo, date, action, reactions, ttlPeriod) = (messageServiceData.flags, messageServiceData.id, messageServiceData.fromId, messageServiceData.peerId, messageServiceData.savedPeerId, messageServiceData.replyTo, messageServiceData.date, messageServiceData.action, messageServiceData.reactions, messageServiceData.ttlPeriod)
let peerId: PeerId = chatPeerId.peerId
let authorId: PeerId? = fromId?.peerId ?? chatPeerId.peerId
var attributes: [MessageAttribute] = []
var threadId: Int64?
if let savedPeerId {
threadId = savedPeerId.peerId.toInt64()
if chatPeerId.peerId.namespace == Namespaces.Peer.CloudChannel, let replyTo {
switch replyTo {
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, _, quoteText, quoteEntities, quoteOffset, todoItemId):
case let .messageReplyHeader(messageReplyHeaderData):
let (innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, quoteText, quoteEntities, quoteOffset, todoItemId) = (messageReplyHeaderData.flags, messageReplyHeaderData.replyToMsgId, messageReplyHeaderData.replyToPeerId, messageReplyHeaderData.replyFrom, messageReplyHeaderData.replyMedia, messageReplyHeaderData.quoteText, messageReplyHeaderData.quoteEntities, messageReplyHeaderData.quoteOffset, messageReplyHeaderData.todoItemId)
var quote: EngineMessageReplyQuote?
let isQuote = (innerFlags & (1 << 9)) != 0
if quoteText != nil || replyMedia != nil {
quote = EngineMessageReplyQuote(text: quoteText ?? "", offset: quoteOffset.flatMap(Int.init), entities: messageTextEntitiesFromApiEntities(quoteEntities ?? []), media: textMediaAndExpirationTimerFromApiMedia(replyMedia, peerId).media)
}
if let replyToMsgId = replyToMsgId {
let replyPeerId = replyToPeerId?.peerId ?? peerId
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: nil, quote: quote, isQuote: isQuote, todoItemId: todoItemId))
} else if let replyHeader = replyHeader {
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
}
case let .messageReplyStoryHeader(peer, storyId):
case let .messageReplyStoryHeader(messageReplyStoryHeaderData):
let (peer, storyId) = (messageReplyStoryHeaderData.peer, messageReplyStoryHeaderData.storyId)
attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: peer.peerId, id: storyId)))
}
}
} else if let replyTo = replyTo {
var threadMessageId: MessageId?
switch replyTo {
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
case let .messageReplyHeader(messageReplyHeaderData):
let (innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId) = (messageReplyHeaderData.flags, messageReplyHeaderData.replyToMsgId, messageReplyHeaderData.replyToPeerId, messageReplyHeaderData.replyFrom, messageReplyHeaderData.replyMedia, messageReplyHeaderData.replyToTopId, messageReplyHeaderData.quoteText, messageReplyHeaderData.quoteEntities, messageReplyHeaderData.quoteOffset, messageReplyHeaderData.todoItemId)
var quote: EngineMessageReplyQuote?
let isQuote = (innerFlags & (1 << 9)) != 0
if quoteText != nil || replyMedia != nil {
@@ -1171,7 +1266,8 @@ extension StoreMessage {
} else if let replyHeader = replyHeader {
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
}
case let .messageReplyStoryHeader(peer, storyId):
case let .messageReplyStoryHeader(messageReplyStoryHeaderData):
let (peer, storyId) = (messageReplyStoryHeaderData.peer, messageReplyStoryHeaderData.storyId)
attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: peer.peerId, id: storyId)))
}
} else {
@@ -6,7 +6,8 @@ import TelegramApi
extension TelegramChatAdminRights {
init?(apiAdminRights: Api.ChatAdminRights) {
switch apiAdminRights {
case let .chatAdminRights(flags):
case let .chatAdminRights(chatAdminRightsData):
let flags = chatAdminRightsData.flags
if flags == 0 {
return nil
}
@@ -18,6 +19,6 @@ extension TelegramChatAdminRights {
var apiAdminRights: Api.ChatAdminRights {
var filteredFlags = self.rights.rawValue
filteredFlags |= 1 << 12
return .chatAdminRights(flags: filteredFlags)
return .chatAdminRights(Api.ChatAdminRights.Cons_chatAdminRights(flags: filteredFlags))
}
}
@@ -5,7 +5,8 @@ import TelegramApi
extension TelegramChatBannedRights {
init(apiBannedRights: Api.ChatBannedRights) {
switch apiBannedRights {
case let .chatBannedRights(flags, untilDate):
case let .chatBannedRights(chatBannedRightsData):
let (flags, untilDate) = (chatBannedRightsData.flags, chatBannedRightsData.untilDate)
var effectiveFlags = TelegramChatBannedRightsFlags(rawValue: flags)
effectiveFlags.remove(.banSendMedia)
effectiveFlags.remove(TelegramChatBannedRightsFlags(rawValue: 1 << 1))
@@ -18,6 +19,6 @@ extension TelegramChatBannedRights {
effectiveFlags.remove(.banSendMedia)
effectiveFlags.remove(TelegramChatBannedRightsFlags(rawValue: 1 << 1))
return .chatBannedRights(flags: effectiveFlags.rawValue, untilDate: self.untilDate)
return .chatBannedRights(.init(flags: effectiveFlags.rawValue, untilDate: self.untilDate))
}
}
@@ -5,17 +5,20 @@ import TelegramApi
extension TelegramExtendedMedia {
init?(apiExtendedMedia: Api.MessageExtendedMedia, peerId: PeerId) {
switch apiExtendedMedia {
case let .messageExtendedMediaPreview(_, width, height, thumb, videoDuration):
case let .messageExtendedMediaPreview(messageExtendedMediaPreviewData):
let (width, height, thumb, videoDuration) = (messageExtendedMediaPreviewData.w, messageExtendedMediaPreviewData.h, messageExtendedMediaPreviewData.thumb, messageExtendedMediaPreviewData.videoDuration)
var dimensions: PixelDimensions?
if let width = width, let height = height {
dimensions = PixelDimensions(width: width, height: height)
}
var immediateThumbnailData: Data?
if let thumb = thumb, case let .photoStrippedSize(_, bytes) = thumb {
if let thumb = thumb, case let .photoStrippedSize(photoStrippedSizeData) = thumb {
let bytes = photoStrippedSizeData.bytes
immediateThumbnailData = bytes.makeData()
}
self = .preview(dimensions: dimensions, immediateThumbnailData: immediateThumbnailData, videoDuration: videoDuration)
case let .messageExtendedMedia(apiMedia):
case let .messageExtendedMedia(messageExtendedMediaData):
let apiMedia = messageExtendedMediaData.media
if let media = textMediaAndExpirationTimerFromApiMedia(apiMedia, peerId).media {
self = .full(media: media)
} else {
@@ -5,33 +5,44 @@ import TelegramApi
func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMediaAction? {
switch action {
case let .messageActionChannelCreate(title):
case let .messageActionChannelCreate(messageActionChannelCreateData):
let title = messageActionChannelCreateData.title
return TelegramMediaAction(action: .groupCreated(title: title))
case let .messageActionChannelMigrateFrom(title, chatId):
case let .messageActionChannelMigrateFrom(messageActionChannelMigrateFromData):
let (title, chatId) = (messageActionChannelMigrateFromData.title, messageActionChannelMigrateFromData.chatId)
return TelegramMediaAction(action: .channelMigratedFromGroup(title: title, groupId: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId))))
case let .messageActionChatAddUser(users):
case let .messageActionChatAddUser(messageActionChatAddUserData):
let users = messageActionChatAddUserData.users
return TelegramMediaAction(action: .addedMembers(peerIds: users.map({ PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) })))
case let .messageActionChatCreate(title, _):
case let .messageActionChatCreate(messageActionChatCreateData):
let title = messageActionChatCreateData.title
return TelegramMediaAction(action: .groupCreated(title: title))
case .messageActionChatDeletePhoto:
return TelegramMediaAction(action: .photoUpdated(image: nil))
case let .messageActionChatDeleteUser(userId):
case let .messageActionChatDeleteUser(messageActionChatDeleteUserData):
let userId = messageActionChatDeleteUserData.userId
return TelegramMediaAction(action: .removedMembers(peerIds: [PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))]))
case let .messageActionChatEditPhoto(photo):
case let .messageActionChatEditPhoto(messageActionChatEditPhotoData):
let photo = messageActionChatEditPhotoData.photo
return TelegramMediaAction(action: .photoUpdated(image: telegramMediaImageFromApiPhoto(photo)))
case let .messageActionChatEditTitle(title):
case let .messageActionChatEditTitle(messageActionChatEditTitleData):
let title = messageActionChatEditTitleData.title
return TelegramMediaAction(action: .titleUpdated(title: title))
case let .messageActionChatJoinedByLink(inviterId):
case let .messageActionChatJoinedByLink(messageActionChatJoinedByLinkData):
let inviterId = messageActionChatJoinedByLinkData.inviterId
return TelegramMediaAction(action: .joinedByLink(inviter: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(inviterId))))
case let .messageActionChatMigrateTo(channelId):
case let .messageActionChatMigrateTo(messageActionChatMigrateToData):
let channelId = messageActionChatMigrateToData.channelId
return TelegramMediaAction(action: .groupMigratedToChannel(channelId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))))
case .messageActionHistoryClear:
return TelegramMediaAction(action: .historyCleared)
case .messageActionPinMessage:
return TelegramMediaAction(action: .pinnedMessageUpdated)
case let .messageActionGameScore(gameId, score):
case let .messageActionGameScore(messageActionGameScoreData):
let (gameId, score) = (messageActionGameScoreData.gameId, messageActionGameScoreData.score)
return TelegramMediaAction(action: .gameScore(gameId: gameId, score: score))
case let .messageActionPhoneCall(flags, callId, reason, duration):
case let .messageActionPhoneCall(messageActionPhoneCallData):
let (flags, callId, reason, duration) = (messageActionPhoneCallData.flags, messageActionPhoneCallData.callId, messageActionPhoneCallData.reason, messageActionPhoneCallData.duration)
var discardReason: PhoneCallDiscardReason?
if let reason = reason {
discardReason = PhoneCallDiscardReason(apiReason: reason)
@@ -40,7 +51,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .phoneCall(callId: callId, discardReason: discardReason, duration: duration, isVideo: isVideo))
case .messageActionEmpty:
return nil
case let .messageActionPaymentSent(flags, currency, totalAmount, invoiceSlug, subscriptionUntilDate):
case let .messageActionPaymentSent(messageActionPaymentSentData):
let (flags, currency, totalAmount, invoiceSlug, subscriptionUntilDate) = (messageActionPaymentSentData.flags, messageActionPaymentSentData.currency, messageActionPaymentSentData.totalAmount, messageActionPaymentSentData.invoiceSlug, messageActionPaymentSentData.subscriptionUntilDate)
let _ = subscriptionUntilDate
let isRecurringInit = (flags & (1 << 2)) != 0
let isRecurringUsed = (flags & (1 << 3)) != 0
@@ -49,14 +61,17 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return nil
case .messageActionScreenshotTaken:
return TelegramMediaAction(action: .historyScreenshot)
case let .messageActionCustomAction(message):
case let .messageActionCustomAction(messageActionCustomActionData):
let message = messageActionCustomActionData.message
return TelegramMediaAction(action: .customText(text: message, entities: [], additionalAttributes: nil))
case let .messageActionBotAllowed(flags, domain, app):
case let .messageActionBotAllowed(messageActionBotAllowedData):
let (flags, domain, app) = (messageActionBotAllowedData.flags, messageActionBotAllowedData.domain, messageActionBotAllowedData.app)
if let domain = domain {
return TelegramMediaAction(action: .botDomainAccessGranted(domain: domain))
} else {
var appName: String?
if case let .botApp(_, _, _, _, appNameValue, _, _, _, _) = app {
if case let .botApp(botAppData) = app {
let appNameValue = botAppData.title
appName = appNameValue
}
var type: BotSendMessageAccessGrantedType?
@@ -70,38 +85,48 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
}
case .messageActionSecureValuesSentMe:
return nil
case let .messageActionSecureValuesSent(types):
case let .messageActionSecureValuesSent(messageActionSecureValuesSentData):
let types = messageActionSecureValuesSentData.types
return TelegramMediaAction(action: .botSentSecureValues(types: types.map(SentSecureValueType.init)))
case .messageActionContactSignUp:
return TelegramMediaAction(action: .peerJoined)
case let .messageActionGeoProximityReached(fromId, toId, distance):
case let .messageActionGeoProximityReached(messageActionGeoProximityReachedData):
let (fromId, toId, distance) = (messageActionGeoProximityReachedData.fromId, messageActionGeoProximityReachedData.toId, messageActionGeoProximityReachedData.distance)
return TelegramMediaAction(action: .geoProximityReached(from: fromId.peerId, to: toId.peerId, distance: distance))
case let .messageActionGroupCall(_, call, duration):
case let .messageActionGroupCall(messageActionGroupCallData):
let (call, duration) = (messageActionGroupCallData.call, messageActionGroupCallData.duration)
switch call {
case let .inputGroupCall(id, accessHash):
case let .inputGroupCall(inputGroupCallData):
let (id, accessHash) = (inputGroupCallData.id, inputGroupCallData.accessHash)
return TelegramMediaAction(action: .groupPhoneCall(callId: id, accessHash: accessHash, scheduleDate: nil, duration: duration))
case .inputGroupCallSlug, .inputGroupCallInviteMessage:
return nil
}
case let .messageActionInviteToGroupCall(call, userIds):
case let .messageActionInviteToGroupCall(messageActionInviteToGroupCallData):
let (call, userIds) = (messageActionInviteToGroupCallData.call, messageActionInviteToGroupCallData.users)
switch call {
case let .inputGroupCall(id, accessHash):
case let .inputGroupCall(inputGroupCallData):
let (id, accessHash) = (inputGroupCallData.id, inputGroupCallData.accessHash)
return TelegramMediaAction(action: .inviteToGroupPhoneCall(callId: id, accessHash: accessHash, peerIds: userIds.map { userId in
PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
}))
case .inputGroupCallSlug, .inputGroupCallInviteMessage:
return nil
}
case let .messageActionSetMessagesTTL(_, period, autoSettingFrom):
case let .messageActionSetMessagesTTL(messageActionSetMessagesTTLData):
let (period, autoSettingFrom) = (messageActionSetMessagesTTLData.period, messageActionSetMessagesTTLData.autoSettingFrom)
return TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(period: period, autoSettingSource: autoSettingFrom.flatMap { PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) }))
case let .messageActionGroupCallScheduled(call, scheduleDate):
case let .messageActionGroupCallScheduled(messageActionGroupCallScheduledData):
let (call, scheduleDate) = (messageActionGroupCallScheduledData.call, messageActionGroupCallScheduledData.scheduleDate)
switch call {
case let .inputGroupCall(id, accessHash):
case let .inputGroupCall(inputGroupCallData):
let (id, accessHash) = (inputGroupCallData.id, inputGroupCallData.accessHash)
return TelegramMediaAction(action: .groupPhoneCall(callId: id, accessHash: accessHash, scheduleDate: scheduleDate, duration: nil))
case .inputGroupCallSlug, .inputGroupCallInviteMessage:
return nil
}
case let .messageActionSetChatTheme(chatTheme):
case let .messageActionSetChatTheme(messageActionSetChatThemeData):
let chatTheme = messageActionSetChatThemeData.theme
if let chatTheme = ChatTheme(apiChatTheme: chatTheme) {
return TelegramMediaAction(action: .setChatTheme(chatTheme: chatTheme))
} else {
@@ -109,13 +134,19 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
}
case .messageActionChatJoinedByRequest:
return TelegramMediaAction(action: .joinedByRequest)
case let .messageActionWebViewDataSentMe(text, _), let .messageActionWebViewDataSent(text):
case let .messageActionWebViewDataSentMe(messageActionWebViewDataSentMeData):
let text = messageActionWebViewDataSentMeData.text
return TelegramMediaAction(action: .webViewData(text))
case let .messageActionGiftPremium(_, currency, amount, days, cryptoCurrency, cryptoAmount, message):
case let .messageActionWebViewDataSent(messageActionWebViewDataSentData):
let text = messageActionWebViewDataSentData.text
return TelegramMediaAction(action: .webViewData(text))
case let .messageActionGiftPremium(messageActionGiftPremiumData):
let (currency, amount, days, cryptoCurrency, cryptoAmount, message) = (messageActionGiftPremiumData.currency, messageActionGiftPremiumData.amount, messageActionGiftPremiumData.days, messageActionGiftPremiumData.cryptoCurrency, messageActionGiftPremiumData.cryptoAmount, messageActionGiftPremiumData.message)
let text: String?
let entities: [MessageTextEntity]?
switch message {
case let .textWithEntities(textValue, entitiesValue):
case let .textWithEntities(textWithEntitiesData):
let (textValue, entitiesValue) = (textWithEntitiesData.text, textWithEntitiesData.entities)
text = textValue
entities = messageTextEntitiesFromApiEntities(entitiesValue)
default:
@@ -123,11 +154,14 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
entities = nil
}
return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, days: days, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, text: text, entities: entities))
case let .messageActionGiftStars(_, currency, amount, stars, cryptoCurrency, cryptoAmount, transactionId):
case let .messageActionGiftStars(messageActionGiftStarsData):
let (currency, amount, stars, cryptoCurrency, cryptoAmount, transactionId) = (messageActionGiftStarsData.currency, messageActionGiftStarsData.amount, messageActionGiftStarsData.stars, messageActionGiftStarsData.cryptoCurrency, messageActionGiftStarsData.cryptoAmount, messageActionGiftStarsData.transactionId)
return TelegramMediaAction(action: .giftStars(currency: currency, amount: amount, count: stars, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, transactionId: transactionId))
case let .messageActionTopicCreate(_, title, iconColor, iconEmojiId):
case let .messageActionTopicCreate(messageActionTopicCreateData):
let (title, iconColor, iconEmojiId) = (messageActionTopicCreateData.title, messageActionTopicCreateData.iconColor, messageActionTopicCreateData.iconEmojiId)
return TelegramMediaAction(action: .topicCreated(title: title, iconColor: iconColor, iconFileId: iconEmojiId))
case let .messageActionTopicEdit(flags, title, iconEmojiId, closed, hidden):
case let .messageActionTopicEdit(messageActionTopicEditData):
let (flags, title, iconEmojiId, closed, hidden) = (messageActionTopicEditData.flags, messageActionTopicEditData.title, messageActionTopicEditData.iconEmojiId, messageActionTopicEditData.closed, messageActionTopicEditData.hidden)
var components: [TelegramMediaActionType.ForumTopicEditComponent] = []
if let title = title {
components.append(.title(title))
@@ -142,50 +176,63 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
components.append(.isHidden(hidden == .boolTrue))
}
return TelegramMediaAction(action: .topicEdited(components: components))
case let .messageActionSuggestProfilePhoto(photo):
case let .messageActionSuggestProfilePhoto(messageActionSuggestProfilePhotoData):
let photo = messageActionSuggestProfilePhotoData.photo
return TelegramMediaAction(action: .suggestedProfilePhoto(image: telegramMediaImageFromApiPhoto(photo)))
case let .messageActionRequestedPeer(buttonId, peers):
case let .messageActionRequestedPeer(messageActionRequestedPeerData):
let (buttonId, peers) = (messageActionRequestedPeerData.buttonId, messageActionRequestedPeerData.peers)
return TelegramMediaAction(action: .requestedPeer(buttonId: buttonId, peerIds: peers.map { $0.peerId }))
case let .messageActionRequestedPeerSentMe(buttonId, _):
case let .messageActionRequestedPeerSentMe(messageActionRequestedPeerSentMeData):
let buttonId = messageActionRequestedPeerSentMeData.buttonId
return TelegramMediaAction(action: .requestedPeer(buttonId: buttonId, peerIds: []))
case let .messageActionSetChatWallPaper(flags, wallpaper):
case let .messageActionSetChatWallPaper(messageActionSetChatWallPaperData):
let (flags, wallpaper) = (messageActionSetChatWallPaperData.flags, messageActionSetChatWallPaperData.wallpaper)
if (flags & (1 << 0)) != 0 {
return TelegramMediaAction(action: .setSameChatWallpaper(wallpaper: TelegramWallpaper(apiWallpaper: wallpaper)))
} else {
return TelegramMediaAction(action: .setChatWallpaper(wallpaper: TelegramWallpaper(apiWallpaper: wallpaper), forBoth: (flags & (1 << 1)) != 0))
}
case let .messageActionGiftCode(flags, boostPeer, months, slug, currency, amount, cryptoCurrency, cryptoAmount, message):
case let .messageActionGiftCode(messageActionGiftCodeData):
let (flags, boostPeer, days, slug, currency, amount, cryptoCurrency, cryptoAmount, message) = (messageActionGiftCodeData.flags, messageActionGiftCodeData.boostPeer, messageActionGiftCodeData.days, messageActionGiftCodeData.slug, messageActionGiftCodeData.currency, messageActionGiftCodeData.amount, messageActionGiftCodeData.cryptoCurrency, messageActionGiftCodeData.cryptoAmount, messageActionGiftCodeData.message)
let text: String?
let entities: [MessageTextEntity]?
switch message {
case let .textWithEntities(textValue, entitiesValue):
case let .textWithEntities(textWithEntitiesData):
let (textValue, entitiesValue) = (textWithEntitiesData.text, textWithEntitiesData.entities)
text = textValue
entities = messageTextEntitiesFromApiEntities(entitiesValue)
default:
text = nil
entities = nil
}
return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 5)) != 0, boostPeerId: boostPeer?.peerId, months: months, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, text: text, entities: entities))
case let .messageActionGiveawayLaunch(_, stars):
return TelegramMediaAction(action: .giveawayLaunched(stars: stars))
case let .messageActionGiveawayResults(flags, winners, unclaimed):
return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 5)) != 0, boostPeerId: boostPeer?.peerId, months: days, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, text: text, entities: entities))
case let .messageActionGiveawayLaunch(messageActionGiveawayLaunchData):
return TelegramMediaAction(action: .giveawayLaunched(stars: messageActionGiveawayLaunchData.stars))
case let .messageActionGiveawayResults(messageActionGiveawayResultsData):
let (flags, winners, unclaimed) = (messageActionGiveawayResultsData.flags, messageActionGiveawayResultsData.winnersCount, messageActionGiveawayResultsData.unclaimedCount)
return TelegramMediaAction(action: .giveawayResults(winners: winners, unclaimed: unclaimed, stars: (flags & (1 << 0)) != 0))
case let .messageActionBoostApply(boosts):
case let .messageActionBoostApply(messageActionBoostApplyData):
let boosts = messageActionBoostApplyData.boosts
return TelegramMediaAction(action: .boostsApplied(boosts: boosts))
case let .messageActionPaymentRefunded(_, peer, currency, totalAmount, payload, charge):
case let .messageActionPaymentRefunded(messageActionPaymentRefundedData):
let (peer, currency, totalAmount, payload, charge) = (messageActionPaymentRefundedData.peer, messageActionPaymentRefundedData.currency, messageActionPaymentRefundedData.totalAmount, messageActionPaymentRefundedData.payload, messageActionPaymentRefundedData.charge)
let transactionId: String
switch charge {
case let .paymentCharge(id, _):
case let .paymentCharge(paymentChargeData):
let id = paymentChargeData.id
transactionId = id
}
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
case let .messageActionPrizeStars(messageActionPrizeStarsData):
let (flags, stars, transactionId, boostPeer, giveawayMsgId) = (messageActionPrizeStarsData.flags, messageActionPrizeStarsData.stars, messageActionPrizeStarsData.transactionId, messageActionPrizeStarsData.boostPeer, messageActionPrizeStarsData.giveawayMsgId)
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, giftMessageId, toId, number):
case let .messageActionStarGift(messageActionStarGiftData):
let (flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, giftMessageId, toId, number) = (messageActionStarGiftData.flags, messageActionStarGiftData.gift, messageActionStarGiftData.message, messageActionStarGiftData.convertStars, messageActionStarGiftData.upgradeMsgId, messageActionStarGiftData.upgradeStars, messageActionStarGiftData.fromId, messageActionStarGiftData.peer, messageActionStarGiftData.savedId, messageActionStarGiftData.prepaidUpgradeHash, messageActionStarGiftData.giftMsgId, messageActionStarGiftData.toId, messageActionStarGiftData.giftNum)
let text: String?
let entities: [MessageTextEntity]?
switch message {
case let .textWithEntities(textValue, entitiesValue):
case let .textWithEntities(textWithEntitiesData):
let (textValue, entitiesValue) = (textWithEntitiesData.text, textWithEntitiesData.entities)
text = textValue
entities = messageTextEntitiesFromApiEntities(entitiesValue)
default:
@@ -196,21 +243,25 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return nil
}
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, isPrepaidUpgrade: (flags & (1 << 13)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, prepaidUpgradeHash: prepaidUpgradeHash, giftMessageId: giftMessageId, upgradeSeparate: (flags & (1 << 16)) != 0, isAuctionAcquired: (flags & (1 << 17)) != 0, toPeerId: toId?.peerId, number: number))
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars):
case let .messageActionStarGiftUnique(messageActionStarGiftUniqueData):
let (flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars, canCraftAt) = (messageActionStarGiftUniqueData.flags, messageActionStarGiftUniqueData.gift, messageActionStarGiftUniqueData.canExportAt, messageActionStarGiftUniqueData.transferStars, messageActionStarGiftUniqueData.fromId, messageActionStarGiftUniqueData.peer, messageActionStarGiftUniqueData.savedId, messageActionStarGiftUniqueData.resaleAmount, messageActionStarGiftUniqueData.canTransferAt, messageActionStarGiftUniqueData.canResellAt, messageActionStarGiftUniqueData.dropOriginalDetailsStars, messageActionStarGiftUniqueData.canCraftAt)
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0, fromOffer: (flags & (1 << 14)) != 0))
case let .messageActionPaidMessagesRefunded(count, stars):
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0, fromOffer: (flags & (1 << 14)) != 0, canCraftAt: canCraftAt, isCrafted: (flags & (1 << 16)) != 0))
case let .messageActionPaidMessagesRefunded(messageActionPaidMessagesRefundedData):
let (count, stars) = (messageActionPaidMessagesRefundedData.count, messageActionPaidMessagesRefundedData.stars)
return TelegramMediaAction(action: .paidMessagesRefunded(count: count, stars: stars))
case let .messageActionPaidMessagesPrice(flags, stars):
case let .messageActionPaidMessagesPrice(messageActionPaidMessagesPriceData):
let (flags, stars) = (messageActionPaidMessagesPriceData.flags, messageActionPaidMessagesPriceData.stars)
let broadcastMessagesAllowed = (flags & (1 << 0)) != 0
return TelegramMediaAction(action: .paidMessagesPriceEdited(stars: stars, broadcastMessagesAllowed: broadcastMessagesAllowed))
case let .messageActionConferenceCall(flags, callId, duration, otherParticipants):
case let .messageActionConferenceCall(messageActionConferenceCallData):
let (flags, callId, duration, otherParticipants) = (messageActionConferenceCallData.flags, messageActionConferenceCallData.callId, messageActionConferenceCallData.duration, messageActionConferenceCallData.otherParticipants)
let isMissed = (flags & (1 << 0)) != 0
let isActive = (flags & (1 << 1)) != 0
let isVideo = (flags & (1 << 4)) != 0
var mappedFlags = TelegramMediaActionType.ConferenceCall.Flags()
if isMissed {
mappedFlags.insert(.isMissed)
@@ -221,18 +272,21 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
if isVideo {
mappedFlags.insert(.isVideo)
}
return TelegramMediaAction(action: .conferenceCall(TelegramMediaActionType.ConferenceCall(
callId: callId,
duration: duration,
flags: mappedFlags,
otherParticipants: otherParticipants.flatMap({ return $0.map(\.peerId) }) ?? []
)))
case let .messageActionTodoCompletions(completed, incompleted):
case let .messageActionTodoCompletions(messageActionTodoCompletionsData):
let (completed, incompleted) = (messageActionTodoCompletionsData.completed, messageActionTodoCompletionsData.incompleted)
return TelegramMediaAction(action: .todoCompletions(completed: completed, incompleted: incompleted))
case let .messageActionTodoAppendTasks(list):
case let .messageActionTodoAppendTasks(messageActionTodoAppendTasksData):
let list = messageActionTodoAppendTasksData.list
return TelegramMediaAction(action: .todoAppendTasks(list.map { TelegramMediaTodo.Item(apiItem: $0) }))
case let .messageActionSuggestedPostApproval(flags, rejectComment, scheduleDate, starsAmount):
case let .messageActionSuggestedPostApproval(messageActionSuggestedPostApprovalData):
let (flags, rejectComment, scheduleDate, starsAmount) = (messageActionSuggestedPostApprovalData.flags, messageActionSuggestedPostApprovalData.rejectComment, messageActionSuggestedPostApprovalData.scheduleDate, messageActionSuggestedPostApprovalData.price)
let status: TelegramMediaActionType.SuggestedPostApprovalStatus
if (flags & (1 << 0)) != 0 {
let reason: TelegramMediaActionType.SuggestedPostApprovalStatus.RejectionReason
@@ -241,9 +295,11 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
switch starsAmount {
case .none:
balanceNeeded = CurrencyAmount(amount: .zero, currency: .stars)
case let .starsAmount(amount, nanos):
case let .starsAmount(starsAmountData):
let (amount, nanos) = (starsAmountData.amount, starsAmountData.nanos)
balanceNeeded = CurrencyAmount(amount: StarsAmount(value: amount, nanos: nanos), currency: .stars)
case let .starsTonAmount(amount):
case let .starsTonAmount(starsTonAmountData):
let amount = starsTonAmountData.amount
balanceNeeded = CurrencyAmount(amount: StarsAmount(value: amount, nanos: 0), currency: .ton)
}
reason = .lowBalance(balanceNeeded: balanceNeeded)
@@ -256,9 +312,11 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
switch starsAmount {
case .none:
amountValue = CurrencyAmount(amount: .zero, currency: .stars)
case let .starsAmount(amount, nanos):
case let .starsAmount(starsAmountData):
let (amount, nanos) = (starsAmountData.amount, starsAmountData.nanos)
amountValue = CurrencyAmount(amount: StarsAmount(value: amount, nanos: nanos), currency: .stars)
case let .starsTonAmount(amount):
case let .starsTonAmount(starsTonAmountData):
let amount = starsTonAmountData.amount
amountValue = CurrencyAmount(amount: StarsAmount(value: amount, nanos: 0), currency: .ton)
}
status = .rejected(reason: .lowBalance(balanceNeeded: amountValue), comment: nil)
@@ -266,25 +324,41 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
status = .approved(timestamp: scheduleDate, amount: starsAmount.flatMap(CurrencyAmount.init(apiAmount:)))
}
return TelegramMediaAction(action: .suggestedPostApprovalStatus(status: status))
case let .messageActionGiftTon(_, currency, amount, cryptoCurrency, cryptoAmount, transactionId):
case let .messageActionGiftTon(messageActionGiftTonData):
let (currency, amount, cryptoCurrency, cryptoAmount, transactionId) = (messageActionGiftTonData.currency, messageActionGiftTonData.amount, messageActionGiftTonData.cryptoCurrency, messageActionGiftTonData.cryptoAmount, messageActionGiftTonData.transactionId)
return TelegramMediaAction(action: .giftTon(currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, transactionId: transactionId))
case let .messageActionSuggestedPostSuccess(price):
case let .messageActionSuggestedPostSuccess(messageActionSuggestedPostSuccessData):
let price = messageActionSuggestedPostSuccessData.price
return TelegramMediaAction(action: .suggestedPostSuccess(amount: CurrencyAmount(apiAmount: price)))
case let .messageActionSuggestedPostRefund(flags):
case let .messageActionSuggestedPostRefund(messageActionSuggestedPostRefundData):
let flags = messageActionSuggestedPostRefundData.flags
return TelegramMediaAction(action: .suggestedPostRefund(TelegramMediaActionType.SuggestedPostRefund(isUserInitiated: (flags & (1 << 0)) != 0)))
case let .messageActionSuggestBirthday(birthday):
case let .messageActionSuggestBirthday(messageActionSuggestBirthdayData):
let birthday = messageActionSuggestBirthdayData.birthday
return TelegramMediaAction(action: .suggestedBirthday(TelegramBirthday(apiBirthday: birthday)))
case let .messageActionStarGiftPurchaseOffer(flags, apiGift, price, expiresAt):
case let .messageActionStarGiftPurchaseOffer(messageActionStarGiftPurchaseOfferData):
let (flags, apiGift, price, expiresAt) = (messageActionStarGiftPurchaseOfferData.flags, messageActionStarGiftPurchaseOfferData.gift, messageActionStarGiftPurchaseOfferData.price, messageActionStarGiftPurchaseOfferData.expiresAt)
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOffer(gift: gift, amount: CurrencyAmount(apiAmount: price), expireDate: expiresAt, isAccepted: (flags & (1 << 0)) != 0, isDeclined: (flags & (1 << 1)) != 0))
case let .messageActionStarGiftPurchaseOfferDeclined(flags, apiGift, price):
case let .messageActionStarGiftPurchaseOfferDeclined(messageActionStarGiftPurchaseOfferDeclinedData):
let (flags, apiGift, price) = (messageActionStarGiftPurchaseOfferDeclinedData.flags, messageActionStarGiftPurchaseOfferDeclinedData.gift, messageActionStarGiftPurchaseOfferDeclinedData.price)
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOfferDeclined(gift: gift, amount: CurrencyAmount(apiAmount: price), hasExpired: (flags & (1 << 0)) != 0))
case let .messageActionNewCreatorPending(messageActionNewCreatorPending):
return TelegramMediaAction(action: .groupCreatorChange(TelegramMediaActionType.GroupCreatorChange(
kind: .pending,
targetPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionNewCreatorPending.newCreatorId))
)))
case let .messageActionChangeCreator(messageActionChangeCreator):
return TelegramMediaAction(action: .groupCreatorChange(TelegramMediaActionType.GroupCreatorChange(
kind: .applied,
targetPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionChangeCreator.newCreatorId))
)))
}
}
@@ -69,13 +69,16 @@ extension StickerPackReference {
switch apiInputSet {
case .inputStickerSetEmpty:
return nil
case let .inputStickerSetID(id, accessHash):
case let .inputStickerSetID(inputStickerSetIDData):
let (id, accessHash) = (inputStickerSetIDData.id, inputStickerSetIDData.accessHash)
self = .id(id: id, accessHash: accessHash)
case let .inputStickerSetShortName(shortName):
case let .inputStickerSetShortName(inputStickerSetShortNameData):
let shortName = inputStickerSetShortNameData.shortName
self = .name(shortName)
case .inputStickerSetAnimatedEmoji:
self = .animatedEmoji
case let .inputStickerSetDice(emoticon):
case let .inputStickerSetDice(inputStickerSetDiceData):
let emoticon = inputStickerSetDiceData.emoticon
self = .dice(emoticon)
case .inputStickerSetAnimatedEmojiAnimations:
self = .animatedEmojiAnimations
@@ -98,7 +101,8 @@ extension StickerPackReference {
extension StickerMaskCoords {
init(apiMaskCoords: Api.MaskCoords) {
switch apiMaskCoords {
case let .maskCoords(n, x, y, zoom):
case let .maskCoords(maskCoordsData):
let (n, x, y, zoom) = (maskCoordsData.n, maskCoordsData.x, maskCoordsData.y, maskCoordsData.zoom)
self.init(n: n, x: x, y: y, zoom: zoom)
}
}
@@ -108,17 +112,21 @@ func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAtt
var result: [TelegramMediaFileAttribute] = []
for attribute in attributes {
switch attribute {
case let .documentAttributeFilename(fileName):
case let .documentAttributeFilename(documentAttributeFilenameData):
let fileName = documentAttributeFilenameData.fileName
result.append(.FileName(fileName: fileName))
case let .documentAttributeSticker(_, alt, stickerSet, maskCoords):
case let .documentAttributeSticker(documentAttributeStickerData):
let (alt, stickerSet, maskCoords) = (documentAttributeStickerData.alt, documentAttributeStickerData.stickerset, documentAttributeStickerData.maskCoords)
result.append(.Sticker(displayText: alt, packReference: StickerPackReference(apiInputSet: stickerSet), maskData: maskCoords.flatMap(StickerMaskCoords.init)))
case .documentAttributeHasStickers:
result.append(.HasLinkedStickers)
case let .documentAttributeImageSize(w, h):
case let .documentAttributeImageSize(documentAttributeImageSizeData):
let (w, h) = (documentAttributeImageSizeData.w, documentAttributeImageSizeData.h)
result.append(.ImageSize(size: PixelDimensions(width: w, height: h)))
case .documentAttributeAnimated:
result.append(.Animated)
case let .documentAttributeVideo(flags, duration, w, h, preloadSize, videoStart, videoCodec):
case let .documentAttributeVideo(documentAttributeVideoData):
let (flags, duration, w, h, preloadSize, videoStart, videoCodec) = (documentAttributeVideoData.flags, documentAttributeVideoData.duration, documentAttributeVideoData.w, documentAttributeVideoData.h, documentAttributeVideoData.preloadPrefixSize, documentAttributeVideoData.videoStartTs, documentAttributeVideoData.videoCodec)
var videoFlags = TelegramMediaVideoFlags()
if (flags & (1 << 0)) != 0 {
videoFlags.insert(.instantRoundVideo)
@@ -130,11 +138,13 @@ func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAtt
videoFlags.insert(.isSilent)
}
result.append(.Video(duration: Double(duration), size: PixelDimensions(width: w, height: h), flags: videoFlags, preloadSize: preloadSize, coverTime: videoStart, videoCodec: videoCodec))
case let .documentAttributeAudio(flags, duration, title, performer, waveform):
case let .documentAttributeAudio(documentAttributeAudioData):
let (flags, duration, title, performer, waveform) = (documentAttributeAudioData.flags, documentAttributeAudioData.duration, documentAttributeAudioData.title, documentAttributeAudioData.performer, documentAttributeAudioData.waveform)
let isVoice = (flags & (1 << 10)) != 0
let waveformBuffer: Data? = waveform?.makeData()
result.append(.Audio(isVoice: isVoice, duration: Int(duration), title: title, performer: performer, waveform: waveformBuffer))
case let .documentAttributeCustomEmoji(flags, alt, stickerSet):
case let .documentAttributeCustomEmoji(documentAttributeCustomEmojiData):
let (flags, alt, stickerSet) = (documentAttributeCustomEmojiData.flags, documentAttributeCustomEmojiData.alt, documentAttributeCustomEmojiData.stickerset)
let isFree = (flags & (1 << 0)) != 0
let isSingleColor = (flags & (1 << 1)) != 0
result.append(.CustomEmoji(isPremium: !isFree, isSingleColor: isSingleColor, alt: alt, packReference: StickerPackReference(apiInputSet: stickerSet)))
@@ -157,18 +167,23 @@ func telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: Int32,
var representations: [TelegramMediaImageRepresentation] = []
for size in sizes {
switch size {
case let .photoCachedSize(type, w, h, _):
case let .photoCachedSize(photoCachedSizeData):
let (type, w, h, _) = (photoCachedSizeData.type, photoCachedSizeData.w, photoCachedSizeData.h, photoCachedSizeData.bytes)
let resource = CloudDocumentSizeMediaResource(datacenterId: datacenterId, documentId: documentId, accessHash: accessHash, sizeSpec: type, fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
case let .photoSize(type, w, h, _):
case let .photoSize(photoSizeData):
let (type, w, h, _) = (photoSizeData.type, photoSizeData.w, photoSizeData.h, photoSizeData.size)
let resource = CloudDocumentSizeMediaResource(datacenterId: datacenterId, documentId: documentId, accessHash: accessHash, sizeSpec: type, fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
case let .photoSizeProgressive(type, w, h, sizes):
case let .photoSizeProgressive(photoSizeProgressiveData):
let (type, w, h, sizes) = (photoSizeProgressiveData.type, photoSizeProgressiveData.w, photoSizeProgressiveData.h, photoSizeProgressiveData.sizes)
let resource = CloudDocumentSizeMediaResource(datacenterId: datacenterId, documentId: documentId, accessHash: accessHash, sizeSpec: type, fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes, immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
case let .photoPathSize(_, data):
case let .photoPathSize(photoPathSizeData):
let (_, data) = (photoPathSizeData.type, photoPathSizeData.bytes)
immediateThumbnailData = data.makeData()
case let .photoStrippedSize(_, data):
case let .photoStrippedSize(photoStrippedSizeData):
let (_, data) = (photoStrippedSizeData.type, photoStrippedSizeData.bytes)
immediateThumbnailData = data.makeData()
case .photoSizeEmpty:
break
@@ -179,7 +194,8 @@ func telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: Int32,
func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [Api.Document]?, videoCover: Api.Photo? = nil) -> TelegramMediaFile? {
switch document {
case let .document(_, id, accessHash, fileReference, _, mimeType, size, thumbs, videoThumbs, dcId, attributes):
case let .document(documentData):
let (id, accessHash, fileReference, mimeType, size, thumbs, videoThumbs, dcId, attributes) = (documentData.id, documentData.accessHash, documentData.fileReference, documentData.mimeType, documentData.size, documentData.thumbs, documentData.videoThumbs, documentData.dcId, documentData.attributes)
var parsedAttributes = telegramMediaFileAttributesFromApiAttributes(attributes)
var isSticker = false
var isAnimated = false
@@ -203,7 +219,8 @@ func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [A
if let videoThumbs = videoThumbs {
for thumb in videoThumbs {
switch thumb {
case let .videoSize(_, type, w, h, _, _):
case let .videoSize(videoSizeData):
let (_, type, w, h, _, _) = (videoSizeData.flags, videoSizeData.type, videoSizeData.w, videoSizeData.h, videoSizeData.size, videoSizeData.videoStartTs)
let resource: TelegramMediaResource
resource = CloudDocumentSizeMediaResource(datacenterId: dcId, documentId: id, accessHash: accessHash, sizeSpec: type, fileReference: fileReference.makeData())
@@ -6,7 +6,8 @@ import TelegramApi
extension TelegramMediaGame {
convenience init(apiGame: Api.Game) {
switch apiGame {
case let .game(_, id, accessHash, shortName, title, description, photo, document):
case let .game(gameData):
let (id, accessHash, shortName, title, description, photo, document) = (gameData.id, gameData.accessHash, gameData.shortName, gameData.title, gameData.description, gameData.photo, gameData.document)
var file: TelegramMediaFile?
if let document = document {
file = telegramMediaFileFromApiDocument(document, altDocuments: [])
@@ -8,18 +8,22 @@ func telegramMediaImageRepresentationsFromApiSizes(datacenterId: Int32, photoId:
var representations: [TelegramMediaImageRepresentation] = []
for size in sizes {
switch size {
case let .photoCachedSize(type, w, h, _):
case let .photoCachedSize(photoCachedSizeData):
let (type, w, h) = (photoCachedSizeData.type, photoCachedSizeData.w, photoCachedSizeData.h)
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: nil, fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
case let .photoSize(type, w, h, size):
case let .photoSize(photoSizeData):
let (type, w, h, size) = (photoSizeData.type, photoSizeData.w, photoSizeData.h, photoSizeData.size)
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
case let .photoSizeProgressive(type, w, h, sizes):
case let .photoSizeProgressive(photoSizeProgressiveData):
let (type, w, h, sizes) = (photoSizeProgressiveData.type, photoSizeProgressiveData.w, photoSizeProgressiveData.h, photoSizeProgressiveData.sizes)
if !sizes.isEmpty {
let resource = CloudPhotoSizeMediaResource(datacenterId: datacenterId, photoId: photoId, accessHash: accessHash, sizeSpec: type, size: Int64(sizes[sizes.count - 1]), fileReference: fileReference)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes, immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
}
case let .photoStrippedSize(_, data):
case let .photoStrippedSize(photoStrippedSizeData):
let data = photoStrippedSizeData.bytes
immediateThumbnailData = data.makeData()
case .photoPathSize:
break
@@ -32,7 +36,8 @@ func telegramMediaImageRepresentationsFromApiSizes(datacenterId: Int32, photoId:
func telegramMediaImageFromApiPhoto(_ photo: Api.Photo) -> TelegramMediaImage? {
switch photo {
case let .photo(flags, id, accessHash, fileReference, _, sizes, videoSizes, dcId):
case let .photo(photoData):
let (flags, id, accessHash, fileReference, sizes, videoSizes, dcId) = (photoData.flags, photoData.id, photoData.accessHash, photoData.fileReference, photoData.sizes, photoData.videoSizes, photoData.dcId)
let (immediateThumbnailData, representations) = telegramMediaImageRepresentationsFromApiSizes(datacenterId: dcId, photoId: id, accessHash: accessHash, fileReference: fileReference.makeData(), sizes: sizes)
var imageFlags: TelegramMediaImageFlags = []
let hasStickers = (flags & (1 << 0)) != 0
@@ -45,14 +50,17 @@ func telegramMediaImageFromApiPhoto(_ photo: Api.Photo) -> TelegramMediaImage? {
if let videoSizes = videoSizes {
for size in videoSizes {
switch size {
case let .videoSize(_, type, w, h, size, videoStartTs):
case let .videoSize(videoSizeData):
let (_, type, w, h, size, videoStartTs) = (videoSizeData.flags, videoSizeData.type, videoSizeData.w, videoSizeData.h, videoSizeData.size, videoSizeData.videoStartTs)
let resource: TelegramMediaResource
resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData())
videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs))
case let .videoSizeEmojiMarkup(fileId, backgroundColors):
case let .videoSizeEmojiMarkup(videoSizeEmojiMarkupData):
let (fileId, backgroundColors) = (videoSizeEmojiMarkupData.emojiId, videoSizeEmojiMarkupData.backgroundColors)
emojiMarkup = TelegramMediaImage.EmojiMarkup(content: .emoji(fileId: fileId), backgroundColors: backgroundColors)
case let .videoSizeStickerMarkup(stickerSet, fileId, backgroundColors):
case let .videoSizeStickerMarkup(videoSizeStickerMarkupData):
let (stickerSet, fileId, backgroundColors) = (videoSizeStickerMarkupData.stickerset, videoSizeStickerMarkupData.stickerId, videoSizeStickerMarkupData.backgroundColors)
if let packReference = StickerPackReference(apiInputSet: stickerSet) {
emojiMarkup = TelegramMediaImage.EmojiMarkup(content: .sticker(packReference: packReference, fileId: fileId), backgroundColors: backgroundColors)
}
@@ -9,7 +9,8 @@ func telegramMediaMapFromApiGeoPoint(_ geo: Api.GeoPoint, title: String?, addres
venue = MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType)
}
switch geo {
case let .geoPoint(_, long, lat, _, accuracyRadius):
case let .geoPoint(geoPointData):
let (_, long, lat, _, accuracyRadius) = (geoPointData.flags, geoPointData.long, geoPointData.lat, geoPointData.accessHash, geoPointData.accuracyRadius)
return TelegramMediaMap(latitude: lat, longitude: long, heading: heading, accuracyRadius: accuracyRadius.flatMap { Double($0) }, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout, liveProximityNotificationRadius: liveProximityNotificationRadius)
case .geoPointEmpty:
return TelegramMediaMap(latitude: 0.0, longitude: 0.0, heading: nil, accuracyRadius: nil, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout, liveProximityNotificationRadius: liveProximityNotificationRadius)
@@ -19,7 +20,8 @@ func telegramMediaMapFromApiGeoPoint(_ geo: Api.GeoPoint, title: String?, addres
func mapGeoAddressFromApiGeoPointAddress(_ geo: Api.GeoPointAddress) -> MapGeoAddress {
switch geo {
case let .geoPointAddress(_, countryIso2, state, city, street):
case let .geoPointAddress(geoPointAddressData):
let (countryIso2, state, city, street) = (geoPointAddressData.countryIso2, geoPointAddressData.state, geoPointAddressData.city, geoPointAddressData.street)
return MapGeoAddress(country: countryIso2, state: state, city: city, street: street)
}
}
@@ -6,11 +6,13 @@ import TelegramApi
extension TelegramMediaPollOption {
init(apiOption: Api.PollAnswer) {
switch apiOption {
case let .pollAnswer(text, option):
case let .pollAnswer(pollAnswerData):
let (text, option) = (pollAnswerData.text, pollAnswerData.option)
let answerText: String
let answerEntities: [MessageTextEntity]
switch text {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
answerText = text
answerEntities = messageTextEntitiesFromApiEntities(entities)
}
@@ -20,14 +22,15 @@ extension TelegramMediaPollOption {
}
var apiOption: Api.PollAnswer {
return .pollAnswer(text: .textWithEntities(text: self.text, entities: apiEntitiesFromMessageTextEntities(self.entities, associatedPeers: SimpleDictionary())), option: Buffer(data: self.opaqueIdentifier))
return .pollAnswer(.init(text: .textWithEntities(.init(text: self.text, entities: apiEntitiesFromMessageTextEntities(self.entities, associatedPeers: SimpleDictionary()))), option: Buffer(data: self.opaqueIdentifier)))
}
}
extension TelegramMediaPollOptionVoters {
init(apiVoters: Api.PollAnswerVoters) {
switch apiVoters {
case let .pollAnswerVoters(flags, option, voters):
case let .pollAnswerVoters(pollAnswerVotersData):
let (flags, option, voters) = (pollAnswerVotersData.flags, pollAnswerVotersData.option, pollAnswerVotersData.voters)
self.init(selected: (flags & (1 << 0)) != 0, opaqueIdentifier: option.makeData(), count: voters, isCorrect: (flags & (1 << 1)) != 0)
}
}
@@ -36,7 +39,8 @@ extension TelegramMediaPollOptionVoters {
extension TelegramMediaPollResults {
init(apiResults: Api.PollResults) {
switch apiResults {
case let .pollResults(_, results, totalVoters, recentVoters, solution, solutionEntities):
case let .pollResults(pollResultsData):
let (results, totalVoters, recentVoters, solution, solutionEntities) = (pollResultsData.results, pollResultsData.totalVoters, pollResultsData.recentVoters, pollResultsData.solution, pollResultsData.solutionEntities)
var parsedSolution: TelegramMediaPollResults.Solution?
if let solution = solution, let solutionEntities = solutionEntities, !solution.isEmpty {
parsedSolution = TelegramMediaPollResults.Solution(text: solution, entities: messageTextEntitiesFromApiEntities(solutionEntities))
@@ -6,11 +6,13 @@ import TelegramApi
extension TelegramMediaTodo.Item {
init(apiItem: Api.TodoItem) {
switch apiItem {
case let .todoItem(id, title):
case let .todoItem(todoItemData):
let (id, title) = (todoItemData.id, todoItemData.title)
let itemText: String
let itemEntities: [MessageTextEntity]
switch title {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
itemText = text
itemEntities = messageTextEntitiesFromApiEntities(entities)
}
@@ -19,14 +21,15 @@ extension TelegramMediaTodo.Item {
}
var apiItem: Api.TodoItem {
return .todoItem(id: self.id, title: .textWithEntities(text: self.text, entities: apiEntitiesFromMessageTextEntities(self.entities, associatedPeers: SimpleDictionary())))
return .todoItem(.init(id: self.id, title: .textWithEntities(.init(text: self.text, entities: apiEntitiesFromMessageTextEntities(self.entities, associatedPeers: SimpleDictionary())))))
}
}
extension TelegramMediaTodo.Completion {
init(apiCompletion: Api.TodoCompletion) {
switch apiCompletion {
case let .todoCompletion(id, completedBy, date):
case let .todoCompletion(todoCompletionData):
let (id, completedBy, date) = (todoCompletionData.id, todoCompletionData.completedBy, todoCompletionData.date)
self.init(id: id, date: date, completedBy: completedBy.peerId)
}
}
@@ -6,9 +6,11 @@ import TelegramApi
extension TelegramMediaWebFile {
convenience init(_ document: Api.WebDocument) {
switch document {
case let .webDocument(url, accessHash, size, mimeType, attributes):
case let .webDocument(webDocumentData):
let (url, accessHash, size, mimeType, attributes) = (webDocumentData.url, webDocumentData.accessHash, webDocumentData.size, webDocumentData.mimeType, webDocumentData.attributes)
self.init(resource: WebFileReferenceMediaResource(url: url, size: Int64(size), accessHash: accessHash), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
case let .webDocumentNoProxy(url, size, mimeType, attributes):
case let .webDocumentNoProxy(webDocumentNoProxyData):
let (url, size, mimeType, attributes) = (webDocumentNoProxyData.url, webDocumentNoProxyData.size, webDocumentNoProxyData.mimeType, webDocumentNoProxyData.attributes)
self.init(resource: HttpReferenceMediaResource(url: url, size: Int64(size)), mimeType: mimeType, size: size, attributes: telegramMediaFileAttributesFromApiAttributes(attributes))
}
}
@@ -6,13 +6,15 @@ import TelegramApi
func telegramMediaWebpageAttributeFromApiWebpageAttribute(_ attribute: Api.WebPageAttribute) -> TelegramMediaWebpageAttribute? {
switch attribute {
case let .webPageAttributeTheme(_, documents, settings):
case let .webPageAttributeTheme(webPageAttributeThemeData):
let (_, documents, settings) = (webPageAttributeThemeData.flags, webPageAttributeThemeData.documents, webPageAttributeThemeData.settings)
var files: [TelegramMediaFile] = []
if let documents = documents {
files = documents.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
}
return .theme(TelegraMediaWebpageThemeAttribute(files: files, settings: settings.flatMap { TelegramThemeSettings(apiThemeSettings: $0) }))
case let .webPageAttributeStickerSet(apiFlags, stickers):
case let .webPageAttributeStickerSet(webPageAttributeStickerSetData):
let (apiFlags, stickers) = (webPageAttributeStickerSetData.flags, webPageAttributeStickerSetData.stickers)
var flags = TelegramMediaWebpageStickerPackAttribute.Flags()
if (apiFlags & (1 << 0)) != 0 {
flags.insert(.isEmoji)
@@ -23,16 +25,19 @@ func telegramMediaWebpageAttributeFromApiWebpageAttribute(_ attribute: Api.WebPa
var files: [TelegramMediaFile] = []
files = stickers.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
return .stickerPack(TelegramMediaWebpageStickerPackAttribute(flags: flags, files: files))
case let .webPageAttributeUniqueStarGift(gift):
case let .webPageAttributeUniqueStarGift(webPageAttributeUniqueStarGiftData):
let gift = webPageAttributeUniqueStarGiftData.gift
if let starGift = StarGift(apiStarGift: gift) {
return .starGift(TelegramMediaWebpageStarGiftAttribute(gift: starGift))
}
return nil
case let .webPageAttributeStarGiftCollection(icons):
case let .webPageAttributeStarGiftCollection(webPageAttributeStarGiftCollectionData):
let icons = webPageAttributeStarGiftCollectionData.icons
var files: [TelegramMediaFile] = []
files = icons.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
return .giftCollection(TelegramMediaWebpageGiftCollectionAttribute(files: files))
case let .webPageAttributeStarGiftAuction(apiGift, endDate):
case let .webPageAttributeStarGiftAuction(webPageAttributeStarGiftAuctionData):
let (apiGift, endDate) = (webPageAttributeStarGiftAuctionData.gift, webPageAttributeStarGiftAuctionData.endDate)
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
@@ -46,10 +51,12 @@ func telegramMediaWebpageFromApiWebpage(_ webpage: Api.WebPage) -> TelegramMedia
switch webpage {
case .webPageNotModified:
return nil
case let .webPagePending(flags, id, url, date):
case let .webPagePending(webPagePendingData):
let (flags, id, url, date) = (webPagePendingData.flags, webPagePendingData.id, webPagePendingData.url, webPagePendingData.date)
let _ = flags
return TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.CloudWebpage, id: id), content: .Pending(date, url))
case let .webPage(flags, id, url, displayUrl, hash, type, siteName, title, description, photo, embedUrl, embedType, embedWidth, embedHeight, duration, author, document, cachedPage, attributes):
case let .webPage(webPageData):
let (flags, id, url, displayUrl, hash, type, siteName, title, description, photo, embedUrl, embedType, embedWidth, embedHeight, duration, author, document, cachedPage, attributes) = (webPageData.flags, webPageData.id, webPageData.url, webPageData.displayUrl, webPageData.hash, webPageData.type, webPageData.siteName, webPageData.title, webPageData.description, webPageData.photo, webPageData.embedUrl, webPageData.embedType, webPageData.embedWidth, webPageData.embedHeight, webPageData.duration, webPageData.author, webPageData.document, webPageData.cachedPage, webPageData.attributes)
var embedSize: PixelDimensions?
if let embedWidth = embedWidth, let embedHeight = embedHeight {
embedSize = PixelDimensions(width: embedWidth, height: embedHeight)
@@ -71,20 +78,21 @@ func telegramMediaWebpageFromApiWebpage(_ webpage: Api.WebPage) -> TelegramMedia
if let attributes = attributes {
webpageAttributes = attributes.compactMap(telegramMediaWebpageAttributeFromApiWebpageAttribute)
for attribute in attributes {
if case let .webPageAttributeStory(_, peerId, id, _) = attribute {
if case let .webPageAttributeStory(webPageAttributeStoryData) = attribute {
let (_, peerId, id, _) = (webPageAttributeStoryData.flags, webPageAttributeStoryData.peer, webPageAttributeStoryData.id, webPageAttributeStoryData.story)
story = TelegramMediaStory(storyId: StoryId(peerId: peerId.peerId, id: id), isMention: false)
}
}
}
var instantPage: InstantPage?
if let cachedPage = cachedPage {
instantPage = InstantPage(apiPage: cachedPage)
}
let isMediaLargeByDefault = (flags & (1 << 13)) != 0
let imageIsVideoCover = (flags & (1 << 14)) != 0
return TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.CloudWebpage, id: id), content: .Loaded(TelegramMediaWebpageLoadedContent(url: url, displayUrl: displayUrl, hash: hash, type: type, websiteName: siteName, title: title, text: description, embedUrl: embedUrl, embedType: embedType, embedSize: embedSize, duration: webpageDuration, author: author, isMediaLargeByDefault: isMediaLargeByDefault, imageIsVideoCover: imageIsVideoCover, image: image, file: file, story: story, attributes: webpageAttributes, instantPage: instantPage)))
case .webPageEmpty:
return nil
@@ -6,7 +6,8 @@ import TelegramApi
extension TelegramPeerNotificationSettings {
convenience init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
case let .peerNotifySettings(peerNotifySettingsData):
let (showPreviews, muteUntil, iosSound, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, storiesDesktopSound) = (peerNotifySettingsData.showPreviews, peerNotifySettingsData.muteUntil, peerNotifySettingsData.iosSound, peerNotifySettingsData.otherSound, peerNotifySettingsData.storiesMuted, peerNotifySettingsData.storiesHideSender, peerNotifySettingsData.storiesIosSound, peerNotifySettingsData.storiesOtherSound)
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
@@ -68,7 +69,8 @@ extension PeerMessageSound {
self = .default
case .notificationSoundNone:
self = .none
case let .notificationSoundLocal(_, data):
case let .notificationSoundLocal(notificationSoundLocalData):
let (_, data) = (notificationSoundLocalData.title, notificationSoundLocalData.data)
var rawApiSound = data
if let index = rawApiSound.firstIndex(of: ".") {
rawApiSound = String(rawApiSound[..<index])
@@ -94,7 +96,8 @@ extension PeerMessageSound {
}
}
self = parsedSound
case let .notificationSoundRingtone(id):
case let .notificationSoundRingtone(notificationSoundRingtoneData):
let id = notificationSoundRingtoneData.id
self = .cloud(fileId: id)
}
}
@@ -107,12 +110,12 @@ extension PeerMessageSound {
return .notificationSoundDefault
case let .bundledModern(id):
let string = "\(id + 100)"
return .notificationSoundLocal(title: string, data: string)
return .notificationSoundLocal(.init(title: string, data: string))
case let .bundledClassic(id):
let string = "\(id + 2)"
return .notificationSoundLocal(title: string, data: string)
return .notificationSoundLocal(.init(title: string, data: string))
case let .cloud(fileId):
return .notificationSoundRingtone(id: fileId)
return .notificationSoundRingtone(.init(id: fileId))
}
}
}
@@ -5,7 +5,8 @@ import TelegramApi
func parsedTelegramProfilePhoto(_ photo: Api.UserProfilePhoto) -> [TelegramMediaImageRepresentation] {
var representations: [TelegramMediaImageRepresentation] = []
switch photo {
case let .userProfilePhoto(flags, id, strippedThumb, dcId):
case let .userProfilePhoto(userProfilePhotoData):
let (flags, id, strippedThumb, dcId) = (userProfilePhotoData.flags, userProfilePhotoData.photoId, userProfilePhotoData.strippedThumb, userProfilePhotoData.dcId)
let hasVideo = (flags & (1 << 0)) != 0
let isPersonal = (flags & (1 << 2)) != 0
@@ -26,7 +27,8 @@ func parsedTelegramProfilePhoto(_ photo: Api.UserProfilePhoto) -> [TelegramMedia
extension TelegramPeerUsername {
init(apiUsername: Api.Username) {
switch apiUsername {
case let .username(flags, username):
case let .username(usernameData):
let (flags, username) = (usernameData.flags, usernameData.username)
self.init(flags: Flags(rawValue: flags), username: username)
}
}
@@ -35,10 +37,11 @@ extension TelegramPeerUsername {
extension PeerVerification {
init(apiBotVerification: Api.BotVerification) {
switch apiBotVerification {
case let .botVerification(botId, iconFileId, description):
case let .botVerification(botVerificationData):
let (botId, icon, description) = (botVerificationData.botId, botVerificationData.icon, botVerificationData.description)
self.init(
botId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)),
iconFileId: iconFileId,
iconFileId: icon,
description: description
)
}
@@ -49,7 +52,8 @@ extension PeerVerification {
extension TelegramUser {
convenience init(user: Api.User) {
switch user {
case let .user(flags, flags2, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames, _, color, profileColor, subscriberCount, verificationIconFileId, _):
case let .user(userData):
let (flags, flags2, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames, _, color, profileColor, subscriberCount, verificationIconFileId, _) = (userData.flags, userData.flags2, userData.id, userData.accessHash, userData.firstName, userData.lastName, userData.username, userData.phone, userData.photo, userData.status, userData.botInfoVersion, userData.restrictionReason, userData.botInlinePlaceholder, userData.langCode, userData.emojiStatus, userData.usernames, userData.storiesMaxId, userData.color, userData.profileColor, userData.botActiveUsers, userData.botVerificationIcon, userData.sendPaidMessagesStars)
let representations: [TelegramMediaImageRepresentation] = photo.flatMap(parsedTelegramProfilePhoto) ?? []
let isMin = (flags & (1 << 20)) != 0
@@ -121,6 +125,9 @@ extension TelegramUser {
if (flags2 & (1 << 16)) != 0 {
botFlags.insert(.hasForum)
}
if (flags2 & (1 << 17)) != 0 {
botFlags.insert(.forumManagedByUser)
}
botInfo = BotUserInfo(flags: botFlags, inlinePlaceholder: botInlinePlaceholder)
}
@@ -130,12 +137,14 @@ extension TelegramUser {
var backgroundEmojiId: Int64?
if let color = color {
switch color {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
if let color {
nameColor = .preset(PeerNameColor(rawValue: color))
}
backgroundEmojiId = backgroundEmojiIdValue
case let .peerColorCollectible(_, collectibleId, giftEmojiId, backgroundEmojiIdValue, accentColor, colors, darkAccentColor, darkColors):
case let .peerColorCollectible(peerColorCollectibleData):
let (_, collectibleId, giftEmojiId, backgroundEmojiIdValue, accentColor, colors, darkAccentColor, darkColors) = (peerColorCollectibleData.flags, peerColorCollectibleData.collectibleId, peerColorCollectibleData.giftEmojiId, peerColorCollectibleData.backgroundEmojiId, peerColorCollectibleData.accentColor, peerColorCollectibleData.colors, peerColorCollectibleData.darkAccentColor, peerColorCollectibleData.darkColors)
nameColor = .collectible(PeerCollectibleColor(
collectibleId: collectibleId,
giftEmojiFileId: giftEmojiId,
@@ -150,12 +159,13 @@ extension TelegramUser {
break
}
}
var profileColorIndex: Int32?
var profileBackgroundEmojiId: Int64?
if let profileColor = profileColor {
switch profileColor {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
profileColorIndex = color
profileBackgroundEmojiId = backgroundEmojiIdValue
default:
@@ -164,14 +174,16 @@ extension TelegramUser {
}
self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: subscriberCount, verificationIconFileId: verificationIconFileId)
case let .userEmpty(id):
case let .userEmpty(userEmptyData):
let id = userEmptyData.id
self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)
}
}
static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? {
switch rhs {
case let .user(flags, _, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _, color, profileColor, subscriberCount, _, _):
case let .user(userData):
let (flags, _, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _, color, profileColor, subscriberCount, _, _) = (userData.flags, userData.flags2, userData.id, userData.accessHash, userData.firstName, userData.lastName, userData.username, userData.phone, userData.photo, userData.status, userData.botInfoVersion, userData.restrictionReason, userData.botInlinePlaceholder, userData.langCode, userData.emojiStatus, userData.usernames, userData.storiesMaxId, userData.color, userData.profileColor, userData.botActiveUsers, userData.botVerificationIcon, userData.sendPaidMessagesStars)
let isMin = (flags & (1 << 20)) != 0
if !isMin {
return TelegramUser(user: rhs)
@@ -256,12 +268,14 @@ extension TelegramUser {
var backgroundEmojiId: Int64?
if let color {
switch color {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
if let color {
nameColor = .preset(PeerNameColor(rawValue: color))
}
backgroundEmojiId = backgroundEmojiIdValue
case let .peerColorCollectible(_, collectibleId, giftEmojiId, backgroundEmojiIdValue, accentColor, colors, darkAccentColor, darkColors):
case let .peerColorCollectible(peerColorCollectibleData):
let (_, collectibleId, giftEmojiId, backgroundEmojiIdValue, accentColor, colors, darkAccentColor, darkColors) = (peerColorCollectibleData.flags, peerColorCollectibleData.collectibleId, peerColorCollectibleData.giftEmojiId, peerColorCollectibleData.backgroundEmojiId, peerColorCollectibleData.accentColor, peerColorCollectibleData.colors, peerColorCollectibleData.darkAccentColor, peerColorCollectibleData.darkColors)
nameColor = .collectible(PeerCollectibleColor(
collectibleId: collectibleId,
giftEmojiFileId: giftEmojiId,
@@ -276,12 +290,13 @@ extension TelegramUser {
break
}
}
var profileColorIndex: Int32?
var profileBackgroundEmojiId: Int64?
if let profileColor = profileColor {
switch profileColor {
case let .peerColor(_, color, backgroundEmojiIdValue):
case let .peerColor(peerColorData):
let (_, color, backgroundEmojiIdValue) = (peerColorData.flags, peerColorData.color, peerColorData.backgroundEmojiId)
profileColorIndex = color
profileBackgroundEmojiId = backgroundEmojiIdValue
default:
@@ -8,17 +8,22 @@ extension TelegramUserPresence {
switch apiStatus {
case .userStatusEmpty:
self.init(status: .none, lastActivity: 0)
case let .userStatusOnline(expires):
case let .userStatusOnline(userStatusOnlineData):
let (expires) = (userStatusOnlineData.expires)
self.init(status: .present(until: expires), lastActivity: 0)
case let .userStatusOffline(wasOnline):
case let .userStatusOffline(userStatusOfflineData):
let (wasOnline) = (userStatusOfflineData.wasOnline)
self.init(status: .present(until: wasOnline), lastActivity: 0)
case let .userStatusRecently(flags):
case let .userStatusRecently(userStatusRecentlyData):
let (flags) = (userStatusRecentlyData.flags)
let isHidden = (flags & (1 << 0)) != 0
self.init(status: .recently(isHidden: isHidden), lastActivity: 0)
case let .userStatusLastWeek(flags):
case let .userStatusLastWeek(userStatusLastWeekData):
let (flags) = (userStatusLastWeekData.flags)
let isHidden = (flags & (1 << 0)) != 0
self.init(status: .lastWeek(isHidden: isHidden), lastActivity: 0)
case let .userStatusLastMonth(flags):
case let .userStatusLastMonth(userStatusLastMonthData):
let (flags) = (userStatusLastMonthData.flags)
let isHidden = (flags & (1 << 0)) != 0
self.init(status: .lastMonth(isHidden: isHidden), lastActivity: 0)
}
@@ -26,7 +31,8 @@ extension TelegramUserPresence {
convenience init?(apiUser: Api.User) {
switch apiUser {
case let .user(_, _, _, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _, _, _, _):
case let .user(userData):
let status = userData.status
if let status = status {
self.init(apiStatus: status)
} else {
@@ -13,47 +13,47 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa
case .Unknown:
break
case .Mention:
apiEntities.append(.messageEntityMention(offset: offset, length: length))
apiEntities.append(.messageEntityMention(.init(offset: offset, length: length)))
case .Hashtag:
apiEntities.append(.messageEntityHashtag(offset: offset, length: length))
apiEntities.append(.messageEntityHashtag(.init(offset: offset, length: length)))
case .BotCommand:
apiEntities.append(.messageEntityBotCommand(offset: offset, length: length))
apiEntities.append(.messageEntityBotCommand(.init(offset: offset, length: length)))
case .Url:
apiEntities.append(.messageEntityUrl(offset: offset, length: length))
apiEntities.append(.messageEntityUrl(.init(offset: offset, length: length)))
case .Email:
apiEntities.append(.messageEntityEmail(offset: offset, length: length))
apiEntities.append(.messageEntityEmail(.init(offset: offset, length: length)))
case .Bold:
apiEntities.append(.messageEntityBold(offset: offset, length: length))
apiEntities.append(.messageEntityBold(.init(offset: offset, length: length)))
case .Italic:
apiEntities.append(.messageEntityItalic(offset: offset, length: length))
apiEntities.append(.messageEntityItalic(.init(offset: offset, length: length)))
case .Code:
apiEntities.append(.messageEntityCode(offset: offset, length: length))
apiEntities.append(.messageEntityCode(.init(offset: offset, length: length)))
case let .Pre(language):
apiEntities.append(.messageEntityPre(offset: offset, length: length, language: language ?? ""))
apiEntities.append(.messageEntityPre(.init(offset: offset, length: length, language: language ?? "")))
case let .TextUrl(url):
apiEntities.append(.messageEntityTextUrl(offset: offset, length: length, url: url))
apiEntities.append(.messageEntityTextUrl(.init(offset: offset, length: length, url: url)))
case let .TextMention(peerId):
if let peer = associatedPeers[peerId], let inputUser = apiInputUser(peer) {
apiEntities.append(.inputMessageEntityMentionName(offset: offset, length: length, userId: inputUser))
apiEntities.append(.inputMessageEntityMentionName(.init(offset: offset, length: length, userId: inputUser)))
}
case .PhoneNumber:
break
case .Strikethrough:
apiEntities.append(.messageEntityStrike(offset: offset, length: length))
apiEntities.append(.messageEntityStrike(.init(offset: offset, length: length)))
case let .BlockQuote(isCollapsed):
var flags: Int32 = 0
if isCollapsed {
flags |= 1 << 0
}
apiEntities.append(.messageEntityBlockquote(flags: flags, offset: offset, length: length))
apiEntities.append(.messageEntityBlockquote(.init(flags: flags, offset: offset, length: length)))
case .Underline:
apiEntities.append(.messageEntityUnderline(offset: offset, length: length))
apiEntities.append(.messageEntityUnderline(.init(offset: offset, length: length)))
case .BankCard:
apiEntities.append(.messageEntityBankCard(offset: offset, length: length))
apiEntities.append(.messageEntityBankCard(.init(offset: offset, length: length)))
case .Spoiler:
apiEntities.append(.messageEntitySpoiler(offset: offset, length: length))
apiEntities.append(.messageEntitySpoiler(.init(offset: offset, length: length)))
case let .CustomEmoji(_, fileId):
apiEntities.append(.messageEntityCustomEmoji(offset: offset, length: length, documentId: fileId))
apiEntities.append(.messageEntityCustomEmoji(.init(offset: offset, length: length, documentId: fileId)))
case .Custom:
break
}
@@ -7,7 +7,8 @@ import TelegramApi
extension TelegramTheme {
convenience init(apiTheme: Api.Theme) {
switch apiTheme {
case let .theme(flags, id, accessHash, slug, title, document, settings, emoticon, installCount):
case let .theme(themeData):
let (flags, id, accessHash, slug, title, document, settings, emoticon, installCount) = (themeData.flags, themeData.id, themeData.accessHash, themeData.slug, themeData.title, themeData.document, themeData.settings, themeData.emoticon, themeData.installsCount)
self.init(id: id, accessHash: accessHash, slug: slug, emoticon: emoticon, title: title, file: document.flatMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }, settings: settings?.compactMap(TelegramThemeSettings.init(apiThemeSettings:)), isCreator: (flags & 1 << 0) != 0, isDefault: (flags & 1 << 1) != 0, installCount: installCount)
}
}
@@ -46,7 +47,8 @@ extension TelegramBaseTheme {
extension TelegramThemeSettings {
convenience init?(apiThemeSettings: Api.ThemeSettings) {
switch apiThemeSettings {
case let .themeSettings(flags, baseTheme, accentColor, outboxAccentColor, messageColors, wallpaper):
case let .themeSettings(themeSettingsData):
let (flags, baseTheme, accentColor, outboxAccentColor, messageColors, wallpaper) = (themeSettingsData.flags, themeSettingsData.baseTheme, themeSettingsData.accentColor, themeSettingsData.outboxAccentColor, themeSettingsData.messageColors, themeSettingsData.wallpaper)
self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), outgoingAccentColor: outboxAccentColor.flatMap { UInt32(bitPattern: $0) }, messageColors: messageColors?.map(UInt32.init(bitPattern:)) ?? [], animateMessageColors: (flags & 1 << 2) != 0, wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:)))
}
}
@@ -73,6 +75,6 @@ extension TelegramThemeSettings {
flags |= 1 << 1
}
return .inputThemeSettings(flags: flags, baseTheme: self.baseTheme.apiBaseTheme, accentColor: Int32(bitPattern: self.accentColor), outboxAccentColor: self.outgoingAccentColor.flatMap { Int32(bitPattern: $0) }, messageColors: self.messageColors.isEmpty ? nil : self.messageColors.map(Int32.init(bitPattern:)), wallpaper: inputWallpaper, wallpaperSettings: inputWallpaperSettings)
return .inputThemeSettings(.init(flags: flags, baseTheme: self.baseTheme.apiBaseTheme, accentColor: Int32(bitPattern: self.accentColor), outboxAccentColor: self.outgoingAccentColor.flatMap { Int32(bitPattern: $0) }, messageColors: self.messageColors.isEmpty ? nil : self.messageColors.map(Int32.init(bitPattern:)), wallpaper: inputWallpaper, wallpaperSettings: inputWallpaperSettings))
}
}
@@ -7,7 +7,8 @@ import TelegramApi
extension WallpaperSettings {
init(apiWallpaperSettings: Api.WallPaperSettings) {
switch apiWallpaperSettings {
case let .wallPaperSettings(flags, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, intensity, rotation, emoticon):
case let .wallPaperSettings(wallPaperSettingsData):
let (flags, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, intensity, rotation, emoticon) = (wallPaperSettingsData.flags, wallPaperSettingsData.backgroundColor, wallPaperSettingsData.secondBackgroundColor, wallPaperSettingsData.thirdBackgroundColor, wallPaperSettingsData.fourthBackgroundColor, wallPaperSettingsData.intensity, wallPaperSettingsData.rotation, wallPaperSettingsData.emoticon)
var colors: [UInt32] = []
if let backgroundColor = backgroundColor {
colors.append(UInt32(bitPattern: backgroundColor))
@@ -60,13 +61,14 @@ func apiWallpaperSettings(_ wallpaperSettings: WallpaperSettings) -> Api.WallPap
flags |= (1 << 6)
fourthBackgroundColor = Int32(bitPattern: wallpaperSettings.colors[3])
}
return .wallPaperSettings(flags: flags, backgroundColor: backgroundColor, secondBackgroundColor: secondBackgroundColor, thirdBackgroundColor: thirdBackgroundColor, fourthBackgroundColor: fourthBackgroundColor, intensity: wallpaperSettings.intensity, rotation: wallpaperSettings.rotation ?? 0, emoticon: wallpaperSettings.emoticon)
return .wallPaperSettings(.init(flags: flags, backgroundColor: backgroundColor, secondBackgroundColor: secondBackgroundColor, thirdBackgroundColor: thirdBackgroundColor, fourthBackgroundColor: fourthBackgroundColor, intensity: wallpaperSettings.intensity, rotation: wallpaperSettings.rotation ?? 0, emoticon: wallpaperSettings.emoticon))
}
extension TelegramWallpaper {
init(apiWallpaper: Api.WallPaper) {
switch apiWallpaper {
case let .wallPaper(id, flags, accessHash, slug, document, settings):
case let .wallPaper(wallPaperData):
let (id, flags, accessHash, slug, document, settings) = (wallPaperData.id, wallPaperData.flags, wallPaperData.accessHash, wallPaperData.slug, wallPaperData.document, wallPaperData.settings)
if let file = telegramMediaFileFromApiDocument(document, altDocuments: []) {
let wallpaperSettings: WallpaperSettings
if let settings = settings {
@@ -79,8 +81,10 @@ extension TelegramWallpaper {
//assertionFailure()
self = .color(0xffffff)
}
case let .wallPaperNoFile(id, _, settings):
if let settings = settings, case let .wallPaperSettings(_, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, _, rotation, emoticon) = settings {
case let .wallPaperNoFile(wallPaperNoFileData):
let (id, _, settings) = (wallPaperNoFileData.id, wallPaperNoFileData.flags, wallPaperNoFileData.settings)
if let settings = settings, case let .wallPaperSettings(wallPaperSettingsData) = settings {
let (_, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, _, rotation, emoticon) = (wallPaperSettingsData.flags, wallPaperSettingsData.backgroundColor, wallPaperSettingsData.secondBackgroundColor, wallPaperSettingsData.thirdBackgroundColor, wallPaperSettingsData.fourthBackgroundColor, wallPaperSettingsData.intensity, wallPaperSettingsData.rotation, wallPaperSettingsData.emoticon)
if id == 0, let emoticon = emoticon {
self = .emoticon(emoticon)
return
@@ -107,13 +111,13 @@ extension TelegramWallpaper {
case .builtin:
return nil
case let .file(file):
return (.inputWallPaperSlug(slug: file.slug), apiWallpaperSettings(file.settings))
return (.inputWallPaperSlug(.init(slug: file.slug)), apiWallpaperSettings(file.settings))
case let .color(color):
return (.inputWallPaperNoFile(id: 0), apiWallpaperSettings(WallpaperSettings(colors: [color])))
return (.inputWallPaperNoFile(.init(id: 0)), apiWallpaperSettings(WallpaperSettings(colors: [color])))
case let .gradient(gradient):
return (.inputWallPaperNoFile(id: gradient.id ?? 0), apiWallpaperSettings(WallpaperSettings(colors: gradient.colors, rotation: gradient.settings.rotation)))
return (.inputWallPaperNoFile(.init(id: gradient.id ?? 0)), apiWallpaperSettings(WallpaperSettings(colors: gradient.colors, rotation: gradient.settings.rotation)))
case let .emoticon(emoticon):
return (.inputWallPaperNoFile(id: 0), apiWallpaperSettings(WallpaperSettings(emoticon: emoticon)))
return (.inputWallPaperNoFile(.init(id: 0)), apiWallpaperSettings(WallpaperSettings(emoticon: emoticon)))
default:
return nil
}
@@ -185,7 +185,7 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
appSandbox = pushNotificationConfiguration.isSandbox ? .boolTrue : .boolFalse
}
let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: flags, logoutTokens: authTokens.map { Buffer(data: $0) }, token: token, appSandbox: appSandbox))
let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(.init(flags: flags, logoutTokens: authTokens.map { Buffer(data: $0) }, token: token, appSandbox: appSandbox)))
enum SendCodeResult {
case password(hint: String?)
@@ -213,7 +213,8 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
return updatedAccount.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapToSignal { result -> Signal<(SendCodeResult, UnauthorizedAccount), MTRpcError> in
switch result {
case let .password(_, _, _, _, hint, _, _, _, _, _, _):
case let .password(passwordData):
let hint = passwordData.hint
return .single((.password(hint: hint), updatedAccount))
}
}
@@ -248,7 +249,8 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
}
|> mapToSignal { result -> Signal<(SendCodeResult, UnauthorizedAccount), AuthorizationCodeRequestError> in
switch result {
case let .password(_, _, _, _, hint, _, _, _, _, _, _):
case let .password(passwordData):
let hint = passwordData.hint
return .single((.password(hint: hint), account))
}
}
@@ -267,14 +269,16 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
return .single(.sentCode(account))
case let .sentCode(sentCode):
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, codeTimeout):
case let .sentCode(sentCodeData):
let (type, phoneCodeHash, nextType, codeTimeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
let parsedType = SentAuthorizationCodeType(apiType: type)
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
if case let .sentCodeTypeFirebaseSms(sentCodeTypeFirebaseSmsData) = type {
let (receipt, pushTimeout) = (sentCodeTypeFirebaseSmsData.receipt, sentCodeTypeFirebaseSmsData.pushTimeout)
return firebaseSecretStream
|> map { mapping -> String? in
guard let receipt = receipt else {
@@ -358,14 +362,16 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: parsedType, hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: previousCodeEntry, usePrevious: false)))
case .sentCodePaymentRequired:
return .never()
case let .sentCodeSuccess(authorization):
case let .sentCodeSuccess(sentCodeSuccessData):
let authorization = sentCodeSuccessData.authorization
switch authorization {
case let .authorization(_, otherwiseReloginDays, _, futureAuthToken, user):
case let .authorization(authorizationData):
let (otherwiseReloginDays, futureAuthToken, apiUser) = (authorizationData.otherwiseReloginDays, authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42"), phone.count <= 5 {
isSupportUser = true
@@ -427,14 +433,16 @@ private func internalResendAuthorizationCode(accountManager: AccountManager<Tele
|> mapToSignal { sentCode -> Signal<SendAuthorizationCodeResult, AuthorizationCodeRequestError> in
return account.postbox.transaction { transaction -> Signal<SendAuthorizationCodeResult, AuthorizationCodeRequestError> in
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, codeTimeout):
case let .sentCode(sentCodeData):
let (type, phoneCodeHash, nextType, codeTimeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
let parsedType = SentAuthorizationCodeType(apiType: type)
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = type {
if case let .sentCodeTypeFirebaseSms(sentCodeTypeFirebaseSmsData) = type {
let (receipt, pushTimeout) = (sentCodeTypeFirebaseSmsData.receipt, sentCodeTypeFirebaseSmsData.pushTimeout)
return firebaseSecretStream
|> map { mapping -> String? in
guard let receipt = receipt else {
@@ -518,7 +526,8 @@ private func internalResendAuthorizationCode(accountManager: AccountManager<Tele
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: number, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: previousCodeEntry, usePrevious: false)))
return .single(.sentCode(account))
case let .sentCodePaymentRequired(storeProduct, codeHash, supportEmailAddress, supportEmailSubject, _, _):
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
return .single(.sentCode(account))
case .sentCodeSuccess:
@@ -555,7 +564,8 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
|> mapToSignal { sentCode -> Signal<Void, AuthorizationCodeRequestError> in
return account.postbox.transaction { transaction -> Signal<Void, AuthorizationCodeRequestError> in
switch sentCode {
case let .sentCode(_, newType, phoneCodeHash, nextType, codeTimeout):
case let .sentCode(sentCodeData):
let (newType, phoneCodeHash, nextType, codeTimeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
let parsedType = SentAuthorizationCodeType(apiType: newType)
var previousCodeEntry: UnauthorizedAccountStateContents?
if let previousCodeEntryValue {
@@ -579,7 +589,8 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
if case let .sentCodeTypeFirebaseSms(_, _, _, _, receipt, pushTimeout, _) = newType {
if case let .sentCodeTypeFirebaseSms(sentCodeTypeFirebaseSmsData) = newType {
let (receipt, pushTimeout) = (sentCodeTypeFirebaseSmsData.receipt, sentCodeTypeFirebaseSmsData.pushTimeout)
return firebaseSecretStream
|> map { mapping -> String? in
guard let receipt = receipt else {
@@ -626,7 +637,8 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
}
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: number, type: parsedType, hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: previousCodeEntry, usePrevious: false)))
case let .sentCodePaymentRequired(storeProduct, codeHash, supportEmailAddress, supportEmailSubject, _, _):
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
case .sentCodeSuccess:
break
@@ -776,7 +788,8 @@ public func sendLoginEmailChangeCode(account: Account, email: String) -> Signal<
}
|> map { result -> ChangeLoginEmailData in
switch result {
case let .sentEmailCode(_, length):
case let .sentEmailCode(sentEmailCodeData):
let length = sentEmailCodeData.length
return ChangeLoginEmailData(email: email, length: length)
}
}
@@ -787,7 +800,7 @@ public func sendLoginEmailCode(account: UnauthorizedAccount, email: String) -> S
if let state = transaction.getState() as? UnauthorizedAccountState {
switch state.contents {
case let .confirmationCodeEntry(phoneNumber, _, phoneCodeHash, _, _, syncContacts, _, _):
return account.network.request(Api.functions.account.sendVerifyEmailCode(purpose: .emailVerifyPurposeLoginSetup(phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash), email: email), automaticFloodWait: false)
return account.network.request(Api.functions.account.sendVerifyEmailCode(purpose: .emailVerifyPurposeLoginSetup(.init(phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash)), email: email), automaticFloodWait: false)
|> `catch` { error -> Signal<Api.account.SentEmailCode, AuthorizationSendEmailCodeError> in
let errorDescription = error.errorDescription ?? ""
if errorDescription.hasPrefix("FLOOD_WAIT") {
@@ -805,7 +818,8 @@ public func sendLoginEmailCode(account: UnauthorizedAccount, email: String) -> S
|> mapToSignal { result -> Signal<Never, AuthorizationSendEmailCodeError> in
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch result {
case let .sentEmailCode(emailPattern, length):
case let .sentEmailCode(sentEmailCodeData):
let (emailPattern, length) = (sentEmailCodeData.emailPattern, sentEmailCodeData.length)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: .email(emailPattern: emailPattern, length: length, resetAvailablePeriod: nil, resetPendingDate: nil, appleSignInAllowed: false, setup: true), hash: phoneCodeHash, timeout: nil, nextType: nil, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
}
return .complete()
@@ -832,11 +846,11 @@ public func verifyLoginEmailChange(account: Account, code: AuthorizationCode.Ema
let verification: Api.EmailVerification
switch code {
case let .emailCode(code):
verification = .emailVerificationCode(code: code)
verification = .emailVerificationCode(.init(code: code))
case let .appleToken(token):
verification = .emailVerificationApple(token: token)
verification = .emailVerificationApple(.init(token: token))
case let .googleToken(token):
verification = .emailVerificationGoogle(token: token)
verification = .emailVerificationGoogle(.init(token: token))
}
return account.network.request(Api.functions.account.verifyEmail(purpose: .emailVerifyPurposeLoginChange, verification: verification), automaticFloodWait: false)
@@ -869,14 +883,14 @@ public func verifyLoginEmailSetup(account: UnauthorizedAccount, code: Authorizat
let verification: Api.EmailVerification
switch code {
case let .emailCode(code):
verification = .emailVerificationCode(code: code)
verification = .emailVerificationCode(.init(code: code))
case let .appleToken(token):
verification = .emailVerificationApple(token: token)
verification = .emailVerificationApple(.init(token: token))
case let .googleToken(token):
verification = .emailVerificationGoogle(token: token)
verification = .emailVerificationGoogle(.init(token: token))
}
return account.network.request(Api.functions.account.verifyEmail(purpose: .emailVerifyPurposeLoginSetup(phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash), verification: verification), automaticFloodWait: false)
return account.network.request(Api.functions.account.verifyEmail(purpose: .emailVerifyPurposeLoginSetup(.init(phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash)), verification: verification), automaticFloodWait: false)
|> `catch` { error -> Signal<Api.account.EmailVerified, AuthorizationEmailVerificationError> in
let errorDescription = error.errorDescription ?? ""
if errorDescription.hasPrefix("FLOOD_WAIT") {
@@ -896,16 +910,19 @@ public func verifyLoginEmailSetup(account: UnauthorizedAccount, code: Authorizat
|> mapToSignal { result -> Signal<Never, AuthorizationEmailVerificationError> in
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch result {
case let .emailVerifiedLogin(_, sentCode):
case let .emailVerifiedLogin(emailVerifiedLoginData):
let sentCode = emailVerifiedLoginData.sentCode
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, timeout):
case let .sentCode(sentCodeData):
let (type, phoneCodeHash, nextType, timeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
case let .sentCodePaymentRequired(storeProduct, codeHash, supportEmailAddress, supportEmailSubject, _, _):
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
case .sentCodeSuccess:
break
@@ -961,16 +978,18 @@ public func resetLoginEmail(account: UnauthorizedAccount, phoneNumber: String, p
|> mapToSignal { sentCode -> Signal<Never, AuthorizationEmailResetError> in
return account.postbox.transaction { transaction -> Signal<Never, NoError> in
switch sentCode {
case let .sentCode(_, type, phoneCodeHash, nextType, codeTimeout):
case let .sentCode(sentCodeData):
let (type, phoneCodeHash, nextType, codeTimeout) = (sentCodeData.type, sentCodeData.phoneCodeHash, sentCodeData.nextType, sentCodeData.timeout)
var parsedNextType: AuthorizationCodeNextType?
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
return .complete()
case let .sentCodePaymentRequired(storeProduct, codeHash, supportEmailAddress, supportEmailSubject, _, _):
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
return .complete()
case .sentCodeSuccess:
@@ -1012,11 +1031,11 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
flags = 1 << 1
switch verification {
case let .emailCode(code):
emailVerification = .emailVerificationCode(code: code)
emailVerification = .emailVerificationCode(.init(code: code))
case let .appleToken(token):
emailVerification = .emailVerificationApple(token: token)
emailVerification = .emailVerificationApple(.init(token: token))
case let .googleToken(token):
emailVerification = .emailVerificationGoogle(token: token)
emailVerification = .emailVerificationGoogle(.init(token: token))
}
}
@@ -1037,7 +1056,8 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
}
|> mapToSignal { result -> Signal<AuthorizationCodeResult, AuthorizationCodeVerificationError> in
switch result {
case let .password(_, _, _, _, hint, _, _, _, _, _, _):
case let .password(passwordData):
let hint = passwordData.hint
return .single(.password(hint: hint ?? ""))
}
}
@@ -1067,14 +1087,15 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
case let .password(hint):
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: false, syncContacts: syncContacts)))
return .single(.loggedIn)
case let .authorization(authorization):
switch authorization {
case let .authorization(_, otherwiseReloginDays, _, futureAuthToken, user):
case let .authorization(authorizationOuter):
switch authorizationOuter {
case let .authorization(authorizationData):
let (otherwiseReloginDays, futureAuthToken, apiUser) = (authorizationData.otherwiseReloginDays, authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42") {
isSupportUser = true
@@ -1089,7 +1110,8 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
switchToAuthorizedAccount(transaction: transaction, account: account, isSupportUser: isSupportUser)
return .loggedIn
}
case let .authorizationSignUpRequired(_, termsOfService):
case let .authorizationSignUpRequired(authorizationSignUpRequiredData):
let termsOfService = authorizationSignUpRequiredData.termsOfService
return .single(.signUp(AuthorizationSignUpData(number: number, codeHash: hash, code: code, termsOfService: termsOfService.flatMap(UnauthorizedAccountTermsOfService.init(apiTermsOfService:)), syncContacts: syncContacts)))
}
}
@@ -1137,12 +1159,13 @@ public func authorizeWithPassword(accountManager: AccountManager<TelegramAccount
|> mapToSignal { result -> Signal<Void, AuthorizationPasswordVerificationError> in
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch result {
case let .authorization(_, _, _, futureAuthToken, user):
case let .authorization(authorizationData):
let (futureAuthToken, apiUser) = (authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
/*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in
return peer
@@ -1215,7 +1238,7 @@ public func authorizeWithPasskey(accountManager: AccountManager<TelegramAccountM
if foreignDatacenter != nil {
flags |= 1 << 0
}
return account.network.request(Api.functions.auth.finishPasskeyLogin(flags: flags, credential: .inputPasskeyCredentialPublicKey(id: passkey.id, rawId: passkey.id, response: .inputPasskeyResponseLogin(clientData: .dataJSON(data: passkey.clientData), authenticatorData: Buffer(data: passkey.authenticatorData), signature: Buffer(data: passkey.signature), userHandle: passkey.userHandle)), fromDcId: (foreignDatacenter?.id).flatMap(Int32.init), fromAuthKeyId: foreignDatacenter?.authKeyId), automaticFloodWait: false)
return account.network.request(Api.functions.auth.finishPasskeyLogin(flags: flags, credential: .inputPasskeyCredentialPublicKey(.init(id: passkey.id, rawId: passkey.id, response: .inputPasskeyResponseLogin(.init(clientData: .dataJSON(.init(data: passkey.clientData)), authenticatorData: Buffer(data: passkey.authenticatorData), signature: Buffer(data: passkey.signature), userHandle: passkey.userHandle)))), fromDcId: (foreignDatacenter?.id).flatMap(Int32.init), fromAuthKeyId: foreignDatacenter?.authKeyId), automaticFloodWait: false)
|> map { authorization in
return .authorization(authorization)
}
@@ -1232,7 +1255,8 @@ public func authorizeWithPasskey(accountManager: AccountManager<TelegramAccountM
}
|> mapToSignal { result -> Signal<AuthorizationCodeResult, AuthorizationCodeVerificationError> in
switch result {
case let .password(_, _, _, _, hint, _, _, _, _, _, _):
case let .password(passwordData):
let hint = passwordData.hint
return .single(.password(hint: hint ?? ""))
}
}
@@ -1262,14 +1286,15 @@ public func authorizeWithPasskey(accountManager: AccountManager<TelegramAccountM
case let .password(hint):
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
return .single(AuthorizeWithPasskeyResult(updatedAccount: account))
case let .authorization(authorization):
switch authorization {
case let .authorization(_, otherwiseReloginDays, _, futureAuthToken, user):
case let .authorization(authorizationOuter):
switch authorizationOuter {
case let .authorization(authorizationData):
let (otherwiseReloginDays, futureAuthToken, apiUser) = (authorizationData.otherwiseReloginDays, authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42") {
isSupportUser = true
@@ -1340,12 +1365,13 @@ public final class RecoveredAccountData {
public func loginWithRecoveredAccountData(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, recoveredAccountData: RecoveredAccountData, syncContacts: Bool) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
switch recoveredAccountData.authorization {
case let .authorization(_, _, _, futureAuthToken, user):
case let .authorization(authorizationData):
let (futureAuthToken, apiUser) = (authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42") {
isSupportUser = true
@@ -1385,7 +1411,7 @@ func _internal_performPasswordRecovery(network: Network, code: String, updatedPa
return .fail(.invalidCode)
}
newSettings = Api.account.PasswordInputSettings.passwordInputSettings(flags: flags, newAlgo: updatedPasswordDerivation.apiAlgo, newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSettings: nil)
newSettings = Api.account.PasswordInputSettings.passwordInputSettings(.init(flags: flags, newAlgo: updatedPasswordDerivation.apiAlgo, newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSettings: nil))
}
var flags: Int32 = 0
@@ -1496,12 +1522,13 @@ public func signUpWithName(accountManager: AccountManager<TelegramAccountManager
}
|> mapToSignal { result -> Signal<Void, SignUpError> in
switch result {
case let .authorization(_, otherwiseReloginDays, _, futureAuthToken, user):
case let .authorization(authorizationData):
let (otherwiseReloginDays, futureAuthToken, apiUser) = (authorizationData.otherwiseReloginDays, authorizationData.futureAuthToken, authorizationData.user)
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
let user = TelegramUser(user: apiUser)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42") {
isSupportUser = true
@@ -1518,7 +1545,7 @@ public func signUpWithName(accountManager: AccountManager<TelegramAccountManager
}
}
|> castError(SignUpError.self)
let switchedAccounts = accountManager.transaction { transaction -> Void in
switchToAuthorizedAccount(transaction: transaction, account: account, isSupportUser: isSupportUser)
}
@@ -5,6 +5,8 @@
// to avoid Swift/ObjC bridging complexities in MtProtoKit
static NSString *const kDeviceSpoofIsEnabled = @"DeviceSpoof.isEnabled";
static NSString *const kDeviceSpoofHasExplicitConfiguration =
@"DeviceSpoof.hasExplicitConfiguration";
static NSString *const kDeviceSpoofSelectedProfileId =
@"DeviceSpoof.selectedProfileId";
static NSString *const kDeviceSpoofCustomDeviceModel =
@@ -12,89 +14,132 @@ static NSString *const kDeviceSpoofCustomDeviceModel =
static NSString *const kDeviceSpoofCustomSystemVersion =
@"DeviceSpoof.customSystemVersion";
static NSDictionary<NSNumber *, NSDictionary<NSString *, NSString *> *> *
DeviceSpoofProfiles(void) {
static NSDictionary<NSNumber *, NSDictionary<NSString *, NSString *> *>
*profiles;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
profiles = @{
@1 : @{
@"deviceModel" : @"iPhone 14 Pro",
@"systemVersion" : @"iOS 17.2"
},
@2 : @{
@"deviceModel" : @"iPhone 15 Pro Max",
@"systemVersion" : @"iOS 17.4"
},
@3 : @{
@"deviceModel" : @"Samsung SM-S918B",
@"systemVersion" : @"Android 14"
},
@4 : @{
@"deviceModel" : @"Google Pixel 8 Pro",
@"systemVersion" : @"Android 14"
},
@5 : @{
@"deviceModel" : @"PC 64bit",
@"systemVersion" : @"Windows 11"
},
@6 : @{
@"deviceModel" : @"MacBook Pro",
@"systemVersion" : @"macOS 14.3"
},
@7 : @{
@"deviceModel" : @"Web",
@"systemVersion" : @"Chrome 121"
},
@8 : @{
@"deviceModel" : @"HUAWEI MNA-LX9",
@"systemVersion" : @"HarmonyOS 4.0"
},
@9 : @{
@"deviceModel" : @"Xiaomi 2311DRK48G",
@"systemVersion" : @"Android 14"
}
};
});
return profiles;
}
static NSString *DeviceSpoofTrimmedString(NSString *value) {
if (value == nil) {
return @"";
}
return
[value stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
static NSInteger DeviceSpoofSanitizedProfileId(NSUserDefaults *defaults) {
NSInteger profileId =
[defaults integerForKey:kDeviceSpoofSelectedProfileId];
if (profileId == 0 || profileId == 100 ||
DeviceSpoofProfiles()[@(profileId)] != nil) {
return profileId;
}
[defaults setInteger:0 forKey:kDeviceSpoofSelectedProfileId];
return 0;
}
static BOOL DeviceSpoofIsEnabled(NSUserDefaults *defaults) {
return [defaults boolForKey:kDeviceSpoofHasExplicitConfiguration] &&
[defaults boolForKey:kDeviceSpoofIsEnabled];
}
static void DeviceSpoofResolveValues(NSUserDefaults *defaults,
NSString *__autoreleasing *deviceModel,
NSString *__autoreleasing *systemVersion) {
*deviceModel = nil;
*systemVersion = nil;
if (!DeviceSpoofIsEnabled(defaults)) {
return;
}
NSInteger profileId = DeviceSpoofSanitizedProfileId(defaults);
if (profileId == 0) {
return;
}
if (profileId == 100) {
NSString *customDeviceModel =
DeviceSpoofTrimmedString([defaults stringForKey:kDeviceSpoofCustomDeviceModel]);
NSString *customSystemVersion =
DeviceSpoofTrimmedString([defaults stringForKey:kDeviceSpoofCustomSystemVersion]);
if (customDeviceModel.length == 0 || customSystemVersion.length == 0) {
return;
}
*deviceModel = customDeviceModel;
*systemVersion = customSystemVersion;
return;
}
NSDictionary<NSString *, NSString *> *profile = DeviceSpoofProfiles()[@(profileId)];
*deviceModel = profile[@"deviceModel"];
*systemVersion = profile[@"systemVersion"];
}
@implementation DeviceSpoofBridge
+ (BOOL)isEnabled {
return
[[NSUserDefaults standardUserDefaults] boolForKey:kDeviceSpoofIsEnabled];
return DeviceSpoofIsEnabled([NSUserDefaults standardUserDefaults]);
}
+ (NSString *)spoofedDeviceModel {
if (![self isEnabled]) {
return nil;
}
NSInteger profileId = [[NSUserDefaults standardUserDefaults]
integerForKey:kDeviceSpoofSelectedProfileId];
// Profile ID 0 = real device
if (profileId == 0) {
return nil;
}
// Profile ID 100 = custom
if (profileId == 100) {
NSString *custom = [[NSUserDefaults standardUserDefaults]
stringForKey:kDeviceSpoofCustomDeviceModel];
if (custom.length > 0) {
return custom;
}
return nil;
}
// Preset profiles
NSDictionary<NSNumber *, NSString *> *profiles = @{
@1 : @"iPhone 14 Pro",
@2 : @"iPhone 15 Pro Max",
@3 : @"Samsung SM-S918B",
@4 : @"Google Pixel 8 Pro",
@5 : @"PC 64bit",
@6 : @"MacBook Pro",
@7 : @"Web",
@8 : @"HUAWEI MNA-LX9",
@9 : @"Xiaomi 2311DRK48G"
};
return profiles[@(profileId)];
NSString *deviceModel = nil;
NSString *systemVersion = nil;
DeviceSpoofResolveValues([NSUserDefaults standardUserDefaults], &deviceModel,
&systemVersion);
return deviceModel;
}
+ (NSString *)spoofedSystemVersion {
if (![self isEnabled]) {
return nil;
}
NSInteger profileId = [[NSUserDefaults standardUserDefaults]
integerForKey:kDeviceSpoofSelectedProfileId];
// Profile ID 0 = real device
if (profileId == 0) {
return nil;
}
// Profile ID 100 = custom
if (profileId == 100) {
NSString *custom = [[NSUserDefaults standardUserDefaults]
stringForKey:kDeviceSpoofCustomSystemVersion];
if (custom.length > 0) {
return custom;
}
return nil;
}
// Preset profiles
NSDictionary<NSNumber *, NSString *> *versions = @{
@1 : @"iOS 17.2",
@2 : @"iOS 17.4",
@3 : @"Android 14",
@4 : @"Android 14",
@5 : @"Windows 11",
@6 : @"macOS 14.3",
@7 : @"Chrome 121",
@8 : @"HarmonyOS 4.0",
@9 : @"Android 14"
};
return versions[@(profileId)];
NSString *deviceModel = nil;
NSString *systemVersion = nil;
DeviceSpoofResolveValues([NSUserDefaults standardUserDefaults], &deviceModel,
&systemVersion);
return systemVersion;
}
@end
@@ -41,10 +41,20 @@ public final class DeviceSpoofManager {
private enum Keys {
static let isEnabled = "DeviceSpoof.isEnabled"
static let hasExplicitConfiguration = "DeviceSpoof.hasExplicitConfiguration"
static let selectedProfileId = "DeviceSpoof.selectedProfileId"
static let customDeviceModel = "DeviceSpoof.customDeviceModel"
static let customSystemVersion = "DeviceSpoof.customSystemVersion"
}
private struct ResolvedConfiguration {
let isEnabled: Bool
let selectedProfileId: Int
let customDeviceModel: String
let customSystemVersion: String
}
private static let validProfileIds = Set(profiles.map { $0.id })
private let defaults = UserDefaults.standard
@@ -52,18 +62,34 @@ public final class DeviceSpoofManager {
/// Whether device spoofing is enabled
public var isEnabled: Bool {
get { defaults.bool(forKey: Keys.isEnabled) }
get {
let configuration = resolvedConfiguration()
return configuration.isEnabled
}
set {
defaults.set(newValue, forKey: Keys.isEnabled)
notifyChanged()
}
}
/// Whether the current spoofing configuration was explicitly set by the user
public var hasExplicitConfiguration: Bool {
get { defaults.bool(forKey: Keys.hasExplicitConfiguration) }
set {
defaults.set(newValue, forKey: Keys.hasExplicitConfiguration)
notifyChanged()
}
}
/// Selected profile ID (0 = real device, 100 = custom)
public var selectedProfileId: Int {
get { defaults.integer(forKey: Keys.selectedProfileId) }
get {
sanitizeStoredConfiguration()
return defaults.integer(forKey: Keys.selectedProfileId)
}
set {
defaults.set(newValue, forKey: Keys.selectedProfileId)
sanitizeStoredConfiguration()
notifyChanged()
}
}
@@ -90,15 +116,19 @@ public final class DeviceSpoofManager {
/// Get the currently effective device model
public var effectiveDeviceModel: String? {
guard isEnabled else { return nil }
if selectedProfileId == 100 {
// Custom profile
let custom = customDeviceModel.trimmingCharacters(in: .whitespacesAndNewlines)
return custom.isEmpty ? nil : custom
let configuration = resolvedConfiguration()
guard configuration.isEnabled else {
return nil
}
if let profile = Self.profiles.first(where: { $0.id == selectedProfileId }), profile.id != 0 {
if configuration.selectedProfileId == 100 {
guard !configuration.customDeviceModel.isEmpty, !configuration.customSystemVersion.isEmpty else {
return nil
}
return configuration.customDeviceModel
}
if let profile = Self.profiles.first(where: { $0.id == configuration.selectedProfileId }), profile.id != 0 {
return profile.deviceModel.isEmpty ? nil : profile.deviceModel
}
@@ -107,15 +137,19 @@ public final class DeviceSpoofManager {
/// Get the currently effective system version
public var effectiveSystemVersion: String? {
guard isEnabled else { return nil }
if selectedProfileId == 100 {
// Custom profile
let custom = customSystemVersion.trimmingCharacters(in: .whitespacesAndNewlines)
return custom.isEmpty ? nil : custom
let configuration = resolvedConfiguration()
guard configuration.isEnabled else {
return nil
}
if let profile = Self.profiles.first(where: { $0.id == selectedProfileId }), profile.id != 0 {
if configuration.selectedProfileId == 100 {
guard !configuration.customDeviceModel.isEmpty, !configuration.customSystemVersion.isEmpty else {
return nil
}
return configuration.customSystemVersion
}
if let profile = Self.profiles.first(where: { $0.id == configuration.selectedProfileId }), profile.id != 0 {
return profile.systemVersion.isEmpty ? nil : profile.systemVersion
}
@@ -134,8 +168,40 @@ public final class DeviceSpoofManager {
private func notifyChanged() {
NotificationCenter.default.post(name: Self.settingsChangedNotification, object: nil)
}
private func sanitizeStoredConfiguration() {
let rawSelectedProfileId = defaults.integer(forKey: Keys.selectedProfileId)
if !Self.validProfileIds.contains(rawSelectedProfileId) {
defaults.set(0, forKey: Keys.selectedProfileId)
}
let rawCustomDeviceModel = defaults.string(forKey: Keys.customDeviceModel) ?? ""
let trimmedCustomDeviceModel = rawCustomDeviceModel.trimmingCharacters(in: .whitespacesAndNewlines)
if rawCustomDeviceModel != trimmedCustomDeviceModel {
defaults.set(trimmedCustomDeviceModel, forKey: Keys.customDeviceModel)
}
let rawCustomSystemVersion = defaults.string(forKey: Keys.customSystemVersion) ?? ""
let trimmedCustomSystemVersion = rawCustomSystemVersion.trimmingCharacters(in: .whitespacesAndNewlines)
if rawCustomSystemVersion != trimmedCustomSystemVersion {
defaults.set(trimmedCustomSystemVersion, forKey: Keys.customSystemVersion)
}
}
private func resolvedConfiguration() -> ResolvedConfiguration {
sanitizeStoredConfiguration()
return ResolvedConfiguration(
isEnabled: defaults.bool(forKey: Keys.hasExplicitConfiguration) && defaults.bool(forKey: Keys.isEnabled),
selectedProfileId: defaults.integer(forKey: Keys.selectedProfileId),
customDeviceModel: defaults.string(forKey: Keys.customDeviceModel) ?? "",
customSystemVersion: defaults.string(forKey: Keys.customSystemVersion) ?? ""
)
}
// MARK: - Init
private init() {}
private init() {
sanitizeStoredConfiguration()
}
}
@@ -244,13 +244,15 @@ func _internal_createForumChannelTopic(postbox: Postbox, network: Network, state
topicId = nil
for update in result.allUpdates {
switch update {
case let .updateNewChannelMessage(message, _, _):
case let .updateNewChannelMessage(updateNewChannelMessageData):
let (message, _, _) = (updateNewChannelMessageData.message, updateNewChannelMessageData.pts, updateNewChannelMessageData.ptsCount)
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peer.isForum) {
if case let .Id(id) = message.id {
topicId = Int64(id.id)
}
}
case let .updateNewMessage(message, _, _):
case let .updateNewMessage(updateNewMessageData):
let (message, _, _) = (updateNewMessageData.message, updateNewMessageData.pts, updateNewMessageData.ptsCount)
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peer.isForum) {
if case let .Id(id) = message.id {
topicId = Int64(id.id)
@@ -489,7 +491,7 @@ func _internal_setForumChannelPinnedTopics(account: Account, id: EnginePeer.Id,
return account.postbox.transaction { transaction -> [Api.InputDialogPeer] in
transaction.setPeerPinnedThreads(peerId: id, threadIds: threadIds)
return threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer).flatMap({ .inputDialogPeer(peer: $0) }) }
return threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer).flatMap({ .inputDialogPeer(.init(peer: $0)) }) }
}
|> castError(SetForumChannelTopicPinnedError.self)
|> mapToSignal { inputPeers -> Signal<Never, SetForumChannelTopicPinnedError> in
@@ -773,7 +775,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
}
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
switch result {
case .savedDialogs(let dialogs, let messages, let chats, let users), .savedDialogsSlice(_, let dialogs, let messages, let chats, let users):
case let .savedDialogs(savedDialogsData):
let (dialogs, messages, chats, users) = (savedDialogsData.dialogs, savedDialogsData.messages, savedDialogsData.chats, savedDialogsData.users)
var items: [LoadMessageHistoryThreadsResult.Item] = []
var pinnedIds: [Int64] = []
@@ -785,7 +788,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
for dialog in dialogs {
switch dialog {
case let .savedDialog(flags, peer, topMessage):
case let .savedDialog(savedDialogData):
let (flags, peer, topMessage) = (savedDialogData.flags, savedDialogData.peer, savedDialogData.topMessage)
if (flags & (1 << 2)) != 0 {
pinnedIds.append(peer.peerId.toInt64())
}
@@ -843,7 +847,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
index: topicIndex,
threadPeer: threadPeer
))
case let .monoForumDialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadReactionsCount, _):
case let .monoForumDialog(monoForumDialogData):
let (flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadReactionsCount) = (monoForumDialogData.flags, monoForumDialogData.peer, monoForumDialogData.topMessage, monoForumDialogData.readInboxMaxId, monoForumDialogData.readOutboxMaxId, monoForumDialogData.unreadCount, monoForumDialogData.unreadReactionsCount)
let isMarkedUnread = (flags & (1 << 3)) != 0
let data = MessageHistoryThreadData(
creationDate: 0,
@@ -918,6 +923,163 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex)
return .single(LoadMessageHistoryThreadsResult(
peerId: peerId,
items: items,
messages: addedMessages,
pinnedThreadIds: pinnedThreadIds,
combinedState: combinedState,
users: users,
chats: chats
))
case let .savedDialogsSlice(savedDialogsSliceData):
let (dialogs, messages, chats, users) = (savedDialogsSliceData.dialogs, savedDialogsSliceData.messages, savedDialogsSliceData.chats, savedDialogsSliceData.users)
var items: [LoadMessageHistoryThreadsResult.Item] = []
var pinnedIds: [Int64] = []
let addedMessages = messages.compactMap { message -> StoreMessage? in
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: false)
}
var minIndex: StoredPeerThreadCombinedState.Index?
for dialog in dialogs {
switch dialog {
case let .savedDialog(savedDialogData):
let (flags, peer, topMessage) = (savedDialogData.flags, savedDialogData.peer, savedDialogData.topMessage)
if (flags & (1 << 2)) != 0 {
pinnedIds.append(peer.peerId.toInt64())
}
let data = MessageHistoryThreadData(
creationDate: 0,
isOwnedByMe: true,
author: peer.peerId,
info: EngineMessageHistoryThread.Info(
title: "",
icon: nil,
iconColor: 0
),
incomingUnreadCount: 0,
isMarkedUnread: false,
maxIncomingReadId: 0,
maxKnownMessageId: topMessage,
maxOutgoingReadId: 0,
isClosed: false,
isHidden: false,
notificationSettings: TelegramPeerNotificationSettings.defaultSettings,
isMessageFeeRemoved: false
)
var topTimestamp: Int32 = 1
for message in addedMessages {
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
topTimestamp = max(topTimestamp, message.timestamp)
}
}
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
if let minIndexValue = minIndex {
if topicIndex < minIndexValue {
minIndex = topicIndex
}
} else {
minIndex = topicIndex
}
var threadPeer: Peer?
for user in users {
if user.peerId == peer.peerId {
threadPeer = TelegramUser(user: user)
break
}
}
items.append(LoadMessageHistoryThreadsResult.Item(
threadId: peer.peerId.toInt64(),
data: data,
topMessage: topMessage,
unreadMentionsCount: 0,
unreadReactionsCount: 0,
index: topicIndex,
threadPeer: threadPeer
))
case let .monoForumDialog(monoForumDialogData):
let (flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadReactionsCount) = (monoForumDialogData.flags, monoForumDialogData.peer, monoForumDialogData.topMessage, monoForumDialogData.readInboxMaxId, monoForumDialogData.readOutboxMaxId, monoForumDialogData.unreadCount, monoForumDialogData.unreadReactionsCount)
let isMarkedUnread = (flags & (1 << 3)) != 0
let data = MessageHistoryThreadData(
creationDate: 0,
isOwnedByMe: true,
author: accountPeerId,
info: EngineMessageHistoryThread.Info(
title: "",
icon: nil,
iconColor: 0
),
incomingUnreadCount: unreadCount,
isMarkedUnread: isMarkedUnread,
maxIncomingReadId: readInboxMaxId,
maxKnownMessageId: topMessage,
maxOutgoingReadId: readOutboxMaxId,
isClosed: false,
isHidden: false,
notificationSettings: TelegramPeerNotificationSettings.defaultSettings,
isMessageFeeRemoved: (flags & (1 << 4)) != 0
)
var topTimestamp: Int32 = 1
for message in addedMessages {
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
topTimestamp = max(topTimestamp, message.timestamp)
}
}
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
if let minIndexValue = minIndex {
if topicIndex < minIndexValue {
minIndex = topicIndex
}
} else {
minIndex = topicIndex
}
var threadPeer: Peer?
for user in users {
if user.peerId == peer.peerId {
threadPeer = TelegramUser(user: user)
break
}
}
items.append(LoadMessageHistoryThreadsResult.Item(
threadId: peer.peerId.toInt64(),
data: data,
topMessage: topMessage,
unreadMentionsCount: 0,
unreadReactionsCount: unreadReactionsCount,
index: topicIndex,
threadPeer: threadPeer
))
}
}
var pinnedThreadIds: [Int64]?
if offsetIndex == nil {
pinnedThreadIds = pinnedIds
}
var nextIndex: StoredPeerThreadCombinedState.Index
if dialogs.count != 0 {
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
} else {
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
}
if let offsetIndex = offsetIndex, nextIndex == offsetIndex {
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
}
let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex)
return .single(LoadMessageHistoryThreadsResult(
peerId: peerId,
items: items,
@@ -981,7 +1143,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
}
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
switch result {
case let .forumTopics(_, _, topics, messages, chats, users, pts):
case let .forumTopics(forumTopicsData):
let (topics, messages, chats, users, pts) = (forumTopicsData.topics, forumTopicsData.messages, forumTopicsData.chats, forumTopicsData.users, forumTopicsData.pts)
var items: [LoadMessageHistoryThreadsResult.Item] = []
var pinnedIds: [Int64] = []
@@ -994,7 +1157,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
for topic in topics {
switch topic {
case let .forumTopic(flags, id, date, peer, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
case let .forumTopic(forumTopicData):
let (flags, id, date, peer, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft) = (forumTopicData.flags, forumTopicData.id, forumTopicData.date, forumTopicData.peer, forumTopicData.title, forumTopicData.iconColor, forumTopicData.iconEmojiId, forumTopicData.topMessage, forumTopicData.readInboxMaxId, forumTopicData.readOutboxMaxId, forumTopicData.unreadCount, forumTopicData.unreadMentionsCount, forumTopicData.unreadReactionsCount, forumTopicData.fromId, forumTopicData.notifySettings, forumTopicData.draft)
let _ = draft
let _ = peer
@@ -1167,7 +1331,7 @@ func _internal_forumChannelTopicNotificationExceptions(account: Account, id: Eng
return .single([])
}
return account.network.request(Api.functions.account.getNotifyExceptions(flags: 1 << 0, peer: Api.InputNotifyPeer.inputNotifyPeer(peer: inputPeer)))
return account.network.request(Api.functions.account.getNotifyExceptions(flags: 1 << 0, peer: Api.InputNotifyPeer.inputNotifyPeer(.init(peer: inputPeer))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
@@ -1180,9 +1344,11 @@ func _internal_forumChannelTopicNotificationExceptions(account: Account, id: Eng
var list: [(threadId: Int64, notificationSettings: EnginePeer.NotificationSettings)] = []
for update in result.allUpdates {
switch update {
case let .updateNotifySettings(peer, notifySettings):
case let .updateNotifySettings(updateNotifySettingsData):
let (peer, notifySettings) = (updateNotifySettingsData.peer, updateNotifySettingsData.notifySettings)
switch peer {
case let .notifyForumTopic(_, topMsgId):
case let .notifyForumTopic(notifyForumTopicData):
let topMsgId = notifyForumTopicData.topMsgId
list.append((Int64(topMsgId), EnginePeer.NotificationSettings(TelegramPeerNotificationSettings(apiSettings: notifySettings))))
default:
break
@@ -1199,10 +1365,12 @@ func _internal_forumChannelTopicNotificationExceptions(account: Account, id: Eng
var infoMapping: [Int64: EngineMessageHistoryThread.Info] = [:]
switch result {
case let .forumTopics(_, _, topics, _, _, _, _):
case let .forumTopics(forumTopicsData):
let topics = forumTopicsData.topics
for topic in topics {
switch topic {
case let .forumTopic(_, id, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
case let .forumTopic(forumTopicData):
let (id, title, iconColor, iconEmojiId) = (forumTopicData.id, forumTopicData.title, forumTopicData.iconColor, forumTopicData.iconEmojiId)
infoMapping[Int64(id)] = EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor)
case .forumTopicDeleted:
break
@@ -35,9 +35,11 @@ public func actualizedPeer(accountPeerId: PeerId, postbox: Postbox, network: Net
if let result = result {
let chats: [Api.Chat]
switch result {
case let .chats(apiChats):
case let .chats(chatsData):
let apiChats = chatsData.chats
chats = apiChats
case let .chatsSlice(_, apiChats):
case let .chatsSlice(chatsSliceData):
let apiChats = chatsSliceData.chats
chats = apiChats
}
let parsedPeersValue = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
@@ -14,13 +14,13 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
} else {
let messageSignal: Signal<Api.messages.Messages?, NoError>?
if messageId.peerId.namespace == Namespaces.Peer.CloudUser || messageId.peerId.namespace == Namespaces.Peer.CloudGroup {
messageSignal = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)]))
messageSignal = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(.init(id: messageId.id))]))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
return .single(nil)
}
} else if messageId.peerId.namespace == Namespaces.Peer.CloudChannel, let channelPeer = transaction.getPeer(messageId.peerId), let inputChannel = apiInputChannel(channelPeer) {
messageSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: [Api.InputMessage.inputMessageID(id: messageId.id)]))
messageSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: [Api.InputMessage.inputMessageID(.init(id: messageId.id))]))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
return .single(nil)
@@ -35,11 +35,14 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
if let result = result {
let apiUsers: [Api.User]
switch result {
case let .messages(_, _, _, users):
case let .messages(messagesData):
let users = messagesData.users
apiUsers = users
case let .messagesSlice(_, _, _, _, _, _, _, _, users):
case let .messagesSlice(messagesSliceData):
let users = messagesSliceData.users
apiUsers = users
case let .channelMessages(_, _, _, _, _, _, _, users):
case let .channelMessages(channelMessagesData):
let users = channelMessagesData.users
apiUsers = users
case .messagesNotModified:
apiUsers = []
@@ -28,7 +28,8 @@ public func requestUpdatesXml(account: Account, source: String) -> Signal<Data,
|> castError(InternalUpdaterError.self)
|> mapToSignal { result in
switch result {
case let .channelMessages(_, _, _, _, apiMessages, _, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.chats, channelMessagesData.users)
if let apiMessage = apiMessages.first, let storeMessage = StoreMessage(apiMessage: apiMessage, accountPeerId: account.peerId, peerIsForum: peer.isForum) {
var peers: [PeerId: Peer] = [:]
@@ -93,13 +94,14 @@ public func downloadAppUpdate(account: Account, source: String, messageId: Int32
}
|> mapToSignal { peer in
if let peer = peer, let inputChannel = apiInputChannel(peer) {
return account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: [Api.InputMessage.inputMessageID(id: messageId)]))
return account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: [Api.InputMessage.inputMessageID(.init(id: messageId))]))
|> retryRequest
|> castError(InternalUpdaterError.self)
|> mapToSignal { messages in
switch messages {
case let .channelMessages(_, _, _, _, apiMessages, _, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.chats, channelMessagesData.users)
var peers: [PeerId: Peer] = [:]
for chat in apiChats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
@@ -110,7 +112,7 @@ public func downloadAppUpdate(account: Account, source: String, messageId: Int32
let telegramUser = TelegramUser(user: user)
peers[telegramUser.id] = telegramUser
}
let messageAndFile:(Message, TelegramMediaFile)? = apiMessages.compactMap { value in
return StoreMessage(apiMessage: value, accountPeerId: account.peerId, peerIsForum: peer.isForum)
}.compactMap { value in
@@ -192,7 +194,8 @@ public func requestApplicationIcons(engine: TelegramEngine, source: String = "ma
|> mapToSignal { result in
switch result {
case let .channelMessages(_, _, _, _, apiMessages, _, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.chats, channelMessagesData.users)
var icons: [TelegramApplicationIcons.Icon] = []
for apiMessage in apiMessages.reversed() {
if let storeMessage = StoreMessage(apiMessage: apiMessage, accountPeerId: engine.account.peerId, peerIsForum: peer.isForum) {
@@ -225,7 +225,8 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
} else {
if let result = (boxedResponse as! BoxedMessage).body as? Api.upload.WebFile {
switch result {
case .webFile(_, _, _, _, let bytes):
case let .webFile(webFileData):
let bytes = webFileData.bytes
subscriber.putNext(bytes.makeData())
}
subscriber.putCompletion()
@@ -278,7 +279,8 @@ class Download: NSObject, MTRequestMessageServiceDelegate {
} else {
if let result = (boxedResponse as! BoxedMessage).body as? Api.upload.File {
switch result {
case let .file(_, _, bytes):
case let .file(fileData):
let bytes = fileData.bytes
subscriber.putNext(bytes.makeData())
case .fileCdnRedirect:
break
@@ -1,3 +1,4 @@
import SGSimpleSettings
import Foundation
import Postbox
import SwiftSignalKit
@@ -388,9 +389,9 @@ private final class FetchImpl {
}
if isStory {
self.defaultPartSize = 512 * 1024
self.defaultPartSize = getSGDownloadPartSize(512 * 1024, fileSize: self.size)
} else {
self.defaultPartSize = 128 * 1024
self.defaultPartSize = getSGDownloadPartSize(128 * 1024, fileSize: self.size)
}
self.cdnPartSize = 128 * 1024
@@ -440,7 +441,7 @@ private final class FetchImpl {
maxPartSize: 1 * 1024 * 1024,
partAlignment: 4 * 1024,
partDivision: 1 * 1024 * 1024,
maxPendingParts: 6,
maxPendingParts: getSGMaxPendingParts(6),
decryptionState: decryptionState
))
}
@@ -696,7 +697,7 @@ private final class FetchImpl {
maxPartSize: self.cdnPartSize * 2,
partAlignment: self.cdnPartSize,
partDivision: 1 * 1024 * 1024,
maxPendingParts: 6,
maxPendingParts: getSGMaxPendingParts(6),
decryptionState: nil
))
self.update()
@@ -745,7 +746,7 @@ private final class FetchImpl {
maxPartSize: self.defaultPartSize,
partAlignment: 4 * 1024,
partDivision: 1 * 1024 * 1024,
maxPendingParts: 6,
maxPendingParts: getSGMaxPendingParts(6),
decryptionState: nil
))
@@ -801,7 +802,8 @@ private final class FetchImpl {
)
|> map { result -> FilePartResult in
switch result {
case let .cdnFile(bytes):
case let .cdnFile(cdnFileData):
let bytes = cdnFileData.bytes
if bytes.size == 0 {
return .data(data: Data(), verifyPartHashData: nil)
} else {
@@ -819,7 +821,8 @@ private final class FetchImpl {
verifyPartHashData: VerifyPartHashData(fetchRange: fetchRange, fetchedData: fetchedData)
)
}
case let .cdnFileReuploadNeeded(requestToken):
case let .cdnFileReuploadNeeded(cdnFileReuploadNeededData):
let requestToken = cdnFileReuploadNeededData.requestToken
return .cdnRefresh(cdnData: cdnData, refreshToken: requestToken.makeData())
}
}
@@ -858,9 +861,11 @@ private final class FetchImpl {
)
|> map { result -> FilePartResult in
switch result {
case let .file(_, _, bytes):
case let .file(fileData):
let bytes = fileData.bytes
return .data(data: bytes.makeData(), verifyPartHashData: nil)
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv, fileHashes):
case let .fileCdnRedirect(fileCdnRedirectData):
let (dcId, fileToken, encryptionKey, encryptionIv, fileHashes) = (fileCdnRedirectData.dcId, fileCdnRedirectData.fileToken, fileCdnRedirectData.encryptionKey, fileCdnRedirectData.encryptionIv, fileCdnRedirectData.fileHashes)
let _ = fileHashes
return .cdnRedirect(CdnData(
id: Int(dcId),
@@ -931,7 +936,7 @@ private final class FetchImpl {
maxPartSize: self.cdnPartSize * 2,
partAlignment: self.cdnPartSize,
partDivision: 1 * 1024 * 1024,
maxPendingParts: 6,
maxPendingParts: getSGMaxPendingParts(6),
decryptionState: nil
))
case let .cdnRefresh(cdnData, refreshToken):
@@ -995,7 +1000,8 @@ private final class FetchImpl {
var filledRange = RangeSet<Int64>()
for hashItem in result {
switch hashItem {
case let .fileHash(offset, limit, hash):
case let .fileHash(fileHashData):
let (offset, limit, hash) = (fileHashData.offset, fileHashData.limit, fileHashData.hash)
let rangeValue: Range<Int64> = offset ..< (offset + Int64(limit))
filledRange.formUnion(RangeSet<Int64>(rangeValue))
state.hashRanges[rangeValue.lowerBound] = HashRangeData(
@@ -197,7 +197,8 @@ private final class MultipartCdnHashSource {
var parsedPartHashes: [Int64: Data] = [:]
for part in partHashes {
switch part {
case let .fileHash(offset, limit, bytes):
case let .fileHash(fileHashData):
let (offset, limit, bytes) = (fileHashData.offset, fileHashData.limit, fileHashData.hash)
assert(limit == 128 * 1024)
parsedPartHashes[offset] = bytes.makeData()
}
@@ -361,17 +362,20 @@ private enum MultipartFetchSource {
}
|> mapToSignal { result, info -> Signal<(Data, NetworkResponseInfo), MultipartFetchDownloadError> in
switch result {
case let .file(_, _, bytes):
case let .file(fileData):
let bytes = fileData.bytes
var resultData = bytes.makeData()
if resultData.count > Int(limit) {
resultData.count = Int(limit)
}
return .single((resultData, info))
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv, partHashes):
case let .fileCdnRedirect(fileCdnRedirectData):
let (dcId, fileToken, encryptionKey, encryptionIv, partHashes) = (fileCdnRedirectData.dcId, fileCdnRedirectData.fileToken, fileCdnRedirectData.encryptionKey, fileCdnRedirectData.encryptionIv, fileCdnRedirectData.fileHashes)
var parsedPartHashes: [Int64: Data] = [:]
for part in partHashes {
switch part {
case let .fileHash(offset, limit, bytes):
case let .fileHash(fileHashData):
let (offset, limit, bytes) = (fileHashData.offset, fileHashData.limit, fileHashData.hash)
assert(limit == 128 * 1024)
parsedPartHashes[offset] = bytes.makeData()
}
@@ -395,7 +399,8 @@ private enum MultipartFetchSource {
}
|> mapToSignal { result, info -> Signal<(Data, NetworkResponseInfo), MultipartFetchDownloadError> in
switch result {
case let .webFile(_, _, _, _, bytes):
case let .webFile(webFileData):
let bytes = webFileData.bytes
var resultData = bytes.makeData()
if resultData.count > Int(limit) {
resultData.count = Int(limit)
@@ -418,9 +423,11 @@ private enum MultipartFetchSource {
}
|> mapToSignal { result, info -> Signal<(Data, NetworkResponseInfo), MultipartFetchDownloadError> in
switch result {
case let .cdnFileReuploadNeeded(token):
case let .cdnFileReuploadNeeded(cdnFileReuploadNeededData):
let token = cdnFileReuploadNeededData.requestToken
return .fail(.reuploadToCdn(masterDatacenterId: masterDatacenterId, token: token.makeData()))
case let .cdnFile(bytes):
case let .cdnFile(cdnFileData):
let bytes = cdnFileData.bytes
if bytes.size == 0 {
return .single((bytes.makeData(), info))
} else {
@@ -1,3 +1,4 @@
import SGSimpleSettings
import Foundation
import Postbox
import TelegramApi
@@ -479,7 +480,8 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
}
}
let manager = MultipartUploadManager(headerSize: headerSize, data: dataSignal, encryptionKey: encryptionKey, hintFileSize: hintFileSize, hintFileIsLarge: hintFileIsLarge, forceNoBigParts: forceNoBigParts, useLargerParts: useLargerParts, increaseParallelParts: increaseParallelParts, uploadPart: { part in
// TODO(swiftgram): Change other variables for uploadSpeedBoost
let manager = MultipartUploadManager(headerSize: headerSize, data: dataSignal, encryptionKey: encryptionKey, hintFileSize: hintFileSize, hintFileIsLarge: hintFileIsLarge, forceNoBigParts: forceNoBigParts, useLargerParts: useLargerParts || SGSimpleSettings.shared.uploadSpeedBoost, increaseParallelParts: increaseParallelParts || SGSimpleSettings.shared.uploadSpeedBoost, uploadPart: { part in
switch uploadInterface {
case let .download(download):
return download.uploadPart(fileId: part.fileId, index: part.index, data: part.data, asBigPart: part.bigPart, bigTotalParts: part.bigTotalParts, useCompression: useCompression, onFloodWaitError: onFloodWaitError)
@@ -505,18 +507,18 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
})
}
if let _ = result.bigTotalParts {
let inputFile = Api.InputEncryptedFile.inputEncryptedFileBigUploaded(id: result.id, parts: result.partCount, keyFingerprint: fingerprint)
let inputFile = Api.InputEncryptedFile.inputEncryptedFileBigUploaded(.init(id: result.id, parts: result.partCount, keyFingerprint: fingerprint))
subscriber.putNext(.inputSecretFile(inputFile, result.size, encryptionKey))
} else {
let inputFile = Api.InputEncryptedFile.inputEncryptedFileUploaded(id: result.id, parts: result.partCount, md5Checksum: result.md5Digest, keyFingerprint: fingerprint)
let inputFile = Api.InputEncryptedFile.inputEncryptedFileUploaded(.init(id: result.id, parts: result.partCount, md5Checksum: result.md5Digest, keyFingerprint: fingerprint))
subscriber.putNext(.inputSecretFile(inputFile, result.size, encryptionKey))
}
} else {
if let _ = result.bigTotalParts {
let inputFile = Api.InputFile.inputFileBig(id: result.id, parts: result.partCount, name: "file.jpg")
let inputFile = Api.InputFile.inputFileBig(.init(id: result.id, parts: result.partCount, name: "file.jpg"))
subscriber.putNext(.inputFile(inputFile))
} else {
let inputFile = Api.InputFile.inputFile(id: result.id, parts: result.partCount, name: "file.jpg", md5Checksum: result.md5Digest)
let inputFile = Api.InputFile.inputFile(.init(id: result.id, parts: result.partCount, name: "file.jpg", md5Checksum: result.md5Digest))
subscriber.putNext(.inputFile(inputFile))
}
}
@@ -1,3 +1,6 @@
// MARK: Swiftgram
import SGSimpleSettings
import Foundation
import Postbox
import TelegramApi
@@ -504,7 +507,6 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
}
let useTempAuthKeys: Bool = true
let context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys)
if let networkSettings = networkSettings {
@@ -899,10 +901,12 @@ public final class Network: NSObject, MTRequestMessageServiceDelegate {
let array = NSMutableArray()
if let result = result {
switch result {
case let .cdnConfig(publicKeys):
case let .cdnConfig(cdnConfigData):
let publicKeys = cdnConfigData.publicKeys
for key in publicKeys {
switch key {
case let .cdnPublicKey(dcId, publicKey):
case let .cdnPublicKey(cdnPublicKeyData):
let (dcId, publicKey) = (cdnPublicKeyData.dcId, cdnPublicKeyData.publicKey)
if id == Int(dcId) {
let dict = NSMutableDictionary()
dict["key"] = publicKey
@@ -964,7 +964,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
buttons.append(button)
} else if case let .switchInline(samePeer, query, peerTypes) = button.action, sourceSentViaBot {
let samePeer = samePeer && peerId == sourceMessage.id.peerId
let updatedButton = ReplyMarkupButton(title: button.titleWhenForwarded ?? button.title, titleWhenForwarded: button.titleWhenForwarded, action: .switchInline(samePeer: samePeer, query: query, peerTypes: peerTypes))
let updatedButton = ReplyMarkupButton(title: button.titleWhenForwarded ?? button.title, titleWhenForwarded: button.titleWhenForwarded, action: .switchInline(samePeer: samePeer, query: query, peerTypes: peerTypes), style: button.style)
buttons.append(updatedButton)
} else {
rows.removeAll()
@@ -103,7 +103,7 @@ func messageContentToUpload(accountPeerId: PeerId, network: Network, postbox: Po
guard let inputPeer = transaction.getPeer(media.storyId.peerId).flatMap(apiInputPeer) else {
return .progress(PendingMessageUploadedContentProgress(progress: 0.0))
}
return .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaStory(peer: inputPeer, id: media.storyId.id), ""), reuploadInfo: nil, cacheReferenceKey: nil))
return .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaStory(.init(peer: inputPeer, id: media.storyId.id)), ""), reuploadInfo: nil, cacheReferenceKey: nil))
}
|> castError(PendingMessageUploadError.self), .text)
} else if let media = media.first as? TelegramMediaWebpage, case let .Loaded(content) = media.content {
@@ -119,7 +119,7 @@ func messageContentToUpload(accountPeerId: PeerId, network: Network, postbox: Po
}
}
}
return .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaWebPage(flags: flags, url: content.url), text), reuploadInfo: nil, cacheReferenceKey: nil))
return .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaWebPage(.init(flags: flags, url: content.url)), text), reuploadInfo: nil, cacheReferenceKey: nil))
}
|> castError(PendingMessageUploadError.self), .text)
} else if let media = media.first, let mediaResult = mediaContentToUpload(accountPeerId: accountPeerId, network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: revalidationContext, forceReupload: forceReupload, isGrouped: isGrouped, passFetchProgress: passFetchProgress, forceNoBigParts: forceNoBigParts, peerId: peerId, media: media, text: text, autoremoveMessageAttribute: autoremoveMessageAttribute, autoclearMessageAttribute: autoclearMessageAttribute, messageId: messageId, attributes: attributes, mediaReference: mediaReference, explicitPartialReference: explicitPartialReference) {
@@ -165,12 +165,12 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
let normalizedProgress = currentProgress / Float(results.count)
if media.count == results.count {
return .content(PendingMessageUploadedContentAndReuploadInfo(
content: .media(.inputMediaPaidMedia(
content: .media(.inputMediaPaidMedia(.init(
flags: 0,
starsAmount: paidContent.amount,
extendedMedia: media,
payload: nil
), text),
)), text),
reuploadInfo: nil,
cacheReferenceKey: nil
))
@@ -181,10 +181,10 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
}
if let image = media as? TelegramMediaImage, let largest = largestImageRepresentation(image.representations) {
if peerId.namespace == Namespaces.Peer.SecretChat, let resource = largest.resource as? SecretFileMediaResource {
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .secretMedia(.inputEncryptedFile(id: resource.fileId, accessHash: resource.accessHash), resource.decryptedSize, resource.key), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .secretMedia(.inputEncryptedFile(.init(id: resource.fileId, accessHash: resource.accessHash)), resource.decryptedSize, resource.key), reuploadInfo: nil, cacheReferenceKey: nil)))
}
if peerId.namespace != Namespaces.Peer.SecretChat, let reference = image.reference, case let .cloud(id, accessHash, maybeFileReference) = reference, let fileReference = maybeFileReference {
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference)), ttlSeconds: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaPhoto(.init(flags: 0, id: Api.InputPhoto.inputPhoto(.init(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference))), ttlSeconds: nil)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else {
return uploadedMediaImageContent(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, forceReupload: forceReupload, isGrouped: isGrouped, peerId: peerId, image: image, messageId: messageId, text: text, attributes: attributes, autoremoveMessageAttribute: autoremoveMessageAttribute, autoclearMessageAttribute: autoclearMessageAttribute, auxiliaryMethods: auxiliaryMethods)
}
@@ -244,7 +244,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
flags |= 1 << 4
}
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: reference)), videoCover: nil, videoTimestamp: videoTimestamp, ttlSeconds: nil, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(.init(flags: flags, id: Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: reference))), videoCover: nil, videoTimestamp: videoTimestamp, ttlSeconds: nil, query: nil)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else {
return .fail(.generic)
}
@@ -265,13 +265,13 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
}
}
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, videoTimestamp: videoTimestamp, ttlSeconds: nil, query: emojiSearchQuery), text), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(.init(flags: flags, id: Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data()))), videoCover: nil, videoTimestamp: videoTimestamp, ttlSeconds: nil, query: emojiSearchQuery)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
}
} else {
return uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, forceReupload: forceReupload, isGrouped: isGrouped, isPaid: false, passFetchProgress: passFetchProgress, forceNoBigParts: forceNoBigParts, peerId: peerId, messageId: messageId, text: text, attributes: attributes, autoremoveMessageAttribute: autoremoveMessageAttribute, autoclearMessageAttribute: autoclearMessageAttribute, file: file)
}
} else if let contact = media as? TelegramMediaContact {
let input = Api.InputMedia.inputMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName, vcard: contact.vCardData ?? "")
let input = Api.InputMedia.inputMediaContact(.init(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName, vcard: contact.vCardData ?? ""))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(input, text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else if let map = media as? TelegramMediaMap {
let input: Api.InputMedia
@@ -287,11 +287,11 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
geoFlags |= 1 << 0
}
if let liveBroadcastingTimeout = map.liveBroadcastingTimeout {
input = .inputMediaGeoLive(flags: flags, geoPoint: Api.InputGeoPoint.inputGeoPoint(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) })), heading: map.heading, period: liveBroadcastingTimeout, proximityNotificationRadius: map.liveProximityNotificationRadius.flatMap({ Int32($0) }))
input = .inputMediaGeoLive(.init(flags: flags, geoPoint: Api.InputGeoPoint.inputGeoPoint(.init(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) }))), heading: map.heading, period: liveBroadcastingTimeout, proximityNotificationRadius: map.liveProximityNotificationRadius.flatMap({ Int32($0) })))
} else if let venue = map.venue {
input = .inputMediaVenue(geoPoint: Api.InputGeoPoint.inputGeoPoint(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) })), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "", venueType: venue.type ?? "")
input = .inputMediaVenue(.init(geoPoint: Api.InputGeoPoint.inputGeoPoint(.init(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) }))), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "", venueType: venue.type ?? ""))
} else {
input = .inputMediaGeoPoint(geoPoint: Api.InputGeoPoint.inputGeoPoint(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) })))
input = .inputMediaGeoPoint(.init(geoPoint: Api.InputGeoPoint.inputGeoPoint(.init(flags: geoFlags, lat: map.latitude, long: map.longitude, accuracyRadius: map.accuracyRadius.flatMap({ Int32($0) })))))
}
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(input, text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else if let poll = media as? TelegramMediaPoll {
@@ -330,7 +330,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
mappedSolutionEntities = apiTextAttributeEntities(TextEntitiesMessageAttribute(entities: solution.entities), associatedPeers: SimpleDictionary())
pollMediaFlags |= 1 << 1
}
let inputPoll = Api.InputMedia.inputMediaPoll(flags: pollMediaFlags, poll: Api.Poll.poll(id: 0, flags: pollFlags, question: .textWithEntities(text: poll.text, entities: apiEntitiesFromMessageTextEntities(poll.textEntities, associatedPeers: SimpleDictionary())), answers: poll.options.map({ $0.apiOption }), closePeriod: poll.deadlineTimeout, closeDate: nil), correctAnswers: correctAnswers, solution: mappedSolution, solutionEntities: mappedSolutionEntities)
let inputPoll = Api.InputMedia.inputMediaPoll(.init(flags: pollMediaFlags, poll: Api.Poll.poll(.init(id: 0, flags: pollFlags, question: .textWithEntities(.init(text: poll.text, entities: apiEntitiesFromMessageTextEntities(poll.textEntities, associatedPeers: SimpleDictionary()))), answers: poll.options.map({ $0.apiOption }), closePeriod: poll.deadlineTimeout, closeDate: nil)), correctAnswers: correctAnswers, solution: mappedSolution, solutionEntities: mappedSolutionEntities))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(inputPoll, text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else if let todo = media as? TelegramMediaTodo {
var flags: Int32 = 0
@@ -340,7 +340,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
if todo.flags.contains(.othersCanComplete) {
flags |= 1 << 1
}
let inputTodo = Api.InputMedia.inputMediaTodo(todo: .todoList(flags: flags, title: .textWithEntities(text: todo.text, entities: apiEntitiesFromMessageTextEntities(todo.textEntities, associatedPeers: SimpleDictionary())), list: todo.items.map { $0.apiItem }))
let inputTodo = Api.InputMedia.inputMediaTodo(.init(todo: .todoList(.init(flags: flags, title: .textWithEntities(.init(text: todo.text, entities: apiEntitiesFromMessageTextEntities(todo.textEntities, associatedPeers: SimpleDictionary()))), list: todo.items.map { $0.apiItem }))))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(inputTodo, text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else if let dice = media as? TelegramMediaDice {
if let tonAmount = dice.tonAmount {
@@ -351,7 +351,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
return postbox.transaction { transaction -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
let gameInfo = currentEmojiGameInfo(transaction: transaction)
if case let .available(info) = gameInfo {
let inputStakeDice = Api.InputMedia.inputMediaStakeDice(gameHash: info.gameHash, tonAmount: tonAmount, clientSeed: Buffer(buffer: clientSeed))
let inputStakeDice = Api.InputMedia.inputMediaStakeDice(.init(gameHash: info.gameHash, tonAmount: tonAmount, clientSeed: Buffer(buffer: clientSeed)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(inputStakeDice, text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else {
return .fail(.generic)
@@ -360,7 +360,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
|> castError(PendingMessageUploadError.self)
|> switchToLatest
} else {
let inputDice = Api.InputMedia.inputMediaDice(emoticon: dice.emoji)
let inputDice = Api.InputMedia.inputMediaDice(.init(emoticon: dice.emoji))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(inputDice, text), reuploadInfo: nil, cacheReferenceKey: nil)))
}
} else if let webPage = media as? TelegramMediaWebpage, case let .Loaded(content) = webPage.content {
@@ -375,7 +375,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
}
}
}
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaWebPage(flags: flags, url: content.url), text), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaWebPage(.init(flags: flags, url: content.url)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
} else {
return nil
}
@@ -535,7 +535,7 @@ if "".isEmpty {
}
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|> then(
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaPhoto(flags: flags, id: .inputPhoto(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference)), ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: nil)))
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaPhoto(.init(flags: flags, id: .inputPhoto(.init(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference))), ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
)
}
referenceKey = key
@@ -657,7 +657,7 @@ if "".isEmpty {
var stickersValue: [Api.InputDocument] = []
for file in attribute.files {
if let resource = file.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
stickersValue.append(Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)))
stickersValue.append(Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference))))
}
}
if !stickersValue.isEmpty {
@@ -676,14 +676,15 @@ if "".isEmpty {
|> mapToSignal { inputPeer -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
if let inputPeer = inputPeer {
if autoclearMessageAttribute != nil {
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedPhoto(flags: flags, file: file, stickers: stickers, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: nil)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedPhoto(.init(flags: flags, file: file, stickers: stickers, ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
}
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(flags: flags, file: file, stickers: stickers, ttlSeconds: ttlSeconds)))
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(.init(flags: flags, file: file, stickers: stickers, ttlSeconds: ttlSeconds))))
|> mapError { _ -> PendingMessageUploadError in return .generic }
|> mapToSignal { result -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
switch result {
case let .messageMediaPhoto(_, photo, _):
case let .messageMediaPhoto(messageMediaPhotoData):
let photo = messageMediaPhotoData.photo
if let photo = photo, let mediaImage = telegramMediaImageFromApiPhoto(photo), let reference = mediaImage.reference, case let .cloud(id, accessHash, maybeFileReference) = reference, let fileReference = maybeFileReference {
var flags: Int32 = 0
var ttlSeconds: Int32?
@@ -695,7 +696,7 @@ if "".isEmpty {
flags |= 1 << 1
}
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaPhoto(flags: flags, id: .inputPhoto(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference)), ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: nil))
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaPhoto(.init(flags: flags, id: .inputPhoto(.init(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference))), ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: nil))
if let _ = ttlSeconds {
return .single(result)
} else {
@@ -727,18 +728,18 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF
case .Animated:
attributes.append(.documentAttributeAnimated)
case let .FileName(fileName):
attributes.append(.documentAttributeFilename(fileName: fileName))
attributes.append(.documentAttributeFilename(.init(fileName: fileName)))
case let .ImageSize(size):
attributes.append(.documentAttributeImageSize(w: Int32(size.width), h: Int32(size.height)))
attributes.append(.documentAttributeImageSize(.init(w: Int32(size.width), h: Int32(size.height))))
case let .Sticker(displayText, packReference, maskCoords):
var stickerSet: Api.InputStickerSet = .inputStickerSetEmpty
var flags: Int32 = 0
if let packReference = packReference {
switch packReference {
case let .id(id, accessHash):
stickerSet = .inputStickerSetID(id: id, accessHash: accessHash)
stickerSet = .inputStickerSetID(.init(id: id, accessHash: accessHash))
case let .name(name):
stickerSet = .inputStickerSetShortName(shortName: name)
stickerSet = .inputStickerSetShortName(.init(shortName: name))
default:
stickerSet = .inputStickerSetEmpty
}
@@ -746,9 +747,9 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF
var inputMaskCoords: Api.MaskCoords?
if let maskCoords = maskCoords {
flags |= 1 << 0
inputMaskCoords = .maskCoords(n: maskCoords.n, x: maskCoords.x, y: maskCoords.y, zoom: maskCoords.zoom)
inputMaskCoords = .maskCoords(.init(n: maskCoords.n, x: maskCoords.x, y: maskCoords.y, zoom: maskCoords.zoom))
}
attributes.append(.documentAttributeSticker(flags: flags, alt: displayText, stickerset: stickerSet, maskCoords: inputMaskCoords))
attributes.append(.documentAttributeSticker(.init(flags: flags, alt: displayText, stickerset: stickerSet, maskCoords: inputMaskCoords)))
case .HasLinkedStickers:
attributes.append(.documentAttributeHasStickers)
case let .Video(duration, size, videoFlags, preloadSize, coverTime, videoCodec):
@@ -771,7 +772,7 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF
if videoCodec != nil {
flags |= (1 << 5)
}
attributes.append(.documentAttributeVideo(flags: flags, duration: duration, w: Int32(size.width), h: Int32(size.height), preloadPrefixSize: preloadSize, videoStartTs: coverTime, videoCodec: videoCodec))
attributes.append(.documentAttributeVideo(.init(flags: flags, duration: duration, w: Int32(size.width), h: Int32(size.height), preloadPrefixSize: preloadSize, videoStartTs: coverTime, videoCodec: videoCodec)))
case let .Audio(isVoice, duration, title, performer, waveform):
var flags: Int32 = 0
if isVoice {
@@ -788,7 +789,7 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF
flags |= Int32(1 << 2)
waveformBuffer = Buffer(data: waveform)
}
attributes.append(.documentAttributeAudio(flags: flags, duration: Int32(duration), title: title, performer: performer, waveform: waveformBuffer))
attributes.append(.documentAttributeAudio(.init(flags: flags, duration: Int32(duration), title: title, performer: performer, waveform: waveformBuffer)))
case .hintFileIsLarge:
break
case .hintIsValidated:
@@ -849,13 +850,15 @@ private func uploadedVideoCover(network: Network, postbox: Postbox, resourceRefe
case .progress:
return .complete()
case let .inputFile(file):
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(flags: 0, file: file, stickers: [], ttlSeconds: nil)))
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(.init(flags: 0, file: file, stickers: [], ttlSeconds: nil))))
|> mapError { _ -> PendingMessageUploadError in return .generic }
|> map { uploadResult in
switch uploadResult {
case let .messageMediaPhoto(_, photo, _):
if case let .photo(_, id, accessHash, fileReference, _, _, _, _) = photo {
return .inputPhoto(id: id, accessHash: accessHash, fileReference: fileReference)
case let .messageMediaPhoto(messageMediaPhotoData):
let photo = messageMediaPhotoData.photo
if case let .photo(photoData) = photo {
let (id, accessHash, fileReference) = (photoData.id, photoData.accessHash, photoData.fileReference)
return .inputPhoto(.init(id: id, accessHash: accessHash, fileReference: fileReference))
} else {
return .inputPhotoEmpty
}
@@ -947,7 +950,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|> then(
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(.init(flags: flags, id: Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference))), videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds, query: nil)), text), reuploadInfo: nil, cacheReferenceKey: nil)))
)
}
}
@@ -1195,7 +1198,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
var stickersValue: [Api.InputDocument] = []
for file in attribute.files {
if let resource = file.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
stickersValue.append(Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)))
stickersValue.append(Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference))))
}
}
if !stickersValue.isEmpty {
@@ -1211,11 +1214,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
}
if ttlSeconds != nil {
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)))
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(.init(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)))
}
if !isGrouped {
let resultInfo = PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)
let resultInfo = PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(.init(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)
return .single(.content(resultInfo))
}
@@ -1226,11 +1229,12 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|> mapError { _ -> PendingMessageUploadError in }
|> mapToSignal { inputPeer -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
if let inputPeer = inputPeer {
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: .inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds)))
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: .inputMediaUploadedDocument(.init(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds))))
|> mapError { _ -> PendingMessageUploadError in return .generic }
|> mapToSignal { result -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
switch result {
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
case let .messageMediaDocument(messageMediaDocumentData):
let (document, altDocuments) = (messageMediaDocumentData.document, messageMediaDocumentData.altDocuments)
if let document = document, let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments), let resource = mediaFile.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
var flags: Int32 = 0
var ttlSeconds: Int32?
@@ -1248,7 +1252,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
flags |= (1 << 4)
}
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaDocument(flags: flags, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil))
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaDocument(.init(flags: flags, id: .inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference))), videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds, query: nil)), text), reuploadInfo: nil, cacheReferenceKey: nil))
if let _ = ttlSeconds {
return .single(result)
} else {
@@ -76,7 +76,7 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
if todo.flags.contains(.othersCanComplete) {
flags |= 1 << 1
}
let inputTodo = Api.InputMedia.inputMediaTodo(todo: .todoList(flags: flags, title: .textWithEntities(text: todo.text, entities: apiEntitiesFromMessageTextEntities(todo.textEntities, associatedPeers: SimpleDictionary())), list: todo.items.map { $0.apiItem }))
let inputTodo = Api.InputMedia.inputMediaTodo(.init(todo: .todoList(.init(flags: flags, title: .textWithEntities(.init(text: todo.text, entities: apiEntitiesFromMessageTextEntities(todo.textEntities, associatedPeers: SimpleDictionary()))), list: todo.items.map { $0.apiItem }))))
uploadedMedia = .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(inputTodo, text), reuploadInfo: nil, cacheReferenceKey: nil)))
}
else if let uploadSignal = generateUploadSignal(forceReupload) {
@@ -234,10 +234,90 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
}
switch result {
case let .updates(updates, users, chats, _, _):
case let .updates(updatesData):
let (updates, users, chats) = (updatesData.updates, updatesData.users, updatesData.chats)
for update in updates {
switch update {
case .updateEditMessage(let message, _, _), .updateNewMessage(let message, _, _), .updateEditChannelMessage(let message, _, _), .updateNewChannelMessage(let message, _, _):
case .updateEditMessage(let data):
let message = data.message
let peers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peer.isForumOrMonoForum), case let .Id(id) = message.id {
transaction.updateMessage(id, update: { previousMessage in
var updatedFlags = message.flags
var updatedLocalTags = message.localTags
if previousMessage.localTags.contains(.OutgoingLiveLocation) {
updatedLocalTags.insert(.OutgoingLiveLocation)
}
if previousMessage.flags.contains(.Incoming) {
updatedFlags.insert(.Incoming)
} else {
updatedFlags.remove(.Incoming)
}
var updatedMedia = message.media
if let previousPaidContent = previousMessage.media.first(where: { $0 is TelegramMediaPaidContent }) as? TelegramMediaPaidContent, case .full = previousPaidContent.extendedMedia.first {
updatedMedia = previousMessage.media
}
return .update(message.withUpdatedLocalTags(updatedLocalTags).withUpdatedFlags(updatedFlags).withUpdatedMedia(updatedMedia))
})
}
case .updateNewMessage(let data):
let message = data.message
let peers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peer.isForumOrMonoForum), case let .Id(id) = message.id {
transaction.updateMessage(id, update: { previousMessage in
var updatedFlags = message.flags
var updatedLocalTags = message.localTags
if previousMessage.localTags.contains(.OutgoingLiveLocation) {
updatedLocalTags.insert(.OutgoingLiveLocation)
}
if previousMessage.flags.contains(.Incoming) {
updatedFlags.insert(.Incoming)
} else {
updatedFlags.remove(.Incoming)
}
var updatedMedia = message.media
if let previousPaidContent = previousMessage.media.first(where: { $0 is TelegramMediaPaidContent }) as? TelegramMediaPaidContent, case .full = previousPaidContent.extendedMedia.first {
updatedMedia = previousMessage.media
}
return .update(message.withUpdatedLocalTags(updatedLocalTags).withUpdatedFlags(updatedFlags).withUpdatedMedia(updatedMedia))
})
}
case .updateEditChannelMessage(let data):
let message = data.message
let peers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peer.isForumOrMonoForum), case let .Id(id) = message.id {
transaction.updateMessage(id, update: { previousMessage in
var updatedFlags = message.flags
var updatedLocalTags = message.localTags
if previousMessage.localTags.contains(.OutgoingLiveLocation) {
updatedLocalTags.insert(.OutgoingLiveLocation)
}
if previousMessage.flags.contains(.Incoming) {
updatedFlags.insert(.Incoming)
} else {
updatedFlags.remove(.Incoming)
}
var updatedMedia = message.media
if let previousPaidContent = previousMessage.media.first(where: { $0 is TelegramMediaPaidContent }) as? TelegramMediaPaidContent, case .full = previousPaidContent.extendedMedia.first {
updatedMedia = previousMessage.media
}
return .update(message.withUpdatedLocalTags(updatedLocalTags).withUpdatedFlags(updatedFlags).withUpdatedMedia(updatedMedia))
})
}
case .updateNewChannelMessage(let data):
let message = data.message
let peers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
@@ -315,13 +395,13 @@ func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, state
if let _ = coordinate.accuracyRadius {
geoFlags |= 1 << 0
}
inputGeoPoint = .inputGeoPoint(flags: geoFlags, lat: coordinate.latitude, long: coordinate.longitude, accuracyRadius: coordinate.accuracyRadius.flatMap({ Int32($0) }))
inputGeoPoint = .inputGeoPoint(.init(flags: geoFlags, lat: coordinate.latitude, long: coordinate.longitude, accuracyRadius: coordinate.accuracyRadius.flatMap({ Int32($0) })))
} else {
var geoFlags: Int32 = 0
if let _ = media.accuracyRadius {
geoFlags |= 1 << 0
}
inputGeoPoint = .inputGeoPoint(flags: geoFlags, lat: media.latitude, long: media.longitude, accuracyRadius: media.accuracyRadius.flatMap({ Int32($0) }))
inputGeoPoint = .inputGeoPoint(.init(flags: geoFlags, lat: media.latitude, long: media.longitude, accuracyRadius: media.accuracyRadius.flatMap({ Int32($0) })))
}
if let _ = heading {
flags |= 1 << 2
@@ -341,9 +421,9 @@ func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, state
period = liveBroadcastingTimeout
}
inputMedia = .inputMediaGeoLive(flags: flags, geoPoint: inputGeoPoint, heading: heading, period: period, proximityNotificationRadius: proximityNotificationRadius)
inputMedia = .inputMediaGeoLive(.init(flags: flags, geoPoint: inputGeoPoint, heading: heading, period: period, proximityNotificationRadius: proximityNotificationRadius))
} else {
inputMedia = .inputMediaGeoLive(flags: 1 << 0, geoPoint: .inputGeoPoint(flags: 0, lat: media.latitude, long: media.longitude, accuracyRadius: nil), heading: nil, period: nil, proximityNotificationRadius: nil)
inputMedia = .inputMediaGeoLive(.init(flags: 1 << 0, geoPoint: .inputGeoPoint(.init(flags: 0, lat: media.latitude, long: media.longitude, accuracyRadius: nil)), heading: nil, period: nil, proximityNotificationRadius: nil))
}
return network.request(Api.functions.messages.editMessage(flags: 1 << 14, peer: inputPeer, id: messageId.id, message: nil, media: inputMedia, replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, quickReplyShortcutId: nil))
@@ -445,14 +445,14 @@ private func sendUploadedMessageContent(
if let _ = replyTodoItemId {
replyFlags |= 1 << 6
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId))
} else if let replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
}
} else if let monoforumPeerId {
replyTo = .inputReplyToMonoForum(monoforumPeerId: monoforumPeerId)
replyTo = .inputReplyToMonoForum(.init(monoforumPeerId: monoforumPeerId))
}
if suggestedPost != nil {
@@ -479,11 +479,11 @@ private func sendUploadedMessageContent(
if let _ = replyTodoItemId {
replyFlags |= 1 << 6
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId))
} else if let replyToStoryId = replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
}
}
@@ -520,33 +520,33 @@ private func sendUploadedMessageContent(
if monoforumPeerId != nil {
replyFlags |= 1 << 5
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: nil))
} else if let replyToStoryId = replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
}
}
sendMessageRequest = network.request(Api.functions.messages.sendInlineBotResult(flags: flags, peer: inputPeer, replyTo: replyTo, randomId: uniqueId, queryId: chatContextResult.queryId, id: chatContextResult.id, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: nil, allowPaidStars: allowPaidStars))
|> map(NetworkRequestResult.result)
case .messageScreenshot:
let replyTo: Api.InputReplyTo
if let replyMessageId = replyMessageId {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
} else if let replyToStoryId = replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
} else {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: 0, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: 0, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
}
} else {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: 0, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: 0, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
}
sendMessageRequest = network.request(Api.functions.messages.sendScreenshotNotification(peer: inputPeer, replyTo: replyTo, randomId: uniqueId))
@@ -698,19 +698,19 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
var replyTo: Api.InputReplyTo?
if let replyMessageId = replyMessageId {
flags |= 1 << 0
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
} else if let replyToStoryId = replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
}
} else if let threadId {
flags |= 1 << 0
replyTo = .inputReplyToMessage(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
}
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: nil))
|> `catch` { _ -> Signal<Api.Updates, NoError> in
return .complete()
@@ -719,17 +719,17 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
var replyTo: Api.InputReplyTo?
if let replyMessageId = replyMessageId {
flags |= 1 << 0
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
} else if let replyToStoryId = replyToStoryId {
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
flags |= 1 << 0
replyTo = .inputReplyToStory(peer: inputPeer, storyId: replyToStoryId.id)
replyTo = .inputReplyToStory(.init(peer: inputPeer, storyId: replyToStoryId.id))
}
} else if let threadId {
flags |= 1 << 0
replyTo = .inputReplyToMessage(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
}
if suggestedPost != nil {
@@ -765,8 +765,9 @@ private func uploadedImage(account: Account, data: Data) -> Signal<UploadMediaEv
|> mapError { _ -> StandaloneSendMessageError in return .generic }
|> map { next -> UploadMediaEvent in
switch next {
case let .inputFile(inputFile):
return .result(Api.InputMedia.inputMediaUploadedPhoto(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil))
case let .inputFile(inputFileData):
let inputFile = inputFileData
return .result(Api.InputMedia.inputMediaUploadedPhoto(.init(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil)))
case .inputSecretFile:
preconditionFailure()
case let .progress(progress):
@@ -780,8 +781,9 @@ private func uploadedFile(account: Account, data: Data, mimeType: String, attrib
|> mapError { _ -> PendingMessageUploadError in return .generic }
|> map { next -> UploadMediaEvent in
switch next {
case let .inputFile(inputFile):
return .result(Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil))
case let .inputFile(inputFileData):
let inputFile = inputFileData
return .result(Api.InputMedia.inputMediaUploadedDocument(.init(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)))
case .inputSecretFile:
preconditionFailure()
case let .progress(progress):
@@ -64,11 +64,12 @@ public func standaloneUploadedImage(postbox: Postbox, network: Network, peerId:
|> mapError { _ -> StandaloneUploadMediaError in }
|> mapToSignal { inputPeer -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
if let inputPeer = inputPeer {
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil)))
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedPhoto(.init(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil))))
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch media {
case let .messageMediaPhoto(_, photo, _):
case let .messageMediaPhoto(messageMediaPhotoData):
let photo = messageMediaPhotoData.photo
if let photo = photo {
if let mediaImage = telegramMediaImageFromApiPhoto(photo) {
return .single(.result(.media(.standalone(media: mediaImage))))
@@ -86,7 +87,7 @@ public func standaloneUploadedImage(postbox: Postbox, network: Network, peerId:
case let .inputSecretFile(file, _, key):
return postbox.transaction { transaction -> Api.InputEncryptedChat? in
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
return Api.InputEncryptedChat.inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash)
return Api.InputEncryptedChat.inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash))
}
return nil
}
@@ -100,7 +101,8 @@ public func standaloneUploadedImage(postbox: Postbox, network: Network, peerId:
}
|> mapToSignal { result -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch result {
case let .encryptedFile(id, accessHash, size, dcId, _):
case let .encryptedFile(encryptedFileData):
let (id, accessHash, size, dcId) = (encryptedFileData.id, encryptedFileData.accessHash, encryptedFileData.size, encryptedFileData.dcId)
return .single(.result(.media(.standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: Int64(data.count), datacenterId: Int(dcId), key: key), progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])))))
case .encryptedFileEmpty:
return .fail(.generic)
@@ -158,11 +160,12 @@ public func standaloneUploadedFile(postbox: Postbox, network: Network, peerId: P
if let _ = thumbnailFile {
flags |= 1 << 2
}
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)))
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(.init(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil))))
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch media {
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
case let .messageMediaDocument(messageMediaDocumentData):
let (document, altDocuments) = (messageMediaDocumentData.document, messageMediaDocumentData.altDocuments)
if let document = document {
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments) {
return .single(.result(.media(.standalone(media: mediaFile))))
@@ -180,7 +183,7 @@ public func standaloneUploadedFile(postbox: Postbox, network: Network, peerId: P
case let .inputSecretFile(file, _, key):
return postbox.transaction { transaction -> Api.InputEncryptedChat? in
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
return Api.InputEncryptedChat.inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash)
return Api.InputEncryptedChat.inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash))
}
return nil
}
@@ -193,7 +196,8 @@ public func standaloneUploadedFile(postbox: Postbox, network: Network, peerId: P
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|> mapToSignal { result -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
switch result {
case let .encryptedFile(id, accessHash, size, dcId, _):
case let .encryptedFile(encryptedFileData):
let (id, accessHash, size, dcId) = (encryptedFileData.id, encryptedFileData.accessHash, encryptedFileData.size, encryptedFileData.dcId)
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: size, datacenterId: Int(dcId), key: key), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: size, attributes: attributes, alternativeRepresentations: [])
return .single(.result(.media(.standalone(media: media))))
@@ -10,7 +10,8 @@ func validatedEncryptionConfig(postbox: Postbox, network: Network) -> Signal<Sec
|> retryRequest
|> mapToSignal { result -> Signal<SecretChatEncryptionConfig, NoError> in
switch result {
case let .dhConfig(g, p, version, _):
case let .dhConfig(dhConfigData):
let (g, p, version) = (dhConfigData.g, dhConfigData.p, dhConfigData.version)
if !MTCheckIsSafeG(UInt32(g)) {
Logger.shared.log("SecretChatEncryptionConfig", "Invalid g")
return .complete()
@@ -26,7 +27,7 @@ func validatedEncryptionConfig(postbox: Postbox, network: Network) -> Signal<Sec
return .never()
}
return .single(SecretChatEncryptionConfig(g: g, p: MemoryBuffer(p), version: version))
case .dhConfigNotModified(_):
case .dhConfigNotModified:
assertionFailure()
return .never()
}
@@ -6,7 +6,8 @@ import TelegramApi
extension SecretChatFileReference {
convenience init?(_ file: Api.EncryptedFile) {
switch file {
case let .encryptedFile(id, accessHash, size, dcId, keyFingerprint):
case let .encryptedFile(encryptedFileData):
let (id, accessHash, size, dcId, keyFingerprint) = (encryptedFileData.id, encryptedFileData.accessHash, encryptedFileData.size, encryptedFileData.dcId, encryptedFileData.keyFingerprint)
self.init(id: id, accessHash: accessHash, size: size, datacenterId: dcId, keyFingerprint: keyFingerprint)
case .encryptedFileEmpty:
return nil
@@ -15,9 +15,11 @@ private func keyFingerprintFromBytes(_ bytes: Buffer) -> Int64 {
extension SecretChatIncomingEncryptedOperation {
convenience init(message: Api.EncryptedMessage) {
switch message {
case let .encryptedMessage(randomId, chatId, date, bytes, file):
case let .encryptedMessage(encryptedMessageData):
let (randomId, chatId, date, bytes, file) = (encryptedMessageData.randomId, encryptedMessageData.chatId, encryptedMessageData.date, encryptedMessageData.bytes, encryptedMessageData.file)
self.init(peerId: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(Int64(chatId))), globallyUniqueId: randomId, timestamp: date, type: .message, keyFingerprint: keyFingerprintFromBytes(bytes), contents: MemoryBuffer(bytes), mediaFileReference: SecretChatFileReference(file))
case let .encryptedMessageService(randomId, chatId, date, bytes):
case let .encryptedMessageService(encryptedMessageServiceData):
let (randomId, chatId, date, bytes) = (encryptedMessageServiceData.randomId, encryptedMessageServiceData.chatId, encryptedMessageServiceData.date, encryptedMessageServiceData.bytes)
self.init(peerId: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(Int64(chatId))), globallyUniqueId: randomId, timestamp: date, type: .service, keyFingerprint: keyFingerprintFromBytes(bytes), contents: MemoryBuffer(bytes), mediaFileReference: nil)
}
}
@@ -6,11 +6,14 @@ import TelegramApi
extension SecretChatOutgoingFileReference {
init?(_ apiFile: Api.InputEncryptedFile) {
switch apiFile {
case let .inputEncryptedFile(id, accessHash):
case let .inputEncryptedFile(inputEncryptedFileData):
let (id, accessHash) = (inputEncryptedFileData.id, inputEncryptedFileData.accessHash)
self = .remote(id: id, accessHash: accessHash)
case let .inputEncryptedFileBigUploaded(id, parts, keyFingerprint):
case let .inputEncryptedFileBigUploaded(inputEncryptedFileBigUploadedData):
let (id, parts, keyFingerprint) = (inputEncryptedFileBigUploadedData.id, inputEncryptedFileBigUploadedData.parts, inputEncryptedFileBigUploadedData.keyFingerprint)
self = .uploadedLarge(id: id, partCount: parts, keyFingerprint: keyFingerprint)
case let .inputEncryptedFileUploaded(id, parts, md5Checksum, keyFingerprint):
case let .inputEncryptedFileUploaded(inputEncryptedFileUploadedData):
let (id, parts, md5Checksum, keyFingerprint) = (inputEncryptedFileUploadedData.id, inputEncryptedFileUploadedData.parts, inputEncryptedFileUploadedData.md5Checksum, inputEncryptedFileUploadedData.keyFingerprint)
self = .uploadedRegular(id: id, partCount: parts, md5Digest: md5Checksum, keyFingerprint: keyFingerprint)
case .inputEncryptedFileEmpty:
return nil
@@ -20,11 +23,11 @@ extension SecretChatOutgoingFileReference {
var apiInputFile: Api.InputEncryptedFile {
switch self {
case let .remote(id, accessHash):
return .inputEncryptedFile(id: id, accessHash: accessHash)
return .inputEncryptedFile(.init(id: id, accessHash: accessHash))
case let .uploadedRegular(id, partCount, md5Digest, keyFingerprint):
return .inputEncryptedFileUploaded(id: id, parts: partCount, md5Checksum: md5Digest, keyFingerprint: keyFingerprint)
return .inputEncryptedFileUploaded(.init(id: id, parts: partCount, md5Checksum: md5Digest, keyFingerprint: keyFingerprint))
case let .uploadedLarge(id, partCount, keyFingerprint):
return .inputEncryptedFileBigUploaded(id: id, parts: partCount, keyFingerprint: keyFingerprint)
return .inputEncryptedFileBigUploaded(.init(id: id, parts: partCount, keyFingerprint: keyFingerprint))
}
}
}
@@ -26,6 +26,11 @@ func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(transaction: T
}
func _internal_addSecretChatMessageScreenshot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
// MISC: Bypass screenshot notifications in secret chats when enabled
if MiscSettingsManager.shared.shouldBypassScreenshotProtection {
return .complete()
}
return account.postbox.transaction { transaction -> Void in
if let _ = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState {
switch state.embeddedState {
@@ -17,7 +17,8 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
let settings = transaction.getPreferencesEntry(key: PreferencesKeys.secretChatSettings)?.get(SecretChatSettings.self) ?? SecretChatSettings.defaultSettings
assert((currentPeer == nil) == (currentState == nil))
switch chat {
case let .encryptedChat(_, _, _, adminId, _, gAOrB, _):
case let .encryptedChat(encryptedChatData):
let (adminId, gAOrB) = (encryptedChatData.adminId, encryptedChatData.gAOrB)
if let currentPeer = currentPeer, let currentState = currentState, adminId == accountPeerId.id._internalGetInt64Value() {
if case let .handshake(handshakeState) = currentState.embeddedState, case let .requested(_, p, a) = handshakeState {
let pData = p.makeData()
@@ -67,7 +68,8 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
} else {
Logger.shared.log("State", "got encryptedChat, but peer or state don't exist or account is not creator")
}
case let .encryptedChatDiscarded(flags, _):
case let .encryptedChatDiscarded(encryptedChatDiscardedData):
let flags = encryptedChatDiscardedData.flags
if let currentPeer = currentPeer, let currentState = currentState {
let isRemoved = (flags & (1 << 0)) != 0
@@ -86,9 +88,10 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
} else {
Logger.shared.log("State", "got encryptedChatDiscarded, but peer doesn't exist")
}
case .encryptedChatEmpty(_):
case .encryptedChatEmpty:
break
case let .encryptedChatRequested(_, folderId, _, accessHash, date, adminId, participantId, gA):
case let .encryptedChatRequested(encryptedChatRequestedData):
let (folderId, accessHash, date, adminId, participantId, gA) = (encryptedChatRequestedData.folderId, encryptedChatRequestedData.accessHash, encryptedChatRequestedData.date, encryptedChatRequestedData.adminId, encryptedChatRequestedData.participantId, encryptedChatRequestedData.gA)
if currentPeer == nil && participantId == accountPeerId.id._internalGetInt64Value() {
if settings.acceptOnThisDevice {
let state = SecretChatState(role: .participant, embeddedState: .handshake(.accepting), keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil)
@@ -122,7 +125,8 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
} else {
Logger.shared.log("State", "got encryptedChatRequested, but peer already exists or this account is creator")
}
case let .encryptedChatWaiting(_, accessHash, date, adminId, participantId):
case let .encryptedChatWaiting(encryptedChatWaitingData):
let (accessHash, date, adminId, participantId) = (encryptedChatWaitingData.accessHash, encryptedChatWaitingData.date, encryptedChatWaitingData.adminId, encryptedChatWaitingData.participantId)
if let requestData = requestData, currentPeer == nil && adminId == accountPeerId.id._internalGetInt64Value() {
let state = SecretChatState(role: .creator, embeddedState: .handshake(.requested(g: requestData.g, p: requestData.p, a: requestData.a)), keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil)
let peer = TelegramSecretChat(id: chat.peerId, creationDate: date, regularPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(participantId)), accessHash: accessHash, role: state.role, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: nil)
@@ -21,7 +21,8 @@ public func updateAutodownloadSettingsInteractively(accountManager: AccountManag
extension AutodownloadPresetSettings {
init(apiAutodownloadSettings: Api.AutoDownloadSettings) {
switch apiAutodownloadSettings {
case let .autoDownloadSettings(flags, photoSizeMax, videoSizeMax, fileSizeMax, videoUploadMaxbitrate, _, _):
case let .autoDownloadSettings(autoDownloadSettingsData):
let (flags, photoSizeMax, videoSizeMax, fileSizeMax, videoUploadMaxbitrate, _, _) = (autoDownloadSettingsData.flags, autoDownloadSettingsData.photoSizeMax, autoDownloadSettingsData.videoSizeMax, autoDownloadSettingsData.fileSizeMax, autoDownloadSettingsData.videoUploadMaxbitrate, autoDownloadSettingsData.smallQueueActiveOperationsMax, autoDownloadSettingsData.largeQueueActiveOperationsMax)
self.init(disabled: (flags & (1 << 0)) != 0, photoSizeMax: Int64(photoSizeMax), videoSizeMax: videoSizeMax, fileSizeMax: fileSizeMax, preloadLargeVideo: (flags & (1 << 1)) != 0, lessDataForPhoneCalls: (flags & (1 << 3)) != 0, videoUploadMaxbitrate: videoUploadMaxbitrate)
}
}
@@ -30,7 +31,8 @@ extension AutodownloadPresetSettings {
extension AutodownloadSettings {
init(apiAutodownloadSettings: Api.account.AutoDownloadSettings) {
switch apiAutodownloadSettings {
case let .autoDownloadSettings(low, medium, high):
case let .autoDownloadSettings(autoDownloadSettingsData):
let (low, medium, high) = (autoDownloadSettingsData.low, autoDownloadSettingsData.medium, autoDownloadSettingsData.high)
self.init(lowPreset: AutodownloadPresetSettings(apiAutodownloadSettings: low), mediumPreset: AutodownloadPresetSettings(apiAutodownloadSettings: medium), highPreset: AutodownloadPresetSettings(apiAutodownloadSettings: high))
}
}
@@ -47,6 +49,6 @@ func apiAutodownloadPresetSettings(_ autodownloadPresetSettings: AutodownloadPre
if autodownloadPresetSettings.lessDataForPhoneCalls {
flags |= (1 << 3)
}
return .autoDownloadSettings(flags: flags, photoSizeMax: Int32(autodownloadPresetSettings.photoSizeMax), videoSizeMax: autodownloadPresetSettings.videoSizeMax, fileSizeMax: autodownloadPresetSettings.fileSizeMax, videoUploadMaxbitrate: autodownloadPresetSettings.videoUploadMaxbitrate, smallQueueActiveOperationsMax: 0, largeQueueActiveOperationsMax: 0)
return .autoDownloadSettings(Api.AutoDownloadSettings.Cons_autoDownloadSettings(flags: flags, photoSizeMax: Int32(autodownloadPresetSettings.photoSizeMax), videoSizeMax: autodownloadPresetSettings.videoSizeMax, fileSizeMax: autodownloadPresetSettings.fileSizeMax, videoUploadMaxbitrate: autodownloadPresetSettings.videoUploadMaxbitrate, smallQueueActiveOperationsMax: 0, largeQueueActiveOperationsMax: 0))
}
@@ -4,14 +4,16 @@ import TelegramApi
import SwiftSignalKit
public struct ContentSettings: Equatable {
public static var `default` = ContentSettings(ignoreContentRestrictionReasons: [], addContentRestrictionReasons: [])
public static var `default` = ContentSettings(ignoreContentRestrictionReasons: [], addContentRestrictionReasons: [], appConfiguration: AppConfiguration.defaultValue)
public var ignoreContentRestrictionReasons: Set<String>
public var addContentRestrictionReasons: [String]
public var appConfiguration: AppConfiguration
public init(ignoreContentRestrictionReasons: Set<String>, addContentRestrictionReasons: [String]) {
public init(ignoreContentRestrictionReasons: Set<String>, addContentRestrictionReasons: [String], appConfiguration: AppConfiguration) {
self.ignoreContentRestrictionReasons = ignoreContentRestrictionReasons
self.addContentRestrictionReasons = addContentRestrictionReasons
self.appConfiguration = appConfiguration
}
}
@@ -27,7 +29,9 @@ extension ContentSettings {
addContentRestrictionReasons = addContentRestrictionReasonsData
}
}
self.init(ignoreContentRestrictionReasons: Set(reasons), addContentRestrictionReasons: addContentRestrictionReasons)
// MARK: Swiftgram
reasons += appConfiguration.sgWebSettings.user.expandedContentReasons()
self.init(ignoreContentRestrictionReasons: Set(reasons), addContentRestrictionReasons: addContentRestrictionReasons, appConfiguration: appConfiguration)
}
}
@@ -61,7 +65,8 @@ public func contentSettingsConfiguration(network: Network) -> Signal<ContentSett
return network.request(Api.functions.account.getContentSettings())
|> map { result -> ContentSettingsConfiguration in
switch result {
case let .contentSettings(flags):
case let .contentSettings(contentSettingsData):
let flags = contentSettingsData.flags
return ContentSettingsConfiguration(sensitiveContentEnabled: (flags & (1 << 0)) != 0, canAdjustSensitiveContent: (flags & (1 << 1)) != 0)
}
}
@@ -6,7 +6,8 @@ import TelegramApi
extension MessageNotificationSettings {
init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
case let .peerNotifySettings(peerNotifySettingsData):
let (showPreviews, muteUntil, iosSound, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, storiesDesktopSound) = (peerNotifySettingsData.showPreviews, peerNotifySettingsData.muteUntil, peerNotifySettingsData.iosSound, peerNotifySettingsData.otherSound, peerNotifySettingsData.storiesMuted, peerNotifySettingsData.storiesHideSender, peerNotifySettingsData.storiesIosSound, peerNotifySettingsData.storiesOtherSound)
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
@@ -6,7 +6,8 @@ import SwiftSignalKit
extension PeerStatusSettings {
init(apiSettings: Api.PeerSettings) {
switch apiSettings {
case let .peerSettings(flags, geoDistance, requestChatTitle, requestChatDate, businessBotId, businessBotManageUrl, chargePaidMessageStars, registrationMonth, phoneCountry, nameChangeDate, photoChangeDate):
case let .peerSettings(peerSettingsData):
let (flags, geoDistance, requestChatTitle, requestChatDate, businessBotId, businessBotManageUrl, chargePaidMessageStars, registrationMonth, phoneCountry, nameChangeDate, photoChangeDate) = (peerSettingsData.flags, peerSettingsData.geoDistance, peerSettingsData.requestChatTitle, peerSettingsData.requestChatDate, peerSettingsData.businessBotId, peerSettingsData.businessBotManageUrl, peerSettingsData.chargePaidMessageStars, peerSettingsData.registrationMonth, peerSettingsData.phoneCountry, peerSettingsData.nameChangeDate, peerSettingsData.photoChangeDate)
var result = PeerStatusSettings.Flags()
if (flags & (1 << 1)) != 0 {
result.insert(.canAddContact)
@@ -230,7 +230,8 @@ extension SelectivePrivacySettings {
current = .enableEveryone(disableFor: [:])
case .privacyValueAllowContacts:
current = .enableContacts(enableFor: [:], disableFor: [:], enableForPremium: false, enableForBots: false)
case let .privacyValueAllowUsers(users):
case let .privacyValueAllowUsers(privacyValueAllowUsersData):
let users = privacyValueAllowUsersData.users
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
enableFor[peer.peer.id] = peer
@@ -240,13 +241,15 @@ extension SelectivePrivacySettings {
break
case .privacyValueDisallowContacts:
break
case let .privacyValueDisallowUsers(users):
case let .privacyValueDisallowUsers(privacyValueDisallowUsersData):
let users = privacyValueDisallowUsersData.users
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
disableFor[peer.peer.id] = peer
}
}
case let .privacyValueAllowChatParticipants(chats):
case let .privacyValueAllowChatParticipants(privacyValueAllowChatParticipantsData):
let chats = privacyValueAllowChatParticipantsData.chats
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
@@ -254,7 +257,8 @@ extension SelectivePrivacySettings {
}
}
}
case let .privacyValueDisallowChatParticipants(chats):
case let .privacyValueDisallowChatParticipants(privacyValueDisallowChatParticipantsData):
let chats = privacyValueDisallowChatParticipantsData.chats
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
@@ -337,7 +341,8 @@ extension TelegramDisallowedGifts {
init(apiDisallowedGifts: Api.DisallowedGiftsSettings?) {
var disallowedGifts: TelegramDisallowedGifts = []
switch apiDisallowedGifts {
case let .disallowedGiftsSettings(giftFlags):
case let .disallowedGiftsSettings(disallowedGiftsSettingsData):
let giftFlags = disallowedGiftsSettingsData.flags
if (giftFlags & (1 << 0)) != 0 {
disallowedGifts.insert(.unlimited)
}
@@ -6,10 +6,12 @@ import TelegramApi
extension UnauthorizedAccountTermsOfService {
init?(apiTermsOfService: Api.help.TermsOfService) {
switch apiTermsOfService {
case let .termsOfService(_, id, text, entities, minAgeConfirm):
case let .termsOfService(termsOfServiceData):
let (_, id, text, entities, minAgeConfirm) = (termsOfServiceData.flags, termsOfServiceData.id, termsOfServiceData.text, termsOfServiceData.entities, termsOfServiceData.minAgeConfirm)
let idData: String
switch id {
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
idData = data
}
self.init(id: idData, text: text, entities: messageTextEntitiesFromApiEntities(entities), ageConfirmation: minAgeConfirm)
@@ -20,27 +22,38 @@ extension UnauthorizedAccountTermsOfService {
extension SentAuthorizationCodeType {
init(apiType: Api.auth.SentCodeType) {
switch apiType {
case let .sentCodeTypeApp(length):
case let .sentCodeTypeApp(sentCodeTypeAppData):
let length = sentCodeTypeAppData.length
self = .otherSession(length: length)
case let .sentCodeTypeSms(length):
case let .sentCodeTypeSms(sentCodeTypeSmsData):
let length = sentCodeTypeSmsData.length
self = .sms(length: length)
case let .sentCodeTypeCall(length):
case let .sentCodeTypeCall(sentCodeTypeCallData):
let length = sentCodeTypeCallData.length
self = .call(length: length)
case let .sentCodeTypeFlashCall(pattern):
case let .sentCodeTypeFlashCall(sentCodeTypeFlashCallData):
let pattern = sentCodeTypeFlashCallData.pattern
self = .flashCall(pattern: pattern)
case let .sentCodeTypeMissedCall(prefix, length):
case let .sentCodeTypeMissedCall(sentCodeTypeMissedCallData):
let (prefix, length) = (sentCodeTypeMissedCallData.prefix, sentCodeTypeMissedCallData.length)
self = .missedCall(numberPrefix: prefix, length: length)
case let .sentCodeTypeEmailCode(flags, emailPattern, length, resetAvailablePeriod, resetPendingDate):
case let .sentCodeTypeEmailCode(sentCodeTypeEmailCodeData):
let (flags, emailPattern, length, resetAvailablePeriod, resetPendingDate) = (sentCodeTypeEmailCodeData.flags, sentCodeTypeEmailCodeData.emailPattern, sentCodeTypeEmailCodeData.length, sentCodeTypeEmailCodeData.resetAvailablePeriod, sentCodeTypeEmailCodeData.resetPendingDate)
self = .email(emailPattern: emailPattern, length: length, resetAvailablePeriod: resetAvailablePeriod, resetPendingDate: resetPendingDate, appleSignInAllowed: (flags & (1 << 0)) != 0, setup: false)
case let .sentCodeTypeSetUpEmailRequired(flags):
case let .sentCodeTypeSetUpEmailRequired(sentCodeTypeSetUpEmailRequiredData):
let flags = sentCodeTypeSetUpEmailRequiredData.flags
self = .emailSetupRequired(appleSignInAllowed: (flags & (1 << 0)) != 0)
case let .sentCodeTypeFragmentSms(url, length):
case let .sentCodeTypeFragmentSms(sentCodeTypeFragmentSmsData):
let (url, length) = (sentCodeTypeFragmentSmsData.url, sentCodeTypeFragmentSmsData.length)
self = .fragment(url: url, length: length)
case let .sentCodeTypeFirebaseSms(_, _, _, _, _, pushTimeout, length):
case let .sentCodeTypeFirebaseSms(sentCodeTypeFirebaseSmsData):
let (pushTimeout, length) = (sentCodeTypeFirebaseSmsData.pushTimeout, sentCodeTypeFirebaseSmsData.length)
self = .firebase(pushTimeout: pushTimeout, length: length)
case let .sentCodeTypeSmsWord(_, beginning):
case let .sentCodeTypeSmsWord(sentCodeTypeSmsWordData):
let beginning = sentCodeTypeSmsWordData.beginning
self = .word(startsWith: beginning)
case let .sentCodeTypeSmsPhrase(_, beginning):
case let .sentCodeTypeSmsPhrase(sentCodeTypeSmsPhraseData):
let beginning = sentCodeTypeSmsPhraseData.beginning
self = .phrase(startsWith: beginning)
}
}
File diff suppressed because it is too large Load Diff
@@ -925,7 +925,8 @@ public final class AccountStateManager {
return postbox.transaction { transaction -> (difference: Api.updates.Difference?, finalStatte: AccountReplayedFinalState?, skipBecauseOfError: Bool, resetState: Bool) in
if let currentState = transaction.getState() as? AuthorizedAccountState {
switch state {
case let .state(pts, qts, date, seq, _):
case let .state(stateData):
let (pts, qts, date, seq) = (stateData.pts, stateData.qts, stateData.date, stateData.seq)
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: qts, date: date, seq: seq)))
}
}
@@ -1883,10 +1884,12 @@ public final class AccountStateManager {
if let updates = Api.parse(Buffer(data: rawData)) as? Api.Updates {
switch updates {
case let .updates(updates, _, _, _, _):
case let .updates(updatesData):
let updates = updatesData.updates
for update in updates {
switch update {
case let .updatePhoneCall(phoneCall):
case let .updatePhoneCall(updatePhoneCallData):
let phoneCall = updatePhoneCallData.phoneCall
if let callSessionManager = self.callSessionManager {
callSessionManager.updateSession(phoneCall, completion: { result in
completion(result)
@@ -2297,17 +2300,20 @@ public final class AccountStateManager {
return nil
}
switch updates {
case let .updates(updates, users, _, _, _):
case let .updates(updatesData):
let (updates, users) = (updatesData.updates, updatesData.users)
var peers: [Peer] = []
for user in users {
peers.append(TelegramUser(user: user))
}
for update in updates {
switch update {
case let .updatePhoneCall(phoneCall):
case let .updatePhoneCall(updatePhoneCallData):
let phoneCall = updatePhoneCallData.phoneCall
switch phoneCall {
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, _, _):
case let .phoneCallRequested(phoneCallRequestedData):
let (flags, id, accessHash, date, adminId) = (phoneCallRequestedData.flags, phoneCallRequestedData.id, phoneCallRequestedData.accessHash, phoneCallRequestedData.date, phoneCallRequestedData.adminId)
guard let peer = peers.first(where: { $0.id == PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)) }) else {
return nil
}
@@ -87,10 +87,11 @@ private func fetchWebpage(account: Account, messageId: MessageId, threadId: Int6
}
} else {
switch inputPeer {
case let .inputPeerChannel(channelId, accessHash):
messages = account.network.request(Api.functions.channels.getMessages(channel: Api.InputChannel.inputChannel(channelId: channelId, accessHash: accessHash), id: [Api.InputMessage.inputMessageID(id: messageId.id)]))
case let .inputPeerChannel(inputPeerChannelData):
let (channelId, accessHash) = (inputPeerChannelData.channelId, inputPeerChannelData.accessHash)
messages = account.network.request(Api.functions.channels.getMessages(channel: Api.InputChannel.inputChannel(.init(channelId: channelId, accessHash: accessHash)), id: [Api.InputMessage.inputMessageID(.init(id: messageId.id))]))
default:
messages = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)]))
messages = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(.init(id: messageId.id))]))
}
}
return messages
@@ -100,17 +101,20 @@ private func fetchWebpage(account: Account, messageId: MessageId, threadId: Int6
let chats: [Api.Chat]
let users: [Api.User]
switch result {
case let .messages(messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.topics, messagesSliceData.chats, messagesSliceData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, _, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -719,10 +723,11 @@ public final class AccountViewTracker {
return .single(nil)
}
|> mapToSignal { result -> Signal<[MessageId: ViewCountContextState], NoError> in
guard case let .messageViews(viewCounts, chats, users)? = result else {
guard case let .messageViews(messageViewsData)? = result else {
return .complete()
}
let (viewCounts, chats, users) = (messageViewsData.views, messageViewsData.chats, messageViewsData.users)
return account.postbox.transaction { transaction -> [MessageId: ViewCountContextState] in
var resultStates: [MessageId: ViewCountContextState] = [:]
@@ -732,7 +737,8 @@ public final class AccountViewTracker {
for i in 0 ..< messageIds.count {
if i < viewCounts.count {
if case let .messageViews(_, views, forwards, replies) = viewCounts[i] {
if case let .messageViews(messageViewsData) = viewCounts[i] {
let (views, forwards, replies) = (messageViewsData.views, messageViewsData.forwards, messageViewsData.replies)
transaction.updateMessage(messageIds[i], update: { currentMessage in
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
var attributes = currentMessage.attributes
@@ -744,7 +750,8 @@ public final class AccountViewTracker {
var repliesReadMaxId: Int32?
if let replies = replies {
switch replies {
case let .messageReplies(_, repliesCountValue, _, recentRepliers, channelId, maxId, readMaxId):
case let .messageReplies(messageRepliesData):
let (repliesCountValue, recentRepliers, channelId, maxId, readMaxId) = (messageRepliesData.replies, messageRepliesData.recentRepliers, messageRepliesData.channelId, messageRepliesData.maxId, messageRepliesData.readMaxId)
if let channelId = channelId {
commentsChannelId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
}
@@ -861,18 +868,22 @@ public final class AccountViewTracker {
return account.postbox.transaction { transaction -> Void in
let updateList: [Api.Update]
switch updates {
case let .updates(updates, _, _, _, _):
case let .updates(updatesData):
let updates = updatesData.updates
updateList = updates
case let .updatesCombined(updates, _, _, _, _, _):
case let .updatesCombined(updatesCombinedData):
let updates = updatesCombinedData.updates
updateList = updates
case let .updateShort(update, _):
case let .updateShort(updateShortData):
let update = updateShortData.update
updateList = [update]
default:
updateList = []
}
for update in updateList {
switch update {
case let .updateMessageReactions(_, peer, msgId, _, _, reactions):
case let .updateMessageReactions(updateMessageReactionsData):
let (peer, msgId, reactions) = (updateMessageReactionsData.peer, updateMessageReactionsData.msgId, updateMessageReactionsData.reactions)
transaction.updateMessage(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), update: { currentMessage in
var updatedReactions = ReactionsMessageAttribute(apiReactions: reactions)
@@ -949,8 +960,9 @@ public final class AccountViewTracker {
case .inputPeerChat, .inputPeerSelf, .inputPeerUser:
request = account.network.request(Api.functions.messages.readMessageContents(id: messageIds.map { $0.id }))
|> map { _ in true }
case let .inputPeerChannel(channelId, accessHash):
request = account.network.request(Api.functions.channels.readMessageContents(channel: .inputChannel(channelId: channelId, accessHash: accessHash), id: messageIds.map { $0.id }))
case let .inputPeerChannel(inputPeerChannelData):
let (channelId, accessHash) = (inputPeerChannelData.channelId, inputPeerChannelData.accessHash)
request = account.network.request(Api.functions.channels.readMessageContents(channel: .inputChannel(.init(channelId: channelId, accessHash: accessHash)), id: messageIds.map { $0.id }))
|> map { _ in true }
default:
return .complete()
@@ -1074,10 +1086,10 @@ public final class AccountViewTracker {
fetchSignal = .never()
}
} else if peerIdAndThreadId.peerId.namespace == Namespaces.Peer.CloudUser || peerIdAndThreadId.peerId.namespace == Namespaces.Peer.CloudGroup {
fetchSignal = account.network.request(Api.functions.messages.getMessages(id: messageIds.map { Api.InputMessage.inputMessageID(id: $0.id) }))
fetchSignal = account.network.request(Api.functions.messages.getMessages(id: messageIds.map { Api.InputMessage.inputMessageID(.init(id: $0.id)) }))
} else if peerIdAndThreadId.peerId.namespace == Namespaces.Peer.CloudChannel {
if let inputChannel = apiInputChannel(peer) {
fetchSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map { Api.InputMessage.inputMessageID(id: $0.id) }))
fetchSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map { Api.InputMessage.inputMessageID(.init(id: $0.id)) }))
}
}
guard let signal = fetchSignal else {
@@ -1087,11 +1099,14 @@ public final class AccountViewTracker {
return signal
|> map { result -> (Peer, [Api.Message], [Api.Chat], [Api.User]) in
switch result {
case let .messages(messages, _, chats, users):
case let .messages(messagesData):
let (messages, chats, users) = (messagesData.messages, messagesData.chats, messagesData.users)
return (peer, messages, chats, users)
case let .messagesSlice(_, _, _, _, _, messages, _, chats, users):
case let .messagesSlice(messagesSliceData):
let (messages, chats, users) = (messagesSliceData.messages, messagesSliceData.chats, messagesSliceData.users)
return (peer, messages, chats, users)
case let .channelMessages(_, _, _, _, messages, _, chats, users):
case let .channelMessages(channelMessagesData):
let (messages, chats, users) = (channelMessagesData.messages, channelMessagesData.chats, channelMessagesData.users)
return (peer, messages, chats, users)
case .messagesNotModified:
return (peer, [], [], [])
@@ -1180,7 +1195,7 @@ public final class AccountViewTracker {
var requests: [Signal<Api.messages.StickerSet?, NoError>] = []
for reference in stickerPacks {
if case let .id(id, accessHash) = reference {
requests.append(account.network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: id, accessHash: accessHash), hash: 0))
requests.append(account.network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(.init(id: id, accessHash: accessHash)), hash: 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
return .single(nil)
@@ -1196,7 +1211,8 @@ public final class AccountViewTracker {
return account.postbox.transaction { transaction -> Void in
for result in results {
switch result {
case let .stickerSet(_, _, _, documents)?:
case let .stickerSet(stickerSetData)?:
let documents = stickerSetData.documents
for document in documents {
if let file = telegramMediaFileFromApiDocument(document, altDocuments: []) {
if transaction.getMedia(file.fileId) != nil {
@@ -1440,7 +1456,8 @@ public final class AccountViewTracker {
if i < slice.count {
let value = result[i]
switch value {
case let .recentStory(flags, maxId):
case let .recentStory(recentStoryData):
let (flags, maxId) = (recentStoryData.flags, recentStoryData.maxId)
if let maxId {
transaction.setStoryItemsInexactMaxId(peerId: slice[i].0, id: maxId, hasLiveItems: (flags & (1 << 0)) != 0)
} else {
@@ -1552,7 +1569,8 @@ public final class AccountViewTracker {
case .requirementToContactPremium:
flags.insert(.premiumRequired)
sendPaidMessageStars = nil
case let .requirementToContactPaidMessages(starsAmount):
case let .requirementToContactPaidMessages(requirementToContactPaidMessagesData):
let starsAmount = requirementToContactPaidMessagesData.starsAmount
flags.remove(.premiumRequired)
sendPaidMessageStars = StarsAmount(value: starsAmount, nanos: 0)
}
@@ -8,7 +8,7 @@ public func currentAppConfiguration(transaction: Transaction) -> AppConfiguratio
}
}
func updateAppConfiguration(transaction: Transaction, _ f: (AppConfiguration) -> AppConfiguration) {
public func updateAppConfiguration(transaction: Transaction, _ f: (AppConfiguration) -> AppConfiguration) {
let current = currentAppConfiguration(transaction: transaction)
let updated = f(current)
if updated != current {
@@ -22,7 +22,8 @@ public struct AppUpdateInfo: Equatable {
extension AppUpdateInfo {
init?(apiAppUpdate: Api.help.AppUpdate) {
switch apiAppUpdate {
case let .appUpdate(flags, _, version, text, entities, _, _, _):
case let .appUpdate(appUpdateData):
let (flags, version, text, entities) = (appUpdateData.flags, appUpdateData.version, appUpdateData.text, appUpdateData.entities)
self.blocking = (flags & (1 << 0)) != 0
self.version = version
self.text = text
@@ -67,7 +67,8 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
for update in result.allUpdates {
switch update {
case let .updateMessageID(id, randomId):
case let .updateMessageID(updateMessageIDData):
let (id, randomId) = (updateMessageIDData.id, updateMessageIDData.randomId)
for attribute in message.attributes {
if let attribute = attribute as? OutgoingMessageInfoAttribute {
if attribute.uniqueId == randomId {
@@ -104,16 +105,19 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
var updatedTimestamp: Int32?
if let apiMessage = apiMessage {
switch apiMessage {
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .message(messageData):
let date = messageData.date
updatedTimestamp = date
case .messageEmpty:
break
case let .messageService(_, _, _, _, _, _, date, _, _, _):
case let .messageService(messageServiceData):
let date = messageServiceData.date
updatedTimestamp = date
}
} else {
switch result {
case let .updateShortSentMessage(_, _, _, _, date, _, _, _):
case let .updateShortSentMessage(updateShortSentMessageData):
let (_, _, _, _, date, _, _, _) = (updateShortSentMessageData.flags, updateShortSentMessageData.id, updateShortSentMessageData.pts, updateShortSentMessageData.ptsCount, updateShortSentMessageData.date, updateShortSentMessageData.media, updateShortSentMessageData.entities, updateShortSentMessageData.ttlPeriod)
updatedTimestamp = date
default:
break
@@ -151,7 +155,8 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
text = updatedMessage.text
forwardInfo = updatedMessage.forwardInfo
threadId = updatedMessage.threadId
} else if case let .updateShortSentMessage(_, _, _, _, _, apiMedia, entities, ttlPeriod) = result {
} else if case let .updateShortSentMessage(updateShortSentMessageData) = result {
let (_, _, _, _, _, apiMedia, entities, ttlPeriod) = (updateShortSentMessageData.flags, updateShortSentMessageData.id, updateShortSentMessageData.pts, updateShortSentMessageData.ptsCount, updateShortSentMessageData.date, updateShortSentMessageData.media, updateShortSentMessageData.entities, updateShortSentMessageData.ttlPeriod)
let (mediaValue, _, nonPremium, hasSpoiler, _, _) = textMediaAndExpirationTimerFromApiMedia(apiMedia, currentMessage.id.peerId)
if let mediaValue = mediaValue {
media = [mediaValue]
@@ -400,7 +405,7 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage
} else if let message = messages.first, let apiMessage = result.messages.first {
if message.scheduleTime != nil && message.scheduleTime == apiMessage.timestamp {
namespace = Namespaces.Message.ScheduledCloud
} else if let apiMessage = result.messages.first, case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage, (flags2 & (1 << 4)) != 0 {
} else if let apiMessage = result.messages.first, case let .message(messageData) = apiMessage, (messageData.flags2 & (1 << 4)) != 0 {
namespace = Namespaces.Message.ScheduledCloud
}
}
@@ -173,7 +173,8 @@ public final class AvailableMessageEffects: Equatable, Codable {
private extension AvailableMessageEffects.MessageEffect {
convenience init?(apiMessageEffect: Api.AvailableEffect, files: [Int64: TelegramMediaFile]) {
switch apiMessageEffect {
case let .availableEffect(flags, id, emoticon, staticIconId, effectStickerId, effectAnimationId):
case let .availableEffect(availableEffectData):
let (flags, id, emoticon, staticIconId, effectStickerId, effectAnimationId) = (availableEffectData.flags, availableEffectData.id, availableEffectData.emoticon, availableEffectData.staticIconId, availableEffectData.effectStickerId, availableEffectData.effectAnimationId)
guard let effectSticker = files[effectStickerId] else {
return nil
}
@@ -239,7 +240,8 @@ func managedSynchronizeAvailableMessageEffects(postbox: Postbox, network: Networ
return .complete()
}
switch result {
case let .availableEffects(hash, effects, documents):
case let .availableEffects(availableEffectsData):
let (hash, effects, documents) = (availableEffectsData.hash, availableEffectsData.effects, availableEffectsData.documents)
var files: [Int64: TelegramMediaFile] = [:]
for document in documents {
if let file = telegramMediaFileFromApiDocument(document, altDocuments: []) {
@@ -314,7 +314,8 @@ public final class AvailableReactions: Equatable, Codable {
private extension AvailableReactions.Reaction {
convenience init?(apiReaction: Api.AvailableReaction) {
switch apiReaction {
case let .availableReaction(flags, reaction, title, staticIcon, appearAnimation, selectAnimation, activateAnimation, effectAnimation, aroundAnimation, centerIcon):
case let .availableReaction(availableReactionData):
let (flags, reaction, title, staticIcon, appearAnimation, selectAnimation, activateAnimation, effectAnimation, aroundAnimation, centerIcon) = (availableReactionData.flags, availableReactionData.reaction, availableReactionData.title, availableReactionData.staticIcon, availableReactionData.appearAnimation, availableReactionData.selectAnimation, availableReactionData.activateAnimation, availableReactionData.effectAnimation, availableReactionData.aroundAnimation, availableReactionData.centerIcon)
guard let staticIconFile = telegramMediaFileFromApiDocument(staticIcon, altDocuments: []) else {
return nil
}
@@ -419,7 +420,8 @@ func managedSynchronizeAvailableReactions(postbox: Postbox, network: Network) ->
}
switch result {
case let .availableReactions(hash, reactions):
case let .availableReactions(availableReactionsData):
let (hash, reactions) = (availableReactionsData.hash, availableReactionsData.reactions)
let availableReactions = AvailableReactions(
hash: hash,
reactions: reactions.compactMap(AvailableReactions.Reaction.init(apiReaction:))
@@ -66,7 +66,8 @@ public struct GroupCallReference: Codable, Equatable {
extension GroupCallReference {
init?(_ apiGroupCall: Api.InputGroupCall) {
switch apiGroupCall {
case let .inputGroupCall(id, accessHash):
case let .inputGroupCall(inputGroupCallData):
let (id, accessHash) = (inputGroupCallData.id, inputGroupCallData.accessHash)
self.init(id: id, accessHash: accessHash)
case .inputGroupCallSlug, .inputGroupCallInviteMessage:
return nil
@@ -74,7 +75,7 @@ extension GroupCallReference {
}
var apiInputGroupCall: Api.InputGroupCall {
return .inputGroupCall(id: self.id, accessHash: self.accessHash)
return .inputGroupCall(.init(id: self.id, accessHash: self.accessHash))
}
}
@@ -329,10 +330,12 @@ public enum CallSessionConnection: Equatable {
private func parseConnection(_ apiConnection: Api.PhoneConnection) -> CallSessionConnection {
switch apiConnection {
case let .phoneConnection(flags, id, ip, ipv6, port, peerTag):
case let .phoneConnection(phoneConnectionData):
let (flags, id, ip, ipv6, port, peerTag) = (phoneConnectionData.flags, phoneConnectionData.id, phoneConnectionData.ip, phoneConnectionData.ipv6, phoneConnectionData.port, phoneConnectionData.peerTag)
let isTcp = (flags & (1 << 0)) != 0
return .reflector(CallSessionConnection.Reflector(id: id, ip: ip, ipv6: ipv6, isTcp: isTcp, port: port, peerTag: peerTag.makeData()))
case let .phoneConnectionWebrtc(flags, id, ip, ipv6, port, username, password):
case let .phoneConnectionWebrtc(phoneConnectionWebrtcData):
let (flags, id, ip, ipv6, port, username, password) = (phoneConnectionWebrtcData.flags, phoneConnectionWebrtcData.id, phoneConnectionWebrtcData.ip, phoneConnectionWebrtcData.ipv6, phoneConnectionWebrtcData.port, phoneConnectionWebrtcData.username, phoneConnectionWebrtcData.password)
return .webRtcReflector(CallSessionConnection.WebRtcReflector(
id: id,
hasStun: (flags & (1 << 1)) != 0,
@@ -751,7 +754,7 @@ private final class CallSessionManagerContext {
self.contexts[internalId] = context
let queue = self.queue
let requestSignal: Signal<Api.Bool, MTRpcError> = self.network.request(Api.functions.phone.receivedCall(peer: .inputPhoneCall(id: stableId, accessHash: accessHash)))
let requestSignal: Signal<Api.Bool, MTRpcError> = self.network.request(Api.functions.phone.receivedCall(peer: .inputPhoneCall(.init(id: stableId, accessHash: accessHash))))
context.acknowledgeIncomingCallDisposable.set(requestSignal.start(error: { [weak self] _ in
queue.async {
@@ -1018,7 +1021,7 @@ private final class CallSessionManagerContext {
if let context = self.contexts[internalId] {
switch context.state {
case let .active(id, accessHash, _, _, _, _, _, _, _, _, _, _):
context.signalingDisposables.add(self.network.request(Api.functions.phone.sendSignalingData(peer: .inputPhoneCall(id: id, accessHash: accessHash), data: Buffer(data: data))).start())
context.signalingDisposables.add(self.network.request(Api.functions.phone.sendSignalingData(peer: .inputPhoneCall(.init(id: id, accessHash: accessHash)), data: Buffer(data: data))).start())
default:
break
}
@@ -1073,10 +1076,12 @@ private final class CallSessionManagerContext {
switch call {
case .phoneCallEmpty:
break
case let .phoneCallAccepted(_, id, _, _, _, _, gB, remoteProtocol):
case let .phoneCallAccepted(phoneCallAcceptedData):
let (id, gB, remoteProtocol) = (phoneCallAcceptedData.id, phoneCallAcceptedData.gB, phoneCallAcceptedData.protocol)
let remoteVersions: [String]
switch remoteProtocol {
case let .phoneCallProtocol(_, _, _, versions):
case let .phoneCallProtocol(phoneCallProtocolData):
let versions = phoneCallProtocolData.libraryVersions
remoteVersions = versions
}
if let internalId = self.contextIdByStableId[id] {
@@ -1129,7 +1134,8 @@ private final class CallSessionManagerContext {
assertionFailure()
}
}
case let .phoneCallDiscarded(flags, id, reason, _):
case let .phoneCallDiscarded(phoneCallDiscardedData):
let (flags, id, reason) = (phoneCallDiscardedData.flags, phoneCallDiscardedData.id, phoneCallDiscardedData.reason)
let reportRating = (flags & (1 << 2)) != 0
let sendDebugLogs = (flags & (1 << 3)) != 0
if let internalId = self.contextIdByStableId[id] {
@@ -1145,7 +1151,8 @@ private final class CallSessionManagerContext {
parsedReason = .ended(.hungUp)
case .phoneCallDiscardReasonMissed:
parsedReason = .ended(.missed)
case let .phoneCallDiscardReasonMigrateConferenceCall(slug):
case let .phoneCallDiscardReasonMigrateConferenceCall(phoneCallDiscardReasonMigrateConferenceCallData):
let slug = phoneCallDiscardReasonMigrateConferenceCallData.slug
parsedReason = .ended(.switchedToConference(slug: slug))
}
} else {
@@ -1185,7 +1192,8 @@ private final class CallSessionManagerContext {
//assertionFailure()
}
}
case let .phoneCall(flags, id, _, _, _, _, gAOrB, keyFingerprint, callProtocol, connections, startDate, customParameters):
case let .phoneCall(phoneCallData):
let (flags, id, gAOrB, keyFingerprint, callProtocol, connections, startDate, customParameters) = (phoneCallData.flags, phoneCallData.id, phoneCallData.gAOrB, phoneCallData.keyFingerprint, phoneCallData.protocol, phoneCallData.connections, phoneCallData.startDate, phoneCallData.customParameters)
let allowsP2P = (flags & (1 << 5)) != 0
let supportsConferenceCalls = (flags & (1 << 8)) != 0
if let internalId = self.contextIdByStableId[id] {
@@ -1200,19 +1208,21 @@ private final class CallSessionManagerContext {
if let (key, calculatedKeyId, keyVisualHash) = self.makeSessionEncryptionKey(config: config, gAHash: gAHash, b: b, gA: gAOrB.makeData()) {
if keyFingerprint == calculatedKeyId {
switch callProtocol {
case let .phoneCallProtocol(_, _, maxLayer, versions):
case let .phoneCallProtocol(phoneCallProtocolData):
let (maxLayer, versions) = (phoneCallProtocolData.maxLayer, phoneCallProtocolData.libraryVersions)
if !versions.isEmpty {
var customParametersValue: String?
switch customParameters {
case .none:
break
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
customParametersValue = data
}
let isVideoPossible = self.videoVersions().contains(where: { versions.contains($0) })
context.isVideoPossible = isVideoPossible
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: calculatedKeyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connections.first!, alternative: Array(connections[1...])), maxLayer: maxLayer, version: versions[0], customParameters: customParametersValue, allowsP2P: allowsP2P, supportsConferenceCalls: supportsConferenceCalls)
self.contextUpdated(internalId: internalId)
} else {
@@ -1227,19 +1237,21 @@ private final class CallSessionManagerContext {
}
case let .confirming(id, accessHash, key, keyId, keyVisualHash, _):
switch callProtocol {
case let .phoneCallProtocol(_, _, maxLayer, versions):
case let .phoneCallProtocol(phoneCallProtocolData):
let (maxLayer, versions) = (phoneCallProtocolData.maxLayer, phoneCallProtocolData.libraryVersions)
if !versions.isEmpty {
var customParametersValue: String?
switch customParameters {
case .none:
break
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
customParametersValue = data
}
let isVideoPossible = self.videoVersions().contains(where: { versions.contains($0) })
context.isVideoPossible = isVideoPossible
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: keyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connections.first!, alternative: Array(connections[1...])), maxLayer: maxLayer, version: versions[0], customParameters: customParametersValue, allowsP2P: allowsP2P, supportsConferenceCalls: supportsConferenceCalls)
self.contextUpdated(internalId: internalId)
} else {
@@ -1251,11 +1263,13 @@ private final class CallSessionManagerContext {
assertionFailure()
}
}
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, gAHash, requestedProtocol):
case let .phoneCallRequested(phoneCallRequestedData):
let (flags, id, accessHash, date, adminId, gAHash, requestedProtocol) = (phoneCallRequestedData.flags, phoneCallRequestedData.id, phoneCallRequestedData.accessHash, phoneCallRequestedData.date, phoneCallRequestedData.adminId, phoneCallRequestedData.gAHash, phoneCallRequestedData.protocol)
let isVideo = (flags & (1 << 6)) != 0
let versions: [String]
switch requestedProtocol {
case let .phoneCallProtocol(_, _, _, libraryVersions):
case let .phoneCallProtocol(phoneCallProtocolData):
let libraryVersions = phoneCallProtocolData.libraryVersions
versions = libraryVersions
}
if self.contextIdByStableId[id] == nil {
@@ -1276,7 +1290,8 @@ private final class CallSessionManagerContext {
}
}
}
case let .phoneCallWaiting(_, id, _, _, _, _, _, receiveDate):
case let .phoneCallWaiting(phoneCallWaitingData):
let (id, receiveDate) = (phoneCallWaitingData.id, phoneCallWaitingData.receiveDate)
if let internalId = self.contextIdByStableId[id] {
if let context = self.contexts[internalId] {
switch context.state {
@@ -1598,7 +1613,7 @@ private func acceptCallSession(accountPeerId: PeerId, postbox: Postbox, network:
return .single(.failed)
}
return network.request(Api.functions.phone.acceptCall(peer: .inputPhoneCall(id: stableId, accessHash: accessHash), gB: Buffer(data: gb), protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions)))
return network.request(Api.functions.phone.acceptCall(peer: .inputPhoneCall(.init(id: stableId, accessHash: accessHash)), gB: Buffer(data: gb), protocol: .phoneCallProtocol(.init(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.phone.PhoneCall?, NoError> in
return .single(nil)
@@ -1607,7 +1622,8 @@ private func acceptCallSession(accountPeerId: PeerId, postbox: Postbox, network:
if let call = call {
return postbox.transaction { transaction -> AcceptCallResult in
switch call {
case let .phoneCall(phoneCall, users):
case let .phoneCall(phoneCallData):
let (phoneCall, users) = (phoneCallData.phoneCall, phoneCallData.users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
switch phoneCall {
@@ -1615,19 +1631,22 @@ private func acceptCallSession(accountPeerId: PeerId, postbox: Postbox, network:
return .failed
case .phoneCallWaiting:
return .success(.waiting(config: config))
case let .phoneCall(flags, id, _, _, _, _, gAOrB, _, callProtocol, connections, startDate, customParameters):
case let .phoneCall(phoneCallData):
let (flags, id, gAOrB, callProtocol, connections, startDate, customParameters) = (phoneCallData.flags, phoneCallData.id, phoneCallData.gAOrB, phoneCallData.protocol, phoneCallData.connections, phoneCallData.startDate, phoneCallData.customParameters)
if id == stableId {
switch callProtocol{
case let .phoneCallProtocol(_, _, maxLayer, versions):
case let .phoneCallProtocol(phoneCallProtocolData):
let (maxLayer, versions) = (phoneCallProtocolData.maxLayer, phoneCallProtocolData.libraryVersions)
if !versions.isEmpty {
var customParametersValue: String?
switch customParameters {
case .none:
break
case let .dataJSON(data):
case let .dataJSON(dataJSONData):
let data = dataJSONData.data
customParametersValue = data
}
return .success(.call(config: config, gA: gAOrB.makeData(), timestamp: startDate, connections: parseConnectionSet(primary: connections.first!, alternative: Array(connections[1...])), maxLayer: maxLayer, version: versions[0], customParameters: customParametersValue, allowsP2P: (flags & (1 << 5)) != 0, supportsConferenceCalls: (flags & (1 << 8)) != 0))
} else {
return .failed
@@ -1672,14 +1691,17 @@ private func requestCallSession(postbox: Postbox, network: Network, peerId: Peer
callFlags |= 1 << 0
}
return network.request(Api.functions.phone.requestCall(flags: callFlags, userId: inputUser, randomId: Int32(bitPattern: arc4random()), gAHash: Buffer(data: gAHash), protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions)))
return network.request(Api.functions.phone.requestCall(flags: callFlags, userId: inputUser, randomId: Int32(bitPattern: arc4random()), gAHash: Buffer(data: gAHash), protocol: .phoneCallProtocol(.init(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions))))
|> map { result -> RequestCallSessionResult in
switch result {
case let .phoneCall(phoneCall, _):
case let .phoneCall(phoneCallData):
let (phoneCall, _) = (phoneCallData.phoneCall, phoneCallData.users)
switch phoneCall {
case let .phoneCallRequested(_, id, accessHash, _, _, _, _, _):
case let .phoneCallRequested(phoneCallRequestedData):
let (id, accessHash) = (phoneCallRequestedData.id, phoneCallRequestedData.accessHash)
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: nil)
case let .phoneCallWaiting(_, id, accessHash, _, _, _, _, receiveDate):
case let .phoneCallWaiting(phoneCallWaitingData):
let (id, accessHash, receiveDate) = (phoneCallWaitingData.id, phoneCallWaitingData.accessHash, phoneCallWaitingData.receiveDate)
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: receiveDate)
default:
return .failed(.generic)
@@ -1709,7 +1731,7 @@ private func requestCallSession(postbox: Postbox, network: Network, peerId: Peer
}
private func confirmCallSession(network: Network, stableId: CallSessionStableId, accessHash: Int64, gA: Data, keyFingerprint: Int64, maxLayer: Int32, versions: [String]) -> Signal<Api.PhoneCall?, NoError> {
return network.request(Api.functions.phone.confirmCall(peer: Api.InputPhoneCall.inputPhoneCall(id: stableId, accessHash: accessHash), gA: Buffer(data: gA), keyFingerprint: keyFingerprint, protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions)))
return network.request(Api.functions.phone.confirmCall(peer: Api.InputPhoneCall.inputPhoneCall(.init(id: stableId, accessHash: accessHash)), gA: Buffer(data: gA), keyFingerprint: keyFingerprint, protocol: .phoneCallProtocol(.init(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.phone.PhoneCall?, NoError> in
return .single(nil)
@@ -1717,7 +1739,8 @@ private func confirmCallSession(network: Network, stableId: CallSessionStableId,
|> map { result -> Api.PhoneCall? in
if let result = result {
switch result {
case let .phoneCall(phoneCall, _):
case let .phoneCall(phoneCallData):
let (phoneCall, _) = (phoneCallData.phoneCall, phoneCallData.users)
return phoneCall
}
} else {
@@ -1751,7 +1774,7 @@ private func dropCallSession(network: Network, addUpdates: @escaping (Api.Update
case .missed:
mappedReason = .phoneCallDiscardReasonMissed
case let .switchToConference(slug):
mappedReason = .phoneCallDiscardReasonMigrateConferenceCall(slug: slug)
mappedReason = .phoneCallDiscardReasonMigrateConferenceCall(.init(slug: slug))
}
var callFlags: Int32 = 0
@@ -1759,7 +1782,7 @@ private func dropCallSession(network: Network, addUpdates: @escaping (Api.Update
callFlags |= 1 << 0
}
return network.request(Api.functions.phone.discardCall(flags: callFlags, peer: Api.InputPhoneCall.inputPhoneCall(id: stableId, accessHash: accessHash), duration: duration, reason: mappedReason, connectionId: 0))
return network.request(Api.functions.phone.discardCall(flags: callFlags, peer: Api.InputPhoneCall.inputPhoneCall(.init(id: stableId, accessHash: accessHash)), duration: duration, reason: mappedReason, connectionId: 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
@@ -1769,12 +1792,15 @@ private func dropCallSession(network: Network, addUpdates: @escaping (Api.Update
var sendDebugLogs: Bool = false
if let updates = updates {
switch updates {
case .updates(let updates, _, _, _, _):
case let .updates(updatesData):
let updates = updatesData.updates
for update in updates {
switch update {
case .updatePhoneCall(let phoneCall):
case let .updatePhoneCall(updatePhoneCallData):
let phoneCall = updatePhoneCallData.phoneCall
switch phoneCall {
case let .phoneCallDiscarded(flags, _, _, _):
case let .phoneCallDiscarded(phoneCallDiscardedData):
let flags = phoneCallDiscardedData.flags
reportRating = (flags & (1 << 2)) != 0
sendDebugLogs = (flags & (1 << 3)) != 0
default:
@@ -100,7 +100,8 @@ func _internal_getChannelBoostStatus(account: Account, peerId: PeerId) -> Signal
return nil
}
switch result {
case let .boostsStatus(flags, level, currentLevelBoosts, boosts, giftBoosts, nextLevelBoosts, premiumAudience, boostUrl, prepaidGiveaways, myBoostSlots):
case let .boostsStatus(boostsStatusData):
let (flags, level, currentLevelBoosts, boosts, giftBoosts, nextLevelBoosts, premiumAudience, boostUrl, prepaidGiveaways, myBoostSlots) = (boostsStatusData.flags, boostsStatusData.level, boostsStatusData.currentLevelBoosts, boostsStatusData.boosts, boostsStatusData.giftBoosts, boostsStatusData.nextLevelBoosts, boostsStatusData.premiumAudience, boostsStatusData.boostUrl, boostsStatusData.prepaidGiveaways, boostsStatusData.myBoostSlots)
let _ = myBoostSlots
return ChannelBoostStatus(level: Int(level), boosts: Int(boosts), giftBoosts: giftBoosts.flatMap(Int.init), currentLevelBoosts: Int(currentLevelBoosts), nextLevelBoosts: nextLevelBoosts.flatMap(Int.init), premiumAudience: premiumAudience.flatMap({ StatsPercentValue(apiPercentValue: $0) }), url: boostUrl, prepaidGiveaways: prepaidGiveaways?.map({ PrepaidGiveaway(apiPrepaidGiveaway: $0) }) ?? [], boostedByMe: (flags & (1 << 2)) != 0)
}
@@ -274,12 +275,14 @@ private final class ChannelBoostersContextImpl {
return ([], 0, nil)
}
switch result {
case let .boostsList(_, count, boosts, nextOffset, users):
case let .boostsList(boostsListData):
let (_, count, boosts, nextOffset, users) = (boostsListData.flags, boostsListData.count, boostsListData.boosts, boostsListData.nextOffset, boostsListData.users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
var resultBoosts: [ChannelBoostersContext.State.Boost] = []
for boost in boosts {
switch boost {
case let .boost(flags, id, userId, giveawayMessageId, date, expires, usedGiftSlug, multiplier, stars):
case let .boost(boostData):
let (flags, id, userId, giveawayMessageId, date, expires, usedGiftSlug, multiplier, stars) = (boostData.flags, boostData.id, boostData.userId, boostData.giveawayMsgId, boostData.date, boostData.expires, boostData.usedGiftSlug, boostData.multiplier, boostData.stars)
var boostFlags: ChannelBoostersContext.State.Boost.Flags = []
var boostPeer: EnginePeer?
if let userId = userId {
@@ -546,12 +549,14 @@ extension MyBoostStatus {
init(apiMyBoostStatus: Api.premium.MyBoosts, accountPeerId: PeerId, transaction: Transaction) {
var boostsResult: [MyBoostStatus.Boost] = []
switch apiMyBoostStatus {
case let .myBoosts(myBoosts, chats, users):
case let .myBoosts(myBoostsData):
let (myBoosts, chats, users) = (myBoostsData.myBoosts, myBoostsData.chats, myBoostsData.users)
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
for boost in myBoosts {
switch boost {
case let .myBoost(_, slot, peer, date, expires, cooldownUntilDate):
case let .myBoost(myBoostData):
let (slot, peer, date, expires, cooldownUntilDate) = (myBoostData.slot, myBoostData.peer, myBoostData.date, myBoostData.expires, myBoostData.cooldownUntilDate)
var boostPeer: EnginePeer?
if let peerId = peer?.peerId, let peer = transaction.getPeer(peerId) {
boostPeer = EnginePeer(peer)
@@ -14,13 +14,17 @@ func channelUpdatesByPeerId(updates: [ChannelUpdate]) -> [PeerId: [ChannelUpdate
for update in updates {
var peerId: PeerId?
switch update.update {
case let .updateNewChannelMessage(message, _, _):
case let .updateNewChannelMessage(updateNewChannelMessageData):
let (message, _, _) = (updateNewChannelMessageData.message, updateNewChannelMessageData.pts, updateNewChannelMessageData.ptsCount)
peerId = apiMessagePeerId(message)
case let .updateDeleteChannelMessages(channelId, _, _, _):
case let .updateDeleteChannelMessages(updateDeleteChannelMessagesData):
let (channelId, _, _, _) = (updateDeleteChannelMessagesData.channelId, updateDeleteChannelMessagesData.messages, updateDeleteChannelMessagesData.pts, updateDeleteChannelMessagesData.ptsCount)
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
case let .updateEditChannelMessage(message, _, _):
case let .updateEditChannelMessage(updateEditChannelMessageData):
let (message, _, _) = (updateEditChannelMessageData.message, updateEditChannelMessageData.pts, updateEditChannelMessageData.ptsCount)
peerId = apiMessagePeerId(message)
case let .updateChannelWebPage(channelId, _, _, _):
case let .updateChannelWebPage(updateChannelWebPageData):
let (channelId, _, _, _) = (updateChannelWebPageData.channelId, updateChannelWebPageData.webpage, updateChannelWebPageData.pts, updateChannelWebPageData.ptsCount)
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
default:
break
@@ -326,7 +326,7 @@ private func pushDeviceContactData(accountPeerId: PeerId, postbox: Postbox, netw
batches = batches
|> mapToSignal { intermediateResult -> Signal<PushDeviceContactsResult, NoError> in
return network.request(Api.functions.contacts.importContacts(contacts: zip(0 ..< batch.count, batch).map { index, item -> Api.InputContact in
return .inputPhoneContact(flags: 0, clientId: Int64(index), phone: item.0.rawValue, firstName: item.1.firstName, lastName: item.1.lastName, note: nil)
return .inputPhoneContact(.init(flags: 0, clientId: Int64(index), phone: item.0.rawValue, firstName: item.1.firstName, lastName: item.1.lastName, note: nil))
}))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.contacts.ImportedContacts?, NoError> in
@@ -341,12 +341,14 @@ private func pushDeviceContactData(accountPeerId: PeerId, postbox: Postbox, netw
var importedCounts: [Int: Int32] = [:]
var peerIdByClientId: [Int64: PeerId] = [:]
switch result {
case let .importedContacts(imported, popularInvites, retryContacts, users):
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
case let .importedContacts(importedContactsData):
let (imported, popularInvites, retryContacts, users) = (importedContactsData.imported, importedContactsData.popularInvites, importedContactsData.retryContacts, importedContactsData.users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
for item in imported {
switch item {
case let .importedContact(userId, clientId):
case let .importedContact(importedContactData):
let (userId, clientId) = (importedContactData.userId, importedContactData.clientId)
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
addedContactPeerIds.insert(peerId)
peerIdByClientId[clientId] = peerId
@@ -357,7 +359,8 @@ private func pushDeviceContactData(accountPeerId: PeerId, postbox: Postbox, netw
}
for item in popularInvites {
switch item {
case let .popularContact(clientId, importers):
case let .popularContact(popularContactData):
let (clientId, importers) = (popularContactData.clientId, popularContactData.importers)
importedCounts[Int(clientId)] = importers
}
}
@@ -405,7 +408,8 @@ private func updateContactPresences(postbox: Postbox, network: Network, accountP
var peerPresences: [PeerId: PeerPresence] = [:]
for status in statuses {
switch status {
case let .contactStatus(userId, status):
case let .contactStatus(contactStatusData):
let (userId, status) = (contactStatusData.userId, contactStatusData.status)
peerPresences[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))] = TelegramUserPresence(apiStatus: status)
}
}
@@ -159,26 +159,30 @@ func managedSynchronizeEmojiSearchCategories(postbox: Postbox, network: Network,
|> mapToSignal { result -> Signal<Never, NoError> in
return postbox.transaction { transaction -> Signal<Never, NoError> in
switch result {
case let .emojiGroups(hash, groups):
case let .emojiGroups(emojiGroupsData):
let (hash, groups) = (emojiGroupsData.hash, emojiGroupsData.groups)
let categories = EmojiSearchCategories(
hash: hash,
groups: groups.compactMap { item -> EmojiSearchCategories.Group? in
switch item {
case let .emojiGroup(title, iconEmojiId, emoticons):
case let .emojiGroup(emojiGroupData):
let (title, iconEmojiId, emoticons) = (emojiGroupData.title, emojiGroupData.iconEmojiId, emojiGroupData.emoticons)
return EmojiSearchCategories.Group(
id: iconEmojiId,
title: title,
identifiers: emoticons,
kind: .generic
)
case let .emojiGroupGreeting(title, iconEmojiId, emoticons):
case let .emojiGroupGreeting(emojiGroupGreetingData):
let (title, iconEmojiId, emoticons) = (emojiGroupGreetingData.title, emojiGroupGreetingData.iconEmojiId, emojiGroupGreetingData.emoticons)
return EmojiSearchCategories.Group(
id: iconEmojiId,
title: title,
identifiers: emoticons,
kind: .greeting
)
case let .emojiGroupPremium(title, iconEmojiId):
case let .emojiGroupPremium(emojiGroupPremiumData):
let (title, iconEmojiId) = (emojiGroupPremiumData.title, emojiGroupPremiumData.iconEmojiId)
return EmojiSearchCategories.Group(
id: iconEmojiId,
title: title,
@@ -30,9 +30,11 @@ struct ParsedDialogs {
private func extractDialogsData(dialogs: Api.messages.Dialogs) -> (apiDialogs: [Api.Dialog], apiMessages: [Api.Message], apiChats: [Api.Chat], apiUsers: [Api.User], apiIsAtLowestBoundary: Bool) {
switch dialogs {
case let .dialogs(dialogs, messages, chats, users):
case let .dialogs(dialogsData):
let (dialogs, messages, chats, users) = (dialogsData.dialogs, dialogsData.messages, dialogsData.chats, dialogsData.users)
return (dialogs, messages, chats, users, true)
case let .dialogsSlice(_, dialogs, messages, chats, users):
case let .dialogsSlice(dialogsSliceData):
let (_, dialogs, messages, chats, users) = (dialogsSliceData.count, dialogsSliceData.dialogs, dialogsSliceData.messages, dialogsSliceData.chats, dialogsSliceData.users)
return (dialogs, messages, chats, users, false)
case .dialogsNotModified:
assertionFailure()
@@ -42,7 +44,8 @@ private func extractDialogsData(dialogs: Api.messages.Dialogs) -> (apiDialogs: [
private func extractDialogsData(peerDialogs: Api.messages.PeerDialogs) -> (apiDialogs: [Api.Dialog], apiMessages: [Api.Message], apiChats: [Api.Chat], apiUsers: [Api.User], apiIsAtLowestBoundary: Bool) {
switch peerDialogs {
case let .peerDialogs(dialogs, messages, chats, users, _):
case let .peerDialogs(peerDialogsData):
let (dialogs, messages, chats, users) = (peerDialogsData.dialogs, peerDialogsData.messages, peerDialogsData.chats, peerDialogsData.users)
return (dialogs, messages, chats, users, false)
}
}
@@ -77,7 +80,8 @@ private func parseDialogs(accountPeerId: PeerId, apiDialogs: [Api.Dialog], apiMe
var apiChannelPts: Int32?
let apiNotificationSettings: Api.PeerNotifySettings
switch dialog {
case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, peerNotificationSettings, pts, _, _, ttlPeriod):
case let .dialog(dialogData):
let (flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, peerNotificationSettings, pts, ttlPeriod) = (dialogData.flags, dialogData.peer, dialogData.topMessage, dialogData.readInboxMaxId, dialogData.readOutboxMaxId, dialogData.unreadCount, dialogData.unreadMentionsCount, dialogData.unreadReactionsCount, dialogData.notifySettings, dialogData.pts, dialogData.ttlPeriod)
if let peer = peers.get(peer.peerId) {
var isExluded = false
if let group = peer as? TelegramGroup {
@@ -109,11 +113,14 @@ private func parseDialogs(accountPeerId: PeerId, apiDialogs: [Api.Dialog], apiMe
}
let peerId: PeerId
switch apiPeer {
case let .peerUser(userId):
case let .peerUser(peerUserData):
let userId = peerUserData.userId
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
case let .peerChat(chatId):
case let .peerChat(peerChatData):
let chatId = peerChatData.chatId
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId))
case let .peerChannel(channelId):
case let .peerChannel(peerChannelData):
let channelId = peerChannelData.channelId
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
}
@@ -133,9 +140,11 @@ private func parseDialogs(accountPeerId: PeerId, apiDialogs: [Api.Dialog], apiMe
}
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
case let .dialogFolder(_, folder, _, _, unreadMutedPeersCount, _, unreadMutedMessagesCount, _):
case let .dialogFolder(dialogFolderData):
let (folder, unreadMutedPeersCount, unreadMutedMessagesCount) = (dialogFolderData.folder, dialogFolderData.unreadMutedPeersCount, dialogFolderData.unreadMutedMessagesCount)
switch folder {
case let .folder(_, id, _, _):
case let .folder(folderData):
let id = folderData.id
referencedFolders[PeerGroupId(rawValue: id)] = PeerGroupUnreadCountersSummary(all: PeerGroupUnreadCounters(messageCount: unreadMutedMessagesCount, chatCount: unreadMutedPeersCount))
}
}
@@ -558,17 +558,20 @@ private func validateChannelMessagesBatch(postbox: Postbox, network: Network, ac
var channelPts: Int32?
switch result {
case let .messages(messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.topics, messagesSliceData.chats, messagesSliceData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, pts, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (pts, apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.pts, channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -629,17 +632,20 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
var channelPts: Int32?
switch result {
case let .messages(messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.topics, messagesSliceData.chats, messagesSliceData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, pts, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (pts, apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.pts, channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -653,7 +659,7 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
} else {
return .complete()
}
return validateReplyThreadBatch(postbox: postbox, network: network, transaction: transaction, accountPeerId: accountPeerId, peerId: peerId, threadId: Int64(threadMessageId), signal: signal, previous: previous, messageNamespace: Namespaces.Message.Cloud)
}
|> switchToLatest
@@ -673,17 +679,20 @@ private func validateScheduledMessagesBatch(postbox: Postbox, network: Network,
let users: [Api.User]
switch result {
case let .messages(messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.topics, messagesSliceData.chats, messagesSliceData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, _, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -721,17 +730,20 @@ private func validateQuickReplyMessagesBatch(postbox: Postbox, network: Network,
let users: [Api.User]
switch result {
case let .messages(messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, topics: apiTopics, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.topics, messagesSliceData.chats, messagesSliceData.users)
let _ = apiTopics
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, _, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -802,16 +814,19 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran
case let .channel(peerId, _):
actuallyRemovedMessagesSignal = postbox.transaction { transaction -> Signal<Set<MessageId>, NoError> in
if let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel) {
return network.request(Api.functions.channels.getMessages(channel: inputChannel, id: maybeRemovedMessageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
return network.request(Api.functions.channels.getMessages(channel: inputChannel, id: maybeRemovedMessageIds.map({ Api.InputMessage.inputMessageID(.init(id: $0.id)) })))
|> map { result -> Set<MessageId> in
let apiMessages: [Api.Message]
switch result {
case let .channelMessages(_, _, _, _, messages, apiTopics, _, _):
case let .channelMessages(channelMessagesData):
let (messages, apiTopics) = (channelMessagesData.messages, channelMessagesData.topics)
apiMessages = messages
let _ = apiTopics
case let .messages(messages, _, _, _):
case let .messages(messagesData):
let messages = messagesData.messages
apiMessages = messages
case let .messagesSlice(_, _, _, _, _, messages, _, _, _):
case let .messagesSlice(messagesSliceData):
let messages = messagesSliceData.messages
apiMessages = messages
case .messagesNotModified:
return Set()
@@ -1051,16 +1066,19 @@ private func validateReplyThreadBatch(postbox: Postbox, network: Network, transa
} else {
actuallyRemovedMessagesSignal = postbox.transaction { transaction -> Signal<Set<MessageId>, NoError> in
if let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel) {
return network.request(Api.functions.channels.getMessages(channel: inputChannel, id: maybeRemovedMessageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
return network.request(Api.functions.channels.getMessages(channel: inputChannel, id: maybeRemovedMessageIds.map({ Api.InputMessage.inputMessageID(.init(id: $0.id)) })))
|> map { result -> Set<MessageId> in
let apiMessages: [Api.Message]
switch result {
case let .channelMessages(_, _, _, _, messages, apiTopics, _, _):
case let .channelMessages(channelMessagesData):
let (messages, apiTopics) = (channelMessagesData.messages, channelMessagesData.topics)
apiMessages = messages
let _ = apiTopics
case let .messages(messages, _, _, _):
case let .messages(messagesData):
let messages = messagesData.messages
apiMessages = messages
case let .messagesSlice(_, _, _, _, _, messages, _, _, _):
case let .messagesSlice(messagesSliceData):
let messages = messagesSliceData.messages
apiMessages = messages
case .messagesNotModified:
return Set()
@@ -244,21 +244,24 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
if let peer = transaction.getPeer(peerId) ?? parsedPeers.get(peerId) {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
signal = source.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
signal = source.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(.init(id: $0.id)) })))
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
if let inputChannel = apiInputChannel(peer) {
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(.init(id: $0.id)) })))
}
}
if let signal = signal {
signals.append(signal
|> map { result in
switch result {
case let .messages(messages, _, chats, users):
case let .messages(messagesData):
let (messages, _, chats, users) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
return (peer, messages, chats, users)
case let .messagesSlice(_, _, _, _, _, messages, _, chats, users):
case let .messagesSlice(messagesSliceData):
let (messages, chats, users) = (messagesSliceData.messages, messagesSliceData.chats, messagesSliceData.users)
return (peer, messages, chats, users)
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
case let .channelMessages(channelMessagesData):
let (messages, apiTopics, chats, users) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
let _ = apiTopics
return (peer, messages, chats, users)
case .messagesNotModified:
@@ -275,21 +278,24 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
if let peer = transaction.getPeer(peerId) ?? parsedPeers.get(peerId) {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
signal = source.request(Api.functions.messages.getMessages(id: messageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
signal = source.request(Api.functions.messages.getMessages(id: messageIds.map({ Api.InputMessage.inputMessageID(.init(id: $0.id)) })))
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
if let inputChannel = apiInputChannel(peer) {
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map({ Api.InputMessage.inputMessageID(.init(id: $0.id)) })))
}
}
if let signal = signal {
signals.append(signal
|> map { result in
switch result {
case let .messages(messages, _, chats, users):
case let .messages(messagesData):
let (messages, _, chats, users) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
return (peer, messages, chats, users)
case let .messagesSlice(_, _, _, _, _, messages, _, chats, users):
case let .messagesSlice(messagesSliceData):
let (messages, chats, users) = (messagesSliceData.messages, messagesSliceData.chats, messagesSliceData.users)
return (peer, messages, chats, users)
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
case let .channelMessages(channelMessagesData):
let (messages, apiTopics, chats, users) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
let _ = apiTopics
return (peer, messages, chats, users)
case .messagesNotModified:
@@ -919,15 +925,18 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
let users: [Api.User]
var channelPts: Int32?
switch result {
case let .messages(messages: apiMessages, _, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, _, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, _, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.chats, messagesSliceData.users)
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, pts, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (pts, apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.pts, channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -1089,13 +1098,13 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
func groupBoundaryPeer(_ peerId: PeerId, accountPeerId: PeerId) -> Api.Peer {
switch peerId.namespace {
case Namespaces.Peer.CloudUser:
return Api.Peer.peerUser(userId: peerId.id._internalGetInt64Value())
return Api.Peer.peerUser(.init(userId: peerId.id._internalGetInt64Value()))
case Namespaces.Peer.CloudGroup:
return Api.Peer.peerChat(chatId: peerId.id._internalGetInt64Value())
return Api.Peer.peerChat(.init(chatId: peerId.id._internalGetInt64Value()))
case Namespaces.Peer.CloudChannel:
return Api.Peer.peerChannel(channelId: peerId.id._internalGetInt64Value())
return Api.Peer.peerChannel(.init(channelId: peerId.id._internalGetInt64Value()))
default:
return Api.Peer.peerUser(userId: accountPeerId.id._internalGetInt64Value())
return Api.Peer.peerUser(.init(userId: accountPeerId.id._internalGetInt64Value()))
}
}
@@ -1210,22 +1219,25 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
offset = single((holeIndex.timestamp, min(holeIndex.id.id, Int32.max - 1) + 1, Api.InputPeer.inputPeerEmpty), NoError.self)
return offset
|> mapToSignal { (timestamp, id, peer) -> Signal<Void, NoError> in
let searchResult = network.request(Api.functions.messages.search(flags: 0, peer: .inputPeerEmpty, q: "", fromId: nil, savedPeerId: nil, savedReaction: nil, topMsgId: nil, filter: .inputMessagesFilterPhoneCalls(flags: 0), minDate: 0, maxDate: holeIndex.timestamp, offsetId: 0, addOffset: 0, limit: limit, maxId: holeIndex.id.id, minId: 0, hash: 0))
let searchResult = network.request(Api.functions.messages.search(flags: 0, peer: .inputPeerEmpty, q: "", fromId: nil, savedPeerId: nil, savedReaction: nil, topMsgId: nil, filter: .inputMessagesFilterPhoneCalls(.init(flags: 0)), minDate: 0, maxDate: holeIndex.timestamp, offsetId: 0, addOffset: 0, limit: limit, maxId: holeIndex.id.id, minId: 0, hash: 0))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
let messages: [Api.Message]
let chats: [Api.Chat]
let users: [Api.User]
switch result {
case let .messages(messages: apiMessages, _, chats: apiChats, users: apiUsers):
case let .messages(messagesData):
let (apiMessages, _, apiChats, apiUsers) = (messagesData.messages, messagesData.topics, messagesData.chats, messagesData.users)
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, _, _, _, _, messages: apiMessages, _, chats: apiChats, users: apiUsers):
case let .messagesSlice(messagesSliceData):
let (apiMessages, apiChats, apiUsers) = (messagesSliceData.messages, messagesSliceData.chats, messagesSliceData.users)
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, _, _, _, apiMessages, apiTopics, apiChats, apiUsers):
case let .channelMessages(channelMessagesData):
let (apiMessages, apiTopics, apiChats, apiUsers) = (channelMessagesData.messages, channelMessagesData.topics, channelMessagesData.chats, channelMessagesData.users)
messages = apiMessages
let _ = apiTopics
chats = apiChats
@@ -12,7 +12,8 @@ func updateAppConfigurationOnce(postbox: Postbox, network: Network) -> Signal<Vo
return network.request(Api.functions.help.getAppConfig(hash: hash))
|> map { result -> (data: Api.JSONValue, hash: Int32)? in
switch result {
case let .appConfig(updatedHash, config):
case let .appConfig(appConfigData):
let (updatedHash, config) = (appConfigData.hash, appConfigData.config)
return (config, updatedHash)
case .appConfigNotModified:
return nil
@@ -205,7 +205,8 @@ private func removeMessages(postbox: Postbox, network: Network, stateManager: Ac
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedMessages(pts, ptsCount):
case let .affectedMessages(affectedMessagesData):
let (pts, ptsCount) = (affectedMessagesData.pts, affectedMessagesData.ptsCount)
stateManager.addUpdateGroups([.updateChannelPts(channelId: peer.id.id._internalGetInt64Value(), pts: pts, ptsCount: ptsCount)])
}
}
@@ -240,13 +241,14 @@ private func removeMessages(postbox: Postbox, network: Network, stateManager: Ac
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedMessages(pts, ptsCount):
case let .affectedMessages(affectedMessagesData):
let (pts, ptsCount) = (affectedMessagesData.pts, affectedMessagesData.ptsCount)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
}
}
return .complete()
}
signal = signal
|> then(partSignal)
}
@@ -396,7 +398,8 @@ private func requestClearHistory(postbox: Postbox, network: Network, stateManage
|> mapToSignal { result -> Signal<Void, Bool> in
if let result = result {
switch result {
case let .affectedHistory(pts, ptsCount, offset):
case let .affectedHistory(affectedHistoryData):
let (pts, ptsCount, offset) = (affectedHistoryData.pts, affectedHistoryData.ptsCount, affectedHistoryData.offset)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
if offset == 0 {
return .fail(true)
@@ -463,7 +466,8 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|> mapToSignal { result -> Signal<Void, Bool> in
if let result = result {
switch result {
case let .affectedHistory(pts, ptsCount, offset):
case let .affectedHistory(affectedHistoryData):
let (pts, ptsCount, offset) = (affectedHistoryData.pts, affectedHistoryData.ptsCount, affectedHistoryData.offset)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
if offset == 0 {
return .fail(true)
@@ -491,7 +495,8 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedHistory(pts, ptsCount, _):
case let .affectedHistory(affectedHistoryData):
let (pts, ptsCount) = (affectedHistoryData.pts, affectedHistoryData.ptsCount)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
return .complete()
}
@@ -539,7 +544,8 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|> mapToSignal { result -> Signal<Void, Bool> in
if let result = result {
switch result {
case let .affectedHistory(pts, ptsCount, offset):
case let .affectedHistory(affectedHistoryData):
let (pts, ptsCount, offset) = (affectedHistoryData.pts, affectedHistoryData.ptsCount, affectedHistoryData.offset)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
if offset == 0 {
return .fail(true)
@@ -14,11 +14,13 @@ func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountM
|> mapToSignal { result, defaultHistoryTtl -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Signal<Void, NoError> in
switch result {
case let .config(flags, _, _, _, _, dcOptions, _, chatSizeMax, megagroupSizeMax, forwardedCountMax, _, _, _, _, _, _, _, _, editTimeLimit, revokeTimeLimit, revokePmTimeLimit, _, stickersRecentLimit, _, _, _, _, _, _, _, autoupdateUrlPrefix, gifSearchUsername, venueSearchUsername, imgSearchUsername, _, _, _, webfileDcId, suggestedLangCode, langPackVersion, baseLangPackVersion, reactionsDefault, autologinToken):
case let .config(configData):
let (flags, dcOptions, chatSizeMax, megagroupSizeMax, forwardedCountMax, editTimeLimit, revokeTimeLimit, revokePmTimeLimit, stickersRecentLimit, autoupdateUrlPrefix, gifSearchUsername, venueSearchUsername, imgSearchUsername, webfileDcId, suggestedLangCode, langPackVersion, baseLangPackVersion, reactionsDefault, autologinToken) = (configData.flags, configData.dcOptions, configData.chatSizeMax, configData.megagroupSizeMax, configData.forwardedCountMax, configData.editTimeLimit, configData.revokeTimeLimit, configData.revokePmTimeLimit, configData.stickersRecentLimit, configData.autoupdateUrlPrefix, configData.gifSearchUsername, configData.venueSearchUsername, configData.imgSearchUsername, configData.webfileDcId, configData.suggestedLangCode, configData.langPackVersion, configData.baseLangPackVersion, configData.reactionsDefault, configData.autologinToken)
var addressList: [Int: [MTDatacenterAddress]] = [:]
for option in dcOptions {
switch option {
case let .dcOption(flags, id, ipAddress, port, secret):
case let .dcOption(dcOptionData):
let (flags, id, ipAddress, port, secret) = (dcOptionData.flags, dcOptionData.id, dcOptionData.ipAddress, dcOptionData.port, dcOptionData.secret)
let preferForMedia = (flags & (1 << 1)) != 0
if addressList[Int(id)] == nil {
addressList[Int(id)] = []
@@ -77,7 +79,8 @@ func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountM
let messageAutoremoveSeconds: Int32?
switch defaultHistoryTtl {
case let .defaultHistoryTTL(period):
case let .defaultHistoryTTL(defaultHistoryTTLData):
let period = defaultHistoryTTLData.period
if period != 0 {
messageAutoremoveSeconds = period
} else {
@@ -256,7 +256,8 @@ private func synchronizeConsumeMessageContents(transaction: Transaction, postbox
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedMessages(pts, ptsCount):
case let .affectedMessages(affectedMessagesData):
let (pts, ptsCount) = (affectedMessagesData.pts, affectedMessagesData.ptsCount)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
}
}
@@ -324,7 +325,8 @@ private func synchronizeReadMessageReactions(transaction: Transaction, postbox:
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedMessages(pts, ptsCount):
case let .affectedMessages(affectedMessagesData):
let (pts, ptsCount) = (affectedMessagesData.pts, affectedMessagesData.ptsCount)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
}
}
@@ -386,7 +388,7 @@ private func synchronizeReadMessageReactions(transaction: Transaction, postbox:
private func synchronizeUnseenPersonalMentionsTag(postbox: Postbox, network: Network, entry: InvalidatedMessageHistoryTagsSummaryEntry) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(entry.key.peerId), let inputPeer = apiInputPeer(peer) {
return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(peer: inputPeer)]))
return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(.init(peer: inputPeer))]))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.PeerDialogs?, NoError> in
return .single(nil)
@@ -394,20 +396,22 @@ private func synchronizeUnseenPersonalMentionsTag(postbox: Postbox, network: Net
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .peerDialogs(dialogs, _, _, _, _):
case let .peerDialogs(peerDialogsData):
let dialogs = peerDialogsData.dialogs
if let dialog = dialogs.filter({ $0.peerId == entry.key.peerId }).first {
let apiTopMessage: Int32
let apiUnreadMentionsCount: Int32
switch dialog {
case let .dialog(_, _, topMessage, _, _, _, unreadMentionsCount, _, _, _, _, _, _):
case let .dialog(dialogData):
let (topMessage, unreadMentionsCount) = (dialogData.topMessage, dialogData.unreadMentionsCount)
apiTopMessage = topMessage
apiUnreadMentionsCount = unreadMentionsCount
case .dialogFolder:
assertionFailure()
return .complete()
}
return postbox.transaction { transaction -> Void in
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: apiUnreadMentionsCount, maxId: apiTopMessage)
}
@@ -428,7 +432,7 @@ private func synchronizeUnseenPersonalMentionsTag(postbox: Postbox, network: Net
private func synchronizeUnseenReactionsTag(postbox: Postbox, network: Network, entry: InvalidatedMessageHistoryTagsSummaryEntry) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(entry.key.peerId), let inputPeer = apiInputPeer(peer) {
return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(peer: inputPeer)]))
return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(.init(peer: inputPeer))]))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.PeerDialogs?, NoError> in
return .single(nil)
@@ -436,20 +440,22 @@ private func synchronizeUnseenReactionsTag(postbox: Postbox, network: Network, e
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .peerDialogs(dialogs, _, _, _, _):
case let .peerDialogs(peerDialogsData):
let dialogs = peerDialogsData.dialogs
if let dialog = dialogs.filter({ $0.peerId == entry.key.peerId }).first {
let apiTopMessage: Int32
let apiUnreadReactionsCount: Int32
switch dialog {
case let .dialog(_, _, topMessage, _, _, _, _, unreadReactionsCount, _, _, _, _, _):
case let .dialog(dialogData):
let (topMessage, unreadReactionsCount) = (dialogData.topMessage, dialogData.unreadReactionsCount)
apiTopMessage = topMessage
apiUnreadReactionsCount = unreadReactionsCount
case .dialogFolder:
assertionFailure()
return .complete()
}
return postbox.transaction { transaction -> Void in
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: nil, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: apiUnreadReactionsCount, maxId: apiTopMessage)
}
@@ -546,7 +552,8 @@ private func synchronizeMessageHistoryTagSummary(accountPeerId: PeerId, postbox:
}
return postbox.transaction { transaction -> Void in
switch result {
case let .channelMessages(_, _, count, _, messages, _, _, _):
case let .channelMessages(channelMessagesData):
let (count, messages) = (channelMessagesData.count, channelMessagesData.messages)
let topId: Int32 = messages.first?.id(namespace: Namespaces.Message.Cloud)?.id ?? 1
transaction.replaceMessageTagSummary(peerId: entry.key.peerId, threadId: threadId, tagMask: entry.key.tagMask, namespace: entry.key.namespace, customTag: nil, count: count, maxId: topId)
default:
@@ -574,16 +581,20 @@ private func synchronizeMessageHistoryTagSummary(accountPeerId: PeerId, postbox:
let apiMessages: [Api.Message]
let apiCount: Int32
switch result {
case let .channelMessages(_, _, count, _, messages, _, _, _):
case let .channelMessages(channelMessagesData):
let (count, messages) = (channelMessagesData.count, channelMessagesData.messages)
apiMessages = messages
apiCount = count
case let .messages(messages, _, _, _):
case let .messages(messagesData):
let messages = messagesData.messages
apiMessages = messages
apiCount = Int32(messages.count)
case let .messagesNotModified(count):
case let .messagesNotModified(messagesNotModifiedData):
let count = messagesNotModifiedData.count
apiMessages = []
apiCount = count
case let .messagesSlice(_, count, _, _, _, messages, _, _, _):
case let .messagesSlice(messagesSliceData):
let (count, messages) = (messagesSliceData.count, messagesSliceData.messages)
apiMessages = messages
apiCount = count
}
@@ -731,12 +742,14 @@ func synchronizeSavedMessageTags(postbox: Postbox, network: Network, peerId: Pee
transaction.setPreferencesEntry(key: PreferencesKeys.didCacheSavedMessageTags(threadId: threadId), value: PreferencesEntry(data: Data()))
}
|> ignoreValues
case let .savedReactionTags(tags, _):
case let .savedReactionTags(savedReactionTagsData):
let tags = savedReactionTagsData.tags
var customFileIds: [Int64] = []
var parsedTags: [SavedMessageTags.Tag] = []
for tag in tags {
switch tag {
case let .savedReactionTag(_, reaction, title, count):
case let .savedReactionTag(savedReactionTagData):
let (reaction, title, count) = (savedReactionTagData.reaction, savedReactionTagData.title, savedReactionTagData.count)
guard let reaction = MessageReaction.Reaction(apiReaction: reaction) else {
continue
}
@@ -50,7 +50,8 @@ public enum EmojiGameInfo: Codable, Equatable {
extension EmojiGameInfo {
init(apiEmojiGameInfo: Api.messages.EmojiGameInfo) {
switch apiEmojiGameInfo {
case let .emojiGameDiceInfo(_, gameHash, prevStake, currentStreak, params, playsLeft):
case let .emojiGameDiceInfo(emojiGameDiceInfoData):
let (gameHash, prevStake, currentStreak, params, playsLeft) = (emojiGameDiceInfoData.gameHash, emojiGameDiceInfoData.prevStake, emojiGameDiceInfoData.currentStreak, emojiGameDiceInfoData.params, emojiGameDiceInfoData.playsLeft)
self = .available(Info(gameHash: gameHash, previousStake: prevStake, currentStreak: currentStreak, parameters: params, playsLeft: playsLeft))
case .emojiGameUnavailable:
self = .unavailable
@@ -120,7 +120,8 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
}
let chatsSettings: MessageNotificationSettings
switch chats {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
case let .peerNotifySettings(peerNotifySettingsData):
let (_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound) = (peerNotifySettingsData.flags, peerNotifySettingsData.showPreviews, peerNotifySettingsData.silent, peerNotifySettingsData.muteUntil, peerNotifySettingsData.iosSound, peerNotifySettingsData.androidSound, peerNotifySettingsData.otherSound, peerNotifySettingsData.storiesMuted, peerNotifySettingsData.storiesHideSender, peerNotifySettingsData.storiesIosSound, peerNotifySettingsData.storiesAndroidSound, peerNotifySettingsData.storiesOtherSound)
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
@@ -130,7 +131,7 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
sound = desktopSound
storiesSound = storiesDesktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
@@ -143,21 +144,21 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
} else {
displayPreviews = true
}
let storiesMutedValue: PeerStoryNotificationSettings.Mute
if let storiesMuted = storiesMuted {
storiesMutedValue = storiesMuted == .boolTrue ? .muted : .unmuted
} else {
storiesMutedValue = .default
}
var storiesHideSenderValue: PeerStoryNotificationSettings.HideSender
if let storiesHideSender = storiesHideSender {
storiesHideSenderValue = storiesHideSender == .boolTrue ? .hide : .show
} else {
storiesHideSenderValue = .default
}
chatsSettings = MessageNotificationSettings(
enabled: enabled,
displayPreviews: displayPreviews,
@@ -172,7 +173,8 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
let userSettings: MessageNotificationSettings
switch users {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
case let .peerNotifySettings(peerNotifySettingsData):
let (_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound) = (peerNotifySettingsData.flags, peerNotifySettingsData.showPreviews, peerNotifySettingsData.silent, peerNotifySettingsData.muteUntil, peerNotifySettingsData.iosSound, peerNotifySettingsData.androidSound, peerNotifySettingsData.otherSound, peerNotifySettingsData.storiesMuted, peerNotifySettingsData.storiesHideSender, peerNotifySettingsData.storiesIosSound, peerNotifySettingsData.storiesAndroidSound, peerNotifySettingsData.storiesOtherSound)
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
@@ -182,7 +184,7 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
sound = desktopSound
storiesSound = storiesDesktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
@@ -195,21 +197,21 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
} else {
displayPreviews = true
}
let storiesMutedValue: PeerStoryNotificationSettings.Mute
if let storiesMuted = storiesMuted {
storiesMutedValue = storiesMuted == .boolTrue ? .muted : .unmuted
} else {
storiesMutedValue = .default
}
var storiesHideSenderValue: PeerStoryNotificationSettings.HideSender
if let storiesHideSender = storiesHideSender {
storiesHideSenderValue = storiesHideSender == .boolTrue ? .hide : .show
} else {
storiesHideSenderValue = .default
}
userSettings = MessageNotificationSettings(
enabled: enabled,
displayPreviews: displayPreviews,
@@ -224,7 +226,8 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
let channelSettings: MessageNotificationSettings
switch channels {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
case let .peerNotifySettings(peerNotifySettingsData):
let (_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound) = (peerNotifySettingsData.flags, peerNotifySettingsData.showPreviews, peerNotifySettingsData.silent, peerNotifySettingsData.muteUntil, peerNotifySettingsData.iosSound, peerNotifySettingsData.androidSound, peerNotifySettingsData.otherSound, peerNotifySettingsData.storiesMuted, peerNotifySettingsData.storiesHideSender, peerNotifySettingsData.storiesIosSound, peerNotifySettingsData.storiesAndroidSound, peerNotifySettingsData.storiesOtherSound)
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
@@ -234,7 +237,7 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
sound = desktopSound
storiesSound = storiesDesktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
@@ -247,21 +250,21 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
} else {
displayPreviews = true
}
let storiesMutedValue: PeerStoryNotificationSettings.Mute
if let storiesMuted = storiesMuted {
storiesMutedValue = storiesMuted == .boolTrue ? .muted : .unmuted
} else {
storiesMutedValue = .default
}
var storiesHideSenderValue: PeerStoryNotificationSettings.HideSender
if let storiesHideSender = storiesHideSender {
storiesHideSenderValue = storiesHideSender == .boolTrue ? .hide : .show
} else {
storiesHideSenderValue = .default
}
channelSettings = MessageNotificationSettings(
enabled: enabled,
displayPreviews: displayPreviews,
@@ -276,7 +279,8 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
let reactionSettings: PeerReactionNotificationSettings
switch reactions {
case let .reactionsNotifySettings(_, messagesNotifyFrom, storiesNotifyFrom, sound, showPreviews):
case let .reactionsNotifySettings(reactionsNotifySettingsData):
let (_, messagesNotifyFrom, storiesNotifyFrom, sound, showPreviews) = (reactionsNotifySettingsData.flags, reactionsNotifySettingsData.messagesNotifyFrom, reactionsNotifySettingsData.storiesNotifyFrom, reactionsNotifySettingsData.sound, reactionsNotifySettingsData.showPreviews)
let mappedMessages: PeerReactionNotificationSettings.Sources
if let messagesNotifyFrom {
switch messagesNotifyFrom {
@@ -361,7 +365,7 @@ private func apiInputPeerNotifySettings(_ settings: MessageNotificationSettings)
flags |= (1 << 8)
}
return .inputPeerNotifySettings(flags: flags, showPreviews: settings.displayPreviews ? .boolTrue : .boolFalse, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound)
return .inputPeerNotifySettings(.init(flags: flags, showPreviews: settings.displayPreviews ? .boolTrue : .boolFalse, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound))
}
private func pushedNotificationSettings(network: Network, settings: GlobalNotificationSettingsSet) -> Signal<Void, NoError> {
@@ -413,13 +417,13 @@ private func pushedNotificationSettings(network: Network, settings: GlobalNotifi
reactionFlags |= 1 << 1
}
let inputReactionSettings: Api.ReactionsNotifySettings = .reactionsNotifySettings(
let inputReactionSettings: Api.ReactionsNotifySettings = .reactionsNotifySettings(.init(
flags: reactionFlags,
messagesNotifyFrom: reactionsMessages,
storiesNotifyFrom: reactionsStories,
sound: settings.reactionSettings.sound.apiSound,
showPreviews: settings.reactionSettings.hideSender == .hide ? .boolFalse : .boolTrue
)
))
let pushedReactions = network.request(Api.functions.account.setReactionsNotifySettings(settings: inputReactionSettings))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.ReactionsNotifySettings?, NoError> in
@@ -118,23 +118,23 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
case .playingGame:
return .sendMessageGamePlayAction
case let .uploadingFile(progress):
return .sendMessageUploadDocumentAction(progress: progress)
return .sendMessageUploadDocumentAction(.init(progress: progress))
case let .uploadingPhoto(progress):
return .sendMessageUploadPhotoAction(progress: progress)
return .sendMessageUploadPhotoAction(.init(progress: progress))
case let .uploadingVideo(progress):
return .sendMessageUploadVideoAction(progress: progress)
return .sendMessageUploadVideoAction(.init(progress: progress))
case .recordingInstantVideo:
return .sendMessageRecordRoundAction
case let .uploadingInstantVideo(progress):
return .sendMessageUploadRoundAction(progress: progress)
return .sendMessageUploadRoundAction(.init(progress: progress))
case .speakingInGroupCall:
return .speakingInGroupCallAction
case .choosingSticker:
return .sendMessageChooseStickerAction
case let .interactingWithEmoji(emoticon, messageId, interaction):
return .sendMessageEmojiInteraction(emoticon: emoticon, msgId: messageId.id, interaction: interaction?.apiDataJson ?? .dataJSON(data: ""))
return .sendMessageEmojiInteraction(.init(emoticon: emoticon, msgId: messageId.id, interaction: interaction?.apiDataJson ?? .dataJSON(.init(data: ""))))
case let .seeingEmojiInteraction(emoticon):
return .sendMessageEmojiInteractionSeen(emoticon: emoticon)
return .sendMessageEmojiInteractionSeen(.init(emoticon: emoticon))
}
} else {
return .sendMessageCancelAction
@@ -142,7 +142,7 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
}
private func requestActivity(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, threadId: Int64?, activity: PeerInputActivity?) -> Signal<Void, NoError> {
// GHOST MODE: Block typing indicator
// GHOST MODE: Block typing indicator updates.
if GhostModeManager.shared.shouldHideTypingIndicator {
return .complete()
}
@@ -195,7 +195,7 @@ private func requestActivity(postbox: Postbox, network: Network, accountPeerId:
}
} else if let peer = peer as? TelegramSecretChat, activity == .typingText {
let _ = PeerId(peer.id.toInt64())
return network.request(Api.functions.messages.setEncryptedTyping(peer: .inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash), typing: .boolTrue))
return network.request(Api.functions.messages.setEncryptedTyping(peer: .inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash)), typing: .boolTrue))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
@@ -132,15 +132,19 @@ func getLocalization(_ transaction: AccountManagerModifier<TelegramAccountManage
private func parseLangPackDifference(_ difference: Api.LangPackDifference) -> (code: String, fromVersion: Int32, version: Int32, entries: [LocalizationEntry]) {
switch difference {
case let .langPackDifference(code, fromVersion, version, strings):
case let .langPackDifference(langPackDifferenceData):
let (code, fromVersion, version, strings) = (langPackDifferenceData.langCode, langPackDifferenceData.fromVersion, langPackDifferenceData.version, langPackDifferenceData.strings)
var entries: [LocalizationEntry] = []
for string in strings {
switch string {
case let .langPackString(key, value):
case let .langPackString(langPackStringData):
let (key, value) = (langPackStringData.key, langPackStringData.value)
entries.append(.string(key: key, value: value))
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
case let .langPackStringPluralized(langPackStringPluralizedData):
let (key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue) = (langPackStringPluralizedData.key, langPackStringPluralizedData.zeroValue, langPackStringPluralizedData.oneValue, langPackStringPluralizedData.twoValue, langPackStringPluralizedData.fewValue, langPackStringPluralizedData.manyValue, langPackStringPluralizedData.otherValue)
entries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
case let .langPackStringDeleted(key):
case let .langPackStringDeleted(langPackStringDeletedData):
let key = langPackStringDeletedData.key
entries.append(.string(key: key, value: ""))
}
}
@@ -242,7 +246,8 @@ private func synchronizeLocalizationUpdates(accountManager: AccountManager<Teleg
func tryApplyingLanguageDifference(transaction: AccountManagerModifier<TelegramAccountManagerTypes>, langCode: String, difference: Api.LangPackDifference) -> Bool {
let (primary, secondary) = getLocalization(transaction)
switch difference {
case let .langPackDifference(updatedCode, fromVersion, updatedVersion, strings):
case let .langPackDifference(langPackDifferenceData):
let (updatedCode, fromVersion, updatedVersion, strings) = (langPackDifferenceData.langCode, langPackDifferenceData.fromVersion, langPackDifferenceData.version, langPackDifferenceData.strings)
var current: (isPrimary: Bool, version: Int32, entries: [LocalizationEntry])?
if updatedCode == primary.code {
current = (true, primary.version, primary.entries)
@@ -259,11 +264,14 @@ func tryApplyingLanguageDifference(transaction: AccountManagerModifier<TelegramA
for string in strings {
switch string {
case let .langPackString(key, value):
case let .langPackString(langPackStringData):
let (key, value) = (langPackStringData.key, langPackStringData.value)
updatedEntries.append(.string(key: key, value: value))
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
case let .langPackStringPluralized(langPackStringPluralizedData):
let (key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue) = (langPackStringPluralizedData.key, langPackStringPluralizedData.zeroValue, langPackStringPluralizedData.oneValue, langPackStringPluralizedData.twoValue, langPackStringPluralizedData.fewValue, langPackStringPluralizedData.manyValue, langPackStringPluralizedData.otherValue)
updatedEntries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
case let .langPackStringDeleted(key):
case let .langPackStringDeleted(langPackStringDeletedData):
let key = langPackStringDeletedData.key
updatedEntries.append(.string(key: key, value: ""))
}
}
@@ -244,14 +244,16 @@ private extension EngineAvailableColorOptions.ColorOption {
let stories: EngineAvailableColorOptions.MultiColorPack?
switch apiColors {
case let .peerColorSet(colors):
case let .peerColorSet(peerColorSetData):
let colors = peerColorSetData.colors
if colors.isEmpty {
return nil
}
palette = EngineAvailableColorOptions.MultiColorPack(colors: colors.map(UInt32.init(bitPattern:)))
background = palette
stories = nil
case let .peerColorProfileSet(palleteColors, bgColors, storyColors):
case let .peerColorProfileSet(peerColorProfileSetData):
let (palleteColors, bgColors, storyColors) = (peerColorProfileSetData.paletteColors, peerColorProfileSetData.bgColors, peerColorProfileSetData.storyColors)
if palleteColors.isEmpty {
return nil
}
@@ -278,7 +280,8 @@ private extension EngineAvailableColorOptions {
var mappedOptions: [Option] = []
for apiColor in apiColors {
switch apiColor {
case let .peerColorOption(flags, colorId, colors, darkColors, requiredChannelMinBoostLevel, requiredGroupMinBoostLevel):
case let .peerColorOption(peerColorOptionData):
let (flags, colorId, colors, darkColors, requiredChannelMinBoostLevel, requiredGroupMinBoostLevel) = (peerColorOptionData.flags, peerColorOptionData.colorId, peerColorOptionData.colors, peerColorOptionData.darkColors, peerColorOptionData.channelMinLevel, peerColorOptionData.groupMinLevel)
let isHidden = (flags & (1 << 0)) != 0
let mappedColors = colors.flatMap(EngineAvailableColorOptions.ColorOption.init(apiColors:))
@@ -348,7 +351,8 @@ private func _internal_fetchPeerColors(postbox: Postbox, network: Network, scope
switch result {
case .peerColorsNotModified:
return .complete()
case let .peerColors(hash, colors):
case let .peerColors(peerColorsData):
let (hash, colors) = (peerColorsData.hash, peerColorsData.colors)
return postbox.transaction { transaction -> Void in
let value = EngineAvailableColorOptions(hash: hash, apiColors: colors)
_internal_setCachedAvailableColorOptions(transaction: transaction, scope: scope, value: value)
@@ -162,8 +162,8 @@ func pushPeerNotificationSettings(postbox: Postbox, network: Network, peerId: Pe
flags |= (1 << 8)
}
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: flags, showPreviews: showPreviews, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound)
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyForumTopic(peer: inputPeer, topMsgId: Int32(clamping: threadId)), settings: inputSettings))
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(.init(flags: flags, showPreviews: showPreviews, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound))
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyForumTopic(.init(peer: inputPeer, topMsgId: Int32(clamping: threadId))), settings: inputSettings))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
@@ -237,8 +237,8 @@ func pushPeerNotificationSettings(postbox: Postbox, network: Network, peerId: Pe
flags |= (1 << 8)
}
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: flags, showPreviews: showPreviews, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound)
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyPeer(peer: inputPeer), settings: inputSettings))
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(.init(flags: flags, showPreviews: showPreviews, silent: nil, muteUntil: muteUntil, sound: sound, storiesMuted: storiesMuted, storiesHideSender: storiesHideSender, storiesSound: storiesSound))
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyPeer(.init(peer: inputPeer)), settings: inputSettings))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
@@ -19,7 +19,8 @@ func updatePremiumPromoConfigurationOnce(accountPeerId: PeerId, postbox: Postbox
return .complete()
}
return postbox.transaction { transaction -> Void in
if case let .premiumPromo(_, _, _, _, _, apiUsers) = result {
if case let .premiumPromo(premiumPromoData) = result {
let apiUsers = premiumPromoData.users
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: apiUsers)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
}
@@ -59,7 +60,8 @@ private func updatePremiumPromoConfiguration(transaction: Transaction, _ f: (Pre
private extension PremiumPromoConfiguration {
init(apiPremiumPromo: Api.help.PremiumPromo) {
switch apiPremiumPromo {
case let .premiumPromo(statusText, statusEntities, videoSections, videoFiles, options, _):
case let .premiumPromo(premiumPromoData):
let (statusText, statusEntities, videoSections, videoFiles, options) = (premiumPromoData.statusText, premiumPromoData.statusEntities, premiumPromoData.videoSections, premiumPromoData.videos, premiumPromoData.periodOptions)
self.status = statusText
self.statusEntities = messageTextEntitiesFromApiEntities(statusEntities)
@@ -73,7 +75,8 @@ private extension PremiumPromoConfiguration {
var productOptions: [PremiumProductOption] = []
for option in options {
if case let .premiumSubscriptionOption(flags, transaction, months, currency, amount, botUrl, storeProduct) = option {
if case let .premiumSubscriptionOption(premiumSubscriptionOptionData) = option {
let (flags, transaction, months, currency, amount, botUrl, storeProduct) = (premiumSubscriptionOptionData.flags, premiumSubscriptionOptionData.transaction, premiumSubscriptionOptionData.months, premiumSubscriptionOptionData.currency, premiumSubscriptionOptionData.amount, premiumSubscriptionOptionData.botUrl, premiumSubscriptionOptionData.storeProduct)
productOptions.append(PremiumProductOption(isCurrent: (flags & (1 << 1)) != 0, months: months, currency: currency, amount: amount, botUrl: botUrl, transactionId: transaction, availableForUpgrade: (flags & (1 << 2)) != 0, storeProductId: storeProduct))
}
}
@@ -166,7 +166,8 @@ public final class ServerSuggestionInfo: Codable, Equatable {
extension ServerSuggestionInfo.Item.Text {
convenience init(_ apiText: Api.TextWithEntities) {
switch apiText {
case let .textWithEntities(text, entities):
case let .textWithEntities(textWithEntitiesData):
let (text, entities) = (textWithEntitiesData.text, textWithEntitiesData.entities)
self.init(string: text, entities: messageTextEntitiesFromApiEntities(entities))
}
}
@@ -175,7 +176,8 @@ extension ServerSuggestionInfo.Item.Text {
extension ServerSuggestionInfo.Item {
convenience init(_ apiItem: Api.PendingSuggestion) {
switch apiItem {
case let .pendingSuggestion(suggestion, title, description, url):
case let .pendingSuggestion(pendingSuggestionData):
let (suggestion, title, description, url) = (pendingSuggestionData.suggestion, pendingSuggestionData.title, pendingSuggestionData.description, pendingSuggestionData.url)
self.init(
id: suggestion,
title: ServerSuggestionInfo.Item.Text(title),
@@ -189,12 +191,12 @@ extension ServerSuggestionInfo.Item {
func _internal_fetchPromoInfo(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return network.request(Api.functions.help.getPromoData())
|> `catch` { _ -> Signal<Api.help.PromoData, NoError> in
return .single(.promoDataEmpty(expires: 10 * 60))
return .single(.promoDataEmpty(.init(expires: 10 * 60)))
}
|> mapToSignal { data -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Void in
switch data {
case .promoDataEmpty:
case .promoDataEmpty(_):
transaction.replaceAdditionalChatListItems([])
let suggestionInfo = ServerSuggestionInfo(
@@ -206,7 +208,8 @@ func _internal_fetchPromoInfo(accountPeerId: EnginePeer.Id, postbox: Postbox, ne
transaction.updatePreferencesEntry(key: PreferencesKeys.serverSuggestionInfo(), { _ in
return PreferencesEntry(suggestionInfo)
})
case let .promoData(flags, expires, peer, psaType, psaMessage, pendingSuggestions, dismissedSuggestions, customPendingSuggestion, chats, users):
case let .promoData(promoDataData):
let (flags, expires, peer, psaType, psaMessage, pendingSuggestions, dismissedSuggestions, customPendingSuggestion, chats, users) = (promoDataData.flags, promoDataData.expires, promoDataData.peer, promoDataData.psaType, promoDataData.psaMessage, promoDataData.pendingSuggestions, promoDataData.dismissedSuggestions, promoDataData.customPendingSuggestion, promoDataData.chats, promoDataData.users)
let _ = expires
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
@@ -53,7 +53,8 @@ func managedRecentStickers(postbox: Postbox, network: Network, forceFetch: Bool
switch result {
case .recentStickersNotModified:
return .single(nil)
case let .recentStickers(_, _, stickers, _):
case let .recentStickers(recentStickersData):
let stickers = recentStickersData.stickers
var items: [OrderedItemListEntry] = []
for sticker in stickers {
if let file = telegramMediaFileFromApiDocument(sticker, altDocuments: []), let id = file.id {
@@ -79,7 +80,8 @@ func managedRecentGifs(postbox: Postbox, network: Network, forceFetch: Bool = fa
switch result {
case .savedGifsNotModified:
return .single(nil)
case let .savedGifs(_, gifs):
case let .savedGifs(savedGifsData):
let gifs = savedGifsData.gifs
var items: [OrderedItemListEntry] = []
for gif in gifs {
if let file = telegramMediaFileFromApiDocument(gif, altDocuments: []), let id = file.id {
@@ -105,11 +107,13 @@ func managedSavedStickers(postbox: Postbox, network: Network, forceFetch: Bool =
switch result {
case .favedStickersNotModified:
return .single(nil)
case let .favedStickers(_, packs, stickers):
case let .favedStickers(favedStickersData):
let (packs, stickers) = (favedStickersData.packs, favedStickersData.stickers)
var fileStringRepresentations: [MediaId: [String]] = [:]
for pack in packs {
switch pack {
case let .stickerPack(text, fileIds):
case let .stickerPack(stickerPackData):
let (text, fileIds) = (stickerPackData.emoticon, stickerPackData.documents)
for fileId in fileIds {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if fileStringRepresentations[mediaId] == nil {
@@ -150,7 +154,8 @@ func managedGreetingStickers(postbox: Postbox, network: Network) -> Signal<Void,
switch result {
case .stickersNotModified:
return .single(nil)
case let .stickers(_, stickers):
case let .stickers(stickersData):
let stickers = stickersData.stickers
var items: [OrderedItemListEntry] = []
for sticker in stickers {
if let file = telegramMediaFileFromApiDocument(sticker, altDocuments: []), let id = file.id {
@@ -177,7 +182,8 @@ func managedPremiumStickers(postbox: Postbox, network: Network) -> Signal<Void,
switch result {
case .stickersNotModified:
return .single(nil)
case let .stickers(_, stickers):
case let .stickers(stickersData):
let stickers = stickersData.stickers
var items: [OrderedItemListEntry] = []
for sticker in stickers {
if let file = telegramMediaFileFromApiDocument(sticker, altDocuments: []), let id = file.id {
@@ -204,7 +210,8 @@ func managedAllPremiumStickers(postbox: Postbox, network: Network) -> Signal<Voi
switch result {
case .stickersNotModified:
return .single(nil)
case let .stickers(_, stickers):
case let .stickers(stickersData):
let stickers = stickersData.stickers
var items: [OrderedItemListEntry] = []
for sticker in stickers {
if let file = telegramMediaFileFromApiDocument(sticker, altDocuments: []), let id = file.id {
@@ -231,9 +238,10 @@ func managedRecentStatusEmoji(postbox: Postbox, network: Network) -> Signal<Void
switch result {
case .emojiStatusesNotModified:
return .single(nil)
case let .emojiStatuses(_, statuses):
case let .emojiStatuses(emojiStatusesData):
let statuses = emojiStatusesData.statuses
let parsedStatuses = statuses.compactMap(PeerEmojiStatus.init(apiStatus:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedStatuses.compactMap(\.emojiFileId))
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -264,9 +272,10 @@ func managedFeaturedStatusEmoji(postbox: Postbox, network: Network) -> Signal<Vo
switch result {
case .emojiStatusesNotModified:
return .single(nil)
case let .emojiStatuses(_, statuses):
case let .emojiStatuses(emojiStatusesData):
let statuses = emojiStatusesData.statuses
let parsedStatuses = statuses.compactMap(PeerEmojiStatus.init(apiStatus:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedStatuses.compactMap(\.emojiFileId))
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -297,9 +306,10 @@ func managedFeaturedChannelStatusEmoji(postbox: Postbox, network: Network) -> Si
switch result {
case .emojiStatusesNotModified:
return .single(nil)
case let .emojiStatuses(_, statuses):
case let .emojiStatuses(emojiStatusesData):
let statuses = emojiStatusesData.statuses
let parsedStatuses = statuses.compactMap(PeerEmojiStatus.init(apiStatus:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedStatuses.compactMap(\.emojiFileId))
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -330,9 +340,10 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
switch result {
case .emojiStatusesNotModified:
return .single(nil)
case let .emojiStatuses(_, statuses):
case let .emojiStatuses(emojiStatusesData):
let statuses = emojiStatusesData.statuses
let parsedStatuses = statuses.compactMap(PeerEmojiStatus.init(apiStatus:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedStatuses.flatMap(\.associatedFileIds))
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -349,9 +360,9 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
slug: slug,
owner: .peerId(accountPeerId),
attributes: [
.model(name: "", file: file, rarity: 0),
.pattern(name: "", file: patternFile, rarity: 0),
.backdrop(name: "", id: 0, innerColor: innerColor, outerColor: outerColor, patternColor: patternColor, textColor: textColor, rarity: 0)
.model(name: "", file: file, rarity: .rare, crafted: true),
.pattern(name: "", file: patternFile, rarity: .rare),
.backdrop(name: "", id: 0, innerColor: innerColor, outerColor: outerColor, patternColor: patternColor, textColor: textColor, rarity: .rare)
],
availability: StarGift.UniqueGift.Availability(issued: 0, total: 0),
giftAddress: nil,
@@ -365,7 +376,8 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
themePeerId: nil,
peerColor: nil,
hostPeerId: nil,
minOfferStars: nil
minOfferStars: nil,
craftChancePermille: nil
)
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
items.append(OrderedItemListEntry(id: RecentStarGiftItemId(id).rawValue, contents: entry))
@@ -395,7 +407,8 @@ func managedProfilePhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void
switch result {
case .emojiListNotModified:
return .single(nil)
case let .emojiList(_, documentIds):
case let .emojiList(emojiListData):
let documentIds = emojiListData.documentId
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: documentIds)
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -426,7 +439,8 @@ func managedGroupPhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void,
switch result {
case .emojiListNotModified:
return .single(nil)
case let .emojiList(_, documentIds):
case let .emojiList(emojiListData):
let documentIds = emojiListData.documentId
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: documentIds)
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -457,7 +471,8 @@ func managedBackgroundIconEmoji(postbox: Postbox, network: Network) -> Signal<Vo
switch result {
case .emojiListNotModified:
return .single(nil)
case let .emojiList(_, documentIds):
case let .emojiList(emojiListData):
let documentIds = emojiListData.documentId
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: documentIds)
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -488,7 +503,8 @@ func managedDisabledChannelStatusIconEmoji(postbox: Postbox, network: Network) -
switch result {
case .emojiListNotModified:
return .single(nil)
case let .emojiList(_, documentIds):
case let .emojiList(emojiListData):
let documentIds = emojiListData.documentId
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: documentIds)
|> map { files -> [OrderedItemListEntry] in
var items: [OrderedItemListEntry] = []
@@ -528,9 +544,10 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal<Void,
switch result {
case .reactionsNotModified:
return .single(nil)
case let .reactions(_, reactions):
case let .reactions(reactionsData):
let reactions = reactionsData.reactions
let parsedReactions = reactions.compactMap(MessageReaction.Reaction.init(apiReaction:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedReactions.compactMap { reaction -> Int64? in
switch reaction {
case .builtin:
@@ -588,9 +605,10 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal<Void, NoE
switch result {
case .reactionsNotModified:
return .single(nil)
case let .reactions(_, reactions):
case let .reactions(reactionsData):
let reactions = reactionsData.reactions
let parsedReactions = reactions.compactMap(MessageReaction.Reaction.init(apiReaction:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedReactions.compactMap { reaction -> Int64? in
switch reaction {
case .builtin:
@@ -648,9 +666,10 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal<Vo
switch result {
case .reactionsNotModified:
return .single(nil)
case let .reactions(_, reactions):
case let .reactions(reactionsData):
let reactions = reactionsData.reactions
let parsedReactions = reactions.compactMap(MessageReaction.Reaction.init(apiReaction:))
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: parsedReactions.compactMap { reaction -> Int64? in
switch reaction {
case .builtin:
@@ -246,7 +246,7 @@ private func initialHandshakeAccept(postbox: Postbox, network: Network, peerId:
memcpy(&keyFingerprint, bytes.advanced(by: keyHash.count - 8), 8)
}
let result = network.request(Api.functions.messages.acceptEncryption(peer: .inputEncryptedChat(chatId: Int32(peerId.id._internalGetInt64Value()), accessHash: accessHash), gB: Buffer(data: gb), keyFingerprint: keyFingerprint))
let result = network.request(Api.functions.messages.acceptEncryption(peer: .inputEncryptedChat(.init(chatId: Int32(peerId.id._internalGetInt64Value()), accessHash: accessHash)), gB: Buffer(data: gb), keyFingerprint: keyFingerprint))
let response = result
|> map { result -> Api.EncryptedChat? in
@@ -1783,9 +1783,11 @@ private func sendMessage(auxiliaryMethods: AccountAuxiliaryMethods, postbox: Pos
var encryptedFile: SecretChatFileReference?
if case let .message(result) = result {
switch result {
case let .sentEncryptedMessage(date):
case let .sentEncryptedMessage(sentEncryptedMessageData):
let date = sentEncryptedMessageData.date
timestamp = date
case let .sentEncryptedFile(date, file):
case let .sentEncryptedFile(sentEncryptedFileData):
let (date, file) = (sentEncryptedFileData.date, sentEncryptedFileData.file)
timestamp = date
encryptedFile = SecretChatFileReference(file)
}
@@ -1928,9 +1930,11 @@ private func sendStandaloneMessage(auxiliaryMethods: AccountAuxiliaryMethods, po
var encryptedFile: SecretChatFileReference?
if case let .message(result) = result {
switch result {
case let .sentEncryptedMessage(date):
case let .sentEncryptedMessage(sentEncryptedMessageData):
let date = sentEncryptedMessageData.date
timestamp = date
case let .sentEncryptedFile(date, file):
case let .sentEncryptedFile(sentEncryptedFileData):
let (date, file) = (sentEncryptedFileData.date, sentEncryptedFileData.file)
timestamp = date
encryptedFile = SecretChatFileReference(file)
}
@@ -2048,9 +2052,11 @@ private func sendServiceActionMessage(postbox: Postbox, network: Network, peerId
var timestamp = currentMessage.timestamp
if case let .message(result) = result {
switch result {
case let .sentEncryptedMessage(date):
case let .sentEncryptedMessage(sentEncryptedMessageData):
let date = sentEncryptedMessageData.date
timestamp = date
case let .sentEncryptedFile(date, _):
case let .sentEncryptedFile(sentEncryptedFileData):
let date = sentEncryptedFileData.date
timestamp = date
}
flags.remove(.Unsent)
@@ -2132,7 +2138,7 @@ private func sendBoxedDecryptedMessage(postbox: Postbox, network: Network, peer:
decryptedMessage.serialize(payload, role: state.role, sequenceInfo: sequenceInfo)
let encryptedPayload = encryptedMessageContents(parameters: parameters, data: MemoryBuffer(payload))
let sendMessage: Signal<Api.messages.SentEncryptedMessage, MTRpcError>
let inputPeer = Api.InputEncryptedChat.inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash)
let inputPeer = Api.InputEncryptedChat.inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash))
var flags: Int32 = 0
if silent {
@@ -2188,7 +2194,7 @@ private func requestTerminateSecretChat(postbox: Postbox, network: Network, peer
}
|> mapToSignal { peer -> Signal<Void, NoError> in
if let peer = peer {
return network.request(Api.functions.messages.reportEncryptedSpam(peer: Api.InputEncryptedChat.inputEncryptedChat(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash)))
return network.request(Api.functions.messages.reportEncryptedSpam(peer: Api.InputEncryptedChat.inputEncryptedChat(.init(chatId: Int32(peer.id.id._internalGetInt64Value()), accessHash: peer.accessHash))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
return .single(nil)
@@ -117,7 +117,7 @@ private func synchronizeAppLogEvents(transaction: Transaction, postbox: Postbox,
switch operation.content {
case let .add(time, type, peerId, data):
if let data = apiJson(data) {
events.append(.inputAppEvent(time: time, type: type, peer: peerId?.toInt64() ?? 0, data: data))
events.append(.inputAppEvent(.init(time: time, type: type, peer: peerId?.toInt64() ?? 0, data: data)))
}
default:
break
@@ -215,17 +215,17 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
innerFlags |= 1 << 6
}
if !discard {
replyTo = .inputReplyToMessage(flags: innerFlags, replyToMsgId: replySubject.messageId.id, topMsgId: topMsgId, replyToPeerId: replyToPeer, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
replyTo = .inputReplyToMessage(.init(flags: innerFlags, replyToMsgId: replySubject.messageId.id, topMsgId: topMsgId, replyToPeerId: replyToPeer, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId))
}
} else if let topMsgId {
flags |= 1 << 0
var innerFlags: Int32 = 0
innerFlags |= 1 << 0
replyTo = .inputReplyToMessage(flags: innerFlags, replyToMsgId: topMsgId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
replyTo = .inputReplyToMessage(.init(flags: innerFlags, replyToMsgId: topMsgId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil))
} else if let monoforumPeerId {
flags |= 1 << 0
replyTo = .inputReplyToMonoForum(monoforumPeerId: monoforumPeerId)
replyTo = .inputReplyToMonoForum(.init(monoforumPeerId: monoforumPeerId))
}
let suggestedPost = inputState?.suggestedPost.flatMap { suggestedPost -> Api.SuggestedPost in
@@ -233,7 +233,7 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
if suggestedPost.timestamp != nil {
flags |= 1 << 0
}
return .suggestedPost(flags: flags, price: suggestedPost.price?.apiAmount ?? .starsAmount(amount: 0, nanos: 0), scheduleDate: suggestedPost.timestamp)
return .suggestedPost(.init(flags: flags, price: suggestedPost.price?.apiAmount ?? .starsAmount(.init(amount: 0, nanos: 0)), scheduleDate: suggestedPost.timestamp))
}
if suggestedPost != nil {
flags |= 1 << 8
@@ -119,7 +119,8 @@ private func synchronizeConsumeMessageContents(transaction: Transaction, network
|> mapToSignal { result -> Signal<Void, NoError> in
if let result = result {
switch result {
case let .affectedMessages(pts, ptsCount):
case let .affectedMessages(affectedMessagesData):
let (pts, ptsCount) = (affectedMessagesData.pts, affectedMessagesData.ptsCount)
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
}
}
@@ -123,18 +123,21 @@ private func synchronizeEmojiKeywords(postbox: Postbox, transaction: Transaction
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
switch result {
case let .emojiKeywordsDifference(langCode, _, version, keywords):
case let .emojiKeywordsDifference(emojiKeywordsDifferenceData):
let (langCode, version, keywords) = (emojiKeywordsDifferenceData.langCode, emojiKeywordsDifferenceData.version, emojiKeywordsDifferenceData.keywords)
if langCode == languageCode {
var itemsToAppend: [String: EmojiKeywordItem] = [:]
var itemsToSubtract: [String: EmojiKeywordItem] = [:]
for apiEmojiKeyword in keywords {
switch apiEmojiKeyword {
case let .emojiKeyword(keyword, emoticons):
let keyword = keyword.replacingOccurrences(of: " ", with: "")
case let .emojiKeyword(emojiKeywordData):
let (rawKeyword, emoticons) = (emojiKeywordData.keyword, emojiKeywordData.emoticons)
let keyword = rawKeyword.replacingOccurrences(of: " ", with: "")
let indexKeys = stringIndexTokens(keyword, transliteration: .none).map { $0.toMemoryBuffer() }
let item = EmojiKeywordItem(index: ItemCollectionItemIndex(index: 0, id: 0), collectionId: collectionId.id, keyword: keyword, emoticons: emoticons, indexKeys: indexKeys)
itemsToAppend[keyword] = item
case let .emojiKeywordDeleted(keyword, emoticons):
case let .emojiKeywordDeleted(emojiKeywordDeletedData):
let (keyword, emoticons) = (emojiKeywordDeletedData.keyword, emojiKeywordDeletedData.emoticons)
let item = EmojiKeywordItem(index: ItemCollectionItemIndex(index: 0, id: 0), collectionId: collectionId.id, keyword: keyword, emoticons: emoticons, indexKeys: [])
itemsToSubtract[keyword] = item
}
@@ -195,11 +198,13 @@ private func synchronizeEmojiKeywords(postbox: Postbox, transaction: Transaction
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
switch result {
case let .emojiKeywordsDifference(langCode, _, version, keywords):
case let .emojiKeywordsDifference(emojiKeywordsDifferenceData):
let (langCode, version, keywords) = (emojiKeywordsDifferenceData.langCode, emojiKeywordsDifferenceData.version, emojiKeywordsDifferenceData.keywords)
var items: [EmojiKeywordItem] = []
var index: Int32 = 0
for apiEmojiKeyword in keywords {
if case let .emojiKeyword(fullKeyword, emoticons) = apiEmojiKeyword, !emoticons.isEmpty {
if case let .emojiKeyword(emojiKeywordData) = apiEmojiKeyword, !emojiKeywordData.emoticons.isEmpty {
let (fullKeyword, emoticons) = (emojiKeywordData.keyword, emojiKeywordData.emoticons)
let keyword = fullKeyword
let indexKeys = stringIndexTokens(keyword, transliteration: .none).map { $0.toMemoryBuffer() }
let item = EmojiKeywordItem(index: ItemCollectionItemIndex(index: index, id: keywordCollectionItemId(keyword, inputLanguageCode: operation.inputLanguageCode)), collectionId: collectionId.id, keyword: keyword, emoticons: emoticons, indexKeys: indexKeys)

Some files were not shown because too many files have changed in this diff Show More