mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-11-03 22:27:13 +01:00
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
3.0 KiB
Swift
62 lines
3.0 KiB
Swift
import Foundation
|
|
import Postbox
|
|
|
|
/// Which message a delivered notification stands for, keyed by the `UNNotificationRequest`
|
|
/// identifier the system assigned to it.
|
|
///
|
|
/// The notification service extension records this for every message notification it
|
|
/// handles. Siri's announce flow (AirPods, CarPlay) later asks the intents extension for the
|
|
/// messages behind a notification through `INSearchForMessagesIntent.notificationIdentifiers`,
|
|
/// and this is the only link between that identifier and a `MessageId`: the identifier is
|
|
/// generated by the system per delivery and never appears in the push payload.
|
|
///
|
|
/// The links live in one item-cache row as a bounded, newest-last list. Request identifiers
|
|
/// are per-delivery UUIDs that never repeat, so a row per link would grow for the life of the
|
|
/// account (the item cache has no eviction), while Siri only ever asks about a notification
|
|
/// that is still recent.
|
|
private struct NotificationRequestMessageIdLink: Codable {
|
|
var requestIdentifier: String
|
|
var peerId: Int64
|
|
var namespace: Int32
|
|
var id: Int32
|
|
}
|
|
|
|
private struct NotificationRequestMessageIdLinks: Codable {
|
|
var links: [NotificationRequestMessageIdLink]
|
|
}
|
|
|
|
/// How many recent notification → message links are kept per account.
|
|
public let _internal_notificationRequestMessageIdsLimit: Int = 256
|
|
|
|
private let notificationRequestMessageIdsEntryId = ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.notificationRequestMessageIds, key: ValueBoxKey("links"))
|
|
|
|
private func loadLinks(transaction: Transaction) -> [NotificationRequestMessageIdLink] {
|
|
return transaction.retrieveItemCacheEntry(id: notificationRequestMessageIdsEntryId)?.get(NotificationRequestMessageIdLinks.self)?.links ?? []
|
|
}
|
|
|
|
public func _internal_setNotificationRequestMessageId(transaction: Transaction, requestIdentifier: String, messageId: MessageId) {
|
|
if requestIdentifier.isEmpty {
|
|
return
|
|
}
|
|
var links = loadLinks(transaction: transaction)
|
|
links.removeAll(where: { $0.requestIdentifier == requestIdentifier })
|
|
links.append(NotificationRequestMessageIdLink(requestIdentifier: requestIdentifier, peerId: messageId.peerId.toInt64(), namespace: messageId.namespace, id: messageId.id))
|
|
if links.count > _internal_notificationRequestMessageIdsLimit {
|
|
links.removeFirst(links.count - _internal_notificationRequestMessageIdsLimit)
|
|
}
|
|
guard let entry = CodableEntry(NotificationRequestMessageIdLinks(links: links)) else {
|
|
return
|
|
}
|
|
transaction.putItemCacheEntry(id: notificationRequestMessageIdsEntryId, entry: entry)
|
|
}
|
|
|
|
public func _internal_getNotificationRequestMessageId(transaction: Transaction, requestIdentifier: String) -> MessageId? {
|
|
if requestIdentifier.isEmpty {
|
|
return nil
|
|
}
|
|
guard let link = loadLinks(transaction: transaction).last(where: { $0.requestIdentifier == requestIdentifier }) else {
|
|
return nil
|
|
}
|
|
return MessageId(peerId: PeerId(link.peerId), namespace: link.namespace, id: link.id)
|
|
}
|