Enable backfilling of attachments without message_attachment rows

This commit is contained in:
trevor-signal 2025-08-26 23:20:14 -04:00 committed by GitHub
commit 37ec000831
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 109 additions and 8 deletions

View file

@ -23,13 +23,20 @@ import {
sql,
sqlJoin,
} from './util';
import type { AttachmentType } from '../types/Attachment';
import { IMAGE_JPEG, stringToMIMEType } from '../types/MIME';
import { type AttachmentType } from '../types/Attachment';
import {
APPLICATION_OCTET_STREAM,
IMAGE_JPEG,
IMAGE_PNG,
stringToMIMEType,
} from '../types/MIME';
import { strictAssert } from '../util/assert';
import type { MessageAttributesType } from '../model-types';
import { createLogger } from '../logging/log';
export const ROOT_MESSAGE_ATTACHMENT_EDIT_HISTORY_INDEX = -1;
const log = createLogger('hydrateMessage');
function toBoolean(value: number | null): boolean | undefined {
if (value == null) {
return undefined;
@ -48,9 +55,12 @@ export function hydrateMessages(
db: ReadableDB,
unhydratedMessages: Array<MessageTypeUnhydrated>
): Array<MessageType> {
const messagesWithColumnsHydrated = unhydratedMessages.map(
hydrateMessageTableColumns
);
const messagesWithColumnsHydrated = unhydratedMessages.map(msg => ({
...hydrateMessageTableColumns(msg),
hasAttachments: msg.hasAttachments === 1,
hasFileAttachments: msg.hasFileAttachments === 1,
hasVisualMediaAttachments: msg.hasVisualMediaAttachments === 1,
}));
return hydrateMessagesWithAttachments(db, messagesWithColumnsHydrated);
}
@ -142,7 +152,13 @@ export function getAttachmentReferencesForMessages(
function hydrateMessagesWithAttachments(
db: ReadableDB,
messagesWithoutAttachments: Array<MessageType>
messagesWithoutAttachments: Array<
MessageType & {
hasAttachments: boolean;
hasVisualMediaAttachments: boolean;
hasFileAttachments: boolean;
}
>
): Array<MessageType> {
const attachmentReferencesForAllMessages = getAttachmentReferencesForMessages(
db,
@ -153,10 +169,56 @@ function hydrateMessagesWithAttachments(
'messageId'
);
return messagesWithoutAttachments.map(msg => {
return messagesWithoutAttachments.map(msgWithExtraFields => {
const {
hasAttachments,
hasFileAttachments,
hasVisualMediaAttachments,
...msg
} = msgWithExtraFields;
const attachmentReferences = attachmentReferencesByMessage[msg.id] ?? [];
if (!attachmentReferences.length) {
return msg;
if (msg.attachments?.length) {
// legacy message, attachments still on JSON
return msg;
}
if (msg.isErased || msg.deletedForEveryone || msg.isViewOnce) {
return msg;
}
if (msg.type !== 'incoming' && msg.type !== 'outgoing') {
return msg;
}
if (
!hasAttachments &&
!hasFileAttachments &&
!hasVisualMediaAttachments
) {
return msg;
}
log.warn(
`Retrieved message that should have attachments but missing message_attachment rows, timestamp: ${msg.timestamp}`
);
// Add an empty attachment to the message to enable backfilling in the UI
return {
...msg,
attachments: [
{
error: true,
size: 0,
width: hasVisualMediaAttachments ? 150 : undefined,
height: hasVisualMediaAttachments ? 150 : undefined,
contentType: hasVisualMediaAttachments
? IMAGE_PNG
: APPLICATION_OCTET_STREAM,
},
],
};
}
const attachmentsByEditHistoryIndex = groupBy(