2025-03-18 14:39:58 +04:00

414 lines
18 KiB
Swift

import Foundation
import Postbox
import TelegramApi
public final class SelectivePrivacyPeer: Equatable {
public let peer: Peer
public let participantCount: Int32?
public init(peer: Peer, participantCount: Int32?) {
self.peer = peer
self.participantCount = participantCount
}
public static func ==(lhs: SelectivePrivacyPeer, rhs: SelectivePrivacyPeer) -> Bool {
if !lhs.peer.isEqual(rhs.peer) {
return false
}
if lhs.participantCount != rhs.participantCount {
return false
}
return true
}
public var userCount: Int {
if let participantCount = self.participantCount {
return Int(participantCount)
} else if let group = self.peer as? TelegramGroup {
return group.participantCount
} else {
return 1
}
}
}
public enum SelectivePrivacySettings: Equatable {
case enableEveryone(disableFor: [PeerId: SelectivePrivacyPeer])
case enableContacts(enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer], enableForPremium: Bool, enableForBots: Bool)
case disableEveryone(enableFor: [PeerId: SelectivePrivacyPeer], enableForCloseFriends: Bool, enableForPremium: Bool, enableForBots: Bool)
public static func ==(lhs: SelectivePrivacySettings, rhs: SelectivePrivacySettings) -> Bool {
switch lhs {
case let .enableEveryone(disableFor):
if case .enableEveryone(disableFor) = rhs {
return true
} else {
return false
}
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
if case .enableContacts(enableFor, disableFor, enableForPremium, enableForBots) = rhs {
return true
} else {
return false
}
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots):
if case .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots) = rhs {
return true
} else {
return false
}
}
}
func withEnabledPeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots):
return .disableEveryone(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
return .enableContacts(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableEveryone:
return self
}
}
func withDisabledPeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettings {
switch self {
case .disableEveryone:
return self
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
return .enableContacts(enableFor: enableFor, disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableEveryone(disableFor):
return .enableEveryone(disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }))
}
}
func withEnableForPremium(_ enableForPremium: Bool) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, _, enableForBots):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableContacts(enableFor, disableFor, _, enableForBots):
return .enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableEveryone:
return self
}
}
func withEnableForCloseFriends(_ enableForCloseFriends: Bool) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, _, enableForPremium, enableForBots):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableContacts:
return self
case .enableEveryone:
return self
}
}
func withEnableForBots(_ enableForBots: Bool?) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, _):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots == true)
case let .enableContacts(enableFor, disableFor, enableForPremium, _):
return .enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots == true)
case let .enableEveryone(disableFor):
return .enableEveryone(disableFor: disableFor)
}
}
}
public struct AccountPrivacySettings: Equatable {
public var presence: SelectivePrivacySettings
public var groupInvitations: SelectivePrivacySettings
public var voiceCalls: SelectivePrivacySettings
public var voiceCallsP2P: SelectivePrivacySettings
public var profilePhoto: SelectivePrivacySettings
public var forwards: SelectivePrivacySettings
public var phoneNumber: SelectivePrivacySettings
public var phoneDiscoveryEnabled: Bool
public var voiceMessages: SelectivePrivacySettings
public var bio: SelectivePrivacySettings
public var birthday: SelectivePrivacySettings
public var giftsAutoSave: SelectivePrivacySettings
public var noPaidMessages: SelectivePrivacySettings
public var globalSettings: GlobalPrivacySettings
public var accountRemovalTimeout: Int32
public var messageAutoremoveTimeout: Int32?
public init(presence: SelectivePrivacySettings, groupInvitations: SelectivePrivacySettings, voiceCalls: SelectivePrivacySettings, voiceCallsP2P: SelectivePrivacySettings, profilePhoto: SelectivePrivacySettings, forwards: SelectivePrivacySettings, phoneNumber: SelectivePrivacySettings, phoneDiscoveryEnabled: Bool, voiceMessages: SelectivePrivacySettings, bio: SelectivePrivacySettings, birthday: SelectivePrivacySettings, giftsAutoSave: SelectivePrivacySettings, noPaidMessages: SelectivePrivacySettings, globalSettings: GlobalPrivacySettings, accountRemovalTimeout: Int32, messageAutoremoveTimeout: Int32?) {
self.presence = presence
self.groupInvitations = groupInvitations
self.voiceCalls = voiceCalls
self.voiceCallsP2P = voiceCallsP2P
self.profilePhoto = profilePhoto
self.forwards = forwards
self.phoneNumber = phoneNumber
self.phoneDiscoveryEnabled = phoneDiscoveryEnabled
self.voiceMessages = voiceMessages
self.bio = bio
self.birthday = birthday
self.giftsAutoSave = giftsAutoSave
self.noPaidMessages = noPaidMessages
self.globalSettings = globalSettings
self.accountRemovalTimeout = accountRemovalTimeout
self.messageAutoremoveTimeout = messageAutoremoveTimeout
}
public static func ==(lhs: AccountPrivacySettings, rhs: AccountPrivacySettings) -> Bool {
if lhs.presence != rhs.presence {
return false
}
if lhs.groupInvitations != rhs.groupInvitations {
return false
}
if lhs.voiceCalls != rhs.voiceCalls {
return false
}
if lhs.voiceCallsP2P != rhs.voiceCallsP2P {
return false
}
if lhs.profilePhoto != rhs.profilePhoto {
return false
}
if lhs.forwards != rhs.forwards {
return false
}
if lhs.phoneNumber != rhs.phoneNumber {
return false
}
if lhs.phoneDiscoveryEnabled != rhs.phoneDiscoveryEnabled {
return false
}
if lhs.voiceMessages != rhs.voiceMessages {
return false
}
if lhs.bio != rhs.bio {
return false
}
if lhs.birthday != rhs.birthday {
return false
}
if lhs.giftsAutoSave != rhs.giftsAutoSave {
return false
}
if lhs.noPaidMessages != rhs.noPaidMessages {
return false
}
if lhs.globalSettings != rhs.globalSettings {
return false
}
if lhs.accountRemovalTimeout != rhs.accountRemovalTimeout {
return false
}
if lhs.messageAutoremoveTimeout != rhs.messageAutoremoveTimeout {
return false
}
return true
}
}
extension SelectivePrivacySettings {
init(apiRules: [Api.PrivacyRule], peers: [PeerId: SelectivePrivacyPeer]) {
var current: SelectivePrivacySettings = .disableEveryone(enableFor: [:], enableForCloseFriends: false, enableForPremium: false, enableForBots: false)
var disableFor: [PeerId: SelectivePrivacyPeer] = [:]
var enableFor: [PeerId: SelectivePrivacyPeer] = [:]
var enableForCloseFriends: Bool = false
var enableForPremium: Bool = false
var enableForBots: Bool?
for rule in apiRules {
switch rule {
case .privacyValueAllowAll:
current = .enableEveryone(disableFor: [:])
case .privacyValueAllowContacts:
current = .enableContacts(enableFor: [:], disableFor: [:], enableForPremium: false, enableForBots: false)
case let .privacyValueAllowUsers(users):
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
enableFor[peer.peer.id] = peer
}
}
case .privacyValueDisallowAll:
break
case .privacyValueDisallowContacts:
break
case let .privacyValueDisallowUsers(users):
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
disableFor[peer.peer.id] = peer
}
}
case let .privacyValueAllowChatParticipants(chats):
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
enableFor[peer.peer.id] = peer
}
}
}
case let .privacyValueDisallowChatParticipants(chats):
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
disableFor[peer.peer.id] = peer
}
}
}
case .privacyValueAllowCloseFriends:
enableForCloseFriends = true
case .privacyValueAllowPremium:
enableForPremium = true
case .privacyValueAllowBots:
enableForBots = true
case .privacyValueDisallowBots:
break
}
}
self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor).withEnableForCloseFriends(enableForCloseFriends).withEnableForPremium(enableForPremium).withEnableForBots(enableForBots)
}
}
public struct GlobalMessageAutoremoveTimeoutSettings: Equatable, Codable {
public static var `default` = GlobalMessageAutoremoveTimeoutSettings(
messageAutoremoveTimeout: nil
)
public var messageAutoremoveTimeout: Int32?
public init(messageAutoremoveTimeout: Int32?) {
self.messageAutoremoveTimeout = messageAutoremoveTimeout
}
}
func updateGlobalMessageAutoremoveTimeoutSettings(transaction: Transaction, _ f: (GlobalMessageAutoremoveTimeoutSettings) -> GlobalMessageAutoremoveTimeoutSettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.globalMessageAutoremoveTimeoutSettings, { current in
let previous = current?.get(GlobalMessageAutoremoveTimeoutSettings.self) ?? GlobalMessageAutoremoveTimeoutSettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}
public struct TelegramDisallowedGifts: OptionSet, Codable {
public var rawValue: Int32
public init() {
self.rawValue = 0
}
public init(rawValue: Int32) {
self.rawValue = rawValue
}
public static let unlimited = TelegramDisallowedGifts(rawValue: 1 << 0)
public static let limited = TelegramDisallowedGifts(rawValue: 1 << 1)
public static let unique = TelegramDisallowedGifts(rawValue: 1 << 2)
public static let premium = TelegramDisallowedGifts(rawValue: 1 << 3)
public static let All: TelegramDisallowedGifts = [
.unlimited,
.limited,
.unique,
.premium
]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
let value = try? container.decode(Int32.self, forKey: "v")
self = TelegramDisallowedGifts(rawValue: value ?? 0)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.rawValue, forKey: "v")
}
}
public struct GlobalPrivacySettings: Equatable, Codable {
public enum NonContactChatsPrivacy: Equatable, Codable {
case everybody
case requirePremium
case paidMessages(StarsAmount)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
switch (try? container.decode(Int32.self, forKey: "t")) ?? 0 {
case 0:
self = .everybody
case 1:
self = .requirePremium
case 2:
self = .paidMessages(StarsAmount(value: try container.decodeIfPresent(Int64.self, forKey: "stars") ?? 0, nanos: 0))
default:
assertionFailure()
self = .everybody
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
switch self {
case .everybody:
try container.encode(0 as Int32, forKey: "t")
case .requirePremium:
try container.encode(1 as Int32, forKey: "t")
case let .paidMessages(amount):
try container.encode(2 as Int32, forKey: "t")
try container.encode(amount.value, forKey: "stars")
}
}
}
public static var `default` = GlobalPrivacySettings(
automaticallyArchiveAndMuteNonContacts: false,
keepArchivedUnmuted: true,
keepArchivedFolders: true,
hideReadTime: false,
nonContactChatsPrivacy: .everybody,
disallowedGifts: [],
displayGiftButton: false
)
public var automaticallyArchiveAndMuteNonContacts: Bool
public var keepArchivedUnmuted: Bool
public var keepArchivedFolders: Bool
public var hideReadTime: Bool
public var nonContactChatsPrivacy: NonContactChatsPrivacy
public var disallowedGifts: TelegramDisallowedGifts
public var displayGiftButton: Bool
public init(
automaticallyArchiveAndMuteNonContacts: Bool,
keepArchivedUnmuted: Bool,
keepArchivedFolders: Bool,
hideReadTime: Bool,
nonContactChatsPrivacy: NonContactChatsPrivacy,
disallowedGifts: TelegramDisallowedGifts,
displayGiftButton: Bool
) {
self.automaticallyArchiveAndMuteNonContacts = automaticallyArchiveAndMuteNonContacts
self.keepArchivedUnmuted = keepArchivedUnmuted
self.keepArchivedFolders = keepArchivedFolders
self.hideReadTime = hideReadTime
self.nonContactChatsPrivacy = nonContactChatsPrivacy
self.disallowedGifts = disallowedGifts
self.displayGiftButton = displayGiftButton
}
}
func fetchGlobalPrivacySettings(transaction: Transaction) -> GlobalPrivacySettings {
return transaction.getPreferencesEntry(key: PreferencesKeys.globalPrivacySettings)?.get(GlobalPrivacySettings.self) ?? GlobalPrivacySettings.default
}
func updateGlobalPrivacySettings(transaction: Transaction, _ f: (GlobalPrivacySettings) -> GlobalPrivacySettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.globalPrivacySettings, { current in
let previous = current?.get(GlobalPrivacySettings.self) ?? GlobalPrivacySettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}