mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
no message
This commit is contained in:
@@ -289,6 +289,16 @@
|
||||
D07827CB1E02F5B200071108 /* RichText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827CA1E02F5B200071108 /* RichText.swift */; };
|
||||
D08774FC1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08774FB1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift */; };
|
||||
D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */; };
|
||||
D08CAA7D1ED77EE90000FDA8 /* LocalizationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA7C1ED77EE90000FDA8 /* LocalizationSettings.swift */; };
|
||||
D08CAA7E1ED77EE90000FDA8 /* LocalizationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA7C1ED77EE90000FDA8 /* LocalizationSettings.swift */; };
|
||||
D08CAA801ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA7F1ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift */; };
|
||||
D08CAA811ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA7F1ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift */; };
|
||||
D08CAA841ED8164B0000FDA8 /* Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA831ED8164B0000FDA8 /* Localization.swift */; };
|
||||
D08CAA851ED8164B0000FDA8 /* Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA831ED8164B0000FDA8 /* Localization.swift */; };
|
||||
D08CAA871ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */; };
|
||||
D08CAA881ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */; };
|
||||
D08CAA8C1ED81EDF0000FDA8 /* Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */; };
|
||||
D08CAA8D1ED81EDF0000FDA8 /* Localizations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */; };
|
||||
D08F4A661E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
@@ -676,6 +686,11 @@
|
||||
D07827CA1E02F5B200071108 /* RichText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RichText.swift; sourceTree = "<group>"; };
|
||||
D08774FB1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedGlobalNotificationSettings.swift; sourceTree = "<group>"; };
|
||||
D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalNotificationSettings.swift; sourceTree = "<group>"; };
|
||||
D08CAA7C1ED77EE90000FDA8 /* LocalizationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizationSettings.swift; sourceTree = "<group>"; };
|
||||
D08CAA7F1ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuggestedLocalizationEntry.swift; sourceTree = "<group>"; };
|
||||
D08CAA831ED8164B0000FDA8 /* Localization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localization.swift; sourceTree = "<group>"; };
|
||||
D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizationInfo.swift; sourceTree = "<group>"; };
|
||||
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localizations.swift; sourceTree = "<group>"; };
|
||||
D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||
D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||
D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerCommands.swift; sourceTree = "<group>"; };
|
||||
@@ -842,6 +857,7 @@
|
||||
D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */,
|
||||
D05A32E61E6F0B5C002760B4 /* RecentAccountSession.swift */,
|
||||
D0FA35041EA6135D00E56FFA /* CacheStorageSettings.swift */,
|
||||
D08CAA7C1ED77EE90000FDA8 /* LocalizationSettings.swift */,
|
||||
);
|
||||
name = Settings;
|
||||
sourceTree = "<group>";
|
||||
@@ -945,6 +961,7 @@
|
||||
D0FA8B961E1E952D001E855B /* Secret Chats */,
|
||||
D021E0DD1DB539E800C6B04F /* Item Collections */,
|
||||
D01B27A01E394D7B0022A4C0 /* Settings */,
|
||||
D08CAA821ED816290000FDA8 /* Localization */,
|
||||
);
|
||||
name = Objects;
|
||||
sourceTree = "<group>";
|
||||
@@ -1208,6 +1225,24 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D08CAA821ED816290000FDA8 /* Localization */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D08CAA7F1ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift */,
|
||||
D08CAA831ED8164B0000FDA8 /* Localization.swift */,
|
||||
D08CAA861ED81DD40000FDA8 /* LocalizationInfo.swift */,
|
||||
);
|
||||
name = Localization;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D08CAA8A1ED81EA10000FDA8 /* Localization */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */,
|
||||
);
|
||||
name = Localization;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D09D8BF71D4FAB1D0081DBEC = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1247,6 +1282,7 @@
|
||||
D0C50E2F1E93A83B00F62E39 /* Calls */,
|
||||
D021E0E01DB5400200C6B04F /* Sticker Management */,
|
||||
D05A32DF1E6F096B002760B4 /* Settings */,
|
||||
D08CAA8A1ED81EA10000FDA8 /* Localization */,
|
||||
D03B0E3A1D631E4400955575 /* Supporting Files */,
|
||||
D09D8C041D4FAB1D0081DBEC /* TelegramCore.h */,
|
||||
D09D8C051D4FAB1D0081DBEC /* Info.plist */,
|
||||
@@ -1592,6 +1628,7 @@
|
||||
D0E23DD51E8042F500B9B6D2 /* FeaturedStickerPack.swift in Sources */,
|
||||
D0FA8B981E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */,
|
||||
D0DF0C911D81A857008AEB01 /* ImageRepresentationsUtils.swift in Sources */,
|
||||
D08CAA8C1ED81EDF0000FDA8 /* Localizations.swift in Sources */,
|
||||
D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */,
|
||||
D0F3A8A21E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift in Sources */,
|
||||
D03B0D5A1D631A6900955575 /* Api.swift in Sources */,
|
||||
@@ -1601,6 +1638,7 @@
|
||||
D0B843B21DA7FF30005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
||||
D03B0CDB1D62245F00955575 /* ApiUtils.swift in Sources */,
|
||||
D0B843C91DA7FF30005F29E1 /* NBPhoneNumberDesc.m in Sources */,
|
||||
D08CAA801ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift in Sources */,
|
||||
D03B0CE61D6224A700955575 /* ReplyMessageAttribute.swift in Sources */,
|
||||
D0BEAF601E54ACF900BD963D /* AccountManager.swift in Sources */,
|
||||
D0FA0ABD1E76C908005BB9B7 /* TwoStepVerification.swift in Sources */,
|
||||
@@ -1664,6 +1702,7 @@
|
||||
D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||
D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||
D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */,
|
||||
D08CAA871ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */,
|
||||
D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */,
|
||||
D00C7CCC1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */,
|
||||
D09BB6B41DB02C2B00A905C0 /* PendingMessageManager.swift in Sources */,
|
||||
@@ -1683,6 +1722,7 @@
|
||||
D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */,
|
||||
D0E35A121DE4A25E00BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */,
|
||||
C239BE9C1E630CA700C2C453 /* UpdatePinnedMessage.swift in Sources */,
|
||||
D08CAA7D1ED77EE90000FDA8 /* LocalizationSettings.swift in Sources */,
|
||||
D0B844531DAC0773005F29E1 /* TelegramUserPresence.swift in Sources */,
|
||||
D08F4A661E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */,
|
||||
D05A32E71E6F0B5C002760B4 /* RecentAccountSession.swift in Sources */,
|
||||
@@ -1742,6 +1782,7 @@
|
||||
C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */,
|
||||
D0B843C11DA7FF30005F29E1 /* NBPhoneMetaData.m in Sources */,
|
||||
D0528E601E65B94E00E2FEF5 /* SingleMessageView.swift in Sources */,
|
||||
D08CAA841ED8164B0000FDA8 /* Localization.swift in Sources */,
|
||||
D0528E5A1E658B3600E2FEF5 /* ManagedLocalInputActivities.swift in Sources */,
|
||||
D0FA8BA41E1FA341001E855B /* SecretChatKeychain.swift in Sources */,
|
||||
D01749601E118FC30057C89A /* AccountIntermediateState.swift in Sources */,
|
||||
@@ -1868,6 +1909,7 @@
|
||||
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */,
|
||||
D0E35A131DE4C69100BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */,
|
||||
D0B418961D7E0580004562A4 /* TelegramMediaFile.swift in Sources */,
|
||||
D08CAA881ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */,
|
||||
D001F3EC1E128A1C007A8C60 /* Holes.swift in Sources */,
|
||||
D0B4189B1D7E0580004562A4 /* TelegramMediaWebpage.swift in Sources */,
|
||||
D00C7CE11E3785710080C3D5 /* MarkMessageContentAsConsumedInteractively.swift in Sources */,
|
||||
@@ -1880,6 +1922,7 @@
|
||||
D0613FD01E60520700202CDB /* ChannelMembers.swift in Sources */,
|
||||
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||
C2366C8A1E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
||||
D08CAA811ED80ED20000FDA8 /* SuggestedLocalizationEntry.swift in Sources */,
|
||||
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
||||
D0C48F3D1E8142EF0075317D /* LoadedPeerFromMessage.swift in Sources */,
|
||||
D0F3A8A01E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift in Sources */,
|
||||
@@ -1917,6 +1960,7 @@
|
||||
D050F2611E4A5AE700988324 /* PrivacySettings.swift in Sources */,
|
||||
D0B8440F1DAB91CD005F29E1 /* Either.swift in Sources */,
|
||||
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */,
|
||||
D08CAA8D1ED81EDF0000FDA8 /* Localizations.swift in Sources */,
|
||||
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */,
|
||||
D001F3EF1E128A1C007A8C60 /* AccountIntermediateState.swift in Sources */,
|
||||
D0223A991EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */,
|
||||
@@ -1987,6 +2031,7 @@
|
||||
C2366C871E4F403C0097CCFF /* AddressNames.swift in Sources */,
|
||||
D02ABC7F1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift in Sources */,
|
||||
D0528E611E65B94E00E2FEF5 /* SingleMessageView.swift in Sources */,
|
||||
D08CAA851ED8164B0000FDA8 /* Localization.swift in Sources */,
|
||||
D0528E5B1E658B3600E2FEF5 /* ManagedLocalInputActivities.swift in Sources */,
|
||||
D0FA8BA51E1FA341001E855B /* SecretChatKeychain.swift in Sources */,
|
||||
D0F7B1E71E045C87007EB8A5 /* JoinChannel.swift in Sources */,
|
||||
@@ -2002,6 +2047,7 @@
|
||||
D0E305A81E5B5CBE00D7A3A2 /* PeerAdmins.swift in Sources */,
|
||||
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */,
|
||||
D0B844431DAB91FD005F29E1 /* Account.swift in Sources */,
|
||||
D08CAA7E1ED77EE90000FDA8 /* LocalizationSettings.swift in Sources */,
|
||||
D0448CA01E27F5EB005A61A7 /* Random.swift in Sources */,
|
||||
C251D7441E65E50500283EDE /* StickerSetInstallation.swift in Sources */,
|
||||
);
|
||||
|
||||
@@ -33,10 +33,10 @@ public class AuthorizedAccountState: AccountState {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.pts = decoder.decodeInt32ForKey("pts")
|
||||
self.qts = decoder.decodeInt32ForKey("qts")
|
||||
self.date = decoder.decodeInt32ForKey("date")
|
||||
self.seq = decoder.decodeInt32ForKey("seq")
|
||||
self.pts = decoder.decodeInt32ForKey("pts", orElse: 0)
|
||||
self.qts = decoder.decodeInt32ForKey("qts", orElse: 0)
|
||||
self.date = decoder.decodeInt32ForKey("date", orElse: 0)
|
||||
self.seq = decoder.decodeInt32ForKey("seq", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -57,8 +57,8 @@ public class AuthorizedAccountState: AccountState {
|
||||
let state: State?
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.masterDatacenterId = decoder.decodeInt32ForKey("masterDatacenterId")
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("peerId"))
|
||||
self.masterDatacenterId = decoder.decodeInt32ForKey("masterDatacenterId", orElse: 0)
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0))
|
||||
self.state = decoder.decodeObjectForKey("state", decoder: { return State(decoder: $0) }) as? State
|
||||
}
|
||||
|
||||
@@ -145,12 +145,16 @@ public class UnauthorizedAccount {
|
||||
postbox.removeKeychainEntryForKey(key)
|
||||
})
|
||||
|
||||
return initializedNetwork(apiId: self.apiId, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment)
|
||||
return self.postbox.modify { modifier -> LocalizationSettings? in
|
||||
return modifier.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings
|
||||
} |> mapToSignal { settings -> Signal<UnauthorizedAccount, NoError> in
|
||||
return initializedNetwork(apiId: self.apiId, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: settings?.languageCode)
|
||||
|> map { network in
|
||||
let updated = UnauthorizedAccount(apiId: self.apiId, id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
|
||||
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
|
||||
return updated
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,6 +224,8 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(SynchronizeChatInputStateOperation.self, f: { SynchronizeChatInputStateOperation(decoder: $0) })
|
||||
declareEncodable(SynchronizeSavedGifsOperation.self, f: { SynchronizeSavedGifsOperation(decoder: $0) })
|
||||
declareEncodable(CacheStorageSettings.self, f: { CacheStorageSettings(decoder: $0) })
|
||||
declareEncodable(LocalizationSettings.self, f: { LocalizationSettings(decoder: $0) })
|
||||
declareEncodable(SuggestedLocalizationEntry.self, f: { SuggestedLocalizationEntry(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
@@ -248,7 +254,7 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, supplementary: Bool
|
||||
initializeMessageNamespacesWithHoles.append((peerNamespace, Namespaces.Message.Cloud))
|
||||
}
|
||||
|
||||
let seedConfiguration = SeedConfiguration(initializeChatListWithHoles: [ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))], initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: allMessageTags)
|
||||
let seedConfiguration = SeedConfiguration(initializeChatListWithHoles: [ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))], initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: MessageTags.all, existingGlobalMessageTags: GlobalMessageTags.all)
|
||||
|
||||
let postbox = openPostbox(basePath: path + "/postbox", globalMessageIdsNamespace: Namespaces.Message.Cloud, seedConfiguration: seedConfiguration)
|
||||
|
||||
@@ -260,36 +266,40 @@ public func accountWithId(apiId: Int32, id: AccountRecordId, supplementary: Bool
|
||||
return postbox.stateView()
|
||||
|> take(1)
|
||||
|> mapToSignal { view -> Signal<AccountResult, NoError> in
|
||||
let accountState = view.state
|
||||
|
||||
let keychain = Keychain(get: { key in
|
||||
return postbox.keychainEntryForKey(key)
|
||||
}, set: { (key, data) in
|
||||
postbox.setKeychainEntryForKey(key, value: data)
|
||||
}, remove: { key in
|
||||
postbox.removeKeychainEntryForKey(key)
|
||||
})
|
||||
|
||||
if let accountState = accountState {
|
||||
switch accountState {
|
||||
case let unauthorizedState as UnauthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
return postbox.modify { modifier -> LocalizationSettings? in
|
||||
return modifier.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings
|
||||
} |> mapToSignal { settings -> Signal<AccountResult, NoError> in
|
||||
let accountState = view.state
|
||||
|
||||
let keychain = Keychain(get: { key in
|
||||
return postbox.keychainEntryForKey(key)
|
||||
}, set: { (key, data) in
|
||||
postbox.setKeychainEntryForKey(key, value: data)
|
||||
}, remove: { key in
|
||||
postbox.removeKeychainEntryForKey(key)
|
||||
})
|
||||
|
||||
if let accountState = accountState {
|
||||
switch accountState {
|
||||
case let unauthorizedState as UnauthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: settings?.languageCode)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
case let authorizedState as AuthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: settings?.languageCode)
|
||||
|> map { network -> AccountResult in
|
||||
return .authorized(Account(id: id, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods))
|
||||
}
|
||||
case let authorizedState as AuthorizedAccountState:
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .authorized(Account(id: id, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods))
|
||||
}
|
||||
case _:
|
||||
assertionFailure("Unexpected accountState \(accountState)")
|
||||
case _:
|
||||
assertionFailure("Unexpected accountState \(accountState)")
|
||||
}
|
||||
}
|
||||
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: settings?.languageCode)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
}
|
||||
|
||||
return initializedNetwork(apiId: apiId, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: testingEnvironment)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,15 @@ public enum SentAuthorizationCodeType: Coding, Equatable {
|
||||
case flashCall(pattern: String)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case SentAuthorizationCodeTypeValue.otherSession.rawValue:
|
||||
self = .otherSession(length: decoder.decodeInt32ForKey("l"))
|
||||
self = .otherSession(length: decoder.decodeInt32ForKey("l", orElse: 0))
|
||||
case SentAuthorizationCodeTypeValue.sms.rawValue:
|
||||
self = .sms(length: decoder.decodeInt32ForKey("l"))
|
||||
self = .sms(length: decoder.decodeInt32ForKey("l", orElse: 0))
|
||||
case SentAuthorizationCodeTypeValue.call.rawValue:
|
||||
self = .call(length: decoder.decodeInt32ForKey("l"))
|
||||
self = .call(length: decoder.decodeInt32ForKey("l", orElse: 0))
|
||||
case SentAuthorizationCodeTypeValue.flashCall.rawValue:
|
||||
self = .flashCall(pattern: decoder.decodeStringForKey("p"))
|
||||
self = .flashCall(pattern: decoder.decodeStringForKey("p", orElse: ""))
|
||||
default:
|
||||
preconditionFailure()
|
||||
}
|
||||
@@ -99,25 +99,25 @@ public enum UnauthorizedAccountStateContents: Coding, Equatable {
|
||||
case empty
|
||||
case phoneEntry(countryCode: Int32, number: String)
|
||||
case confirmationCodeEntry(number: String, type: SentAuthorizationCodeType, hash: String, timeout: Int32?, nextType: AuthorizationCodeNextType?)
|
||||
case passwordEntry(hint: String, number:String?, code:String?)
|
||||
case passwordEntry(hint: String, number: String?, code: String?)
|
||||
case signUp(number: String, codeHash: String, code: String, firstName: String, lastName: String)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case UnauthorizedAccountStateContentsValue.empty.rawValue:
|
||||
self = .empty
|
||||
case UnauthorizedAccountStateContentsValue.phoneEntry.rawValue:
|
||||
self = .phoneEntry(countryCode: decoder.decodeInt32ForKey("cc"), number: decoder.decodeStringForKey("n"))
|
||||
self = .phoneEntry(countryCode: decoder.decodeInt32ForKey("cc", orElse: 1), number: decoder.decodeStringForKey("n", orElse: ""))
|
||||
case UnauthorizedAccountStateContentsValue.confirmationCodeEntry.rawValue:
|
||||
var nextType: AuthorizationCodeNextType?
|
||||
if let value = decoder.decodeInt32ForKey("nt") as Int32? {
|
||||
if let value = decoder.decodeOptionalInt32ForKey("nt") {
|
||||
nextType = AuthorizationCodeNextType(rawValue: value)
|
||||
}
|
||||
self = .confirmationCodeEntry(number: decoder.decodeStringForKey("num"), type: decoder.decodeObjectForKey("t", decoder: { SentAuthorizationCodeType(decoder: $0) }) as! SentAuthorizationCodeType, hash: decoder.decodeStringForKey("h"), timeout: decoder.decodeInt32ForKey("tm"), nextType: nextType)
|
||||
self = .confirmationCodeEntry(number: decoder.decodeStringForKey("num", orElse: ""), type: decoder.decodeObjectForKey("t", decoder: { SentAuthorizationCodeType(decoder: $0) }) as! SentAuthorizationCodeType, hash: decoder.decodeStringForKey("h", orElse: ""), timeout: decoder.decodeOptionalInt32ForKey("tm"), nextType: nextType)
|
||||
case UnauthorizedAccountStateContentsValue.passwordEntry.rawValue:
|
||||
self = .passwordEntry(hint: decoder.decodeStringForKey("h"), number: decoder.decodeStringForKey("n"), code: decoder.decodeStringForKey("c"))
|
||||
self = .passwordEntry(hint: decoder.decodeStringForKey("h", orElse: ""), number: decoder.decodeOptionalStringForKey("n"), code: decoder.decodeOptionalStringForKey("c"))
|
||||
case UnauthorizedAccountStateContentsValue.signUp.rawValue:
|
||||
self = .signUp(number: decoder.decodeStringForKey("n"), codeHash: decoder.decodeStringForKey("h"), code: decoder.decodeStringForKey("c"), firstName: decoder.decodeStringForKey("f"), lastName: decoder.decodeStringForKey("l"))
|
||||
self = .signUp(number: decoder.decodeStringForKey("n", orElse: ""), codeHash: decoder.decodeStringForKey("h", orElse: ""), code: decoder.decodeStringForKey("c", orElse: ""), firstName: decoder.decodeStringForKey("f", orElse: ""), lastName: decoder.decodeStringForKey("l", orElse: ""))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .empty
|
||||
@@ -231,7 +231,7 @@ public final class UnauthorizedAccountState: AccountState {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.masterDatacenterId = decoder.decodeInt32ForKey("dc")
|
||||
self.masterDatacenterId = decoder.decodeInt32ForKey("dc", orElse: 0)
|
||||
self.contents = decoder.decodeObjectForKey("c", decoder: { UnauthorizedAccountStateContents(decoder: $0) }) as! UnauthorizedAccountStateContents
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,28 @@ import Foundation
|
||||
import MtProtoKitDynamic
|
||||
#endif
|
||||
|
||||
public enum CallListViewType {
|
||||
case all
|
||||
case missed
|
||||
}
|
||||
|
||||
public enum CallListViewEntry {
|
||||
case message(Message, [Message])
|
||||
case hole(MessageIndex)
|
||||
}
|
||||
|
||||
public final class CallListView {
|
||||
public let entries: [CallListViewEntry]
|
||||
public let earlier: MessageIndex?
|
||||
public let later: MessageIndex?
|
||||
|
||||
init(entries: [CallListViewEntry], earlier: MessageIndex?, later: MessageIndex?) {
|
||||
self.entries = entries
|
||||
self.earlier = earlier
|
||||
self.later = later
|
||||
}
|
||||
}
|
||||
|
||||
private func pendingWebpages(entries: [MessageHistoryEntry]) -> Set<MessageId> {
|
||||
var messageIds = Set<MessageId>()
|
||||
for case let .MessageEntry(message, _, _, _) in entries {
|
||||
@@ -160,6 +182,10 @@ public final class AccountViewTracker {
|
||||
private var pendingWebpageMessageIds: [MessageId: Int] = [:]
|
||||
private var webpageDisposables: [MessageId: Disposable] = [:]
|
||||
|
||||
private var viewVisibleCallListHoleIds: [Int32: Set<MessageIndex>] = [:]
|
||||
private var visibleCallListHoleIds: [MessageIndex: Int] = [:]
|
||||
private var visibleCallListHoleDisposables: [MessageIndex: Disposable] = [:]
|
||||
|
||||
private var updatedViewCountMessageIdsAndTimestamps: [MessageId: Int32] = [:]
|
||||
private var nextUpdatedViewCountDisposableId: Int32 = 0
|
||||
private var updatedViewCountDisposables = DisposableDict<Int32>()
|
||||
@@ -238,6 +264,66 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateVisibleCallListHoles(viewId: Int32, holeIds: Set<MessageIndex>) {
|
||||
self.queue.async {
|
||||
var addedHoleIds: [MessageIndex] = []
|
||||
var removedHoleIds: [MessageIndex] = []
|
||||
|
||||
let viewHoleIds: Set<MessageIndex> = self.viewVisibleCallListHoleIds[viewId] ?? Set()
|
||||
|
||||
let viewAddedHoleIds = holeIds.subtracting(viewHoleIds)
|
||||
let viewRemovedHoleIds = viewHoleIds.subtracting(holeIds)
|
||||
for holeId in viewAddedHoleIds {
|
||||
if let count = self.visibleCallListHoleIds[holeId] {
|
||||
self.visibleCallListHoleIds[holeId] = count + 1
|
||||
} else {
|
||||
self.visibleCallListHoleIds[holeId] = 1
|
||||
addedHoleIds.append(holeId)
|
||||
}
|
||||
}
|
||||
for holeId in viewRemovedHoleIds {
|
||||
if let count = self.visibleCallListHoleIds[holeId] {
|
||||
if count == 1 {
|
||||
self.visibleCallListHoleIds.removeValue(forKey: holeId)
|
||||
removedHoleIds.append(holeId)
|
||||
} else {
|
||||
self.visibleCallListHoleIds[holeId] = count - 1
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
|
||||
if holeIds.isEmpty {
|
||||
self.viewVisibleCallListHoleIds.removeValue(forKey: viewId)
|
||||
} else {
|
||||
self.viewVisibleCallListHoleIds[viewId] = holeIds
|
||||
}
|
||||
|
||||
for holeId in removedHoleIds {
|
||||
if let disposable = self.visibleCallListHoleDisposables.removeValue(forKey: holeId) {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
if let account = self.account {
|
||||
for holeId in addedHoleIds {
|
||||
if self.visibleCallListHoleDisposables[holeId] == nil {
|
||||
self.visibleCallListHoleDisposables[holeId] = fetchCallListHole(network: account.network, postbox: account.postbox, holeIndex: holeId).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.queue.async {
|
||||
strongSelf.visibleCallListHoleDisposables.removeValue(forKey: holeId)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateViewCountForMessageIds(messageIds: Set<MessageId>) {
|
||||
self.queue.async {
|
||||
var addedMessageIds: [MessageId] = []
|
||||
@@ -568,4 +654,123 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func callListView(type: CallListViewType, index: MessageIndex, count: Int) -> Signal<CallListView, NoError> {
|
||||
if let account = self.account {
|
||||
let granularity: Int32 = 60 * 60 * 24
|
||||
let timezoneOffset: Int32 = {
|
||||
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
var now: time_t = time_t(nowTimestamp)
|
||||
var timeinfoNow: tm = tm()
|
||||
localtime_r(&now, &timeinfoNow)
|
||||
return Int32(timeinfoNow.tm_gmtoff)
|
||||
}()
|
||||
|
||||
let groupingPredicate: (Message, Message) -> Bool = { lhs, rhs in
|
||||
if lhs.id.peerId != rhs.id.peerId {
|
||||
return false
|
||||
}
|
||||
let lhsTimestamp = ((lhs.timestamp + timezoneOffset) / (granularity)) * (granularity)
|
||||
let rhsTimestamp = ((rhs.timestamp + timezoneOffset) / (granularity)) * (granularity)
|
||||
if lhsTimestamp != rhsTimestamp {
|
||||
return false
|
||||
}
|
||||
var lhsMissed = false
|
||||
var lhsOther = false
|
||||
inner: for media in lhs.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
if case let .phoneCall(_, discardReason, _) = action.action {
|
||||
if lhs.flags.contains(.Incoming), let discardReason = discardReason, case .missed = discardReason {
|
||||
lhsMissed = true
|
||||
} else {
|
||||
lhsOther = true
|
||||
}
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
var rhsMissed = false
|
||||
var rhsOther = false
|
||||
inner: for media in rhs.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
if case let .phoneCall(_, discardReason, _) = action.action {
|
||||
if rhs.flags.contains(.Incoming), let discardReason = discardReason, case .missed = discardReason {
|
||||
rhsMissed = true
|
||||
} else {
|
||||
rhsOther = true
|
||||
}
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
if lhsMissed != rhsMissed || lhsOther != rhsOther {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
let key = PostboxViewKey.globalMessageTags(globalTag: type == .all ? GlobalMessageTags.Calls : GlobalMessageTags.MissedCalls, position: index, count: 200, groupingPredicate: groupingPredicate)
|
||||
let signal = account.postbox.combinedView(keys: [key]) |> map { view -> GlobalMessageTagsView in
|
||||
let messageView = view.views[key] as! GlobalMessageTagsView
|
||||
return messageView
|
||||
}
|
||||
|
||||
let managed = withState(signal, { [weak self] () -> Int32 in
|
||||
if let strongSelf = self {
|
||||
return OSAtomicIncrement32(&strongSelf.nextViewId)
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}, next: { [weak self] next, viewId in
|
||||
if let strongSelf = self {
|
||||
var holes = Set<MessageIndex>()
|
||||
for entry in next.entries {
|
||||
if case let .hole(index) = entry {
|
||||
holes.insert(index)
|
||||
}
|
||||
}
|
||||
strongSelf.updateVisibleCallListHoles(viewId: viewId, holeIds: holes)
|
||||
}
|
||||
}, disposed: { [weak self] viewId in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateVisibleCallListHoles(viewId: viewId, holeIds: Set())
|
||||
}
|
||||
})
|
||||
|
||||
return managed
|
||||
|> map { view -> CallListView in
|
||||
var entries: [CallListViewEntry] = []
|
||||
if !view.entries.isEmpty {
|
||||
var currentMessages: [Message] = []
|
||||
for entry in view.entries {
|
||||
switch entry {
|
||||
case let .hole(index):
|
||||
if !currentMessages.isEmpty {
|
||||
entries.append(.message(currentMessages[currentMessages.count - 1], currentMessages))
|
||||
currentMessages.removeAll()
|
||||
}
|
||||
//entries.append(.hole(index))
|
||||
case let .message(message):
|
||||
if currentMessages.isEmpty || groupingPredicate(message, currentMessages[currentMessages.count - 1]) {
|
||||
currentMessages.append(message)
|
||||
} else {
|
||||
if !currentMessages.isEmpty {
|
||||
entries.append(.message(currentMessages[currentMessages.count - 1], currentMessages))
|
||||
currentMessages.removeAll()
|
||||
}
|
||||
currentMessages.append(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !currentMessages.isEmpty {
|
||||
entries.append(.message(currentMessages[currentMessages.count - 1], currentMessages))
|
||||
currentMessages.removeAll()
|
||||
}
|
||||
}
|
||||
return CallListView(entries: entries, earlier: view.earlier, later: view.later)
|
||||
}
|
||||
} else {
|
||||
return .never()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1343524562] = { return Api.InputChannel.parse_inputChannel($0) }
|
||||
dict[98092748] = { return Api.DcOption.parse_dcOption($0) }
|
||||
dict[-1212732749] = { return Api.account.PasswordSettings.parse_passwordSettings($0) }
|
||||
dict[292985073] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
||||
dict[-1987579119] = { return Api.help.AppUpdate.parse_appUpdate($0) }
|
||||
dict[-1000708810] = { return Api.help.AppUpdate.parse_noAppUpdate($0) }
|
||||
dict[-209337866] = { return Api.LangPackDifference.parse_langPackDifference($0) }
|
||||
dict[-791039645] = { return Api.channels.ChannelParticipant.parse_channelParticipant($0) }
|
||||
dict[-1299865402] = { return Api.ChannelParticipantRole.parse_channelRoleEmpty($0) }
|
||||
dict[-1776756363] = { return Api.ChannelParticipantRole.parse_channelRoleModerator($0) }
|
||||
@@ -196,6 +198,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-523384512] = { return Api.Update.parse_updateBotShippingQuery($0) }
|
||||
dict[1563376297] = { return Api.Update.parse_updateBotPrecheckoutQuery($0) }
|
||||
dict[-1425052898] = { return Api.Update.parse_updatePhoneCall($0) }
|
||||
dict[281165899] = { return Api.Update.parse_updateLangPackTooLong($0) }
|
||||
dict[1442983757] = { return Api.Update.parse_updateLangPack($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) }
|
||||
@@ -340,7 +344,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[-882895228] = { return Api.Config.parse_config($0) }
|
||||
dict[-163699244] = { 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) }
|
||||
@@ -442,6 +446,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-326966976] = { return Api.phone.PhoneCall.parse_phoneCall($0) }
|
||||
dict[-1132882121] = { return Api.Bool.parse_boolFalse($0) }
|
||||
dict[-1720552011] = { return Api.Bool.parse_boolTrue($0) }
|
||||
dict[-892239370] = { return Api.LangPackString.parse_langPackString($0) }
|
||||
dict[1816636575] = { return Api.LangPackString.parse_langPackStringPluralized($0) }
|
||||
dict[-1036396922] = { return Api.InputWebFileLocation.parse_inputWebFileLocation($0) }
|
||||
dict[-947462709] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
||||
dict[398898678] = { return Api.help.Support.parse_support($0) }
|
||||
@@ -654,8 +660,12 @@ public struct Api {
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.account.PasswordSettings:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.LangPackLanguage:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.help.AppUpdate:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.LangPackDifference:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.channels.ChannelParticipant:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ChannelParticipantRole:
|
||||
@@ -914,6 +924,8 @@ public struct Api {
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.Bool:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.LangPackString:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputWebFileLocation:
|
||||
return _1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessageFwdHeader:
|
||||
@@ -4296,6 +4308,106 @@ public struct Api {
|
||||
}
|
||||
}
|
||||
|
||||
public enum LangPackLanguage: CustomStringConvertible {
|
||||
case langPackLanguage(name: String, nativeName: String, langCode: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
|
||||
switch self {
|
||||
case .langPackLanguage(let name, let nativeName, let langCode):
|
||||
if boxed {
|
||||
buffer.appendInt32(292985073)
|
||||
}
|
||||
serializeString(name, buffer: buffer, boxed: false)
|
||||
serializeString(nativeName, buffer: buffer, boxed: false)
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate static func parse_langPackLanguage(_ reader: BufferReader) -> LangPackLanguage? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.LangPackLanguage.langPackLanguage(name: _1!, nativeName: _2!, langCode: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .langPackLanguage(let name, let nativeName, let langCode):
|
||||
return "(langPackLanguage name: \(name), nativeName: \(nativeName), langCode: \(langCode))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum LangPackDifference: CustomStringConvertible {
|
||||
case langPackDifference(langCode: String, fromVersion: Int32, version: Int32, strings: [Api.LangPackString])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
|
||||
switch self {
|
||||
case .langPackDifference(let langCode, let fromVersion, let version, let strings):
|
||||
if boxed {
|
||||
buffer.appendInt32(-209337866)
|
||||
}
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
serializeInt32(fromVersion, buffer: buffer, boxed: false)
|
||||
serializeInt32(version, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(strings.count))
|
||||
for item in strings {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate static func parse_langPackDifference(_ reader: BufferReader) -> LangPackDifference? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: [Api.LangPackString]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackString.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.LangPackDifference.langPackDifference(langCode: _1!, fromVersion: _2!, version: _3!, strings: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .langPackDifference(let langCode, let fromVersion, let version, let strings):
|
||||
return "(langPackDifference langCode: \(langCode), fromVersion: \(fromVersion), version: \(version), strings: \(strings))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChannelParticipantRole: CustomStringConvertible {
|
||||
case channelRoleEmpty
|
||||
case channelRoleModerator
|
||||
@@ -5207,6 +5319,8 @@ public struct Api {
|
||||
case updateBotShippingQuery(queryId: Int64, userId: Int32, payload: Buffer, shippingAddress: Api.PostAddress)
|
||||
case updateBotPrecheckoutQuery(flags: Int32, queryId: Int64, userId: Int32, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, currency: String, totalAmount: Int64)
|
||||
case updatePhoneCall(phoneCall: Api.PhoneCall)
|
||||
case updateLangPackTooLong
|
||||
case updateLangPack(difference: Api.LangPackDifference)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
|
||||
switch self {
|
||||
@@ -5712,6 +5826,18 @@ public struct Api {
|
||||
}
|
||||
phoneCall.serialize(buffer, true)
|
||||
break
|
||||
case .updateLangPackTooLong:
|
||||
if boxed {
|
||||
buffer.appendInt32(281165899)
|
||||
}
|
||||
|
||||
break
|
||||
case .updateLangPack(let difference):
|
||||
if boxed {
|
||||
buffer.appendInt32(1442983757)
|
||||
}
|
||||
difference.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -6752,6 +6878,22 @@ public struct Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
fileprivate static func parse_updateLangPackTooLong(_ reader: BufferReader) -> Update? {
|
||||
return Api.Update.updateLangPackTooLong
|
||||
}
|
||||
fileprivate static func parse_updateLangPack(_ reader: BufferReader) -> Update? {
|
||||
var _1: Api.LangPackDifference?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.LangPackDifference
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.Update.updateLangPack(difference: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
get {
|
||||
@@ -6876,6 +7018,10 @@ public struct Api {
|
||||
return "(updateBotPrecheckoutQuery flags: \(flags), queryId: \(queryId), userId: \(userId), payload: \(payload), info: \(info), shippingOptionId: \(shippingOptionId), currency: \(currency), totalAmount: \(totalAmount))"
|
||||
case .updatePhoneCall(let phoneCall):
|
||||
return "(updatePhoneCall phoneCall: \(phoneCall))"
|
||||
case .updateLangPackTooLong:
|
||||
return "(updateLangPackTooLong)"
|
||||
case .updateLangPack(let difference):
|
||||
return "(updateLangPack difference: \(difference))"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10326,13 +10472,13 @@ public struct Api {
|
||||
}
|
||||
|
||||
public enum Config: CustomStringConvertible {
|
||||
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?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, 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?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, suggestedLangCode: String?, 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 pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, 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 pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let suggestedLangCode, let disabledFeatures):
|
||||
if boxed {
|
||||
buffer.appendInt32(-882895228)
|
||||
buffer.appendInt32(-163699244)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
@@ -10367,6 +10513,7 @@ public struct Api {
|
||||
serializeInt32(callConnectTimeoutMs, buffer: buffer, boxed: false)
|
||||
serializeInt32(callPacketTimeoutMs, buffer: buffer, boxed: false)
|
||||
serializeString(meUrlPrefix, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(suggestedLangCode!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(disabledFeatures.count))
|
||||
for item in disabledFeatures {
|
||||
@@ -10440,9 +10587,11 @@ public struct Api {
|
||||
_28 = reader.readInt32()
|
||||
var _29: String?
|
||||
_29 = parseString(reader)
|
||||
var _30: [Api.DisabledFeature]?
|
||||
var _30: String?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_30 = parseString(reader) }
|
||||
var _31: [Api.DisabledFeature]?
|
||||
if let _ = reader.readInt32() {
|
||||
_30 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self)
|
||||
_31 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
@@ -10473,9 +10622,10 @@ public struct Api {
|
||||
let _c27 = _27 != nil
|
||||
let _c28 = _28 != nil
|
||||
let _c29 = _29 != nil
|
||||
let _c30 = _30 != 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 && _c29 && _c30 {
|
||||
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, pinnedDialogsCountMax: _24!, callReceiveTimeoutMs: _25!, callRingTimeoutMs: _26!, callConnectTimeoutMs: _27!, callPacketTimeoutMs: _28!, meUrlPrefix: _29!, disabledFeatures: _30!)
|
||||
let _c30 = (Int(_1!) & Int(1 << 2) == 0) || _30 != nil
|
||||
let _c31 = _31 != 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 && _c29 && _c30 && _c31 {
|
||||
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, pinnedDialogsCountMax: _24!, callReceiveTimeoutMs: _25!, callRingTimeoutMs: _26!, callConnectTimeoutMs: _27!, callPacketTimeoutMs: _28!, meUrlPrefix: _29!, suggestedLangCode: _30, disabledFeatures: _31!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@@ -10485,8 +10635,8 @@ public struct Api {
|
||||
public var description: String {
|
||||
get {
|
||||
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 pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let disabledFeatures):
|
||||
return "(config flags: \(flags), date: \(date), expires: \(expires), testMode: \(testMode), thisDc: \(thisDc), dcOptions: \(dcOptions), chatSizeMax: \(chatSizeMax), megagroupSizeMax: \(megagroupSizeMax), forwardedCountMax: \(forwardedCountMax), onlineUpdatePeriodMs: \(onlineUpdatePeriodMs), offlineBlurTimeoutMs: \(offlineBlurTimeoutMs), offlineIdleTimeoutMs: \(offlineIdleTimeoutMs), onlineCloudTimeoutMs: \(onlineCloudTimeoutMs), notifyCloudDelayMs: \(notifyCloudDelayMs), notifyDefaultDelayMs: \(notifyDefaultDelayMs), chatBigSize: \(chatBigSize), pushChatPeriodMs: \(pushChatPeriodMs), pushChatLimit: \(pushChatLimit), savedGifsLimit: \(savedGifsLimit), editTimeLimit: \(editTimeLimit), ratingEDecay: \(ratingEDecay), stickersRecentLimit: \(stickersRecentLimit), tmpSessions: \(tmpSessions), pinnedDialogsCountMax: \(pinnedDialogsCountMax), callReceiveTimeoutMs: \(callReceiveTimeoutMs), callRingTimeoutMs: \(callRingTimeoutMs), callConnectTimeoutMs: \(callConnectTimeoutMs), callPacketTimeoutMs: \(callPacketTimeoutMs), meUrlPrefix: \(meUrlPrefix), disabledFeatures: \(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 pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let suggestedLangCode, let disabledFeatures):
|
||||
return "(config flags: \(flags), date: \(date), expires: \(expires), testMode: \(testMode), thisDc: \(thisDc), dcOptions: \(dcOptions), chatSizeMax: \(chatSizeMax), megagroupSizeMax: \(megagroupSizeMax), forwardedCountMax: \(forwardedCountMax), onlineUpdatePeriodMs: \(onlineUpdatePeriodMs), offlineBlurTimeoutMs: \(offlineBlurTimeoutMs), offlineIdleTimeoutMs: \(offlineIdleTimeoutMs), onlineCloudTimeoutMs: \(onlineCloudTimeoutMs), notifyCloudDelayMs: \(notifyCloudDelayMs), notifyDefaultDelayMs: \(notifyDefaultDelayMs), chatBigSize: \(chatBigSize), pushChatPeriodMs: \(pushChatPeriodMs), pushChatLimit: \(pushChatLimit), savedGifsLimit: \(savedGifsLimit), editTimeLimit: \(editTimeLimit), ratingEDecay: \(ratingEDecay), stickersRecentLimit: \(stickersRecentLimit), tmpSessions: \(tmpSessions), pinnedDialogsCountMax: \(pinnedDialogsCountMax), callReceiveTimeoutMs: \(callReceiveTimeoutMs), callRingTimeoutMs: \(callRingTimeoutMs), callConnectTimeoutMs: \(callConnectTimeoutMs), callPacketTimeoutMs: \(callPacketTimeoutMs), meUrlPrefix: \(meUrlPrefix), suggestedLangCode: \(suggestedLangCode), disabledFeatures: \(disabledFeatures))"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13336,6 +13486,95 @@ public struct Api {
|
||||
}
|
||||
}
|
||||
|
||||
public enum LangPackString: CustomStringConvertible {
|
||||
case langPackString(key: String, value: String)
|
||||
case langPackStringPluralized(flags: Int32, key: String, zeroValue: String?, oneValue: String?, twoValue: String?, fewValue: String?, manyValue: String?, otherValue: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
if boxed {
|
||||
buffer.appendInt32(-892239370)
|
||||
}
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
serializeString(value, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
if boxed {
|
||||
buffer.appendInt32(1816636575)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(zeroValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(oneValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(twoValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(fewValue!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeString(manyValue!, buffer: buffer, boxed: false)}
|
||||
serializeString(otherValue, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate static func parse_langPackString(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.LangPackString.langPackString(key: _1!, value: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
fileprivate static func parse_langPackStringPluralized(_ reader: BufferReader) -> LangPackString? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
|
||||
var _8: String?
|
||||
_8 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.LangPackString.langPackStringPluralized(flags: _1!, key: _2!, zeroValue: _3, oneValue: _4, twoValue: _5, fewValue: _6, manyValue: _7, otherValue: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .langPackString(let key, let value):
|
||||
return "(langPackString key: \(key), value: \(value))"
|
||||
case .langPackStringPluralized(let flags, let key, let zeroValue, let oneValue, let twoValue, let fewValue, let manyValue, let otherValue):
|
||||
return "(langPackStringPluralized flags: \(flags), key: \(key), zeroValue: \(zeroValue), oneValue: \(oneValue), twoValue: \(twoValue), fewValue: \(fewValue), manyValue: \(manyValue), otherValue: \(otherValue))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum InputWebFileLocation: CustomStringConvertible {
|
||||
case inputWebFileLocation(url: String, accessHash: Int64)
|
||||
|
||||
@@ -22217,6 +22456,68 @@ public struct Api {
|
||||
})
|
||||
}
|
||||
}
|
||||
public struct langpack {
|
||||
public static func getLangPack(langCode langCode: String) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.LangPackDifference?) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1699363442)
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription({return "(langpack.getLangPack langCode: \(langCode))"}), buffer, { (buffer: Buffer) -> Api.LangPackDifference? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.LangPackDifference?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.LangPackDifference
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getStrings(langCode langCode: String, keys: [String]) -> (CustomStringConvertible, Buffer, (Buffer) -> [Api.LangPackString]?) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(773776152)
|
||||
serializeString(langCode, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(keys.count))
|
||||
for item in keys {
|
||||
serializeString(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
return (FunctionDescription({return "(langpack.getStrings langCode: \(langCode), keys: \(keys))"}), buffer, { (buffer: Buffer) -> [Api.LangPackString]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Api.LangPackString]?
|
||||
if let _ = reader.readInt32() {
|
||||
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackString.self)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getDifference(fromVersion fromVersion: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.LangPackDifference?) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(187583869)
|
||||
serializeInt32(fromVersion, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription({return "(langpack.getDifference fromVersion: \(fromVersion))"}), buffer, { (buffer: Buffer) -> Api.LangPackDifference? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.LangPackDifference?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.LangPackDifference
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getLanguages() -> (CustomStringConvertible, Buffer, (Buffer) -> [Api.LangPackLanguage]?) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-2146445955)
|
||||
|
||||
return (FunctionDescription({return "(langpack.getLanguages )"}), buffer, { (buffer: Buffer) -> [Api.LangPackLanguage]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Api.LangPackLanguage]?
|
||||
if let _ = reader.readInt32() {
|
||||
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackLanguage.self)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public struct photos {
|
||||
public static func updateProfilePhoto(id id: Api.InputPhoto) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.UserProfilePhoto?) {
|
||||
let buffer = Buffer()
|
||||
|
||||
@@ -16,7 +16,7 @@ public func applyMaxReadIndexInteractively(postbox: Postbox, network: Network, i
|
||||
if let message = modifier.getMessage(id) {
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? AutoremoveTimeoutMessageAttribute {
|
||||
if attribute.countdownBeginTime == nil && !message.containsSecretMedia {
|
||||
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && !message.containsSecretMedia {
|
||||
modifier.updateMessage(message.id, update: { currentMessage in
|
||||
var storeForwardInfo: StoreMessageForwardInfo?
|
||||
if let forwardInfo = currentMessage.forwardInfo {
|
||||
@@ -49,7 +49,7 @@ func applyOutgoingReadMaxIndex(modifier: Modifier, index: MessageIndex, beginAt
|
||||
if let message = modifier.getMessage(id), !message.flags.contains(.Incoming) {
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? AutoremoveTimeoutMessageAttribute {
|
||||
if attribute.countdownBeginTime == nil && !message.containsSecretMedia {
|
||||
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && !message.containsSecretMedia {
|
||||
modifier.updateMessage(message.id, update: { currentMessage in
|
||||
var storeForwardInfo: StoreMessageForwardInfo?
|
||||
if let forwardInfo = currentMessage.forwardInfo {
|
||||
|
||||
@@ -122,7 +122,9 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
||||
}
|
||||
}
|
||||
|
||||
return .update(StoreMessage(id: updatedId, globallyUniqueId: nil, timestamp: updatedTimestamp ?? currentMessage.timestamp, flags: [], tags: tagsForStoreMessage(media: media, textEntities: entitiesAttribute?.entities), globalTags: globalTagsForStoreMessage(media: media), forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media))
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), media: media, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
return .update(StoreMessage(id: updatedId, globallyUniqueId: nil, timestamp: updatedTimestamp ?? currentMessage.timestamp, flags: [], tags: tags, globalTags: globalTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media))
|
||||
})
|
||||
if let updatedTimestamp = updatedTimestamp {
|
||||
modifier.offsetPendingMessagesTimestamps(lowerBound: message.id, timestamp: updatedTimestamp)
|
||||
|
||||
@@ -33,7 +33,7 @@ public final class ArchivedStickerPacksInfo: OrderedItemListEntryContents {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.count = (decoder.decodeInt32ForKey("c") as Int32)
|
||||
self.count = decoder.decodeInt32ForKey("c", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -21,8 +21,8 @@ public class AutoremoveTimeoutMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.timeout = decoder.decodeInt32ForKey("t")
|
||||
self.countdownBeginTime = decoder.decodeInt32ForKey("c")
|
||||
self.timeout = decoder.decodeInt32ForKey("t", orElse: 0)
|
||||
self.countdownBeginTime = decoder.decodeOptionalInt32ForKey("c")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -15,8 +15,8 @@ public struct BotCommand: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.text = decoder.decodeStringForKey("t")
|
||||
self.description = decoder.decodeStringForKey("d")
|
||||
self.text = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.description = decoder.decodeStringForKey("d", orElse: "")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -39,7 +39,7 @@ public final class BotInfo: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.description = decoder.decodeStringForKey("d")
|
||||
self.description = decoder.decodeStringForKey("d", orElse: "")
|
||||
self.commands = decoder.decodeObjectArrayWithDecoderForKey("c")
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public struct CacheStorageSettings: PreferencesEntry, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.defaultCacheStorageTimeout = decoder.decodeInt32ForKey("dt") as Int32
|
||||
self.defaultCacheStorageTimeout = decoder.decodeInt32ForKey("dt", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -32,17 +32,17 @@ public struct CachedChannelParticipantsSummary: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
if let memberCount = decoder.decodeInt32ForKey("p.m") as Int32? {
|
||||
if let memberCount = decoder.decodeOptionalInt32ForKey("p.m") {
|
||||
self.memberCount = memberCount
|
||||
} else {
|
||||
self.memberCount = 0
|
||||
}
|
||||
if let adminCount = decoder.decodeInt32ForKey("p.a") as Int32? {
|
||||
if let adminCount = decoder.decodeOptionalInt32ForKey("p.a") {
|
||||
self.adminCount = adminCount
|
||||
} else {
|
||||
self.adminCount = 0
|
||||
}
|
||||
if let bannedCount = decoder.decodeInt32ForKey("p.b") as Int32? {
|
||||
if let bannedCount = decoder.decodeOptionalInt32ForKey("p.b") {
|
||||
self.bannedCount = bannedCount
|
||||
} else {
|
||||
self.bannedCount = 0
|
||||
@@ -163,15 +163,15 @@ public final class CachedChannelData: CachedPeerData {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.flags = CachedChannelFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.about = decoder.decodeStringForKey("a")
|
||||
self.flags = CachedChannelFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
self.about = decoder.decodeOptionalStringForKey("a")
|
||||
self.participantsSummary = CachedChannelParticipantsSummary(decoder: decoder)
|
||||
self.exportedInvitation = decoder.decodeObjectForKey("i", decoder: { ExportedInvitation(decoder: $0) }) as? ExportedInvitation
|
||||
self.botInfos = decoder.decodeObjectArrayWithDecoderForKey("b") as [CachedPeerBotInfo]
|
||||
var peerIds = Set<PeerId>()
|
||||
self.topParticipants = decoder.decodeObjectForKey("p", decoder: { CachedChannelParticipants(decoder: $0) }) as? CachedChannelParticipants
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))!
|
||||
if let pinnedMessagePeerId = (decoder.decodeInt64ForKey("pm.p") as Int64?), let pinnedMessageNamespace = (decoder.decodeInt32ForKey("pm.n") as Int32?), let pinnedMessageId = (decoder.decodeInt32ForKey("pm.i") as Int32?) {
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r", orElse: 0))!
|
||||
if let pinnedMessagePeerId = decoder.decodeOptionalInt64ForKey("pm.p"), let pinnedMessageNamespace = decoder.decodeOptionalInt32ForKey("pm.n"), let pinnedMessageId = decoder.decodeOptionalInt32ForKey("pm.i") {
|
||||
self.pinnedMessageId = MessageId(peerId: PeerId(pinnedMessagePeerId), namespace: pinnedMessageNamespace, id: pinnedMessageId)
|
||||
} else {
|
||||
self.pinnedMessageId = nil
|
||||
|
||||
@@ -61,18 +61,18 @@ public enum ChannelParticipant: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case ChannelParticipantValue.member.rawValue:
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case ChannelParticipantValue.creator.rawValue:
|
||||
self = .creator(id: PeerId(decoder.decodeInt64ForKey("i")))
|
||||
self = .creator(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)))
|
||||
case ChannelParticipantValue.editor.rawValue:
|
||||
self = .editor(id: PeerId(decoder.decodeInt64ForKey("i")), invitedBy: PeerId(decoder.decodeInt64ForKey("p")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .editor(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedBy: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case ChannelParticipantValue.moderator.rawValue:
|
||||
self = .moderator(id: PeerId(decoder.decodeInt64ForKey("i")), invitedBy: PeerId(decoder.decodeInt64ForKey("p")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .moderator(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedBy: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class CachedPeerBotInfo: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p"))
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p", orElse: 0))
|
||||
self.botInfo = decoder.decodeObjectForKey("i", decoder: { return BotInfo(decoder: $0) }) as! BotInfo
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.participants = participants
|
||||
self.exportedInvitation = decoder.decodeObjectForKey("i", decoder: { ExportedInvitation(decoder: $0) }) as? ExportedInvitation
|
||||
self.botInfos = decoder.decodeObjectArrayWithDecoderForKey("b") as [CachedPeerBotInfo]
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))!
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r", orElse: 0))!
|
||||
|
||||
var peerIds = Set<PeerId>()
|
||||
if let participants = participants {
|
||||
|
||||
@@ -22,15 +22,15 @@ public enum GroupParticipant: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case 0:
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i")), invitedBy: PeerId(decoder.decodeInt64ForKey("b")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedBy: PeerId(decoder.decodeInt64ForKey("b", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case 1:
|
||||
self = .creator(id: PeerId(decoder.decodeInt64ForKey("i")))
|
||||
self = .creator(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)))
|
||||
case 2:
|
||||
self = .admin(id: PeerId(decoder.decodeInt64ForKey("i")), invitedBy: PeerId(decoder.decodeInt64ForKey("b")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .admin(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedBy: PeerId(decoder.decodeInt64ForKey("b", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
default:
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i")), invitedBy: PeerId(decoder.decodeInt64ForKey("b")), invitedAt: decoder.decodeInt32ForKey("t"))
|
||||
self = .member(id: PeerId(decoder.decodeInt64ForKey("i", orElse: 0)), invitedBy: PeerId(decoder.decodeInt64ForKey("b", orElse: 0)), invitedAt: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class CachedGroupParticipants: Coding, Equatable {
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.participants = decoder.decodeObjectArrayWithDecoderForKey("p")
|
||||
self.version = decoder.decodeInt32ForKey("v")
|
||||
self.version = decoder.decodeInt32ForKey("v", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -31,11 +31,11 @@ public final class CachedUserData: CachedPeerData {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.about = decoder.decodeStringForKey("a")
|
||||
self.about = decoder.decodeOptionalStringForKey("a")
|
||||
self.botInfo = decoder.decodeObjectForKey("bi") as? BotInfo
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r"))!
|
||||
self.isBlocked = decoder.decodeInt32ForKey("b") != 0
|
||||
self.commonGroupCount = decoder.decodeInt32ForKey("cg")
|
||||
self.reportStatus = PeerReportStatus(rawValue: decoder.decodeInt32ForKey("r", orElse: 0))!
|
||||
self.isBlocked = decoder.decodeInt32ForKey("b", orElse: 0) != 0
|
||||
self.commonGroupCount = decoder.decodeInt32ForKey("cg", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -13,7 +13,7 @@ final class ChannelState: PeerChatState, Equatable, CustomStringConvertible {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.pts = decoder.decodeInt32ForKey("pts")
|
||||
self.pts = decoder.decodeInt32ForKey("pts", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -16,11 +16,11 @@ public enum ChatContextResultMessage: Coding, Equatable {
|
||||
case contact(media: TelegramMediaContact, replyMarkup: ReplyMarkupMessageAttribute?)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("_v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("_v", orElse: 0) {
|
||||
case 0:
|
||||
self = .auto(caption: decoder.decodeStringForKey("c"), replyMarkup: decoder.decodeObjectForKey("m") as? ReplyMarkupMessageAttribute)
|
||||
self = .auto(caption: decoder.decodeStringForKey("c", orElse: ""), replyMarkup: decoder.decodeObjectForKey("m") as? ReplyMarkupMessageAttribute)
|
||||
case 1:
|
||||
self = .text(text: decoder.decodeStringForKey("t"), entities: decoder.decodeObjectForKey("e") as? TextEntitiesMessageAttribute, disableUrlPreview: decoder.decodeInt32ForKey("du") != 0, replyMarkup: decoder.decodeObjectForKey("m") as? ReplyMarkupMessageAttribute)
|
||||
self = .text(text: decoder.decodeStringForKey("t", orElse: ""), entities: decoder.decodeObjectForKey("e") as? TextEntitiesMessageAttribute, disableUrlPreview: decoder.decodeInt32ForKey("du", orElse: 0) != 0, replyMarkup: decoder.decodeObjectForKey("m") as? ReplyMarkupMessageAttribute)
|
||||
case 2:
|
||||
self = .mapLocation(media: decoder.decodeObjectForKey("l") as! TelegramMediaMap, replyMarkup: decoder.decodeObjectForKey("m") as? ReplyMarkupMessageAttribute)
|
||||
case 3:
|
||||
|
||||
@@ -32,7 +32,7 @@ final class CloudChatRemoveMessagesOperation: Coding {
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.messageIds = MessageId.decodeArrayFromBuffer(decoder.decodeBytesForKeyNoCopy("i")!)
|
||||
self.type = CloudChatRemoveMessagesType(rawValue: decoder.decodeInt32ForKey("t"))!
|
||||
self.type = CloudChatRemoveMessagesType(rawValue: decoder.decodeInt32ForKey("t", orElse: 0))!
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
@@ -55,9 +55,9 @@ final class CloudChatRemoveChatOperation: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p"))
|
||||
self.reportChatSpam = (decoder.decodeInt32ForKey("r") as Int32) != 0
|
||||
if let messageIdPeerId = (decoder.decodeInt64ForKey("m.p") as Int64?), let messageIdNamespace = (decoder.decodeInt32ForKey("m.n") as Int32?), let messageIdId = (decoder.decodeInt32ForKey("m.i") as Int32?) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p", orElse: 0))
|
||||
self.reportChatSpam = decoder.decodeInt32ForKey("r", orElse: 0) != 0
|
||||
if let messageIdPeerId = decoder.decodeOptionalInt64ForKey("m.p"), let messageIdNamespace = decoder.decodeOptionalInt32ForKey("m.n"), let messageIdId = decoder.decodeOptionalInt32ForKey("m.i") {
|
||||
self.topMessageId = MessageId(peerId: PeerId(messageIdPeerId), namespace: messageIdNamespace, id: messageIdId)
|
||||
} else {
|
||||
self.topMessageId = nil
|
||||
@@ -89,8 +89,8 @@ final class CloudChatClearHistoryOperation: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p"))
|
||||
self.topMessageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p")), namespace: decoder.decodeInt32ForKey("m.n"), id: decoder.decodeInt32ForKey("m.i"))
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p", orElse: 0))
|
||||
self.topMessageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("m.n", orElse: 0), id: decoder.decodeInt32ForKey("m.i", orElse: 0))
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -64,11 +64,11 @@ public class CloudFileMediaResource: TelegramCloudMediaResource {
|
||||
}
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d") as Int32)
|
||||
self.volumeId = decoder.decodeInt64ForKey("v")
|
||||
self.localId = decoder.decodeInt32ForKey("l")
|
||||
self.secret = decoder.decodeInt64ForKey("s")
|
||||
if let size = decoder.decodeInt32ForKey("n") as Int32? {
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
self.volumeId = decoder.decodeInt64ForKey("v", orElse: 0)
|
||||
self.localId = decoder.decodeInt32ForKey("l", orElse: 0)
|
||||
self.secret = decoder.decodeInt64ForKey("s", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
@@ -146,10 +146,10 @@ public class CloudDocumentMediaResource: TelegramCloudMediaResource {
|
||||
}
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d") as Int32)
|
||||
self.fileId = decoder.decodeInt64ForKey("f")
|
||||
self.accessHash = decoder.decodeInt64ForKey("a")
|
||||
if let size = (decoder.decodeInt32ForKey("n") as Int32?) {
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
self.fileId = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("n") {
|
||||
self.size = Int(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
@@ -204,7 +204,7 @@ public class LocalFileMediaResource: TelegramMediaResource {
|
||||
}
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.fileId = decoder.decodeInt64ForKey("f")
|
||||
self.fileId = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -258,10 +258,10 @@ public class LocalFileReferenceMediaResource: TelegramMediaResource {
|
||||
}
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.localFilePath = decoder.decodeStringForKey("p")
|
||||
self.randomId = decoder.decodeInt64ForKey("r")
|
||||
self.isUniquelyReferencedTemporaryFile = (decoder.decodeInt32ForKey("t") as Int32) != 0
|
||||
self.size = decoder.decodeInt32ForKey("s")
|
||||
self.localFilePath = decoder.decodeStringForKey("p", orElse: "")
|
||||
self.randomId = decoder.decodeInt64ForKey("r", orElse: 0)
|
||||
self.isUniquelyReferencedTemporaryFile = decoder.decodeInt32ForKey("t", orElse: 0) != 0
|
||||
self.size = decoder.decodeOptionalInt32ForKey("s")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -318,8 +318,8 @@ public final class HttpReferenceMediaResource: TelegramMediaResource {
|
||||
}
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.url = decoder.decodeStringForKey("u")
|
||||
if let size = (decoder.decodeInt32ForKey("s") as Int32?) {
|
||||
self.url = decoder.decodeStringForKey("u", orElse: "")
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
@@ -396,15 +396,15 @@ public struct SecretFileMediaResource: TelegramCloudMediaResource {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.fileId = decoder.decodeInt64ForKey("i")
|
||||
self.accessHash = decoder.decodeInt64ForKey("a")
|
||||
if let size = decoder.decodeInt32ForKey("s") as Int32? {
|
||||
self.fileId = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
}
|
||||
self.decryptedSize = decoder.decodeInt32ForKey("ds")
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d"))
|
||||
self.decryptedSize = decoder.decodeInt32ForKey("ds", orElse: 0)
|
||||
self.datacenterId = Int(decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
self.key = decoder.decodeObjectForKey("k", decoder: { SecretFileEncryptionKey(decoder: $0) }) as! SecretFileEncryptionKey
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ public class ConsumableContentMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.consumed = (decoder.decodeInt32ForKey("c") as Int32) != 0
|
||||
self.consumed = decoder.decodeInt32ForKey("c", orElse: 0) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -13,7 +13,7 @@ public class EditedMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.date = decoder.decodeInt32ForKey("d")
|
||||
self.date = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -211,7 +211,9 @@ func enqueueMessages(modifier: Modifier, account: Account, peerId: PeerId, messa
|
||||
authorId = account.peerId
|
||||
}
|
||||
|
||||
storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, timestamp: timestamp, flags: flags, tags: tagsForStoreMessage(media: mediaList, textEntities: entitiesAttribute?.entities), globalTags: globalTagsForStoreMessage(media: mediaList), forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList))
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: false, media: mediaList, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList))
|
||||
case let .forward(source):
|
||||
if let sourceMessage = modifier.getMessage(source), let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] {
|
||||
if let peer = peer as? TelegramSecretChat {
|
||||
@@ -255,7 +257,9 @@ func enqueueMessages(modifier: Modifier, account: Account, peerId: PeerId, messa
|
||||
}
|
||||
}
|
||||
|
||||
storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, timestamp: timestamp, flags: flags, tags: tagsForStoreMessage(media: sourceMessage.media, textEntities: entitiesAttribute?.entities), globalTags: globalTagsForStoreMessage(media: sourceMessage.media), forwardInfo: forwardInfo, authorId: account.peerId, text: sourceMessage.text, attributes: attributes, media: sourceMessage.media))
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: false, media: sourceMessage.media, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, forwardInfo: forwardInfo, authorId: account.peerId, text: sourceMessage.text, attributes: attributes, media: sourceMessage.media))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public struct ExportedInvitation: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.link = decoder.decodeStringForKey("l")
|
||||
self.link = decoder.decodeStringForKey("l", orElse: "")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -39,7 +39,7 @@ public final class FeaturedStickerPackItem: OrderedItemListEntryContents {
|
||||
public init(decoder: Decoder) {
|
||||
self.info = decoder.decodeObjectForKey("i") as! StickerPackCollectionInfo
|
||||
self.topItems = decoder.decodeObjectArrayForKey("t")
|
||||
self.unread = (decoder.decodeInt32ForKey("u") as Int32) != 0
|
||||
self.unread = decoder.decodeInt32ForKey("u", orElse: 0) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -13,7 +13,7 @@ public class ForwardSourceInfoAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p")), namespace: decoder.decodeInt32ForKey("n"), id: decoder.decodeInt32ForKey("i"))
|
||||
self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), namespace: decoder.decodeInt32ForKey("n", orElse: 0), id: decoder.decodeInt32ForKey("i", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -21,8 +21,8 @@ public struct MessageNotificationSettings: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.enabled = (decoder.decodeInt32ForKey("e") as Int32) != 0
|
||||
self.displayPreviews = (decoder.decodeInt32ForKey("p") as Int32) != 0
|
||||
self.enabled = decoder.decodeInt32ForKey("e", orElse: 0) != 0
|
||||
self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0
|
||||
self.sound = PeerMessageSound.decodeInline(decoder)
|
||||
}
|
||||
|
||||
|
||||
@@ -401,3 +401,81 @@ func fetchChatListHole(network: Network, postbox: Postbox, hole: ChatListHole) -
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fetchCallListHole(network: Network, postbox: Postbox, holeIndex: MessageIndex, limit: Int32 = 100) -> Signal<Void, NoError> {
|
||||
let offset: Signal<(Int32, Int32, Api.InputPeer), NoError>
|
||||
if holeIndex.id.peerId.namespace == Namespaces.Peer.Empty {
|
||||
offset = single((0, 0, Api.InputPeer.inputPeerEmpty), NoError.self)
|
||||
} else {
|
||||
offset = postbox.loadedPeerWithId(holeIndex.id.peerId)
|
||||
|> take(1)
|
||||
|> map { peer in
|
||||
return (holeIndex.timestamp, holeIndex.id.id + 1, apiInputPeer(peer) ?? .inputPeerEmpty)
|
||||
}
|
||||
}
|
||||
return offset
|
||||
|> mapToSignal { (timestamp, id, peer) -> Signal<Void, NoError> in
|
||||
let searchResult = network.request(Api.functions.messages.search(flags: 0, peer: peer, q: "", filter: .inputMessagesFilterPhoneCalls(flags: 0), minDate: 0, maxDate: holeIndex.timestamp, offset: 0, maxId: holeIndex.id.id, limit: limit))
|
||||
|> 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):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
}
|
||||
return postbox.modify { modifier -> Void in
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var topIndex: MessageIndex?
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
storeMessages.append(storeMessage)
|
||||
if let index = storeMessage.index, topIndex == nil || index < topIndex! {
|
||||
topIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var updatedIndex: MessageIndex?
|
||||
if let topIndex = topIndex {
|
||||
updatedIndex = topIndex.predecessor()
|
||||
}
|
||||
|
||||
modifier.replaceGlobalMessageTagsHole(globalTags: [.Calls, .MissedCalls], index: holeIndex, with: updatedIndex, messages: storeMessages)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
modifier.updatePeerPresences(peerPresences)
|
||||
}
|
||||
}
|
||||
return searchResult
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class InlineBotMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("i"))
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public indirect enum InstantPageBlock: Coding, Equatable {
|
||||
case channelBanner(TelegramChannel?)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case InstantPageBlockType.unsupported.rawValue:
|
||||
self = .unsupported
|
||||
case InstantPageBlockType.title.rawValue:
|
||||
@@ -63,7 +63,7 @@ public indirect enum InstantPageBlock: Coding, Equatable {
|
||||
case InstantPageBlockType.subtitle.rawValue:
|
||||
self = .subtitle(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.authorDate.rawValue:
|
||||
self = .authorDate(author: decoder.decodeObjectForKey("a", decoder: { RichText(decoder: $0) }) as! RichText, date: decoder.decodeInt32ForKey("d"))
|
||||
self = .authorDate(author: decoder.decodeObjectForKey("a", decoder: { RichText(decoder: $0) }) as! RichText, date: decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
case InstantPageBlockType.header.rawValue:
|
||||
self = .header(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.subheader.rawValue:
|
||||
@@ -77,29 +77,29 @@ public indirect enum InstantPageBlock: Coding, Equatable {
|
||||
case InstantPageBlockType.divider.rawValue:
|
||||
self = .divider
|
||||
case InstantPageBlockType.anchor.rawValue:
|
||||
self = .anchor(decoder.decodeStringForKey("s"))
|
||||
self = .anchor(decoder.decodeStringForKey("s", orElse: ""))
|
||||
case InstantPageBlockType.list.rawValue:
|
||||
self = .list(items: decoder.decodeObjectArrayWithDecoderForKey("l"), ordered: decoder.decodeInt32ForKey("o") != 0)
|
||||
self = .list(items: decoder.decodeObjectArrayWithDecoderForKey("l"), ordered: decoder.decodeOptionalInt32ForKey("o") != 0)
|
||||
case InstantPageBlockType.blockQuote.rawValue:
|
||||
self = .blockQuote(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.pullQuote.rawValue:
|
||||
self = .pullQuote(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.image.rawValue:
|
||||
self = .image(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n"), id: decoder.decodeInt64ForKey("i.i")), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
self = .image(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0)), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.video.rawValue:
|
||||
self = .video(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n"), id: decoder.decodeInt64ForKey("i.i")), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText, autoplay: decoder.decodeInt32ForKey("ap") != 0, loop: decoder.decodeInt32ForKey("lo") != 0)
|
||||
self = .video(id: MediaId(namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0)), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText, autoplay: decoder.decodeInt32ForKey("ap", orElse: 0) != 0, loop: decoder.decodeInt32ForKey("lo", orElse: 0) != 0)
|
||||
case InstantPageBlockType.cover.rawValue:
|
||||
self = .cover(decoder.decodeObjectForKey("c", decoder: { InstantPageBlock(decoder: $0) }) as! InstantPageBlock)
|
||||
case InstantPageBlockType.webEmbed.rawValue:
|
||||
self = .webEmbed(url: decoder.decodeStringForKey("u"), html: decoder.decodeStringForKey("h"), dimensions: CGSize(width: CGFloat(decoder.decodeInt32ForKey("sw")), height: CGFloat(decoder.decodeInt32ForKey("sh"))), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText, stretchToWidth: decoder.decodeInt32ForKey("st") != 0, allowScrolling: decoder.decodeInt32ForKey("as") != 0)
|
||||
self = .webEmbed(url: decoder.decodeOptionalStringForKey("u"), html: decoder.decodeOptionalStringForKey("h"), dimensions: CGSize(width: CGFloat(decoder.decodeInt32ForKey("sw", orElse: 0)), height: CGFloat(decoder.decodeInt32ForKey("sh", orElse: 0))), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText, stretchToWidth: decoder.decodeInt32ForKey("st", orElse: 0) != 0, allowScrolling: decoder.decodeInt32ForKey("as", orElse: 0) != 0)
|
||||
case InstantPageBlockType.postEmbed.rawValue:
|
||||
var avatarId: MediaId?
|
||||
let avatarIdNamespace: Int32? = decoder.decodeInt32ForKey("av.n")
|
||||
let avatarIdId: Int64? = decoder.decodeInt64ForKey("av.i")
|
||||
let avatarIdNamespace: Int32? = decoder.decodeOptionalInt32ForKey("av.n")
|
||||
let avatarIdId: Int64? = decoder.decodeOptionalInt64ForKey("av.i")
|
||||
if let avatarIdNamespace = avatarIdNamespace, let avatarIdId = avatarIdId {
|
||||
avatarId = MediaId(namespace: avatarIdNamespace, id: avatarIdId)
|
||||
}
|
||||
self = .postEmbed(url: decoder.decodeStringForKey("u"), webpageId: MediaId(namespace: decoder.decodeInt32ForKey("w.n"), id: decoder.decodeInt64ForKey("w.i")), avatarId: avatarId, author: decoder.decodeStringForKey("a"), date: decoder.decodeInt32ForKey("d"), blocks: decoder.decodeObjectArrayWithDecoderForKey("b"), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
self = .postEmbed(url: decoder.decodeStringForKey("u", orElse: ""), webpageId: MediaId(namespace: decoder.decodeInt32ForKey("w.n", orElse: 0), id: decoder.decodeInt64ForKey("w.i", orElse: 0)), avatarId: avatarId, author: decoder.decodeStringForKey("a", orElse: ""), date: decoder.decodeInt32ForKey("d", orElse: 0), blocks: decoder.decodeObjectArrayWithDecoderForKey("b"), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.collage.rawValue:
|
||||
self = .collage(items: decoder.decodeObjectArrayWithDecoderForKey("b"), caption: decoder.decodeObjectForKey("c", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case InstantPageBlockType.slideshow.rawValue:
|
||||
@@ -420,7 +420,7 @@ public final class InstantPage: Coding, Equatable {
|
||||
public init(decoder: Decoder) {
|
||||
self.blocks = decoder.decodeObjectArrayWithDecoderForKey("b")
|
||||
self.media = MediaDictionary(decoder: decoder).dict
|
||||
self.isComplete = decoder.decodeInt32ForKey("c") != 0
|
||||
self.isComplete = decoder.decodeInt32ForKey("c", orElse: 0) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
249
TelegramCore/Localization.swift
Normal file
249
TelegramCore/Localization.swift
Normal file
@@ -0,0 +1,249 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
#else
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public enum LocalizationEntry: Equatable {
|
||||
case string(key: String, value: String)
|
||||
case pluralizedString(key: String, zero: String?, one: String?, two: String?, few: String?, many: String?, other: String)
|
||||
|
||||
public static func ==(lhs: LocalizationEntry, rhs: LocalizationEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .string(key, value):
|
||||
if case .string(key, value) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .pluralizedString(lhsKey, lhsZero, lhsOne, lhsTwo, lhsFew, lhsMany, lhsOther):
|
||||
if case let .pluralizedString(rhsKey, rhsZero, rhsOne, rhsTwo, rhsFew, rhsMany, rhsOther) = rhs {
|
||||
if lhsKey != rhsKey {
|
||||
return false
|
||||
}
|
||||
if lhsZero != rhsZero {
|
||||
return false
|
||||
}
|
||||
if lhsOne != lhsOne {
|
||||
return false
|
||||
}
|
||||
if lhsTwo != lhsTwo {
|
||||
return false
|
||||
}
|
||||
if lhsFew != lhsFew {
|
||||
return false
|
||||
}
|
||||
if lhsMany != lhsMany {
|
||||
return false
|
||||
}
|
||||
if lhsOther != lhsOther {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct LocalizationEntryFlags: OptionSet {
|
||||
var rawValue: Int8
|
||||
|
||||
init(rawValue: Int8) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
init() {
|
||||
self.rawValue = 0
|
||||
}
|
||||
|
||||
static let pluralized = LocalizationEntryFlags(rawValue: (1 << 0))
|
||||
static let hasZero = LocalizationEntryFlags(rawValue: (1 << 1))
|
||||
static let hasOne = LocalizationEntryFlags(rawValue: (1 << 2))
|
||||
static let hasTwo = LocalizationEntryFlags(rawValue: (1 << 3))
|
||||
static let hasFew = LocalizationEntryFlags(rawValue: (1 << 4))
|
||||
static let hasMany = LocalizationEntryFlags(rawValue: (1 << 5))
|
||||
}
|
||||
|
||||
private func writeString(_ buffer: WriteBuffer, _ string: String) {
|
||||
if let data = string.data(using: .utf8) {
|
||||
var length: Int32 = Int32(data.count)
|
||||
buffer.write(&length, offset: 0, length: 4)
|
||||
buffer.write(data)
|
||||
} else {
|
||||
var length: Int32 = 0
|
||||
buffer.write(&length, offset: 0, length: 4)
|
||||
}
|
||||
}
|
||||
|
||||
public final class Localization: Coding, Equatable {
|
||||
public let entries: [LocalizationEntry]
|
||||
|
||||
init(entries: [LocalizationEntry]) {
|
||||
self.entries = entries
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
let count = decoder.decodeInt32ForKey("c", orElse: 0)
|
||||
var entries: [LocalizationEntry] = []
|
||||
if let data = decoder.decodeBytesForKey("d") {
|
||||
for _ in 0 ..< count {
|
||||
var flagsValue: Int8 = 0
|
||||
data.read(&flagsValue, offset: 0, length: 1)
|
||||
let flags = LocalizationEntryFlags(rawValue: flagsValue)
|
||||
|
||||
var length: Int32 = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
|
||||
let keyData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let key = String(data: keyData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
|
||||
if flags.contains(.pluralized) {
|
||||
var zero: String?
|
||||
var one: String?
|
||||
var two: String?
|
||||
var few: String?
|
||||
var many: String?
|
||||
var other: String?
|
||||
|
||||
if flags.contains(.hasZero) {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
zero = value
|
||||
}
|
||||
|
||||
if flags.contains(.hasZero) {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
one = value
|
||||
}
|
||||
|
||||
if flags.contains(.hasZero) {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
two = value
|
||||
}
|
||||
|
||||
if flags.contains(.hasZero) {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
few = value
|
||||
}
|
||||
|
||||
if flags.contains(.hasZero) {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
many = value
|
||||
}
|
||||
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
other = value
|
||||
|
||||
if let key = key, let other = other {
|
||||
entries.append(.pluralizedString(key: key, zero: zero, one: one, two: two, few: few, many: many, other: other))
|
||||
}
|
||||
} else {
|
||||
length = 0
|
||||
data.read(&length, offset: 0, length: 4)
|
||||
let valueData = Data(bytes: data.memory.advanced(by: data.offset), count: Int(length))
|
||||
let value = String(data: valueData, encoding: .utf8)
|
||||
data.skip(Int(length))
|
||||
|
||||
if let key = key, let value = value {
|
||||
entries.append(.string(key: key, value: value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.entries = entries
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
encoder.encodeInt32(Int32(self.entries.count), forKey: "c")
|
||||
|
||||
let buffer = WriteBuffer()
|
||||
for entry in self.entries {
|
||||
var flags: LocalizationEntryFlags = []
|
||||
switch entry {
|
||||
case .string:
|
||||
flags = []
|
||||
case let .pluralizedString(_, zero, one, two, few, many, _):
|
||||
flags.insert(.pluralized)
|
||||
if zero != nil {
|
||||
flags.insert(.hasZero)
|
||||
}
|
||||
if one != nil {
|
||||
flags.insert(.hasOne)
|
||||
}
|
||||
if two != nil {
|
||||
flags.insert(.hasTwo)
|
||||
}
|
||||
if few != nil {
|
||||
flags.insert(.hasFew)
|
||||
}
|
||||
if many != nil {
|
||||
flags.insert(.hasMany)
|
||||
}
|
||||
}
|
||||
var flagsValue: Int8 = flags.rawValue
|
||||
buffer.write(&flagsValue, offset: 0, length: 1)
|
||||
|
||||
switch entry {
|
||||
case let .string(key, value):
|
||||
writeString(buffer, key)
|
||||
writeString(buffer, value)
|
||||
case let .pluralizedString(key, zero, one, two, few, many, other):
|
||||
writeString(buffer, key)
|
||||
if let zero = zero {
|
||||
writeString(buffer, zero)
|
||||
}
|
||||
if let one = one {
|
||||
writeString(buffer, one)
|
||||
}
|
||||
if let two = two {
|
||||
writeString(buffer, two)
|
||||
}
|
||||
if let few = few {
|
||||
writeString(buffer, few)
|
||||
}
|
||||
if let many = many {
|
||||
writeString(buffer, many)
|
||||
}
|
||||
writeString(buffer, other)
|
||||
}
|
||||
}
|
||||
encoder.encodeBytes(buffer, forKey: "d")
|
||||
}
|
||||
|
||||
public static func ==(lhs: Localization, rhs: Localization) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.entries == rhs.entries {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
26
TelegramCore/LocalizationInfo.swift
Normal file
26
TelegramCore/LocalizationInfo.swift
Normal file
@@ -0,0 +1,26 @@
|
||||
import Foundation
|
||||
|
||||
public final class LocalizationInfo {
|
||||
public let languageCode: String
|
||||
public let title: String
|
||||
public let localizedTitle: String
|
||||
|
||||
init(languageCode: String, title: String, localizedTitle: String) {
|
||||
self.languageCode = languageCode
|
||||
self.title = title
|
||||
self.localizedTitle = localizedTitle
|
||||
}
|
||||
}
|
||||
|
||||
public final class SuggestedLocalizationInfo {
|
||||
public let languageCode: String
|
||||
public let extractedEntries: [LocalizationEntry]
|
||||
|
||||
public let availableLocalizations: [LocalizationInfo]
|
||||
|
||||
init(languageCode: String, extractedEntries: [LocalizationEntry], availableLocalizations: [LocalizationInfo]) {
|
||||
self.languageCode = languageCode
|
||||
self.extractedEntries = extractedEntries
|
||||
self.availableLocalizations = availableLocalizations
|
||||
}
|
||||
}
|
||||
40
TelegramCore/LocalizationSettings.swift
Normal file
40
TelegramCore/LocalizationSettings.swift
Normal file
@@ -0,0 +1,40 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public final class LocalizationSettings: PreferencesEntry, Equatable {
|
||||
public let languageCode: String
|
||||
public let localization: Localization
|
||||
|
||||
init(languageCode: String, localization: Localization) {
|
||||
self.languageCode = languageCode
|
||||
self.localization = localization
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "en")
|
||||
self.localization = decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
encoder.encodeString(self.languageCode, forKey: "lc")
|
||||
encoder.encodeObject(self.localization, forKey: "loc")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
if let to = to as? LocalizationSettings {
|
||||
return self == to
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: LocalizationSettings, rhs: LocalizationSettings) -> Bool {
|
||||
return lhs.languageCode == rhs.languageCode && lhs.localization == rhs.localization
|
||||
}
|
||||
}
|
||||
83
TelegramCore/Localizations.swift
Normal file
83
TelegramCore/Localizations.swift
Normal file
@@ -0,0 +1,83 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public func suggestedLocalizationInfo(network: Network, languageCode: String, extractKeys: [String]) -> Signal<SuggestedLocalizationInfo, NoError> {
|
||||
return combineLatest(network.request(Api.functions.langpack.getLanguages()), network.request(Api.functions.langpack.getStrings(langCode: languageCode, keys: extractKeys)))
|
||||
|> retryRequest
|
||||
|> map { languages, strings -> SuggestedLocalizationInfo in
|
||||
var entries: [LocalizationEntry] = []
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
entries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
entries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
}
|
||||
}
|
||||
var infos: [LocalizationInfo] = []
|
||||
for language in languages {
|
||||
switch language {
|
||||
case let .langPackLanguage(name, nativeName, langCode):
|
||||
infos.append(LocalizationInfo(languageCode: langCode, title: name, localizedTitle: nativeName))
|
||||
}
|
||||
}
|
||||
return SuggestedLocalizationInfo(languageCode: languageCode, extractedEntries: entries, availableLocalizations: infos)
|
||||
}
|
||||
}
|
||||
|
||||
public func availableLocalizations(network: Network) -> Signal<[LocalizationInfo], NoError> {
|
||||
return network.request(Api.functions.langpack.getLanguages())
|
||||
|> retryRequest
|
||||
|> map { languages -> [LocalizationInfo] in
|
||||
var infos: [LocalizationInfo] = []
|
||||
for language in languages {
|
||||
switch language {
|
||||
case let .langPackLanguage(name, nativeName, langCode):
|
||||
infos.append(LocalizationInfo(languageCode: langCode, title: name, localizedTitle: nativeName))
|
||||
}
|
||||
}
|
||||
return infos
|
||||
}
|
||||
}
|
||||
|
||||
public func downloadLocalization(network: Network, languageCode: String) -> Signal<Localization, NoError> {
|
||||
return network.request(Api.functions.langpack.getLangPack(langCode: languageCode))
|
||||
|> retryRequest
|
||||
|> map { result -> Localization in
|
||||
var entries: [LocalizationEntry] = []
|
||||
switch result {
|
||||
case let .langPackDifference(_, _, _, strings):
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
entries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
entries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Localization(entries: entries)
|
||||
}
|
||||
}
|
||||
|
||||
public func downoadAndApplyLocalization(postbox: Postbox, network: Network, languageCode: String) -> Signal<Void, NoError> {
|
||||
return downloadLocalization(network: network, languageCode: languageCode)
|
||||
|> mapToSignal { language -> Signal<Void, NoError> in
|
||||
return postbox.modify { modifier -> Void in
|
||||
modifier.updatePreferencesEntry(key: PreferencesKeys.localizationSettings, { _ in
|
||||
return LocalizationSettings(languageCode: languageCode, localization: language)
|
||||
})
|
||||
|
||||
network.context.updateApiEnvironment { current in
|
||||
return current?.withUpdatedLangPackCode(languageCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ import Foundation
|
||||
import TelegramCorePrivateModule
|
||||
#if os(macOS)
|
||||
import SwiftSignalKitMac
|
||||
import PostboxMac
|
||||
#else
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
private let queue = DispatchQueue(label: "org.telegram.Telegram.trace", qos: .utility)
|
||||
@@ -59,13 +61,13 @@ public func registerLoggingFunctions() {
|
||||
private var sharedLogger: Logger?
|
||||
|
||||
public final class Logger {
|
||||
private let queue = DispatchQueue(label: "org.telegram.Telegram.log", qos: .utility)
|
||||
private let queue = Queue(name: "org.telegram.Telegram.log", qos: .utility)
|
||||
private let maxLength: Int = 2 * 1024 * 1024
|
||||
//private let maxLength: Int = 4 * 1024
|
||||
private let maxFiles: Int = 20
|
||||
|
||||
private let basePath: String
|
||||
private var file: (Int32, Int)?
|
||||
private var file: (ManagedFile, Int)?
|
||||
|
||||
public var logToFile: Bool = true
|
||||
public var logToConsole: Bool = true
|
||||
@@ -133,14 +135,14 @@ public final class Logger {
|
||||
content = String(format: "[%@] %d-%d-%d %02d:%02d:%02d.%03d %@", arguments: [tag, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_mday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(timeinfo.tm_sec), Int(milliseconds), string])
|
||||
}
|
||||
|
||||
var fd: Int32?
|
||||
var currentFile: ManagedFile?
|
||||
var openNew = false
|
||||
if let (file, length) = self.file {
|
||||
if length >= self.maxLength {
|
||||
close(file)
|
||||
self.file = nil
|
||||
openNew = true
|
||||
} else {
|
||||
fd = file
|
||||
currentFile = file
|
||||
}
|
||||
} else {
|
||||
openNew = true
|
||||
@@ -172,10 +174,9 @@ public final class Logger {
|
||||
if let (_, url) = maxCreationDate {
|
||||
var value = stat()
|
||||
if stat(url.path, &value) == 0 && Int(value.st_size) < self.maxLength {
|
||||
let handle = open(url.path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
||||
if handle >= 0 {
|
||||
fd = handle
|
||||
self.file = (handle, Int(value.st_size))
|
||||
if let file = ManagedFile(queue: self.queue, path: url.path, mode: .append) {
|
||||
self.file = (file, Int(value.st_size))
|
||||
currentFile = file
|
||||
}
|
||||
} else {
|
||||
createNew = true
|
||||
@@ -190,23 +191,22 @@ public final class Logger {
|
||||
|
||||
let path = self.basePath + "/" + fileName
|
||||
|
||||
let handle = open(path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
||||
if handle >= 0 {
|
||||
fd = handle
|
||||
self.file = (handle, 0)
|
||||
if let file = ManagedFile(queue: self.queue, path: path, mode: .append) {
|
||||
self.file = (file, 0)
|
||||
currentFile = file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let fd = fd {
|
||||
if let currentFile = currentFile {
|
||||
if let data = content.data(using: .utf8) {
|
||||
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
|
||||
write(fd, bytes, data.count)
|
||||
currentFile.write(bytes, count: data.count)
|
||||
}
|
||||
var newline: UInt8 = 0x0a
|
||||
write(fd, &newline, 1)
|
||||
currentFile.write(&newline, count: 1)
|
||||
if let file = self.file {
|
||||
self.file = (file.0, file.1 + data.count)
|
||||
self.file = (file.0, file.1 + data.count + 1)
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ func managedAutoremoveMessageOperations(postbox: Postbox) -> Signal<Void, NoErro
|
||||
})
|
||||
|
||||
return ActionDisposable {
|
||||
disposable.dispose()
|
||||
let disposables = helper.with { helper -> [Disposable] in
|
||||
return helper.reset()
|
||||
}
|
||||
|
||||
@@ -11,29 +11,46 @@ import Foundation
|
||||
|
||||
func managedConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let poll = Signal<Void, NoError> { subscriber in
|
||||
return network.request(Api.functions.help.getConfig()).start(next: { result in
|
||||
switch result {
|
||||
case let .config(_, _, _, _, _, dcOptions, chatSizeMax, megagroupSizeMax, forwardedCountMax, onlineUpdatePeriodMs, offlineBlurTimeoutMs, offlineIdleTimeoutMs, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, tmpSessions, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, disabledFeatures):
|
||||
var addressList: [Int: [MTDatacenterAddress]] = [:]
|
||||
for option in dcOptions {
|
||||
switch option {
|
||||
case let .dcOption(flags, id, ipAddress, port):
|
||||
let preferForMedia = (flags & (1 << 1)) != 0
|
||||
if addressList[Int(id)] == nil {
|
||||
addressList[Int(id)] = []
|
||||
return (network.request(Api.functions.help.getConfig()) |> retryRequest |> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return postbox.modify { modifier -> Void in
|
||||
switch result {
|
||||
case let .config(_, _, _, _, _, dcOptions, chatSizeMax, megagroupSizeMax, forwardedCountMax, onlineUpdatePeriodMs, offlineBlurTimeoutMs, offlineIdleTimeoutMs, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, tmpSessions, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, suggestedLangCode, disabledFeatures):
|
||||
var addressList: [Int: [MTDatacenterAddress]] = [:]
|
||||
for option in dcOptions {
|
||||
switch option {
|
||||
case let .dcOption(flags, id, ipAddress, port):
|
||||
let preferForMedia = (flags & (1 << 1)) != 0
|
||||
if addressList[Int(id)] == nil {
|
||||
addressList[Int(id)] = []
|
||||
}
|
||||
let restrictToTcp = (flags & (1 << 2)) != 0
|
||||
let isCdn = (flags & (1 << 3)) != 0
|
||||
addressList[Int(id)]!.append(MTDatacenterAddress(ip: ipAddress, port: UInt16(port), preferForMedia: preferForMedia, restrictToTcp: restrictToTcp, cdn: isCdn))
|
||||
}
|
||||
}
|
||||
network.context.performBatchUpdates {
|
||||
for (id, list) in addressList {
|
||||
network.context.updateAddressSetForDatacenter(withId: id, addressSet: MTDatacenterAddressSet(addressList: list))
|
||||
}
|
||||
}
|
||||
|
||||
modifier.updatePreferencesEntry(key: PreferencesKeys.suggestedLocalization, { entry in
|
||||
var currentLanguageCode: String?
|
||||
if let entry = entry as? SuggestedLocalizationEntry {
|
||||
currentLanguageCode = entry.languageCode
|
||||
}
|
||||
if currentLanguageCode != suggestedLangCode {
|
||||
if let suggestedLangCode = suggestedLangCode {
|
||||
return SuggestedLocalizationEntry(languageCode: suggestedLangCode, isSeen: false)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
let restrictToTcp = (flags & (1 << 2)) != 0
|
||||
let isCdn = (flags & (1 << 3)) != 0
|
||||
addressList[Int(id)]!.append(MTDatacenterAddress(ip: ipAddress, port: UInt16(port), preferForMedia: preferForMedia, restrictToTcp: restrictToTcp, cdn: isCdn))
|
||||
}
|
||||
}
|
||||
network.context.performBatchUpdates {
|
||||
for (id, list) in addressList {
|
||||
network.context.updateAddressSetForDatacenter(withId: id, addressSet: MTDatacenterAddressSet(addressList: list))
|
||||
}
|
||||
}
|
||||
}
|
||||
return entry
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}).start()
|
||||
}
|
||||
|
||||
return (poll |> then(.complete() |> delay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||
|
||||
@@ -29,7 +29,7 @@ public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageI
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
for i in 0 ..< updatedAttributes.count {
|
||||
if let attribute = updatedAttributes[i] as? AutoremoveTimeoutMessageAttribute {
|
||||
if attribute.countdownBeginTime == nil && message.containsSecretMedia {
|
||||
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && message.containsSecretMedia {
|
||||
updatedAttributes[i] = AutoremoveTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: timestamp)
|
||||
updateMessage = true
|
||||
|
||||
@@ -92,7 +92,7 @@ func markMessageContentAsConsumedRemotely(modifier: Modifier, messageId: Message
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
for i in 0 ..< updatedAttributes.count {
|
||||
if let attribute = updatedAttributes[i] as? AutoremoveTimeoutMessageAttribute {
|
||||
if attribute.countdownBeginTime == nil && message.containsSecretMedia {
|
||||
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && message.containsSecretMedia {
|
||||
updatedAttributes[i] = AutoremoveTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: timestamp)
|
||||
updateMessage = true
|
||||
modifier.addTimestampBasedMessageAttribute(tag: 0, timestamp: timestamp + attribute.timeout, messageId: messageId)
|
||||
|
||||
@@ -62,9 +62,17 @@ public extension MessageTags {
|
||||
static let Music = MessageTags(rawValue: 1 << 2)
|
||||
static let WebPage = MessageTags(rawValue: 1 << 3)
|
||||
static let VoiceOrInstantVideo = MessageTags(rawValue: 1 << 4)
|
||||
|
||||
static let all: MessageTags = [.PhotoOrVideo, .File, .Music, .WebPage, .VoiceOrInstantVideo]
|
||||
}
|
||||
|
||||
public extension GlobalMessageTags {
|
||||
static let Calls = GlobalMessageTags(rawValue: 1 << 0)
|
||||
static let MissedCalls = GlobalMessageTags(rawValue: 1 << 1)
|
||||
|
||||
static let all: GlobalMessageTags = [.Calls, .MissedCalls]
|
||||
}
|
||||
|
||||
let allMessageTags: MessageTags = [.PhotoOrVideo, .File, .Music, .WebPage, .VoiceOrInstantVideo]
|
||||
let peerIdNamespacesWithInitialCloudMessageHoles = [Namespaces.Peer.CloudUser, Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel]
|
||||
|
||||
struct OperationLogTags {
|
||||
@@ -86,6 +94,8 @@ struct OperationLogTags {
|
||||
private enum PreferencesKeyValues: Int32 {
|
||||
case globalNotifications = 0
|
||||
case cacheStorageSettings = 1
|
||||
case localizationSettings = 2
|
||||
case suggestedLocalization = 3
|
||||
}
|
||||
|
||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||
@@ -106,4 +116,16 @@ public struct PreferencesKeys {
|
||||
key.setInt32(0, value: PreferencesKeyValues.cacheStorageSettings.rawValue)
|
||||
return key
|
||||
}()
|
||||
|
||||
public static let localizationSettings: ValueBoxKey = {
|
||||
let key = ValueBoxKey(length: 4)
|
||||
key.setInt32(0, value: PreferencesKeyValues.localizationSettings.rawValue)
|
||||
return key
|
||||
}()
|
||||
|
||||
public static let suggestedLocalization: ValueBoxKey = {
|
||||
let key = ValueBoxKey(length: 4)
|
||||
key.setInt32(0, value: PreferencesKeyValues.suggestedLocalization.rawValue)
|
||||
return key
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -293,18 +293,19 @@ func networkUsageStats(basePath: String, reset: ResetNetworkUsageStats) -> Signa
|
||||
}) |> then(Signal<NetworkUsageStats, NoError>.complete() |> delay(5.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||
}
|
||||
|
||||
func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool) -> Signal<Network, NoError> {
|
||||
func initializedNetwork(apiId: Int32, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?) -> Signal<Network, NoError> {
|
||||
return Signal { subscriber in
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
let _ = registeredLoggingFunctions
|
||||
|
||||
let serialization = Serialization()
|
||||
|
||||
let apiEnvironment = MTApiEnvironment()
|
||||
var apiEnvironment = MTApiEnvironment()
|
||||
|
||||
apiEnvironment.apiId = apiId
|
||||
apiEnvironment.layer = NSNumber(value: Int(serialization.currentLayer()))
|
||||
apiEnvironment.disableUpdates = supplementary
|
||||
apiEnvironment = apiEnvironment.withUpdatedLangPackCode(languageCode ?? "en")
|
||||
|
||||
let context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment)!
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ public class OutgoingChatContextResultMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.queryId = decoder.decodeInt64ForKey("q")
|
||||
self.id = decoder.decodeStringForKey("i")
|
||||
self.queryId = decoder.decodeInt64ForKey("q", orElse: 0)
|
||||
self.id = decoder.decodeStringForKey("i", orElse: "")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class OutgoingContentInfoMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.flags = OutgoingContentInfoFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.flags = OutgoingContentInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -29,8 +29,8 @@ public class OutgoingMessageInfoAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.uniqueId = decoder.decodeInt64ForKey("u")
|
||||
self.flags = OutgoingMessageInfoFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.uniqueId = decoder.decodeInt64ForKey("u", orElse: 0)
|
||||
self.flags = OutgoingMessageInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -13,7 +13,7 @@ public final class PeerAccessRestrictionInfo: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.reason = decoder.decodeStringForKey("rsn")
|
||||
self.reason = decoder.decodeStringForKey("rsn", orElse: "")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -531,8 +531,10 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: true, media: parsedMedia, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: tagsForStoreMessage(media: parsedMedia, textEntities: entitiesAttribute?.entities), globalTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||
case let .decryptedMessageService(randomId, action):
|
||||
switch action {
|
||||
case let .decryptedMessageActionDeleteMessages(randomIds):
|
||||
|
||||
@@ -16,11 +16,11 @@ public enum ReplyMarkupButtonAction: Coding, Equatable {
|
||||
case payment
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case 0:
|
||||
self = .text
|
||||
case 1:
|
||||
self = .url(decoder.decodeStringForKey("u"))
|
||||
self = .url(decoder.decodeStringForKey("u", orElse: ""))
|
||||
case 2:
|
||||
self = .callback(decoder.decodeBytesForKey("d") ?? MemoryBuffer())
|
||||
case 3:
|
||||
@@ -28,7 +28,7 @@ public enum ReplyMarkupButtonAction: Coding, Equatable {
|
||||
case 4:
|
||||
self = .requestMap
|
||||
case 5:
|
||||
self = .switchInline(samePeer: decoder.decodeInt32ForKey("s") != 0, query: decoder.decodeStringForKey("q"))
|
||||
self = .switchInline(samePeer: decoder.decodeInt32ForKey("s", orElse: 0) != 0, query: decoder.decodeStringForKey("q", orElse: ""))
|
||||
case 6:
|
||||
self = .openWebApp
|
||||
case 7:
|
||||
@@ -127,7 +127,7 @@ public struct ReplyMarkupButton: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.title = decoder.decodeStringForKey(".t")
|
||||
self.title = decoder.decodeStringForKey(".t", orElse: "")
|
||||
self.action = ReplyMarkupButtonAction(decoder: decoder)
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public class ReplyMarkupMessageAttribute: MessageAttribute, Equatable {
|
||||
|
||||
public required init(decoder: Decoder) {
|
||||
self.rows = decoder.decodeObjectArrayWithDecoderForKey("r")
|
||||
self.flags = ReplyMarkupMessageFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.flags = ReplyMarkupMessageFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -17,8 +17,8 @@ public class ReplyMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
let namespaceAndId: Int64 = decoder.decodeInt64ForKey("i")
|
||||
self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p")), namespace: Int32(namespaceAndId & 0xffffffff), id: Int32((namespaceAndId >> 32) & 0xffffffff))
|
||||
let namespaceAndId: Int64 = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), namespace: Int32(namespaceAndId & 0xffffffff), id: Int32((namespaceAndId >> 32) & 0xffffffff))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -30,12 +30,12 @@ final class CachedResolvedByNamePeer: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
if let peerId = (decoder.decodeInt64ForKey("p") as Int64?) {
|
||||
if let peerId = decoder.decodeOptionalInt64ForKey("p") {
|
||||
self.peerId = PeerId(peerId)
|
||||
} else {
|
||||
self.peerId = nil
|
||||
}
|
||||
self.timestamp = decoder.decodeInt32ForKey("t")
|
||||
self.timestamp = decoder.decodeInt32ForKey("t", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -31,11 +31,11 @@ public indirect enum RichText: Coding, Equatable {
|
||||
case concat([RichText])
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case RichTextTypes.empty.rawValue:
|
||||
self = .empty
|
||||
case RichTextTypes.plain.rawValue:
|
||||
self = .plain(decoder.decodeStringForKey("s"))
|
||||
self = .plain(decoder.decodeStringForKey("s", orElse: ""))
|
||||
case RichTextTypes.bold.rawValue:
|
||||
self = .bold(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case RichTextTypes.italic.rawValue:
|
||||
@@ -47,15 +47,15 @@ public indirect enum RichText: Coding, Equatable {
|
||||
case RichTextTypes.fixed.rawValue:
|
||||
self = .fixed(decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText)
|
||||
case RichTextTypes.url.rawValue:
|
||||
let webpageIdNamespace: Int32? = decoder.decodeInt32ForKey("w.n")
|
||||
let webpageIdId: Int64? = decoder.decodeInt64ForKey("w.i")
|
||||
let webpageIdNamespace: Int32? = decoder.decodeOptionalInt32ForKey("w.n")
|
||||
let webpageIdId: Int64? = decoder.decodeOptionalInt64ForKey("w.i")
|
||||
var webpageId: MediaId?
|
||||
if let webpageIdNamespace = webpageIdNamespace, let webpageIdId = webpageIdId {
|
||||
webpageId = MediaId(namespace: webpageIdNamespace, id: webpageIdId)
|
||||
}
|
||||
self = .url(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, url: decoder.decodeStringForKey("u"), webpageId: webpageId)
|
||||
self = .url(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, url: decoder.decodeStringForKey("u", orElse: ""), webpageId: webpageId)
|
||||
case RichTextTypes.email.rawValue:
|
||||
self = .email(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, email: decoder.decodeStringForKey("e"))
|
||||
self = .email(text: decoder.decodeObjectForKey("t", decoder: { RichText(decoder: $0) }) as! RichText, email: decoder.decodeStringForKey("e", orElse: ""))
|
||||
case RichTextTypes.concat.rawValue:
|
||||
self = .concat(decoder.decodeObjectArrayWithDecoderForKey("a"))
|
||||
default:
|
||||
|
||||
@@ -21,9 +21,9 @@ final class SecretChatEncryptionConfig: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.g = decoder.decodeInt32ForKey("g")
|
||||
self.g = decoder.decodeInt32ForKey("g", orElse: 0)
|
||||
self.p = decoder.decodeBytesForKey("p")!
|
||||
self.version = decoder.decodeInt32ForKey("v")
|
||||
self.version = decoder.decodeInt32ForKey("v", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -21,11 +21,11 @@ final class SecretChatFileReference: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.id = decoder.decodeInt64ForKey("i")
|
||||
self.accessHash = decoder.decodeInt64ForKey("a")
|
||||
self.size = decoder.decodeInt32ForKey("s")
|
||||
self.datacenterId = decoder.decodeInt32ForKey("d")
|
||||
self.keyFingerprint = decoder.decodeInt32ForKey("f")
|
||||
self.id = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
self.datacenterId = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
self.keyFingerprint = decoder.decodeInt32ForKey("f", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -15,8 +15,8 @@ struct SecretChatOperationSequenceInfo: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.topReceivedOperationIndex = decoder.decodeInt32ForKey("r")
|
||||
self.operationIndex = decoder.decodeInt32ForKey("o")
|
||||
self.topReceivedOperationIndex = decoder.decodeInt32ForKey("r", orElse: 0)
|
||||
self.operationIndex = decoder.decodeInt32ForKey("o", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
@@ -41,8 +41,8 @@ final class SecretChatIncomingDecryptedOperation: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.timestamp = decoder.decodeInt32ForKey("t")
|
||||
self.layer = decoder.decodeInt32ForKey("l")
|
||||
self.timestamp = decoder.decodeInt32ForKey("t", orElse: 0)
|
||||
self.layer = decoder.decodeInt32ForKey("l", orElse: 0)
|
||||
self.sequenceInfo = decoder.decodeObjectForKey("s", decoder: { SecretChatOperationSequenceInfo(decoder: $0) }) as? SecretChatOperationSequenceInfo
|
||||
self.contents = decoder.decodeBytesForKey("c")!
|
||||
self.file = decoder.decodeObjectForKey("f", decoder: { SecretChatFileReference(decoder: $0) }) as? SecretChatFileReference
|
||||
|
||||
@@ -47,11 +47,11 @@ final class SecretChatIncomingEncryptedOperation: Coding {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p"))
|
||||
self.globallyUniqueId = decoder.decodeInt64ForKey("u")
|
||||
self.timestamp = decoder.decodeInt32ForKey("t")
|
||||
self.type = SecretChatIncomingEncryptedOperationType(decoder.decodeInt32ForKey("k"))
|
||||
self.keyFingerprint = decoder.decodeInt64ForKey("f")
|
||||
self.peerId = PeerId(decoder.decodeInt64ForKey("p", orElse: 0))
|
||||
self.globallyUniqueId = decoder.decodeInt64ForKey("u", orElse: 0)
|
||||
self.timestamp = decoder.decodeInt32ForKey("t", orElse: 0)
|
||||
self.type = SecretChatIncomingEncryptedOperationType(decoder.decodeInt32ForKey("k", orElse: 0))
|
||||
self.keyFingerprint = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
self.contents = decoder.decodeBytesForKey("c")!
|
||||
self.mediaFileReference = decoder.decodeObjectForKey("m", decoder: { SecretChatFileReference(decoder: $0) }) as? SecretChatFileReference
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ enum SecretChatKeyValidity: Coding, Equatable {
|
||||
case sequenceBasedIndexRange(fromCanonicalIndex: Int32)
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case 0:
|
||||
self = .indefinite
|
||||
case 1:
|
||||
self = .sequenceBasedIndexRange(fromCanonicalIndex: decoder.decodeInt32ForKey("l"))
|
||||
self = .sequenceBasedIndexRange(fromCanonicalIndex: decoder.decodeInt32ForKey("l", orElse: 0))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .sequenceBasedIndexRange(fromCanonicalIndex: Int32.max)
|
||||
@@ -63,10 +63,10 @@ final class SecretChatKey: Coding, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.fingerprint = decoder.decodeInt64ForKey("f")
|
||||
self.fingerprint = decoder.decodeInt64ForKey("f", orElse: 0)
|
||||
self.key = decoder.decodeBytesForKey("k")!
|
||||
self.validity = decoder.decodeObjectForKey("v", decoder: { SecretChatKeyValidity(decoder: $0) }) as! SecretChatKeyValidity
|
||||
self.useCount = decoder.decodeInt32ForKey("u")
|
||||
self.useCount = decoder.decodeInt32ForKey("u", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -17,13 +17,13 @@ enum SecretChatOutgoingFileReference: Coding {
|
||||
case uploadedLarge(id: Int64, partCount: Int32, keyFingerprint: Int32)
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case SecretChatOutgoingFileValue.remote.rawValue:
|
||||
self = .remote(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("a"))
|
||||
self = .remote(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("a", orElse: 0))
|
||||
case SecretChatOutgoingFileValue.uploadedRegular.rawValue:
|
||||
self = .uploadedRegular(id: decoder.decodeInt64ForKey("i"), partCount: decoder.decodeInt32ForKey("p"), md5Digest: decoder.decodeStringForKey("d"), keyFingerprint: decoder.decodeInt32ForKey("f"))
|
||||
self = .uploadedRegular(id: decoder.decodeInt64ForKey("i", orElse: 0), partCount: decoder.decodeInt32ForKey("p", orElse: 0), md5Digest: decoder.decodeStringForKey("d", orElse: ""), keyFingerprint: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
case SecretChatOutgoingFileValue.uploadedLarge.rawValue:
|
||||
self = .uploadedLarge(id: decoder.decodeInt64ForKey("i"), partCount: decoder.decodeInt32ForKey("p"), keyFingerprint: decoder.decodeInt32ForKey("f"))
|
||||
self = .uploadedLarge(id: decoder.decodeInt64ForKey("i", orElse: 0), partCount: decoder.decodeInt32ForKey("p", orElse: 0), keyFingerprint: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .remote(id: 0, accessHash: 0)
|
||||
@@ -64,7 +64,7 @@ struct SecretChatOutgoingFile: Coding {
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.reference = decoder.decodeObjectForKey("r", decoder: { SecretChatOutgoingFileReference(decoder: $0) }) as! SecretChatOutgoingFileReference
|
||||
self.size = decoder.decodeInt32ForKey("s")
|
||||
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
self.key = SecretFileEncryptionKey(aesKey: decoder.decodeBytesForKey("k")!.makeData(), aesIv: decoder.decodeBytesForKey("i")!.makeData())
|
||||
}
|
||||
|
||||
@@ -116,39 +116,39 @@ enum SecretChatOutgoingOperationContents: Coding {
|
||||
case terminate
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case SecretChatOutgoingOperationValue.initialHandshakeAccept.rawValue:
|
||||
self = .initialHandshakeAccept(gA: decoder.decodeBytesForKey("g")!, accessHash: decoder.decodeInt64ForKey("h"), b: decoder.decodeBytesForKey("b")!)
|
||||
self = .initialHandshakeAccept(gA: decoder.decodeBytesForKey("g")!, accessHash: decoder.decodeInt64ForKey("h", orElse: 0), b: decoder.decodeBytesForKey("b")!)
|
||||
case SecretChatOutgoingOperationValue.sendMessage.rawValue:
|
||||
self = .sendMessage(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, id: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("i.p")), namespace: decoder.decodeInt32ForKey("i.n"), id: decoder.decodeInt32ForKey("i.i")), file: decoder.decodeObjectForKey("f", decoder: { SecretChatOutgoingFile(decoder: $0) }) as? SecretChatOutgoingFile)
|
||||
self = .sendMessage(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, id: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("i.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt32ForKey("i.i", orElse: 0)), file: decoder.decodeObjectForKey("f", decoder: { SecretChatOutgoingFile(decoder: $0) }) as? SecretChatOutgoingFile)
|
||||
case SecretChatOutgoingOperationValue.readMessagesContent.rawValue:
|
||||
self = .readMessagesContent(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
self = .readMessagesContent(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
case SecretChatOutgoingOperationValue.deleteMessages.rawValue:
|
||||
self = .deleteMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
self = .deleteMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
case SecretChatOutgoingOperationValue.screenshotMessages.rawValue:
|
||||
self = .screenshotMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
self = .screenshotMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
||||
case SecretChatOutgoingOperationValue.clearHistory.rawValue:
|
||||
self = .clearHistory(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"))
|
||||
self = .clearHistory(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.resendOperations.rawValue:
|
||||
self = .resendOperations(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), fromSeqNo: decoder.decodeInt32ForKey("f"), toSeqNo: decoder.decodeInt32ForKey("t"))
|
||||
self = .resendOperations(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), fromSeqNo: decoder.decodeInt32ForKey("f", orElse: 0), toSeqNo: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.reportLayerSupport.rawValue:
|
||||
self = .reportLayerSupport(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), layerSupport: decoder.decodeInt32ForKey("l"))
|
||||
self = .reportLayerSupport(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), layerSupport: decoder.decodeInt32ForKey("l", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.pfsRequestKey.rawValue:
|
||||
self = .pfsRequestKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), rekeySessionId: decoder.decodeInt64ForKey("s"), a: decoder.decodeBytesForKey("a")!)
|
||||
self = .pfsRequestKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), a: decoder.decodeBytesForKey("a")!)
|
||||
case SecretChatOutgoingOperationValue.pfsAcceptKey.rawValue:
|
||||
self = .pfsAcceptKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), rekeySessionId: decoder.decodeInt64ForKey("s"), gA: decoder.decodeBytesForKey("g")!, b: decoder.decodeBytesForKey("b")!)
|
||||
self = .pfsAcceptKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), gA: decoder.decodeBytesForKey("g")!, b: decoder.decodeBytesForKey("b")!)
|
||||
case SecretChatOutgoingOperationValue.pfsAbortSession.rawValue:
|
||||
self = .pfsAbortSession(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), rekeySessionId: decoder.decodeInt64ForKey("s"))
|
||||
self = .pfsAbortSession(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.pfsCommitKey.rawValue:
|
||||
self = .pfsCommitKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), rekeySessionId: decoder.decodeInt64ForKey("s"), keyFingerprint: decoder.decodeInt64ForKey("f"))
|
||||
self = .pfsCommitKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), keyFingerprint: decoder.decodeInt64ForKey("f", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.noop.rawValue:
|
||||
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"))
|
||||
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
case SecretChatOutgoingOperationValue.setMessageAutoremoveTimeout.rawValue:
|
||||
self = .setMessageAutoremoveTimeout(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i"), timeout: decoder.decodeInt32ForKey("t"), messageId: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p")), namespace: decoder.decodeInt32ForKey("m.n"), id: decoder.decodeInt32ForKey("m.i")))
|
||||
self = .setMessageAutoremoveTimeout(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), timeout: decoder.decodeInt32ForKey("t", orElse: 0), messageId: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("m.n", orElse: 0), id: decoder.decodeInt32ForKey("m.i", orElse: 0)))
|
||||
case SecretChatOutgoingOperationValue.terminate.rawValue:
|
||||
self = .terminate
|
||||
default:
|
||||
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l"))!, actionGloballyUniqueId: 0)
|
||||
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: 0)
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
@@ -256,8 +256,8 @@ final class SecretChatOutgoingOperation: Coding {
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.contents = decoder.decodeObjectForKey("c", decoder: { SecretChatOutgoingOperationContents(decoder: $0) }) as! SecretChatOutgoingOperationContents
|
||||
self.mutable = (decoder.decodeInt32ForKey("m") as Int32) != 0
|
||||
self.delivered = (decoder.decodeInt32ForKey("d") as Int32) != 0
|
||||
self.mutable = decoder.decodeInt32ForKey("m", orElse: 0) != 0
|
||||
self.delivered = decoder.decodeInt32ForKey("d", orElse: 0) != 0
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -44,9 +44,9 @@ public struct SecretChatKeySha1Fingerprint: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.k0 = decoder.decodeInt64ForKey("k0")
|
||||
self.k1 = decoder.decodeInt64ForKey("k1")
|
||||
self.k2 = decoder.decodeInt32ForKey("k2")
|
||||
self.k0 = decoder.decodeInt64ForKey("k0", orElse: 0)
|
||||
self.k1 = decoder.decodeInt64ForKey("k1", orElse: 0)
|
||||
self.k2 = decoder.decodeInt32ForKey("k2", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -114,10 +114,10 @@ public struct SecretChatKeySha256Fingerprint: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.k0 = decoder.decodeInt64ForKey("k0")
|
||||
self.k1 = decoder.decodeInt64ForKey("k1")
|
||||
self.k2 = decoder.decodeInt64ForKey("k2")
|
||||
self.k3 = decoder.decodeInt64ForKey("k3")
|
||||
self.k0 = decoder.decodeInt64ForKey("k0", orElse: 0)
|
||||
self.k1 = decoder.decodeInt64ForKey("k1", orElse: 0)
|
||||
self.k2 = decoder.decodeInt64ForKey("k2", orElse: 0)
|
||||
self.k3 = decoder.decodeInt64ForKey("k3", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -198,11 +198,11 @@ enum SecretChatHandshakeState: Coding, Equatable {
|
||||
case requested(g: Int32, p: MemoryBuffer, a: MemoryBuffer)
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case 0:
|
||||
self = .accepting
|
||||
case 1:
|
||||
self = .requested(g: decoder.decodeInt32ForKey("g"), p: decoder.decodeBytesForKey("p")!, a: decoder.decodeBytesForKey("a")!)
|
||||
self = .requested(g: decoder.decodeInt32ForKey("g", orElse: 0), p: decoder.decodeBytesForKey("p")!, a: decoder.decodeBytesForKey("a")!)
|
||||
default:
|
||||
self = .accepting
|
||||
assertionFailure()
|
||||
@@ -251,9 +251,9 @@ struct SecretChatLayerNegotiationState: Coding, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.activeLayer = decoder.decodeInt32ForKey("a")
|
||||
self.locallyRequestedLayer = decoder.decodeInt32ForKey("lr")
|
||||
self.remotelyRequestedLayer = decoder.decodeInt32ForKey("rr")
|
||||
self.activeLayer = decoder.decodeInt32ForKey("a", orElse: 0)
|
||||
self.locallyRequestedLayer = decoder.decodeOptionalInt32ForKey("lr")
|
||||
self.remotelyRequestedLayer = decoder.decodeOptionalInt32ForKey("rr")
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
@@ -302,7 +302,7 @@ enum SecretChatRekeySessionData: Coding, Equatable {
|
||||
case accepted(key: MemoryBuffer, keyFingerprint: Int64)
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case SecretChatRekeySessionDataValue.requesting.rawValue:
|
||||
self = .requesting
|
||||
case SecretChatRekeySessionDataValue.requested.rawValue:
|
||||
@@ -310,7 +310,7 @@ enum SecretChatRekeySessionData: Coding, Equatable {
|
||||
case SecretChatRekeySessionDataValue.accepting.rawValue:
|
||||
self = .accepting
|
||||
case SecretChatRekeySessionDataValue.accepted.rawValue:
|
||||
self = .accepted(key: decoder.decodeBytesForKey("k")!, keyFingerprint: decoder.decodeInt64ForKey("f"))
|
||||
self = .accepted(key: decoder.decodeBytesForKey("k")!, keyFingerprint: decoder.decodeInt64ForKey("f", orElse: 0))
|
||||
default:
|
||||
preconditionFailure()
|
||||
}
|
||||
@@ -373,7 +373,7 @@ struct SecretChatRekeySessionState: Coding, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.id = decoder.decodeInt64ForKey("i")
|
||||
self.id = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.data = decoder.decodeObjectForKey("d", decoder: { SecretChatRekeySessionData(decoder: $0) }) as! SecretChatRekeySessionData
|
||||
}
|
||||
|
||||
@@ -411,9 +411,9 @@ struct SecretChatSequenceBasedLayerState: Coding, Equatable {
|
||||
init(decoder: Decoder) {
|
||||
self.layerNegotiationState = decoder.decodeObjectForKey("ln", decoder: { SecretChatLayerNegotiationState(decoder: $0) }) as! SecretChatLayerNegotiationState
|
||||
self.rekeyState = decoder.decodeObjectForKey("rs", decoder: { SecretChatRekeySessionState(decoder: $0) }) as? SecretChatRekeySessionState
|
||||
self.baseIncomingOperationIndex = decoder.decodeInt32ForKey("bi")
|
||||
self.baseOutgoingOperationIndex = decoder.decodeInt32ForKey("bo")
|
||||
if let topProcessedCanonicalIncomingOperationIndex = decoder.decodeInt32ForKey("pi") as Int32? {
|
||||
self.baseIncomingOperationIndex = decoder.decodeInt32ForKey("bi", orElse: 0)
|
||||
self.baseOutgoingOperationIndex = decoder.decodeInt32ForKey("bo", orElse: 0)
|
||||
if let topProcessedCanonicalIncomingOperationIndex = decoder.decodeOptionalInt32ForKey("pi") {
|
||||
self.topProcessedCanonicalIncomingOperationIndex = topProcessedCanonicalIncomingOperationIndex
|
||||
} else {
|
||||
self.topProcessedCanonicalIncomingOperationIndex = nil
|
||||
@@ -495,7 +495,7 @@ enum SecretChatEmbeddedState: Coding, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case SecretChatEmbeddedStateValue.terminated.rawValue:
|
||||
self = .terminated
|
||||
case SecretChatEmbeddedStateValue.handshake.rawValue:
|
||||
@@ -575,11 +575,11 @@ final class SecretChatState: PeerChatState, SecretChatKeyState, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.role = SecretChatRole(rawValue: decoder.decodeInt32ForKey("r"))!
|
||||
self.role = SecretChatRole(rawValue: decoder.decodeInt32ForKey("r", orElse: 0))!
|
||||
self.embeddedState = decoder.decodeObjectForKey("s", decoder: { return SecretChatEmbeddedState(decoder: $0) }) as! SecretChatEmbeddedState
|
||||
self.keychain = decoder.decodeObjectForKey("k", decoder: { return SecretChatKeychain(decoder: $0) }) as! SecretChatKeychain
|
||||
self.keyFingerprint = decoder.decodeObjectForKey("f", decoder: { return SecretChatKeyFingerprint(decoder: $0) }) as? SecretChatKeyFingerprint
|
||||
self.messageAutoremoveTimeout = decoder.decodeInt32ForKey("a")
|
||||
self.messageAutoremoveTimeout = decoder.decodeOptionalInt32ForKey("a")
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -20,7 +20,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 66
|
||||
return 67
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
@@ -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<DcOption> 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<DisabledFeature> = Config;
|
||||
case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
var addressList = [MTDatacenterAddress]()
|
||||
for option in dcOptions {
|
||||
switch option {
|
||||
|
||||
@@ -55,13 +55,13 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.id = ItemCollectionId(namespace: decoder.decodeInt32ForKey("i.n"), id: decoder.decodeInt64ForKey("i.i"))
|
||||
self.accessHash = decoder.decodeInt64ForKey("a")
|
||||
self.title = decoder.decodeStringForKey("t")
|
||||
self.shortName = decoder.decodeStringForKey("s")
|
||||
self.hash = decoder.decodeInt32ForKey("h")
|
||||
self.flags = StickerPackCollectionInfoFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.count = decoder.decodeInt32ForKey("n")
|
||||
self.id = ItemCollectionId(namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0))
|
||||
self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.shortName = decoder.decodeStringForKey("s", orElse: "")
|
||||
self.hash = decoder.decodeInt32ForKey("h", orElse: 0)
|
||||
self.flags = StickerPackCollectionInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
self.count = decoder.decodeInt32ForKey("n", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -116,7 +116,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.index = ItemCollectionItemIndex(index: decoder.decodeInt32ForKey("i.n"), id: decoder.decodeInt64ForKey("i.i"))
|
||||
self.index = ItemCollectionItemIndex(index: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0))
|
||||
self.file = decoder.decodeObjectForKey("f") as! TelegramMediaFile
|
||||
self.indexKeys = decoder.decodeBytesArrayForKey("s")
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public func tagsForStoreMessage(media: [Media], textEntities: [MessageTextEntity]?) -> MessageTags {
|
||||
public func tagsForStoreMessage(incoming: Bool, media: [Media], textEntities: [MessageTextEntity]?) -> (MessageTags, GlobalMessageTags) {
|
||||
var tags = MessageTags()
|
||||
var globalTags = GlobalMessageTags()
|
||||
for attachment in media {
|
||||
if let _ = attachment as? TelegramMediaImage {
|
||||
tags.insert(.PhotoOrVideo)
|
||||
} else if let file = attachment as? TelegramMediaFile {
|
||||
var refinedTag: MessageTags?
|
||||
var refinedTag: MessageTags? = .File
|
||||
inner: for attribute in file.attributes {
|
||||
switch attribute {
|
||||
case let .Video(_, _, flags):
|
||||
@@ -28,17 +29,28 @@ public func tagsForStoreMessage(media: [Media], textEntities: [MessageTextEntity
|
||||
refinedTag = .Music
|
||||
}
|
||||
break inner
|
||||
case .Sticker:
|
||||
refinedTag = nil
|
||||
break inner
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
if let refinedTag = refinedTag {
|
||||
tags.insert(refinedTag)
|
||||
} else {
|
||||
tags.insert(.File)
|
||||
}
|
||||
} else if let webpage = attachment as? TelegramMediaWebpage, case .Loaded = webpage.content {
|
||||
tags.insert(.WebPage)
|
||||
} else if let action = attachment as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case let .phoneCall(_, discardReason, _):
|
||||
globalTags.insert(.Calls)
|
||||
if incoming, let discardReason = discardReason, case .missed = discardReason {
|
||||
globalTags.insert(.MissedCalls)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if let textEntities = textEntities, !textEntities.isEmpty && !tags.contains(.WebPage) {
|
||||
@@ -51,11 +63,7 @@ public func tagsForStoreMessage(media: [Media], textEntities: [MessageTextEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
public func globalTagsForStoreMessage(media: [Media]) -> GlobalMessageTags {
|
||||
return []
|
||||
return (tags, globalTags)
|
||||
}
|
||||
|
||||
extension Api.Message {
|
||||
@@ -425,7 +433,9 @@ extension StoreMessage {
|
||||
storeFlags.insert(.Personal)
|
||||
}
|
||||
|
||||
self.init(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), globallyUniqueId: nil, timestamp: date, flags: storeFlags, tags: tagsForStoreMessage(media: medias, textEntities: entitiesAttribute?.entities), globalTags: globalTagsForStoreMessage(media: medias), forwardInfo: forwardInfo, authorId: authorId, text: messageText, attributes: attributes, media: medias)
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), media: medias, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
self.init(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), globallyUniqueId: nil, timestamp: date, flags: storeFlags, tags: tags, globalTags: globalTags, forwardInfo: forwardInfo, authorId: authorId, text: messageText, attributes: attributes, media: medias)
|
||||
case .messageEmpty:
|
||||
return nil
|
||||
case let .messageService(flags, id, fromId, toId, replyToMsgId, date, action):
|
||||
@@ -474,7 +484,9 @@ extension StoreMessage {
|
||||
media.append(action)
|
||||
}
|
||||
|
||||
self.init(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), globallyUniqueId: nil, timestamp: date, flags: storeFlags, tags: [], globalTags: globalTagsForStoreMessage(media: media), forwardInfo: nil, authorId: authorId, text: "", attributes: attributes, media: media)
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), media: media, textEntities: nil)
|
||||
|
||||
self.init(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), globallyUniqueId: nil, timestamp: date, flags: storeFlags, tags: tags, globalTags: globalTags, forwardInfo: nil, authorId: authorId, text: "", attributes: attributes, media: media)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
51
TelegramCore/SuggestedLocalizationEntry.swift
Normal file
51
TelegramCore/SuggestedLocalizationEntry.swift
Normal file
@@ -0,0 +1,51 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public final class SuggestedLocalizationEntry: PreferencesEntry {
|
||||
public let languageCode: String
|
||||
public let isSeen: Bool
|
||||
|
||||
init(languageCode: String, isSeen: Bool) {
|
||||
self.languageCode = languageCode
|
||||
self.isSeen = isSeen
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "en")
|
||||
self.isSeen = decoder.decodeInt32ForKey("s", orElse: 0) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
encoder.encodeString(self.languageCode, forKey: "lc")
|
||||
encoder.encodeInt32(self.isSeen ? 1 : 0, forKey: "s")
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
if let to = to as? SuggestedLocalizationEntry {
|
||||
return self == to
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: SuggestedLocalizationEntry, rhs: SuggestedLocalizationEntry) -> Bool {
|
||||
return lhs.languageCode == rhs.languageCode && lhs.isSeen == rhs.isSeen
|
||||
}
|
||||
}
|
||||
|
||||
public func markSuggestedLocalizationAsSeenInteractively(postbox: Postbox, languageCode: String) -> Signal<Void, NoError> {
|
||||
return postbox.modify { modifier -> Void in
|
||||
modifier.updatePreferencesEntry(key: PreferencesKeys.suggestedLocalization, { current in
|
||||
if let current = current as? SuggestedLocalizationEntry, current.languageCode == languageCode, !current.isSeen {
|
||||
return SuggestedLocalizationEntry(languageCode: languageCode, isSeen: true)
|
||||
}
|
||||
return current
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,11 @@ enum SynchronizeSavedGifsOperationContent: Coding {
|
||||
case sync
|
||||
|
||||
init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case SynchronizeSavedGifsOperationContentType.add.rawValue:
|
||||
self = .add(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("h"))
|
||||
self = .add(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0))
|
||||
case SynchronizeSavedGifsOperationContentType.remove.rawValue:
|
||||
self = .remove(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("h"))
|
||||
self = .remove(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0))
|
||||
case SynchronizeSavedGifsOperationContentType.sync.rawValue:
|
||||
self = .sync
|
||||
default:
|
||||
|
||||
@@ -17,9 +17,9 @@ public struct SynchronizeableChatInputState: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.text = decoder.decodeStringForKey("t")
|
||||
self.timestamp = decoder.decodeInt32ForKey("s")
|
||||
if let messageIdPeerId = (decoder.decodeInt64ForKey("m.p") as Int64?), let messageIdNamespace = (decoder.decodeInt32ForKey("m.n") as Int32?), let messageIdId = (decoder.decodeInt32ForKey("m.i") as Int32?) {
|
||||
self.text = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.timestamp = decoder.decodeInt32ForKey("s", orElse: 0)
|
||||
if let messageIdPeerId = decoder.decodeOptionalInt64ForKey("m.p"), let messageIdNamespace = decoder.decodeOptionalInt32ForKey("m.n"), let messageIdId = decoder.decodeOptionalInt32ForKey("m.i") {
|
||||
self.replyToMessageId = MessageId(peerId: PeerId(messageIdPeerId), namespace: messageIdNamespace, id: messageIdId)
|
||||
} else {
|
||||
self.replyToMessageId = nil
|
||||
|
||||
@@ -149,11 +149,11 @@ public enum TelegramChannelInfo: Equatable {
|
||||
}
|
||||
|
||||
fileprivate static func decode(decoder: Decoder) -> TelegramChannelInfo {
|
||||
let type: Int32 = decoder.decodeInt32ForKey("i.t")
|
||||
let type: Int32 = decoder.decodeInt32ForKey("i.t", orElse: 0)
|
||||
if type == 0 {
|
||||
return .broadcast(TelegramChannelBroadcastInfo(flags: TelegramChannelBroadcastFlags(rawValue: decoder.decodeInt32ForKey("i.f"))))
|
||||
return .broadcast(TelegramChannelBroadcastInfo(flags: TelegramChannelBroadcastFlags(rawValue: decoder.decodeInt32ForKey("i.f", orElse: 0))))
|
||||
} else {
|
||||
return .group(TelegramChannelGroupInfo(flags: TelegramChannelGroupFlags(rawValue: decoder.decodeInt32ForKey("i.f"))))
|
||||
return .group(TelegramChannelGroupInfo(flags: TelegramChannelGroupFlags(rawValue: decoder.decodeInt32ForKey("i.f", orElse: 0))))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,17 +209,17 @@ public final class TelegramChannel: Peer {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i"))
|
||||
self.accessHash = decoder.decodeInt64ForKey("ah")
|
||||
self.title = decoder.decodeStringForKey("t")
|
||||
self.username = decoder.decodeStringForKey("un")
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
self.accessHash = decoder.decodeOptionalInt64ForKey("ah")
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.username = decoder.decodeOptionalStringForKey("un")
|
||||
self.photo = decoder.decodeObjectArrayForKey("ph")
|
||||
self.creationDate = decoder.decodeInt32ForKey("d")
|
||||
self.version = decoder.decodeInt32ForKey("v")
|
||||
self.participationStatus = TelegramChannelParticipationStatus(rawValue: decoder.decodeInt32ForKey("ps"))
|
||||
self.role = TelegramChannelRole(rawValue: decoder.decodeInt32ForKey("ro"))
|
||||
self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
self.version = decoder.decodeInt32ForKey("v", orElse: 0)
|
||||
self.participationStatus = TelegramChannelParticipationStatus(rawValue: decoder.decodeInt32ForKey("ps", orElse: 0))
|
||||
self.role = TelegramChannelRole(rawValue: decoder.decodeInt32ForKey("ro", orElse: 0))
|
||||
self.info = TelegramChannelInfo.decode(decoder: decoder)
|
||||
self.flags = TelegramChannelFlags(rawValue: decoder.decodeInt32ForKey("fl"))
|
||||
self.flags = TelegramChannelFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0))
|
||||
self.restrictionInfo = decoder.decodeObjectForKey("ri") as? PeerAccessRestrictionInfo
|
||||
}
|
||||
|
||||
|
||||
@@ -74,22 +74,22 @@ public final class TelegramGroup: Peer {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i"))
|
||||
self.title = decoder.decodeStringForKey("t")
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.photo = decoder.decodeObjectArrayForKey("ph")
|
||||
self.participantCount = Int(decoder.decodeInt32ForKey("pc"))
|
||||
self.role = TelegramGroupRole(rawValue: decoder.decodeInt32ForKey("r"))!
|
||||
self.membership = TelegramGroupMembership(rawValue: decoder.decodeInt32ForKey("m"))!
|
||||
self.flags = TelegramGroupFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
let migrationPeerId: Int64? = decoder.decodeInt64ForKey("mr.i")
|
||||
let migrationAccessHash: Int64? = decoder.decodeInt64ForKey("mr.a")
|
||||
self.participantCount = Int(decoder.decodeInt32ForKey("pc", orElse: 0))
|
||||
self.role = TelegramGroupRole(rawValue: decoder.decodeInt32ForKey("r", orElse: 0))!
|
||||
self.membership = TelegramGroupMembership(rawValue: decoder.decodeInt32ForKey("m", orElse: 0))!
|
||||
self.flags = TelegramGroupFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
let migrationPeerId: Int64? = decoder.decodeOptionalInt64ForKey("mr.i")
|
||||
let migrationAccessHash: Int64? = decoder.decodeOptionalInt64ForKey("mr.a")
|
||||
if let migrationPeerId = migrationPeerId, let migrationAccessHash = migrationAccessHash {
|
||||
self.migrationReference = TelegramGroupToChannelMigrationReference(peerId: PeerId(migrationPeerId), accessHash: migrationAccessHash)
|
||||
} else {
|
||||
self.migrationReference = nil
|
||||
}
|
||||
self.creationDate = decoder.decodeInt32ForKey("d")
|
||||
self.version = Int(decoder.decodeInt32ForKey("v"))
|
||||
self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
self.version = Int(decoder.decodeInt32ForKey("v", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -30,10 +30,10 @@ public enum TelegramMediaActionType: Coding, Equatable {
|
||||
case phoneCall(callId: Int64, discardReason: PhoneCallDiscardReason?, duration: Int32?)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue")
|
||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||
switch rawValue {
|
||||
case 1:
|
||||
self = .groupCreated(title: decoder.decodeStringForKey("title"))
|
||||
self = .groupCreated(title: decoder.decodeStringForKey("title", orElse: ""))
|
||||
case 2:
|
||||
self = .addedMembers(peerIds: PeerId.decodeArrayFromBuffer(decoder.decodeBytesForKeyNoCopy("peerIds")!))
|
||||
case 3:
|
||||
@@ -41,29 +41,29 @@ public enum TelegramMediaActionType: Coding, Equatable {
|
||||
case 4:
|
||||
self = .photoUpdated(image: decoder.decodeObjectForKey("image") as? TelegramMediaImage)
|
||||
case 5:
|
||||
self = .titleUpdated(title: decoder.decodeStringForKey("title"))
|
||||
self = .titleUpdated(title: decoder.decodeStringForKey("title", orElse: ""))
|
||||
case 6:
|
||||
self = .pinnedMessageUpdated
|
||||
case 7:
|
||||
self = .joinedByLink(inviter: PeerId(decoder.decodeInt64ForKey("inviter")))
|
||||
self = .joinedByLink(inviter: PeerId(decoder.decodeInt64ForKey("inviter", orElse: 0)))
|
||||
case 8:
|
||||
self = .channelMigratedFromGroup(title: decoder.decodeStringForKey("title"), groupId: PeerId(decoder.decodeInt64ForKey("groupId")))
|
||||
self = .channelMigratedFromGroup(title: decoder.decodeStringForKey("title", orElse: ""), groupId: PeerId(decoder.decodeInt64ForKey("groupId", orElse: 0)))
|
||||
case 9:
|
||||
self = .groupMigratedToChannel(channelId: PeerId(decoder.decodeInt64ForKey("channelId")))
|
||||
self = .groupMigratedToChannel(channelId: PeerId(decoder.decodeInt64ForKey("channelId", orElse: 0)))
|
||||
case 10:
|
||||
self = .historyCleared
|
||||
case 11:
|
||||
self = .historyScreenshot
|
||||
case 12:
|
||||
self = .messageAutoremoveTimeoutUpdated(decoder.decodeInt32ForKey("t"))
|
||||
self = .messageAutoremoveTimeoutUpdated(decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case 13:
|
||||
self = .gameScore(gameId: decoder.decodeInt64ForKey("i"), score: decoder.decodeInt32ForKey("s"))
|
||||
self = .gameScore(gameId: decoder.decodeInt64ForKey("i", orElse: 0), score: decoder.decodeInt32ForKey("s", orElse: 0))
|
||||
case 14:
|
||||
var discardReason: PhoneCallDiscardReason?
|
||||
if let value = (decoder.decodeInt32ForKey("dr") as Int32?) {
|
||||
if let value = decoder.decodeOptionalInt32ForKey("dr") {
|
||||
discardReason = PhoneCallDiscardReason(rawValue: value)
|
||||
}
|
||||
self = .phoneCall(callId: decoder.decodeInt64ForKey("i"), discardReason: discardReason, duration: decoder.decodeInt32ForKey("d"))
|
||||
self = .phoneCall(callId: decoder.decodeInt64ForKey("i", orElse: 0), discardReason: discardReason, duration: decoder.decodeInt32ForKey("d", orElse: 0))
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ public final class TelegramMediaContact: Media {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.firstName = decoder.decodeStringForKey("n.f")
|
||||
self.lastName = decoder.decodeStringForKey("n.l")
|
||||
self.phoneNumber = decoder.decodeStringForKey("pn")
|
||||
if let peerIdValue: Int64 = decoder.decodeInt64ForKey("p") {
|
||||
self.firstName = decoder.decodeStringForKey("n.f", orElse: "")
|
||||
self.lastName = decoder.decodeStringForKey("n.l", orElse: "")
|
||||
self.phoneNumber = decoder.decodeStringForKey("pn", orElse: "")
|
||||
if let peerIdValue = decoder.decodeOptionalInt64ForKey("p") {
|
||||
self.peerId = PeerId(peerIdValue)
|
||||
self.peerIds = [PeerId(peerIdValue)]
|
||||
} else {
|
||||
|
||||
@@ -18,11 +18,11 @@ public enum StickerPackReference: Coding {
|
||||
case name(String)
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("r") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||
case 0:
|
||||
self = .id(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("h"))
|
||||
self = .id(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0))
|
||||
case 1:
|
||||
self = .name(decoder.decodeStringForKey("n"))
|
||||
self = .name(decoder.decodeStringForKey("n", orElse: ""))
|
||||
default:
|
||||
self = .name("")
|
||||
assertionFailure()
|
||||
@@ -66,25 +66,25 @@ public enum TelegramMediaFileAttribute: Coding {
|
||||
case HasLinkedStickers
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
let type: Int32 = decoder.decodeInt32ForKey("t")
|
||||
let type: Int32 = decoder.decodeInt32ForKey("t", orElse: 0)
|
||||
switch type {
|
||||
case typeFileName:
|
||||
self = .FileName(fileName: decoder.decodeStringForKey("fn"))
|
||||
self = .FileName(fileName: decoder.decodeStringForKey("fn", orElse: ""))
|
||||
case typeSticker:
|
||||
self = .Sticker(displayText: decoder.decodeStringForKey("dt"), packReference: decoder.decodeObjectForKey("pr", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference)
|
||||
self = .Sticker(displayText: decoder.decodeStringForKey("dt", orElse: ""), packReference: decoder.decodeObjectForKey("pr", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference)
|
||||
case typeImageSize:
|
||||
self = .ImageSize(size: CGSize(width: CGFloat(decoder.decodeInt32ForKey("w")), height: CGFloat(decoder.decodeInt32ForKey("h"))))
|
||||
self = .ImageSize(size: CGSize(width: CGFloat(decoder.decodeInt32ForKey("w", orElse: 0)), height: CGFloat(decoder.decodeInt32ForKey("h", orElse: 0))))
|
||||
case typeAnimated:
|
||||
self = .Animated
|
||||
case typeVideo:
|
||||
self = .Video(duration: Int(decoder.decodeInt32ForKey("du")), size: CGSize(width: CGFloat(decoder.decodeInt32ForKey("w")), height: CGFloat(decoder.decodeInt32ForKey("h"))), flags: TelegramMediaVideoFlags(rawValue: decoder.decodeInt32ForKey("f")))
|
||||
self = .Video(duration: Int(decoder.decodeInt32ForKey("du", orElse: 0)), size: CGSize(width: CGFloat(decoder.decodeInt32ForKey("w", orElse: 0)), height: CGFloat(decoder.decodeInt32ForKey("h", orElse: 0))), flags: TelegramMediaVideoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0)))
|
||||
case typeAudio:
|
||||
let waveformBuffer = decoder.decodeBytesForKeyNoCopy("wf")
|
||||
var waveform: MemoryBuffer?
|
||||
if let waveformBuffer = waveformBuffer {
|
||||
waveform = MemoryBuffer(copyOf: waveformBuffer)
|
||||
}
|
||||
self = .Audio(isVoice: decoder.decodeInt32ForKey("iv") != 0, duration: Int(decoder.decodeInt32ForKey("du")), title: decoder.decodeStringForKey("ti"), performer: decoder.decodeStringForKey("pe"), waveform: waveform)
|
||||
self = .Audio(isVoice: decoder.decodeInt32ForKey("iv", orElse: 0) != 0, duration: Int(decoder.decodeInt32ForKey("du", orElse: 0)), title: decoder.decodeOptionalStringForKey("ti"), performer: decoder.decodeOptionalStringForKey("pe"), waveform: waveform)
|
||||
case typeHasLinkedStickers:
|
||||
self = .HasLinkedStickers
|
||||
default:
|
||||
@@ -162,8 +162,8 @@ public final class TelegramMediaFile: Media, Equatable {
|
||||
self.fileId = MediaId(decoder.decodeBytesForKeyNoCopy("i")!)
|
||||
self.resource = decoder.decodeObjectForKey("r") as! TelegramMediaResource
|
||||
self.previewRepresentations = decoder.decodeObjectArrayForKey("pr")
|
||||
self.mimeType = decoder.decodeStringForKey("mt")
|
||||
if let size = (decoder.decodeInt32ForKey("s") as Int32?) {
|
||||
self.mimeType = decoder.decodeStringForKey("mt", orElse: "")
|
||||
if let size = decoder.decodeOptionalInt32ForKey("s") {
|
||||
self.size = Int(size)
|
||||
} else {
|
||||
self.size = nil
|
||||
|
||||
@@ -30,11 +30,11 @@ public final class TelegramMediaGame: Media {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.gameId = decoder.decodeInt64ForKey("i")
|
||||
self.accessHash = decoder.decodeInt64ForKey("h")
|
||||
self.name = decoder.decodeStringForKey("n")
|
||||
self.title = decoder.decodeStringForKey("t")
|
||||
self.description = decoder.decodeStringForKey("d")
|
||||
self.gameId = decoder.decodeInt64ForKey("i", orElse: 0)
|
||||
self.accessHash = decoder.decodeInt64ForKey("h", orElse: 0)
|
||||
self.name = decoder.decodeStringForKey("n", orElse: "")
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.description = decoder.decodeStringForKey("d", orElse: "")
|
||||
self.image = decoder.decodeObjectForKey("p") as? TelegramMediaImage
|
||||
self.file = decoder.decodeObjectForKey("f") as? TelegramMediaFile
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public final class TelegramMediaImageRepresentation: Coding, Equatable, CustomSt
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.dimensions = CGSize(width: CGFloat(decoder.decodeInt32ForKey("dx")), height: CGFloat(decoder.decodeInt32ForKey("dy")))
|
||||
self.dimensions = CGSize(width: CGFloat(decoder.decodeInt32ForKey("dx", orElse: 0)), height: CGFloat(decoder.decodeInt32ForKey("dy", orElse: 0)))
|
||||
self.resource = decoder.decodeObjectForKey("r") as! TelegramMediaResource
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ public final class NamedGeoPlace: Coding {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.country = decoder.decodeStringForKey("gp_co")
|
||||
self.state = decoder.decodeStringForKey("gp_sta")
|
||||
self.city = decoder.decodeStringForKey("gp_ci")
|
||||
self.district = decoder.decodeStringForKey("gp_dis")
|
||||
self.street = decoder.decodeStringForKey("gp_str")
|
||||
self.country = decoder.decodeOptionalStringForKey("gp_co")
|
||||
self.state = decoder.decodeOptionalStringForKey("gp_sta")
|
||||
self.city = decoder.decodeOptionalStringForKey("gp_ci")
|
||||
self.district = decoder.decodeOptionalStringForKey("gp_dis")
|
||||
self.street = decoder.decodeOptionalStringForKey("gp_str")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -65,10 +65,10 @@ public final class MapVenue: Coding {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.title = decoder.decodeStringForKey("ti")
|
||||
self.address = decoder.decodeStringForKey("ad")
|
||||
self.provider = decoder.decodeStringForKey("pr")
|
||||
self.id = decoder.decodeStringForKey("id")
|
||||
self.title = decoder.decodeStringForKey("ti", orElse: "")
|
||||
self.address = decoder.decodeOptionalStringForKey("ad")
|
||||
self.provider = decoder.decodeOptionalStringForKey("pr")
|
||||
self.id = decoder.decodeOptionalStringForKey("id")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -103,8 +103,8 @@ public final class TelegramMediaMap: Media {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.latitude = decoder.decodeDoubleForKey("la")
|
||||
self.longitude = decoder.decodeDoubleForKey("lo")
|
||||
self.latitude = decoder.decodeDoubleForKey("la", orElse: 0.0)
|
||||
self.longitude = decoder.decodeDoubleForKey("lo", orElse: 0.0)
|
||||
self.geoPlace = decoder.decodeObjectForKey("gp", decoder: { NamedGeoPlace(decoder: $0) }) as? NamedGeoPlace
|
||||
self.venue = decoder.decodeObjectForKey("ve", decoder: { MapVenue(decoder: $0) }) as? MapVenue
|
||||
}
|
||||
|
||||
@@ -40,25 +40,25 @@ public final class TelegramMediaWebpageLoadedContent: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.url = decoder.decodeStringForKey("u")
|
||||
self.displayUrl = decoder.decodeStringForKey("d")
|
||||
self.type = decoder.decodeStringForKey("ty")
|
||||
self.websiteName = decoder.decodeStringForKey("ws")
|
||||
self.title = decoder.decodeStringForKey("ti")
|
||||
self.text = decoder.decodeStringForKey("tx")
|
||||
self.embedUrl = decoder.decodeStringForKey("eu")
|
||||
self.embedType = decoder.decodeStringForKey("et")
|
||||
if let embedSizeWidth: Int32 = decoder.decodeInt32ForKey("esw"), let embedSizeHeight: Int32 = decoder.decodeInt32ForKey("esh") {
|
||||
self.url = decoder.decodeStringForKey("u", orElse: "")
|
||||
self.displayUrl = decoder.decodeStringForKey("d", orElse: "")
|
||||
self.type = decoder.decodeOptionalStringForKey("ty")
|
||||
self.websiteName = decoder.decodeOptionalStringForKey("ws")
|
||||
self.title = decoder.decodeOptionalStringForKey("ti")
|
||||
self.text = decoder.decodeOptionalStringForKey("tx")
|
||||
self.embedUrl = decoder.decodeOptionalStringForKey("eu")
|
||||
self.embedType = decoder.decodeOptionalStringForKey("et")
|
||||
if let embedSizeWidth = decoder.decodeOptionalInt32ForKey("esw"), let embedSizeHeight = decoder.decodeOptionalInt32ForKey("esh") {
|
||||
self.embedSize = CGSize(width: CGFloat(embedSizeWidth), height: CGFloat(embedSizeHeight))
|
||||
} else {
|
||||
self.embedSize = nil
|
||||
}
|
||||
if let duration: Int32 = decoder.decodeInt32ForKey("du") {
|
||||
if let duration = decoder.decodeOptionalInt32ForKey("du") {
|
||||
self.duration = Int(duration)
|
||||
} else {
|
||||
self.duration = nil
|
||||
}
|
||||
self.author = decoder.decodeStringForKey("au")
|
||||
self.author = decoder.decodeOptionalStringForKey("au")
|
||||
|
||||
if let image = decoder.decodeObjectForKey("im") as? TelegramMediaImage {
|
||||
self.image = image
|
||||
@@ -207,8 +207,8 @@ public final class TelegramMediaWebpage: Media, Equatable {
|
||||
public init(decoder: Decoder) {
|
||||
self.webpageId = MediaId(decoder.decodeBytesForKeyNoCopy("i")!)
|
||||
|
||||
if decoder.decodeInt32ForKey("ct") == 0 {
|
||||
self.content = .Pending(decoder.decodeInt32ForKey("pendingDate"))
|
||||
if decoder.decodeInt32ForKey("ct", orElse: 0) == 0 {
|
||||
self.content = .Pending(decoder.decodeInt32ForKey("pendingDate", orElse: 0))
|
||||
} else {
|
||||
self.content = .Loaded(TelegramMediaWebpageLoadedContent(decoder: decoder))
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ public enum PeerMuteState: Equatable {
|
||||
case muted(until: Int32)
|
||||
|
||||
fileprivate static func decodeInline(_ decoder: Decoder) -> PeerMuteState {
|
||||
switch decoder.decodeInt32ForKey("m.v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("m.v", orElse: 0) {
|
||||
case 0:
|
||||
return .unmuted
|
||||
case 1:
|
||||
return .muted(until: decoder.decodeInt32ForKey("m.u"))
|
||||
return .muted(until: decoder.decodeInt32ForKey("m.u", orElse: 0))
|
||||
default:
|
||||
return .unmuted
|
||||
}
|
||||
@@ -62,13 +62,13 @@ public enum PeerMessageSound: Equatable {
|
||||
case bundledClassic(id: Int32)
|
||||
|
||||
static func decodeInline(_ decoder: Decoder) -> PeerMessageSound {
|
||||
switch decoder.decodeInt32ForKey("s.v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("s.v", orElse: 0) {
|
||||
case PeerMessageSoundValue.none.rawValue:
|
||||
return .none
|
||||
case PeerMessageSoundValue.bundledModern.rawValue:
|
||||
return .bundledModern(id: decoder.decodeInt32ForKey("s.i"))
|
||||
return .bundledModern(id: decoder.decodeInt32ForKey("s.i", orElse: 0))
|
||||
case PeerMessageSoundValue.bundledClassic.rawValue:
|
||||
return .bundledClassic(id: decoder.decodeInt32ForKey("s.i"))
|
||||
return .bundledClassic(id: decoder.decodeInt32ForKey("s.i", orElse: 0))
|
||||
default:
|
||||
assertionFailure()
|
||||
return .bundledModern(id: 0)
|
||||
|
||||
@@ -34,15 +34,15 @@ public final class TelegramSecretChat: Peer {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i"))
|
||||
self.regularPeerId = PeerId(decoder.decodeInt64ForKey("r"))
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
self.regularPeerId = PeerId(decoder.decodeInt64ForKey("r", orElse: 0))
|
||||
self.notificationSettingsPeerId = self.regularPeerId
|
||||
self.accessHash = decoder.decodeInt64ForKey("h")
|
||||
self.creationDate = decoder.decodeInt32ForKey("d")
|
||||
self.role = SecretChatRole(rawValue: decoder.decodeInt32ForKey("o"))!
|
||||
self.embeddedState = SecretChatEmbeddedPeerState(rawValue: decoder.decodeInt32ForKey("s"))!
|
||||
self.accessHash = decoder.decodeInt64ForKey("h", orElse: 0)
|
||||
self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0)
|
||||
self.role = SecretChatRole(rawValue: decoder.decodeInt32ForKey("o", orElse: 0))!
|
||||
self.embeddedState = SecretChatEmbeddedPeerState(rawValue: decoder.decodeInt32ForKey("s", orElse: 0))!
|
||||
self.associatedPeerIds = [self.regularPeerId]
|
||||
self.messageAutoremoveTimeout = decoder.decodeInt32ForKey("at")
|
||||
self.messageAutoremoveTimeout = decoder.decodeOptionalInt32ForKey("at")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -45,8 +45,8 @@ public struct BotUserInfo: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.flags = BotUserInfoFlags(rawValue: decoder.decodeInt32ForKey("f"))
|
||||
self.inlinePlaceholder = decoder.decodeStringForKey("ip")
|
||||
self.flags = BotUserInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
self.inlinePlaceholder = decoder.decodeOptionalStringForKey("ip")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
@@ -108,20 +108,20 @@ public final class TelegramUser: Peer {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i"))
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
|
||||
let accessHash: Int64 = decoder.decodeInt64ForKey("ah")
|
||||
let accessHash: Int64 = decoder.decodeInt64ForKey("ah", orElse: 0)
|
||||
if accessHash != 0 {
|
||||
self.accessHash = accessHash
|
||||
} else {
|
||||
self.accessHash = nil
|
||||
}
|
||||
|
||||
self.firstName = decoder.decodeStringForKey("fn")
|
||||
self.lastName = decoder.decodeStringForKey("ln")
|
||||
self.firstName = decoder.decodeOptionalStringForKey("fn")
|
||||
self.lastName = decoder.decodeOptionalStringForKey("ln")
|
||||
|
||||
self.username = decoder.decodeStringForKey("un")
|
||||
self.phone = decoder.decodeStringForKey("p")
|
||||
self.username = decoder.decodeOptionalStringForKey("un")
|
||||
self.phone = decoder.decodeOptionalStringForKey("p")
|
||||
|
||||
self.photo = decoder.decodeObjectArrayForKey("ph")
|
||||
|
||||
@@ -131,7 +131,7 @@ public final class TelegramUser: Peer {
|
||||
self.botInfo = nil
|
||||
}
|
||||
|
||||
self.flags = UserInfoFlags(rawValue: decoder.decodeInt32ForKey("fl"))
|
||||
self.flags = UserInfoFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
@@ -90,11 +90,11 @@ public enum UserPresenceStatus: Comparable, Coding {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
switch decoder.decodeInt32ForKey("v") as Int32 {
|
||||
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
||||
case 0:
|
||||
self = .none
|
||||
case 1:
|
||||
self = .present(until: decoder.decodeInt32ForKey("t"))
|
||||
self = .present(until: decoder.decodeInt32ForKey("t", orElse: 0))
|
||||
case 2:
|
||||
self = .recently
|
||||
case 3:
|
||||
|
||||
@@ -107,8 +107,8 @@ public struct MessageTextEntity: Coding, Equatable {
|
||||
}
|
||||
|
||||
public init(decoder: Decoder) {
|
||||
self.range = Int(decoder.decodeInt32ForKey("start")) ..< Int(decoder.decodeInt32ForKey("end"))
|
||||
let type: Int32 = decoder.decodeInt32ForKey("_rawValue")
|
||||
self.range = Int(decoder.decodeInt32ForKey("start", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("end", orElse: 0))
|
||||
let type: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||
switch type {
|
||||
case 1:
|
||||
self.type = .Mention
|
||||
@@ -129,9 +129,9 @@ public struct MessageTextEntity: Coding, Equatable {
|
||||
case 9:
|
||||
self.type = .Pre
|
||||
case 10:
|
||||
self.type = .TextUrl(url: decoder.decodeStringForKey("url"))
|
||||
self.type = .TextUrl(url: decoder.decodeStringForKey("url", orElse: ""))
|
||||
case 11:
|
||||
self.type = .TextMention(peerId: PeerId(decoder.decodeInt64ForKey("peerId")))
|
||||
self.type = .TextMention(peerId: PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0)))
|
||||
default:
|
||||
self.type = .Unknown
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class ViewCountMessageAttribute: MessageAttribute {
|
||||
}
|
||||
|
||||
required public init(decoder: Decoder) {
|
||||
self.count = Int(decoder.decodeInt32ForKey("c"))
|
||||
self.count = Int(decoder.decodeInt32ForKey("c", orElse: 0))
|
||||
}
|
||||
|
||||
public func encode(_ encoder: Encoder) {
|
||||
|
||||
Reference in New Issue
Block a user