Skip to content

Commit 5c44843

Browse files
Avoid orphaning quoted attachment thumbnails
Co-authored-by: trevor-signal <[email protected]>
1 parent 27f405d commit 5c44843

File tree

4 files changed

+590
-22
lines changed

4 files changed

+590
-22
lines changed

ts/jobs/AttachmentDownloadManager.preload.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
isIncrementalMacVerificationError,
2020
} from '../util/downloadAttachment.preload.js';
2121
import {
22+
deleteAttachmentData as doDeleteAttachmentData,
2223
deleteDownloadData as doDeleteDownloadData,
2324
processNewAttachment as doProcessNewAttachment,
2425
} from '../util/migrations.preload.js';
@@ -39,6 +40,7 @@ import {
3940
getUndownloadedAttachmentSignature,
4041
isIncremental,
4142
hasRequiredInformationForRemoteBackup,
43+
deleteAllAttachmentFilesOnDisk,
4244
} from '../util/Attachment.std.js';
4345
import type { ReadonlyMessageAttributesType } from '../model-types.d.ts';
4446
import { backupsService } from '../services/backups/index.preload.js';
@@ -48,7 +50,10 @@ import {
4850
getMaximumIncomingAttachmentSizeInKb,
4951
getMaximumIncomingTextAttachmentSizeInKb,
5052
} from '../types/AttachmentSize.std.js';
51-
import { addAttachmentToMessage } from '../messageModifiers/AttachmentDownloads.preload.js';
53+
import {
54+
addAttachmentToMessage,
55+
AttachmentNotNeededForMessageError,
56+
} from '../messageModifiers/AttachmentDownloads.preload.js';
5257
import * as Errors from '../types/errors.std.js';
5358
import { redactGenericText } from '../util/privacy.node.js';
5459
import {
@@ -491,6 +496,7 @@ export class AttachmentDownloadManager extends JobManager<CoreAttachmentDownload
491496
}
492497

