diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index f9a427c025..d56fa5be45 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -128,7 +128,6 @@ D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D591D631A6900955575 /* Serialization.swift */; }; D0B418B71D7E05A6004562A4 /* Phonebook.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D6A1D631A9D00955575 /* Phonebook.swift */; }; D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D6C1D631AA300955575 /* ContactManagement.swift */; }; - D0B418B91D7E05AD004562A4 /* SearchMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D711D631ABA00955575 /* SearchMessages.swift */; }; D0B418BA1D7E05BB004562A4 /* NetworkLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = D03B0E421D631E6600955575 /* NetworkLogging.m */; }; D0B418BB1D7E05BE004562A4 /* NetworkLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = D03B0E411D631E6600955575 /* NetworkLogging.h */; }; D0B418BC1D7E05D0004562A4 /* TelegramCoreIncludes.h in Headers */ = {isa = PBXBuildFile; fileRef = D03B0E5B1D63240700955575 /* TelegramCoreIncludes.h */; }; @@ -215,6 +214,11 @@ D0DF0C911D81A857008AEB01 /* ImageRepresentationsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0C901D81A857008AEB01 /* ImageRepresentationsUtils.swift */; }; D0DF0C931D81AD09008AEB01 /* MessageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0C921D81AD09008AEB01 /* MessageUtils.swift */; }; D0DF0CA81D82BF32008AEB01 /* PeerParticipants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0CA71D82BF32008AEB01 /* PeerParticipants.swift */; }; + D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D711D631ABA00955575 /* SearchMessages.swift */; }; + D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */; }; + D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */; }; + D0F3CC7D1DDE289E008148FA /* ResolvePeerByName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */; }; + D0F3CC7E1DDE289E008148FA /* ResolvePeerByName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */; }; D0F7AB2C1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */; }; D0F7AB2D1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */; }; D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F7AB2E1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift */; }; @@ -368,6 +372,7 @@ D0DF0C901D81A857008AEB01 /* ImageRepresentationsUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageRepresentationsUtils.swift; sourceTree = ""; }; D0DF0C921D81AD09008AEB01 /* MessageUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageUtils.swift; sourceTree = ""; }; D0DF0CA71D82BF32008AEB01 /* PeerParticipants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerParticipants.swift; sourceTree = ""; }; + D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResolvePeerByName.swift; sourceTree = ""; }; D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditedMessageAttribute.swift; sourceTree = ""; }; D0F7AB2E1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyMarkupMessageAttribute.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -704,7 +709,7 @@ D03B0D601D631A7200955575 /* Account */, D03B0D691D631A9200955575 /* Contacts */, D03B0D6E1D631AA900955575 /* Messages */, - D0DF0C881D819C5F008AEB01 /* Peer Management */, + D0DF0C881D819C5F008AEB01 /* Peers */, D021E0E01DB5400200C6B04F /* Sticker Management */, D03B0E3A1D631E4400955575 /* Supporting Files */, D09D8C041D4FAB1D0081DBEC /* TelegramCore.h */, @@ -731,14 +736,15 @@ path = TelegramCoreMac; sourceTree = ""; }; - D0DF0C881D819C5F008AEB01 /* Peer Management */ = { + D0DF0C881D819C5F008AEB01 /* Peers */ = { isa = PBXGroup; children = ( D0DF0C891D819C7E008AEB01 /* JoinChannel.swift */, D0DF0CA71D82BF32008AEB01 /* PeerParticipants.swift */, D0B843961DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift */, + D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */, ); - name = "Peer Management"; + name = Peers; sourceTree = ""; }; /* End PBXGroup section */ @@ -932,6 +938,7 @@ D01AC9211DD5E7E500E8160F /* RequestEditMessage.swift in Sources */, D01AC91D1DD5DA5E00E8160F /* RequestMessageActionCallback.swift in Sources */, D09BB6B61DB0428000A905C0 /* PendingMessageUploadedContent.swift in Sources */, + D0F3CC7D1DDE289E008148FA /* ResolvePeerByName.swift in Sources */, D0B843B71DA7FF30005F29E1 /* NBMetadataCoreMapper.m in Sources */, D0AB0B921D65E9FA002C78E7 /* ManagedServiceViews.swift in Sources */, D03B0CCE1D62239600955575 /* PhoneNumbers.swift in Sources */, @@ -1037,12 +1044,15 @@ D0B418951D7E0580004562A4 /* TelegramMediaContact.swift in Sources */, D0B8444F1DAB9206005F29E1 /* ChangePeerNotificationSettings.swift in Sources */, D0B8443B1DAB91EF005F29E1 /* Holes.swift in Sources */, + D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */, D073CEA11DCBF3D3007511FD /* StickerPack.swift in Sources */, D0B8443E1DAB91EF005F29E1 /* SynchronizePeerReadState.swift in Sources */, D0B8440D1DAB91CD005F29E1 /* ImageRepresentationsUtils.swift in Sources */, D03C536A1DAD5CA9004C17B3 /* TelegramUser.swift in Sources */, D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */, + D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */, D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */, + D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */, D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */, D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */, D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */, @@ -1059,8 +1069,8 @@ D03C536D1DAD5CA9004C17B3 /* ApiGroupOrChannel.swift in Sources */, D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */, D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */, - D0B418B91D7E05AD004562A4 /* SearchMessages.swift in Sources */, D0B8443F1DAB91EF005F29E1 /* UpdateGroup.swift in Sources */, + D0F3CC7E1DDE289E008148FA /* ResolvePeerByName.swift in Sources */, D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */, D0F7AB2D1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */, D0B844121DAB91CD005F29E1 /* Log.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index b9e1948794..f5ce867923 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -242,6 +242,7 @@ private var declaredEncodables: Void = { declareEncodable(ForwardSourceInfoAttribute.self, f: { ForwardSourceInfoAttribute(decoder: $0) }) declareEncodable(EditedMessageAttribute.self, f: { EditedMessageAttribute(decoder: $0) }) declareEncodable(ReplyMarkupMessageAttribute.self, f: { ReplyMarkupMessageAttribute(decoder: $0) }) + declareEncodable(CachedResolvedByNamePeer.self, f: { CachedResolvedByNamePeer(decoder: $0) }) return }() diff --git a/TelegramCore/Api.swift b/TelegramCore/Api.swift index 1a8fbe59f4..606cac9886 100644 --- a/TelegramCore/Api.swift +++ b/TelegramCore/Api.swift @@ -152,7 +152,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[628472761] = { return Api.Update.parse_updateContactRegistered($0) } dict[1602468195] = { return Api.Update.parse_updateContactLocated($0) } dict[1869154659] = { return Api.Update.parse_updateActivation($0) } - dict[-1895411046] = { return Api.Update.parse_updateNewAuthorization($0) } dict[-623425266] = { return Api.Update.parse_updatePhoneCallRequested($0) } dict[1443495816] = { return Api.Update.parse_updatePhoneCallConfirmed($0) } dict[833498306] = { return Api.Update.parse_updatePhoneCallDeclined($0) } @@ -168,7 +167,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1548249383] = { return Api.Update.parse_updateUserTyping($0) } dict[-1704596961] = { return Api.Update.parse_updateChatUserTyping($0) } dict[-1489818765] = { return Api.Update.parse_updateUserName($0) } - dict[942527460] = { return Api.Update.parse_updateServiceNotification($0) } dict[-298113238] = { return Api.Update.parse_updatePrivacy($0) } dict[314130811] = { return Api.Update.parse_updateUserPhone($0) } dict[522914557] = { return Api.Update.parse_updateNewMessage($0) } @@ -208,6 +206,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-103646630] = { return Api.Update.parse_updateInlineBotCallbackQuery($0) } dict[1081547008] = { return Api.Update.parse_updateChannelWebPage($0) } dict[-1425052898] = { return Api.Update.parse_updatePhoneCall($0) } + dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) } dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) } dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) } dict[-1861910545] = { return Api.ChannelParticipant.parse_channelParticipantModerator($0) } @@ -351,7 +350,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[182649427] = { return Api.MessageRange.parse_messageRange($0) } dict[946083368] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultSuccess($0) } dict[904138920] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultArchive($0) } - dict[-1704251862] = { return Api.Config.parse_config($0) } + dict[-1233953423] = { return Api.Config.parse_config($0) } dict[-75283823] = { return Api.TopPeerCategoryPeers.parse_topPeerCategoryPeers($0) } dict[-1107729093] = { return Api.Game.parse_game($0) } dict[-1032140601] = { return Api.BotCommand.parse_botCommand($0) } @@ -4441,7 +4440,6 @@ public struct Api { case updateContactRegistered(userId: Int32, date: Int32) case updateContactLocated(contacts: [Api.ContactLocated]) case updateActivation(userId: Int32) - case updateNewAuthorization(authKeyId: Int64, date: Int32, device: String, location: String) case updatePhoneCallRequested(phoneCall: Api.PhoneCall) case updatePhoneCallConfirmed(id: Int64, aOrB: Buffer, connection: Api.PhoneConnection) case updatePhoneCallDeclined(id: Int64) @@ -4457,7 +4455,6 @@ public struct Api { case updateUserTyping(userId: Int32, action: Api.SendMessageAction) case updateChatUserTyping(chatId: Int32, userId: Int32, action: Api.SendMessageAction) case updateUserName(userId: Int32, firstName: String, lastName: String, username: String) - case updateServiceNotification(type: String, message: String, media: Api.MessageMedia, popup: Api.Bool) case updatePrivacy(key: Api.PrivacyKey, rules: [Api.PrivacyRule]) case updateUserPhone(userId: Int32, phone: String) case updateNewMessage(message: Api.Message, pts: Int32, ptsCount: Int32) @@ -4497,6 +4494,7 @@ public struct Api { case updateInlineBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int32, msgId: Api.InputBotInlineMessageID, chatInstance: Int64, data: Buffer?, gameShortName: String?) case updateChannelWebPage(channelId: Int32, webpage: Api.WebPage, pts: Int32, ptsCount: Int32) case updatePhoneCall(phoneCall: Api.PhoneCall) + case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool { switch self { @@ -4554,15 +4552,6 @@ public struct Api { } serializeInt32(userId, buffer: buffer, boxed: false) break - case .updateNewAuthorization(let authKeyId, let date, let device, let location): - if boxed { - buffer.appendInt32(-1895411046) - } - serializeInt64(authKeyId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeString(device, buffer: buffer, boxed: false) - serializeString(location, buffer: buffer, boxed: false) - break case .updatePhoneCallRequested(let phoneCall): if boxed { buffer.appendInt32(-623425266) @@ -4676,15 +4665,6 @@ public struct Api { serializeString(lastName, buffer: buffer, boxed: false) serializeString(username, buffer: buffer, boxed: false) break - case .updateServiceNotification(let type, let message, let media, let popup): - if boxed { - buffer.appendInt32(942527460) - } - serializeString(type, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - let _ = media.serialize(buffer, true) - let _ = popup.serialize(buffer, true) - break case .updatePrivacy(let key, let rules): if boxed { buffer.appendInt32(-298113238) @@ -5017,6 +4997,21 @@ public struct Api { } let _ = phoneCall.serialize(buffer, true) break + case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities): + if boxed { + buffer.appendInt32(-337352679) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(inboxDate!, buffer: buffer, boxed: false)} + serializeString(type, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + let _ = media.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + let _ = item.serialize(buffer, true) + } + break } return true } @@ -5118,26 +5113,6 @@ public struct Api { return nil } } - fileprivate static func parse_updateNewAuthorization(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateNewAuthorization(authKeyId: _1!, date: _2!, device: _3!, location: _4!) - } - else { - return nil - } - } fileprivate static func parse_updatePhoneCallRequested(_ reader: BufferReader) -> Update? { var _1: Api.PhoneCall? if let signature = reader.readInt32() { @@ -5384,30 +5359,6 @@ public struct Api { return nil } } - fileprivate static func parse_updateServiceNotification(_ reader: BufferReader) -> Update? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - var _3: Api.MessageMedia? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.MessageMedia - } - var _4: Api.Bool? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Bool - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateServiceNotification(type: _1!, message: _2!, media: _3!, popup: _4!) - } - else { - return nil - } - } fileprivate static func parse_updatePrivacy(_ reader: BufferReader) -> Update? { var _1: Api.PrivacyKey? if let signature = reader.readInt32() { @@ -6069,6 +6020,36 @@ public struct Api { return nil } } + fileprivate static func parse_updateServiceNotification(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Api.MessageMedia? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + var _6: [Api.MessageEntity]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateServiceNotification(flags: _1!, inboxDate: _2, type: _3!, message: _4!, media: _5!, entities: _6!) + } + else { + return nil + } + } } @@ -9084,13 +9065,13 @@ public struct Api { } public enum Config: /*CustomStringConvertible, */ApiSerializeableObject { - case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, chatBigSize: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, tmpSessions: Int32?, disabledFeatures: [Api.DisabledFeature]) + case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, chatBigSize: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, tmpSessions: Int32?, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, disabledFeatures: [Api.DisabledFeature]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool { switch self { - case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let chatBigSize, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let ratingEDecay, let stickersRecentLimit, let tmpSessions, let disabledFeatures): + case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let chatBigSize, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let ratingEDecay, let stickersRecentLimit, let tmpSessions, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let disabledFeatures): if boxed { - buffer.appendInt32(-1704251862) + buffer.appendInt32(-1233953423) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(date, buffer: buffer, boxed: false) @@ -9119,6 +9100,10 @@ public struct Api { serializeInt32(ratingEDecay, buffer: buffer, boxed: false) serializeInt32(stickersRecentLimit, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)} + serializeInt32(callReceiveTimeoutMs, buffer: buffer, boxed: false) + serializeInt32(callRingTimeoutMs, buffer: buffer, boxed: false) + serializeInt32(callConnectTimeoutMs, buffer: buffer, boxed: false) + serializeInt32(callPacketTimeoutMs, buffer: buffer, boxed: false) buffer.appendInt32(481674261) buffer.appendInt32(Int32(disabledFeatures.count)) for item in disabledFeatures { @@ -9180,9 +9165,17 @@ public struct Api { _22 = reader.readInt32() var _23: Int32? if Int(_1!) & Int(1 << 0) != 0 {_23 = reader.readInt32() } - var _24: [Api.DisabledFeature]? + var _24: Int32? + _24 = reader.readInt32() + var _25: Int32? + _25 = reader.readInt32() + var _26: Int32? + _26 = reader.readInt32() + var _27: Int32? + _27 = reader.readInt32() + var _28: [Api.DisabledFeature]? if let _ = reader.readInt32() { - _24 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self) + _28 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self) } let _c1 = _1 != nil let _c2 = _2 != nil @@ -9208,8 +9201,12 @@ public struct Api { let _c22 = _22 != nil let _c23 = (Int(_1!) & Int(1 << 0) == 0) || _23 != nil let _c24 = _24 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 { - return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, chatSizeMax: _7!, megagroupSizeMax: _8!, forwardedCountMax: _9!, onlineUpdatePeriodMs: _10!, offlineBlurTimeoutMs: _11!, offlineIdleTimeoutMs: _12!, onlineCloudTimeoutMs: _13!, notifyCloudDelayMs: _14!, notifyDefaultDelayMs: _15!, chatBigSize: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, ratingEDecay: _21!, stickersRecentLimit: _22!, tmpSessions: _23, disabledFeatures: _24!) + let _c25 = _25 != nil + let _c26 = _26 != nil + let _c27 = _27 != nil + let _c28 = _28 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 { + return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, chatSizeMax: _7!, megagroupSizeMax: _8!, forwardedCountMax: _9!, onlineUpdatePeriodMs: _10!, offlineBlurTimeoutMs: _11!, offlineIdleTimeoutMs: _12!, onlineCloudTimeoutMs: _13!, notifyCloudDelayMs: _14!, notifyDefaultDelayMs: _15!, chatBigSize: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, ratingEDecay: _21!, stickersRecentLimit: _22!, tmpSessions: _23, callReceiveTimeoutMs: _24!, callRingTimeoutMs: _25!, callConnectTimeoutMs: _26!, callPacketTimeoutMs: _27!, disabledFeatures: _28!) } else { return nil diff --git a/TelegramCore/EnqueueMessage.swift b/TelegramCore/EnqueueMessage.swift index 52ed238e72..a42c5ccdd5 100644 --- a/TelegramCore/EnqueueMessage.swift +++ b/TelegramCore/EnqueueMessage.swift @@ -10,6 +10,15 @@ import Foundation public enum EnqueueMessage { case message(text: String, media: Media?, replyToMessageId: MessageId?) case forward(source: MessageId) + + public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage { + switch self { + case let .message(text, media, _): + return .message(text: text, media: media, replyToMessageId: replyToMessageId) + case .forward: + return self + } + } } private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAttribute]) -> [MessageAttribute] { diff --git a/TelegramCore/Namespaces.swift b/TelegramCore/Namespaces.swift index 8927eb59fe..24c2e34ae9 100644 --- a/TelegramCore/Namespaces.swift +++ b/TelegramCore/Namespaces.swift @@ -36,6 +36,10 @@ public struct Namespaces { public static let CloudRecentGifs: Int32 = 2 public static let CloudRecentStickers: Int32 = 0 } + + struct CachedItemCollection { + public static let resolvedByNamePeers: Int8 = 0 + } } public extension MessageTags { diff --git a/TelegramCore/PendingMessageManager.swift b/TelegramCore/PendingMessageManager.swift index ad0d076284..bd7515f47d 100644 --- a/TelegramCore/PendingMessageManager.swift +++ b/TelegramCore/PendingMessageManager.swift @@ -245,25 +245,25 @@ public final class PendingMessageManager { let sendMessageRequest: Signal switch content { - case let .text(text): - sendMessageRequest = network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: nil), tag: dependencyTag) - |> mapError { _ -> NoError in - return NoError() - } - case let .media(inputMedia): - sendMessageRequest = network.request(Api.functions.messages.sendMedia(flags: 0, peer: inputPeer, replyToMsgId: replyMessageId, media: inputMedia, randomId: uniqueId, replyMarkup: nil), tag: dependencyTag) - |> mapError { _ -> NoError in - return NoError() - } - case let .forward(sourceInfo): - if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = modifier.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) { - sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: 0, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer), tag: dependencyTag) + case let .text(text): + sendMessageRequest = network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: nil), tag: dependencyTag) |> mapError { _ -> NoError in return NoError() } - } else { - sendMessageRequest = .fail(NoError()) - } + case let .media(inputMedia): + sendMessageRequest = network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, media: inputMedia, randomId: uniqueId, replyMarkup: nil), tag: dependencyTag) + |> mapError { _ -> NoError in + return NoError() + } + case let .forward(sourceInfo): + if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = modifier.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) { + sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: 0, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer), tag: dependencyTag) + |> mapError { _ -> NoError in + return NoError() + } + } else { + sendMessageRequest = .fail(NoError()) + } } return sendMessageRequest diff --git a/TelegramCore/ReplyMarkupMessageAttribute.swift b/TelegramCore/ReplyMarkupMessageAttribute.swift index 34b05e4328..ba5fea7e1a 100644 --- a/TelegramCore/ReplyMarkupMessageAttribute.swift +++ b/TelegramCore/ReplyMarkupMessageAttribute.swift @@ -75,6 +75,7 @@ public enum ReplyMarkupButtonAction: Coding { case let .switchInline(samePeer, query): encoder.encodeInt32(5, forKey: "v") encoder.encodeInt32(samePeer ? 1 : 0, forKey: "s") + encoder.encodeString(query, forKey: "1") case .openWebApp: encoder.encodeInt32(6, forKey: "v") } diff --git a/TelegramCore/RequestEditMessage.swift b/TelegramCore/RequestEditMessage.swift index c15852ef48..749d36096b 100644 --- a/TelegramCore/RequestEditMessage.swift +++ b/TelegramCore/RequestEditMessage.swift @@ -30,8 +30,8 @@ public func requestEditMessage(account: Account, messageId: MessageId, text: Str } |> mapToSignal { result -> Signal in if let result = result { - return .single(true) account.stateManager.addUpdates(result) + return .single(true) } else { return .single(false) } diff --git a/TelegramCore/RequestMessageActionCallback.swift b/TelegramCore/RequestMessageActionCallback.swift index e766a32782..d238b48762 100644 --- a/TelegramCore/RequestMessageActionCallback.swift +++ b/TelegramCore/RequestMessageActionCallback.swift @@ -17,7 +17,7 @@ public func requestMessageActionCallback(account: Account, messageId: MessageId, var flags: Int32 = 0 var dataBuffer: Buffer? if let data = data { - flags != Int32(1 << 0) + flags |= Int32(1 << 0) dataBuffer = Buffer(data: data.makeData()) } return account.network.request(Api.functions.messages.getBotCallbackAnswer(flags: flags, peer: inputPeer, msgId: messageId.id, data: dataBuffer)) diff --git a/TelegramCore/ResolvePeerByName.swift b/TelegramCore/ResolvePeerByName.swift new file mode 100644 index 0000000000..efcf408677 --- /dev/null +++ b/TelegramCore/ResolvePeerByName.swift @@ -0,0 +1,106 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + +final class CachedResolvedByNamePeer: Coding { + let peerId: PeerId? + let timestamp: Int32 + + static func key(name: String) -> ValueBoxKey { + let nameData = name.data(using: .utf8)! + let key = ValueBoxKey(length: nameData.count) + nameData.withUnsafeBytes { (bytes: UnsafePointer) -> Void in + memcpy(key.memory, bytes, nameData.count) + } + return key + } + + init(peerId: PeerId?, timestamp: Int32) { + self.peerId = peerId + self.timestamp = timestamp + } + + init(decoder: Decoder) { + if let peerId = (decoder.decodeInt64ForKey("p") as Int64?) { + self.peerId = PeerId(peerId) + } else { + self.peerId = nil + } + self.timestamp = decoder.decodeInt32ForKey("t") + } + + func encode(_ encoder: Encoder) { + if let peerId = self.peerId { + encoder.encodeInt64(peerId.toInt64(), forKey: "p") + } else { + encoder.encodeNil(forKey: "p") + } + encoder.encodeInt32(self.timestamp, forKey: "t") + } +} + +private let resolvedByNamePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200) + +public func resolvePeerByName(account: Account, name: String, ageLimit: Int32 = 60 * 5) -> Signal { + var normalizedName = name + if normalizedName.hasPrefix("@") { + normalizedName = normalizedName.substring(from: name.index(after: name.startIndex)) + } + + return account.postbox.modify { modifier -> CachedResolvedByNamePeer? in + return modifier.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName))) as? CachedResolvedByNamePeer + } |> mapToSignal { cachedEntry -> Signal in + let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) + if let cachedEntry = cachedEntry, cachedEntry.timestamp <= timestamp && cachedEntry.timestamp >= timestamp - ageLimit { + return .single(cachedEntry.peerId) + } else { + return account.network.request(Api.functions.contacts.resolveUsername(username: normalizedName)) + |> mapError { _ -> NoError in + return NoError() + } + |> mapToSignal { result -> Signal in + return account.postbox.modify { modifier -> PeerId? in + var peerId: PeerId? = nil + + //contacts.resolvedPeer peer:Peer chats:Vector users:Vector = contacts.ResolvedPeer; + switch result { + case let .resolvedPeer(apiPeer, chats, users): + var peers: [PeerId: Peer] = [:] + + for user in users { + if let user = TelegramUser.merge(modifier.getPeer(user.peerId) as? TelegramUser, rhs: user) { + peers[user.id] = user + } + } + + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers[groupOrChannel.id] = groupOrChannel + } + } + + if let peer = peers[apiPeer.peerId] { + peerId = peer.id + + modifier.updatePeers(Array(peers.values), update: { _, updated -> Peer in + return updated + }) + } + } + + let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) + modifier.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: CachedResolvedByNamePeer(peerId: peerId, timestamp: timestamp), collectionSpec: resolvedByNamePeersCollectionSpec) + return peerId + } + } + |> `catch` { _ -> Signal in + return .single(nil) + } + } + } +} diff --git a/TelegramCore/Serialization.swift b/TelegramCore/Serialization.swift index 3eb7326cdf..2930c0a373 100644 --- a/TelegramCore/Serialization.swift +++ b/TelegramCore/Serialization.swift @@ -57,7 +57,7 @@ public class Serialization: NSObject, MTSerialization { if let config = parse(Buffer(data: response)) { switch config { //config flags:# date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int tmp_sessions:flags.0?int phonecalls_enabled:flags.1?true disabled_features:Vector = Config; - case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): var addressList = [MTDatacenterAddress]() for option in dcOptions { switch option { diff --git a/TelegramCore/StateManagement.swift b/TelegramCore/StateManagement.swift index a60c016297..d42555a7fb 100644 --- a/TelegramCore/StateManagement.swift +++ b/TelegramCore/StateManagement.swift @@ -22,14 +22,16 @@ private final class InitialState { let channelStates: [PeerId: ChannelState] let peerNotificationSettings: [PeerId: PeerNotificationSettings] let peerIdsWithNewMessages: Set + let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]] - init(state: AuthorizedAccountState.State, peerIds: Set, messageIds: Set, peerIdsWithNewMessages: Set, channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings]) { + init(state: AuthorizedAccountState.State, peerIds: Set, messageIds: Set, peerIdsWithNewMessages: Set, channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) { self.state = state self.peerIds = peerIds self.messageIds = messageIds self.channelStates = channelStates self.peerIdsWithNewMessages = peerIdsWithNewMessages self.peerNotificationSettings = peerNotificationSettings + self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps } } @@ -64,19 +66,24 @@ private struct MutableState { fileprivate var peerNotificationSettings: [PeerId: PeerNotificationSettings] fileprivate var storedMessages: Set + fileprivate var storedMessagesByPeerIdAndTimestamp: [PeerId: Set] + fileprivate var insertedPeers: [PeerId: Peer] = [:] - init(initialState: InitialState, initialPeers: [PeerId: Peer], initialStoredMessages: Set) { + fileprivate var preCachedResources: [(MediaResource, Data)] = [] + + init(initialState: InitialState, initialPeers: [PeerId: Peer], initialStoredMessages: Set, storedMessagesByPeerIdAndTimestamp: [PeerId: Set]) { self.initialState = initialState self.state = initialState.state self.peers = initialPeers self.storedMessages = initialStoredMessages self.channelStates = initialState.channelStates self.peerNotificationSettings = initialState.peerNotificationSettings + self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp self.branchOperationIndex = 0 } - init(initialState: InitialState, operations: [MutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set, branchOperationIndex: Int) { + init(initialState: InitialState, operations: [MutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set, storedMessagesByPeerIdAndTimestamp: [PeerId: Set], branchOperationIndex: Int) { self.initialState = initialState self.operations = operations self.state = state @@ -84,11 +91,12 @@ private struct MutableState { self.channelStates = channelStates self.storedMessages = storedMessages self.peerNotificationSettings = peerNotificationSettings + self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp self.branchOperationIndex = branchOperationIndex } func branch() -> MutableState { - return MutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, branchOperationIndex: self.operations.count) + return MutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, branchOperationIndex: self.operations.count) } mutating func merge(_ other: MutableState) { @@ -98,6 +106,11 @@ private struct MutableState { for (_, peer) in other.insertedPeers { self.peers[peer.id] = peer } + self.preCachedResources.append(contentsOf: other.preCachedResources) + } + + mutating func addPreCachedResource(_ resource: MediaResource, data: Data) { + self.preCachedResources.append((resource, data)) } mutating func addMessages(_ messages: [StoreMessage], location: AddMessagesLocation) { @@ -258,7 +271,6 @@ private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Se return messageIds } - private func peersWithNewMessagesFromUpdateGroups(_ groups: [UpdateGroup]) -> Set { var peerIds = Set() @@ -273,6 +285,29 @@ private func peersWithNewMessagesFromUpdateGroups(_ groups: [UpdateGroup]) -> Se return peerIds } +private func locallyGeneratedMessageTimestampsFromUpdateGroups(_ groups: [UpdateGroup]) -> [PeerId: [(MessageId.Namespace, Int32)]] { + var messageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]] = [:] + for group in groups { + for update in group.updates { + switch update { + case let .updateServiceNotification(_, date, _, _, _, _): + if let date = date { + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 777000) + if messageTimestamps[peerId] == nil { + messageTimestamps[peerId] = [(Namespaces.Message.Local, date)] + } else { + messageTimestamps[peerId]!.append((Namespaces.Message.Local, date)) + } + } + default: + break + } + } + } + + return messageTimestamps +} + private func peerIdsFromDifference(_ difference: Api.updates.Difference) -> Set { var peerIds = Set() @@ -390,7 +425,43 @@ private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Differ return peerIds } -private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, associatedMessageIds: Set, peerIdsWithNewMessages: Set) -> MutableState { +private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.updates.Difference) -> [PeerId: [(MessageId.Namespace, Int32)]] { + var messageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]] = [:] + + var otherUpdates: [Api.Update]? + switch difference { + case let .difference(_, _, apiOtherUpdates, _, _, _): + otherUpdates = apiOtherUpdates + case .differenceEmpty: + break + case let .differenceSlice(_, _, apiOtherUpdates, _, _, _): + otherUpdates = apiOtherUpdates + case .differenceTooLong: + break + } + + if let otherUpdates = otherUpdates { + for update in otherUpdates { + switch update { + case let .updateServiceNotification(_, date, _, _, _, _): + if let date = date { + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 777000) + if messageTimestamps[peerId] == nil { + messageTimestamps[peerId] = [(Namespaces.Message.Local, date)] + } else { + messageTimestamps[peerId]!.append((Namespaces.Message.Local, date)) + } + } + default: + break + } + } + } + + return messageTimestamps +} + +private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, associatedMessageIds: Set, peerIdsWithNewMessages: Set, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> MutableState { var peers: [PeerId: Peer] = [:] var channelStates: [PeerId: ChannelState] = [:] @@ -407,6 +478,20 @@ private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, } let storedMessages = modifier.filterStoredMessageIds(associatedMessageIds) + var storedMessagesByPeerIdAndTimestamp: [PeerId: Set] = [:] + if !locallyGeneratedMessageTimestamps.isEmpty { + for (peerId, namespacesAndTimestamps) in locallyGeneratedMessageTimestamps { + for (namespace, timestamp) in namespacesAndTimestamps { + if let messageId = modifier.storedMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp) { + if storedMessagesByPeerIdAndTimestamp[peerId] == nil { + storedMessagesByPeerIdAndTimestamp[peerId] = Set([MessageIndex(id: messageId, timestamp: timestamp)]) + } else { + storedMessagesByPeerIdAndTimestamp[peerId]!.insert(MessageIndex(id: messageId, timestamp: timestamp)) + } + } + } + } + } var peerNotificationSettings: [PeerId: PeerNotificationSettings] = [:] for peerId in peerIdsWithNewMessages { @@ -415,7 +500,7 @@ private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, } } - return MutableState(initialState: InitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, channelStates: channelStates, peerNotificationSettings: peerNotificationSettings), initialPeers: peers, initialStoredMessages: storedMessages) + return MutableState(initialState: InitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, channelStates: channelStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps), initialPeers: peers, initialStoredMessages: storedMessages, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp) } private func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGroup]) -> Signal { @@ -424,7 +509,7 @@ private func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGro let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups) let peerIdsWithNewMessages = peersWithNewMessagesFromUpdateGroups(groups) - return initialStateWithPeerIds(modifier, peerIds: peerIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages) + return initialStateWithPeerIds(modifier, peerIds: peerIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups)) } } @@ -433,7 +518,7 @@ private func initialStateWithDifference(_ account: Account, difference: Api.upda let peerIds = peerIdsFromDifference(difference) let associatedMessageIds = associatedMessageIdsFromDifference(difference) let peerIdsWithNewMessages = peersWithNewMessagesFromDifference(difference) - return initialStateWithPeerIds(modifier, peerIds: peerIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages) + return initialStateWithPeerIds(modifier, peerIds: peerIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference)) } } @@ -593,6 +678,11 @@ private func finalStateWithDifference(account: Account, state: MutableState, dif updatedState.mergeUsers(users) for message in messages { + if let preCachedResources = message.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } if let message = StoreMessage(apiMessage: message) { updatedState.addMessages([message], location: .UpperHistoryBlock) } @@ -715,6 +805,11 @@ private func finalStateWithUpdates(account: Account, state: MutableState, update if previousState.pts >= pts { //trace("State", what: "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old delete update") } else if previousState.pts + ptsCount == pts { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } updatedState.editMessage(messageId, message: message) updatedState.updateChannelState(peerId, state: previousState.setPts(pts)) } else { @@ -737,14 +832,24 @@ private func finalStateWithUpdates(account: Account, state: MutableState, update updatedState.deleteMessagesWithGlobalIds(messages) case let .updateEditMessage(apiMessage, _, _): if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } updatedState.editMessage(messageId, message: message) } - case let .updateNewChannelMessage(message, pts, ptsCount): - if let message = StoreMessage(apiMessage: message) { + case let .updateNewChannelMessage(apiMessage, pts, ptsCount): + if let message = StoreMessage(apiMessage: apiMessage) { if let previousState = updatedState.channelStates[message.id.peerId] { if previousState.pts >= pts { //trace("State", what: "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) skip old message \(message.id) (\(message.text))") } else if previousState.pts + ptsCount == pts { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } updatedState.addMessages([message], location: .UpperHistoryBlock) updatedState.updateChannelState(message.id.peerId, state: previousState.setPts(pts)) } else { @@ -762,10 +867,52 @@ private func finalStateWithUpdates(account: Account, state: MutableState, update } } } - case let .updateNewMessage(message, _, _): - if let message = StoreMessage(apiMessage: message) { + case let .updateNewMessage(apiMessage, _, _): + if let message = StoreMessage(apiMessage: apiMessage) { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } updatedState.addMessages([message], location: .UpperHistoryBlock) } + case let .updateServiceNotification(flags, date, type, text, media, entities): + if let date = date { + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 777000) + + var alreadyStored = false + if let storedMessages = updatedState.storedMessagesByPeerIdAndTimestamp[peerId] { + for index in storedMessages { + if index.timestamp == date { + alreadyStored = true + break + } + } + } + + if alreadyStored { + trace("State", what: "skipping message at \(date) for \(peerId): already stored") + } else { + var attributes: [MessageAttribute] = [] + if !entities.isEmpty { + attributes.append(TextEntitiesMessageAttribute(entities: messageTextEntitiesFromApiEntities(entities))) + } + var messageText = text + var medias: [Media] = [] + + let (mediaText, mediaValue) = textAndMediaFromApiMedia(media) + if let mediaText = mediaText { + messageText = mediaText + } + if let mediaValue = mediaValue { + medias.append(mediaValue) + } + + let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, timestamp: date, flags: [.Incoming], tags: [], forwardInfo: nil, authorId: peerId, text: messageText, attributes: attributes, media: []) + updatedState.addMessages([message], location: .UpperHistoryBlock) + } + } + break case let .updateReadChannelInbox(channelId, maxId): updatedState.readInbox(MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: maxId)) case let .updateReadChannelOutbox(channelId, maxId): @@ -989,8 +1136,13 @@ private func pollChannel(_ account: Account, peer: Peer, state: MutableState) -> updatedState.mergeChats(chats) updatedState.mergeUsers(users) - for message in newMessages { - if let message = StoreMessage(apiMessage: message) { + for apiMessage in newMessages { + if let message = StoreMessage(apiMessage: apiMessage) { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } updatedState.addMessages([message], location: .UpperHistoryBlock) } } @@ -1025,8 +1177,14 @@ private func pollChannel(_ account: Account, peer: Peer, state: MutableState) -> updatedState.addHole(MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32.max)) - for message in messages { - if let message = StoreMessage(apiMessage: message) { + for apiMessage in messages { + if let message = StoreMessage(apiMessage: apiMessage) { + if let preCachedResources = apiMessage.preCachedResources { + for (resource, data) in preCachedResources { + updatedState.addPreCachedResource(resource, data: data) + } + } + let location: AddMessagesLocation if case let .Id(id) = message.id, id.id == topMessage { location = .UpperHistoryBlock @@ -1269,6 +1427,11 @@ private func pollDifference(_ account: Account) -> Signal { } else { return finalStateWithDifference(account: account, state: state, difference: difference) |> mapToSignal { finalState -> Signal in + if !finalState.state.preCachedResources.isEmpty { + for (resource, data) in finalState.state.preCachedResources { + account.postbox.mediaBox.storeResourceData(resource.id, data: data) + } + } return account.postbox.modify { modifier -> Signal in if replayFinalState(modifier, finalState: finalState.state) { if case .differenceSlice = difference { @@ -1451,6 +1614,12 @@ public final class StateManager { |> mapToSignal { state in return finalStateWithUpdateGroups(account, state: state, groups: groups) |> mapToSignal { finalState in + if !finalState.state.preCachedResources.isEmpty { + for (resource, data) in finalState.state.preCachedResources { + account.postbox.mediaBox.storeResourceData(resource.id, data: data) + } + } + return account.postbox.modify { modifier -> Bool in return replayFinalState(modifier, finalState: finalState.state) } |> deliverOn(stateQueue) |> mapToSignal { [weak strongSelf] result in diff --git a/TelegramCore/UpdatesApiUtils.swift b/TelegramCore/UpdatesApiUtils.swift index 083c5e87ea..602a69d4a0 100644 --- a/TelegramCore/UpdatesApiUtils.swift +++ b/TelegramCore/UpdatesApiUtils.swift @@ -5,6 +5,39 @@ import Foundation import Postbox #endif +extension Api.MessageMedia { + var preCachedResources: [(MediaResource, Data)]? { + switch self { + case let .messageMediaPhoto(photo, _): + switch photo { + case let .photo(_, _, _, _, sizes): + for size in sizes { + switch size { + case let .photoCachedSize(_, location, _, _, bytes): + switch location { + case let .fileLocation(dcId, volumeId, localId, secret): + let data = bytes.makeData() + let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: data.count) + return [(resource, data)] + default: + break + } + default: + break + } + } + return nil + default: + return nil + } + case let .messageMediaDocument(document, _): + return nil + default: + return nil + } + } +} + extension Api.Message { var rawId: Int32 { switch self { @@ -57,6 +90,15 @@ extension Api.Message { return nil } } + + var preCachedResources: [(MediaResource, Data)]? { + switch self { + case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _): + return media?.preCachedResources + default: + return nil + } + } } extension Api.Chat {