From 235a188291a129f96ebd8effb2a41c54849d857f Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Fri, 6 Jan 2023 19:55:12 -0500 Subject: [PATCH] Always download link preview image --- ts/services/LinkPreview.ts | 50 +++++++++++++++++--------------- ts/services/storyLoader.ts | 4 +++ ts/textsecure/MessageReceiver.ts | 3 ++ ts/types/Attachment.ts | 7 ++--- ts/util/sendStoryMessage.ts | 28 +++++++++++++++++- 5 files changed, 63 insertions(+), 29 deletions(-) diff --git a/ts/services/LinkPreview.ts b/ts/services/LinkPreview.ts index caf4daa5f5..d008d5c559 100644 --- a/ts/services/LinkPreview.ts +++ b/ts/services/LinkPreview.ts @@ -254,32 +254,36 @@ export function getLinkPreviewForSend(message: string): Array { // the message. This can happen if you have a link preview, then quickly delete // the link and send the message. .filter(({ url }: Readonly<{ url: string }>) => urlsInMessage.has(url)) - .map((item: LinkPreviewResult) => { - if (item.image) { - // We eliminate the ObjectURL here, unneeded for send or save - return { - ...item, - image: omit(item.image, 'url'), - title: dropNull(item.title), - description: dropNull(item.description), - date: dropNull(item.date), - domain: LinkPreview.getDomain(item.url), - isStickerPack: LinkPreview.isStickerPack(item.url), - }; - } - - return { - ...item, - title: dropNull(item.title), - description: dropNull(item.description), - date: dropNull(item.date), - domain: LinkPreview.getDomain(item.url), - isStickerPack: LinkPreview.isStickerPack(item.url), - }; - }) + .map(sanitizeLinkPreview) ); } +export function sanitizeLinkPreview( + item: LinkPreviewResult | LinkPreviewType +): LinkPreviewType { + if (item.image) { + // We eliminate the ObjectURL here, unneeded for send or save + return { + ...item, + image: omit(item.image, 'url'), + title: dropNull(item.title), + description: dropNull(item.description), + date: dropNull(item.date), + domain: LinkPreview.getDomain(item.url), + isStickerPack: LinkPreview.isStickerPack(item.url), + }; + } + + return { + ...item, + title: dropNull(item.title), + description: dropNull(item.description), + date: dropNull(item.date), + domain: LinkPreview.getDomain(item.url), + isStickerPack: LinkPreview.isStickerPack(item.url), + }; +} + async function getPreview( url: string, abortSignal: Readonly diff --git a/ts/services/storyLoader.ts b/ts/services/storyLoader.ts index 8c0830f3a0..9d3efc143d 100644 --- a/ts/services/storyLoader.ts +++ b/ts/services/storyLoader.ts @@ -47,6 +47,10 @@ export function getStoryDataFromMessageAttributes( ? getAttachmentsForMessage(message) : [unresolvedAttachment]; + // If a story message has a preview property in its attributes then we + // rebuild the textAttachment data structure to contain the all the data it + // needs to fully render the text attachment including the link preview and + // its image. let preview: LinkPreviewType | undefined; if (message.preview?.length) { strictAssert( diff --git a/ts/textsecure/MessageReceiver.ts b/ts/textsecure/MessageReceiver.ts index 5df5232598..0424bef7b7 100644 --- a/ts/textsecure/MessageReceiver.ts +++ b/ts/textsecure/MessageReceiver.ts @@ -2053,6 +2053,9 @@ export default class MessageReceiver } if (msg.textAttachment) { + // If a text attachment has a link preview we remove it from the + // textAttachment data structure and instead process the preview and add + // it as a "preview" property for the message attributes. const { text, preview: unprocessedPreview } = msg.textAttachment; if (unprocessedPreview) { preview = processPreview([unprocessedPreview]); diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts index 1bedaac683..a776762b4e 100644 --- a/ts/types/Attachment.ts +++ b/ts/types/Attachment.ts @@ -13,6 +13,7 @@ import { } from 'lodash'; import { blobToArrayBuffer } from 'blob-util'; +import type { LinkPreviewType } from './message/LinkPreviews'; import type { LoggerType } from './Logging'; import * as MIME from './MIME'; import { toLogFormat } from './errors'; @@ -99,11 +100,7 @@ export type TextAttachmentType = { textStyle?: number | null; textForegroundColor?: number | null; textBackgroundColor?: number | null; - preview?: { - image?: AttachmentType; - title?: string | null; - url?: string | null; - } | null; + preview?: LinkPreviewType; gradient?: { startColor?: number | null; endColor?: number | null; diff --git a/ts/util/sendStoryMessage.ts b/ts/util/sendStoryMessage.ts index a2d7b435bb..a056eaf2da 100644 --- a/ts/util/sendStoryMessage.ts +++ b/ts/util/sendStoryMessage.ts @@ -24,6 +24,21 @@ import { isGroupV2 } from './whatTypeOfConversation'; import { isNotNil } from './isNotNil'; import { collect } from './iterables'; import { DurationInSeconds } from './durations'; +import { sanitizeLinkPreview } from '../services/LinkPreview'; + +function cleanLinkPreviewIfAny(attachment: AttachmentType): AttachmentType { + if (!attachment.textAttachment || !attachment.textAttachment.preview) { + return attachment; + } + + return { + ...attachment, + textAttachment: { + ...attachment.textAttachment, + preview: undefined, + }, + }; +} export async function sendStoryMessage( listIds: Array, @@ -135,7 +150,17 @@ export async function sendStoryMessage( sendStateByListId.set(distributionList.id, sendStateByConversationId); }); - const attachments: Array = [attachment]; + const cleanedAttachment = cleanLinkPreviewIfAny(attachment); + const attachments: Array = [cleanedAttachment]; + + const linkPreview = attachment?.textAttachment?.preview; + const sanitizedLinkPreview = linkPreview + ? sanitizeLinkPreview(linkPreview) + : undefined; + // If a text attachment has a link preview we remove it from the + // textAttachment data structure and instead process the preview and add + // it as a "preview" property for the message attributes. + const preview = sanitizedLinkPreview ? [sanitizedLinkPreview] : undefined; // * Gather all the job data we'll be sending to the sendStory job // * Create the message for each distribution list @@ -161,6 +186,7 @@ export async function sendStoryMessage( expireTimer: DurationInSeconds.DAY, expirationStartTimestamp: Date.now(), id: UUID.generate().toString(), + preview, readStatus: ReadStatus.Read, received_at: incrementMessageCounter(), received_at_ms: timestamp,