diff --git a/ts/models/messages.ts b/ts/models/messages.ts index 41704b56449..fa850b35cc9 100644 --- a/ts/models/messages.ts +++ b/ts/models/messages.ts @@ -3564,7 +3564,12 @@ export class MessageModel extends window.Backbone.Model { del: DeleteModel, shouldPersist = true ): Promise { + if (this.deletingForEveryone || this.get('deletedForEveryone')) { + return; + } + log.info('Handling DOE.', { + messageId: this.id, fromId: del.get('fromId'), targetSentTimestamp: del.get('targetSentTimestamp'), messageServerTimestamp: this.get('serverTimestamp'), diff --git a/ts/util/deleteForEveryone.ts b/ts/util/deleteForEveryone.ts index d58e1f04648..0c5cdf9d8ab 100644 --- a/ts/util/deleteForEveryone.ts +++ b/ts/util/deleteForEveryone.ts @@ -5,18 +5,27 @@ import type { DeleteModel } from '../messageModifiers/Deletes'; import type { MessageModel } from '../models/messages'; import * as log from '../logging/log'; import { DAY } from './durations'; +import { isMe } from './whatTypeOfConversation'; import { getContactId } from '../messages/helpers'; +import { isStory } from '../state/selectors/message'; export async function deleteForEveryone( message: MessageModel, doe: DeleteModel, shouldPersist = true ): Promise { - if (message.deletingForEveryone || message.get('deletedForEveryone')) { - return; - } - if (isDeletionByMe(message, doe)) { + const conversation = message.getConversation(); + + // Our 1:1 stories are deleted through ts/util/onStoryRecipientUpdate.ts + if ( + isStory(message.attributes) && + conversation && + isMe(conversation.attributes) + ) { + return; + } + await message.handleDeleteForEveryone(doe, shouldPersist); return; } diff --git a/ts/util/onStoryRecipientUpdate.ts b/ts/util/onStoryRecipientUpdate.ts index dfe31912643..e74702efa6d 100644 --- a/ts/util/onStoryRecipientUpdate.ts +++ b/ts/util/onStoryRecipientUpdate.ts @@ -5,13 +5,13 @@ import { isEqual } from 'lodash'; import type { DeleteAttributesType } from '../messageModifiers/Deletes'; import type { StoryRecipientUpdateEvent } from '../textsecure/messageReceiverEvents'; import * as log from '../logging/log'; -import { Deletes } from '../messageModifiers/Deletes'; +import { DeleteModel } from '../messageModifiers/Deletes'; import { SendStatus } from '../messages/MessageSendState'; -import { deleteForEveryone } from './deleteForEveryone'; import { getConversationIdForLogging } from './idForLogging'; import { isStory } from '../state/selectors/message'; import { normalizeUuid } from './normalizeUuid'; import { queueUpdateMessage } from './messageBatcher'; +import { isMe } from './whatTypeOfConversation'; export async function onStoryRecipientUpdate( event: StoryRecipientUpdateEvent @@ -25,7 +25,12 @@ export async function onStoryRecipientUpdate( const logId = `onStoryRecipientUpdate(${destinationUuid}, ${timestamp})`; if (!conversation) { - log.info(`${logId}: no conversation`); + log.warn(`${logId}: no conversation`); + return; + } + + if (!isMe(conversation.attributes)) { + log.warn(`${logId}: story recipient update on invalid conversation`); return; } @@ -47,7 +52,13 @@ export async function onStoryRecipientUpdate( const isAllowedToReply = new Map(); const distributionListIdToConversationIds = new Map>(); data.storyMessageRecipients.forEach(item => { - const convo = window.ConversationController.get(item.destinationUuid); + if (!item.destinationUuid) { + return; + } + + const convo = window.ConversationController.get( + normalizeUuid(item.destinationUuid, `${logId}.destinationUuid`) + ); if (!convo || !item.distributionListIds) { return; @@ -161,11 +172,16 @@ export async function onStoryRecipientUpdate( serverTimestamp: Number(item.serverTimestamp), targetSentTimestamp: item.timestamp, }; - const doe = Deletes.getSingleton().add(delAttributes); + const doe = new DeleteModel(delAttributes); + // There are no longer any remaining members for this message so lets // run it through deleteForEveryone which marks the message as // deletedForEveryone locally. - deleteForEveryone(message, doe); + // + // NOTE: We don't call `Deletes.onDelete()` so the message lookup by + // sent timestamp doesn't happen (it would return all copies of the + // story, not just the one we want to delete). + message.handleDeleteForEveryone(doe); } else { message.set({ sendStateByConversationId: nextSendStateByConversationId,