// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { Database } from '@signalapp/better-sqlite3'; import type { ReadonlyDeep } from 'type-fest'; import type { ConversationAttributesType, MessageAttributesType, SenderKeyInfoType, } from '../model-types.d'; import type { StoredJob } from '../jobs/types'; import type { ReactionType, ReactionReadStatus } from '../types/Reactions'; import type { ConversationColorType, CustomColorType } from '../types/Colors'; import type { StorageAccessType } from '../types/Storage.d'; import type { BytesToStrings } from '../types/Util'; import type { QualifiedAddressStringType } from '../types/QualifiedAddress'; import type { StoryDistributionIdString } from '../types/StoryDistributionId'; import type { AciString, PniString, ServiceIdString } from '../types/ServiceId'; import type { BadgeType } from '../badges/types'; import type { ReadStatus } from '../messages/MessageReadStatus'; import type { RawBodyRange } from '../types/BodyRange'; import type { GetMessagesBetweenOptions, MaybeStaleCallHistory, } from './Server'; import type { MessageTimestamps } from '../state/ducks/conversations'; import type { CallHistoryDetails, CallHistoryFilter, CallHistoryGroup, CallHistoryPagination, CallLogEventTarget, } from '../types/CallDisposition'; import type { CallLinkRecord, CallLinkStateType, CallLinkType, DefunctCallLinkType, } from '../types/CallLink'; import type { AttachmentDownloadJobType } from '../types/AttachmentDownload'; import type { GroupSendEndorsementsData, GroupSendMemberEndorsementRecord, } from '../types/GroupSendEndorsements'; import type { SyncTaskType } from '../util/syncTasks'; import type { AttachmentBackupJobType } from '../types/AttachmentBackup'; import type { SingleProtoJobQueue } from '../jobs/singleProtoJobQueue'; export type ReadableDB = Database & { __readable_db: never }; export type WritableDB = ReadableDB & { __writable_db: never }; export type AdjacentMessagesByConversationOptionsType = Readonly<{ conversationId: string; messageId?: string; includeStoryReplies: boolean; limit?: number; receivedAt?: number; sentAt?: number; storyId: string | undefined; requireVisualMediaAttachments?: boolean; requireFileAttachments?: boolean; }>; export type GetNearbyMessageFromDeletedSetOptionsType = Readonly<{ conversationId: string; lastSelectedMessage: MessageTimestamps; deletedMessageIds: ReadonlyArray; storyId: string | undefined; includeStoryReplies: boolean; }>; export type MessageMetricsType = { id: string; received_at: number; sent_at: number; }; export type ConversationMetricsType = { oldest?: MessageMetricsType; newest?: MessageMetricsType; oldestUnseen?: MessageMetricsType; totalUnseen: number; }; export type ConversationType = ConversationAttributesType; export type EmojiType = { shortName: string; lastUsage: number; }; export type IdentityKeyType = { firstUse: boolean; id: ServiceIdString | `conversation:${string}`; nonblockingApproval: boolean; publicKey: Uint8Array; timestamp: number; verified: number; }; export type StoredIdentityKeyType = { firstUse: boolean; id: ServiceIdString | `conversation:${string}`; nonblockingApproval: boolean; publicKey: string; timestamp: number; verified: number; }; export type IdentityKeyIdType = IdentityKeyType['id']; export type ItemKeyType = keyof StorageAccessType; export type AllItemsType = Partial; export type StoredAllItemsType = Partial>; export type ItemType = { id: K; value: StorageAccessType[K]; }; export type StoredItemType = { id: K; value: BytesToStrings; }; export type MessageType = MessageAttributesType; export type MessageTypeUnhydrated = { json: string; }; export type PreKeyIdType = `${ServiceIdString}:${number}`; export type KyberPreKeyType = { id: PreKeyIdType; createdAt: number; data: Uint8Array; isConfirmed: boolean; isLastResort: boolean; keyId: number; ourServiceId: ServiceIdString; }; export type StoredKyberPreKeyType = KyberPreKeyType & { data: string; }; export type PreKeyType = { id: PreKeyIdType; createdAt: number; keyId: number; ourServiceId: ServiceIdString; privateKey: Uint8Array; publicKey: Uint8Array; }; export type StoredPreKeyType = PreKeyType & { privateKey: string; publicKey: string; }; export type ServerSearchResultMessageType = { json: string; // If the FTS matches text in message.body, snippet will be populated ftsSnippet: string | null; // Otherwise, a matching mention will be returned mentionAci: string | null; mentionStart: number | null; mentionLength: number | null; }; export type ClientSearchResultMessageType = MessageType & { json: string; bodyRanges: ReadonlyArray; snippet: string; }; export type SentProtoType = { contentHint: number; proto: Uint8Array; timestamp: number; urgent: boolean; hasPniSignatureMessage: boolean; }; export type SentProtoWithMessageIdsType = SentProtoType & { messageIds: Array; }; export type SentRecipientsType = Record>; export type SentMessagesType = Array; // These two are for test only export type SentRecipientsDBType = { payloadId: number; recipientServiceId: ServiceIdString; deviceId: number; }; export type SentMessageDBType = { payloadId: number; messageId: string; }; export type SenderKeyType = { // Primary key id: `${QualifiedAddressStringType}--${string}`; // These two are combined into one string to give us the final id senderId: string; distributionId: string; // Raw data to serialize/deserialize into signal-client SenderKeyRecord data: Uint8Array; lastUpdatedDate: number; }; export type SenderKeyIdType = SenderKeyType['id']; export type SessionType = { id: QualifiedAddressStringType; ourServiceId: ServiceIdString; serviceId: ServiceIdString; conversationId: string; deviceId: number; record: Uint8Array; }; export type SessionIdType = SessionType['id']; export type SignedPreKeyType = { confirmed: boolean; created_at: number; ourServiceId: ServiceIdString; id: `${ServiceIdString}:${number}`; keyId: number; privateKey: Uint8Array; publicKey: Uint8Array; }; export type StoredSignedPreKeyType = { confirmed: boolean; created_at: number; ourServiceId: ServiceIdString; id: `${ServiceIdString}:${number}`; keyId: number; privateKey: string; publicKey: string; }; export type SignedPreKeyIdType = SignedPreKeyType['id']; export type StickerType = Readonly<{ id: number; packId: string; emoji?: string; isCoverOnly: boolean; lastUsed?: number; path: string; width: number; height: number; version: 1 | 2; localKey?: string; size?: number; }>; export const StickerPackStatuses = [ 'known', 'ephemeral', 'downloaded', 'installed', 'pending', 'error', ] as const; export type StickerPackStatusType = (typeof StickerPackStatuses)[number]; export type StorageServiceFieldsType = Readonly<{ storageID?: string; storageVersion?: number; storageUnknownFields?: Uint8Array | null; storageNeedsSync: boolean; }>; export type InstalledStickerPackType = Readonly<{ id: string; key: string; uninstalledAt?: undefined; position?: number | null; }> & StorageServiceFieldsType; export type UninstalledStickerPackType = Readonly<{ id: string; key?: undefined; uninstalledAt: number; position?: undefined; }> & StorageServiceFieldsType; export type StickerPackInfoType = | InstalledStickerPackType | UninstalledStickerPackType; export type StickerPackType = InstalledStickerPackType & Readonly<{ attemptedStatus?: 'downloaded' | 'installed' | 'ephemeral'; author: string; coverStickerId: number; createdAt: number; downloadAttempts: number; installedAt?: number; lastUsed?: number; status: StickerPackStatusType; stickerCount: number; stickers: Record; title: string; }>; export type UnprocessedType = { id: string; timestamp: number; receivedAtCounter: number | null; version: number; attempts: number; envelope?: string; messageAgeSec?: number; source?: string; sourceServiceId?: ServiceIdString; sourceDevice?: number; destinationServiceId?: ServiceIdString; updatedPni?: PniString; serverGuid?: string; serverTimestamp?: number; decrypted?: string; urgent?: boolean; story?: boolean; reportingToken?: string; }; export type UnprocessedUpdateType = { source?: string; sourceServiceId?: ServiceIdString; sourceDevice?: number; serverGuid?: string; serverTimestamp?: number; decrypted?: string; }; export type ConversationMessageStatsType = { activity?: MessageType; preview?: MessageType; hasUserInitiatedMessages: boolean; }; export type DeleteSentProtoRecipientOptionsType = Readonly<{ timestamp: number; recipientServiceId: ServiceIdString; deviceId: number; }>; export type DeleteSentProtoRecipientResultType = Readonly<{ successfulPhoneNumberShares: ReadonlyArray; }>; export type StoryDistributionType = Readonly<{ id: StoryDistributionIdString; name: string; deletedAtTimestamp?: number; allowsReplies: boolean; isBlockList: boolean; senderKeyInfo: SenderKeyInfoType | undefined; }> & StorageServiceFieldsType; export type StoryDistributionMemberType = Readonly<{ listId: StoryDistributionIdString; serviceId: ServiceIdString; }>; export type StoryDistributionWithMembersType = Readonly< { members: Array; } & StoryDistributionType >; export type StoryReadType = Readonly<{ authorId: ServiceIdString; conversationId: string; storyId: string; storyReadDate: number; }>; export type ReactionResultType = Pick< ReactionType, 'targetAuthorAci' | 'targetTimestamp' | 'messageId' > & { rowid: number }; export type GetUnreadByConversationAndMarkReadResultType = Array< { originalReadStatus: ReadStatus | undefined } & Pick< MessageType, | 'id' | 'source' | 'sourceServiceId' | 'sent_at' | 'type' | 'readStatus' | 'seenStatus' | 'expirationStartTimestamp' > >; export type GetConversationRangeCenteredOnMessageResultType = Readonly<{ older: Array; newer: Array; metrics: ConversationMetricsType; }>; export type MessageCursorType = Readonly<{ done: boolean; runId: string; count: number; }>; export type MessageAttachmentsCursorType = MessageCursorType & Readonly<{ __message_attachments_cursor: never; }>; export type GetKnownMessageAttachmentsResultType = Readonly<{ cursor: MessageAttachmentsCursorType; attachments: ReadonlyArray; downloads: ReadonlyArray; }>; export type PageMessagesCursorType = MessageCursorType & Readonly<{ __page_messages_cursor: never; }>; export type PageMessagesResultType = Readonly<{ cursor: PageMessagesCursorType; messages: ReadonlyArray; }>; export type GetAllStoriesResultType = ReadonlyArray< MessageType & { hasReplies: boolean; hasRepliesFromSelf: boolean; } >; export type EditedMessageType = Readonly<{ conversationId: string; messageId: string; sentAt: number; readStatus: MessageType['readStatus']; }>; export type BackupCdnMediaObjectType = { mediaId: string; cdnNumber: number; sizeOnBackupCdn: number; }; export type GetRecentStoryRepliesOptionsType = { limit?: number; messageId?: string; receivedAt?: number; sentAt?: number; }; export enum AttachmentDownloadSource { BACKUP_IMPORT = 'backup_import', STANDARD = 'standard', } type ReadableInterface = { close: () => void; getSenderKeyById: (id: SenderKeyIdType) => SenderKeyType | undefined; getAllSenderKeys: () => Array; getAllSentProtos: () => Array; // Test-only _getAllSentProtoRecipients: () => Array; _getAllSentProtoMessageIds: () => Array; getAllSessions: () => Array; getConversationCount: () => number; getConversationById: (id: string) => ConversationType | undefined; getAllConversations: () => Array; getAllConversationIds: () => Array; getAllGroupsInvolvingServiceId: ( serviceId: ServiceIdString ) => Array; getGroupSendCombinedEndorsementExpiration: (groupId: string) => number | null; getGroupSendEndorsementsData: ( groupId: string ) => GroupSendEndorsementsData | null; getGroupSendMemberEndorsement: ( groupId: string, memberAci: AciString ) => GroupSendMemberEndorsementRecord | null; getMessageCount: (conversationId?: string) => number; getStoryCount: (conversationId: string) => number; pageMessages: (cursor?: PageMessagesCursorType) => PageMessagesResultType; finishPageMessages: (cursor: PageMessagesCursorType) => void; getTotalUnreadForConversation: ( conversationId: string, options: { storyId: string | undefined; includeStoryReplies: boolean; } ) => number; getTotalUnreadMentionsOfMeForConversation: ( conversationId: string, options: { storyId?: string; includeStoryReplies: boolean; } ) => number; getOldestUnreadMentionOfMeForConversation( conversationId: string, options: { storyId?: string; includeStoryReplies: boolean; } ): MessageMetricsType | undefined; getReactionByTimestamp: ( fromId: string, timestamp: number ) => ReactionType | undefined; _getAllReactions: () => Array; getMessageBySender: (options: { source?: string; sourceServiceId?: ServiceIdString; sourceDevice?: number; sent_at: number; }) => MessageType | undefined; getMessageById: (id: string) => MessageType | undefined; getMessagesById: (messageIds: ReadonlyArray) => Array; _getAllMessages: () => Array; _getAllEditedMessages: () => Array<{ messageId: string; sentAt: number }>; getAllMessageIds: () => Array; getMessagesBySentAt: (sentAt: number) => Array; getExpiredMessages: () => Array; getMessagesUnexpectedlyMissingExpirationStartTimestamp: () => Array; getSoonestMessageExpiry: () => undefined | number; getNextTapToViewMessageTimestampToAgeOut: () => undefined | number; getTapToViewMessagesNeedingErase: ( maxTimestamp: number ) => Array; // getOlderMessagesByConversation is JSON on server, full message on Client getAllStories: (options: { conversationId?: string; sourceServiceId?: ServiceIdString; }) => GetAllStoriesResultType; // getNewerMessagesByConversation is JSON on server, full message on Client getMessageMetricsForConversation: (options: { conversationId: string; storyId?: string; includeStoryReplies: boolean; }) => ConversationMetricsType; // getConversationRangeCenteredOnMessage is JSON on server, full message on client getConversationMessageStats: (options: { conversationId: string; includeStoryReplies: boolean; }) => ConversationMessageStatsType; getLastConversationMessage(options: { conversationId: string; }): MessageType | undefined; getAllCallHistory: () => ReadonlyArray; getCallHistoryUnreadCount(): number; getCallHistoryMessageByCallId(options: { conversationId: string; callId: string; }): MessageType | undefined; getCallHistory( callId: string, peerId: ServiceIdString | string ): CallHistoryDetails | undefined; getCallHistoryGroupsCount(filter: CallHistoryFilter): number; getCallHistoryGroups( filter: CallHistoryFilter, pagination: CallHistoryPagination ): Array; hasGroupCallHistoryMessage: ( conversationId: string, eraId: string ) => boolean; callLinkExists(roomId: string): boolean; defunctCallLinkExists(roomId: string): boolean; getAllCallLinks: () => ReadonlyArray; getCallLinkByRoomId: (roomId: string) => CallLinkType | undefined; getCallLinkRecordByRoomId: (roomId: string) => CallLinkRecord | undefined; getAllAdminCallLinks(): ReadonlyArray; getAllCallLinkRecordsWithAdminKey(): ReadonlyArray; getAllDefunctCallLinksWithAdminKey(): ReadonlyArray; getAllMarkedDeletedCallLinkRoomIds(): ReadonlyArray; getMessagesBetween: ( conversationId: string, options: GetMessagesBetweenOptions ) => Array; getNearbyMessageFromDeletedSet: ( options: GetNearbyMessageFromDeletedSetOptionsType ) => string | null; getMostRecentAddressableMessages: ( conversationId: string, limit?: number ) => Array; getMostRecentAddressableNondisappearingMessages: ( conversationId: string, limit?: number ) => Array; getUnprocessedCount: () => number; getUnprocessedById: (id: string) => UnprocessedType | undefined; getAttachmentDownloadJob( job: Pick< AttachmentDownloadJobType, 'messageId' | 'attachmentType' | 'digest' > ): AttachmentDownloadJobType; getBackupCdnObjectMetadata: ( mediaId: string ) => BackupCdnMediaObjectType | undefined; getStickerCount: () => number; getAllStickerPacks: () => Array; getInstalledStickerPacks: () => Array; getUninstalledStickerPacks: () => Array; getStickerPackInfo: (packId: string) => StickerPackInfoType | undefined; getAllStickers: () => Array; getRecentStickers: (options?: { limit?: number }) => Array; getRecentEmojis: (limit?: number) => Array; getAllBadges(): Array; _getAllStoryDistributions(): Array; _getAllStoryDistributionMembers(): Array; getAllStoryDistributionsWithMembers(): Array; getStoryDistributionWithMembers( id: string ): StoryDistributionWithMembersType | undefined; _getAllStoryReads(): Array; getLastStoryReadsForAuthor(options: { authorId: ServiceIdString; conversationId?: string; limit?: number; }): Array; countStoryReadsByConversation(conversationId: string): number; getMessagesNeedingUpgrade: ( limit: number, options: { maxVersion: number } ) => Array; getMessageServerGuidsForSpam: (conversationId: string) => Array; getJobsInQueue(queueType: string): Array; wasGroupCallRingPreviouslyCanceled(ringId: bigint): boolean; getMaxMessageCounter(): number | undefined; getStatisticsForLogging(): Record; getSizeOfPendingBackupAttachmentDownloadJobs(): number; }; type WritableInterface = { close: () => void; removeIndexedDBFiles: () => void; removeIdentityKeyById: (id: IdentityKeyIdType) => number; removeAllIdentityKeys: () => number; removeKyberPreKeyById: (id: PreKeyIdType | Array) => number; removeKyberPreKeysByServiceId: (serviceId: ServiceIdString) => void; removeAllKyberPreKeys: () => number; removePreKeyById: (id: PreKeyIdType | Array) => number; removePreKeysByServiceId: (serviceId: ServiceIdString) => void; removeAllPreKeys: () => number; removeSignedPreKeyById: ( id: SignedPreKeyIdType | Array ) => number; removeSignedPreKeysByServiceId: (serviceId: ServiceIdString) => void; removeAllSignedPreKeys: () => number; removeAllItems: () => number; removeItemById: (id: ItemKeyType | Array) => number; createOrUpdateSenderKey: (key: SenderKeyType) => void; removeAllSenderKeys: () => void; removeSenderKeyById: (id: SenderKeyIdType) => void; getSentProtoByRecipient: (options: { now: number; recipientServiceId: ServiceIdString; timestamp: number; }) => SentProtoWithMessageIdsType | undefined; insertSentProto: ( proto: SentProtoType, options: { recipients: SentRecipientsType; messageIds: SentMessagesType; } ) => number; deleteSentProtosOlderThan: (timestamp: number) => void; deleteSentProtoByMessageId: (messageId: string) => void; insertProtoRecipients: (options: { id: number; recipientServiceId: ServiceIdString; deviceIds: Array; }) => void; deleteSentProtoRecipient: ( options: | DeleteSentProtoRecipientOptionsType | ReadonlyArray ) => DeleteSentProtoRecipientResultType; removeAllSentProtos: () => void; createOrUpdateSession: (data: SessionType) => void; createOrUpdateSessions: (array: Array) => void; commitDecryptResult(options: { senderKeys: Array; sessions: Array; unprocessed: Array; }): void; removeSessionById: (id: SessionIdType) => number; removeSessionsByConversation: (conversationId: string) => void; removeSessionsByServiceId: (serviceId: ServiceIdString) => void; removeAllSessions: () => number; saveConversation: (data: ConversationType) => void; saveConversations: (array: Array) => void; // updateConversation is a normal data method on Server, a sync batch-add on Client updateConversations: (array: Array) => void; // removeConversation handles either one id or an array on Server, and one id on Client _removeAllConversations: () => void; updateAllConversationColors: ( conversationColor?: ConversationColorType, customColorData?: { id: string; value: CustomColorType; } ) => void; removeAllProfileKeyCredentials: () => void; replaceAllEndorsementsForGroup: (data: GroupSendEndorsementsData) => void; deleteAllEndorsementsForGroup: (groupId: string) => void; saveMessage: ( data: ReadonlyDeep, options: { jobToInsert?: StoredJob; forceSave?: boolean; ourAci: AciString; } ) => string; saveMessages: ( arrayOfMessages: ReadonlyArray>, options: { forceSave?: boolean; ourAci: AciString } ) => Array; getUnreadByConversationAndMarkRead: (options: { conversationId: string; includeStoryReplies: boolean; newestUnreadAt: number; now?: number; readAt?: number; storyId?: string; }) => GetUnreadByConversationAndMarkReadResultType; getUnreadEditedMessagesAndMarkRead: (options: { conversationId: string; newestUnreadAt: number; }) => GetUnreadByConversationAndMarkReadResultType; getUnreadReactionsAndMarkRead: (options: { conversationId: string; newestUnreadAt: number; storyId?: string; }) => Array; markReactionAsRead: ( targetAuthorServiceId: ServiceIdString, targetTimestamp: number ) => ReactionType | undefined; removeReactionFromConversation: (reaction: { emoji: string; fromId: string; targetAuthorServiceId: ServiceIdString; targetTimestamp: number; }) => void; addReaction: ( reactionObj: ReactionType, options: { readStatus: ReactionReadStatus; } ) => void; _removeAllReactions: () => void; _removeAllMessages: () => void; incrementMessagesMigrationAttempts: ( messageIds: ReadonlyArray ) => void; clearCallHistory: (target: CallLogEventTarget) => ReadonlyArray; _removeAllCallHistory: () => void; markCallHistoryDeleted: (callId: string) => void; cleanupCallHistoryMessages: () => void; markCallHistoryRead(callId: string): void; markAllCallHistoryRead(target: CallLogEventTarget): number; markAllCallHistoryReadInConversation(target: CallLogEventTarget): number; saveCallHistory(callHistory: CallHistoryDetails): void; markCallHistoryMissed(callIds: ReadonlyArray): void; getRecentStaleRingsAndMarkOlderMissed(): ReadonlyArray; insertCallLink(callLink: CallLinkType): void; updateCallLink(callLink: CallLinkType): void; updateCallLinkAdminKeyByRoomId(roomId: string, adminKey: string): void; updateCallLinkState( roomId: string, callLinkState: CallLinkStateType ): CallLinkType; beginDeleteAllCallLinks(): boolean; beginDeleteCallLink(roomId: string): boolean; deleteCallHistoryByRoomId(roomid: string): void; deleteCallLinkAndHistory(roomId: string): void; finalizeDeleteCallLink(roomId: string): void; _removeAllCallLinks(): void; insertDefunctCallLink(defunctCallLink: DefunctCallLinkType): void; updateDefunctCallLink(defunctCallLink: DefunctCallLinkType): void; deleteCallLinkFromSync(roomId: string): void; migrateConversationMessages: (obsoleteId: string, currentId: string) => void; saveEditedMessage: ( mainMessage: ReadonlyDeep, ourAci: AciString, opts: ReadonlyDeep ) => void; saveEditedMessages: ( mainMessage: ReadonlyDeep, ourAci: AciString, history: ReadonlyArray> ) => void; removeSyncTaskById: (id: string) => void; saveSyncTasks: (tasks: Array) => void; getAllSyncTasks: () => Array; getAllUnprocessedIds: () => Array; getUnprocessedByIdsAndIncrementAttempts: ( ids: ReadonlyArray ) => Array; updateUnprocessedWithData: (id: string, data: UnprocessedUpdateType) => void; updateUnprocessedsWithData: ( array: Array<{ id: string; data: UnprocessedUpdateType }> ) => void; removeUnprocessed: (id: string | Array) => void; /** only for testing */ removeAllUnprocessed: () => void; getNextAttachmentDownloadJobs: (options: { limit: number; prioritizeMessageIds?: Array; sources?: Array; timestamp?: number; }) => Array; saveAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void; resetAttachmentDownloadActive: () => void; removeAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void; removeAllBackupAttachmentDownloadJobs: () => void; getNextAttachmentBackupJobs: (options: { limit: number; timestamp?: number; }) => Array; saveAttachmentBackupJob: (job: AttachmentBackupJobType) => void; markAllAttachmentBackupJobsInactive: () => void; removeAttachmentBackupJob: (job: AttachmentBackupJobType) => void; clearAllAttachmentBackupJobs: () => void; clearAllBackupCdnObjectMetadata: () => void; saveBackupCdnObjectMetadata: ( mediaObjects: Array ) => void; createOrUpdateStickerPack: (pack: StickerPackType) => void; createOrUpdateStickerPacks: (packs: ReadonlyArray) => void; updateStickerPackStatus: ( id: string, status: StickerPackStatusType, options?: { timestamp: number } ) => void; updateStickerPackInfo: (info: StickerPackInfoType) => void; createOrUpdateSticker: (sticker: StickerType) => void; createOrUpdateStickers: (sticker: ReadonlyArray) => void; updateStickerLastUsed: ( packId: string, stickerId: number, lastUsed: number ) => void; addStickerPackReference: (messageId: string, packId: string) => void; deleteStickerPackReference: ( messageId: string, packId: string ) => ReadonlyArray | undefined; deleteStickerPack: (packId: string) => Array; addUninstalledStickerPack: (pack: UninstalledStickerPackType) => void; addUninstalledStickerPacks: ( pack: ReadonlyArray ) => void; removeUninstalledStickerPack: (packId: string) => void; installStickerPack: (packId: string, timestamp: number) => void; uninstallStickerPack: (packId: string, timestamp: number) => void; clearAllErrorStickerPackAttempts: () => void; updateEmojiUsage: (shortName: string, timeUsed?: number) => void; updateOrCreateBadges(badges: ReadonlyArray): void; badgeImageFileDownloaded(url: string, localPath: string): void; _deleteAllStoryDistributions(): void; createNewStoryDistribution( distribution: StoryDistributionWithMembersType ): void; modifyStoryDistribution(distribution: StoryDistributionType): void; modifyStoryDistributionMembers( listId: string, options: { toAdd: Array; toRemove: Array; } ): void; modifyStoryDistributionWithMembers( distribution: StoryDistributionType, options: { toAdd: Array; toRemove: Array; } ): void; deleteStoryDistribution(id: StoryDistributionIdString): void; _deleteAllStoryReads(): void; addNewStoryRead(read: StoryReadType): void; removeAll: () => void; removeAllConfiguration: () => void; eraseStorageServiceState: () => void; insertJob(job: Readonly): void; deleteJob(id: string): void; processGroupCallRingCancellation(ringId: bigint): void; cleanExpiredGroupCallRingCancellations(): void; }; // Adds a database argument type AddReadonlyDB = { [Key in keyof I]: I[Key] extends (...args: infer Args) => infer R ? (db: ReadableDB, ...args: Args) => R : never; }; export type ServerReadableDirectInterface = ReadableInterface & { // Differing signature on client/server searchMessages: ({ query, conversationId, options, contactServiceIdsMatchingQuery, }: { query: string; conversationId?: string; options?: { limit?: number }; contactServiceIdsMatchingQuery?: Array; }) => Array; getRecentStoryReplies( storyId: string, options?: GetRecentStoryRepliesOptionsType ): Array; getOlderMessagesByConversation: ( options: AdjacentMessagesByConversationOptionsType ) => Array; getNewerMessagesByConversation: ( options: AdjacentMessagesByConversationOptionsType ) => Array; getConversationRangeCenteredOnMessage: ( options: AdjacentMessagesByConversationOptionsType ) => GetConversationRangeCenteredOnMessageResultType; getIdentityKeyById: ( id: IdentityKeyIdType ) => StoredIdentityKeyType | undefined; getAllIdentityKeys: () => Array; getKyberPreKeyById: (id: PreKeyIdType) => StoredKyberPreKeyType | undefined; getAllKyberPreKeys: () => Array; getPreKeyById: (id: PreKeyIdType) => StoredPreKeyType | undefined; getAllPreKeys: () => Array; getSignedPreKeyById: ( id: SignedPreKeyIdType ) => StoredSignedPreKeyType | undefined; getAllSignedPreKeys: () => Array; getItemById(id: K): StoredItemType | undefined; getAllItems: () => StoredAllItemsType; // Server-only getKnownMessageAttachments: ( cursor?: MessageAttachmentsCursorType ) => GetKnownMessageAttachmentsResultType; finishGetKnownMessageAttachments: ( cursor: MessageAttachmentsCursorType ) => void; getKnownDownloads: () => Array; getKnownConversationAttachments: () => Array; getAllBadgeImageFileLocalPaths: () => Set; }; export type ServerReadableInterface = AddReadonlyDB; // Adds a database argument type AddWritableDB = { [Key in keyof I]: I[Key] extends (...args: infer Args) => infer R ? (db: WritableDB, ...args: Args) => R : never; }; export type ServerWritableDirectInterface = WritableInterface & { // Differing signature on client/server updateConversation: (data: ConversationType) => void; removeConversation: (id: Array | string) => void; removeMessage: (id: string) => void; removeMessages: (ids: ReadonlyArray) => void; createOrUpdateIdentityKey: (data: StoredIdentityKeyType) => void; bulkAddIdentityKeys: (array: Array) => void; createOrUpdateKyberPreKey: (data: StoredKyberPreKeyType) => void; bulkAddKyberPreKeys: (array: Array) => void; createOrUpdatePreKey: (data: StoredPreKeyType) => void; bulkAddPreKeys: (array: Array) => void; createOrUpdateSignedPreKey: (data: StoredSignedPreKeyType) => void; bulkAddSignedPreKeys: (array: Array) => void; createOrUpdateItem(data: StoredItemType): void; // Server-only removeKnownStickers: (allStickers: ReadonlyArray) => Array; removeKnownDraftAttachments: ( allStickers: ReadonlyArray ) => Array; runCorruptionChecks: () => void; }; export type ServerWritableInterface = AddWritableDB; // Makes sync calls - async export type ClientInterfaceWrap = { [Key in keyof I]: I[Key] extends (...args: infer Args) => infer R ? (...args: Args) => Promise : never; }; export type ClientOnlyReadableInterface = ClientInterfaceWrap<{ // Differing signature on client/server searchMessages: ({ query, conversationId, options, contactServiceIdsMatchingQuery, }: { query: string; conversationId?: string; options?: { limit?: number }; contactServiceIdsMatchingQuery?: Array; }) => Array; getRecentStoryReplies( storyId: string, options?: GetRecentStoryRepliesOptionsType ): Array; getOlderMessagesByConversation: ( options: AdjacentMessagesByConversationOptionsType ) => Array; getNewerMessagesByConversation: ( options: AdjacentMessagesByConversationOptionsType ) => Array; getConversationRangeCenteredOnMessage: ( options: AdjacentMessagesByConversationOptionsType ) => GetConversationRangeCenteredOnMessageResultType; getIdentityKeyById: (id: IdentityKeyIdType) => IdentityKeyType | undefined; getAllIdentityKeys: () => Array; getKyberPreKeyById: (id: PreKeyIdType) => KyberPreKeyType | undefined; getAllKyberPreKeys: () => Array; getPreKeyById: (id: PreKeyIdType) => PreKeyType | undefined; getAllPreKeys: () => Array; getSignedPreKeyById: (id: SignedPreKeyIdType) => SignedPreKeyType | undefined; getAllSignedPreKeys: () => Array; getItemById(id: K): ItemType | undefined; getAllItems: () => AllItemsType; }>; export type ClientOnlyWritableInterface = ClientInterfaceWrap<{ // Differing signature on client/server updateConversation: (data: ConversationType) => void; removeConversation: (id: string) => void; flushUpdateConversationBatcher: () => void; removeMessage: ( id: string, options: { fromSync?: boolean; singleProtoJobQueue: SingleProtoJobQueue; } ) => void; removeMessages: ( ids: ReadonlyArray, options: { fromSync?: boolean; singleProtoJobQueue: SingleProtoJobQueue; } ) => void; createOrUpdateIdentityKey: (data: IdentityKeyType) => void; bulkAddIdentityKeys: (array: Array) => void; createOrUpdateKyberPreKey: (data: KyberPreKeyType) => void; bulkAddKyberPreKeys: (array: Array) => void; createOrUpdatePreKey: (data: PreKeyType) => void; bulkAddPreKeys: (array: Array) => void; createOrUpdateSignedPreKey: (data: SignedPreKeyType) => void; bulkAddSignedPreKeys: (array: Array) => void; createOrUpdateItem(data: ItemType): void; // Client-side only shutdown: () => void; removeDB: () => void; removeMessagesInConversation: ( conversationId: string, options: { fromSync?: boolean; logId: string; receivedAt?: number; singleProtoJobQueue: SingleProtoJobQueue; } ) => void; removeOtherData: () => void; cleanupOrphanedAttachments: () => void; ensureFilePermissions: () => void; }>; export type ClientReadableInterface = ClientInterfaceWrap & ClientOnlyReadableInterface; export type ClientWritableInterface = ClientInterfaceWrap & ClientOnlyWritableInterface;