mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-25 17:43:18 +00:00
Added json app configuration fetch
Added app log events synchronization Added A/B test API
This commit is contained in:
parent
b6b1c8f376
commit
008ecf61a1
@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
09028386218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */; };
|
09028386218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */; };
|
||||||
|
0962E66721B59BAA00245FD9 /* ManagedAppConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E66621B59BAA00245FD9 /* ManagedAppConfigurationUpdates.swift */; };
|
||||||
|
0962E66921B5A11100245FD9 /* SynchronizeAppLogEventsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E66821B5A11100245FD9 /* SynchronizeAppLogEventsOperation.swift */; };
|
||||||
|
0962E66B21B5A41C00245FD9 /* ManagedSynchronizeAppLogEventsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E66A21B5A41C00245FD9 /* ManagedSynchronizeAppLogEventsOperations.swift */; };
|
||||||
|
0962E66D21B5C56F00245FD9 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E66C21B5C56F00245FD9 /* JSON.swift */; };
|
||||||
|
0962E66F21B6147600245FD9 /* AppConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E66E21B6147600245FD9 /* AppConfiguration.swift */; };
|
||||||
|
0962E67521B6437600245FD9 /* SplitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0962E67421B6437600245FD9 /* SplitTest.swift */; };
|
||||||
9F06831021A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */; };
|
9F06831021A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */; };
|
||||||
9F06831121A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */; };
|
9F06831121A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */; };
|
||||||
9F10CE8B20613C78002DD61A /* SecretApiLayer73.swift in Sources */ = {isa = PBXBuildFile; fileRef = D018EDFF2044939F00CBB130 /* SecretApiLayer73.swift */; };
|
9F10CE8B20613C78002DD61A /* SecretApiLayer73.swift in Sources */ = {isa = PBXBuildFile; fileRef = D018EDFF2044939F00CBB130 /* SecretApiLayer73.swift */; };
|
||||||
@ -776,6 +782,12 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedVoipConfigurationUpdates.swift; sourceTree = "<group>"; };
|
09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedVoipConfigurationUpdates.swift; sourceTree = "<group>"; };
|
||||||
|
0962E66621B59BAA00245FD9 /* ManagedAppConfigurationUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedAppConfigurationUpdates.swift; sourceTree = "<group>"; };
|
||||||
|
0962E66821B5A11100245FD9 /* SynchronizeAppLogEventsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynchronizeAppLogEventsOperation.swift; sourceTree = "<group>"; };
|
||||||
|
0962E66A21B5A41C00245FD9 /* ManagedSynchronizeAppLogEventsOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeAppLogEventsOperations.swift; sourceTree = "<group>"; };
|
||||||
|
0962E66C21B5C56F00245FD9 /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
|
||||||
|
0962E66E21B6147600245FD9 /* AppConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
0962E67421B6437600245FD9 /* SplitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitTest.swift; sourceTree = "<group>"; };
|
||||||
9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationExceptionsList.swift; sourceTree = "<group>"; };
|
9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationExceptionsList.swift; sourceTree = "<group>"; };
|
||||||
9FC8ADAA206BBFF10094F7B4 /* RecentWebSessions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentWebSessions.swift; sourceTree = "<group>"; };
|
9FC8ADAA206BBFF10094F7B4 /* RecentWebSessions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentWebSessions.swift; sourceTree = "<group>"; };
|
||||||
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportMessageLink.swift; sourceTree = "<group>"; };
|
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportMessageLink.swift; sourceTree = "<group>"; };
|
||||||
@ -1242,6 +1254,7 @@
|
|||||||
D0FA08BA2046B37900DD23FC /* ContentPrivacySettings.swift */,
|
D0FA08BA2046B37900DD23FC /* ContentPrivacySettings.swift */,
|
||||||
D026099D20C695AF006C34AC /* Wallpapers.swift */,
|
D026099D20C695AF006C34AC /* Wallpapers.swift */,
|
||||||
D051DB13215EC5A300F30F92 /* AppChangelogState.swift */,
|
D051DB13215EC5A300F30F92 /* AppChangelogState.swift */,
|
||||||
|
0962E66E21B6147600245FD9 /* AppConfiguration.swift */,
|
||||||
);
|
);
|
||||||
name = Settings;
|
name = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1340,6 +1353,8 @@
|
|||||||
D0F8C39F2017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift */,
|
D0F8C39F2017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift */,
|
||||||
D0E412E9206AD18E00BEE4A2 /* DecryptedResourceData.swift */,
|
D0E412E9206AD18E00BEE4A2 /* DecryptedResourceData.swift */,
|
||||||
C28D3CEF20D3DA900027F4D6 /* DeepLinkInfo.swift */,
|
C28D3CEF20D3DA900027F4D6 /* DeepLinkInfo.swift */,
|
||||||
|
0962E66C21B5C56F00245FD9 /* JSON.swift */,
|
||||||
|
0962E67421B6437600245FD9 /* SplitTest.swift */,
|
||||||
);
|
);
|
||||||
name = Utils;
|
name = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1501,6 +1516,9 @@
|
|||||||
09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */,
|
09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */,
|
||||||
D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */,
|
D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */,
|
||||||
D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */,
|
D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */,
|
||||||
|
0962E66621B59BAA00245FD9 /* ManagedAppConfigurationUpdates.swift */,
|
||||||
|
0962E66821B5A11100245FD9 /* SynchronizeAppLogEventsOperation.swift */,
|
||||||
|
0962E66A21B5A41C00245FD9 /* ManagedSynchronizeAppLogEventsOperations.swift */,
|
||||||
);
|
);
|
||||||
name = State;
|
name = State;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2145,6 +2163,7 @@
|
|||||||
D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
||||||
D03B0CB91D62233400955575 /* Either.swift in Sources */,
|
D03B0CB91D62233400955575 /* Either.swift in Sources */,
|
||||||
D0D748021E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
D0D748021E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
||||||
|
0962E66D21B5C56F00245FD9 /* JSON.swift in Sources */,
|
||||||
D03B0CBD1D62234300955575 /* Regex.swift in Sources */,
|
D03B0CBD1D62234300955575 /* Regex.swift in Sources */,
|
||||||
D00BDA191EE593D600C64C5E /* TelegramChannelAdminRights.swift in Sources */,
|
D00BDA191EE593D600C64C5E /* TelegramChannelAdminRights.swift in Sources */,
|
||||||
D0B843B91DA7FF30005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
D0B843B91DA7FF30005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||||
@ -2254,12 +2273,14 @@
|
|||||||
D00422D321677F4500719B67 /* ManagedAccountPresence.swift in Sources */,
|
D00422D321677F4500719B67 /* ManagedAccountPresence.swift in Sources */,
|
||||||
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */,
|
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */,
|
||||||
D05464972073872C002ECC1E /* SecureIdBankStatementValue.swift in Sources */,
|
D05464972073872C002ECC1E /* SecureIdBankStatementValue.swift in Sources */,
|
||||||
|
0962E67521B6437600245FD9 /* SplitTest.swift in Sources */,
|
||||||
D0B843CB1DA7FF30005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
D0B843CB1DA7FF30005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
||||||
D03B0D5E1D631A6900955575 /* Network.swift in Sources */,
|
D03B0D5E1D631A6900955575 /* Network.swift in Sources */,
|
||||||
D0B8438E1DA7D296005F29E1 /* CachedGroupParticipants.swift in Sources */,
|
D0B8438E1DA7D296005F29E1 /* CachedGroupParticipants.swift in Sources */,
|
||||||
D0B843BD1DA7FF30005F29E1 /* NBMetadataHelper.m in Sources */,
|
D0B843BD1DA7FF30005F29E1 /* NBMetadataHelper.m in Sources */,
|
||||||
D03B0CF51D62250800955575 /* TelegramMediaContact.swift in Sources */,
|
D03B0CF51D62250800955575 /* TelegramMediaContact.swift in Sources */,
|
||||||
D03B0CFB1D62250800955575 /* TelegramMediaWebpage.swift in Sources */,
|
D03B0CFB1D62250800955575 /* TelegramMediaWebpage.swift in Sources */,
|
||||||
|
0962E66B21B5A41C00245FD9 /* ManagedSynchronizeAppLogEventsOperations.swift in Sources */,
|
||||||
D09A2FEB1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift in Sources */,
|
D09A2FEB1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift in Sources */,
|
||||||
D0E35A101DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */,
|
D0E35A101DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */,
|
||||||
D0E23DDA1E806F7700B9B6D2 /* ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift in Sources */,
|
D0E23DDA1E806F7700B9B6D2 /* ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift in Sources */,
|
||||||
@ -2267,6 +2288,7 @@
|
|||||||
D0BE303A20619EE800FBE6D8 /* SecureIdForm.swift in Sources */,
|
D0BE303A20619EE800FBE6D8 /* SecureIdForm.swift in Sources */,
|
||||||
D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */,
|
D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */,
|
||||||
D03DC9131F82F89D001D584C /* RegularChatState.swift in Sources */,
|
D03DC9131F82F89D001D584C /* RegularChatState.swift in Sources */,
|
||||||
|
0962E66721B59BAA00245FD9 /* ManagedAppConfigurationUpdates.swift in Sources */,
|
||||||
D0613FCF1E60520700202CDB /* ChannelMembers.swift in Sources */,
|
D0613FCF1E60520700202CDB /* ChannelMembers.swift in Sources */,
|
||||||
D0B2F7742052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift in Sources */,
|
D0B2F7742052DEF700D3BFB9 /* TelegramDeviceContactImportInfo.swift in Sources */,
|
||||||
C2366C891E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
C2366C891E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
||||||
@ -2404,6 +2426,7 @@
|
|||||||
D0CA3F84207391560042D2B6 /* SecureIdPadding.swift in Sources */,
|
D0CA3F84207391560042D2B6 /* SecureIdPadding.swift in Sources */,
|
||||||
D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */,
|
D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */,
|
||||||
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
|
||||||
|
0962E66921B5A11100245FD9 /* SynchronizeAppLogEventsOperation.swift in Sources */,
|
||||||
D049EAF51E44DF3300A2CD3A /* AccountState.swift in Sources */,
|
D049EAF51E44DF3300A2CD3A /* AccountState.swift in Sources */,
|
||||||
C28725421EF967E700613564 /* NotificationInfoMessageAttribute.swift in Sources */,
|
C28725421EF967E700613564 /* NotificationInfoMessageAttribute.swift in Sources */,
|
||||||
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
|
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
|
||||||
@ -2472,6 +2495,7 @@
|
|||||||
D03B0D081D62255C00955575 /* ChannelState.swift in Sources */,
|
D03B0D081D62255C00955575 /* ChannelState.swift in Sources */,
|
||||||
D08984F521187ECA00918162 /* NetworkType.swift in Sources */,
|
D08984F521187ECA00918162 /* NetworkType.swift in Sources */,
|
||||||
C251D7431E65E50500283EDE /* StickerSetInstallation.swift in Sources */,
|
C251D7431E65E50500283EDE /* StickerSetInstallation.swift in Sources */,
|
||||||
|
0962E66F21B6147600245FD9 /* AppConfiguration.swift in Sources */,
|
||||||
D07047BA1F3DF75500F6A8D4 /* ConsumePersonalMessageAction.swift in Sources */,
|
D07047BA1F3DF75500F6A8D4 /* ConsumePersonalMessageAction.swift in Sources */,
|
||||||
D07E413F208A769D00FCA8F0 /* ProxyServersStatuses.swift in Sources */,
|
D07E413F208A769D00FCA8F0 /* ProxyServersStatuses.swift in Sources */,
|
||||||
D0C0B58D1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift in Sources */,
|
D0C0B58D1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift in Sources */,
|
||||||
|
|||||||
@ -1097,11 +1097,13 @@ public class Account {
|
|||||||
}))
|
}))
|
||||||
self.managedOperationsDisposable.add(managedConfigurationUpdates(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedConfigurationUpdates(postbox: self.postbox, network: self.network).start())
|
||||||
self.managedOperationsDisposable.add(managedVoipConfigurationUpdates(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedVoipConfigurationUpdates(postbox: self.postbox, network: self.network).start())
|
||||||
|
self.managedOperationsDisposable.add(managedAppConfigurationUpdates(postbox: self.postbox, network: self.network).start())
|
||||||
self.managedOperationsDisposable.add(managedTermsOfServiceUpdates(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedTermsOfServiceUpdates(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedAppChangelog(postbox: self.postbox, network: self.network, stateManager: self.stateManager, appVersion: self.networkArguments.appVersion).start())
|
self.managedOperationsDisposable.add(managedAppChangelog(postbox: self.postbox, network: self.network, stateManager: self.stateManager, appVersion: self.networkArguments.appVersion).start())
|
||||||
self.managedOperationsDisposable.add(managedProxyInfoUpdates(postbox: self.postbox, network: self.network, viewTracker: self.viewTracker).start())
|
self.managedOperationsDisposable.add(managedProxyInfoUpdates(postbox: self.postbox, network: self.network, viewTracker: self.viewTracker).start())
|
||||||
self.managedOperationsDisposable.add(managedLocalizationUpdatesOperations(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedLocalizationUpdatesOperations(postbox: self.postbox, network: self.network).start())
|
||||||
self.managedOperationsDisposable.add(managedPendingPeerNotificationSettings(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedPendingPeerNotificationSettings(postbox: self.postbox, network: self.network).start())
|
||||||
|
self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start())
|
||||||
|
|
||||||
let storagePreferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.cacheStorageSettings]))
|
let storagePreferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.cacheStorageSettings]))
|
||||||
let mediaBox = postbox.mediaBox
|
let mediaBox = postbox.mediaBox
|
||||||
|
|||||||
@ -118,8 +118,11 @@ private var declaredEncodables: Void = {
|
|||||||
declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) })
|
declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) })
|
||||||
declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) })
|
declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) })
|
||||||
declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) })
|
declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) })
|
||||||
|
declareEncodable(SynchronizeAppLogEventsOperation.self, f: { SynchronizeAppLogEventsOperation(decoder: $0) })
|
||||||
declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) })
|
declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) })
|
||||||
declareEncodable(AppChangelogState.self, f: { AppChangelogState(decoder: $0) })
|
declareEncodable(AppChangelogState.self, f: { AppChangelogState(decoder: $0) })
|
||||||
|
declareEncodable(AppConfiguration.self, f: { AppConfiguration(decoder: $0) })
|
||||||
|
declareEncodable(JSON.self, f: { JSON(decoder: $0) })
|
||||||
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@ -51,6 +51,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-614138572] = { return Api.account.TmpPassword.parse_tmpPassword($0) }
|
dict[-614138572] = { return Api.account.TmpPassword.parse_tmpPassword($0) }
|
||||||
dict[-2103600678] = { return Api.SecureRequiredType.parse_secureRequiredType($0) }
|
dict[-2103600678] = { return Api.SecureRequiredType.parse_secureRequiredType($0) }
|
||||||
dict[41187252] = { return Api.SecureRequiredType.parse_secureRequiredTypeOneOf($0) }
|
dict[41187252] = { return Api.SecureRequiredType.parse_secureRequiredTypeOneOf($0) }
|
||||||
|
dict[1064139624] = { return Api.JSONValue.parse_jsonNull($0) }
|
||||||
|
dict[-952869270] = { return Api.JSONValue.parse_jsonBool($0) }
|
||||||
|
dict[736157604] = { return Api.JSONValue.parse_jsonNumber($0) }
|
||||||
|
dict[-1222740358] = { return Api.JSONValue.parse_jsonString($0) }
|
||||||
|
dict[-146520221] = { return Api.JSONValue.parse_jsonArray($0) }
|
||||||
|
dict[-1715350371] = { return Api.JSONValue.parse_jsonObject($0) }
|
||||||
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
|
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
|
||||||
dict[-1673036328] = { return Api.Photo.parse_photo($0) }
|
dict[-1673036328] = { return Api.Photo.parse_photo($0) }
|
||||||
dict[-1683826688] = { return Api.Chat.parse_chatEmpty($0) }
|
dict[-1683826688] = { return Api.Chat.parse_chatEmpty($0) }
|
||||||
@ -526,6 +532,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1471006352] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonHangup($0) }
|
dict[1471006352] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonHangup($0) }
|
||||||
dict[-84416311] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonBusy($0) }
|
dict[-84416311] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonBusy($0) }
|
||||||
dict[-1910892683] = { return Api.NearestDc.parse_nearestDc($0) }
|
dict[-1910892683] = { return Api.NearestDc.parse_nearestDc($0) }
|
||||||
|
dict[-1059185703] = { return Api.JSONObjectValue.parse_jsonObjectValue($0) }
|
||||||
dict[-1916114267] = { return Api.photos.Photos.parse_photos($0) }
|
dict[-1916114267] = { return Api.photos.Photos.parse_photos($0) }
|
||||||
dict[352657236] = { return Api.photos.Photos.parse_photosSlice($0) }
|
dict[352657236] = { return Api.photos.Photos.parse_photosSlice($0) }
|
||||||
dict[2010127419] = { return Api.contacts.ImportedContacts.parse_importedContacts($0) }
|
dict[2010127419] = { return Api.contacts.ImportedContacts.parse_importedContacts($0) }
|
||||||
@ -662,7 +669,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1788705589] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) }
|
dict[1788705589] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) }
|
||||||
dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) }
|
dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) }
|
||||||
dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) }
|
dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) }
|
||||||
dict[1996904104] = { return Api.InputAppEvent.parse_inputAppEvent($0) }
|
dict[488313413] = { return Api.InputAppEvent.parse_inputAppEvent($0) }
|
||||||
dict[-1148011883] = { return Api.MessageEntity.parse_messageEntityUnknown($0) }
|
dict[-1148011883] = { return Api.MessageEntity.parse_messageEntityUnknown($0) }
|
||||||
dict[-100378723] = { return Api.MessageEntity.parse_messageEntityMention($0) }
|
dict[-100378723] = { return Api.MessageEntity.parse_messageEntityMention($0) }
|
||||||
dict[1868782349] = { return Api.MessageEntity.parse_messageEntityHashtag($0) }
|
dict[1868782349] = { return Api.MessageEntity.parse_messageEntityHashtag($0) }
|
||||||
@ -778,6 +785,8 @@ struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.SecureRequiredType:
|
case let _1 as Api.SecureRequiredType:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.JSONValue:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.Photo:
|
case let _1 as Api.Photo:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.Chat:
|
case let _1 as Api.Chat:
|
||||||
@ -1112,6 +1121,8 @@ struct Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.NearestDc:
|
case let _1 as Api.NearestDc:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.JSONObjectValue:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.photos.Photos:
|
case let _1 as Api.photos.Photos:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.contacts.ImportedContacts:
|
case let _1 as Api.contacts.ImportedContacts:
|
||||||
|
|||||||
@ -1242,6 +1242,146 @@ extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
enum JSONValue: TypeConstructorDescription {
|
||||||
|
case jsonNull
|
||||||
|
case jsonBool(value: Api.Bool)
|
||||||
|
case jsonNumber(value: Double)
|
||||||
|
case jsonString(value: String)
|
||||||
|
case jsonArray(value: [Api.JSONValue])
|
||||||
|
case jsonObject(value: [Api.JSONObjectValue])
|
||||||
|
|
||||||
|
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
|
switch self {
|
||||||
|
case .jsonNull:
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(1064139624)
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case .jsonBool(let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-952869270)
|
||||||
|
}
|
||||||
|
value.serialize(buffer, true)
|
||||||
|
break
|
||||||
|
case .jsonNumber(let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(736157604)
|
||||||
|
}
|
||||||
|
serializeDouble(value, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
|
case .jsonString(let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1222740358)
|
||||||
|
}
|
||||||
|
serializeString(value, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
|
case .jsonArray(let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-146520221)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(value.count))
|
||||||
|
for item in value {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case .jsonObject(let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1715350371)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(value.count))
|
||||||
|
for item in value {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
|
switch self {
|
||||||
|
case .jsonNull:
|
||||||
|
return ("jsonNull", [])
|
||||||
|
case .jsonBool(let value):
|
||||||
|
return ("jsonBool", [("value", value)])
|
||||||
|
case .jsonNumber(let value):
|
||||||
|
return ("jsonNumber", [("value", value)])
|
||||||
|
case .jsonString(let value):
|
||||||
|
return ("jsonString", [("value", value)])
|
||||||
|
case .jsonArray(let value):
|
||||||
|
return ("jsonArray", [("value", value)])
|
||||||
|
case .jsonObject(let value):
|
||||||
|
return ("jsonObject", [("value", value)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parse_jsonNull(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
return Api.JSONValue.jsonNull
|
||||||
|
}
|
||||||
|
static func parse_jsonBool(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
var _1: Api.Bool?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_1 = Api.parse(reader, signature: signature) as? Api.Bool
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.JSONValue.jsonBool(value: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static func parse_jsonNumber(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
var _1: Double?
|
||||||
|
_1 = reader.readDouble()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.JSONValue.jsonNumber(value: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static func parse_jsonString(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
var _1: String?
|
||||||
|
_1 = parseString(reader)
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.JSONValue.jsonString(value: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static func parse_jsonArray(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
var _1: [Api.JSONValue]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONValue.self)
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.JSONValue.jsonArray(value: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static func parse_jsonObject(_ reader: BufferReader) -> JSONValue? {
|
||||||
|
var _1: [Api.JSONObjectValue]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONObjectValue.self)
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.JSONValue.jsonObject(value: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
enum Photo: TypeConstructorDescription {
|
enum Photo: TypeConstructorDescription {
|
||||||
case photoEmpty(id: Int64)
|
case photoEmpty(id: Int64)
|
||||||
@ -13428,6 +13568,46 @@ extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
enum JSONObjectValue: TypeConstructorDescription {
|
||||||
|
case jsonObjectValue(key: String, value: Api.JSONValue)
|
||||||
|
|
||||||
|
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
|
switch self {
|
||||||
|
case .jsonObjectValue(let key, let value):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1059185703)
|
||||||
|
}
|
||||||
|
serializeString(key, buffer: buffer, boxed: false)
|
||||||
|
value.serialize(buffer, true)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
|
switch self {
|
||||||
|
case .jsonObjectValue(let key, let value):
|
||||||
|
return ("jsonObjectValue", [("key", key), ("value", value)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parse_jsonObjectValue(_ reader: BufferReader) -> JSONObjectValue? {
|
||||||
|
var _1: String?
|
||||||
|
_1 = parseString(reader)
|
||||||
|
var _2: Api.JSONValue?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_2 = Api.parse(reader, signature: signature) as? Api.JSONValue
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
if _c1 && _c2 {
|
||||||
|
return Api.JSONObjectValue.jsonObjectValue(key: _1!, value: _2!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
enum InputWebDocument: TypeConstructorDescription {
|
enum InputWebDocument: TypeConstructorDescription {
|
||||||
case inputWebDocument(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute])
|
case inputWebDocument(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute])
|
||||||
@ -16464,18 +16644,18 @@ extension Api {
|
|||||||
|
|
||||||
}
|
}
|
||||||
enum InputAppEvent: TypeConstructorDescription {
|
enum InputAppEvent: TypeConstructorDescription {
|
||||||
case inputAppEvent(time: Double, type: String, peer: Int64, data: String)
|
case inputAppEvent(time: Double, type: String, peer: Int64, data: Api.JSONValue)
|
||||||
|
|
||||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .inputAppEvent(let time, let type, let peer, let data):
|
case .inputAppEvent(let time, let type, let peer, let data):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1996904104)
|
buffer.appendInt32(488313413)
|
||||||
}
|
}
|
||||||
serializeDouble(time, buffer: buffer, boxed: false)
|
serializeDouble(time, buffer: buffer, boxed: false)
|
||||||
serializeString(type, buffer: buffer, boxed: false)
|
serializeString(type, buffer: buffer, boxed: false)
|
||||||
serializeInt64(peer, buffer: buffer, boxed: false)
|
serializeInt64(peer, buffer: buffer, boxed: false)
|
||||||
serializeString(data, buffer: buffer, boxed: false)
|
data.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -16494,8 +16674,10 @@ extension Api {
|
|||||||
_2 = parseString(reader)
|
_2 = parseString(reader)
|
||||||
var _3: Int64?
|
var _3: Int64?
|
||||||
_3 = reader.readInt64()
|
_3 = reader.readInt64()
|
||||||
var _4: String?
|
var _4: Api.JSONValue?
|
||||||
_4 = parseString(reader)
|
if let signature = reader.readInt32() {
|
||||||
|
_4 = Api.parse(reader, signature: signature) as? Api.JSONValue
|
||||||
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
|
|||||||
@ -3956,24 +3956,6 @@ extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static func saveAppLog(events: [Api.InputAppEvent]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
|
||||||
let buffer = Buffer()
|
|
||||||
buffer.appendInt32(1862465352)
|
|
||||||
buffer.appendInt32(481674261)
|
|
||||||
buffer.appendInt32(Int32(events.count))
|
|
||||||
for item in events {
|
|
||||||
item.serialize(buffer, true)
|
|
||||||
}
|
|
||||||
return (FunctionDescription(name: "help.saveAppLog", parameters: [("events", events)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
|
||||||
let reader = BufferReader(buffer)
|
|
||||||
var result: Api.Bool?
|
|
||||||
if let signature = reader.readInt32() {
|
|
||||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
static func getInviteText() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.help.InviteText>) {
|
static func getInviteText() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.help.InviteText>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1295590211)
|
buffer.appendInt32(1295590211)
|
||||||
@ -4142,6 +4124,38 @@ extension Api {
|
|||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func getAppConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.JSONValue>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1735311088)
|
||||||
|
|
||||||
|
return (FunctionDescription(name: "help.getAppConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.JSONValue? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.JSONValue?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.JSONValue
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static func saveAppLog(events: [Api.InputAppEvent]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(1862465352)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(events.count))
|
||||||
|
for item in events {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
return (FunctionDescription(name: "help.saveAppLog", parameters: [("events", events)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.Bool?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct updates {
|
struct updates {
|
||||||
static func getState() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.updates.State>) {
|
static func getState() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.updates.State>) {
|
||||||
|
|||||||
53
TelegramCore/AppConfiguration.swift
Normal file
53
TelegramCore/AppConfiguration.swift
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public struct AppConfiguration: PreferencesEntry, Equatable {
|
||||||
|
public var data: JSON?
|
||||||
|
|
||||||
|
public static var defaultValue: AppConfiguration {
|
||||||
|
return AppConfiguration(data: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(data: JSON?) {
|
||||||
|
self.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.data = decoder.decodeObjectForKey("data", decoder: { JSON(decoder: $0) }) as? JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
if let data = self.data {
|
||||||
|
encoder.encodeObject(data, forKey: "data")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||||
|
guard let to = to as? AppConfiguration else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return self == to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func currentAppConfiguration(transaction: Transaction) -> AppConfiguration {
|
||||||
|
if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration) as? AppConfiguration {
|
||||||
|
return entry
|
||||||
|
} else {
|
||||||
|
return AppConfiguration.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateAppConfiguration(transaction: Transaction, _ f: (AppConfiguration) -> AppConfiguration) {
|
||||||
|
let current = currentAppConfiguration(transaction: transaction)
|
||||||
|
let updated = f(current)
|
||||||
|
if updated != current {
|
||||||
|
transaction.setPreferencesEntry(key: PreferencesKeys.appConfiguration, value: updated)
|
||||||
|
}
|
||||||
|
}
|
||||||
480
TelegramCore/JSON.swift
Normal file
480
TelegramCore/JSON.swift
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
import Foundation
|
||||||
|
import Postbox
|
||||||
|
|
||||||
|
public indirect enum JSON: PostboxCoding, Equatable {
|
||||||
|
case null
|
||||||
|
case number(Double)
|
||||||
|
case string(String)
|
||||||
|
case bool(Bool)
|
||||||
|
case array([JSON])
|
||||||
|
case dictionary([String: JSON])
|
||||||
|
|
||||||
|
private enum ValueType: Int32 {
|
||||||
|
case null = 0
|
||||||
|
case number = 1
|
||||||
|
case string = 2
|
||||||
|
case bool = 3
|
||||||
|
case array = 4
|
||||||
|
case dictionary = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
private init?(_ object: Any) {
|
||||||
|
if let object = object as? JSONValue {
|
||||||
|
self = object.jsonValue
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init?(data: Data) {
|
||||||
|
if let object = try? JSONSerialization.jsonObject(with: data, options: []) {
|
||||||
|
self.init(object)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init?(string: String) {
|
||||||
|
if let data = string.data(using: .utf8) {
|
||||||
|
self.init(data: data)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||||
|
case ValueType.null.rawValue:
|
||||||
|
self = .null
|
||||||
|
case ValueType.number.rawValue:
|
||||||
|
self = .number(decoder.decodeDoubleForKey("v", orElse: 0.0))
|
||||||
|
case ValueType.string.rawValue:
|
||||||
|
self = .string(decoder.decodeStringForKey("v", orElse: ""))
|
||||||
|
case ValueType.bool.rawValue:
|
||||||
|
self = .bool(decoder.decodeBoolForKey("v", orElse: false))
|
||||||
|
case ValueType.array.rawValue:
|
||||||
|
self = .array(decoder.decodeObjectArrayForKey("v"))
|
||||||
|
case ValueType.dictionary.rawValue:
|
||||||
|
self = .dictionary(decoder.decodeObjectDictionaryForKey("v", keyDecoder: { $0.decodeStringForKey("k", orElse: "")
|
||||||
|
}, valueDecoder: { JSON(decoder: $0) }))
|
||||||
|
default:
|
||||||
|
self = .null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
switch self {
|
||||||
|
case .null:
|
||||||
|
encoder.encodeInt32(ValueType.null.rawValue, forKey: "r")
|
||||||
|
case let .number(value):
|
||||||
|
encoder.encodeInt32(ValueType.number.rawValue, forKey: "r")
|
||||||
|
encoder.encodeDouble(value, forKey: "v")
|
||||||
|
case let .string(value):
|
||||||
|
encoder.encodeInt32(ValueType.string.rawValue, forKey: "r")
|
||||||
|
encoder.encodeString(value, forKey: "v")
|
||||||
|
case let .bool(value):
|
||||||
|
encoder.encodeInt32(ValueType.bool.rawValue, forKey: "r")
|
||||||
|
encoder.encodeBool(value, forKey: "v")
|
||||||
|
case let .array(value):
|
||||||
|
encoder.encodeInt32(ValueType.array.rawValue, forKey: "r")
|
||||||
|
encoder.encodeObjectArray(value, forKey: "v")
|
||||||
|
case let .dictionary(value):
|
||||||
|
encoder.encodeInt32(ValueType.dictionary.rawValue, forKey: "r")
|
||||||
|
encoder.encodeObjectDictionary(value, forKey: "v") { key, encoder in
|
||||||
|
encoder.encodeString(key, forKey: "k")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: JSON, rhs: JSON) -> Bool {
|
||||||
|
switch lhs {
|
||||||
|
case .null:
|
||||||
|
if case .null = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .number(value):
|
||||||
|
if case .number(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .string(value):
|
||||||
|
if case .string(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .bool(value):
|
||||||
|
if case .bool(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .array(value):
|
||||||
|
if case .array(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .dictionary(value):
|
||||||
|
if case .dictionary(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Index: Comparable {
|
||||||
|
case array(Int)
|
||||||
|
case dictionary(DictionaryIndex<String, JSON>)
|
||||||
|
case null
|
||||||
|
|
||||||
|
static public func ==(lhs: Index, rhs: Index) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case let (.array(lhs), .array(rhs)):
|
||||||
|
return lhs == rhs
|
||||||
|
case let (.dictionary(lhs), .dictionary(rhs)):
|
||||||
|
return lhs == rhs
|
||||||
|
case (.null, .null):
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public func <(lhs: Index, rhs: Index) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case let (.array(lhs), .array(rhs)):
|
||||||
|
return lhs < rhs
|
||||||
|
case let (.dictionary(lhs), .dictionary(rhs)):
|
||||||
|
return lhs < rhs
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON: Collection {
|
||||||
|
public var startIndex: Index {
|
||||||
|
switch self {
|
||||||
|
case let .array(value):
|
||||||
|
return .array(value.startIndex)
|
||||||
|
case let .dictionary(value):
|
||||||
|
return .dictionary(value.startIndex)
|
||||||
|
default:
|
||||||
|
return .null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var endIndex: Index {
|
||||||
|
switch self {
|
||||||
|
case let .array(value):
|
||||||
|
return .array(value.endIndex)
|
||||||
|
case let .dictionary(value):
|
||||||
|
return .dictionary(value.endIndex)
|
||||||
|
default:
|
||||||
|
return .null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func index(after i: Index) -> Index {
|
||||||
|
switch (i, self) {
|
||||||
|
case let (.array(index), .array(value)):
|
||||||
|
return .array(value.index(after: index))
|
||||||
|
case let (.dictionary(index), .dictionary(value)):
|
||||||
|
return .dictionary(value.index(after: index))
|
||||||
|
default:
|
||||||
|
return .null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscript (position: Index) -> (String, JSON) {
|
||||||
|
switch (position, self) {
|
||||||
|
case let (.array(index), .array(value)):
|
||||||
|
return (String(index), value[index])
|
||||||
|
case let (.dictionary(index), .dictionary(value)):
|
||||||
|
let (key, value) = value[index]
|
||||||
|
return (key, value)
|
||||||
|
default:
|
||||||
|
return ("", .null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum JSONKey {
|
||||||
|
case index(Int)
|
||||||
|
case key(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol JSONSubscriptType {
|
||||||
|
var jsonKey: JSONKey { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int: JSONSubscriptType {
|
||||||
|
public var jsonKey: JSONKey {
|
||||||
|
return .index(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String: JSONSubscriptType {
|
||||||
|
public var jsonKey: JSONKey {
|
||||||
|
return .key(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON {
|
||||||
|
fileprivate var value: JSONElement {
|
||||||
|
get {
|
||||||
|
switch self {
|
||||||
|
case .null:
|
||||||
|
return 0
|
||||||
|
case let .number(value):
|
||||||
|
return value
|
||||||
|
case let .string(value):
|
||||||
|
return value
|
||||||
|
case let .bool(value):
|
||||||
|
return value
|
||||||
|
case let .array(values):
|
||||||
|
var array: [JSONElement] = []
|
||||||
|
for value in values {
|
||||||
|
array.append(value.value)
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
case let .dictionary(values):
|
||||||
|
var dictionary: [String: JSONElement] = [:]
|
||||||
|
for (key, value) in values {
|
||||||
|
dictionary[key] = value.value
|
||||||
|
}
|
||||||
|
return dictionary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON {
|
||||||
|
public subscript(key: JSONSubscriptType) -> JSONElement? {
|
||||||
|
get {
|
||||||
|
switch (key.jsonKey, self) {
|
||||||
|
case let (.index(index), .array(value)):
|
||||||
|
if value.indices.contains(index) {
|
||||||
|
return value[index].value
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case let (.key(key), .dictionary(value)):
|
||||||
|
if let value = value[key] {
|
||||||
|
return value.value
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON: ExpressibleByDictionaryLiteral {
|
||||||
|
public init(dictionaryLiteral elements: (String, Any)...) {
|
||||||
|
self = .dictionary(elements.reduce([String: JSON]()) { (dictionary, element) in
|
||||||
|
var dictionary = dictionary
|
||||||
|
if let value = JSON(element.1) {
|
||||||
|
dictionary[element.0] = value
|
||||||
|
}
|
||||||
|
return dictionary
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON: ExpressibleByArrayLiteral {
|
||||||
|
public init(arrayLiteral elements: Any...) {
|
||||||
|
self = .array(elements.compactMap { JSON($0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol JSONElement {}
|
||||||
|
private protocol JSONValue {
|
||||||
|
var jsonValue: JSON { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int8: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int16: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int32: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int64: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt8: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt16: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt32: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt64: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(Double(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Double: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .number(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .string(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Bool: JSONElement, JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .bool(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array: JSONElement where Element == JSONElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array: JSONValue where Element == JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .array(self.map { $0.jsonValue })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Dictionary: JSONElement where Key == String, Value == JSONElement {
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Dictionary: JSONValue where Key == String, Value == JSONValue {
|
||||||
|
var jsonValue: JSON {
|
||||||
|
return .dictionary(self.mapValues { $0.jsonValue })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Bool {
|
||||||
|
init(apiBool: Api.Bool) {
|
||||||
|
switch apiBool {
|
||||||
|
case .boolTrue:
|
||||||
|
self.init(true)
|
||||||
|
case .boolFalse:
|
||||||
|
self.init(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiBool: Api.Bool {
|
||||||
|
if self {
|
||||||
|
return .boolTrue
|
||||||
|
} else {
|
||||||
|
return .boolFalse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSON {
|
||||||
|
private init?(apiJson: Api.JSONValue, root: Bool) {
|
||||||
|
switch (apiJson, root) {
|
||||||
|
case (.jsonNull, false):
|
||||||
|
self = .null
|
||||||
|
case let (.jsonNumber(value), false):
|
||||||
|
self = .number(value)
|
||||||
|
case let (.jsonString(value), false):
|
||||||
|
self = .string(value)
|
||||||
|
case let (.jsonBool(value), false):
|
||||||
|
self = .bool(Bool(apiBool: value))
|
||||||
|
case let (.jsonArray(value), _):
|
||||||
|
self = .array(value.compactMap { JSON(apiJson: $0, root: false) })
|
||||||
|
case let (.jsonObject(value), _):
|
||||||
|
self = .dictionary(value.reduce([String: JSON]()) { dictionary, value in
|
||||||
|
var dictionary = dictionary
|
||||||
|
switch value {
|
||||||
|
case let .jsonObjectValue(key, value):
|
||||||
|
if let value = JSON(apiJson: value, root: false) {
|
||||||
|
dictionary[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dictionary
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(apiJson: Api.JSONValue) {
|
||||||
|
self.init(apiJson: apiJson, root: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func apiJson(_ json: JSON, root: Bool) -> Api.JSONValue? {
|
||||||
|
switch (json, root) {
|
||||||
|
case (.null, false):
|
||||||
|
return .jsonNull
|
||||||
|
case let (.number(value), false):
|
||||||
|
return .jsonNumber(value: value)
|
||||||
|
case let (.string(value), false):
|
||||||
|
return .jsonString(value: value)
|
||||||
|
case let (.bool(value), false):
|
||||||
|
return .jsonBool(value: value.apiBool)
|
||||||
|
case let (.array(value), _):
|
||||||
|
return .jsonArray(value: value.compactMap { apiJson($0, root: false) })
|
||||||
|
case let (.dictionary(value), _):
|
||||||
|
return .jsonObject(value: value.reduce([Api.JSONObjectValue]()) { objectValues, keyAndValue in
|
||||||
|
var objectValues = objectValues
|
||||||
|
if let value = apiJson(keyAndValue.value, root: false) {
|
||||||
|
objectValues.append(.jsonObjectValue(key: keyAndValue.key, value: value))
|
||||||
|
}
|
||||||
|
return objectValues
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiJson(_ json: JSON) -> Api.JSONValue? {
|
||||||
|
return apiJson(json, root: true)
|
||||||
|
}
|
||||||
29
TelegramCore/ManagedAppConfigurationUpdates.swift
Normal file
29
TelegramCore/ManagedAppConfigurationUpdates.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
func managedAppConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||||
|
let poll = Signal<Void, NoError> { subscriber in
|
||||||
|
return (network.request(Api.functions.help.getAppConfig())
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||||
|
return postbox.transaction { transaction -> Void in
|
||||||
|
if let data = JSON(apiJson: result) {
|
||||||
|
updateAppConfiguration(transaction: transaction, { configuration -> AppConfiguration in
|
||||||
|
var configuration = configuration
|
||||||
|
configuration.data = data
|
||||||
|
return configuration
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
|
return (poll |> then(.complete() |> suspendAwareDelay(12.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||||
|
}
|
||||||
143
TelegramCore/ManagedSynchronizeAppLogEventsOperations.swift
Normal file
143
TelegramCore/ManagedSynchronizeAppLogEventsOperations.swift
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private final class ManagedSynchronizeAppLogEventsOperationsHelper {
|
||||||
|
var operationDisposables: [Int32: Disposable] = [:]
|
||||||
|
|
||||||
|
func update(_ entries: [PeerMergedOperationLogEntry]) -> (disposeOperations: [Disposable], beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)]) {
|
||||||
|
var disposeOperations: [Disposable] = []
|
||||||
|
var beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)] = []
|
||||||
|
|
||||||
|
var hasRunningOperationForPeerId = Set<PeerId>()
|
||||||
|
var validMergedIndices = Set<Int32>()
|
||||||
|
for entry in entries {
|
||||||
|
if !hasRunningOperationForPeerId.contains(entry.peerId) {
|
||||||
|
hasRunningOperationForPeerId.insert(entry.peerId)
|
||||||
|
validMergedIndices.insert(entry.mergedIndex)
|
||||||
|
|
||||||
|
if self.operationDisposables[entry.mergedIndex] == nil {
|
||||||
|
let disposable = MetaDisposable()
|
||||||
|
beginOperations.append((entry, disposable))
|
||||||
|
self.operationDisposables[entry.mergedIndex] = disposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var removeMergedIndices: [Int32] = []
|
||||||
|
for (mergedIndex, disposable) in self.operationDisposables {
|
||||||
|
if !validMergedIndices.contains(mergedIndex) {
|
||||||
|
removeMergedIndices.append(mergedIndex)
|
||||||
|
disposeOperations.append(disposable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for mergedIndex in removeMergedIndices {
|
||||||
|
self.operationDisposables.removeValue(forKey: mergedIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (disposeOperations, beginOperations)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reset() -> [Disposable] {
|
||||||
|
let disposables = Array(self.operationDisposables.values)
|
||||||
|
self.operationDisposables.removeAll()
|
||||||
|
return disposables
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func withTakenOperation(postbox: Postbox, peerId: PeerId, tag: PeerOperationLogTag, tagLocalIndex: Int32, _ f: @escaping (Transaction, PeerMergedOperationLogEntry?) -> Signal<Void, NoError>) -> Signal<Void, NoError> {
|
||||||
|
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
|
var result: PeerMergedOperationLogEntry?
|
||||||
|
transaction.operationLogUpdateEntry(peerId: peerId, tag: tag, tagLocalIndex: tagLocalIndex, { entry in
|
||||||
|
if let entry = entry, let _ = entry.mergedIndex, entry.contents is SynchronizeAppLogEventsOperation {
|
||||||
|
result = entry.mergedEntry!
|
||||||
|
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
|
||||||
|
} else {
|
||||||
|
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return f(transaction, result)
|
||||||
|
} |> switchToLatest
|
||||||
|
}
|
||||||
|
|
||||||
|
func managedSynchronizeAppLogEventsOperations(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||||
|
return Signal { _ in
|
||||||
|
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeAppLogEvents
|
||||||
|
|
||||||
|
let helper = Atomic<ManagedSynchronizeAppLogEventsOperationsHelper>(value: ManagedSynchronizeAppLogEventsOperationsHelper())
|
||||||
|
|
||||||
|
let peerId = PeerId(namespace: 0, id: 0)
|
||||||
|
let _ = (postbox.transaction({ t in
|
||||||
|
t.operationLogRemoveAllEntries(peerId: peerId, tag: tag)
|
||||||
|
})).start()
|
||||||
|
|
||||||
|
let disposable = postbox.mergedOperationLogView(tag: tag, limit: 50).start(next: { view in
|
||||||
|
let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)]) in
|
||||||
|
return helper.update(view.entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
for disposable in disposeOperations {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entry, disposable) in beginOperations {
|
||||||
|
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in
|
||||||
|
if let entry = entry {
|
||||||
|
if let operation = entry.contents as? SynchronizeAppLogEventsOperation {
|
||||||
|
return synchronizeAppLogEvents(transaction: transaction, postbox: postbox, network: network, operations: [operation])
|
||||||
|
} else {
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .complete()
|
||||||
|
})
|
||||||
|
|> then(postbox.transaction { transaction -> Void in
|
||||||
|
let _ = transaction.operationLogRemoveEntry(peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex)
|
||||||
|
})
|
||||||
|
|
||||||
|
disposable.set(signal.start())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return ActionDisposable {
|
||||||
|
let disposables = helper.with { helper -> [Disposable] in
|
||||||
|
return helper.reset()
|
||||||
|
}
|
||||||
|
for disposable in disposables {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func synchronizeAppLogEvents(transaction: Transaction, postbox: Postbox, network: Network, operations: [SynchronizeAppLogEventsOperation]) -> Signal<Void, NoError> {
|
||||||
|
var events: [Api.InputAppEvent] = []
|
||||||
|
for operation in operations {
|
||||||
|
switch operation.content {
|
||||||
|
case let .add(time, type, peerId, data):
|
||||||
|
if let data = apiJson(data) {
|
||||||
|
events.append(.inputAppEvent(time: time, type: type, peer: peerId?.toInt64() ?? 0, data: data))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return network.request(Api.functions.help.saveAppLog(events: events))
|
||||||
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -93,9 +93,9 @@ func managedSynchronizePinnedChatsOperations(postbox: Postbox, network: Network,
|
|||||||
}
|
}
|
||||||
return .complete()
|
return .complete()
|
||||||
})
|
})
|
||||||
|> then(postbox.transaction { transaction -> Void in
|
|> then(postbox.transaction { transaction -> Void in
|
||||||
let _ = transaction.operationLogRemoveEntry(peerId: entry.peerId, tag: OperationLogTags.SynchronizePinnedChats, tagLocalIndex: entry.tagLocalIndex)
|
let _ = transaction.operationLogRemoveEntry(peerId: entry.peerId, tag: OperationLogTags.SynchronizePinnedChats, tagLocalIndex: entry.tagLocalIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
disposable.set((signal |> delay(2.0, queue: Queue.concurrentDefaultQueue())).start())
|
disposable.set((signal |> delay(2.0, queue: Queue.concurrentDefaultQueue())).start())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,6 +126,7 @@ public struct OperationLogTags {
|
|||||||
static let SynchronizeGroupedPeers = PeerOperationLogTag(value: 15)
|
static let SynchronizeGroupedPeers = PeerOperationLogTag(value: 15)
|
||||||
static let SynchronizeMarkAllUnseenPersonalMessages = PeerOperationLogTag(value: 16)
|
static let SynchronizeMarkAllUnseenPersonalMessages = PeerOperationLogTag(value: 16)
|
||||||
static let SynchronizeRecentlyUsedStickers = PeerOperationLogTag(value: 17)
|
static let SynchronizeRecentlyUsedStickers = PeerOperationLogTag(value: 17)
|
||||||
|
static let SynchronizeAppLogEvents = PeerOperationLogTag(value: 18)
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension PeerSummaryCounterTags {
|
public extension PeerSummaryCounterTags {
|
||||||
@ -148,6 +149,7 @@ private enum PreferencesKeyValues: Int32 {
|
|||||||
case voipConfiguration = 11
|
case voipConfiguration = 11
|
||||||
case appChangelogState = 12
|
case appChangelogState = 12
|
||||||
case localizationListState = 13
|
case localizationListState = 13
|
||||||
|
case appConfiguration = 14
|
||||||
}
|
}
|
||||||
|
|
||||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||||
@ -234,6 +236,12 @@ public struct PreferencesKeys {
|
|||||||
key.setInt32(0, value: PreferencesKeyValues.localizationListState.rawValue)
|
key.setInt32(0, value: PreferencesKeyValues.localizationListState.rawValue)
|
||||||
return key
|
return key
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
public static let appConfiguration: ValueBoxKey = {
|
||||||
|
let key = ValueBoxKey(length: 4)
|
||||||
|
key.setInt32(0, value: PreferencesKeyValues.appConfiguration.rawValue)
|
||||||
|
return key
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum SharedDataKeyValues: Int32 {
|
private enum SharedDataKeyValues: Int32 {
|
||||||
|
|||||||
@ -68,25 +68,25 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan
|
|||||||
|> mapError {_ in return UploadPeerPhotoError.generic}
|
|> mapError {_ in return UploadPeerPhotoError.generic}
|
||||||
|> mapToSignal { photo -> Signal<(UpdatePeerPhotoStatus, MediaResource?), UploadPeerPhotoError> in
|
|> mapToSignal { photo -> Signal<(UpdatePeerPhotoStatus, MediaResource?), UploadPeerPhotoError> in
|
||||||
|
|
||||||
let representations:[TelegramMediaImageRepresentation]
|
let representations: [TelegramMediaImageRepresentation]
|
||||||
switch photo {
|
switch photo {
|
||||||
case let .photo(photo: apiPhoto, users: _):
|
case let .photo(photo: apiPhoto, users: _):
|
||||||
switch apiPhoto {
|
switch apiPhoto {
|
||||||
case .photoEmpty:
|
case .photoEmpty:
|
||||||
representations = []
|
representations = []
|
||||||
case let .photo(photo):
|
case let .photo(photo):
|
||||||
var sizes = photo.sizes
|
var sizes = photo.sizes
|
||||||
if sizes.count == 3 {
|
if sizes.count == 3 {
|
||||||
sizes.remove(at: 1)
|
sizes.remove(at: 1)
|
||||||
}
|
}
|
||||||
representations = telegramMediaImageRepresentationsFromApiSizes(sizes)
|
representations = telegramMediaImageRepresentationsFromApiSizes(sizes)
|
||||||
if let resource = result.resource as? LocalFileReferenceMediaResource {
|
if let resource = result.resource as? LocalFileReferenceMediaResource {
|
||||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: resource.localFilePath)) {
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: resource.localFilePath)) {
|
||||||
for representation in representations {
|
for representation in representations {
|
||||||
postbox.mediaBox.storeResourceData(representation.resource.id, data: data)
|
postbox.mediaBox.storeResourceData(representation.resource.id, data: data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -202,7 +202,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 90
|
return 91
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
public func parseMessage(_ data: Data!) -> Any! {
|
||||||
|
|||||||
29
TelegramCore/SplitTest.swift
Normal file
29
TelegramCore/SplitTest.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import Foundation
|
||||||
|
import Postbox
|
||||||
|
|
||||||
|
public protocol SplitTestEvent: RawRepresentable where RawValue == String {
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol SplitTestConfiguration {
|
||||||
|
static var defaultValue: Self { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol SplitTest {
|
||||||
|
associatedtype Configuration: SplitTestConfiguration
|
||||||
|
associatedtype Event: SplitTestEvent
|
||||||
|
|
||||||
|
var postbox: Postbox { get }
|
||||||
|
var bucket: String? { get }
|
||||||
|
var configuration: Configuration { get }
|
||||||
|
|
||||||
|
init(postbox: Postbox, bucket: String?, configuration: Configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SplitTest {
|
||||||
|
public func addEvent(_ event: Self.Event, data: JSON = []) {
|
||||||
|
if let bucket = self.bucket {
|
||||||
|
//TODO: merge additional data
|
||||||
|
addAppLogEvent(postbox: self.postbox, time: Date().timeIntervalSince1970, type: event.rawValue, peerId: nil, data: ["bucket": bucket])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
98
TelegramCore/SynchronizeAppLogEventsOperation.swift
Normal file
98
TelegramCore/SynchronizeAppLogEventsOperation.swift
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private enum SynchronizeAppLogEventsOperationContentType: Int32 {
|
||||||
|
case add
|
||||||
|
case sync
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SynchronizeAppLogEventsOperationContent: PostboxCoding {
|
||||||
|
case add(time: Double, type: String, peerId: PeerId?, data: JSON)
|
||||||
|
case sync
|
||||||
|
|
||||||
|
init(decoder: PostboxDecoder) {
|
||||||
|
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||||
|
case SynchronizeAppLogEventsOperationContentType.add.rawValue:
|
||||||
|
var peerId: PeerId?
|
||||||
|
if let id = decoder.decodeOptionalInt64ForKey("p") {
|
||||||
|
peerId = PeerId(id)
|
||||||
|
}
|
||||||
|
self = .add(time: decoder.decodeDoubleForKey("tm", orElse: 0.0), type: decoder.decodeStringForKey("t", orElse: ""), peerId: peerId, data: decoder.decodeObjectForKey("d", decoder: { JSON(decoder: $0) }) as! JSON)
|
||||||
|
case SynchronizeAppLogEventsOperationContentType.sync.rawValue:
|
||||||
|
self = .sync
|
||||||
|
default:
|
||||||
|
assertionFailure()
|
||||||
|
self = .sync
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ encoder: PostboxEncoder) {
|
||||||
|
switch self {
|
||||||
|
case let .add(time, type, peerId, data):
|
||||||
|
encoder.encodeInt32(SynchronizeAppLogEventsOperationContentType.add.rawValue, forKey: "r")
|
||||||
|
encoder.encodeDouble(time, forKey: "tm")
|
||||||
|
encoder.encodeString(type, forKey: "t")
|
||||||
|
if let peerId = peerId {
|
||||||
|
encoder.encodeInt64(peerId.toInt64(), forKey: "p")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "p")
|
||||||
|
}
|
||||||
|
encoder.encodeObject(data, forKey: "d")
|
||||||
|
case .sync:
|
||||||
|
encoder.encodeInt32(SynchronizeAppLogEventsOperationContentType.sync.rawValue, forKey: "r")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class SynchronizeAppLogEventsOperation: PostboxCoding {
|
||||||
|
let content: SynchronizeAppLogEventsOperationContent
|
||||||
|
|
||||||
|
init(content: SynchronizeAppLogEventsOperationContent) {
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
|
|
||||||
|
init(decoder: PostboxDecoder) {
|
||||||
|
self.content = decoder.decodeObjectForKey("c", decoder: { SynchronizeAppLogEventsOperationContent(decoder: $0) }) as! SynchronizeAppLogEventsOperationContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeObject(self.content, forKey: "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func addAppLogEvent(postbox: Postbox, time: Double, type: String, peerId: PeerId?, data: JSON) {
|
||||||
|
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeAppLogEvents
|
||||||
|
let peerId = PeerId(namespace: 0, id: 0)
|
||||||
|
let _ = (postbox.transaction { transaction in
|
||||||
|
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeAppLogEventsOperation(content: .add(time: time, type: type, peerId: peerId, data: data)))
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func invokeAppLogEventsSynchronization(postbox: Postbox) {
|
||||||
|
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeAppLogEvents
|
||||||
|
let peerId = PeerId(namespace: 0, id: 0)
|
||||||
|
|
||||||
|
let _ = (postbox.transaction { transaction in
|
||||||
|
var topOperation: (SynchronizeSavedStickersOperation, Int32)?
|
||||||
|
transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
|
||||||
|
if let operation = entry.contents as? SynchronizeSavedStickersOperation, case .sync = operation.content {
|
||||||
|
topOperation = (operation, entry.tagLocalIndex)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if let (_, topLocalIndex) = topOperation {
|
||||||
|
let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeAppLogEventsOperation(content: .sync))
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user