mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-07 14:53:35 +00:00
Merge branch 'master' of https://github.com/peter-iakovlev/TelegramCore
Conflicts: TelegramCore/ProcessSecretChatIncomingDecryptedOperations.swift
This commit is contained in:
commit
d3a0226f72
@ -115,6 +115,31 @@ public func enqueueMessages(account: Account, peerId: PeerId, messages: [Enqueue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<Void, NoError> {
|
||||||
|
return account.postbox.modify { modifier -> Void in
|
||||||
|
var removeMessageIds: [MessageId] = []
|
||||||
|
for (peerId, ids) in messagesIdsGroupedByPeerId(messageIds) {
|
||||||
|
var messages: [EnqueueMessage] = []
|
||||||
|
for id in ids {
|
||||||
|
if let message = modifier.getMessage(id), !message.flags.contains(.Incoming) {
|
||||||
|
removeMessageIds.append(id)
|
||||||
|
|
||||||
|
var replyToMessageId: MessageId?
|
||||||
|
for attribute in message.attributes {
|
||||||
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
|
replyToMessageId = attribute.messageId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.append(.message(text: message.text, attributes: message.attributes, media: message.media.first, replyToMessageId: replyToMessageId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = enqueueMessages(modifier: modifier, account: account, peerId: peerId, messages: messages.map { (false, $0) })
|
||||||
|
}
|
||||||
|
modifier.deleteMessages(removeMessageIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func enqueueMessages(modifier: Modifier, account: Account, peerId: PeerId, messages: [(Bool, EnqueueMessage)]) -> [MessageId?] {
|
func enqueueMessages(modifier: Modifier, account: Account, peerId: PeerId, messages: [(Bool, EnqueueMessage)]) -> [MessageId?] {
|
||||||
if let peer = modifier.getPeer(peerId) {
|
if let peer = modifier.getPeer(peerId) {
|
||||||
var storeMessages: [StoreMessage] = []
|
var storeMessages: [StoreMessage] = []
|
||||||
|
|||||||
@ -57,7 +57,6 @@ public extension Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func messagesIdsGroupedByPeerId(_ ids: Set<MessageId>) -> [PeerId: [MessageId]] {
|
func messagesIdsGroupedByPeerId(_ ids: Set<MessageId>) -> [PeerId: [MessageId]] {
|
||||||
var dict: [PeerId: [MessageId]] = [:]
|
var dict: [PeerId: [MessageId]] = [:]
|
||||||
|
|
||||||
@ -73,6 +72,20 @@ func messagesIdsGroupedByPeerId(_ ids: Set<MessageId>) -> [PeerId: [MessageId]]
|
|||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func messagesIdsGroupedByPeerId(_ ids: [MessageId]) -> [PeerId: [MessageId]] {
|
||||||
|
var dict: [PeerId: [MessageId]] = [:]
|
||||||
|
|
||||||
|
for id in ids {
|
||||||
|
let peerId = id.peerId
|
||||||
|
if dict[peerId] == nil {
|
||||||
|
dict[peerId] = [id]
|
||||||
|
} else {
|
||||||
|
dict[peerId]!.append(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? {
|
func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? {
|
||||||
guard case let .Id(id) = message.id else {
|
guard case let .Id(id) = message.id else {
|
||||||
|
|||||||
@ -32,6 +32,28 @@ public enum SelectivePrivacySettings: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withEnabledPeerIds(_ peerIds: Set<PeerId>) -> SelectivePrivacySettings {
|
||||||
|
switch self {
|
||||||
|
case let .disableEveryone(enableFor):
|
||||||
|
return .disableEveryone(enableFor: enableFor.union(peerIds))
|
||||||
|
case let .enableContacts(enableFor, disableFor):
|
||||||
|
return .enableContacts(enableFor: enableFor.union(peerIds), disableFor: disableFor)
|
||||||
|
case .enableEveryone:
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func withDisabledPeerIds(_ peerIds: Set<PeerId>) -> SelectivePrivacySettings {
|
||||||
|
switch self {
|
||||||
|
case .disableEveryone:
|
||||||
|
return self
|
||||||
|
case let .enableContacts(enableFor, disableFor):
|
||||||
|
return .enableContacts(enableFor: enableFor, disableFor: disableFor.union(peerIds))
|
||||||
|
case let .enableEveryone(disableFor):
|
||||||
|
return .enableEveryone(disableFor: disableFor.union(peerIds))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AccountPrivacySettings: Equatable {
|
public struct AccountPrivacySettings: Equatable {
|
||||||
@ -41,6 +63,13 @@ public struct AccountPrivacySettings: Equatable {
|
|||||||
|
|
||||||
public let accountRemovalTimeout: Int32
|
public let accountRemovalTimeout: Int32
|
||||||
|
|
||||||
|
public init(presence: SelectivePrivacySettings, groupInvitations: SelectivePrivacySettings, voiceCalls: SelectivePrivacySettings, accountRemovalTimeout: Int32) {
|
||||||
|
self.presence = presence
|
||||||
|
self.groupInvitations = groupInvitations
|
||||||
|
self.voiceCalls = voiceCalls
|
||||||
|
self.accountRemovalTimeout = accountRemovalTimeout
|
||||||
|
}
|
||||||
|
|
||||||
public static func ==(lhs: AccountPrivacySettings, rhs: AccountPrivacySettings) -> Bool {
|
public static func ==(lhs: AccountPrivacySettings, rhs: AccountPrivacySettings) -> Bool {
|
||||||
if lhs.presence != rhs.presence {
|
if lhs.presence != rhs.presence {
|
||||||
return false
|
return false
|
||||||
@ -59,3 +88,31 @@ public struct AccountPrivacySettings: Equatable {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension SelectivePrivacySettings {
|
||||||
|
init(apiRules: [Api.PrivacyRule]) {
|
||||||
|
var current: SelectivePrivacySettings = .disableEveryone(enableFor: Set())
|
||||||
|
|
||||||
|
var disableFor = Set<PeerId>()
|
||||||
|
var enableFor = Set<PeerId>()
|
||||||
|
|
||||||
|
for rule in apiRules {
|
||||||
|
switch rule {
|
||||||
|
case .privacyValueAllowAll:
|
||||||
|
current = .enableEveryone(disableFor: Set())
|
||||||
|
case .privacyValueAllowContacts:
|
||||||
|
current = .enableContacts(enableFor: Set(), disableFor: Set())
|
||||||
|
case let .privacyValueAllowUsers(users):
|
||||||
|
enableFor = Set(users.map { PeerId(namespace: Namespaces.Peer.CloudUser, id: $0) })
|
||||||
|
case .privacyValueDisallowAll:
|
||||||
|
current = .disableEveryone(enableFor: Set())
|
||||||
|
case .privacyValueDisallowContacts:
|
||||||
|
break
|
||||||
|
case let .privacyValueDisallowUsers(users):
|
||||||
|
disableFor = Set(users.map { PeerId(namespace: Namespaces.Peer.CloudUser, id: $0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self = current.withEnabledPeerIds(enableFor).withDisabledPeerIds(disableFor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -158,7 +158,6 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, modifier:
|
|||||||
} else {
|
} else {
|
||||||
if let layer = SecretChatSequenceBasedLayer(rawValue: parsedLayer.rawValue) {
|
if let layer = SecretChatSequenceBasedLayer(rawValue: parsedLayer.rawValue) {
|
||||||
let role = updatedState.role
|
let role = updatedState.role
|
||||||
|
|
||||||
let fromSeqNo: Int32 = (topProcessedCanonicalIncomingOperationIndex + 1) * 2 + (role == .creator ? 1 : 1)
|
let fromSeqNo: Int32 = (topProcessedCanonicalIncomingOperationIndex + 1) * 2 + (role == .creator ? 1 : 1)
|
||||||
let toSeqNo: Int32 = (canonicalIncomingIndex - 1) * 2 + (role == .creator ? 1 : 0)
|
let toSeqNo: Int32 = (canonicalIncomingIndex - 1) * 2 + (role == .creator ? 1 : 0)
|
||||||
updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: arc4random64(), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: arc4random64(), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
||||||
@ -545,11 +544,11 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||||||
return nil
|
return nil
|
||||||
case .decryptedMessageActionFlushHistory:
|
case .decryptedMessageActionFlushHistory:
|
||||||
return nil
|
return nil
|
||||||
case let .decryptedMessageActionNotifyLayer(layer):
|
case .decryptedMessageActionNotifyLayer:
|
||||||
return nil
|
return nil
|
||||||
case let .decryptedMessageActionReadMessages(randomIds):
|
case .decryptedMessageActionReadMessages:
|
||||||
return nil
|
return nil
|
||||||
case let .decryptedMessageActionScreenshotMessages(randomIds):
|
case .decryptedMessageActionScreenshotMessages:
|
||||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .historyScreenshot)]), [])
|
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .historyScreenshot)]), [])
|
||||||
case let .decryptedMessageActionSetMessageTTL(ttlSeconds):
|
case let .decryptedMessageActionSetMessageTTL(ttlSeconds):
|
||||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(ttlSeconds))]), [])
|
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, timestamp: timestamp, flags: [.Incoming], tags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(ttlSeconds))]), [])
|
||||||
|
|||||||
@ -7,19 +7,118 @@ import Foundation
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public func updatedAccountPrivacySettings(account: Account) -> Signal<AccountPrivacySettings, NoError> {
|
public func requestAccountPrivacySettings(account: Account) -> Signal<AccountPrivacySettings, NoError> {
|
||||||
let lastSeenPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyStatusTimestamp))
|
let lastSeenPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyStatusTimestamp))
|
||||||
let groupPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyChatInvite))
|
let groupPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyChatInvite))
|
||||||
let voiceCallPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyPhoneCall))
|
let voiceCallPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyPhoneCall))
|
||||||
let autoremoveTimeout = account.network.request(Api.functions.account.getAccountTTL())
|
let autoremoveTimeout = account.network.request(Api.functions.account.getAccountTTL())
|
||||||
return combineLatest(lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, autoremoveTimeout)
|
return combineLatest(lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, autoremoveTimeout)
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> map { lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, autoremoveTimeout -> AccountPrivacySettings in
|
|> mapToSignal { lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, autoremoveTimeout -> Signal<AccountPrivacySettings, NoError> in
|
||||||
let accountTimeoutSeconds: Int32
|
let accountTimeoutSeconds: Int32
|
||||||
switch autoremoveTimeout {
|
switch autoremoveTimeout {
|
||||||
case let .accountDaysTTL(days):
|
case let .accountDaysTTL(days):
|
||||||
accountTimeoutSeconds = days * 24 * 60 * 60
|
accountTimeoutSeconds = days * 24 * 60 * 60
|
||||||
}
|
}
|
||||||
return AccountPrivacySettings(presence: .enableEveryone(disableFor: Set()), groupInvitations: .enableEveryone(disableFor: Set()), voiceCalls: .enableEveryone(disableFor: Set()), accountRemovalTimeout: accountTimeoutSeconds)
|
|
||||||
|
|
||||||
|
let lastSeenRules: [Api.PrivacyRule]
|
||||||
|
let groupRules: [Api.PrivacyRule]
|
||||||
|
let voiceRules: [Api.PrivacyRule]
|
||||||
|
var apiUsers: [Api.User] = []
|
||||||
|
|
||||||
|
switch lastSeenPrivacy {
|
||||||
|
case let .privacyRules(rules, users):
|
||||||
|
apiUsers.append(contentsOf: users)
|
||||||
|
lastSeenRules = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
switch groupPrivacy {
|
||||||
|
case let .privacyRules(rules, users):
|
||||||
|
apiUsers.append(contentsOf: users)
|
||||||
|
groupRules = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
switch voiceCallPrivacy {
|
||||||
|
case let .privacyRules(rules, users):
|
||||||
|
apiUsers.append(contentsOf: users)
|
||||||
|
voiceRules = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
let peers = apiUsers.map { TelegramUser(user: $0) }
|
||||||
|
|
||||||
|
return account.postbox.modify { modifier -> AccountPrivacySettings in
|
||||||
|
updatePeers(modifier: modifier, peers: peers, update: { _, updated in
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
|
||||||
|
return AccountPrivacySettings(presence: SelectivePrivacySettings(apiRules: lastSeenRules), groupInvitations: SelectivePrivacySettings(apiRules: groupRules), voiceCalls: SelectivePrivacySettings(apiRules: voiceRules), accountRemovalTimeout: accountTimeoutSeconds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func updateAccountRemovalTimeout(account: Account, timeout: Int32) -> Signal<Void, NoError> {
|
||||||
|
return account.network.request(Api.functions.account.setAccountTTL(ttl: .accountDaysTTL(days: timeout / (24 * 60 * 60))))
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UpdateSelectiveAccountPrivacySettingsType {
|
||||||
|
case presence
|
||||||
|
case groupInvitations
|
||||||
|
case voiceCalls
|
||||||
|
|
||||||
|
var apiKey: Api.InputPrivacyKey {
|
||||||
|
switch self {
|
||||||
|
case .presence:
|
||||||
|
return .inputPrivacyKeyStatusTimestamp
|
||||||
|
case .groupInvitations:
|
||||||
|
return .inputPrivacyKeyChatInvite
|
||||||
|
case .voiceCalls:
|
||||||
|
return .inputPrivacyKeyPhoneCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func apiInputUsers(modifier: Modifier, peerIds: [PeerId]) -> [Api.InputUser] {
|
||||||
|
var result: [Api.InputUser] = []
|
||||||
|
for peerId in peerIds {
|
||||||
|
if let peer = modifier.getPeer(peerId), let inputUser = apiInputUser(peer) {
|
||||||
|
result.append(inputUser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateSelectiveAccountPrivacySettings(account: Account, type: UpdateSelectiveAccountPrivacySettingsType, settings: SelectivePrivacySettings) -> Signal<Void, NoError> {
|
||||||
|
return account.postbox.modify { modifier -> Signal<Void, NoError> in
|
||||||
|
var rules: [Api.InputPrivacyRule] = []
|
||||||
|
switch settings {
|
||||||
|
case let .disableEveryone(enableFor):
|
||||||
|
if !enableFor.isEmpty {
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueAllowUsers(users: apiInputUsers(modifier: modifier, peerIds: Array(enableFor))))
|
||||||
|
}
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueDisallowAll)
|
||||||
|
case let .enableContacts(enableFor, disableFor):
|
||||||
|
if !enableFor.isEmpty {
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueAllowUsers(users: apiInputUsers(modifier: modifier, peerIds: Array(enableFor))))
|
||||||
|
}
|
||||||
|
if !disableFor.isEmpty {
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueDisallowUsers(users: apiInputUsers(modifier: modifier, peerIds: Array(disableFor))))
|
||||||
|
}
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueAllowContacts)
|
||||||
|
case let.enableEveryone(disableFor):
|
||||||
|
if !disableFor.isEmpty {
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueDisallowUsers(users: apiInputUsers(modifier: modifier, peerIds: Array(disableFor))))
|
||||||
|
}
|
||||||
|
rules.append(Api.InputPrivacyRule.inputPrivacyValueAllowAll)
|
||||||
|
}
|
||||||
|
return account.network.request(Api.functions.account.setPrivacy(key: type.apiKey, rules: rules))
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
} |> switchToLatest
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user