Normalize message attachments
This commit is contained in:
parent
8d8e0329cf
commit
d6e81eee11
39 changed files with 2540 additions and 807 deletions
|
@ -37,7 +37,10 @@ import type {
|
|||
CallLinkType,
|
||||
DefunctCallLinkType,
|
||||
} from '../types/CallLink';
|
||||
import type { AttachmentDownloadJobType } from '../types/AttachmentDownload';
|
||||
import type {
|
||||
AttachmentDownloadJobType,
|
||||
AttachmentDownloadJobTypeType,
|
||||
} from '../types/AttachmentDownload';
|
||||
import type {
|
||||
GroupSendEndorsementsData,
|
||||
GroupSendMemberEndorsementRecord,
|
||||
|
@ -46,6 +49,7 @@ import type { SyncTaskType } from '../util/syncTasks';
|
|||
import type { AttachmentBackupJobType } from '../types/AttachmentBackup';
|
||||
import type { GifType } from '../components/fun/panels/FunPanelGifs';
|
||||
import type { NotificationProfileType } from '../types/NotificationProfile';
|
||||
import { strictAssert } from '../util/assert';
|
||||
|
||||
export type ReadableDB = Database & { __readable_db: never };
|
||||
export type WritableDB = ReadableDB & { __writable_db: never };
|
||||
|
@ -217,7 +221,10 @@ export type StoredPreKeyType = PreKeyType & {
|
|||
privateKey: string;
|
||||
publicKey: string;
|
||||
};
|
||||
export type ServerSearchResultMessageType = MessageTypeUnhydrated & {
|
||||
export type ServerSearchResultMessageType = MessageType &
|
||||
ServerMessageSearchResultType;
|
||||
|
||||
export type ServerMessageSearchResultType = {
|
||||
// If the FTS matches text in message.body, snippet will be populated
|
||||
ftsSnippet: string | null;
|
||||
|
||||
|
@ -537,6 +544,136 @@ export enum AttachmentDownloadSource {
|
|||
BACKFILL = 'backfill',
|
||||
}
|
||||
|
||||
export const MESSAGE_ATTACHMENT_COLUMNS = [
|
||||
'messageId',
|
||||
'conversationId',
|
||||
'sentAt',
|
||||
'attachmentType',
|
||||
'orderInMessage',
|
||||
'editHistoryIndex',
|
||||
'clientUuid',
|
||||
'size',
|
||||
'contentType',
|
||||
'path',
|
||||
'localKey',
|
||||
'plaintextHash',
|
||||
'caption',
|
||||
'fileName',
|
||||
'blurHash',
|
||||
'height',
|
||||
'width',
|
||||
'digest',
|
||||
'key',
|
||||
'iv',
|
||||
'flags',
|
||||
'downloadPath',
|
||||
'transitCdnKey',
|
||||
'transitCdnNumber',
|
||||
'transitCdnUploadTimestamp',
|
||||
'backupMediaName',
|
||||
'backupCdnNumber',
|
||||
'incrementalMac',
|
||||
'incrementalMacChunkSize',
|
||||
'isReencryptableToSameDigest',
|
||||
'reencryptionIv',
|
||||
'reencryptionKey',
|
||||
'reencryptionDigest',
|
||||
'thumbnailPath',
|
||||
'thumbnailSize',
|
||||
'thumbnailContentType',
|
||||
'thumbnailLocalKey',
|
||||
'thumbnailVersion',
|
||||
'screenshotPath',
|
||||
'screenshotSize',
|
||||
'screenshotContentType',
|
||||
'screenshotLocalKey',
|
||||
'screenshotVersion',
|
||||
'backupThumbnailPath',
|
||||
'backupThumbnailSize',
|
||||
'backupThumbnailContentType',
|
||||
'backupThumbnailLocalKey',
|
||||
'backupThumbnailVersion',
|
||||
'storyTextAttachmentJson',
|
||||
'localBackupPath',
|
||||
'isCorrupted',
|
||||
'backfillError',
|
||||
'error',
|
||||
'wasTooBig',
|
||||
'copiedFromQuotedAttachment',
|
||||
'version',
|
||||
'pending',
|
||||
] as const satisfies Array<keyof MessageAttachmentDBType>;
|
||||
|
||||
export type MessageAttachmentDBType = {
|
||||
messageId: string;
|
||||
attachmentType: AttachmentDownloadJobTypeType;
|
||||
orderInMessage: number;
|
||||
editHistoryIndex: number | null;
|
||||
conversationId: string;
|
||||
sentAt: number;
|
||||
clientUuid: string | null;
|
||||
size: number;
|
||||
contentType: string;
|
||||
path: string | null;
|
||||
plaintextHash: string | null;
|
||||
downloadPath: string | null;
|
||||
caption: string | null;
|
||||
blurHash: string | null;
|
||||
width: number | null;
|
||||
height: number | null;
|
||||
flags: number | null;
|
||||
key: string | null;
|
||||
iv: string | null;
|
||||
digest: string | null;
|
||||
fileName: string | null;
|
||||
incrementalMac: string | null;
|
||||
incrementalMacChunkSize: number | null;
|
||||
localKey: string | null;
|
||||
version: 1 | 2 | null;
|
||||
transitCdnKey: string | null;
|
||||
transitCdnNumber: number | null;
|
||||
transitCdnUploadTimestamp: number | null;
|
||||
backupMediaName: string | null;
|
||||
backupCdnNumber: number | null;
|
||||
thumbnailPath: string | null;
|
||||
thumbnailSize: number | null;
|
||||
thumbnailContentType: string | null;
|
||||
thumbnailLocalKey: string | null;
|
||||
thumbnailVersion: 1 | 2 | null;
|
||||
screenshotPath: string | null;
|
||||
screenshotSize: number | null;
|
||||
screenshotContentType: string | null;
|
||||
screenshotLocalKey: string | null;
|
||||
screenshotVersion: 1 | 2 | null;
|
||||
backupThumbnailPath: string | null;
|
||||
backupThumbnailSize: number | null;
|
||||
backupThumbnailContentType: string | null;
|
||||
backupThumbnailLocalKey: string | null;
|
||||
backupThumbnailVersion: 1 | 2 | null;
|
||||
reencryptionIv: string | null;
|
||||
reencryptionKey: string | null;
|
||||
reencryptionDigest: string | null;
|
||||
storyTextAttachmentJson: string | null;
|
||||
localBackupPath: string | null;
|
||||
isCorrupted: 1 | 0 | null;
|
||||
backfillError: 1 | 0 | null;
|
||||
error: 1 | 0 | null;
|
||||
wasTooBig: 1 | 0 | null;
|
||||
pending: 1 | 0 | null;
|
||||
isReencryptableToSameDigest: 1 | 0 | null;
|
||||
copiedFromQuotedAttachment: 1 | 0 | null;
|
||||
};
|
||||
|
||||
// Test to make sure that MESSAGE_ATTACHMENT_COLUMNS &
|
||||
// MessageAttachmentDBReferenceType remain in sync!
|
||||
const testDBRefTypeMatchesColumnNames = true as unknown as [
|
||||
keyof MessageAttachmentDBType,
|
||||
] satisfies [(typeof MESSAGE_ATTACHMENT_COLUMNS)[number]];
|
||||
strictAssert(
|
||||
testDBRefTypeMatchesColumnNames,
|
||||
'attachment_columns must match DB fields type'
|
||||
);
|
||||
|
||||
type ReadableInterface = {
|
||||
close: () => void;
|
||||
|
||||
|
@ -744,6 +881,9 @@ type ReadableInterface = {
|
|||
|
||||
getStatisticsForLogging(): Record<string, string>;
|
||||
getSizeOfPendingBackupAttachmentDownloadJobs(): number;
|
||||
getAttachmentReferencesForMessages: (
|
||||
messageIds: Array<string>
|
||||
) => Array<MessageAttachmentDBType>;
|
||||
};
|
||||
|
||||
type WritableInterface = {
|
||||
|
@ -866,6 +1006,7 @@ type WritableInterface = {
|
|||
) => void;
|
||||
_removeAllReactions: () => void;
|
||||
_removeAllMessages: () => void;
|
||||
_removeMessage: (id: string) => void;
|
||||
incrementMessagesMigrationAttempts: (
|
||||
messageIds: ReadonlyArray<string>
|
||||
) => void;
|
||||
|
@ -1072,16 +1213,16 @@ export type ServerReadableDirectInterface = ReadableInterface & {
|
|||
getRecentStoryReplies(
|
||||
storyId: string,
|
||||
options?: GetRecentStoryRepliesOptionsType
|
||||
): Array<MessageTypeUnhydrated>;
|
||||
): Array<MessageType>;
|
||||
getOlderMessagesByConversation: (
|
||||
options: AdjacentMessagesByConversationOptionsType
|
||||
) => Array<MessageTypeUnhydrated>;
|
||||
) => Array<MessageType>;
|
||||
getNewerMessagesByConversation: (
|
||||
options: AdjacentMessagesByConversationOptionsType
|
||||
) => Array<MessageTypeUnhydrated>;
|
||||
) => Array<MessageType>;
|
||||
getConversationRangeCenteredOnMessage: (
|
||||
options: AdjacentMessagesByConversationOptionsType
|
||||
) => GetConversationRangeCenteredOnMessageResultType<MessageTypeUnhydrated>;
|
||||
) => GetConversationRangeCenteredOnMessageResultType<MessageType>;
|
||||
|
||||
getIdentityKeyById: (
|
||||
id: IdentityKeyIdType
|
||||
|
@ -1141,7 +1282,11 @@ export type ServerWritableDirectInterface = WritableInterface & {
|
|||
) => string;
|
||||
saveMessages: (
|
||||
arrayOfMessages: ReadonlyArray<ReadonlyDeep<MessageType>>,
|
||||
options: { forceSave?: boolean; ourAci: AciString }
|
||||
options: {
|
||||
forceSave?: boolean;
|
||||
ourAci: AciString;
|
||||
_testOnlyAvoidNormalizingAttachments?: boolean;
|
||||
}
|
||||
) => Array<string>;
|
||||
saveMessagesIndividually: (
|
||||
arrayOfMessages: ReadonlyArray<ReadonlyDeep<MessageType>>,
|
||||
|
@ -1241,6 +1386,7 @@ export type ClientOnlyWritableInterface = ClientInterfaceWrap<{
|
|||
forceSave?: boolean;
|
||||
ourAci: AciString;
|
||||
postSaveUpdates: () => Promise<void>;
|
||||
_testOnlyAvoidNormalizingAttachments?: boolean;
|
||||
}
|
||||
) => string;
|
||||
saveMessages: (
|
||||
|
@ -1249,6 +1395,7 @@ export type ClientOnlyWritableInterface = ClientInterfaceWrap<{
|
|||
forceSave?: boolean;
|
||||
ourAci: AciString;
|
||||
postSaveUpdates: () => Promise<void>;
|
||||
_testOnlyAvoidNormalizingAttachments?: boolean;
|
||||
}
|
||||
) => Array<string>;
|
||||
saveMessagesIndividually: (
|
||||
|
@ -1311,7 +1458,7 @@ export type ClientOnlyWritableInterface = ClientInterfaceWrap<{
|
|||
}
|
||||
) => void;
|
||||
removeOtherData: () => void;
|
||||
cleanupOrphanedAttachments: () => void;
|
||||
cleanupOrphanedAttachments: (options?: { _block: boolean }) => void;
|
||||
ensureFilePermissions: () => void;
|
||||
}>;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue