├── .gitignore
├── TelegramCore.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── TelegramCore.xcscheme
├── TelegramCore
├── AccessSecureId.swift
├── Account.swift
├── AccountEnvironmentAttribute.swift
├── AccountIntermediateState.swift
├── AccountManager.swift
├── AccountSortOrderAttribute.swift
├── AccountState.swift
├── AccountStateManagementUtils.swift
├── AccountStateManager.swift
├── AccountStateReset.swift
├── AccountViewTracker.swift
├── ActiveSessionsContext.swift
├── AddPeerMember.swift
├── AddressNames.swift
├── Api0.swift
├── Api1.swift
├── Api2.swift
├── Api3.swift
├── ApiGroupOrChannel.swift
├── ApiUtils.swift
├── AppChangelog.swift
├── AppChangelogState.swift
├── AppConfiguration.swift
├── ApplyMaxReadIndexInteractively.swift
├── ApplyUpdateMessage.swift
├── ArchivedStickerPacks.swift
├── ArchivedStickerPacksInfo.swift
├── AuthorSignatureMessageAttribute.swift
├── Authorization.swift
├── AutodownloadSettings.swift
├── AutoremoveTimeoutMessageAttribute.swift
├── BlockedPeers.swift
├── BlockedPeersContext.swift
├── BotInfo.swift
├── BotPaymentForm.swift
├── Buffer.swift
├── CacheStorageSettings.swift
├── CachedChannelData.swift
├── CachedChannelParticipants.swift
├── CachedGroupData.swift
├── CachedGroupParticipants.swift
├── CachedSentMediaReferences.swift
├── CachedStickerPack.swift
├── CachedUserData.swift
├── CallSessionManager.swift
├── CanSendMessagesToPeer.swift
├── CancelAccountReset.swift
├── ChangeAccountPhoneNumber.swift
├── ChangePeerNotificationSettings.swift
├── ChannelAdminEventLogContext.swift
├── ChannelAdminEventLogs.swift
├── ChannelAdmins.swift
├── ChannelBlacklist.swift
├── ChannelCreation.swift
├── ChannelHistoryAvailabilitySettings.swift
├── ChannelMembers.swift
├── ChannelMessageStateVersionAttribute.swift
├── ChannelParticipants.swift
├── ChannelState.swift
├── ChannelStats.swift
├── ChatContextResult.swift
├── ChatHistoryPreloadManager.swift
├── ChatOnlineMembers.swift
├── CheckPeerChatServiceActions.swift
├── ClearCloudDrafts.swift
├── CloudChatRemoveMessagesOperation.swift
├── CloudFileMediaResource.swift
├── CloudMediaResourceParameters.swift
├── CollectCacheUsageStats.swift
├── Config
│ └── TelegramCore.xcconfig
├── ConfirmTwoStepRecoveryEmail.swift
├── ConsumableContentMessageAttribute.swift
├── ConsumablePersonalMentionMessageAttribute.swift
├── ConsumePersonalMessageAction.swift
├── ContactManagement.swift
├── ContactSyncManager.swift
├── ContactsSettings.swift
├── ContentPrivacySettings.swift
├── ContentRequiresValidationMessageAttribute.swift
├── ConvertGroupToSupergroup.swift
├── CoreSettings.swift
├── CreateGroup.swift
├── CreateSecretChat.swift
├── Crypto.h
├── Crypto.m
├── DecryptedResourceData.swift
├── DeepLinkInfo.swift
├── DeleteMessages.swift
├── DeleteMessagesInteractively.swift
├── DeserializeFunctionResponse.swift
├── DeviceContact.swift
├── Download.swift
├── EarliestUnseenPersonalMentionMessage.swift
├── EditedMessageAttribute.swift
├── Either.swift
├── EmojiKeywords.swift
├── EncryptedMediaResource.swift
├── EnqueueMessage.swift
├── ExportMessageLink.swift
├── ExportedInvitation.swift
├── FeaturedStickerPack.swift
├── Fetch.swift
├── FetchChatList.swift
├── FetchHttpResource.swift
├── FetchSecretFileResource.swift
├── FetchedMediaResource.swift
├── FindChannelById.swift
├── ForwardGame.swift
├── ForwardSourceInfoAttribute.swift
├── GlobalNotificationSettings.swift
├── GlobalTelegramCoreConfiguration.swift
├── GrantSecureIdAccess.swift
├── GroupFeedPeers.swift
├── GroupReturnAndLeft.swift
├── GroupsInCommon.swift
├── HistoryViewChannelStateValidation.swift
├── Holes.swift
├── ImageRepresentationsUtils.swift
├── ImportContact.swift
├── Info.plist
├── InitializeAccountAfterLogin.swift
├── InlineBotMessageAttribute.swift
├── InstallInteractiveReadMessagesAction.swift
├── InstantPage.swift
├── InteractivePhoneFormatter.swift
├── InvitationLinks.swift
├── JSON.swift
├── JoinChannel.swift
├── JoinLink.swift
├── LimitsConfiguration.swift
├── LoadMessagesIfNecessary.swift
├── LoadedPeer.swift
├── LoadedPeerFromMessage.swift
├── LoadedStickerPack.swift
├── Localization.swift
├── LocalizationInfo.swift
├── LocalizationListState.swift
├── LocalizationPreview.swift
├── LocalizationSettings.swift
├── Localizations.swift
├── Log.swift
├── LoggedOutAccountAttribute.swift
├── LoggingSettings.swift
├── MD5.swift
├── ManageChannelDiscussionGroup.swift
├── ManagedAccountPresence.swift
├── ManagedAppConfigurationUpdates.swift
├── ManagedAutodownloadSettingsUpdates.swift
├── ManagedAutoremoveMessageOperations.swift
├── ManagedChatListHoles.swift
├── ManagedCloudChatRemoveMessagesOperations.swift
├── ManagedConfigurationUpdates.swift
├── ManagedConsumePersonalMessagesActions.swift
├── ManagedGlobalNotificationSettings.swift
├── ManagedLocalInputActivities.swift
├── ManagedLocalizationUpdatesOperations.swift
├── ManagedMessageHistoryHoles.swift
├── ManagedNotificationSettingsBehaviors.swift
├── ManagedPendingPeerNotificationSettings.swift
├── ManagedProxyInfoUpdates.swift
├── ManagedRecentStickers.swift
├── ManagedSecretChatOutgoingOperations.swift
├── ManagedServiceViews.swift
├── ManagedSynchronizeAppLogEventsOperations.swift
├── ManagedSynchronizeChatInputStateOperations.swift
├── ManagedSynchronizeConsumeMessageContentsOperations.swift
├── ManagedSynchronizeEmojiKeywordsOperations.swift
├── ManagedSynchronizeGroupMessageStats.swift
├── ManagedSynchronizeGroupedPeersOperations.swift
├── ManagedSynchronizeInstalledStickerPacksOperations.swift
├── ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift
├── ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift
├── ManagedSynchronizePeerReadStates.swift
├── ManagedSynchronizePinnedChatsOperations.swift
├── ManagedSynchronizeRecentlyUsedMediaOperations.swift
├── ManagedSynchronizeSavedGifsOperations.swift
├── ManagedSynchronizeSavedStickersOperations.swift
├── ManagedVoipConfigurationUpdates.swift
├── MarkAllChatsAsRead.swift
├── MarkMessageContentAsConsumedInteractively.swift
├── MediaResourceApiUtils.swift
├── MediaResourceNetworkStatsTag.swift
├── MemoryBufferExtensions.swift
├── MessageMediaPreuploadManager.swift
├── MessageUtils.swift
├── MonotonicTime.h
├── MonotonicTime.m
├── MonotonicTime.swift
├── MultipartFetch.swift
├── MultipartUpload.swift
├── MultipeerManager.swift
├── MultiplexedRequestManager.swift
├── Namespaces.swift
├── Network.swift
├── NetworkLogging.h
├── NetworkLogging.m
├── NetworkSettings.swift
├── NetworkType.swift
├── NotificationAutolockReportManager.swift
├── NotificationExceptionsList.swift
├── NotificationInfoMessageAttribute.swift
├── OutgoingChatContextResultMessageAttribute.swift
├── OutgoingContentInfoMessageAttribute.swift
├── OutgoingMessageInfoAttribute.swift
├── OutgoingMessageWithChatContextResult.swift
├── PeerAccessRestrictionInfo.swift
├── PeerAdmins.swift
├── PeerCommands.swift
├── PeerGroupMessageStateVersionAttribute.swift
├── PeerInputActivity.swift
├── PeerInputActivityManager.swift
├── PeerLiveLocationsContext.swift
├── PeerParticipants.swift
├── PeerPhotoUpdater.swift
├── PeerReportStatus.swift
├── PeerSpecificStickerPack.swift
├── PeerUtils.swift
├── PendingMessageManager.swift
├── PendingMessageUploadedContent.swift
├── PhoneNumber.swift
├── PhoneNumbers.swift
├── Polls.swift
├── PrivacySettings.swift
├── ProcessSecretChatIncomingDecryptedOperations.swift
├── ProcessSecretChatIncomingEncryptedOperations.swift
├── ProxyServersStatuses.swift
├── ProxySettings.swift
├── Random.swift
├── RateCall.swift
├── Reachability.h
├── Reachability.m
├── RecentAccountSession.swift
├── RecentAccountSessions.swift
├── RecentMediaItem.swift
├── RecentPeerItem.swift
├── RecentPeers.swift
├── RecentWebSessions.swift
├── RecentlySearchedPeerIds.swift
├── RecentlyUsedHashtags.swift
├── Regex.swift
├── RegisterNotificationToken.swift
├── RegularChatState.swift
├── RemoteStorageConfiguration.swift
├── RemovePeerChat.swift
├── RemovePeerMember.swift
├── ReplyMarkupMessageAttribute.swift
├── ReplyMessageAttribute.swift
├── ReportPeer.swift
├── RequestChatContextResults.swift
├── RequestEditMessage.swift
├── RequestMessageActionCallback.swift
├── RequestPhoneNumber.swift
├── RequestSecureIdForm.swift
├── RequestStartBot.swift
├── RequestUserPhotos.swift
├── ResolvePeerByName.swift
├── RichText.swift
├── SaveSecureIdValue.swift
├── SavedStickerItem.swift
├── SearchBotsConfiguration.swift
├── SearchGroupMembers.swift
├── SearchMessages.swift
├── SearchPeers.swift
├── SearchStickers.swift
├── SecretApiLayer46.swift
├── SecretApiLayer73.swift
├── SecretApiLayer8.swift
├── SecretChatEncryption.swift
├── SecretChatEncryptionConfig.swift
├── SecretChatFileReference.swift
├── SecretChatIncomingDecryptedOperation.swift
├── SecretChatIncomingEncryptedOperation.swift
├── SecretChatKeychain.swift
├── SecretChatLayerNegotiation.swift
├── SecretChatOutgoingOperation.swift
├── SecretChatRekeySession.swift
├── SecretChatState.swift
├── SecureFileMediaResource.swift
├── SecureIdAddressValue.swift
├── SecureIdBankStatementValue.swift
├── SecureIdConfiguration.swift
├── SecureIdDataTypes.swift
├── SecureIdDriversLicenseValue.swift
├── SecureIdEmailValue.swift
├── SecureIdForm.swift
├── SecureIdIDCardValue.swift
├── SecureIdInternalPassportValue.swift
├── SecureIdPadding.swift
├── SecureIdPassportRegistrationValue.swift
├── SecureIdPassportValue.swift
├── SecureIdPersonalDetailsValue.swift
├── SecureIdPhoneValue.swift
├── SecureIdRentalAgreementValue.swift
├── SecureIdTemporaryRegistrationValue.swift
├── SecureIdUtilityBillValue.swift
├── SecureIdValue.swift
├── SecureIdValueAccessContext.swift
├── SecureIdValueContentError.swift
├── SecureIdVerificationDocumentReference.swift
├── Serialization.swift
├── SetSecretChatMessageAutoremoveTimeoutInteractively.swift
├── SingleMessageView.swift
├── SourceReferenceMessageAttribute.swift
├── SplitTest.swift
├── StandaloneSendMessage.swift
├── StandaloneUploadedMedia.swift
├── StickerManagement.swift
├── StickerPack.swift
├── StickerPackInteractiveOperations.swift
├── StickerSetInstallation.swift
├── StoreMessage_Telegram.swift
├── StringFormat.swift
├── SuggestedLocalizationEntry.swift
├── SupportPeerId.swift
├── SynchronizeAppLogEventsOperation.swift
├── SynchronizeChatInputStateOperation.swift
├── SynchronizeConsumeMessageContentsOperation.swift
├── SynchronizeEmojiKeywordsOperation.swift
├── SynchronizeGroupedPeersOperation.swift
├── SynchronizeInstalledStickerPacksOperations.swift
├── SynchronizeLocalizationUpdatesOperation.swift
├── SynchronizeMarkAllUnseenPersonalMessagesOperation.swift
├── SynchronizePeerReadState.swift
├── SynchronizePinnedChatsOperation.swift
├── SynchronizeRecentlyUsedMediaOperations.swift
├── SynchronizeSavedGifsOperation.swift
├── SynchronizeSavedStickersOperation.swift
├── SynchronizeableChatInputState.swift
├── TelegramChannel.swift
├── TelegramChannelAdminRights.swift
├── TelegramChannelBannedRights.swift
├── TelegramCore.h
├── TelegramCoreIncludes.h
├── TelegramCorePrivate
│ └── module.modulemap
├── TelegramDeviceContactImportInfo.swift
├── TelegramGroup.swift
├── TelegramMediaAction.swift
├── TelegramMediaContact.swift
├── TelegramMediaExpiredContent.swift
├── TelegramMediaFile.swift
├── TelegramMediaGame.swift
├── TelegramMediaImage.swift
├── TelegramMediaInvoice.swift
├── TelegramMediaMap.swift
├── TelegramMediaPoll.swift
├── TelegramMediaResource.swift
├── TelegramMediaWebDocument.swift
├── TelegramMediaWebpage.swift
├── TelegramPeerNotificationSettings.swift
├── TelegramSecretChat.swift
├── TelegramUser.swift
├── TelegramUserPresence.swift
├── TeleramMediaUnsupported.swift
├── TermsOfService.swift
├── TextEntitiesMessageAttribute.swift
├── ToggleChannelSignatures.swift
├── TogglePeerChatPinned.swift
├── TwoStepVerification.swift
├── Unixtime.swift
├── UpdateAccountPeerName.swift
├── UpdateCachedPeerData.swift
├── UpdateContactName.swift
├── UpdateGroup.swift
├── UpdateGroupSpecificStickerset.swift
├── UpdateMessageMedia.swift
├── UpdateMessageService.swift
├── UpdatePeerChatInterfaceState.swift
├── UpdatePeerInfo.swift
├── UpdatePeers.swift
├── UpdatePinnedMessage.swift
├── UpdateSecretChat.swift
├── UpdatedAccountPrivacySettings.swift
├── UpdatesApiUtils.swift
├── UploadSecureIdFile.swift
├── VerifySecureIdValue.swift
├── ViewCountMessageAttribute.swift
├── VoipConfiguration.swift
├── Wallpaper.swift
├── Wallpapers.swift
├── WebpagePreview.swift
├── module.private-mac.modulemap
└── module.private.modulemap
├── TelegramCoreMac
├── Info.plist
└── TelegramCoreMac.h
├── TelegramCoreTests
├── Info.plist
└── TelegramCoreTests.m
└── third-party
└── libphonenumber-iOS
├── NBAsYouTypeFormatter.h
├── NBAsYouTypeFormatter.m
├── NBMetadataCore.h
├── NBMetadataCore.m
├── NBMetadataCoreMapper.h
├── NBMetadataCoreMapper.m
├── NBMetadataCoreTest.h
├── NBMetadataCoreTest.m
├── NBMetadataCoreTestMapper.h
├── NBMetadataCoreTestMapper.m
├── NBMetadataHelper.h
├── NBMetadataHelper.m
├── NBNumberFormat.h
├── NBNumberFormat.m
├── NBPhoneMetaData.h
├── NBPhoneMetaData.m
├── NBPhoneMetaDataGenerator.h
├── NBPhoneMetaDataGenerator.m
├── NBPhoneNumber.h
├── NBPhoneNumber.m
├── NBPhoneNumberDefines.h
├── NBPhoneNumberDefines.m
├── NBPhoneNumberDesc.h
├── NBPhoneNumberDesc.m
├── NBPhoneNumberUtil.h
└── NBPhoneNumberUtil.m
/.gitignore:
--------------------------------------------------------------------------------
1 | fastlane/README.md
2 | fastlane/report.xml
3 | fastlane/test_output/*
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.xcscmblueprint
15 | *.moved-aside
16 | DerivedData
17 | *.hmap
18 | *.ipa
19 | *.xcuserstate
20 | .DS_Store
21 | *.dSYM
22 | *.dSYM.zip
23 | *.ipa
24 | */xcuserdata/*
25 |
--------------------------------------------------------------------------------
/TelegramCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TelegramCore/AccountEnvironmentAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public enum AccountEnvironment: Int32 {
9 | case production = 0
10 | case test = 1
11 | }
12 |
13 | public final class AccountEnvironmentAttribute: AccountRecordAttribute {
14 | public let environment: AccountEnvironment
15 |
16 | public init(environment: AccountEnvironment) {
17 | self.environment = environment
18 | }
19 |
20 | public init(decoder: PostboxDecoder) {
21 | self.environment = AccountEnvironment(rawValue: decoder.decodeInt32ForKey("environment", orElse: 0)) ?? .production
22 | }
23 |
24 | public func encode(_ encoder: PostboxEncoder) {
25 | encoder.encodeInt32(self.environment.rawValue, forKey: "environment")
26 | }
27 |
28 | public func isEqual(to: AccountRecordAttribute) -> Bool {
29 | guard let to = to as? AccountEnvironmentAttribute else {
30 | return false
31 | }
32 | if self.environment != to.environment {
33 | return false
34 | }
35 | return true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/TelegramCore/AccountSortOrderAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class AccountSortOrderAttribute: AccountRecordAttribute {
9 | public let order: Int32
10 |
11 | public init(order: Int32) {
12 | self.order = order
13 | }
14 |
15 | public init(decoder: PostboxDecoder) {
16 | self.order = decoder.decodeInt32ForKey("order", orElse: 0)
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt32(self.order, forKey: "order")
21 | }
22 |
23 | public func isEqual(to: AccountRecordAttribute) -> Bool {
24 | guard let to = to as? AccountSortOrderAttribute else {
25 | return false
26 | }
27 | if self.order != to.order {
28 | return false
29 | }
30 | return true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/TelegramCore/AppChangelog.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | func managedAppChangelog(postbox: Postbox, network: Network, stateManager: AccountStateManager, appVersion: String) -> Signal {
13 | return stateManager.pollStateUpdateCompletion()
14 | |> take(1)
15 | |> mapToSignal { _ -> Signal in
16 | return postbox.transaction { transaction -> AppChangelogState in
17 | return transaction.getPreferencesEntry(key: PreferencesKeys.appChangelogState) as? AppChangelogState ?? AppChangelogState.default
18 | }
19 | |> mapToSignal { appChangelogState -> Signal in
20 | let appChangelogState = appChangelogState
21 | if appChangelogState.checkedVersion == appVersion {
22 | return .complete()
23 | }
24 | let previousVersion = appChangelogState.previousVersion
25 | return network.request(Api.functions.help.getAppChangelog(prevAppVersion: previousVersion))
26 | |> map(Optional.init)
27 | |> `catch` { _ -> Signal in
28 | return .single(nil)
29 | }
30 | |> mapToSignal { updates -> Signal in
31 | if let updates = updates {
32 | stateManager.addUpdates(updates)
33 | }
34 |
35 | return postbox.transaction { transaction in
36 | updateAppChangelogState(transaction: transaction, { state in
37 | var state = state
38 | state.checkedVersion = appVersion
39 | state.previousVersion = appVersion
40 | return state
41 | })
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/TelegramCore/AppChangelogState.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | struct AppChangelogState: PreferencesEntry, Equatable {
13 | var checkedVersion: String
14 | var previousVersion: String
15 |
16 | static var `default` = AppChangelogState(checkedVersion: "", previousVersion: "5.0.8")
17 |
18 | init(checkedVersion: String, previousVersion: String) {
19 | self.checkedVersion = checkedVersion
20 | self.previousVersion = previousVersion
21 | }
22 |
23 | init(decoder: PostboxDecoder) {
24 | self.checkedVersion = decoder.decodeStringForKey("checkedVersion", orElse: "")
25 | self.previousVersion = decoder.decodeStringForKey("previousVersion", orElse: "")
26 | }
27 |
28 | func encode(_ encoder: PostboxEncoder) {
29 | encoder.encodeString(self.checkedVersion, forKey: "checkedVersion")
30 | encoder.encodeString(self.previousVersion, forKey: "previousVersion")
31 | }
32 |
33 | func isEqual(to: PreferencesEntry) -> Bool {
34 | guard let to = to as? AppChangelogState else {
35 | return false
36 | }
37 |
38 | return self == to
39 | }
40 | }
41 |
42 | func updateAppChangelogState(transaction: Transaction, _ f: @escaping (AppChangelogState) -> AppChangelogState) {
43 | transaction.updatePreferencesEntry(key: PreferencesKeys.appChangelogState, { current in
44 | return f((current as? AppChangelogState) ?? AppChangelogState.default)
45 | })
46 | }
47 |
--------------------------------------------------------------------------------
/TelegramCore/AppConfiguration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct AppConfiguration: PreferencesEntry, Equatable {
9 | public var data: JSON?
10 |
11 | public static var defaultValue: AppConfiguration {
12 | return AppConfiguration(data: nil)
13 | }
14 |
15 | init(data: JSON?) {
16 | self.data = data
17 | }
18 |
19 | public init(decoder: PostboxDecoder) {
20 | self.data = decoder.decodeObjectForKey("data", decoder: { JSON(decoder: $0) }) as? JSON
21 | }
22 |
23 | public func encode(_ encoder: PostboxEncoder) {
24 | if let data = self.data {
25 | encoder.encodeObject(data, forKey: "data")
26 | } else {
27 | encoder.encodeNil(forKey: "data")
28 | }
29 | }
30 |
31 | public func isEqual(to: PreferencesEntry) -> Bool {
32 | guard let to = to as? AppConfiguration else {
33 | return false
34 | }
35 | return self == to
36 | }
37 | }
38 |
39 | public func currentAppConfiguration(transaction: Transaction) -> AppConfiguration {
40 | if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration) as? AppConfiguration {
41 | return entry
42 | } else {
43 | return AppConfiguration.defaultValue
44 | }
45 | }
46 |
47 | func updateAppConfiguration(transaction: Transaction, _ f: (AppConfiguration) -> AppConfiguration) {
48 | let current = currentAppConfiguration(transaction: transaction)
49 | let updated = f(current)
50 | if updated != current {
51 | transaction.setPreferencesEntry(key: PreferencesKeys.appConfiguration, value: updated)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/TelegramCore/ArchivedStickerPacks.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public enum ArchivedStickerPacksNamespace: Int32 {
11 | case stickers = 0
12 | case masks = 1
13 | }
14 |
15 | public final class ArchivedStickerPackItem {
16 | public let info: StickerPackCollectionInfo
17 | public let topItems: [StickerPackItem]
18 |
19 | public init(info: StickerPackCollectionInfo, topItems: [StickerPackItem]) {
20 | self.info = info
21 | self.topItems = topItems
22 | }
23 | }
24 |
25 | public func archivedStickerPacks(account: Account, namespace: ArchivedStickerPacksNamespace = .stickers) -> Signal<[ArchivedStickerPackItem], NoError> {
26 | var flags: Int32 = 0
27 | if case .masks = namespace {
28 | flags |= 1 << 0
29 | }
30 | return account.network.request(Api.functions.messages.getArchivedStickers(flags: flags, offsetId: 0, limit: 100))
31 | |> map { result -> [ArchivedStickerPackItem] in
32 | var archivedItems: [ArchivedStickerPackItem] = []
33 | switch result {
34 | case let .archivedStickers(_, sets):
35 | for set in sets {
36 | let (info, items) = parsePreviewStickerSet(set)
37 | archivedItems.append(ArchivedStickerPackItem(info: info, topItems: items))
38 | }
39 | }
40 | return archivedItems
41 | } |> `catch` { _ in
42 | return .single([])
43 | }
44 | }
45 |
46 | public func removeArchivedStickerPack(account: Account, info: StickerPackCollectionInfo) -> Signal {
47 | return account.network.request(Api.functions.messages.uninstallStickerSet(stickerset: Api.InputStickerSet.inputStickerSetID(id: info.id.id, accessHash: info.accessHash)))
48 | |> `catch` { _ -> Signal in
49 | return .single(.boolFalse)
50 | }
51 | |> mapToSignal { _ -> Signal in
52 | return .complete()
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/TelegramCore/ArchivedStickerPacksInfo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct ArchivedStickerPacksInfoId {
9 | public let rawValue: MemoryBuffer
10 | public let id: Int32
11 |
12 | init(_ rawValue: MemoryBuffer) {
13 | self.rawValue = rawValue
14 | assert(rawValue.length == 4)
15 | var idValue: Int32 = 0
16 | memcpy(&idValue, rawValue.memory, 4)
17 | self.id = idValue
18 | }
19 |
20 | init(_ id: Int32) {
21 | self.id = id
22 | var idValue: Int32 = id
23 | self.rawValue = MemoryBuffer(memory: malloc(4)!, capacity: 4, length: 4, freeWhenDone: true)
24 | memcpy(self.rawValue.memory, &idValue, 4)
25 | }
26 | }
27 |
28 | public final class ArchivedStickerPacksInfo: OrderedItemListEntryContents {
29 | public let count: Int32
30 |
31 | init(count: Int32) {
32 | self.count = count
33 | }
34 |
35 | public init(decoder: PostboxDecoder) {
36 | self.count = decoder.decodeInt32ForKey("c", orElse: 0)
37 | }
38 |
39 | public func encode(_ encoder: PostboxEncoder) {
40 | encoder.encodeInt32(self.count, forKey: "c")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/TelegramCore/AuthorSignatureMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class AuthorSignatureMessageAttribute: MessageAttribute {
9 | public let signature: String
10 |
11 | public let associatedPeerIds: [PeerId] = []
12 |
13 | init(signature: String) {
14 | self.signature = signature
15 | }
16 |
17 | required public init(decoder: PostboxDecoder) {
18 | self.signature = decoder.decodeStringForKey("s", orElse: "")
19 | }
20 |
21 | public func encode(_ encoder: PostboxEncoder) {
22 | encoder.encodeString(self.signature, forKey: "s")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/TelegramCore/AutoremoveTimeoutMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public class AutoremoveTimeoutMessageAttribute: MessageAttribute {
13 | public let timeout: Int32
14 | public let countdownBeginTime: Int32?
15 |
16 | public var associatedMessageIds: [MessageId] = []
17 |
18 | public init(timeout: Int32, countdownBeginTime: Int32?) {
19 | self.timeout = timeout
20 | self.countdownBeginTime = countdownBeginTime
21 | }
22 |
23 | required public init(decoder: PostboxDecoder) {
24 | self.timeout = decoder.decodeInt32ForKey("t", orElse: 0)
25 | self.countdownBeginTime = decoder.decodeOptionalInt32ForKey("c")
26 | }
27 |
28 | public func encode(_ encoder: PostboxEncoder) {
29 | encoder.encodeInt32(self.timeout, forKey: "t")
30 | if let countdownBeginTime = self.countdownBeginTime {
31 | encoder.encodeInt32(countdownBeginTime, forKey: "c")
32 | } else {
33 | encoder.encodeNil(forKey: "c")
34 | }
35 | }
36 | }
37 |
38 | public extension Message {
39 | public var containsSecretMedia: Bool {
40 | var found = false
41 | for attribute in self.attributes {
42 | if let attribute = attribute as? AutoremoveTimeoutMessageAttribute {
43 | if attribute.timeout > 1 * 60 {
44 | return false
45 | }
46 | found = true
47 | break
48 | }
49 | }
50 |
51 | if !found {
52 | return false
53 | }
54 |
55 | for media in self.media {
56 | switch media {
57 | case _ as TelegramMediaImage:
58 | return true
59 | case let file as TelegramMediaFile:
60 | if file.isVideo || file.isAnimated || file.isVoice {
61 | return true
62 | }
63 | default:
64 | break
65 | }
66 | }
67 |
68 | return false
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/TelegramCore/BotInfo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct BotCommand: PostboxCoding, Equatable {
9 | public let text: String
10 | public let description: String
11 |
12 | init(text: String, description: String) {
13 | self.text = text
14 | self.description = description
15 | }
16 |
17 | public init(decoder: PostboxDecoder) {
18 | self.text = decoder.decodeStringForKey("t", orElse: "")
19 | self.description = decoder.decodeStringForKey("d", orElse: "")
20 | }
21 |
22 | public func encode(_ encoder: PostboxEncoder) {
23 | encoder.encodeString(self.text, forKey: "t")
24 | encoder.encodeString(self.description, forKey: "d")
25 | }
26 |
27 | public static func ==(lhs: BotCommand, rhs: BotCommand) -> Bool {
28 | return lhs.text == rhs.text && lhs.description == rhs.description
29 | }
30 | }
31 |
32 | public final class BotInfo: PostboxCoding, Equatable {
33 | public let description: String
34 | public let commands: [BotCommand]
35 |
36 | init(description: String, commands: [BotCommand]) {
37 | self.description = description
38 | self.commands = commands
39 | }
40 |
41 | public init(decoder: PostboxDecoder) {
42 | self.description = decoder.decodeStringForKey("d", orElse: "")
43 | self.commands = decoder.decodeObjectArrayWithDecoderForKey("c")
44 | }
45 |
46 | public func encode(_ encoder: PostboxEncoder) {
47 | encoder.encodeString(self.description, forKey: "d")
48 | encoder.encodeObjectArray(self.commands, forKey: "c")
49 | }
50 |
51 | public static func ==(lhs: BotInfo, rhs: BotInfo) -> Bool {
52 | return lhs.description == rhs.description && lhs.commands == rhs.commands
53 | }
54 | }
55 |
56 | extension BotInfo {
57 | convenience init(apiBotInfo: Api.BotInfo) {
58 | switch apiBotInfo {
59 | case let .botInfo(_, description, commands):
60 | self.init(description: description, commands: commands.map { command in
61 | switch command {
62 | case let .botCommand(command, description):
63 | return BotCommand(text: command, description: description)
64 | }
65 | })
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/TelegramCore/CacheStorageSettings.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public struct CacheStorageSettings: PreferencesEntry, Equatable {
11 | public let defaultCacheStorageTimeout: Int32
12 |
13 | public static var defaultSettings: CacheStorageSettings {
14 | return CacheStorageSettings(defaultCacheStorageTimeout: Int32.max)
15 | }
16 |
17 | init(defaultCacheStorageTimeout: Int32) {
18 | self.defaultCacheStorageTimeout = defaultCacheStorageTimeout
19 | }
20 |
21 | public init(decoder: PostboxDecoder) {
22 | self.defaultCacheStorageTimeout = decoder.decodeInt32ForKey("dt", orElse: 0)
23 | }
24 |
25 | public func encode(_ encoder: PostboxEncoder) {
26 | encoder.encodeInt32(self.defaultCacheStorageTimeout, forKey: "dt")
27 | }
28 |
29 | public func isEqual(to: PreferencesEntry) -> Bool {
30 | if let to = to as? CacheStorageSettings {
31 | return self == to
32 | } else {
33 | return false
34 | }
35 | }
36 |
37 | public static func ==(lhs: CacheStorageSettings, rhs: CacheStorageSettings) -> Bool {
38 | return lhs.defaultCacheStorageTimeout == rhs.defaultCacheStorageTimeout
39 | }
40 |
41 | public func withUpdatedDefaultCacheStorageTimeout(_ defaultCacheStorageTimeout: Int32) -> CacheStorageSettings {
42 | return CacheStorageSettings(defaultCacheStorageTimeout: defaultCacheStorageTimeout)
43 | }
44 | }
45 |
46 | public func updateCacheStorageSettingsInteractively(accountManager: AccountManager, _ f: @escaping (CacheStorageSettings) -> CacheStorageSettings) -> Signal {
47 | return accountManager.transaction { transaction -> Void in
48 | transaction.updateSharedData(SharedDataKeys.cacheStorageSettings, { entry in
49 | let currentSettings: CacheStorageSettings
50 | if let entry = entry as? CacheStorageSettings {
51 | currentSettings = entry
52 | } else {
53 | currentSettings = CacheStorageSettings.defaultSettings
54 | }
55 | return f(currentSettings)
56 | })
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/TelegramCore/CachedSentMediaReferences.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private let cachedSentMediaCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10000, highWaterItemCount: 20000)
11 |
12 | enum CachedSentMediaReferenceKey {
13 | case image(hash: Data)
14 | case file(hash: Data)
15 |
16 | var key: ValueBoxKey {
17 | switch self {
18 | case let .image(hash):
19 | let result = ValueBoxKey(length: 1 + hash.count)
20 | result.setUInt8(0, value: 0)
21 | hash.withUnsafeBytes { (bytes: UnsafePointer) -> Void in
22 | memcpy(result.memory.advanced(by: 1), bytes, hash.count)
23 | }
24 | return result
25 | case let .file(hash):
26 | let result = ValueBoxKey(length: 1 + hash.count)
27 | result.setUInt8(0, value: 1)
28 | hash.withUnsafeBytes { (bytes: UnsafePointer) -> Void in
29 | memcpy(result.memory.advanced(by: 1), bytes, hash.count)
30 | }
31 | return result
32 | }
33 | }
34 | }
35 |
36 | func cachedSentMediaReference(postbox: Postbox, key: CachedSentMediaReferenceKey) -> Signal {
37 | return postbox.transaction { transaction -> Media? in
38 | return transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key)) as? Media
39 | }
40 | }
41 |
42 | func storeCachedSentMediaReference(transaction: Transaction, key: CachedSentMediaReferenceKey, media: Media) {
43 | transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key), entry: media, collectionSpec: cachedSentMediaCollectionSpec)
44 | }
45 |
--------------------------------------------------------------------------------
/TelegramCore/CanSendMessagesToPeer.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public func canSendMessagesToPeer(_ peer: Peer) -> Bool {
9 | if peer is TelegramUser || peer is TelegramGroup {
10 | return !peer.isDeleted
11 | } else if let peer = peer as? TelegramSecretChat {
12 | return peer.embeddedState == .active
13 | } else if let peer = peer as? TelegramChannel {
14 | return peer.hasPermission(.sendMessages)
15 | } else {
16 | return false
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/TelegramCore/ChannelHistoryAvailabilitySettings.swift:
--------------------------------------------------------------------------------
1 | #if os(macOS)
2 | import PostboxMac
3 | import SwiftSignalKitMac
4 | #else
5 | import Postbox
6 | import SwiftSignalKit
7 | #endif
8 |
9 | public enum ChannelHistoryAvailabilityError {
10 | case generic
11 | case hasNotPermissions
12 | }
13 |
14 | public func updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, historyAvailableForNewMembers: Bool) -> Signal {
15 | return postbox.transaction { transaction -> Peer? in
16 | return transaction.getPeer(peerId)
17 | }
18 | |> introduceError(ChannelHistoryAvailabilityError.self)
19 | |> mapToSignal { peer in
20 |
21 | guard let peer = peer, let inputChannel = apiInputChannel(peer) else {
22 | return .fail(.generic)
23 | }
24 |
25 | return network.request(Api.functions.channels.togglePreHistoryHidden(channel: inputChannel, enabled: historyAvailableForNewMembers ? .boolFalse : .boolTrue))
26 | |> `catch` { error -> Signal in
27 | if error.errorDescription == "CHAT_ADMIN_REQUIRED" {
28 | return .fail(.hasNotPermissions)
29 | }
30 | return .fail(.generic)
31 | }
32 | |> mapToSignal { updates -> Signal in
33 | accountStateManager.addUpdates(updates)
34 | return postbox.transaction { transaction -> Void in
35 | transaction.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in
36 | if let currentData = currentData as? CachedChannelData {
37 | var flags = currentData.flags
38 | if historyAvailableForNewMembers {
39 | flags.insert(.preHistoryEnabled)
40 | } else {
41 | flags.remove(.preHistoryEnabled)
42 | }
43 | return currentData.withUpdatedFlags(flags)
44 | } else {
45 | return currentData
46 | }
47 | })
48 | } |> introduceError(ChannelHistoryAvailabilityError.self)
49 | }
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/TelegramCore/ChannelMessageStateVersionAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ChannelMessageStateVersionAttribute: MessageAttribute {
9 | public let pts: Int32
10 |
11 | public init(pts: Int32) {
12 | self.pts = pts
13 | }
14 |
15 | required public init(decoder: PostboxDecoder) {
16 | self.pts = decoder.decodeInt32ForKey("p", orElse: 0)
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt32(self.pts, forKey: "p")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/TelegramCore/ChannelStats.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import PostboxMac
5 | #else
6 | import SwiftSignalKit
7 | import Postbox
8 | #endif
9 |
10 | public enum ChannelStatsUrlError {
11 | case generic
12 | }
13 |
14 | public func channelStatsUrl(postbox: Postbox, network: Network, peerId: PeerId, params: String, darkTheme: Bool) -> Signal {
15 | return postbox.transaction { transaction -> Api.InputPeer? in
16 | return transaction.getPeer(peerId).flatMap(apiInputPeer)
17 | }
18 | |> introduceError(ChannelStatsUrlError.self)
19 | |> mapToSignal { inputPeer -> Signal in
20 | guard let inputPeer = inputPeer else {
21 | return .fail(.generic)
22 | }
23 | var flags: Int32 = 0
24 | if darkTheme {
25 | flags |= (1 << 0)
26 | }
27 | return network.request(Api.functions.messages.getStatsURL(flags: flags, peer: inputPeer, params: params))
28 | |> map { result -> String in
29 | switch result {
30 | case let .statsURL(url):
31 | return url
32 | }
33 | }
34 | |> `catch` { _ -> Signal in
35 | return .fail(.generic)
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/TelegramCore/ChatOnlineMembers.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import PostboxMac
5 | #else
6 | import SwiftSignalKit
7 | import Postbox
8 | #endif
9 |
10 | public func chatOnlineMembers(postbox: Postbox, network: Network, peerId: PeerId) -> Signal {
11 | return postbox.transaction { transaction -> Api.InputPeer? in
12 | return transaction.getPeer(peerId).flatMap(apiInputPeer)
13 | }
14 | |> mapToSignal { inputPeer -> Signal in
15 | guard let inputPeer = inputPeer else {
16 | return .single(0)
17 | }
18 | return network.request(Api.functions.messages.getOnlines(peer: inputPeer))
19 | |> map { value -> Int32 in
20 | switch value {
21 | case let .chatOnlines(onlines):
22 | return onlines
23 | }
24 | }
25 | |> `catch` { _ -> Signal in
26 | return .single(0)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/TelegramCore/CheckPeerChatServiceActions.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func checkPeerChatServiceActions(postbox: Postbox, peerId: PeerId) -> Signal {
11 | return postbox.transaction { transaction -> Void in
12 | transaction.applyMarkUnread(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, value: false, interactive: true)
13 |
14 | if peerId.namespace == Namespaces.Peer.SecretChat {
15 | if let state = transaction.getPeerChatState(peerId) as? SecretChatState {
16 | let updatedState = secretChatCheckLayerNegotiationIfNeeded(transaction: transaction, peerId: peerId, state: state)
17 | if state != updatedState {
18 | transaction.setPeerChatState(peerId, state: updatedState)
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/TelegramCore/CloudMediaResourceParameters.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum CloudMediaResourceLocation: Equatable {
4 | case photo(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String)
5 | case file(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String)
6 | case peerPhoto(peer: PeerReference, fullSize: Bool, volumeId: Int64, localId: Int64)
7 | case stickerPackThumbnail(packReference: StickerPackReference, volumeId: Int64, localId: Int64)
8 | }
9 |
--------------------------------------------------------------------------------
/TelegramCore/Config/TelegramCore.xcconfig:
--------------------------------------------------------------------------------
1 | SWIFT_INCLUDE_PATHS = $(SRCROOT)/TelegramCore
2 | MODULEMAP_PRIVATE_FILE = $(SRCROOT)/TelegramCore/module.private.modulemap
3 |
--------------------------------------------------------------------------------
/TelegramCore/ConfirmTwoStepRecoveryEmail.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import MtProtoKitMac
5 | #else
6 | import SwiftSignalKit
7 | import MtProtoKitDynamic
8 | #endif
9 |
10 | public enum ConfirmTwoStepRecoveryEmailError {
11 | case invalidEmail
12 | case invalidCode
13 | case flood
14 | case expired
15 | case generic
16 | }
17 |
18 | public func confirmTwoStepRecoveryEmail(network: Network, code: String) -> Signal {
19 | return network.request(Api.functions.account.confirmPasswordEmail(code: code), automaticFloodWait: false)
20 | |> mapError { error -> ConfirmTwoStepRecoveryEmailError in
21 | if error.errorDescription == "EMAIL_INVALID" {
22 | return .invalidEmail
23 | } else if error.errorDescription == "CODE_INVALID" {
24 | return .invalidCode
25 | } else if error.errorDescription == "EMAIL_HASH_EXPIRED" {
26 | return .expired
27 | } else if error.errorDescription.hasPrefix("FLOOD_WAIT") {
28 | return .flood
29 | }
30 | return .generic
31 | }
32 | |> ignoreValues
33 | }
34 |
35 | public enum ResendTwoStepRecoveryEmailError {
36 | case flood
37 | case generic
38 | }
39 |
40 | public func resendTwoStepRecoveryEmail(network: Network) -> Signal {
41 | return network.request(Api.functions.account.resendPasswordEmail(), automaticFloodWait: false)
42 | |> mapError { error -> ResendTwoStepRecoveryEmailError in
43 | if error.errorDescription.hasPrefix("FLOOD_WAIT") {
44 | return .flood
45 | }
46 | return .generic
47 | }
48 | |> ignoreValues
49 | }
50 |
51 | public enum CancelTwoStepRecoveryEmailError {
52 | case generic
53 | }
54 |
55 | public func cancelTwoStepRecoveryEmail(network: Network) -> Signal {
56 | return network.request(Api.functions.account.cancelPasswordEmail(), automaticFloodWait: false)
57 | |> mapError { _ -> CancelTwoStepRecoveryEmailError in
58 | return .generic
59 | }
60 | |> ignoreValues
61 | }
62 |
--------------------------------------------------------------------------------
/TelegramCore/ConsumableContentMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ConsumableContentMessageAttribute: MessageAttribute {
9 | public let consumed: Bool
10 |
11 | public init(consumed: Bool) {
12 | self.consumed = consumed
13 | }
14 |
15 | required public init(decoder: PostboxDecoder) {
16 | self.consumed = decoder.decodeInt32ForKey("c", orElse: 0) != 0
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt32(self.consumed ? 1 : 0, forKey: "c")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/TelegramCore/ConsumablePersonalMentionMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ConsumablePersonalMentionMessageAttribute: MessageAttribute {
9 | public let consumed: Bool
10 | public let pending: Bool
11 |
12 | public init(consumed: Bool, pending: Bool) {
13 | self.consumed = consumed
14 | self.pending = pending
15 | }
16 |
17 | required public init(decoder: PostboxDecoder) {
18 | self.consumed = decoder.decodeInt32ForKey("c", orElse: 0) != 0
19 | self.pending = decoder.decodeInt32ForKey("p", orElse: 0) != 0
20 | }
21 |
22 | public func encode(_ encoder: PostboxEncoder) {
23 | encoder.encodeInt32(self.consumed ? 1 : 0, forKey: "c")
24 | encoder.encodeInt32(self.pending ? 1 : 0, forKey: "p")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/TelegramCore/ConsumePersonalMessageAction.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | final class ConsumePersonalMessageAction: PendingMessageActionData {
11 | init() {
12 | }
13 |
14 | init(decoder: PostboxDecoder) {
15 | }
16 |
17 | func encode(_ encoder: PostboxEncoder) {
18 | }
19 |
20 | func isEqual(to: PendingMessageActionData) -> Bool {
21 | if let _ = to as? ConsumePersonalMessageAction {
22 | return true
23 | } else {
24 | return false
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/TelegramCore/ContactsSettings.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct ContactsSettings: Equatable, PreferencesEntry {
9 | public var synchronizeContacts: Bool
10 |
11 | public static var defaultSettings: ContactsSettings {
12 | return ContactsSettings(synchronizeContacts: true)
13 | }
14 |
15 | public init(synchronizeContacts: Bool) {
16 | self.synchronizeContacts = synchronizeContacts
17 | }
18 |
19 | public init(decoder: PostboxDecoder) {
20 | self.synchronizeContacts = decoder.decodeInt32ForKey("synchronizeContacts", orElse: 0) != 0
21 | }
22 |
23 | public func encode(_ encoder: PostboxEncoder) {
24 | encoder.encodeInt32(self.synchronizeContacts ? 1 : 0, forKey: "synchronizeContacts")
25 | }
26 |
27 | public func isEqual(to: PreferencesEntry) -> Bool {
28 | if let to = to as? ContactsSettings {
29 | return self == to
30 | } else {
31 | return false
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/TelegramCore/ContentPrivacySettings.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public final class ContentPrivacySettings: PreferencesEntry, Equatable {
13 | public let enableSecretChatWebpagePreviews: Bool?
14 |
15 | public static var defaultSettings = ContentPrivacySettings(enableSecretChatWebpagePreviews: nil)
16 |
17 | public init(enableSecretChatWebpagePreviews: Bool?) {
18 | self.enableSecretChatWebpagePreviews = enableSecretChatWebpagePreviews
19 | }
20 |
21 | public init(decoder: PostboxDecoder) {
22 | self.enableSecretChatWebpagePreviews = decoder.decodeOptionalInt32ForKey("enableSecretChatWebpagePreviews").flatMap { $0 != 0 }
23 | }
24 |
25 | public func encode(_ encoder: PostboxEncoder) {
26 | if let enableSecretChatWebpagePreviews = self.enableSecretChatWebpagePreviews {
27 | encoder.encodeInt32(enableSecretChatWebpagePreviews ? 1 : 0, forKey: "enableSecretChatWebpagePreviews")
28 | } else {
29 | encoder.encodeNil(forKey: "enableSecretChatWebpagePreviews")
30 | }
31 | }
32 |
33 | public func withUpdatedEnableSecretChatWebpagePreviews(_ enableSecretChatWebpagePreviews: Bool) -> ContentPrivacySettings {
34 | return ContentPrivacySettings(enableSecretChatWebpagePreviews: enableSecretChatWebpagePreviews)
35 | }
36 |
37 | public func isEqual(to: PreferencesEntry) -> Bool {
38 | guard let to = to as? ContentPrivacySettings else {
39 | return false
40 | }
41 |
42 | return self == to
43 | }
44 |
45 | public static func ==(lhs: ContentPrivacySettings, rhs: ContentPrivacySettings) -> Bool {
46 | if lhs.enableSecretChatWebpagePreviews != rhs.enableSecretChatWebpagePreviews {
47 | return false
48 | }
49 | return true
50 | }
51 | }
52 |
53 | public func updateContentPrivacySettings(postbox: Postbox, _ f: @escaping (ContentPrivacySettings) -> ContentPrivacySettings) -> Signal {
54 | return postbox.transaction { transaction -> Void in
55 | var updated: ContentPrivacySettings?
56 | transaction.updatePreferencesEntry(key: PreferencesKeys.contentPrivacySettings, { current in
57 | if let current = current as? ContentPrivacySettings {
58 | updated = f(current)
59 | return updated
60 | } else {
61 | updated = f(ContentPrivacySettings.defaultSettings)
62 | return updated
63 | }
64 | })
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/TelegramCore/ContentRequiresValidationMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ContentRequiresValidationMessageAttribute: MessageAttribute {
9 | public init() {
10 | }
11 |
12 | required public init(decoder: PostboxDecoder) {
13 | }
14 |
15 | public func encode(_ encoder: PostboxEncoder) {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/TelegramCore/ConvertGroupToSupergroup.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public enum ConvertGroupToSupergroupError {
13 | case generic
14 | }
15 |
16 | public func convertGroupToSupergroup(account: Account, peerId: PeerId) -> Signal {
17 | return account.network.request(Api.functions.messages.migrateChat(chatId: peerId.id))
18 | |> mapError { _ -> ConvertGroupToSupergroupError in
19 | return .generic
20 | }
21 | |> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .fail(.generic))
22 | |> mapToSignal { updates -> Signal in
23 | account.stateManager.addUpdates(updates)
24 | var createdPeerId: PeerId?
25 | for message in updates.messages {
26 | if apiMessagePeerId(message) != peerId {
27 | createdPeerId = apiMessagePeerId(message)
28 | break
29 | }
30 | }
31 |
32 | if let createdPeerId = createdPeerId {
33 | return account.postbox.multiplePeersView([createdPeerId])
34 | |> filter { view in
35 | return view.peers[createdPeerId] != nil
36 | }
37 | |> take(1)
38 | |> map { _ in
39 | return createdPeerId
40 | }
41 | |> mapError { _ -> ConvertGroupToSupergroupError in
42 | return .generic
43 | }
44 | |> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .fail(.generic))
45 | }
46 | return .fail(.generic)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/TelegramCore/CoreSettings.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public final class CoreSettings: PreferencesEntry, Equatable {
13 | public let fastForward: Bool
14 |
15 | public static var defaultSettings = CoreSettings(fastForward: true)
16 |
17 | public init(fastForward: Bool) {
18 | self.fastForward = fastForward
19 | }
20 |
21 | public init(decoder: PostboxDecoder) {
22 | self.fastForward = decoder.decodeInt32ForKey("fastForward", orElse: 0) != 0
23 | }
24 |
25 | public func encode(_ encoder: PostboxEncoder) {
26 | encoder.encodeInt32(self.fastForward ? 1 : 0, forKey: "fastForward")
27 | }
28 |
29 | public func withUpdatedFastForward(_ fastForward: Bool) -> CoreSettings {
30 | return CoreSettings(fastForward: fastForward)
31 | }
32 |
33 | public func isEqual(to: PreferencesEntry) -> Bool {
34 | guard let to = to as? CoreSettings else {
35 | return false
36 | }
37 |
38 | return self == to
39 | }
40 |
41 | public static func ==(lhs: CoreSettings, rhs: CoreSettings) -> Bool {
42 | if lhs.fastForward != rhs.fastForward {
43 | return false
44 | }
45 | return true
46 | }
47 | }
48 |
49 | public func updateCoreSettings(postbox: Postbox, _ f: @escaping (CoreSettings) -> CoreSettings) -> Signal {
50 | return postbox.transaction { transaction -> Void in
51 | var updated: CoreSettings?
52 | transaction.updatePreferencesEntry(key: PreferencesKeys.coreSettings, { current in
53 | if let current = current as? CoreSettings {
54 | updated = f(current)
55 | return updated
56 | } else {
57 | updated = f(CoreSettings.defaultSettings)
58 | return updated
59 | }
60 | })
61 | }
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/TelegramCore/CreateGroup.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public enum CreateGroupError {
13 | case generic
14 | case privacy
15 | }
16 |
17 | public func createGroup(account: Account, title: String, peerIds: [PeerId]) -> Signal {
18 | return account.postbox.transaction { transaction -> Signal in
19 | var inputUsers: [Api.InputUser] = []
20 | for peerId in peerIds {
21 | if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) {
22 | inputUsers.append(inputUser)
23 | } else {
24 | return .single(nil)
25 | }
26 | }
27 | return account.network.request(Api.functions.messages.createChat(users: inputUsers, title: title))
28 | |> mapError { error -> CreateGroupError in
29 | if error.errorDescription == "USERS_TOO_FEW" {
30 | return .privacy
31 | }
32 | return .generic
33 | }
34 | |> mapToSignal { updates -> Signal in
35 | account.stateManager.addUpdates(updates)
36 | if let message = updates.messages.first, let peerId = apiMessagePeerId(message) {
37 | return account.postbox.multiplePeersView([peerId])
38 | |> filter { view in
39 | return view.peers[peerId] != nil
40 | }
41 | |> take(1)
42 | |> introduceError(CreateGroupError.self)
43 | |> map { _ in
44 | return peerId
45 | }
46 | } else {
47 | return .single(nil)
48 | }
49 | }
50 | }
51 | |> introduceError(CreateGroupError.self)
52 | |> switchToLatest
53 | }
54 |
--------------------------------------------------------------------------------
/TelegramCore/Crypto.h:
--------------------------------------------------------------------------------
1 | #ifndef __CRYPTO_H_
2 | #define __CRYPTO_H_
3 |
4 | #import
5 |
6 | NSData * _Nonnull CryptoMD5(const void *bytes, int count);
7 | NSData * _Nonnull CryptoSHA1(const void *bytes, int count);
8 | NSData * _Nonnull CryptoSHA256(const void *bytes, int count);
9 | NSData * _Nonnull CryptoSHA512(const void *bytes, int count);
10 |
11 | @interface IncrementalMD5 : NSObject
12 |
13 | - (instancetype _Nonnull)init;
14 | - (void)update:(NSData * _Nonnull)data;
15 | - (void)update:(const void * _Nonnull)bytes count:(int)count;
16 | - (NSData * _Nonnull)complete;
17 |
18 | @end
19 |
20 | NSData * _Nullable CryptoAES(bool encrypt, NSData * _Nonnull key, NSData * _Nonnull iv, NSData * _Nonnull data);
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/TelegramCore/Crypto.m:
--------------------------------------------------------------------------------
1 | #include "Crypto.h"
2 |
3 | #import
4 |
5 | NSData * _Nonnull CryptoMD5(const void *bytes, int count) {
6 | NSMutableData *result = [[NSMutableData alloc] initWithLength:(NSUInteger)CC_MD5_DIGEST_LENGTH];
7 | CC_MD5(bytes, (CC_LONG)count, result.mutableBytes);
8 | return result;
9 | }
10 |
11 | NSData * _Nonnull CryptoSHA1(const void *bytes, int count) {
12 | NSMutableData *result = [[NSMutableData alloc] initWithLength:(NSUInteger)CC_SHA1_DIGEST_LENGTH];
13 | CC_SHA1(bytes, (CC_LONG)count, result.mutableBytes);
14 | return result;
15 | }
16 |
17 | NSData * _Nonnull CryptoSHA256(const void *bytes, int count) {
18 | NSMutableData *result = [[NSMutableData alloc] initWithLength:(NSUInteger)CC_SHA256_DIGEST_LENGTH];
19 | CC_SHA256(bytes, (CC_LONG)count, result.mutableBytes);
20 | return result;
21 | }
22 |
23 | NSData * _Nonnull CryptoSHA512(const void *bytes, int count) {
24 | NSMutableData *result = [[NSMutableData alloc] initWithLength:(NSUInteger)CC_SHA512_DIGEST_LENGTH];
25 | CC_SHA512(bytes, (CC_LONG)count, result.mutableBytes);
26 | return result;
27 | }
28 |
29 | @interface IncrementalMD5 () {
30 | CC_MD5_CTX _ctx;
31 | }
32 |
33 | @end
34 |
35 | @implementation IncrementalMD5
36 |
37 | - (instancetype _Nonnull)init {
38 | self = [super init];
39 | if (self != nil) {
40 | CC_MD5_Init(&_ctx);
41 | }
42 | return self;
43 | }
44 |
45 | - (void)update:(NSData * _Nonnull)data {
46 | CC_MD5_Update(&_ctx, data.bytes, (CC_LONG)data.length);
47 | }
48 |
49 | - (void)update:(const void *)bytes count:(int)count {
50 | CC_MD5_Update(&_ctx, bytes, (CC_LONG)count);
51 | }
52 |
53 | - (NSData *)complete {
54 | NSMutableData *result = [[NSMutableData alloc] initWithLength:(NSUInteger)CC_MD5_DIGEST_LENGTH];
55 | CC_MD5_Final(result.mutableBytes, &_ctx);
56 | return result;
57 | }
58 |
59 | @end
60 |
61 | NSData * _Nullable CryptoAES(bool encrypt, NSData * _Nonnull key, NSData * _Nonnull iv, NSData * _Nonnull data) {
62 | if (key.length != 32) {
63 | return nil;
64 | }
65 | if (iv.length != 16) {
66 | return nil;
67 | }
68 | NSMutableData *processedData = [[NSMutableData alloc] initWithLength:data.length];
69 | size_t processedCount = 0;
70 | CCStatus status = CCCrypt(encrypt ? kCCEncrypt : kCCDecrypt, kCCAlgorithmAES128, 0, key.bytes, key.length, iv.bytes, data.bytes, data.length, processedData.mutableBytes, processedData.length, &processedCount);
71 | if (status != kCCSuccess) {
72 | return nil;
73 | }
74 | if (processedCount != (size_t)processedData.length) {
75 | return nil;
76 | }
77 | return processedData;
78 | }
79 |
--------------------------------------------------------------------------------
/TelegramCore/DecryptedResourceData.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public func decryptedResourceData(data: MediaResourceData, resource: MediaResource, params: Any) -> Data? {
9 | guard data.complete else {
10 | return nil
11 | }
12 | guard let data = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: [.mappedRead]) else {
13 | return nil
14 | }
15 | if let resource = resource as? EncryptedMediaResource {
16 | return resource.decrypt(data: data, params: params)
17 | } else {
18 | return data
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/TelegramCore/DeepLinkInfo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | #else
5 | import SwiftSignalKit
6 | #endif
7 |
8 | public struct DeepLinkInfo {
9 | public let message: String
10 | public let entities: [MessageTextEntity]
11 | public let updateApp: Bool
12 | }
13 |
14 | public func getDeepLinkInfo(network: Network, path: String) -> Signal {
15 | return network.request(Api.functions.help.getDeepLinkInfo(path: path)) |> retryRequest
16 | |> map { value -> DeepLinkInfo? in
17 | switch value {
18 | case .deepLinkInfoEmpty:
19 | return nil
20 | case let .deepLinkInfo(flags, message, entities):
21 | return DeepLinkInfo(message: message, entities: entities != nil ? messageTextEntitiesFromApiEntities(entities!) : [], updateApp: (flags & (1 << 0)) != 0)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/TelegramCore/DeleteMessages.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private func removeMessageMedia(message: Message, mediaBox: MediaBox) {
11 | for media in message.media {
12 | if let image = media as? TelegramMediaImage {
13 | let _ = mediaBox.removeCachedResources(Set(image.representations.map({ WrappedMediaResourceId($0.resource.id) }))).start()
14 | } else if let file = media as? TelegramMediaFile {
15 | let _ = mediaBox.removeCachedResources(Set(file.previewRepresentations.map({ WrappedMediaResourceId($0.resource.id) }))).start()
16 | let _ = mediaBox.removeCachedResources(Set([WrappedMediaResourceId(file.resource.id)])).start()
17 | }
18 | }
19 | }
20 |
21 | public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId]) {
22 | for id in ids {
23 | if id.peerId.namespace == Namespaces.Peer.SecretChat {
24 | if let message = transaction.getMessage(id) {
25 | removeMessageMedia(message: message, mediaBox: mediaBox)
26 | }
27 | }
28 | }
29 | transaction.deleteMessages(ids)
30 | }
31 |
32 | public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId) {
33 | if peerId.namespace == Namespaces.Peer.SecretChat {
34 | transaction.withAllMessages(peerId: peerId, { message in
35 | removeMessageMedia(message: message, mediaBox: mediaBox)
36 | return true
37 | })
38 | }
39 | transaction.clearHistory(peerId)
40 | }
41 |
--------------------------------------------------------------------------------
/TelegramCore/DeserializeFunctionResponse.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public final class FunctionDescription {
4 | let name: String
5 | let parameters: [(String, Any)]
6 |
7 | init(name: String, parameters: [(String, Any)]) {
8 | self.name = name
9 | self.parameters = parameters
10 | }
11 | }
12 |
13 | public final class DeserializeFunctionResponse {
14 | private let f: (Buffer) -> T?
15 |
16 | public init(_ f: @escaping (Buffer) -> T?) {
17 | self.f = f
18 | }
19 |
20 | public func parse(_ buffer: Buffer) -> T? {
21 | return self.f(buffer)
22 | }
23 | }
24 |
25 | protocol TypeConstructorDescription {
26 | func descriptionFields() -> (String, [(String, Any)])
27 | }
28 |
--------------------------------------------------------------------------------
/TelegramCore/EditedMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class EditedMessageAttribute: MessageAttribute {
9 | public let date: Int32
10 |
11 | init(date: Int32) {
12 | self.date = date
13 | }
14 |
15 | required public init(decoder: PostboxDecoder) {
16 | self.date = decoder.decodeInt32ForKey("d", orElse: 0)
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt32(self.date, forKey: "d")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/TelegramCore/Either.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum Either {
4 | case left(value: Left)
5 | case right(value: Right)
6 | }
7 |
--------------------------------------------------------------------------------
/TelegramCore/EncryptedMediaResource.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public protocol EncryptedMediaResource {
4 | func decrypt(data: Data, params: Any) -> Data?
5 | }
6 |
--------------------------------------------------------------------------------
/TelegramCore/ExportMessageLink.swift:
--------------------------------------------------------------------------------
1 |
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 |
11 | public func exportMessageLink(account: Account, peerId: PeerId, messageId: MessageId) -> Signal {
12 | return account.postbox.transaction { transaction -> Peer? in
13 | return transaction.getPeer(peerId)
14 | }
15 | |> mapToSignal { peer -> Signal in
16 | if let peer = peer, let input = apiInputChannel(peer) {
17 | return account.network.request(Api.functions.channels.exportMessageLink(channel: input, id: messageId.id, grouped: .boolTrue)) |> mapError { _ in return }
18 | |> map { res in
19 | switch res {
20 | case let .exportedMessageLink(link, _):
21 | return link
22 | }
23 | } |> `catch` { _ -> Signal in
24 | return .single(nil)
25 | }
26 | } else {
27 | return .single(nil)
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/TelegramCore/ExportedInvitation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct ExportedInvitation: PostboxCoding, Equatable {
9 | public let link: String
10 |
11 | init(link: String) {
12 | self.link = link
13 | }
14 |
15 | public init(decoder: PostboxDecoder) {
16 | self.link = decoder.decodeStringForKey("l", orElse: "")
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeString(self.link, forKey: "l")
21 | }
22 |
23 | public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool {
24 | return lhs.link == rhs.link
25 | }
26 | }
27 |
28 | extension ExportedInvitation {
29 | init?(apiExportedInvite: Api.ExportedChatInvite) {
30 | switch apiExportedInvite {
31 | case .chatInviteEmpty:
32 | return nil
33 | case let .chatInviteExported(link):
34 | self = ExportedInvitation(link: link)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/TelegramCore/FeaturedStickerPack.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct FeaturedStickerPackItemId {
9 | public let rawValue: MemoryBuffer
10 | public let packId: Int64
11 |
12 | init(_ rawValue: MemoryBuffer) {
13 | self.rawValue = rawValue
14 | assert(rawValue.length == 8)
15 | var idValue: Int64 = 0
16 | memcpy(&idValue, rawValue.memory, 8)
17 | self.packId = idValue
18 | }
19 |
20 | init(_ packId: Int64) {
21 | self.packId = packId
22 | var idValue: Int64 = packId
23 | self.rawValue = MemoryBuffer(memory: malloc(8)!, capacity: 8, length: 8, freeWhenDone: true)
24 | memcpy(self.rawValue.memory, &idValue, 8)
25 | }
26 | }
27 |
28 | public final class FeaturedStickerPackItem: OrderedItemListEntryContents {
29 | public let info: StickerPackCollectionInfo
30 | public let topItems: [StickerPackItem]
31 | public let unread: Bool
32 |
33 | init(info: StickerPackCollectionInfo, topItems: [StickerPackItem], unread: Bool) {
34 | self.info = info
35 | self.topItems = topItems
36 | self.unread = unread
37 | }
38 |
39 | public init(decoder: PostboxDecoder) {
40 | self.info = decoder.decodeObjectForKey("i") as! StickerPackCollectionInfo
41 | self.topItems = decoder.decodeObjectArrayForKey("t")
42 | self.unread = decoder.decodeInt32ForKey("u", orElse: 0) != 0
43 | }
44 |
45 | public func encode(_ encoder: PostboxEncoder) {
46 | encoder.encodeObject(self.info, forKey: "i")
47 | encoder.encodeObjectArray(self.topItems, forKey: "t")
48 | encoder.encodeInt32(self.unread ? 1 : 0, forKey: "u")
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/TelegramCore/FetchHttpResource.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public func fetchHttpResource(url: String) -> Signal {
13 | if let url = URL(string: url) {
14 | let signal = MTHttpRequestOperation.data(forHttpUrl: url)!
15 | return Signal { subscriber in
16 | subscriber.putNext(.reset)
17 | let disposable = signal.start(next: { next in
18 | let data = next as! Data
19 | let fetchResult: MediaResourceDataFetchResult = .dataPart(resourceOffset: 0, data: data, range: 0 ..< data.count, complete: true)
20 | subscriber.putNext(fetchResult)
21 | subscriber.putCompletion()
22 | }, error: { _ in
23 | subscriber.putError(.generic)
24 | }, completed: {
25 | })
26 |
27 | return ActionDisposable {
28 | disposable?.dispose()
29 | }
30 | }
31 | } else {
32 | return .never()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/TelegramCore/FetchSecretFileResource.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, intervals: Signal<[(Range, MediaBoxFetchPriority)], NoError>, parameters: MediaResourceFetchParameters?) -> Signal {
13 | return multipartFetch(postbox: account.postbox, network: account.network, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, resource: resource, datacenterId: resource.datacenterId, size: resource.size, intervals: intervals, parameters: parameters, encryptionKey: resource.key, decryptedSize: resource.decryptedSize)
14 | }
15 |
--------------------------------------------------------------------------------
/TelegramCore/FindChannelById.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import PostboxMac
5 | #else
6 | import SwiftSignalKit
7 | import Postbox
8 | #endif
9 |
10 | public func findChannelById(postbox: Postbox, network: Network, channelId: Int32) -> Signal {
11 | return network.request(Api.functions.channels.getChannels(id: [.inputChannel(channelId: channelId, accessHash: 0)]))
12 | |> map(Optional.init)
13 | |> `catch` { _ -> Signal in
14 | return .single(nil)
15 | }
16 | |> mapToSignal { result -> Signal in
17 | guard let result = result else {
18 | return .single(nil)
19 | }
20 | let chats: [Api.Chat]
21 | switch result {
22 | case let .chats(apiChats):
23 | chats = apiChats
24 | case let .chatsSlice(_, apiChats):
25 | chats = apiChats
26 | }
27 | guard let chat = chats.first else {
28 | return .single(nil)
29 | }
30 | guard let peer = parseTelegramGroupOrChannel(chat: chat) else {
31 | return .single(nil)
32 | }
33 |
34 | return postbox.transaction { transaction -> Peer? in
35 | updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
36 | return updated
37 | })
38 | return peer
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TelegramCore/ForwardGame.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId) -> Signal {
11 | return account.postbox.transaction { transaction -> Signal in
12 | if let message = transaction.getMessage(messageId), let fromPeer = transaction.getPeer(messageId.peerId), let fromInputPeer = apiInputPeer(fromPeer), let toPeer = transaction.getPeer(peerId), let toInputPeer = apiInputPeer(toPeer) {
13 | return account.network.request(Api.functions.messages.forwardMessages(flags: 1 << 8, fromPeer: fromInputPeer, id: [messageId.id], randomId: [arc4random64()], toPeer: toInputPeer))
14 | |> map(Optional.init)
15 | |> `catch` { _ -> Signal in
16 | return .single(nil)
17 | }
18 | |> mapToSignal { updates -> Signal in
19 | if let updates = updates {
20 | account.stateManager.addUpdates(updates)
21 | }
22 | return .complete()
23 | }
24 | }
25 | return .complete()
26 | } |> switchToLatest
27 | }
28 |
--------------------------------------------------------------------------------
/TelegramCore/ForwardSourceInfoAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ForwardSourceInfoAttribute: MessageAttribute {
9 | public let messageId: MessageId
10 |
11 | init(messageId: MessageId) {
12 | self.messageId = messageId
13 | }
14 |
15 | required public init(decoder: PostboxDecoder) {
16 | self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), namespace: decoder.decodeInt32ForKey("n", orElse: 0), id: decoder.decodeInt32ForKey("i", orElse: 0))
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt64(self.messageId.peerId.toInt64(), forKey: "p")
21 | encoder.encodeInt32(self.messageId.namespace, forKey: "n")
22 | encoder.encodeInt32(self.messageId.id, forKey: "i")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/TelegramCore/GlobalTelegramCoreConfiguration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public final class GlobalTelegramCoreConfiguration {
4 | public static var readMessages: Bool = true
5 | }
6 |
--------------------------------------------------------------------------------
/TelegramCore/GroupFeedPeers.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func availableGroupFeedPeers(postbox: Postbox, network: Network, groupId: PeerGroupId) -> Signal<[(Peer, Bool)], NoError> {
11 | /*feed*/
12 | return .single([])
13 | /*return network.request(Api.functions.channels.getFeedSources(flags: 0, feedId: groupId.rawValue, hash: 0))
14 | |> retryRequest
15 | |> mapToSignal { result -> Signal<[(Peer, Bool)], NoError> in
16 | return postbox.transaction { transaction -> [(Peer, Bool)] in
17 | switch result {
18 | case .feedSourcesNotModified:
19 | return []
20 | case let .feedSources(_, newlyJoinedFeed, feeds, chats, users):
21 | var includedPeerIds = Set()
22 | var excludedPeerIds = Set()
23 | for feedsInfo in feeds {
24 | switch feedsInfo {
25 | case let .feedBroadcasts(feedId, channels):
26 | if feedId == groupId.rawValue {
27 | for id in channels {
28 | includedPeerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: id))
29 | }
30 | }
31 | case let .feedBroadcastsUngrouped(channels):
32 | for id in channels {
33 | excludedPeerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: id))
34 | }
35 | }
36 | }
37 | var peers: [(Peer, Bool)] = []
38 | for peerId in includedPeerIds {
39 | if let peer = transaction.getPeer(peerId) {
40 | peers.append((peer, true))
41 | }
42 | }
43 | for peerId in excludedPeerIds {
44 | if let peer = transaction.getPeer(peerId) {
45 | peers.append((peer, false))
46 | }
47 | }
48 | return peers
49 | }
50 | }
51 | }*/
52 | }
53 |
--------------------------------------------------------------------------------
/TelegramCore/GroupReturnAndLeft.swift:
--------------------------------------------------------------------------------
1 |
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 |
13 | public func returnGroup(account: Account, peerId: PeerId) -> Signal {
14 | return account.postbox.loadedPeerWithId(account.peerId)
15 | |> take(1)
16 | |> mapToSignal { peer -> Signal in
17 | if let inputUser = apiInputUser(peer) {
18 | return account.network.request(Api.functions.messages.addChatUser(chatId: peerId.id, userId: inputUser, fwdLimit: 50))
19 | |> retryRequest
20 | |> mapToSignal { updates -> Signal in
21 | account.stateManager.addUpdates(updates)
22 | return .complete()
23 | }
24 | } else {
25 | return .complete()
26 | }
27 | }
28 | }
29 |
30 | public func leftGroup(account: Account, peerId: PeerId) -> Signal {
31 | return account.postbox.loadedPeerWithId(account.peerId)
32 | |> take(1)
33 | |> mapToSignal { peer -> Signal in
34 | if let inputUser = apiInputUser(peer) {
35 | return account.network.request(Api.functions.messages .deleteChatUser(chatId: peerId.id, userId: inputUser))
36 | |> retryRequest
37 | |> mapToSignal { updates -> Signal in
38 | account.stateManager.addUpdates(updates)
39 | return .complete()
40 | }
41 | } else {
42 | return .complete()
43 | }
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/TelegramCore/GroupsInCommon.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func groupsInCommon(account:Account, peerId:PeerId) -> Signal<[PeerId], NoError> {
11 | return account.postbox.transaction { transaction -> Signal<[PeerId], NoError> in
12 | if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) {
13 | return account.network.request(Api.functions.messages.getCommonChats(userId: inputUser, maxId: 0, limit: 100))
14 | |> retryRequest
15 | |> mapToSignal { result -> Signal<[PeerId], NoError> in
16 | let chats: [Api.Chat]
17 | switch result {
18 | case let .chats(chats: apiChats):
19 | chats = apiChats
20 | case let .chatsSlice(count: _, chats: apiChats):
21 | chats = apiChats
22 | }
23 |
24 | return account.postbox.transaction { transaction -> [PeerId] in
25 | var peers:[Peer] = []
26 | for chat in chats {
27 | if let peer = parseTelegramGroupOrChannel(chat: chat) {
28 | peers.append(peer)
29 | }
30 | }
31 | updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer? in
32 | return updated
33 | })
34 | return peers.map {$0.id}
35 | }
36 | }
37 | } else {
38 | return .single([])
39 | }
40 | } |> switchToLatest
41 | }
42 |
--------------------------------------------------------------------------------
/TelegramCore/ImportContact.swift:
--------------------------------------------------------------------------------
1 | #if os(macOS)
2 | import PostboxMac
3 | import SwiftSignalKitMac
4 | #else
5 | import Postbox
6 | import SwiftSignalKit
7 | #endif
8 |
9 | public func importContact(account:Account, firstName: String, lastName: String, phoneNumber: String) -> Signal {
10 |
11 | let input = Api.InputContact.inputPhoneContact(clientId: 1, phone: phoneNumber, firstName: firstName, lastName: lastName)
12 |
13 | return account.network.request(Api.functions.contacts.importContacts(contacts: [input]))
14 | |> map(Optional.init)
15 | |> `catch` { _ -> Signal in
16 | return .single(nil)
17 | }
18 | |> mapToSignal { result -> Signal in
19 | return account.postbox.transaction { transaction -> PeerId? in
20 | if let result = result {
21 | switch result {
22 | case let .importedContacts(_, _, _, users):
23 | if let first = users.first {
24 | let user = TelegramUser(user: first)
25 | let peerId = user.id
26 | updatePeers(transaction: transaction, peers: [user], update: { _, updated in
27 | return updated
28 | })
29 | var peerIds = transaction.getContactPeerIds()
30 | if !peerIds.contains(peerId) {
31 | peerIds.insert(peerId)
32 | transaction.replaceContactPeerIds(peerIds)
33 | }
34 | return peerId
35 | }
36 | }
37 | }
38 | return nil
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TelegramCore/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TelegramCore/InitializeAccountAfterLogin.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import PostboxMac
5 | #else
6 | import SwiftSignalKit
7 | import Postbox
8 | #endif
9 |
10 | func initializedAppSettingsAfterLogin(transaction: Transaction, appVersion: String, syncContacts: Bool) {
11 | updateAppChangelogState(transaction: transaction, { state in
12 | var state = state
13 | state.checkedVersion = appVersion
14 | state.previousVersion = appVersion
15 | return state
16 | })
17 | transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { _ in
18 | return ContactsSettings(synchronizeContacts: syncContacts)
19 | })
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/TelegramCore/InlineBotMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class InlineBotMessageAttribute: MessageAttribute {
9 | public let peerId: PeerId?
10 | public let title: String?
11 |
12 | public var associatedPeerIds: [PeerId] {
13 | if let peerId = self.peerId {
14 | return [peerId]
15 | } else {
16 | return []
17 | }
18 | }
19 |
20 | init(peerId: PeerId?, title: String?) {
21 | self.peerId = peerId
22 | self.title = title
23 | }
24 |
25 | required public init(decoder: PostboxDecoder) {
26 | if let peerId = decoder.decodeOptionalInt64ForKey("i") {
27 | self.peerId = PeerId(peerId)
28 | } else {
29 | self.peerId = nil
30 | }
31 | self.title = decoder.decodeOptionalStringForKey("t")
32 | }
33 |
34 | public func encode(_ encoder: PostboxEncoder) {
35 | if let peerId = self.peerId {
36 | encoder.encodeInt64(peerId.toInt64(), forKey: "i")
37 | } else {
38 | encoder.encodeNil(forKey: "i")
39 | }
40 | if let title = self.title {
41 | encoder.encodeString(title, forKey: "t")
42 | } else {
43 | encoder.encodeNil(forKey: "t")
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/TelegramCore/InteractivePhoneFormatter.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import TelegramCorePrivateModule
3 |
4 | public final class InteractivePhoneFormatter {
5 | private let formatter = NBAsYouTypeFormatter(regionCode: "US")!
6 |
7 | public init() {
8 | }
9 |
10 | public func updateText(_ text: String) -> (String?, String) {
11 | self.formatter.clear()
12 | let string = self.formatter.inputString(text)
13 | return (self.formatter.regionPrefix, string ?? "")
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/TelegramCore/LocalizationPreview.swift:
--------------------------------------------------------------------------------
1 | #if os(macOS)
2 | import PostboxMac
3 | import SwiftSignalKitMac
4 | import MtProtoKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | import MtProtoKitDynamic
9 | #endif
10 |
11 | public enum RequestLocalizationPreviewError {
12 | case generic
13 | }
14 |
15 | public func requestLocalizationPreview(network: Network, identifier: String) -> Signal {
16 | return network.request(Api.functions.langpack.getLanguage(langPack: "", langCode: identifier))
17 | |> mapError { _ -> RequestLocalizationPreviewError in
18 | return .generic
19 | }
20 | |> map { language -> LocalizationInfo in
21 | return LocalizationInfo(apiLanguage: language)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/TelegramCore/LoggedOutAccountAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class LoggedOutAccountAttribute: AccountRecordAttribute {
9 | public init() {
10 | }
11 |
12 | public init(decoder: PostboxDecoder) {
13 | }
14 |
15 | public func encode(_ encoder: PostboxEncoder) {
16 | }
17 |
18 | public func isEqual(to: AccountRecordAttribute) -> Bool {
19 | return to is LoggedOutAccountAttribute
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/TelegramCore/MD5.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import TelegramCorePrivateModule
3 | #if os(macOS)
4 | import PostboxMac
5 | #else
6 | import Postbox
7 | #endif
8 |
9 | public extension MemoryBuffer {
10 | public func md5Digest() -> Data {
11 | return CryptoMD5(self.memory, Int32(self.length))
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedAppConfigurationUpdates.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | func managedAppConfigurationUpdates(postbox: Postbox, network: Network) -> Signal {
13 | let poll = Signal { subscriber in
14 | return (network.request(Api.functions.help.getAppConfig())
15 | |> retryRequest
16 | |> mapToSignal { result -> Signal in
17 | return postbox.transaction { transaction -> Void in
18 | if let data = JSON(apiJson: result) {
19 | updateAppConfiguration(transaction: transaction, { configuration -> AppConfiguration in
20 | var configuration = configuration
21 | configuration.data = data
22 | return configuration
23 | })
24 | }
25 | }
26 | }).start()
27 | }
28 | return (poll |> then(.complete() |> suspendAwareDelay(12.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
29 | }
30 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedAutodownloadSettingsUpdates.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | func managedAutodownloadSettingsUpdates(accountManager: AccountManager, network: Network) -> Signal {
13 | let poll = Signal { subscriber in
14 | return (network.request(Api.functions.account.getAutoDownloadSettings())
15 | |> retryRequest
16 | |> mapToSignal { result -> Signal in
17 | return updateAutodownloadSettingsInteractively(accountManager: accountManager, { _ -> AutodownloadSettings in
18 | return AutodownloadSettings(apiAutodownloadSettings: result)
19 | })
20 | }).start()
21 | }
22 | return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
23 | }
24 |
25 | public enum SavedAutodownloadPreset {
26 | case low
27 | case medium
28 | case high
29 | }
30 |
31 | public func saveAutodownloadSettings(account: Account, preset: SavedAutodownloadPreset, settings: AutodownloadPresetSettings) -> Signal {
32 | var flags: Int32 = 0
33 | switch preset {
34 | case .low:
35 | flags |= (1 << 0)
36 | case .high:
37 | flags |= (1 << 1)
38 | default:
39 | break
40 | }
41 | return account.network.request(Api.functions.account.saveAutoDownloadSettings(flags: flags, settings: apiAutodownloadPresetSettings(settings)))
42 | |> `catch` { _ -> Signal in
43 | return .complete()
44 | }
45 | |> mapToSignal { _ -> Signal in
46 | return .complete()
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedChatListHoles.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private final class ManagedChatListHolesState {
11 | private var holeDisposables: [ChatListHolesEntry: Disposable] = [:]
12 |
13 | func clearDisposables() -> [Disposable] {
14 | let disposables = Array(self.holeDisposables.values)
15 | self.holeDisposables.removeAll()
16 | return disposables
17 | }
18 |
19 | func update(entries: Set) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) {
20 | var removed: [Disposable] = []
21 | var added: [ChatListHolesEntry: MetaDisposable] = [:]
22 |
23 | for (entry, disposable) in self.holeDisposables {
24 | if !entries.contains(entry) {
25 | removed.append(disposable)
26 | self.holeDisposables.removeValue(forKey: entry)
27 | }
28 | }
29 |
30 | for entry in entries {
31 | if self.holeDisposables[entry] == nil {
32 | let disposable = MetaDisposable()
33 | self.holeDisposables[entry] = disposable
34 | added[entry] = disposable
35 | }
36 | }
37 |
38 | return (removed, added)
39 | }
40 | }
41 |
42 | func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: PeerId) -> Signal {
43 | return Signal { _ in
44 | let state = Atomic(value: ManagedChatListHolesState())
45 |
46 | let disposable = postbox.chatListHolesView().start(next: { view in
47 | let (removed, added) = state.with { state -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) in
48 | return state.update(entries: view.entries)
49 | }
50 |
51 | for disposable in removed {
52 | disposable.dispose()
53 | }
54 |
55 | for (entry, disposable) in added {
56 | disposable.set(fetchChatListHole(postbox: postbox, network: network, accountPeerId: accountPeerId, groupId: entry.groupId, hole: entry.hole).start())
57 | }
58 | })
59 |
60 | return ActionDisposable {
61 | disposable.dispose()
62 | for disposable in state.with({ state -> [Disposable] in
63 | state.clearDisposables()
64 | }) {
65 | disposable.dispose()
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedNotificationSettingsBehaviors.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | func managedNotificationSettingsBehaviors(postbox: Postbox) -> Signal {
11 | return postbox.combinedView(keys: [.peerNotificationSettingsBehaviorTimestampView])
12 | |> mapToSignal { views -> Signal in
13 | guard let view = views.views[.peerNotificationSettingsBehaviorTimestampView] as? PeerNotificationSettingsBehaviorTimestampView else {
14 | return .complete()
15 | }
16 | guard let earliestTimestamp = view.earliestTimestamp else {
17 | return .complete()
18 | }
19 |
20 | let checkSignal = postbox.transaction { transaction -> Void in
21 | let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
22 | for (peerId, notificationSettings) in transaction.getPeerIdsAndNotificationSettingsWithBehaviorTimestampLessThanOrEqualTo(timestamp) {
23 | if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings {
24 | if case let .muted(untilTimestamp) = notificationSettings.muteState, untilTimestamp <= timestamp {
25 | transaction.updateCurrentPeerNotificationSettings([peerId: notificationSettings.withUpdatedMuteState(.unmuted)])
26 | }
27 | }
28 | }
29 | }
30 | |> ignoreValues
31 |
32 | let timeout = earliestTimestamp - Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
33 | if timeout <= 0 {
34 | return checkSignal
35 | } else {
36 | return checkSignal |> delay(Double(timeout), queue: .mainQueue())
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedServiceViews.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | func managedServiceViews(accountPeerId: PeerId, network: Network, postbox: Postbox, stateManager: AccountStateManager, pendingMessageManager: PendingMessageManager) -> Signal {
11 | return Signal { _ in
12 | let disposable = DisposableSet()
13 | disposable.add(managedMessageHistoryHoles(accountPeerId: accountPeerId, network: network, postbox: postbox).start())
14 | disposable.add(managedChatListHoles(network: network, postbox: postbox, accountPeerId: accountPeerId).start())
15 | disposable.add(managedSynchronizePeerReadStates(network: network, postbox: postbox, stateManager: stateManager).start())
16 | disposable.add(managedSynchronizeGroupMessageStats(network: network, postbox: postbox, stateManager: stateManager).start())
17 |
18 | return disposable
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/TelegramCore/ManagedVoipConfigurationUpdates.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | func managedVoipConfigurationUpdates(postbox: Postbox, network: Network) -> Signal {
13 | let poll = Signal { subscriber in
14 | return (network.request(Api.functions.phone.getCallConfig())
15 | |> retryRequest
16 | |> mapToSignal { result -> Signal in
17 | return postbox.transaction { transaction -> Void in
18 | switch result {
19 | case let .dataJSON(data):
20 | updateVoipConfiguration(transaction: transaction, { configuration in
21 | var configuration = configuration
22 | configuration.serializedData = data
23 | return configuration
24 | })
25 | }
26 | }
27 | }).start()
28 | }
29 | return (poll |> then(.complete() |> suspendAwareDelay(12.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
30 | }
31 |
--------------------------------------------------------------------------------
/TelegramCore/MediaResourceApiUtils.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension SecretChatFileReference {
4 | func resource(key: SecretFileEncryptionKey, decryptedSize: Int32) -> SecretFileMediaResource {
5 | return SecretFileMediaResource(fileId: self.id, accessHash: self.accessHash, containerSize: self.size, decryptedSize: decryptedSize, datacenterId: Int(self.datacenterId), key: key)
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/TelegramCore/MediaResourceNetworkStatsTag.swift:
--------------------------------------------------------------------------------
1 | #if os(macOS)
2 | import PostboxMac
3 | #else
4 | import Postbox
5 | #endif
6 |
7 | public enum MediaResourceStatsCategory {
8 | case generic
9 | case image
10 | case video
11 | case audio
12 | case file
13 | case call
14 | }
15 |
16 | public final class TelegramMediaResourceFetchTag: MediaResourceFetchTag {
17 | public let statsCategory: MediaResourceStatsCategory
18 |
19 | public init(statsCategory: MediaResourceStatsCategory) {
20 | self.statsCategory = statsCategory
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/TelegramCore/MemoryBufferExtensions.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public extension MemoryBuffer {
9 | public convenience init(_ buffer: Buffer) {
10 | let memory = malloc(Int(buffer.size))!
11 | memcpy(memory, buffer.data, Int(buffer.size))
12 | self.init(memory: memory, capacity: Int(buffer.size), length: Int(buffer.size), freeWhenDone: true)
13 | }
14 | }
15 |
16 | extension Buffer {
17 | convenience init(bufferNoCopy: MemoryBuffer) {
18 | self.init(memory: bufferNoCopy.memory, size: bufferNoCopy.length, capacity: bufferNoCopy.length, freeWhenDone: false)
19 | }
20 |
21 | convenience init(buffer: MemoryBuffer) {
22 | let memory = malloc(buffer.length)!
23 | memcpy(memory, buffer.memory, buffer.length)
24 | self.init(memory: memory, size: buffer.length, capacity: buffer.length, freeWhenDone: true)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/TelegramCore/MonotonicTime.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | int64_t MonotonicGetBootTimestamp();
4 | int64_t MonotonicGetUptime();
5 |
--------------------------------------------------------------------------------
/TelegramCore/MonotonicTime.m:
--------------------------------------------------------------------------------
1 | #import "MonotonicTime.h"
2 |
3 | #include
4 |
5 | int64_t MonotonicGetBootTimestamp() {
6 | struct timeval boottime;
7 | int mib[2] = {CTL_KERN, KERN_BOOTTIME};
8 | size_t size = sizeof(boottime);
9 | int rc = sysctl(mib, 2, &boottime, &size, NULL, 0);
10 | if (rc != 0) {
11 | return 0;
12 | }
13 | return boottime.tv_sec * 1000000 + boottime.tv_usec;
14 | }
15 |
16 | int64_t MonotonicGetUptime() {
17 | int64_t before_now;
18 | int64_t after_now;
19 | struct timeval now;
20 |
21 | after_now = MonotonicGetBootTimestamp();
22 | do {
23 | before_now = after_now;
24 | gettimeofday(&now, NULL);
25 | after_now = MonotonicGetBootTimestamp();
26 | } while (after_now != before_now);
27 |
28 | return now.tv_sec * 1000000 + now.tv_usec - before_now;
29 | }
30 |
--------------------------------------------------------------------------------
/TelegramCore/MonotonicTime.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | import TelegramCorePrivateModule
4 |
5 | public struct MonotonicTime {
6 | public func getBootTimestamp() -> Int64 {
7 | return MonotonicGetBootTimestamp()
8 | }
9 |
10 | public func getUptime() -> Int64 {
11 | return MonotonicGetUptime()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/TelegramCore/NetworkLogging.h:
--------------------------------------------------------------------------------
1 | #ifndef Telegram_NetworkLogging_h
2 | #define Telegram_NetworkLogging_h
3 |
4 | #import
5 |
6 | void NetworkRegisterLoggingFunction();
7 | void NetworkSetLoggingEnabled(bool);
8 |
9 | void setBridgingTraceFunction(void (*)(NSString *, NSString *));
10 | void setBridgingShortTraceFunction(void (*)(NSString *, NSString *));
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/TelegramCore/NetworkLogging.m:
--------------------------------------------------------------------------------
1 | #import "NetworkLogging.h"
2 |
3 | #import
4 |
5 | #if TARGET_OS_IOS
6 | # import
7 | #else
8 | # import
9 | #endif
10 |
11 | static void (*bridgingTrace)(NSString *, NSString *);
12 | void setBridgingTraceFunction(void (*f)(NSString *, NSString *)) {
13 | bridgingTrace = f;
14 | }
15 |
16 | static void (*bridgingShortTrace)(NSString *, NSString *);
17 | void setBridgingShortTraceFunction(void (*f)(NSString *, NSString *)) {
18 | bridgingShortTrace = f;
19 | }
20 |
21 | static void TGTelegramLoggingFunction(NSString *format, va_list args) {
22 | if (bridgingTrace) {
23 | bridgingTrace(@"MT", [[NSString alloc] initWithFormat:format arguments:args]);
24 | }
25 | }
26 |
27 | static void TGTelegramShortLoggingFunction(NSString *format, va_list args) {
28 | if (bridgingShortTrace) {
29 | bridgingShortTrace(@"MT", [[NSString alloc] initWithFormat:format arguments:args]);
30 | }
31 | }
32 |
33 | void NetworkRegisterLoggingFunction() {
34 | static dispatch_once_t onceToken;
35 | dispatch_once(&onceToken, ^{
36 | MTLogSetLoggingFunction(&TGTelegramLoggingFunction);
37 | MTLogSetShortLoggingFunction(&TGTelegramShortLoggingFunction);
38 | });
39 | }
40 |
41 | void NetworkSetLoggingEnabled(bool value) {
42 | MTLogSetEnabled(value);
43 | }
44 |
--------------------------------------------------------------------------------
/TelegramCore/NotificationInfoMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct NotificationInfoMessageAttributeFlags: OptionSet {
9 | public var rawValue: Int32
10 |
11 | public init(rawValue: Int32) {
12 | self.rawValue = rawValue
13 | }
14 |
15 | public init() {
16 | self.rawValue = 0
17 | }
18 |
19 | public static let muted = NotificationInfoMessageAttributeFlags(rawValue: 1)
20 | public static let personal = NotificationInfoMessageAttributeFlags(rawValue: 2)
21 |
22 | }
23 |
24 | public class NotificationInfoMessageAttribute: MessageAttribute {
25 | public let flags: NotificationInfoMessageAttributeFlags
26 |
27 | public init(flags: NotificationInfoMessageAttributeFlags) {
28 | self.flags = flags
29 | }
30 |
31 | required public init(decoder: PostboxDecoder) {
32 | self.flags = NotificationInfoMessageAttributeFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
33 | }
34 |
35 | public func encode(_ encoder: PostboxEncoder) {
36 | encoder.encodeInt32(self.flags.rawValue, forKey: "f")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/TelegramCore/OutgoingChatContextResultMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class OutgoingChatContextResultMessageAttribute: MessageAttribute {
9 | public let queryId: Int64
10 | public let id: String
11 | public let hideVia: Bool
12 |
13 | init(queryId: Int64, id: String, hideVia: Bool) {
14 | self.queryId = queryId
15 | self.id = id
16 | self.hideVia = hideVia
17 | }
18 |
19 | required public init(decoder: PostboxDecoder) {
20 | self.queryId = decoder.decodeInt64ForKey("q", orElse: 0)
21 | self.id = decoder.decodeStringForKey("i", orElse: "")
22 | self.hideVia = decoder.decodeBoolForKey("v", orElse: false)
23 | }
24 |
25 | public func encode(_ encoder: PostboxEncoder) {
26 | encoder.encodeInt64(self.queryId, forKey: "q")
27 | encoder.encodeString(self.id, forKey: "i")
28 | encoder.encodeBool(self.hideVia, forKey: "v")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/TelegramCore/OutgoingContentInfoMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct OutgoingContentInfoFlags: OptionSet {
9 | public var rawValue: Int32
10 |
11 | public init() {
12 | self.rawValue = 0
13 | }
14 |
15 | public init(rawValue: Int32) {
16 | self.rawValue = rawValue
17 | }
18 |
19 | public static let disableLinkPreviews = OutgoingContentInfoFlags(rawValue: 1 << 0)
20 | }
21 |
22 | public class OutgoingContentInfoMessageAttribute: MessageAttribute {
23 | public let flags: OutgoingContentInfoFlags
24 |
25 | public init(flags: OutgoingContentInfoFlags) {
26 | self.flags = flags
27 | }
28 |
29 | required public init(decoder: PostboxDecoder) {
30 | self.flags = OutgoingContentInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
31 | }
32 |
33 | public func encode(_ encoder: PostboxEncoder) {
34 | encoder.encodeInt32(self.flags.rawValue, forKey: "f")
35 | }
36 |
37 | public func withUpdatedFlags(_ flags: OutgoingContentInfoFlags) -> OutgoingContentInfoMessageAttribute {
38 | return OutgoingContentInfoMessageAttribute(flags: flags)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/TelegramCore/OutgoingMessageInfoAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct OutgoingMessageInfoFlags: OptionSet {
9 | public var rawValue: Int32
10 |
11 | public init() {
12 | self.rawValue = 0
13 | }
14 |
15 | public init(rawValue: Int32) {
16 | self.rawValue = rawValue
17 | }
18 |
19 | public static var transformedMedia = OutgoingMessageInfoFlags(rawValue: 1 << 0)
20 | }
21 |
22 | public class OutgoingMessageInfoAttribute: MessageAttribute {
23 | public let uniqueId: Int64
24 | public let flags: OutgoingMessageInfoFlags
25 | public let acknowledged: Bool
26 |
27 | init(uniqueId: Int64, flags: OutgoingMessageInfoFlags, acknowledged: Bool) {
28 | self.uniqueId = uniqueId
29 | self.flags = flags
30 | self.acknowledged = acknowledged
31 | }
32 |
33 | required public init(decoder: PostboxDecoder) {
34 | self.uniqueId = decoder.decodeInt64ForKey("u", orElse: 0)
35 | self.flags = OutgoingMessageInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
36 | self.acknowledged = decoder.decodeInt32ForKey("ack", orElse: 0) != 0
37 | }
38 |
39 | public func encode(_ encoder: PostboxEncoder) {
40 | encoder.encodeInt64(self.uniqueId, forKey: "u")
41 | encoder.encodeInt32(self.flags.rawValue, forKey: "f")
42 | encoder.encodeInt32(self.acknowledged ? 1 : 0, forKey: "ack")
43 | }
44 |
45 | public func withUpdatedFlags(_ flags: OutgoingMessageInfoFlags) -> OutgoingMessageInfoAttribute {
46 | return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: flags, acknowledged: self.acknowledged)
47 | }
48 |
49 | public func withUpdatedAcknowledged(_ acknowledged: Bool) -> OutgoingMessageInfoAttribute {
50 | return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: self.flags, acknowledged: acknowledged)
51 | }
52 | }
53 |
54 | public extension Message {
55 | public var isSentOrAcknowledged: Bool {
56 | if self.flags.contains(.Failed) {
57 | return false
58 | } else if self.flags.isSending {
59 | for attribute in self.attributes {
60 | if let attribute = attribute as? OutgoingMessageInfoAttribute {
61 | if attribute.acknowledged {
62 | return true
63 | }
64 | }
65 | }
66 | return false
67 | } else {
68 | return true
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/TelegramCore/PeerAccessRestrictionInfo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class PeerAccessRestrictionInfo: PostboxCoding, Equatable {
9 | public let reason: String
10 |
11 | init(reason: String) {
12 | self.reason = reason
13 | }
14 |
15 | public init(decoder: PostboxDecoder) {
16 | self.reason = decoder.decodeStringForKey("rsn", orElse: "")
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeString(self.reason, forKey: "rsn")
21 | }
22 |
23 | public static func ==(lhs: PeerAccessRestrictionInfo, rhs: PeerAccessRestrictionInfo) -> Bool {
24 | return lhs.reason == rhs.reason
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/TelegramCore/PeerCommands.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public struct PeerCommand: Equatable {
11 | public let peer: Peer
12 | public let command: BotCommand
13 |
14 | public static func ==(lhs: PeerCommand, rhs: PeerCommand) -> Bool {
15 | return lhs.peer.isEqual(rhs.peer) && lhs.command == rhs.command
16 | }
17 | }
18 |
19 | public struct PeerCommands: Equatable {
20 | public let commands: [PeerCommand]
21 |
22 | public static func ==(lhs: PeerCommands, rhs: PeerCommands) -> Bool {
23 | return lhs.commands == rhs.commands
24 | }
25 | }
26 |
27 | public func peerCommands(account: Account, id: PeerId) -> Signal {
28 | return account.postbox.peerView(id: id) |> map { view -> PeerCommands in
29 | if let cachedUserData = view.cachedData as? CachedUserData {
30 | if let botInfo = cachedUserData.botInfo {
31 | if let botPeer = view.peers[id] {
32 | var commands: [PeerCommand] = []
33 | for command in botInfo.commands {
34 | commands.append(PeerCommand(peer: botPeer, command: command))
35 | }
36 | return PeerCommands(commands: commands)
37 | }
38 | }
39 | return PeerCommands(commands: [])
40 | }
41 | else if let cachedGroupData = view.cachedData as? CachedGroupData {
42 | var commands: [PeerCommand] = []
43 | for cachedBotInfo in cachedGroupData.botInfos {
44 | if let botPeer = view.peers[cachedBotInfo.peerId] {
45 | for command in cachedBotInfo.botInfo.commands {
46 | commands.append(PeerCommand(peer: botPeer, command: command))
47 | }
48 | }
49 | }
50 | return PeerCommands(commands: commands)
51 | } else if let cachedChannelData = view.cachedData as? CachedChannelData {
52 | var commands: [PeerCommand] = []
53 | for cachedBotInfo in cachedChannelData.botInfos {
54 | if let botPeer = view.peers[cachedBotInfo.peerId] {
55 | for command in cachedBotInfo.botInfo.commands {
56 | commands.append(PeerCommand(peer: botPeer, command: command))
57 | }
58 | }
59 | }
60 | return PeerCommands(commands: commands)
61 | } else {
62 | return PeerCommands(commands: [])
63 | }
64 | }
65 | |> distinctUntilChanged
66 | }
67 |
--------------------------------------------------------------------------------
/TelegramCore/PeerGroupMessageStateVersionAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class PeerGroupMessageStateVersionAttribute: MessageAttribute {
9 | public let stateIndex: Int32
10 |
11 | public init(stateIndex: Int32) {
12 | self.stateIndex = stateIndex
13 | }
14 |
15 | required public init(decoder: PostboxDecoder) {
16 | self.stateIndex = decoder.decodeInt32ForKey("p", orElse: 0)
17 | }
18 |
19 | public func encode(_ encoder: PostboxEncoder) {
20 | encoder.encodeInt32(self.stateIndex, forKey: "p")
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/TelegramCore/PeerLiveLocationsContext.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func topPeerActiveLiveLocationMessages(viewTracker: AccountViewTracker, accountPeerId: PeerId, peerId: PeerId) -> Signal<(Peer?, [Message]), NoError> {
11 | return viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 50, fixedCombinedReadStates: nil, tagMask: .liveLocation, orderStatistics: [], additionalData: [.peer(accountPeerId)])
12 | |> map { (view, _, _) -> (Peer?, [Message]) in
13 | var accountPeer: Peer?
14 | for entry in view.additionalData {
15 | if case let .peer(id, peer) = entry {
16 | accountPeer = peer
17 | break
18 | }
19 | }
20 |
21 | let timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
22 | var result: [Message] = []
23 | for entry in view.entries {
24 | for media in entry.message.media {
25 | if let location = media as? TelegramMediaMap, let liveBroadcastingTimeout = location.liveBroadcastingTimeout {
26 | if entry.message.timestamp + liveBroadcastingTimeout > timestamp {
27 | result.append(entry.message)
28 | }
29 | } else {
30 | assertionFailure()
31 | }
32 | }
33 | }
34 | return (accountPeer, result)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/TelegramCore/PeerParticipants.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private struct PeerParticipants: Equatable {
11 | let peers: [Peer]
12 |
13 | static func ==(lhs: PeerParticipants, rhs: PeerParticipants) -> Bool {
14 | if lhs.peers.count != rhs.peers.count {
15 | return false
16 | }
17 | for i in 0 ..< lhs.peers.count {
18 | if !lhs.peers[i].isEqual(rhs.peers[i]) {
19 | return false
20 | }
21 | }
22 | return true
23 | }
24 | }
25 |
26 | public func peerParticipants(postbox: Postbox, id: PeerId) -> Signal<[Peer], NoError> {
27 | return postbox.peerView(id: id) |> map { view -> PeerParticipants in
28 | if let cachedGroupData = view.cachedData as? CachedGroupData, let participants = cachedGroupData.participants {
29 | var peers: [Peer] = []
30 | for participant in participants.participants {
31 | if let peer = view.peers[participant.peerId] {
32 | peers.append(peer)
33 | }
34 | }
35 | return PeerParticipants(peers: peers)
36 | } else {
37 | return PeerParticipants(peers: [])
38 | }
39 | }
40 | |> distinctUntilChanged |> map { participants in
41 | return participants.peers
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/TelegramCore/PeerReportStatus.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum PeerReportStatus: Int32 {
4 | case unknown
5 | case none
6 | case canReport
7 | case didReport
8 | }
9 |
--------------------------------------------------------------------------------
/TelegramCore/PeerSpecificStickerPack.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private struct WrappedStickerPackCollectionInfo: Equatable {
11 | let info: StickerPackCollectionInfo?
12 |
13 | static func ==(lhs: WrappedStickerPackCollectionInfo, rhs: WrappedStickerPackCollectionInfo) -> Bool {
14 | return lhs.info == rhs.info
15 | }
16 | }
17 |
18 | public struct PeerSpecificStickerPackData {
19 | public let packInfo: (StickerPackCollectionInfo, [ItemCollectionItem])?
20 | public let canSetup: Bool
21 | }
22 |
23 | public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId: PeerId) -> Signal {
24 | if peerId.namespace == Namespaces.Peer.CloudChannel {
25 | let signal: Signal<(WrappedStickerPackCollectionInfo, Bool), NoError> = postbox.combinedView(keys: [.cachedPeerData(peerId: peerId)])
26 | |> map { view -> (WrappedStickerPackCollectionInfo, Bool) in
27 | let dataView = view.views[.cachedPeerData(peerId: peerId)] as? CachedPeerDataView
28 | return (WrappedStickerPackCollectionInfo(info: (dataView?.cachedPeerData as? CachedChannelData)?.stickerPack), (dataView?.cachedPeerData as? CachedChannelData)?.flags.contains(.canSetStickerSet) ?? false)
29 | }
30 | |> distinctUntilChanged(isEqual: { lhs, rhs -> Bool in
31 | return lhs.0 == rhs.0 && lhs.1 == rhs.1
32 | })
33 |
34 | return signal
35 | |> mapToSignal { info, canInstall -> Signal in
36 | if let info = info.info {
37 | return cachedStickerPack(postbox: postbox, network: network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceRemote: false)
38 | |> map { result -> PeerSpecificStickerPackData in
39 | if case let .result(info, items, _) = result {
40 | return PeerSpecificStickerPackData(packInfo: (info, items), canSetup: canInstall)
41 | } else {
42 | return PeerSpecificStickerPackData(packInfo: nil, canSetup: canInstall)
43 | }
44 | }
45 | } else {
46 | return .single(PeerSpecificStickerPackData(packInfo: nil, canSetup: canInstall))
47 | }
48 | }
49 | } else {
50 | return .single(PeerSpecificStickerPackData(packInfo: nil, canSetup: false))
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/TelegramCore/PhoneNumber.swift:
--------------------------------------------------------------------------------
1 |
2 | public struct PhoneNumberWithLabel: Equatable {
3 | public let label: String
4 | public let number: String
5 |
6 | public init(label: String, number: String) {
7 | self.label = label
8 | self.number = number
9 | }
10 |
11 | public static func ==(lhs: PhoneNumberWithLabel, rhs: PhoneNumberWithLabel) -> Bool {
12 | return lhs.label == rhs.label && lhs.number == rhs.number
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/TelegramCore/PhoneNumbers.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import TelegramCorePrivateModule
3 |
4 | private let phoneNumberUtil = NBPhoneNumberUtil()
5 |
6 | public func formatPhoneNumber(_ string: String) -> String {
7 | do {
8 | let number = try phoneNumberUtil.parse("+" + string, defaultRegion: nil)
9 | return try phoneNumberUtil.format(number, numberFormat: .INTERNATIONAL)
10 | } catch _ {
11 | return string
12 | }
13 | }
14 |
15 | public func isViablePhoneNumber(_ string: String) -> Bool {
16 | return phoneNumberUtil.isViablePhoneNumber(string)
17 | }
18 |
--------------------------------------------------------------------------------
/TelegramCore/Random.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public func arc4random64() -> Int64 {
4 | var value: Int64 = 0
5 | arc4random_buf(&value, 8)
6 | return value
7 | }
8 |
--------------------------------------------------------------------------------
/TelegramCore/RateCall.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import MtProtoKitMac
5 | import SwiftSignalKitMac
6 | #else
7 | import Postbox
8 | import MtProtoKitDynamic
9 | import SwiftSignalKit
10 | #endif
11 |
12 | public func rateCall(account: Account, callId: CallId, starsCount: Int32, comment: String = "", userInitiated: Bool) -> Signal {
13 | var flags: Int32 = 0
14 | if userInitiated {
15 | flags |= (1 << 0)
16 | }
17 | return account.network.request(Api.functions.phone.setCallRating(flags: flags, peer: Api.InputPhoneCall.inputPhoneCall(id: callId.id, accessHash: callId.accessHash), rating: starsCount, comment: comment))
18 | |> retryRequest
19 | |> map { _ in }
20 | }
21 |
22 | public func saveCallDebugLog(account: Account, callId: CallId, log: String) -> Signal {
23 | return account.network.request(Api.functions.phone.saveCallDebug(peer: Api.InputPhoneCall.inputPhoneCall(id: callId.id, accessHash: callId.accessHash), debug: .dataJSON(data: log)))
24 | |> retryRequest
25 | |> map { _ in }
26 | }
27 |
--------------------------------------------------------------------------------
/TelegramCore/Reachability.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
7 | */
8 |
9 | #import
10 | #import
11 | #import
12 |
13 |
14 | typedef enum : NSInteger {
15 | NotReachable = 0,
16 | ReachableViaWiFi,
17 | ReachableViaWWAN
18 | } NetworkStatus;
19 |
20 | #pragma mark IPv6 Support
21 | //Reachability fully support IPv6. For full details, see ReadMe.md.
22 |
23 |
24 | extern NSString *kReachabilityChangedNotification;
25 |
26 |
27 | @interface Reachability : NSObject
28 |
29 | @property (nonatomic, copy) void (^reachabilityChanged)(NetworkStatus status);
30 |
31 | /*!
32 | * Use to check the reachability of a given host name.
33 | */
34 | + (instancetype)reachabilityWithHostName:(NSString *)hostName;
35 |
36 | /*!
37 | * Use to check the reachability of a given IP address.
38 | */
39 | + (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress;
40 |
41 | /*!
42 | * Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
43 | */
44 | + (instancetype)reachabilityForInternetConnection;
45 |
46 |
47 | #pragma mark reachabilityForLocalWiFi
48 | //reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information.
49 | //+ (instancetype)reachabilityForLocalWiFi;
50 |
51 | /*!
52 | * Start listening for reachability notifications on the current run loop.
53 | */
54 | - (BOOL)startNotifier;
55 | - (void)stopNotifier;
56 |
57 | - (NetworkStatus)currentReachabilityStatus;
58 |
59 | /*!
60 | * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
61 | */
62 | - (BOOL)connectionRequired;
63 |
64 | @end
65 |
66 |
67 |
--------------------------------------------------------------------------------
/TelegramCore/RecentAccountSessions.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func requestRecentAccountSessions(account: Account) -> Signal<[RecentAccountSession], NoError> {
11 | return account.network.request(Api.functions.account.getAuthorizations())
12 | |> retryRequest
13 | |> map { result -> [RecentAccountSession] in
14 | var sessions: [RecentAccountSession] = []
15 | switch result {
16 | case let .authorizations(authorizations):
17 | for authorization in authorizations {
18 | sessions.append(RecentAccountSession(apiAuthorization: authorization))
19 | }
20 | }
21 | return sessions
22 | }
23 | }
24 |
25 | public enum TerminateSessionError {
26 | case generic
27 | case freshReset
28 | }
29 |
30 | public func terminateAccountSession(account: Account, hash: Int64) -> Signal {
31 | return account.network.request(Api.functions.account.resetAuthorization(hash: hash))
32 | |> mapError { error -> TerminateSessionError in
33 | if error.errorCode == 406 {
34 | return .freshReset
35 | }
36 | return .generic
37 | }
38 | |> mapToSignal { _ -> Signal in
39 | return .single(Void())
40 | }
41 | }
42 |
43 | public func terminateOtherAccountSessions(account: Account) -> Signal {
44 | return account.network.request(Api.functions.auth.resetAuthorizations())
45 | |> retryRequest
46 | |> mapToSignal { _ -> Signal in
47 | return .single(Void())
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/TelegramCore/RecentMediaItem.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct RecentMediaItemId {
9 | public let rawValue: MemoryBuffer
10 | public let mediaId: MediaId
11 |
12 | init(_ rawValue: MemoryBuffer) {
13 | self.rawValue = rawValue
14 | assert(rawValue.length == 4 + 8)
15 | var mediaIdNamespace: Int32 = 0
16 | var mediaIdId: Int64 = 0
17 | memcpy(&mediaIdNamespace, rawValue.memory, 4)
18 | memcpy(&mediaIdId, rawValue.memory.advanced(by: 4), 8)
19 | self.mediaId = MediaId(namespace: mediaIdNamespace, id: mediaIdId)
20 | }
21 |
22 | public init(_ mediaId: MediaId) {
23 | self.mediaId = mediaId
24 | var mediaIdNamespace: Int32 = mediaId.namespace
25 | var mediaIdId: Int64 = mediaId.id
26 | self.rawValue = MemoryBuffer(memory: malloc(4 + 8)!, capacity: 4 + 8, length: 4 + 8, freeWhenDone: true)
27 | memcpy(self.rawValue.memory, &mediaIdNamespace, 4)
28 | memcpy(self.rawValue.memory.advanced(by: 4), &mediaIdId, 8)
29 | }
30 | }
31 |
32 | public final class RecentMediaItem: OrderedItemListEntryContents, Equatable {
33 | public let media: Media
34 |
35 | init(_ media: Media) {
36 | self.media = media
37 | }
38 |
39 | public init(decoder: PostboxDecoder) {
40 | self.media = decoder.decodeObjectForKey("m") as! Media
41 | }
42 |
43 | public func encode(_ encoder: PostboxEncoder) {
44 | encoder.encodeObject(self.media, forKey: "m")
45 | }
46 |
47 | public static func ==(lhs: RecentMediaItem, rhs: RecentMediaItem) -> Bool {
48 | return lhs.media.isEqual(to: rhs.media)
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/TelegramCore/RecentPeerItem.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct RecentPeerItemId {
9 | public let rawValue: MemoryBuffer
10 | public let peerId: PeerId
11 |
12 | init(_ rawValue: MemoryBuffer) {
13 | self.rawValue = rawValue
14 | assert(rawValue.length == 8)
15 | var idValue: Int64 = 0
16 | memcpy(&idValue, rawValue.memory, 8)
17 | self.peerId = PeerId(idValue)
18 | }
19 |
20 | init(_ peerId: PeerId) {
21 | self.peerId = peerId
22 | var idValue: Int64 = peerId.toInt64()
23 | self.rawValue = MemoryBuffer(memory: malloc(8)!, capacity: 8, length: 8, freeWhenDone: true)
24 | memcpy(self.rawValue.memory, &idValue, 8)
25 | }
26 | }
27 |
28 | public final class RecentPeerItem: OrderedItemListEntryContents {
29 | public let rating: Double
30 |
31 | init(rating: Double) {
32 | self.rating = rating
33 | }
34 |
35 | public init(decoder: PostboxDecoder) {
36 | self.rating = decoder.decodeDoubleForKey("r", orElse: 0.0)
37 | }
38 |
39 | public func encode(_ encoder: PostboxEncoder) {
40 | encoder.encodeDouble(self.rating, forKey: "r")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/TelegramCore/RecentlyUsedHashtags.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | private struct RecentHashtagItemId {
11 | public let rawValue: MemoryBuffer
12 |
13 | var value: String {
14 | return String(data: self.rawValue.makeData(), encoding: .utf8) ?? ""
15 | }
16 |
17 | init(_ rawValue: MemoryBuffer) {
18 | self.rawValue = rawValue
19 | }
20 |
21 | init?(_ value: String) {
22 | if let data = value.data(using: .utf8) {
23 | self.rawValue = MemoryBuffer(data: data)
24 | } else {
25 | return nil
26 | }
27 | }
28 | }
29 |
30 | final class RecentHashtagItem: OrderedItemListEntryContents {
31 | init() {
32 | }
33 |
34 | public init(decoder: PostboxDecoder) {
35 | }
36 |
37 | public func encode(_ encoder: PostboxEncoder) {
38 | }
39 | }
40 |
41 | func addRecentlyUsedHashtag(transaction: Transaction, string: String) {
42 | if let itemId = RecentHashtagItemId(string) {
43 | transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlyUsedHashtags, item: OrderedItemListEntry(id: itemId.rawValue, contents: RecentHashtagItem()), removeTailIfCountExceeds: 100)
44 | }
45 | }
46 |
47 | public func removeRecentlyUsedHashtag(postbox: Postbox, string: String) -> Signal {
48 | return postbox.transaction { transaction -> Void in
49 | if let itemId = RecentHashtagItemId(string) {
50 | transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlyUsedHashtags, itemId: itemId.rawValue)
51 | }
52 | }
53 | }
54 |
55 | public func recentlyUsedHashtags(postbox: Postbox) -> Signal<[String], NoError> {
56 | return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlyUsedHashtags)])
57 | |> mapToSignal { view -> Signal<[String], NoError> in
58 | return postbox.transaction { transaction -> [String] in
59 | var result: [String] = []
60 | if let view = view.views[.orderedItemList(id: Namespaces.OrderedItemList.RecentlyUsedHashtags)] as? OrderedItemListView {
61 | for item in view.items {
62 | let value = RecentHashtagItemId(item.id).value
63 | result.append(value)
64 | }
65 | }
66 | return result
67 | }
68 | }
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/TelegramCore/Regex.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct Regex {
4 | let pattern: String
5 | let options: NSRegularExpression.Options!
6 |
7 | private var matcher: NSRegularExpression {
8 | return try! NSRegularExpression(pattern: self.pattern, options: self.options)
9 | }
10 |
11 | public init(_ pattern: String) {
12 | self.pattern = pattern
13 | self.options = []
14 | }
15 |
16 | public func match(_ string: String, options: NSRegularExpression.MatchingOptions = []) -> Bool {
17 | return self.matcher.numberOfMatches(in: string, options: options, range: NSMakeRange(0, string.utf16.count)) != 0
18 | }
19 | }
20 |
21 | public protocol RegularExpressionMatchable {
22 | func match(_ regex: Regex) -> Bool
23 | }
24 |
25 | extension String: RegularExpressionMatchable {
26 | public func match(_ regex: Regex) -> Bool {
27 | return regex.match(self)
28 | }
29 | }
30 |
31 | public func ~=(pattern: Regex, matchable: T) -> Bool {
32 | return matchable.match(pattern)
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/RegisterNotificationToken.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import SwiftSignalKitMac
4 | import PostboxMac
5 | #else
6 | import SwiftSignalKit
7 | import Postbox
8 | #endif
9 |
10 | public enum NotificationTokenType {
11 | case aps(encrypt: Bool)
12 | case voip
13 | }
14 |
15 | public func unregisterNotificationToken(account: Account, token: Data, type: NotificationTokenType, otherAccountUserIds: [Int32]) -> Signal {
16 | let mappedType: Int32
17 | switch type {
18 | case .aps:
19 | mappedType = 1
20 | case .voip:
21 | mappedType = 9
22 | }
23 | return account.network.request(Api.functions.account.unregisterDevice(tokenType: mappedType, token: hexString(token), otherUids: otherAccountUserIds))
24 | |> retryRequest
25 | |> ignoreValues
26 | }
27 |
28 | public func registerNotificationToken(account: Account, token: Data, type: NotificationTokenType, sandbox: Bool, otherAccountUserIds: [Int32]) -> Signal {
29 | return masterNotificationsKey(account: account, ignoreDisabled: false)
30 | |> mapToSignal { masterKey -> Signal in
31 | let mappedType: Int32
32 | var keyData = Data()
33 | switch type {
34 | case let .aps(encrypt):
35 | mappedType = 1
36 | if encrypt {
37 | keyData = masterKey.data
38 | }
39 | case .voip:
40 | mappedType = 9
41 | keyData = masterKey.data
42 | }
43 | return account.network.request(Api.functions.account.registerDevice(tokenType: mappedType, token: hexString(token), appSandbox: sandbox ? .boolTrue : .boolFalse, secret: Buffer(data: keyData), otherUids: otherAccountUserIds))
44 | |> retryRequest
45 | |> ignoreValues
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/TelegramCore/RegularChatState.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | final class RegularChatState: PeerChatState, Equatable {
9 | let invalidatedPts: Int32?
10 |
11 | init(invalidatedPts: Int32?) {
12 | self.invalidatedPts = invalidatedPts
13 | }
14 |
15 | init(decoder: PostboxDecoder) {
16 | self.invalidatedPts = decoder.decodeOptionalInt32ForKey("ipts")
17 | }
18 |
19 | func encode(_ encoder: PostboxEncoder) {
20 | if let invalidatedPts = self.invalidatedPts {
21 | encoder.encodeInt32(invalidatedPts, forKey: "ipts")
22 | } else {
23 | encoder.encodeNil(forKey: "ipts")
24 | }
25 | }
26 |
27 | func withUpdatedInvalidatedPts(_ invalidatedPts: Int32?) -> RegularChatState {
28 | return RegularChatState(invalidatedPts: invalidatedPts)
29 | }
30 |
31 | func equals(_ other: PeerChatState) -> Bool {
32 | if let other = other as? RegularChatState, other == self {
33 | return true
34 | }
35 | return false
36 | }
37 |
38 | static func ==(lhs: RegularChatState, rhs: RegularChatState) -> Bool {
39 | return lhs.invalidatedPts == rhs.invalidatedPts
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TelegramCore/RemoteStorageConfiguration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public final class RemoteStorageConfiguration: PreferencesEntry {
11 | public let webDocumentsHostDatacenterId: Int32
12 |
13 | init(webDocumentsHostDatacenterId: Int32) {
14 | self.webDocumentsHostDatacenterId = webDocumentsHostDatacenterId
15 | }
16 |
17 | public init(decoder: PostboxDecoder) {
18 | self.webDocumentsHostDatacenterId = decoder.decodeInt32ForKey("webDocumentsHostDatacenterId", orElse: 4)
19 | }
20 |
21 | public func encode(_ encoder: PostboxEncoder) {
22 | encoder.encodeInt32(self.webDocumentsHostDatacenterId, forKey: "webDocumentsHostDatacenterId")
23 | }
24 |
25 | public func isEqual(to: PreferencesEntry) -> Bool {
26 | guard let to = to as? RemoteStorageConfiguration else {
27 | return false
28 | }
29 | if self.webDocumentsHostDatacenterId != to.webDocumentsHostDatacenterId {
30 | return false
31 | }
32 | return true
33 | }
34 | }
35 |
36 | public func currentWebDocumentsHostDatacenterId(postbox: Postbox, isTestingEnvironment: Bool) -> Signal {
37 | return postbox.transaction { transaction -> Int32 in
38 | if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.remoteStorageConfiguration) as? RemoteStorageConfiguration {
39 | return entry.webDocumentsHostDatacenterId
40 | } else {
41 | if isTestingEnvironment {
42 | return 2
43 | } else {
44 | return 4
45 | }
46 | }
47 | }
48 | }
49 |
50 | func updateRemoteStorageConfiguration(transaction: Transaction, configuration: RemoteStorageConfiguration) {
51 | let current = transaction.getPreferencesEntry(key: PreferencesKeys.remoteStorageConfiguration) as? RemoteStorageConfiguration
52 | if let current = current, current.isEqual(to: configuration) {
53 | return
54 | }
55 |
56 | transaction.setPreferencesEntry(key: PreferencesKeys.remoteStorageConfiguration, value: configuration)
57 | }
58 |
--------------------------------------------------------------------------------
/TelegramCore/ReplyMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ReplyMessageAttribute: MessageAttribute {
9 | public let messageId: MessageId
10 |
11 | public var associatedMessageIds: [MessageId] {
12 | return [self.messageId]
13 | }
14 |
15 | public init(messageId: MessageId) {
16 | self.messageId = messageId
17 | }
18 |
19 | required public init(decoder: PostboxDecoder) {
20 | let namespaceAndId: Int64 = decoder.decodeInt64ForKey("i", orElse: 0)
21 | self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), namespace: Int32(namespaceAndId & 0xffffffff), id: Int32((namespaceAndId >> 32) & 0xffffffff))
22 | }
23 |
24 | public func encode(_ encoder: PostboxEncoder) {
25 | let namespaceAndId = Int64(self.messageId.namespace) | (Int64(self.messageId.id) << 32)
26 | encoder.encodeInt64(namespaceAndId, forKey: "i")
27 | encoder.encodeInt64(self.messageId.peerId.toInt64(), forKey: "p")
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/TelegramCore/RequestChatContextResults.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public func requestChatContextResults(account: Account, botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String) -> Signal {
13 | return combineLatest(account.postbox.transaction { transaction -> (bot: Peer, peer: Peer)? in
14 | if let bot = transaction.getPeer(botId), let peer = transaction.getPeer(peerId) {
15 | return (bot, peer)
16 | } else {
17 | return nil
18 | }
19 | }, location)
20 | |> mapToSignal { botAndPeer, location -> Signal in
21 | if let (bot, peer) = botAndPeer, let inputBot = apiInputUser(bot) {
22 | var flags: Int32 = 0
23 | var inputPeer: Api.InputPeer = .inputPeerEmpty
24 | var geoPoint: Api.InputGeoPoint?
25 | if let actualInputPeer = apiInputPeer(peer) {
26 | inputPeer = actualInputPeer
27 | }
28 | if let (latitude, longitude) = location {
29 | flags |= (1 << 0)
30 | geoPoint = Api.InputGeoPoint.inputGeoPoint(lat: latitude, long: longitude)
31 | }
32 | return account.network.request(Api.functions.messages.getInlineBotResults(flags: flags, bot: inputBot, peer: inputPeer, geoPoint: geoPoint, query: query, offset: offset))
33 | |> map { result -> ChatContextResultCollection? in
34 | return ChatContextResultCollection(apiResults: result, botId: bot.id, peerId: peerId, query: query, geoPoint: location)
35 | }
36 | |> `catch` { _ -> Signal in
37 | return .single(nil)
38 | }
39 | } else {
40 | return .single(nil)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/TelegramCore/RequestPhoneNumber.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func requestPhoneNumber(account: Account, peerId: PeerId) -> Signal {
11 | return .never()
12 | /*return account.postbox.transaction { transaction -> Api.InputPeer? in
13 | return transaction.getPeer(peerId).flatMap(apiInputPeer)
14 | }
15 | |> mapToSignal { inputPeer -> Signal in
16 | guard let inputPeer = inputPeer else {
17 | return .complete()
18 | }
19 | return account.network.request(Api.functions.messages.sendPhoneNumberRequest(peer: inputPeer, randomId: arc4random64()))
20 | |> map(Optional.init)
21 | |> `catch` { _ -> Signal in
22 | return .single(nil)
23 | }
24 | |> mapToSignal { updates -> Signal in
25 | if let updates = updates {
26 | account.stateManager.addUpdates(updates)
27 | }
28 | return .complete()
29 | }
30 | }*/
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/TelegramCore/SavedStickerItem.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class SavedStickerItem: OrderedItemListEntryContents, Equatable {
9 | public let file: TelegramMediaFile
10 | public let stringRepresentations: [String]
11 |
12 | init(file: TelegramMediaFile, stringRepresentations: [String]) {
13 | self.file = file
14 | self.stringRepresentations = stringRepresentations
15 | }
16 |
17 | public init(decoder: PostboxDecoder) {
18 | self.file = decoder.decodeObjectForKey("f") as! TelegramMediaFile
19 | self.stringRepresentations = decoder.decodeStringArrayForKey("sr")
20 | }
21 |
22 | public func encode(_ encoder: PostboxEncoder) {
23 | encoder.encodeObject(self.file, forKey: "f")
24 | encoder.encodeStringArray(self.stringRepresentations, forKey: "sr")
25 | }
26 |
27 | public static func ==(lhs: SavedStickerItem, rhs: SavedStickerItem) -> Bool {
28 | return lhs.file.isEqual(to: rhs.file) && lhs.stringRepresentations == rhs.stringRepresentations
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/TelegramCore/SearchBotsConfiguration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public struct SearchBotsConfiguration: Equatable, PreferencesEntry {
9 | public let imageBotUsername: String?
10 | public let gifBotUsername: String?
11 | public let venueBotUsername: String?
12 |
13 | public static var defaultValue: SearchBotsConfiguration {
14 | return SearchBotsConfiguration(imageBotUsername: "bing", gifBotUsername: "gif", venueBotUsername: "foursquare")
15 | }
16 |
17 | init(imageBotUsername: String?, gifBotUsername: String?, venueBotUsername: String?) {
18 | self.imageBotUsername = imageBotUsername
19 | self.gifBotUsername = gifBotUsername
20 | self.venueBotUsername = venueBotUsername
21 | }
22 |
23 | public init(decoder: PostboxDecoder) {
24 | self.imageBotUsername = decoder.decodeOptionalStringForKey("img")
25 | self.gifBotUsername = decoder.decodeOptionalStringForKey("gif")
26 | self.venueBotUsername = decoder.decodeOptionalStringForKey("venue")
27 | }
28 |
29 | public func encode(_ encoder: PostboxEncoder) {
30 | if let imageBotUsername = self.imageBotUsername {
31 | encoder.encodeString(imageBotUsername, forKey: "img")
32 | } else {
33 | encoder.encodeNil(forKey: "img")
34 | }
35 | if let gifBotUsername = self.gifBotUsername {
36 | encoder.encodeString(gifBotUsername, forKey: "gif")
37 | } else {
38 | encoder.encodeNil(forKey: "gif")
39 | }
40 | if let venueBotUsername = self.venueBotUsername {
41 | encoder.encodeString(venueBotUsername, forKey: "venue")
42 | } else {
43 | encoder.encodeNil(forKey: "venue")
44 | }
45 | }
46 |
47 | public func isEqual(to: PreferencesEntry) -> Bool {
48 | guard let to = to as? SearchBotsConfiguration else {
49 | return false
50 | }
51 | return self == to
52 | }
53 | }
54 |
55 | public func currentSearchBotsConfiguration(transaction: Transaction) -> SearchBotsConfiguration {
56 | if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.searchBotsConfiguration) as? SearchBotsConfiguration {
57 | return entry
58 | } else {
59 | return SearchBotsConfiguration.defaultValue
60 | }
61 | }
62 |
63 | func updateSearchBotsConfiguration(transaction: Transaction, configuration: SearchBotsConfiguration) {
64 | if !currentSearchBotsConfiguration(transaction: transaction).isEqual(to: configuration) {
65 | transaction.setPreferencesEntry(key: PreferencesKeys.searchBotsConfiguration, value: configuration)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/TelegramCore/SecretChatEncryptionConfig.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public final class SecretChatEncryptionConfig: PostboxCoding {
13 | let g: Int32
14 | let p: MemoryBuffer
15 | let version: Int32
16 |
17 | public init(g: Int32, p: MemoryBuffer, version: Int32) {
18 | self.g = g
19 | self.p = p
20 | self.version = version
21 | }
22 |
23 | public init(decoder: PostboxDecoder) {
24 | self.g = decoder.decodeInt32ForKey("g", orElse: 0)
25 | self.p = decoder.decodeBytesForKey("p")!
26 | self.version = decoder.decodeInt32ForKey("v", orElse: 0)
27 | }
28 |
29 | public func encode(_ encoder: PostboxEncoder) {
30 | encoder.encodeInt32(self.g, forKey: "g")
31 | encoder.encodeBytes(self.p, forKey: "p")
32 | encoder.encodeInt32(self.version, forKey: "v")
33 | }
34 | }
35 |
36 | func validatedEncryptionConfig(postbox: Postbox, network: Network) -> Signal {
37 | return network.request(Api.functions.messages.getDhConfig(version: 0, randomLength: 0))
38 | |> retryRequest
39 | |> mapToSignal { result -> Signal in
40 | switch result {
41 | case let .dhConfig(g, p, version, _):
42 | if !MTCheckIsSafeG(UInt32(g)) {
43 | Logger.shared.log("SecretChatEncryptionConfig", "Invalid g")
44 | return .complete()
45 | }
46 |
47 | if !MTCheckMod(p.makeData(), UInt32(g), network.context.keychain) {
48 | Logger.shared.log("SecretChatEncryptionConfig", "Invalid p or g")
49 | return .complete()
50 | }
51 |
52 | if !MTCheckIsSafePrime(p.makeData(), network.context.keychain) {
53 | Logger.shared.log("SecretChatEncryptionConfig", "Invalid p")
54 | return .never()
55 | }
56 | return .single(SecretChatEncryptionConfig(g: g, p: MemoryBuffer(p), version: version))
57 | case .dhConfigNotModified(_):
58 | assertionFailure()
59 | return .never()
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/TelegramCore/SecretChatFileReference.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | final class SecretChatFileReference: PostboxCoding {
9 | let id: Int64
10 | let accessHash: Int64
11 | let size: Int32
12 | let datacenterId: Int32
13 | let keyFingerprint: Int32
14 |
15 | init(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, keyFingerprint: Int32) {
16 | self.id = id
17 | self.accessHash = accessHash
18 | self.size = size
19 | self.datacenterId = datacenterId
20 | self.keyFingerprint = keyFingerprint
21 | }
22 |
23 | init(decoder: PostboxDecoder) {
24 | self.id = decoder.decodeInt64ForKey("i", orElse: 0)
25 | self.accessHash = decoder.decodeInt64ForKey("a", orElse: 0)
26 | self.size = decoder.decodeInt32ForKey("s", orElse: 0)
27 | self.datacenterId = decoder.decodeInt32ForKey("d", orElse: 0)
28 | self.keyFingerprint = decoder.decodeInt32ForKey("f", orElse: 0)
29 | }
30 |
31 | func encode(_ encoder: PostboxEncoder) {
32 | encoder.encodeInt64(self.id, forKey: "i")
33 | encoder.encodeInt64(self.accessHash, forKey: "a")
34 | encoder.encodeInt32(self.size, forKey: "s")
35 | encoder.encodeInt32(self.datacenterId, forKey: "d")
36 | encoder.encodeInt32(self.keyFingerprint, forKey: "f")
37 | }
38 | }
39 |
40 | extension SecretChatFileReference {
41 | convenience init?(_ file: Api.EncryptedFile) {
42 | switch file {
43 | case let .encryptedFile(id, accessHash, size, dcId, keyFingerprint):
44 | self.init(id: id, accessHash: accessHash, size: size, datacenterId: dcId, keyFingerprint: keyFingerprint)
45 | case .encryptedFileEmpty:
46 | return nil
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/TelegramCore/SecretChatIncomingDecryptedOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | struct SecretChatOperationSequenceInfo: PostboxCoding {
9 | let topReceivedOperationIndex: Int32
10 | let operationIndex: Int32
11 |
12 | init(topReceivedOperationIndex: Int32, operationIndex: Int32) {
13 | self.topReceivedOperationIndex = topReceivedOperationIndex
14 | self.operationIndex = operationIndex
15 | }
16 |
17 | init(decoder: PostboxDecoder) {
18 | self.topReceivedOperationIndex = decoder.decodeInt32ForKey("r", orElse: 0)
19 | self.operationIndex = decoder.decodeInt32ForKey("o", orElse: 0)
20 | }
21 |
22 | func encode(_ encoder: PostboxEncoder) {
23 | encoder.encodeInt32(self.topReceivedOperationIndex, forKey: "r")
24 | encoder.encodeInt32(self.operationIndex, forKey: "o")
25 | }
26 | }
27 |
28 | final class SecretChatIncomingDecryptedOperation: PostboxCoding {
29 | let timestamp: Int32
30 | let layer: Int32
31 | let sequenceInfo: SecretChatOperationSequenceInfo?
32 | let contents: MemoryBuffer
33 | let file: SecretChatFileReference?
34 |
35 | init(timestamp: Int32, layer: Int32, sequenceInfo: SecretChatOperationSequenceInfo?, contents: MemoryBuffer, file: SecretChatFileReference?) {
36 | self.timestamp = timestamp
37 | self.layer = layer
38 | self.sequenceInfo = sequenceInfo
39 | self.contents = contents
40 | self.file = file
41 | }
42 |
43 | init(decoder: PostboxDecoder) {
44 | self.timestamp = decoder.decodeInt32ForKey("t", orElse: 0)
45 | self.layer = decoder.decodeInt32ForKey("l", orElse: 0)
46 | self.sequenceInfo = decoder.decodeObjectForKey("s", decoder: { SecretChatOperationSequenceInfo(decoder: $0) }) as? SecretChatOperationSequenceInfo
47 | self.contents = decoder.decodeBytesForKey("c")!
48 | self.file = decoder.decodeObjectForKey("f", decoder: { SecretChatFileReference(decoder: $0) }) as? SecretChatFileReference
49 | }
50 |
51 | func encode(_ encoder: PostboxEncoder) {
52 | encoder.encodeInt32(self.timestamp, forKey: "t")
53 | encoder.encodeInt32(self.layer, forKey: "l")
54 | if let sequenceInfo = self.sequenceInfo {
55 | encoder.encodeObject(sequenceInfo, forKey: "s")
56 | } else {
57 | encoder.encodeNil(forKey: "s")
58 | }
59 | encoder.encodeBytes(self.contents, forKey: "c")
60 | if let file = self.file {
61 | encoder.encodeObject(file, forKey: "f")
62 | } else {
63 | encoder.encodeNil(forKey: "f")
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdAddressValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdAddressValue: Equatable {
4 | public var street1: String
5 | public var street2: String
6 | public var city: String
7 | public var state: String
8 | public var countryCode: String
9 | public var postcode: String
10 |
11 | public init(street1: String, street2: String, city: String, state: String, countryCode: String, postcode: String) {
12 | self.street1 = street1
13 | self.street2 = street2
14 | self.city = city
15 | self.state = state
16 | self.countryCode = countryCode
17 | self.postcode = postcode
18 | }
19 |
20 | public static func ==(lhs: SecureIdAddressValue, rhs: SecureIdAddressValue) -> Bool {
21 | if lhs.street1 != rhs.street1 {
22 | return false
23 | }
24 | if lhs.street2 != rhs.street2 {
25 | return false
26 | }
27 | if lhs.city != rhs.city {
28 | return false
29 | }
30 | if lhs.state != rhs.state {
31 | return false
32 | }
33 | if lhs.countryCode != rhs.countryCode {
34 | return false
35 | }
36 | if lhs.postcode != rhs.postcode {
37 | return false
38 | }
39 | return true
40 | }
41 | }
42 |
43 | extension SecureIdAddressValue {
44 | init?(dict: [String: Any], fileReferences: [SecureIdVerificationDocumentReference]) {
45 | guard let street1 = dict["street_line1"] as? String else {
46 | return nil
47 | }
48 | let street2 = (dict["street_line2"] as? String) ?? ""
49 | guard let city = dict["city"] as? String else {
50 | return nil
51 | }
52 | guard let state = dict["state"] as? String else {
53 | return nil
54 | }
55 | guard let countryCode = dict["country_code"] as? String else {
56 | return nil
57 | }
58 | guard let postcode = dict["post_code"] as? String else {
59 | return nil
60 | }
61 |
62 | self.init(street1: street1, street2: street2, city: city, state: state, countryCode: countryCode, postcode: postcode)
63 | }
64 |
65 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference]) {
66 | var dict: [String: Any] = [:]
67 | dict["street_line1"] = self.street1
68 | if !self.street2.isEmpty {
69 | dict["street_line2"] = self.street2
70 | }
71 | dict["city"] = self.city
72 | dict["state"] = self.state
73 | dict["country_code"] = self.countryCode
74 | dict["post_code"] = self.postcode
75 |
76 | return (dict, [])
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdBankStatementValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdBankStatementValue: Equatable {
4 | public var verificationDocuments: [SecureIdVerificationDocumentReference]
5 | public var translations: [SecureIdVerificationDocumentReference]
6 |
7 | public init(verificationDocuments: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
8 | self.verificationDocuments = verificationDocuments
9 | self.translations = translations
10 | }
11 |
12 | public static func ==(lhs: SecureIdBankStatementValue, rhs: SecureIdBankStatementValue) -> Bool {
13 | if lhs.verificationDocuments != rhs.verificationDocuments {
14 | return false
15 | }
16 | if lhs.translations != rhs.translations {
17 | return false
18 | }
19 | return true
20 | }
21 | }
22 |
23 | extension SecureIdBankStatementValue {
24 | init?(fileReferences: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
25 | let verificationDocuments: [SecureIdVerificationDocumentReference] = fileReferences
26 |
27 | self.init(verificationDocuments: verificationDocuments, translations: translations)
28 | }
29 |
30 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference], [SecureIdVerificationDocumentReference]) {
31 | return ([:], self.verificationDocuments, self.translations)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdEmailValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdEmailValue: Equatable {
4 | public let email: String
5 |
6 | public init(email: String) {
7 | self.email = email
8 | }
9 |
10 | public static func ==(lhs: SecureIdEmailValue, rhs: SecureIdEmailValue) -> Bool {
11 | if lhs.email != rhs.email {
12 | return false
13 | }
14 | return true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdForm.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public enum SecureIdRequestedFormField: Equatable {
9 | case just(SecureIdRequestedFormFieldValue)
10 | case oneOf([SecureIdRequestedFormFieldValue])
11 | }
12 |
13 | public enum SecureIdRequestedFormFieldValue: Equatable {
14 | case personalDetails(nativeName: Bool)
15 | case passport(selfie: Bool, translation: Bool)
16 | case driversLicense(selfie: Bool, translation: Bool)
17 | case idCard(selfie: Bool, translation: Bool)
18 | case internalPassport(selfie: Bool, translation: Bool)
19 | case passportRegistration(translation: Bool)
20 | case address
21 | case utilityBill(translation: Bool)
22 | case bankStatement(translation: Bool)
23 | case rentalAgreement(translation: Bool)
24 | case phone
25 | case email
26 | case temporaryRegistration(translation: Bool)
27 | }
28 |
29 | public struct SecureIdForm: Equatable {
30 | public let peerId: PeerId
31 | public let requestedFields: [SecureIdRequestedFormField]
32 | public let values: [SecureIdValueWithContext]
33 |
34 | public init(peerId: PeerId, requestedFields: [SecureIdRequestedFormField], values: [SecureIdValueWithContext]) {
35 | self.peerId = peerId
36 | self.requestedFields = requestedFields
37 | self.values = values
38 | }
39 |
40 | public static func ==(lhs: SecureIdForm, rhs: SecureIdForm) -> Bool {
41 | if lhs.peerId != rhs.peerId {
42 | return false
43 | }
44 | if lhs.requestedFields != rhs.requestedFields {
45 | return false
46 | }
47 | if lhs.values != rhs.values {
48 | return false
49 | }
50 | return true
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdPadding.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | func paddedSecureIdData(_ data: Data) -> Data {
4 | var paddingCount = Int(47 + arc4random_uniform(255 - 47))
5 | paddingCount -= ((data.count + paddingCount) % 16)
6 | var result = Data(count: paddingCount + data.count)
7 | result.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in
8 | bytes.advanced(by: 0).pointee = UInt8(paddingCount)
9 | arc4random_buf(bytes.advanced(by: 1), paddingCount - 1)
10 | data.withUnsafeBytes { (source: UnsafePointer) -> Void in
11 | memcpy(bytes.advanced(by: paddingCount), source, data.count)
12 | }
13 | }
14 | return result
15 | }
16 |
17 | func unpaddedSecureIdData(_ data: Data) -> Data? {
18 | var paddingCount: UInt8 = 0
19 | data.copyBytes(to: &paddingCount, count: 1)
20 |
21 | if paddingCount < 0 || paddingCount > data.count {
22 | return nil
23 | }
24 |
25 | return data.subdata(in: Int(paddingCount) ..< data.count)
26 | }
27 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdPassportRegistrationValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdPassportRegistrationValue: Equatable {
4 | public var verificationDocuments: [SecureIdVerificationDocumentReference]
5 | public var translations: [SecureIdVerificationDocumentReference]
6 |
7 | public init(verificationDocuments: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
8 | self.verificationDocuments = verificationDocuments
9 | self.translations = translations
10 | }
11 |
12 | public static func ==(lhs: SecureIdPassportRegistrationValue, rhs: SecureIdPassportRegistrationValue) -> Bool {
13 | if lhs.verificationDocuments != rhs.verificationDocuments {
14 | return false
15 | }
16 | if lhs.translations != rhs.translations {
17 | return false
18 | }
19 | return true
20 | }
21 | }
22 |
23 | extension SecureIdPassportRegistrationValue {
24 | init?(fileReferences: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
25 | let verificationDocuments: [SecureIdVerificationDocumentReference] = fileReferences
26 |
27 | self.init(verificationDocuments: verificationDocuments, translations: translations)
28 | }
29 |
30 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference], [SecureIdVerificationDocumentReference]) {
31 | return ([:], self.verificationDocuments, self.translations)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdPhoneValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdPhoneValue: Equatable {
4 | public let phone: String
5 |
6 | public init(phone: String) {
7 | self.phone = phone
8 | }
9 |
10 | public static func ==(lhs: SecureIdPhoneValue, rhs: SecureIdPhoneValue) -> Bool {
11 | if lhs.phone != rhs.phone {
12 | return false
13 | }
14 | return true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdRentalAgreementValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdRentalAgreementValue: Equatable {
4 | public var verificationDocuments: [SecureIdVerificationDocumentReference]
5 | public var translations: [SecureIdVerificationDocumentReference]
6 |
7 | public init(verificationDocuments: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
8 | self.verificationDocuments = verificationDocuments
9 | self.translations = translations
10 | }
11 |
12 | public static func ==(lhs: SecureIdRentalAgreementValue, rhs: SecureIdRentalAgreementValue) -> Bool {
13 | if lhs.verificationDocuments != rhs.verificationDocuments {
14 | return false
15 | }
16 | if lhs.translations != rhs.translations {
17 | return false
18 | }
19 | return true
20 | }
21 | }
22 |
23 | extension SecureIdRentalAgreementValue {
24 | init?(fileReferences: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
25 | let verificationDocuments: [SecureIdVerificationDocumentReference] = fileReferences
26 |
27 | self.init(verificationDocuments: verificationDocuments, translations: translations)
28 | }
29 |
30 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference], [SecureIdVerificationDocumentReference]) {
31 | return ([:], self.verificationDocuments, self.translations)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdTemporaryRegistrationValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdTemporaryRegistrationValue: Equatable {
4 | public var verificationDocuments: [SecureIdVerificationDocumentReference]
5 | public var translations: [SecureIdVerificationDocumentReference]
6 |
7 | public init(verificationDocuments: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
8 | self.verificationDocuments = verificationDocuments
9 | self.translations = translations
10 | }
11 |
12 | public static func ==(lhs: SecureIdTemporaryRegistrationValue, rhs: SecureIdTemporaryRegistrationValue) -> Bool {
13 | if lhs.verificationDocuments != rhs.verificationDocuments {
14 | return false
15 | }
16 | if lhs.translations != rhs.translations {
17 | return false
18 | }
19 | return true
20 | }
21 | }
22 |
23 | extension SecureIdTemporaryRegistrationValue {
24 | init?(fileReferences: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
25 | let verificationDocuments: [SecureIdVerificationDocumentReference] = fileReferences
26 |
27 | self.init(verificationDocuments: verificationDocuments, translations: translations)
28 | }
29 |
30 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference], [SecureIdVerificationDocumentReference]) {
31 | return ([:], self.verificationDocuments, self.translations)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdUtilityBillValue.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdUtilityBillValue: Equatable {
4 | public var verificationDocuments: [SecureIdVerificationDocumentReference]
5 | public var translations: [SecureIdVerificationDocumentReference]
6 |
7 | public init(verificationDocuments: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
8 | self.verificationDocuments = verificationDocuments
9 | self.translations = translations
10 | }
11 |
12 | public static func ==(lhs: SecureIdUtilityBillValue, rhs: SecureIdUtilityBillValue) -> Bool {
13 | if lhs.verificationDocuments != rhs.verificationDocuments {
14 | return false
15 | }
16 | if lhs.translations != rhs.translations {
17 | return false
18 | }
19 | return true
20 | }
21 | }
22 |
23 | extension SecureIdUtilityBillValue {
24 | init?(fileReferences: [SecureIdVerificationDocumentReference], translations: [SecureIdVerificationDocumentReference]) {
25 | let verificationDocuments: [SecureIdVerificationDocumentReference] = fileReferences
26 |
27 | self.init(verificationDocuments: verificationDocuments, translations: translations)
28 | }
29 |
30 | func serialize() -> ([String: Any], [SecureIdVerificationDocumentReference], [SecureIdVerificationDocumentReference]) {
31 | return ([:], self.verificationDocuments, self.translations)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdValueAccessContext.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public struct SecureIdValueAccessContext: Equatable {
4 | let secret: Data
5 | let id: Int64
6 |
7 | public static func ==(lhs: SecureIdValueAccessContext, rhs: SecureIdValueAccessContext) -> Bool {
8 | if lhs.secret != rhs.secret {
9 | return false
10 | }
11 | if lhs.id != rhs.id {
12 | return false
13 | }
14 | return true
15 | }
16 | }
17 |
18 | public func generateSecureIdValueEmptyAccessContext() -> SecureIdValueAccessContext? {
19 | return SecureIdValueAccessContext(secret: Data(), id: 0)
20 | }
21 |
22 | public func generateSecureIdValueAccessContext() -> SecureIdValueAccessContext? {
23 | guard let secret = generateSecureSecretData() else {
24 | return nil
25 | }
26 | let secretHashData = sha512Digest(secret)
27 | var secretHash: Int64 = 0
28 | secretHashData.withUnsafeBytes { (bytes: UnsafePointer) -> Void in
29 | memcpy(&secretHash, bytes.advanced(by: secretHashData.count - 8), 8)
30 | }
31 | return SecureIdValueAccessContext(secret: secret, id: secretHash)
32 | }
33 |
--------------------------------------------------------------------------------
/TelegramCore/SecureIdVerificationDocumentReference.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum SecureIdVerificationDocumentReference: Equatable {
4 | case remote(SecureIdFileReference)
5 | case uploaded(UploadedSecureIdFile)
6 |
7 | public static func ==(lhs: SecureIdVerificationDocumentReference, rhs: SecureIdVerificationDocumentReference) -> Bool {
8 | switch lhs {
9 | case let .remote(file):
10 | if case .remote(file) = rhs {
11 | return true
12 | } else {
13 | return false
14 | }
15 | case let .uploaded(file):
16 | if case .uploaded(file) = rhs {
17 | return true
18 | } else {
19 | return false
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/TelegramCore/SetSecretChatMessageAutoremoveTimeoutInteractively.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal {
11 | return account.postbox.transaction { transaction -> Void in
12 | if let peer = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState {
13 | if state.messageAutoremoveTimeout != timeout {
14 | let updatedPeer = peer.withUpdatedMessageAutoremoveTimeout(timeout)
15 | let updatedState = state.withUpdatedMessageAutoremoveTimeout(timeout)
16 | if !updatedPeer.isEqual(peer) {
17 | updatePeers(transaction: transaction, peers: [updatedPeer], update: { $1 })
18 | }
19 | if updatedState != state {
20 | transaction.setPeerChatState(peerId, state: updatedState)
21 | }
22 |
23 | let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!))), replyToMessageId: nil, localGroupingKey: nil))])
24 | }
25 | }
26 | }
27 | }
28 |
29 | public func addSecretChatMessageScreenshot(account: Account, peerId: PeerId) -> Signal {
30 | return account.postbox.transaction { transaction -> Void in
31 | if let peer = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState {
32 | let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil))])
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/TelegramCore/SourceReferenceMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class SourceReferenceMessageAttribute: MessageAttribute {
9 | public let messageId: MessageId
10 | public let associatedMessageIds: [MessageId] = []
11 | public let associatedPeerIds: [PeerId]
12 |
13 | public init(messageId: MessageId) {
14 | self.messageId = messageId
15 | self.associatedPeerIds = [messageId.peerId]
16 | }
17 |
18 | required public init(decoder: PostboxDecoder) {
19 | let namespaceAndId: Int64 = decoder.decodeInt64ForKey("i", orElse: 0)
20 | self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("p", orElse: 0)), namespace: Int32(namespaceAndId & 0xffffffff), id: Int32((namespaceAndId >> 32) & 0xffffffff))
21 | self.associatedPeerIds = [self.messageId.peerId]
22 | }
23 |
24 | public func encode(_ encoder: PostboxEncoder) {
25 | let namespaceAndId = Int64(self.messageId.namespace) | (Int64(self.messageId.id) << 32)
26 | encoder.encodeInt64(namespaceAndId, forKey: "i")
27 | encoder.encodeInt64(self.messageId.peerId.toInt64(), forKey: "p")
28 | }
29 | }
30 |
31 |
32 |
--------------------------------------------------------------------------------
/TelegramCore/SplitTest.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public protocol SplitTestEvent: RawRepresentable where RawValue == String {
9 | }
10 |
11 | public protocol SplitTestConfiguration {
12 | static var defaultValue: Self { get }
13 | }
14 |
15 | public protocol SplitTest {
16 | associatedtype Configuration: SplitTestConfiguration
17 | associatedtype Event: SplitTestEvent
18 |
19 | var postbox: Postbox { get }
20 | var bucket: String? { get }
21 | var configuration: Configuration { get }
22 |
23 | init(postbox: Postbox, bucket: String?, configuration: Configuration)
24 | }
25 |
26 | extension SplitTest {
27 | public func addEvent(_ event: Self.Event, data: JSON = []) {
28 | if let bucket = self.bucket {
29 | //TODO: merge additional data
30 | addAppLogEvent(postbox: self.postbox, time: Date().timeIntervalSince1970, type: event.rawValue, peerId: nil, data: ["bucket": bucket])
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/StringFormat.swift:
--------------------------------------------------------------------------------
1 | public func dataSizeString(_ size: Int, forceDecimal: Bool = false, decimalSeparator: String = ".") -> String {
2 | return dataSizeString(Int64(size), forceDecimal: forceDecimal, decimalSeparator: decimalSeparator)
3 | }
4 |
5 | public func dataSizeString(_ size: Int64, forceDecimal: Bool = false, decimalSeparator: String = ".") -> String {
6 | if size >= 1024 * 1024 * 1024 {
7 | let remainder = Int64((Double(size % (1024 * 1024 * 1024)) / (1024 * 1024 * 102.4)).rounded(.down))
8 | if remainder != 0 || forceDecimal {
9 | return "\(size / (1024 * 1024 * 1024))\(decimalSeparator)\(remainder) GB"
10 | } else {
11 | return "\(size / (1024 * 1024 * 1024)) GB"
12 | }
13 | } else if size >= 1024 * 1024 {
14 | let remainder = Int64((Double(size % (1024 * 1024)) / (1024.0 * 102.4)).rounded(.down))
15 | if remainder != 0 || forceDecimal {
16 | return "\(size / (1024 * 1024))\(decimalSeparator)\(remainder) MB"
17 | } else {
18 | return "\(size / (1024 * 1024)) MB"
19 | }
20 | } else if size >= 1024 {
21 | let remainder = (size % (1024)) / (102)
22 | if remainder != 0 || forceDecimal {
23 | return "\(size / 1024)\(decimalSeparator)\(remainder) KB"
24 | } else {
25 | return "\(size / 1024) KB"
26 | }
27 | } else {
28 | return "\(size) B"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/TelegramCore/SuggestedLocalizationEntry.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public final class SuggestedLocalizationEntry: PreferencesEntry {
11 | public let languageCode: String
12 | public let isSeen: Bool
13 |
14 | init(languageCode: String, isSeen: Bool) {
15 | self.languageCode = languageCode
16 | self.isSeen = isSeen
17 | }
18 |
19 | public init(decoder: PostboxDecoder) {
20 | self.languageCode = decoder.decodeStringForKey("lc", orElse: "en")
21 | self.isSeen = decoder.decodeInt32ForKey("s", orElse: 0) != 0
22 | }
23 |
24 | public func encode(_ encoder: PostboxEncoder) {
25 | encoder.encodeString(self.languageCode, forKey: "lc")
26 | encoder.encodeInt32(self.isSeen ? 1 : 0, forKey: "s")
27 | }
28 |
29 | public func isEqual(to: PreferencesEntry) -> Bool {
30 | if let to = to as? SuggestedLocalizationEntry {
31 | return self == to
32 | } else {
33 | return false
34 | }
35 | }
36 |
37 | public static func ==(lhs: SuggestedLocalizationEntry, rhs: SuggestedLocalizationEntry) -> Bool {
38 | return lhs.languageCode == rhs.languageCode && lhs.isSeen == rhs.isSeen
39 | }
40 | }
41 |
42 | public func markSuggestedLocalizationAsSeenInteractively(postbox: Postbox, languageCode: String) -> Signal {
43 | return postbox.transaction { transaction -> Void in
44 | transaction.updatePreferencesEntry(key: PreferencesKeys.suggestedLocalization, { current in
45 | if let current = current as? SuggestedLocalizationEntry {
46 | if current.languageCode == languageCode, !current.isSeen {
47 | return SuggestedLocalizationEntry(languageCode: languageCode, isSeen: true)
48 | }
49 | } else {
50 | return SuggestedLocalizationEntry(languageCode: languageCode, isSeen: true)
51 | }
52 | return current
53 | })
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/TelegramCore/SupportPeerId.swift:
--------------------------------------------------------------------------------
1 | #if os(macOS)
2 | import PostboxMac
3 | import SwiftSignalKitMac
4 | import MtProtoKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | import MtProtoKitDynamic
9 | #endif
10 |
11 |
12 | public func supportPeerId(account:Account) -> Signal {
13 | return account.network.request(Api.functions.help.getSupport())
14 | |> map(Optional.init)
15 | |> `catch` { _ in
16 | return Signal.single(nil)
17 | }
18 | |> mapToSignal { support -> Signal in
19 | if let support = support {
20 | switch support {
21 | case let .support(phoneNumber: _, user: user):
22 | let user = TelegramUser(user: user)
23 | return account.postbox.transaction { transaction -> PeerId in
24 | updatePeers(transaction: transaction, peers: [user], update: { (previous, updated) -> Peer? in
25 | return updated
26 | })
27 | return user.id
28 | }
29 | }
30 | }
31 | return .single(nil)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizeChatInputStateOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | final class SynchronizeChatInputStateOperation: PostboxCoding {
9 | let previousState: SynchronizeableChatInputState?
10 |
11 | init(previousState: SynchronizeableChatInputState?) {
12 | self.previousState = previousState
13 | }
14 |
15 | init(decoder: PostboxDecoder) {
16 | self.previousState = decoder.decodeObjectForKey("p", decoder: { SynchronizeableChatInputState(decoder: $0) }) as? SynchronizeableChatInputState
17 | }
18 |
19 | func encode(_ encoder: PostboxEncoder) {
20 | if let previousState = self.previousState {
21 | encoder.encodeObject(previousState, forKey: "p")
22 | } else {
23 | encoder.encodeNil(forKey: "p")
24 | }
25 | }
26 | }
27 |
28 | func addSynchronizeChatInputStateOperation(transaction: Transaction, peerId: PeerId) {
29 | var updateLocalIndex: Int32?
30 | let tag: PeerOperationLogTag = OperationLogTags.SynchronizeChatInputStates
31 |
32 | var previousOperation: SynchronizeChatInputStateOperation?
33 | transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
34 | updateLocalIndex = entry.tagLocalIndex
35 | if let operation = entry.contents as? SynchronizeChatInputStateOperation {
36 | previousOperation = operation
37 | }
38 | return false
39 | })
40 | var previousState: SynchronizeableChatInputState?
41 | if let previousOperation = previousOperation {
42 | previousState = previousOperation.previousState
43 | } else if let peerChatInterfaceState = transaction.getPeerChatInterfaceState(peerId) as? SynchronizeableChatInterfaceState {
44 | previousState = peerChatInterfaceState.synchronizeableInputState
45 | }
46 | let operationContents = SynchronizeChatInputStateOperation(previousState: previousState)
47 | if let updateLocalIndex = updateLocalIndex {
48 | let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: updateLocalIndex)
49 | }
50 | transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents)
51 | }
52 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizeConsumeMessageContentsOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | final class SynchronizeConsumeMessageContentsOperation: PostboxCoding {
9 | let messageIds: [MessageId]
10 |
11 | init(messageIds: [MessageId]) {
12 | self.messageIds = messageIds
13 | }
14 |
15 | init(decoder: PostboxDecoder) {
16 | self.messageIds = MessageId.decodeArrayFromBuffer(decoder.decodeBytesForKeyNoCopy("i")!)
17 | }
18 |
19 | func encode(_ encoder: PostboxEncoder) {
20 | let buffer = WriteBuffer()
21 | MessageId.encodeArrayToBuffer(self.messageIds, buffer: buffer)
22 | encoder.encodeBytes(buffer, forKey: "i")
23 | }
24 | }
25 |
26 | func addSynchronizeConsumeMessageContentsOperation(transaction: Transaction, messageIds: [MessageId]) {
27 | for (peerId, messageIds) in messagesIdsGroupedByPeerId(Set(messageIds)) {
28 | var updateLocalIndex: Int32?
29 | /*transaction.operationLogEnumerateEntries(peerId: peerId, tag: OperationLogTags.SynchronizeConsumeMessageContents, { entry in
30 | updateLocalIndex = entry.tagLocalIndex
31 | return false
32 | })*/
33 | let operationContents = SynchronizeConsumeMessageContentsOperation(messageIds: messageIds)
34 | if let updateLocalIndex = updateLocalIndex {
35 | let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: OperationLogTags.SynchronizeConsumeMessageContents, tagLocalIndex: updateLocalIndex)
36 | }
37 | transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.SynchronizeConsumeMessageContents, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizeEmojiKeywordsOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | final class SynchronizeEmojiKeywordsOperation: PostboxCoding {
9 | let inputLanguageCode: String
10 | let languageCode: String?
11 | let fromVersion: Int32?
12 |
13 | init(inputLanguageCode: String, languageCode: String?, fromVersion: Int32?) {
14 | self.inputLanguageCode = inputLanguageCode
15 | self.languageCode = languageCode
16 | self.fromVersion = fromVersion
17 | }
18 |
19 | init(decoder: PostboxDecoder) {
20 | self.inputLanguageCode = decoder.decodeStringForKey("ilc", orElse: "")
21 | self.languageCode = decoder.decodeOptionalStringForKey("lc")
22 | self.fromVersion = decoder.decodeOptionalInt32ForKey("v")
23 | }
24 |
25 | func encode(_ encoder: PostboxEncoder) {
26 | encoder.encodeString(self.inputLanguageCode, forKey: "ilc")
27 | if let languageCode = self.languageCode {
28 | encoder.encodeString(languageCode, forKey: "lc")
29 | } else {
30 | encoder.encodeNil(forKey: "lc")
31 | }
32 | if let fromVersion = self.fromVersion {
33 | encoder.encodeInt32(fromVersion, forKey: "v")
34 | } else {
35 | encoder.encodeNil(forKey: "v")
36 | }
37 | }
38 | }
39 |
40 | func addSynchronizeEmojiKeywordsOperation(transaction: Transaction, inputLanguageCode: String, languageCode: String?, fromVersion: Int32?) {
41 | let tag = OperationLogTags.SynchronizeEmojiKeywords
42 | let peerId = PeerId(emojiKeywordColletionIdForCode(inputLanguageCode).id)
43 |
44 | var hasExistingOperation = false
45 | transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag) { entry -> Bool in
46 | hasExistingOperation = true
47 | return false
48 | }
49 |
50 | guard !hasExistingOperation else {
51 | return
52 | }
53 | let operationContents = SynchronizeEmojiKeywordsOperation(inputLanguageCode: inputLanguageCode, languageCode: languageCode, fromVersion: fromVersion)
54 | transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents)
55 | }
56 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizeLocalizationUpdatesOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | final class SynchronizeLocalizationUpdatesOperation: PostboxCoding {
11 | init() {
12 | }
13 |
14 | init(decoder: PostboxDecoder) {
15 | }
16 |
17 | func encode(_ encoder: PostboxEncoder) {
18 | }
19 | }
20 |
21 | func addSynchronizeLocalizationUpdatesOperation(transaction: Transaction) {
22 | let tag: PeerOperationLogTag = OperationLogTags.SynchronizeLocalizationUpdates
23 | let peerId = PeerId(namespace: 0, id: 0)
24 |
25 | var topLocalIndex: Int32?
26 | transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
27 | topLocalIndex = entry.tagLocalIndex
28 | return false
29 | })
30 |
31 | if let topLocalIndex = topLocalIndex {
32 | let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
33 | }
34 |
35 | transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeLocalizationUpdatesOperation())
36 | }
37 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizeMarkAllUnseenPersonalMessagesOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | final class SynchronizeMarkAllUnseenPersonalMessagesOperation: PostboxCoding {
11 | let maxId: MessageId.Id
12 |
13 | init(maxId: MessageId.Id) {
14 | self.maxId = maxId
15 | }
16 |
17 | init(decoder: PostboxDecoder) {
18 | self.maxId = decoder.decodeInt32ForKey("maxId", orElse: Int32.min + 1)
19 | }
20 |
21 | func encode(_ encoder: PostboxEncoder) {
22 | encoder.encodeInt32(self.maxId, forKey: "maxId")
23 | }
24 | }
25 |
26 | func addSynchronizeMarkAllUnseenPersonalMessagesOperation(transaction: Transaction, peerId: PeerId, maxId: MessageId.Id) {
27 | let tag: PeerOperationLogTag = OperationLogTags.SynchronizeMarkAllUnseenPersonalMessages
28 |
29 | var topLocalIndex: Int32?
30 | var currentMaxId: MessageId.Id?
31 | transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
32 | topLocalIndex = entry.tagLocalIndex
33 | if let operation = entry.contents as? SynchronizeMarkAllUnseenPersonalMessagesOperation {
34 | currentMaxId = operation.maxId
35 | }
36 | return false
37 | })
38 |
39 | if let topLocalIndex = topLocalIndex {
40 | if let currentMaxId = currentMaxId, currentMaxId >= maxId {
41 | return
42 | }
43 | let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
44 | }
45 |
46 | transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeMarkAllUnseenPersonalMessagesOperation(maxId: maxId))
47 | }
48 |
--------------------------------------------------------------------------------
/TelegramCore/SynchronizePinnedChatsOperation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | private struct PreviousPeerItemId: PostboxCoding {
9 | let id: PinnedItemId
10 |
11 | init(_ id: PinnedItemId) {
12 | self.id = id
13 | }
14 |
15 | init(decoder: PostboxDecoder) {
16 | switch decoder.decodeInt32ForKey("_t", orElse: 0) {
17 | case 0:
18 | self.id = .peer(PeerId(decoder.decodeInt64ForKey("i", orElse: 0)))
19 | default:
20 | preconditionFailure()
21 | }
22 | }
23 |
24 | func encode(_ encoder: PostboxEncoder) {
25 | switch self.id {
26 | case let .peer(peerId):
27 | encoder.encodeInt32(0, forKey: "_t")
28 | encoder.encodeInt64(peerId.toInt64(), forKey: "i")
29 | }
30 | }
31 | }
32 |
33 | final class SynchronizePinnedChatsOperation: PostboxCoding {
34 | let previousItemIds: [PinnedItemId]
35 |
36 | init(previousItemIds: [PinnedItemId]) {
37 | self.previousItemIds = previousItemIds
38 | }
39 |
40 | init(decoder: PostboxDecoder) {
41 | let wrappedIds: [PreviousPeerItemId] = decoder.decodeObjectArrayWithDecoderForKey("previousItemIds")
42 | self.previousItemIds = wrappedIds.map { $0.id }
43 | }
44 |
45 | func encode(_ encoder: PostboxEncoder) {
46 | encoder.encodeObjectArray(self.previousItemIds.map(PreviousPeerItemId.init), forKey: "previousItemIds")
47 | }
48 | }
49 |
50 | func addSynchronizePinnedChatsOperation(transaction: Transaction, groupId: PeerGroupId) {
51 | let rawId: Int32 = groupId.rawValue
52 | var previousItemIds = transaction.getPinnedItemIds(groupId: groupId)
53 | var updateLocalIndex: Int32?
54 |
55 | transaction.operationLogEnumerateEntries(peerId: PeerId(namespace: 0, id: rawId), tag: OperationLogTags.SynchronizePinnedChats, { entry in
56 | updateLocalIndex = entry.tagLocalIndex
57 | if let contents = entry.contents as? SynchronizePinnedChatsOperation {
58 | previousItemIds = contents.previousItemIds
59 | }
60 | return false
61 | })
62 | let operationContents = SynchronizePinnedChatsOperation(previousItemIds: previousItemIds)
63 | if let updateLocalIndex = updateLocalIndex {
64 | let _ = transaction.operationLogRemoveEntry(peerId: PeerId(namespace: 0, id: rawId), tag: OperationLogTags.SynchronizePinnedChats, tagLocalIndex: updateLocalIndex)
65 | }
66 | transaction.operationLogAddEntry(peerId: PeerId(namespace: 0, id: rawId), tag: OperationLogTags.SynchronizePinnedChats, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents)
67 | }
68 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramCore.h:
--------------------------------------------------------------------------------
1 | //
2 | // TelegramCore.h
3 | // TelegramCore
4 | //
5 | // Created by Peter on 8/1/16.
6 | // Copyright © 2016 Peter. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for TelegramCore.
12 | FOUNDATION_EXPORT double TelegramCoreVersionNumber;
13 |
14 | //! Project version string for TelegramCore.
15 | FOUNDATION_EXPORT const unsigned char TelegramCoreVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramCoreIncludes.h:
--------------------------------------------------------------------------------
1 | #ifndef TelegramCoreIncludes_h
2 | #define TelegramCoreIncludes_h
3 |
4 | #import "Crypto.h"
5 | #import "Reachability.h"
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramCorePrivate/module.modulemap:
--------------------------------------------------------------------------------
1 | module TelegramCorePrivateModule {
2 | header "../../third-party/libphonenumber-iOS/NBPhoneNumber.h"
3 | header "../../third-party/libphonenumber-iOS/NBPhoneNumberUtil.h"
4 | header "../../third-party/libphonenumber-iOS/NBAsYouTypeFormatter.h"
5 | header "../NetworkLogging.h"
6 | header "../MonotonicTime.h"
7 | header "../TelegramCoreIncludes.h"
8 | }
9 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramMediaContact.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class TelegramMediaContact: Media {
9 | public let id: MediaId? = nil
10 | public let firstName: String
11 | public let lastName: String
12 | public let phoneNumber: String
13 | public let peerId: PeerId?
14 | public let vCardData: String?
15 |
16 | public let peerIds: [PeerId]
17 |
18 | public init(firstName: String, lastName: String, phoneNumber: String, peerId: PeerId?, vCardData: String?) {
19 | self.firstName = firstName
20 | self.lastName = lastName
21 | self.phoneNumber = phoneNumber
22 | self.peerId = peerId
23 | self.vCardData = vCardData
24 | if let peerId = peerId {
25 | self.peerIds = [peerId]
26 | } else {
27 | self.peerIds = []
28 | }
29 | }
30 |
31 | public init(decoder: PostboxDecoder) {
32 | self.firstName = decoder.decodeStringForKey("n.f", orElse: "")
33 | self.lastName = decoder.decodeStringForKey("n.l", orElse: "")
34 | self.phoneNumber = decoder.decodeStringForKey("pn", orElse: "")
35 | if let peerIdValue = decoder.decodeOptionalInt64ForKey("p") {
36 | self.peerId = PeerId(peerIdValue)
37 | self.peerIds = [PeerId(peerIdValue)]
38 | } else {
39 | self.peerId = nil
40 | self.peerIds = []
41 | }
42 | self.vCardData = decoder.decodeOptionalStringForKey("vc")
43 | }
44 |
45 | public func encode(_ encoder: PostboxEncoder) {
46 | encoder.encodeString(self.firstName, forKey: "n.f")
47 | encoder.encodeString(self.lastName, forKey: "n.l")
48 | encoder.encodeString(self.phoneNumber, forKey: "pn")
49 | if let peerId = self.peerId {
50 | encoder.encodeInt64(peerId.toInt64(), forKey: "p")
51 | }
52 | if let vCardData = self.vCardData {
53 | encoder.encodeString(vCardData, forKey: "vc")
54 | } else {
55 | encoder.encodeNil(forKey: "vc")
56 | }
57 | }
58 |
59 | public func isEqual(to other: Media) -> Bool {
60 | if let other = other as? TelegramMediaContact {
61 | if self.id == other.id && self.firstName == other.firstName && self.lastName == other.lastName && self.phoneNumber == other.phoneNumber && self.peerId == other.peerId && self.vCardData == other.vCardData && self.peerIds == other.peerIds {
62 | return true
63 | }
64 | }
65 | return false
66 | }
67 |
68 | public func isSemanticallyEqual(to other: Media) -> Bool {
69 | return self.isEqual(to: other)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramMediaExpiredContent.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public enum TelegramMediaExpiredContentData: Int32 {
9 | case image
10 | case file
11 | }
12 |
13 | public final class TelegramMediaExpiredContent: Media {
14 | public let data: TelegramMediaExpiredContentData
15 |
16 | public let id: MediaId? = nil
17 | public let peerIds: [PeerId] = []
18 |
19 | public init(data: TelegramMediaExpiredContentData) {
20 | self.data = data
21 | }
22 |
23 | public init(decoder: PostboxDecoder) {
24 | self.data = TelegramMediaExpiredContentData(rawValue: decoder.decodeInt32ForKey("d", orElse: 0))!
25 | }
26 |
27 | public func encode(_ encoder: PostboxEncoder) {
28 | encoder.encodeInt32(self.data.rawValue, forKey: "d")
29 | }
30 |
31 | public func isEqual(to other: Media) -> Bool {
32 | if let other = other as? TelegramMediaExpiredContent {
33 | return self.data == other.data
34 | } else {
35 | return false
36 | }
37 | }
38 |
39 | public func isSemanticallyEqual(to other: Media) -> Bool {
40 | return self.isEqual(to: other)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/TelegramCore/TelegramMediaResource.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public protocol TelegramMediaResource: MediaResource, PostboxCoding {
9 | }
10 |
--------------------------------------------------------------------------------
/TelegramCore/TeleramMediaUnsupported.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public final class TelegramMediaUnsupported: Media {
9 | public let id: MediaId? = nil
10 | public let peerIds: [PeerId] = []
11 |
12 | init() {
13 | }
14 |
15 | public init(decoder: PostboxDecoder) {
16 | }
17 |
18 | public func encode(_ encoder: PostboxEncoder) {
19 | }
20 |
21 | public func isEqual(to other: Media) -> Bool {
22 | if other is TelegramMediaUnsupported {
23 | return true
24 | }
25 | return false
26 | }
27 |
28 | public func isSemanticallyEqual(to other: Media) -> Bool {
29 | return self.isEqual(to: other)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/TelegramCore/ToggleChannelSignatures.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public func toggleShouldChannelMessagesSignatures(account:Account, peerId:PeerId, enabled: Bool) -> Signal {
13 | return account.postbox.transaction { transaction -> Signal in
14 | if let peer = transaction.getPeer(peerId) as? TelegramChannel, let inputChannel = apiInputChannel(peer) {
15 | return account.network.request(Api.functions.channels.toggleSignatures(channel: inputChannel, enabled: enabled ? .boolTrue : .boolFalse)) |> retryRequest |> map { updates -> Void in
16 | account.stateManager.addUpdates(updates)
17 | }
18 | } else {
19 | return .complete()
20 | }
21 | } |> switchToLatest
22 | }
23 |
--------------------------------------------------------------------------------
/TelegramCore/UpdateAccountPeerName.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public func updateAccountPeerName(account: Account, firstName: String, lastName: String) -> Signal {
13 | return account.network.request(Api.functions.account.updateProfile(flags: (1 << 0) | (1 << 1), firstName: firstName, lastName: lastName, about: nil))
14 | |> map { result -> Api.User? in
15 | return result
16 | }
17 | |> `catch` { _ in
18 | return .single(nil)
19 | }
20 | |> mapToSignal { result -> Signal in
21 | return account.postbox.transaction { transaction -> Void in
22 | if let result = result {
23 | let peer = TelegramUser(user: result)
24 | updatePeers(transaction: transaction, peers: [peer], update: { $1 })
25 | }
26 | }
27 | }
28 | }
29 |
30 | public enum UpdateAboutError {
31 | case generic
32 | }
33 |
34 |
35 | public func updateAbout(account: Account, about: String?) -> Signal {
36 | return account.network.request(Api.functions.account.updateProfile(flags: about == nil ? 0 : (1 << 2), firstName: nil, lastName: nil, about: about))
37 | |> mapError { _ -> UpdateAboutError in
38 | return .generic
39 | }
40 | |> mapToSignal { apiUser -> Signal in
41 | return account.postbox.transaction { transaction -> Void in
42 | transaction.updatePeerCachedData(peerIds: Set([account.peerId]), update: { _, current in
43 | if let current = current as? CachedUserData {
44 | return current.withUpdatedAbout(about)
45 | } else {
46 | return current
47 | }
48 | })
49 | } |> mapError { _ -> UpdateAboutError in return .generic }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/TelegramCore/UpdateContactName.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | import MtProtoKitMac
6 | #else
7 | import Postbox
8 | import SwiftSignalKit
9 | import MtProtoKitDynamic
10 | #endif
11 |
12 | public enum UpdateContactNameError {
13 | case generic
14 | }
15 |
16 | public func updateContactName(account: Account, peerId: PeerId, firstName: String, lastName: String) -> Signal {
17 | return account.postbox.transaction { transaction -> Signal in
18 | if let peer = transaction.getPeer(peerId) as? TelegramUser, let phone = peer.phone, !phone.isEmpty {
19 | return account.network.request(Api.functions.contacts.importContacts(contacts: [Api.InputContact.inputPhoneContact(clientId: 1, phone: phone, firstName: firstName, lastName: lastName)]))
20 | |> mapError { _ -> UpdateContactNameError in
21 | return .generic
22 | }
23 | |> mapToSignal { result -> Signal in
24 | return account.postbox.transaction { transaction -> Void in
25 | switch result {
26 | case let .importedContacts(_, _, _, users):
27 | if let first = users.first {
28 | let user = TelegramUser(user: first)
29 | updatePeers(transaction: transaction, peers: [user], update: { _, updated in
30 | return updated
31 | })
32 | }
33 | }
34 | } |> mapError { _ -> UpdateContactNameError in return .generic }
35 | }
36 | } else {
37 | return .fail(.generic)
38 | }
39 | } |> mapError { _ -> UpdateContactNameError in return .generic } |> switchToLatest
40 | }
41 |
--------------------------------------------------------------------------------
/TelegramCore/UpdateGroupSpecificStickerset.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 |
11 | public enum UpdateGroupSpecificStickersetError {
12 | case generic
13 | }
14 |
15 | public func updateGroupSpecificStickerset(postbox: Postbox, network: Network, peerId: PeerId, info: StickerPackCollectionInfo?) -> Signal {
16 | return postbox.loadedPeerWithId(peerId)
17 | |> introduceError(UpdateGroupSpecificStickersetError.self)
18 | |> mapToSignal { peer -> Signal in
19 | let inputStickerset: Api.InputStickerSet
20 | if let info = info {
21 | inputStickerset = Api.InputStickerSet.inputStickerSetShortName(shortName: info.shortName)
22 | } else {
23 | inputStickerset = Api.InputStickerSet.inputStickerSetEmpty
24 | }
25 | if let inputChannel = apiInputChannel(peer) {
26 | return network.request(Api.functions.channels.setStickers(channel: inputChannel, stickerset: inputStickerset))
27 | |> mapError { _ -> UpdateGroupSpecificStickersetError in
28 | return .generic
29 | }
30 | |> mapToSignal { value -> Signal in
31 | switch value {
32 | case .boolTrue:
33 | return postbox.transaction { transaction -> Void in
34 | return transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current -> CachedPeerData? in
35 | return (current as? CachedChannelData)?.withUpdatedStickerPack(info)
36 | })
37 | }
38 | |> introduceError(UpdateGroupSpecificStickersetError.self)
39 | default:
40 | return .complete()
41 | }
42 | }
43 | }
44 | return .complete()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/TelegramCore/UpdateMessageMedia.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | func updateMessageMedia(transaction: Transaction, id: MediaId, media: Media?) {
9 | let updatedMessageIndices = transaction.updateMedia(id, update: media)
10 | for index in updatedMessageIndices {
11 | transaction.updateMessage(index.id, update: { currentMessage in
12 | var textEntities: [MessageTextEntity]?
13 | for attribute in currentMessage.attributes {
14 | if let attribute = attribute as? TextEntitiesMessageAttribute {
15 | textEntities = attribute.entities
16 | break
17 | }
18 | }
19 | let (tags, _) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: currentMessage.attributes, media: currentMessage.media, textEntities: textEntities)
20 | if tags == currentMessage.tags {
21 | return .skip
22 | }
23 |
24 | var storeForwardInfo: StoreMessageForwardInfo?
25 | if let forwardInfo = currentMessage.forwardInfo {
26 | storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
27 | }
28 | return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
29 | })
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/TelegramCore/UpdatePeerChatInterfaceState.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | import SwiftSignalKitMac
5 | #else
6 | import Postbox
7 | import SwiftSignalKit
8 | #endif
9 |
10 | public func updatePeerChatInterfaceState(account: Account, peerId: PeerId, state: SynchronizeableChatInterfaceState) -> Signal {
11 | return account.postbox.transaction { transaction -> Void in
12 | let currentInputState = (transaction.getPeerChatInterfaceState(peerId) as? SynchronizeableChatInterfaceState)?.synchronizeableInputState
13 | let updatedInputState = state.synchronizeableInputState
14 |
15 | if currentInputState != updatedInputState {
16 | if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudGroup {
17 | addSynchronizeChatInputStateOperation(transaction: transaction, peerId: peerId)
18 | }
19 | }
20 | transaction.updatePeerChatInterfaceState(peerId, update: { _ in
21 | return state
22 | })
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/TelegramCore/ViewCountMessageAttribute.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public class ViewCountMessageAttribute: MessageAttribute {
9 | public let count: Int
10 |
11 | public var associatedMessageIds: [MessageId] = []
12 |
13 | init(count: Int) {
14 | self.count = count
15 | }
16 |
17 | required public init(decoder: PostboxDecoder) {
18 | self.count = Int(decoder.decodeInt32ForKey("c", orElse: 0))
19 | }
20 |
21 | public func encode(_ encoder: PostboxEncoder) {
22 | encoder.encodeInt32(Int32(self.count), forKey: "c")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/TelegramCore/VoipConfiguration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if os(macOS)
3 | import PostboxMac
4 | #else
5 | import Postbox
6 | #endif
7 |
8 | public enum VoiceCallP2PMode: Int32 {
9 | case never = 0
10 | case contacts = 1
11 | case always = 2
12 | }
13 |
14 | public struct VoipConfiguration: PreferencesEntry, Equatable {
15 | public var serializedData: String?
16 |
17 | public static var defaultValue: VoipConfiguration {
18 | return VoipConfiguration(serializedData: nil)
19 | }
20 |
21 | init(serializedData: String?) {
22 | self.serializedData = serializedData
23 | }
24 |
25 | public init(decoder: PostboxDecoder) {
26 | self.serializedData = decoder.decodeOptionalStringForKey("serializedData")
27 | }
28 |
29 | public func encode(_ encoder: PostboxEncoder) {
30 | if let serializedData = self.serializedData {
31 | encoder.encodeString(serializedData, forKey: "serializedData")
32 | } else {
33 | encoder.encodeNil(forKey: "serializedData")
34 | }
35 | }
36 |
37 | public func isEqual(to: PreferencesEntry) -> Bool {
38 | guard let to = to as? VoipConfiguration else {
39 | return false
40 | }
41 | return self == to
42 | }
43 | }
44 |
45 | public func currentVoipConfiguration(transaction: Transaction) -> VoipConfiguration {
46 | if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.voipConfiguration) as? VoipConfiguration {
47 | return entry
48 | } else {
49 | return VoipConfiguration.defaultValue
50 | }
51 | }
52 |
53 | func updateVoipConfiguration(transaction: Transaction, _ f: (VoipConfiguration) -> VoipConfiguration) {
54 | let current = currentVoipConfiguration(transaction: transaction)
55 | let updated = f(current)
56 | if updated != current {
57 | transaction.setPreferencesEntry(key: PreferencesKeys.voipConfiguration, value: updated)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/TelegramCore/module.private-mac.modulemap:
--------------------------------------------------------------------------------
1 | module TelegramCoreMac.TelegramCorePrivate {
2 | export *
3 | }
4 |
--------------------------------------------------------------------------------
/TelegramCore/module.private.modulemap:
--------------------------------------------------------------------------------
1 | module TelegramCore.TelegramCorePrivate {
2 | export *
3 | }
4 |
--------------------------------------------------------------------------------
/TelegramCoreMac/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2016 Peter. All rights reserved.
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/TelegramCoreMac/TelegramCoreMac.h:
--------------------------------------------------------------------------------
1 | //
2 | // TelegramCoreMac.h
3 | // TelegramCoreMac
4 | //
5 | // Created by Peter on 9/5/16.
6 | // Copyright © 2016 Peter. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for TelegramCoreMac.
12 | FOUNDATION_EXPORT double TelegramCoreMacVersionNumber;
13 |
14 | //! Project version string for TelegramCoreMac.
15 | FOUNDATION_EXPORT const unsigned char TelegramCoreMacVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/TelegramCoreTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TelegramCoreTests/TelegramCoreTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TelegramCoreTests.m
3 | // TelegramCoreTests
4 | //
5 | // Created by Peter on 8/1/16.
6 | // Copyright © 2016 Peter. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TelegramCoreTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TelegramCoreTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBAsYouTypeFormatter.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBAsYouTypeFormatter.h
3 | // libPhoneNumber
4 | //
5 | // Created by ishtar on 13. 2. 25..
6 | //
7 |
8 | #import
9 |
10 |
11 | @class NBAsYouTypeFormatter;
12 |
13 |
14 | @interface NBAsYouTypeFormatter : NSObject
15 |
16 | - (id)initWithRegionCode:(NSString *)regionCode;
17 | - (id)initWithRegionCodeForTest:(NSString *)regionCode;
18 | - (id)initWithRegionCode:(NSString *)regionCode bundle:(NSBundle *)bundle;
19 | - (id)initWithRegionCodeForTest:(NSString *)regionCode bundle:(NSBundle *)bundle;
20 |
21 | - (NSString *)inputString:(NSString *)string;
22 | - (NSString *)inputStringAndRememberPosition:(NSString *)string;
23 |
24 | - (NSString *)inputDigit:(NSString*)nextChar;
25 | - (NSString *)inputDigitAndRememberPosition:(NSString*)nextChar;
26 |
27 | - (NSString *)removeLastDigit;
28 | - (NSString *)removeLastDigitAndRememberPosition;
29 |
30 | - (NSInteger)getRememberedPosition;
31 |
32 | - (void)clear;
33 |
34 | @property (nonatomic, assign, readonly) BOOL isSuccessfulFormatting;
35 |
36 | @property (nonatomic, strong, readonly) NSString *regionPrefix;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBMetadataCoreMapper.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT (This file was auto-generated from NBPhoneMetaDataGenerator)
2 |
3 | #import
4 |
5 | @interface NBMetadataCoreMapper : NSObject
6 |
7 | + (NSArray *)ISOCodeFromCallingNumber:(NSString *)key;
8 |
9 | @end
10 |
11 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBMetadataCoreTest.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT (This file was auto-generated from NBPhoneMetaDataGenerator)
2 |
3 | #import
4 | #import "NBPhoneMetaData.h"
5 |
6 | @interface NBPhoneMetadataTestAD : NBPhoneMetaData
7 | @end
8 |
9 | @interface NBPhoneMetadataTestBR : NBPhoneMetaData
10 | @end
11 |
12 | @interface NBPhoneMetadataTestAU : NBPhoneMetaData
13 | @end
14 |
15 | @interface NBPhoneMetadataTestBB : NBPhoneMetaData
16 | @end
17 |
18 | @interface NBPhoneMetadataTestAE : NBPhoneMetaData
19 | @end
20 |
21 | @interface NBPhoneMetadataTestCX : NBPhoneMetaData
22 | @end
23 |
24 | @interface NBPhoneMetadataTestBS : NBPhoneMetaData
25 | @end
26 |
27 | @interface NBPhoneMetadataTestDE : NBPhoneMetaData
28 | @end
29 |
30 | @interface NBPhoneMetadataTestKR : NBPhoneMetaData
31 | @end
32 |
33 | @interface NBPhoneMetadataTestNZ : NBPhoneMetaData
34 | @end
35 |
36 | @interface NBPhoneMetadataTestPL : NBPhoneMetaData
37 | @end
38 |
39 | @interface NBPhoneMetadataTestSE : NBPhoneMetaData
40 | @end
41 |
42 | @interface NBPhoneMetadataTestCA : NBPhoneMetaData
43 | @end
44 |
45 | @interface NBPhoneMetadataTestAO : NBPhoneMetaData
46 | @end
47 |
48 | @interface NBPhoneMetadataTest800 : NBPhoneMetaData
49 | @end
50 |
51 | @interface NBPhoneMetadataTestYT : NBPhoneMetaData
52 | @end
53 |
54 | @interface NBPhoneMetadataTestFR : NBPhoneMetaData
55 | @end
56 |
57 | @interface NBPhoneMetadataTestGG : NBPhoneMetaData
58 | @end
59 |
60 | @interface NBPhoneMetadataTestHU : NBPhoneMetaData
61 | @end
62 |
63 | @interface NBPhoneMetadataTestSG : NBPhoneMetaData
64 | @end
65 |
66 | @interface NBPhoneMetadataTestJP : NBPhoneMetaData
67 | @end
68 |
69 | @interface NBPhoneMetadataTestCC : NBPhoneMetaData
70 | @end
71 |
72 | @interface NBPhoneMetadataTestMX : NBPhoneMetaData
73 | @end
74 |
75 | @interface NBPhoneMetadataTestUS : NBPhoneMetaData
76 | @end
77 |
78 | @interface NBPhoneMetadataTestIT : NBPhoneMetaData
79 | @end
80 |
81 | @interface NBPhoneMetadataTestAR : NBPhoneMetaData
82 | @end
83 |
84 | @interface NBPhoneMetadataTest979 : NBPhoneMetaData
85 | @end
86 |
87 | @interface NBPhoneMetadataTestGB : NBPhoneMetaData
88 | @end
89 |
90 | @interface NBPhoneMetadataTestBY : NBPhoneMetaData
91 | @end
92 |
93 | @interface NBPhoneMetadataTestCN : NBPhoneMetaData
94 | @end
95 |
96 | @interface NBPhoneMetadataTestRE : NBPhoneMetaData
97 | @end
98 |
99 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBMetadataCoreTestMapper.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT (This file was auto-generated from NBPhoneMetaDataGenerator)
2 |
3 | #import
4 |
5 | @interface NBMetadataCoreTestMapper : NSObject
6 |
7 | + (NSArray *)ISOCodeFromCallingNumber:(NSString *)key;
8 |
9 | @end
10 |
11 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBMetadataHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBMetadataHelper.h
3 | // libPhoneNumber
4 | //
5 | // Created by tabby on 2015. 2. 8..
6 | // Copyright (c) 2015년 ohtalk.me. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "NBPhoneNumberDefines.h"
11 |
12 |
13 | @class NBPhoneMetaData;
14 |
15 | @interface NBMetadataHelper : NSObject
16 |
17 | + (BOOL)hasValue:(NSString *)string;
18 |
19 | - (NSDictionary *)CCode2CNMap;
20 |
21 | - (NSArray *)getAllMetadata;
22 |
23 | - (NBPhoneMetaData *)getMetadataForNonGeographicalRegion:(NSNumber *)countryCallingCode;
24 | - (NBPhoneMetaData *)getMetadataForRegion:(NSString *)regionCode;
25 |
26 | - (NSArray *)regionCodeFromCountryCode:(NSNumber *)countryCodeNumber;
27 | - (NSString *)countryCodeFromRegionCode:(NSString *)regionCode;
28 |
29 | - (NSString *)stringByTrimming:(NSString *)aString;
30 | - (NSString *)normalizeNonBreakingSpace:(NSString *)aString;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBNumberFormat.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBPhoneNumberFormat.h
3 | // libPhoneNumber
4 | //
5 | //
6 |
7 | #import
8 |
9 |
10 | @interface NBNumberFormat : NSObject
11 |
12 | // from phonemetadata.pb.js
13 | /* 1 */ @property (nonatomic, strong) NSString *pattern;
14 | /* 2 */ @property (nonatomic, strong) NSString *format;
15 | /* 3 */ @property (nonatomic, strong) NSMutableArray *leadingDigitsPatterns;
16 | /* 4 */ @property (nonatomic, strong) NSString *nationalPrefixFormattingRule;
17 | /* 6 */ @property (nonatomic, assign) BOOL nationalPrefixOptionalWhenFormatting;
18 | /* 5 */ @property (nonatomic, strong) NSString *domesticCarrierCodeFormattingRule;
19 |
20 | - (id)initWithPattern:(NSString *)pattern withFormat:(NSString *)format withLeadingDigitsPatterns:(NSMutableArray *)leadingDigitsPatterns withNationalPrefixFormattingRule:(NSString *)nationalPrefixFormattingRule whenFormatting:(BOOL)nationalPrefixOptionalWhenFormatting withDomesticCarrierCodeFormattingRule:(NSString *)domesticCarrierCodeFormattingRule;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBPhoneMetaData.h:
--------------------------------------------------------------------------------
1 | //
2 | // M2PhoneMetaData.h
3 | // libPhoneNumber
4 | //
5 | //
6 |
7 | #import
8 |
9 |
10 | @class NBPhoneNumberDesc, NBNumberFormat;
11 |
12 | @interface NBPhoneMetaData : NSObject
13 |
14 | // from phonemetadata.pb.js
15 | /* 1 */ @property (nonatomic, strong) NBPhoneNumberDesc *generalDesc;
16 | /* 2 */ @property (nonatomic, strong) NBPhoneNumberDesc *fixedLine;
17 | /* 3 */ @property (nonatomic, strong) NBPhoneNumberDesc *mobile;
18 | /* 4 */ @property (nonatomic, strong) NBPhoneNumberDesc *tollFree;
19 | /* 5 */ @property (nonatomic, strong) NBPhoneNumberDesc *premiumRate;
20 | /* 6 */ @property (nonatomic, strong) NBPhoneNumberDesc *sharedCost;
21 | /* 7 */ @property (nonatomic, strong) NBPhoneNumberDesc *personalNumber;
22 | /* 8 */ @property (nonatomic, strong) NBPhoneNumberDesc *voip;
23 | /* 21 */ @property (nonatomic, strong) NBPhoneNumberDesc *pager;
24 | /* 25 */ @property (nonatomic, strong) NBPhoneNumberDesc *uan;
25 | /* 27 */ @property (nonatomic, strong) NBPhoneNumberDesc *emergency;
26 | /* 28 */ @property (nonatomic, strong) NBPhoneNumberDesc *voicemail;
27 | /* 24 */ @property (nonatomic, strong) NBPhoneNumberDesc *noInternationalDialling;
28 | /* 9 */ @property (nonatomic, strong) NSString *codeID;
29 | /* 10 */ @property (nonatomic, strong) NSNumber *countryCode;
30 | /* 11 */ @property (nonatomic, strong) NSString *internationalPrefix;
31 | /* 17 */ @property (nonatomic, strong) NSString *preferredInternationalPrefix;
32 | /* 12 */ @property (nonatomic, strong) NSString *nationalPrefix;
33 | /* 13 */ @property (nonatomic, strong) NSString *preferredExtnPrefix;
34 | /* 15 */ @property (nonatomic, strong) NSString *nationalPrefixForParsing;
35 | /* 16 */ @property (nonatomic, strong) NSString *nationalPrefixTransformRule;
36 | /* 18 */ @property (nonatomic, assign) BOOL sameMobileAndFixedLinePattern;
37 | /* 19 */ @property (nonatomic, strong) NSMutableArray *numberFormats;
38 | /* 20 */ @property (nonatomic, strong) NSMutableArray *intlNumberFormats;
39 | /* 22 */ @property (nonatomic, assign) BOOL mainCountryForCode;
40 | /* 23 */ @property (nonatomic, strong) NSString *leadingDigits;
41 | /* 26 */ @property (nonatomic, assign) BOOL leadingZeroPossible;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBPhoneMetaDataGenerator.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBPhoneMetaDataGenerator.h
3 | // libPhoneNumber
4 | //
5 | //
6 |
7 | #import
8 |
9 |
10 | @interface NBPhoneMetaDataGenerator : NSObject
11 |
12 | - (void)generateMetadataClasses;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBPhoneNumber.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBPhoneNumber.h
3 | // libPhoneNumber
4 | //
5 | //
6 |
7 | #import
8 | #import "NBPhoneNumberDefines.h"
9 |
10 |
11 | @interface NBPhoneNumber : NSObject
12 |
13 | // from phonemetadata.pb.js
14 | /* 1 */ @property (nonatomic, strong, readwrite) NSNumber *countryCode;
15 | /* 2 */ @property (nonatomic, strong, readwrite) NSNumber *nationalNumber;
16 | /* 3 */ @property (nonatomic, strong, readwrite) NSString *extension;
17 | /* 4 */ @property (nonatomic, assign, readwrite) BOOL italianLeadingZero;
18 | /* 5 */ @property (nonatomic, strong, readwrite) NSString *rawInput;
19 | /* 6 */ @property (nonatomic, strong, readwrite) NSNumber *countryCodeSource;
20 | /* 7 */ @property (nonatomic, strong, readwrite) NSString *preferredDomesticCarrierCode;
21 |
22 | - (void)clearCountryCodeSource;
23 | - (NBECountryCodeSource)getCountryCodeSourceOrDefault;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBPhoneNumberDefines.m:
--------------------------------------------------------------------------------
1 | #import "NBPhoneNumberDefines.h"
2 |
3 | NSString * const NB_UNKNOWN_REGION = @"ZZ";
4 | NSString * const NB_NON_BREAKING_SPACE = @"\u00a0";
5 | NSString * const NB_PLUS_CHARS = @"++";
6 | NSString * const NB_VALID_DIGITS_STRING = @"0-90-9٠-٩۰-۹";
7 | NSString * const NB_REGION_CODE_FOR_NON_GEO_ENTITY = @"001";
8 |
--------------------------------------------------------------------------------
/third-party/libphonenumber-iOS/NBPhoneNumberDesc.h:
--------------------------------------------------------------------------------
1 | //
2 | // NBPhoneNumberDesc.h
3 | // libPhoneNumber
4 | //
5 | //
6 |
7 | #import
8 |
9 |
10 | @interface NBPhoneNumberDesc : NSObject
11 |
12 | // from phonemetadata.pb.js
13 | /* 2 */ @property (nonatomic, strong, readwrite) NSString *nationalNumberPattern;
14 | /* 3 */ @property (nonatomic, strong, readwrite) NSString *possibleNumberPattern;
15 | /* 6 */ @property (nonatomic, strong, readwrite) NSString *exampleNumber;
16 |
17 | - (id)initWithNationalNumberPattern:(NSString *)nnp withPossibleNumberPattern:(NSString *)pnp withExample:(NSString *)exp;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------