mirror of
https://github.com/GLEGram/GLEGram-iOS.git
synced 2026-04-26 12:56:34 +02:00
4647310322
Based on Swiftgram 12.5 (Telegram iOS 12.5). All GLEGram features ported and organized in GLEGram/ folder. Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass, Font Replacement, Fake Profile, Chat Export, Plugin System, and more. See CHANGELOG_12.5.md for full details.
219 lines
14 KiB
Swift
219 lines
14 KiB
Swift
import Foundation
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramApi
|
|
#if canImport(SGDeletedMessages)
|
|
import SGDeletedMessages
|
|
#if canImport(SGLogging)
|
|
import SGLogging
|
|
#endif
|
|
#endif
|
|
#if canImport(SGSimpleSettings)
|
|
import SGSimpleSettings
|
|
#endif
|
|
|
|
func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Never, NoError> {
|
|
return network.request(Api.functions.updates.getState())
|
|
|> retryRequest
|
|
|> mapToSignal { state -> Signal<Never, NoError> in
|
|
let chatList = fetchChatList(accountPeerId: accountPeerId, postbox: postbox, network: network, location: .general, upperBound: .absoluteUpperBound(), hash: 0, limit: 100)
|
|
|
|
return chatList
|
|
|> mapToSignal { fetchedChats -> Signal<Never, NoError> in
|
|
guard let fetchedChats = fetchedChats else {
|
|
return .never()
|
|
}
|
|
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, resolveThreads: false, { transaction, additionalPeers, additionalMessages -> Void in
|
|
for peerId in transaction.chatListGetAllPeerIds() {
|
|
if peerId.namespace != Namespaces.Peer.SecretChat {
|
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
|
}
|
|
|
|
if peerId.namespace != Namespaces.Peer.SecretChat {
|
|
transaction.addHole(peerId: peerId, threadId: nil, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1))
|
|
}
|
|
|
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
|
if let channel = transaction.getPeer(peerId) as? TelegramChannel, channel.isForumOrMonoForum {
|
|
transaction.setPeerPinnedThreads(peerId: peerId, threadIds: [])
|
|
for threadId in transaction.setMessageHistoryThreads(peerId: peerId) {
|
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: nil)
|
|
transaction.addHole(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1))
|
|
}
|
|
}
|
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, _ in nil })
|
|
transaction.setPeerThreadCombinedState(peerId: peerId, state: nil)
|
|
}
|
|
}
|
|
|
|
transaction.removeAllChatListEntries(groupId: .root, exceptPeerNamespace: Namespaces.Peer.SecretChat)
|
|
transaction.removeAllChatListEntries(groupId: .group(1), exceptPeerNamespace: Namespaces.Peer.SecretChat)
|
|
|
|
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: fetchedChats.peers.union(with: additionalPeers))
|
|
|
|
for (threadMessageId, data) in fetchedChats.threadInfos {
|
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, info: entry)
|
|
}
|
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
|
}
|
|
|
|
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
|
let _ = transaction.addMessages(fetchedChats.storeMessages, location: .UpperHistoryBlock)
|
|
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
|
// MARK: - GLEGram - Bump maxKnownId for saved-deleted tops
|
|
var readStates = fetchedChats.readStates
|
|
#if canImport(SGDeletedMessages)
|
|
if SGDeletedMessages.showDeletedMessages {
|
|
for (peerId, namespaces) in readStates {
|
|
guard let cloudState = namespaces[Namespaces.Message.Cloud] else {
|
|
continue
|
|
}
|
|
switch cloudState {
|
|
case let .idBased(maxIncomingReadId, maxOutgoingReadId, maxKnownId, count, markedUnread):
|
|
if let localTop = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud),
|
|
localTop.id > maxKnownId,
|
|
let localTopMessage = transaction.getMessage(localTop),
|
|
localTopMessage.sgDeletedAttribute.isDeleted {
|
|
#if canImport(SGLogging)
|
|
SGLogger.shared.log("SGDeletedMessages", "ResetState.resetIncomingReadStates: bump maxKnownId peerId=\(peerId) \(maxKnownId)→\(localTop.id) (saved deleted top)")
|
|
#endif
|
|
var updated = namespaces
|
|
updated[Namespaces.Message.Cloud] = .idBased(
|
|
maxIncomingReadId: maxIncomingReadId,
|
|
maxOutgoingReadId: maxOutgoingReadId,
|
|
maxKnownId: localTop.id,
|
|
count: count,
|
|
markedUnread: markedUnread
|
|
)
|
|
readStates[peerId] = updated
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
transaction.resetIncomingReadStates(readStates)
|
|
|
|
for (peerId, autoremoveValue) in fetchedChats.ttlPeriods {
|
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
|
if peerId.namespace == Namespaces.Peer.CloudUser {
|
|
let current = (current as? CachedUserData) ?? CachedUserData()
|
|
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
|
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
|
let current = (current as? CachedChannelData) ?? CachedChannelData()
|
|
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
|
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
|
let current = (current as? CachedGroupData) ?? CachedGroupData()
|
|
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
|
} else {
|
|
return current
|
|
}
|
|
})
|
|
}
|
|
for (peerId, value) in fetchedChats.viewForumAsMessages {
|
|
if value {
|
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
|
let current = (current as? CachedChannelData) ?? CachedChannelData()
|
|
return current.withUpdatedViewForumAsMessages(.known(value))
|
|
} else {
|
|
return current
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
for hole in transaction.allChatListHoles(groupId: .root) {
|
|
transaction.replaceChatListHole(groupId: .root, index: hole.index, hole: nil)
|
|
}
|
|
for hole in transaction.allChatListHoles(groupId: .group(1)) {
|
|
transaction.replaceChatListHole(groupId: .group(1), index: hole.index, hole: nil)
|
|
}
|
|
|
|
if let hole = fetchedChats.lowerNonPinnedIndex.flatMap(ChatListHole.init) {
|
|
transaction.addChatListHole(groupId: .root, hole: hole)
|
|
}
|
|
transaction.addChatListHole(groupId: .group(1), hole: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(0)), namespace: Namespaces.Message.Cloud, id: 1), timestamp: Int32.max - 1)))
|
|
|
|
for peerId in fetchedChats.chatPeerIds {
|
|
if let peer = transaction.getPeer(peerId) {
|
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: .root, pinningIndex: transaction.getPeerChatListIndex(peerId)?.1.pinningIndex, minTimestamp: minTimestampForPeerInclusion(peer)))
|
|
} else {
|
|
assertionFailure()
|
|
}
|
|
}
|
|
|
|
for (peerId, peerGroupId) in fetchedChats.peerGroupIds {
|
|
if let peer = transaction.getPeer(peerId) {
|
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: peerGroupId, pinningIndex: nil, minTimestamp: minTimestampForPeerInclusion(peer)))
|
|
} else {
|
|
assertionFailure()
|
|
}
|
|
}
|
|
|
|
for (peerId, pts) in fetchedChats.channelStates {
|
|
if let current = transaction.getPeerChatState(peerId) as? ChannelState {
|
|
transaction.setPeerChatState(peerId, state: current.withUpdatedPts(pts))
|
|
} else {
|
|
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
|
}
|
|
}
|
|
|
|
if let replacePinnedItemIds = fetchedChats.pinnedItemIds {
|
|
// MARK: - GLEGram - Unlimited pinned chats with local premium
|
|
let serverPinned = replacePinnedItemIds.map(PinnedItemId.peer)
|
|
let unlimitedPinned: Bool
|
|
#if canImport(SGSimpleSettings)
|
|
unlimitedPinned = SGSimpleSettings.shared.enableLocalPremium
|
|
#else
|
|
unlimitedPinned = false
|
|
#endif
|
|
if unlimitedPinned {
|
|
let currentLocal = transaction.getPinnedItemIds(groupId: .root)
|
|
let serverIds = Set(serverPinned)
|
|
let localExtras = currentLocal.filter { !serverIds.contains($0) }
|
|
let merged = serverPinned + localExtras
|
|
transaction.setPinnedItemIds(groupId: .root, itemIds: merged)
|
|
} else {
|
|
transaction.setPinnedItemIds(groupId: .root, itemIds: serverPinned)
|
|
}
|
|
}
|
|
|
|
for (peerId, summary) in fetchedChats.mentionTagSummaries {
|
|
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
|
|
}
|
|
for (peerId, summary) in fetchedChats.reactionTagSummaries {
|
|
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: summary.count, maxId: summary.range.maxId)
|
|
}
|
|
|
|
for (groupId, summary) in fetchedChats.folderSummaries {
|
|
transaction.resetPeerGroupSummary(groupId: groupId, namespace: Namespaces.Message.Cloud, summary: summary)
|
|
}
|
|
|
|
let savedMessageTags = transaction.getMessageTagSummaryCustomTags(peerId: accountPeerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud)
|
|
if !savedMessageTags.isEmpty {
|
|
for tag in savedMessageTags {
|
|
transaction.replaceMessageTagSummary(peerId: accountPeerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag, count: 0, maxId: 1)
|
|
}
|
|
transaction.invalidateMessageHistoryTagsSummary(peerId: accountPeerId, threadId: nil, namespace: Namespaces.Message.Cloud, tagMask: [], customTag: savedMessageTags[0])
|
|
}
|
|
|
|
transaction.reindexUnreadCounters()
|
|
|
|
if let currentState = transaction.getState() as? AuthorizedAccountState {
|
|
switch state {
|
|
case let .state(stateData):
|
|
let (pts, qts, date, seq) = (stateData.pts, stateData.qts, stateData.date, stateData.seq)
|
|
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: qts, date: date, seq: seq)))
|
|
}
|
|
}
|
|
})
|
|
|> ignoreValues
|
|
}
|
|
}
|
|
}
|