493498
type DependenciesType = {
499+
deleteAttachmentData: typeof doDeleteAttachmentData;
494500
deleteDownloadData: typeof doDeleteDownloadData;
495501
downloadAttachment: typeof downloadAttachmentUtil;
496502
processNewAttachment: typeof doProcessNewAttachment;
@@ -503,6 +509,7 @@ export async function runDownloadAttachmentJob({
503509
isLastAttempt,
504510
options,
505511
dependencies = {
512+
deleteAttachmentData: doDeleteAttachmentData,
506513
deleteDownloadData: doDeleteDownloadData,
507514
downloadAttachment: downloadAttachmentUtil,
508515
processNewAttachment: doProcessNewAttachment,
@@ -567,6 +574,23 @@ export async function runDownloadAttachmentJob({
567574
return { status: 'finished' };
568575
}
569576

577+
if (error instanceof AttachmentNotNeededForMessageError) {
578+
if (job.attachmentType === 'quote') {
579+
log.info(
580+
`${logId}: quote attachment not needed, likely the thumbnail was already copied from original message`
581+
);
582+
} else {
583+
log.error(`${logId}: attachment not found on message`);
584+
}
585+
586+
await deleteAllAttachmentFilesOnDisk({
587+
deleteDownloadOnDisk: dependencies.deleteDownloadData,
588+
deleteAttachmentOnDisk: dependencies.deleteAttachmentData,
589+
})(error.attachment);
590+
591+
return { status: 'finished' };
592+
}
593+
570594
if (error instanceof AttachmentSizeError) {
571595
log.info(`${logId}: Attachment is too big.`);
572596
await addAttachmentToMessage(
@@ -884,6 +908,11 @@ export async function runDownloadAttachmentJobInner({
884908
if (isAbortError(error)) {
885909
throw error;
886910
}
911+
912+
if (error instanceof AttachmentNotNeededForMessageError) {
913+
throw error;
914+
}
915+
887916
if (mightHaveBackupThumbnailToDownload && !attemptBackupThumbnailFirst) {
888917
log.error(
889918
`${logId}: failed to download fullsize attachment, falling back to backup thumbnail`,

ts/messageModifiers/AttachmentDownloads.preload.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ export async function markAttachmentAsCorrupted(
6969
});
7070
}
7171

72+
export class AttachmentNotNeededForMessageError extends Error {
73+
constructor(public readonly attachment: AttachmentType) {
74+
super('AttachmentNotNeededForMessageError');
75+
}
76+
}
77+
7278
export async function addAttachmentToMessage(
7379
messageId: string,
7480
attachment: AttachmentType,
@@ -167,14 +173,15 @@ export async function addAttachmentToMessage(
167173
await deleteAttachmentData(attachment.path);
168174
}
169175
if (!handledAnywhere) {
170-
log.warn(
171-
`${logPrefix}: Long message attachment found no matching place to apply`
172-
);
176+
// eslint-disable-next-line no-unsafe-finally
177+
throw new AttachmentNotNeededForMessageError(attachment);
173178
}
174179
}
175180
return;
176181
}
177182

183+
let foundPlaceForAttachment = false;
184+
178185
const maybeReplaceAttachment = (existing: AttachmentType): AttachmentType => {
179186
if (isDownloaded(existing)) {
180187
return existing;
@@ -184,13 +191,13 @@ export async function addAttachmentToMessage(
184191
return existing;
185192
}
186193

194+
foundPlaceForAttachment = true;
187195
return attachment;
188196
};
189197

190198
if (type === 'attachment') {
191199
const attachments = message.get('attachments');
192200

193-
let handledAnywhere = false;
194201
let handledInEditHistory = false;
195202

196203
const editHistory = message.get('editHistory');
@@ -207,7 +214,6 @@ export async function addAttachmentToMessage(
207214
attachments: edit.attachments.map(item => {
208215
const newItem = maybeReplaceAttachment(item);
209216
handledInEditHistory ||= item !== newItem;
210-
handledAnywhere ||= handledInEditHistory;
211217
return newItem;
212218
}),
213219
};
@@ -220,18 +226,12 @@ export async function addAttachmentToMessage(
220226

221227
if (attachments) {
222228
message.set({
223-
attachments: attachments.map(item => {
224-
const newItem = maybeReplaceAttachment(item);
225-
handledAnywhere ||= item !== newItem;
226-
return newItem;
227-
}),
229+
attachments: attachments.map(maybeReplaceAttachment),
228230
});
229231
}
230232

231-
if (!handledAnywhere) {
232-
log.warn(
233-
`${logPrefix}: 'attachment' type found no matching place to apply`
234-
);
233+
if (!foundPlaceForAttachment) {
234+
throw new AttachmentNotNeededForMessageError(attachment);
235235
}
236236

237237
return;
@@ -243,7 +243,7 @@ export async function addAttachmentToMessage(
243243
let handledInEditHistory = false;
244244

245245
const editHistory = message.get('editHistory');
246-
if (preview && editHistory) {
246+
if (editHistory) {
247247
const newEditHistory = editHistory.map(edit => {
248248
if (!edit.preview) {
249249
return edit;
@@ -282,6 +282,10 @@ export async function addAttachmentToMessage(
282282
});
283283
}
284284

285+
if (!foundPlaceForAttachment) {
286+
throw new AttachmentNotNeededForMessageError(attachment);
287+
}
288+
285289
return;
286290
}
287291

@@ -290,7 +294,6 @@ export async function addAttachmentToMessage(
290294
if (!contacts?.length) {
291295
throw new Error(`${logPrefix}: no contacts, cannot add attachment!`);
292296
}
293-
let handled = false;
294297

295298
const newContacts = contacts.map(contact => {
296299
if (!contact.avatar?.avatar) {
@@ -301,7 +304,6 @@ export async function addAttachmentToMessage(
301304

302305
const newAttachment = maybeReplaceAttachment(existingAttachment);
303306
if (existingAttachment !== newAttachment) {
304-
handled = true;
305307
return {
306308
...contact,
307309
avatar: { ...contact.avatar, avatar: newAttachment },
@@ -310,10 +312,8 @@ export async function addAttachmentToMessage(
310312
return contact;
311313
});
312314

313-
if (!handled) {
314-
throw new Error(
315-
`${logPrefix}: Couldn't find matching contact with avatar attachment for message`
316-
);
315+
if (!foundPlaceForAttachment) {
316+
throw new AttachmentNotNeededForMessageError(attachment);
317317
}
318318

319319
message.set({ contact: newContacts });
@@ -374,6 +374,10 @@ export async function addAttachmentToMessage(
374374
message.set({ quote: newQuote });
375375
}
376376

377+
if (!foundPlaceForAttachment) {
378+
throw new AttachmentNotNeededForMessageError(attachment);
379+
}
380+
377381
return;
378382
}
379383

@@ -389,6 +393,11 @@ export async function addAttachmentToMessage(
389393
data: sticker.data ? maybeReplaceAttachment(sticker.data) : attachment,
390394
},
391395
});
396+
397+
if (!foundPlaceForAttachment) {
398+
throw new AttachmentNotNeededForMessageError(attachment);
399+
}
400+
392401
return;
393402
}
394403

0 commit comments

Comments
 (0)