105 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Copyright 2020-2021 Signal Messenger, LLC
 | 
						|
// SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
 | 
						|
/* eslint-disable max-classes-per-file */
 | 
						|
 | 
						|
import { Collection, Model } from 'backbone';
 | 
						|
import { MessageModel } from '../models/messages';
 | 
						|
 | 
						|
type DeleteAttributesType = {
 | 
						|
  targetSentTimestamp: number;
 | 
						|
  serverTimestamp: number;
 | 
						|
  fromId: string;
 | 
						|
};
 | 
						|
 | 
						|
export class DeleteModel extends Model<DeleteAttributesType> {}
 | 
						|
 | 
						|
let singleton: Deletes | undefined;
 | 
						|
 | 
						|
export class Deletes extends Collection<DeleteModel> {
 | 
						|
  static getSingleton(): Deletes {
 | 
						|
    if (!singleton) {
 | 
						|
      singleton = new Deletes();
 | 
						|
    }
 | 
						|
 | 
						|
    return singleton;
 | 
						|
  }
 | 
						|
 | 
						|
  forMessage(message: MessageModel): Array<DeleteModel> {
 | 
						|
    const matchingDeletes = this.filter(item => {
 | 
						|
      return (
 | 
						|
        item.get('targetSentTimestamp') === message.get('sent_at') &&
 | 
						|
        item.get('fromId') === message.getContactId()
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    if (matchingDeletes.length > 0) {
 | 
						|
      window.log.info('Found early DOE for message');
 | 
						|
      this.remove(matchingDeletes);
 | 
						|
      return matchingDeletes;
 | 
						|
    }
 | 
						|
 | 
						|
    return [];
 | 
						|
  }
 | 
						|
 | 
						|
  async onDelete(del: DeleteModel): Promise<void> {
 | 
						|
    try {
 | 
						|
      // The conversation the deleted message was in; we have to find it in the database
 | 
						|
      //   to to figure that out.
 | 
						|
      const targetConversation = await window.ConversationController.getConversationForTargetMessage(
 | 
						|
        del.get('fromId'),
 | 
						|
        del.get('targetSentTimestamp')
 | 
						|
      );
 | 
						|
 | 
						|
      if (!targetConversation) {
 | 
						|
        window.log.info(
 | 
						|
          'No target conversation for DOE',
 | 
						|
          del.get('fromId'),
 | 
						|
          del.get('targetSentTimestamp')
 | 
						|
        );
 | 
						|
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // Do not await, since this can deadlock the queue
 | 
						|
      targetConversation.queueJob('Deletes.onDelete', async () => {
 | 
						|
        window.log.info('Handling DOE for', del.get('targetSentTimestamp'));
 | 
						|
 | 
						|
        const messages = await window.Signal.Data.getMessagesBySentAt(
 | 
						|
          del.get('targetSentTimestamp'),
 | 
						|
          {
 | 
						|
            MessageCollection: window.Whisper.MessageCollection,
 | 
						|
          }
 | 
						|
        );
 | 
						|
 | 
						|
        const targetMessage = messages.find(
 | 
						|
          m => del.get('fromId') === m.getContactId()
 | 
						|
        );
 | 
						|
 | 
						|
        if (!targetMessage) {
 | 
						|
          window.log.info(
 | 
						|
            'No message for DOE',
 | 
						|
            del.get('fromId'),
 | 
						|
            del.get('targetSentTimestamp')
 | 
						|
          );
 | 
						|
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        const message = window.MessageController.register(
 | 
						|
          targetMessage.id,
 | 
						|
          targetMessage
 | 
						|
        );
 | 
						|
 | 
						|
        await window.Signal.Util.deleteForEveryone(message, del);
 | 
						|
 | 
						|
        this.remove(del);
 | 
						|
      });
 | 
						|
    } catch (error) {
 | 
						|
      window.log.error(
 | 
						|
        'Deletes.onDelete error:',
 | 
						|
        error && error.stack ? error.stack : error
 | 
						|
      );
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |