You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			84 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			84 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
| import { getMessageQueue } from '../../..';
 | |
| import { SignalService } from '../../../../protobuf';
 | |
| import { SnodeNamespaces } from '../../../apis/snode_api/namespaces';
 | |
| import { getConversationController } from '../../../conversations';
 | |
| import { DisappearingMessages } from '../../../disappearing_messages';
 | |
| import { PubKey } from '../../../types';
 | |
| import { UserUtils } from '../../../utils';
 | |
| import { ExpirableMessage, ExpirableMessageParams } from '../ExpirableMessage';
 | |
| 
 | |
| interface DataExtractionNotificationMessageParams extends ExpirableMessageParams {
 | |
|   referencedAttachmentTimestamp: number;
 | |
| }
 | |
| 
 | |
| export class DataExtractionNotificationMessage extends ExpirableMessage {
 | |
|   public readonly referencedAttachmentTimestamp: number;
 | |
| 
 | |
|   constructor(params: DataExtractionNotificationMessageParams) {
 | |
|     super(params);
 | |
|     this.referencedAttachmentTimestamp = params.referencedAttachmentTimestamp;
 | |
|     // this does not make any sense
 | |
|     if (!this.referencedAttachmentTimestamp) {
 | |
|       throw new Error('referencedAttachmentTimestamp must be set');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   public contentProto(): SignalService.Content {
 | |
|     const content = super.contentProto();
 | |
|     content.dataExtractionNotification = this.dataExtractionProto();
 | |
|     return content;
 | |
|   }
 | |
| 
 | |
|   protected dataExtractionProto(): SignalService.DataExtractionNotification {
 | |
|     const ACTION_ENUM = SignalService.DataExtractionNotification.Type;
 | |
| 
 | |
|     const action = ACTION_ENUM.MEDIA_SAVED; // we cannot know when user screenshots, so it can only be a media saved on desktop
 | |
| 
 | |
|     return new SignalService.DataExtractionNotification({
 | |
|       type: action,
 | |
|       timestamp: this.referencedAttachmentTimestamp,
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Currently only enabled for private chats
 | |
|  */
 | |
| export const sendDataExtractionNotification = async (
 | |
|   conversationId: string,
 | |
|   attachmentSender: string,
 | |
|   referencedAttachmentTimestamp: number
 | |
| ) => {
 | |
|   const convo = getConversationController().get(conversationId);
 | |
|   if (!convo || !convo.isPrivate() || convo.isMe() || UserUtils.isUsFromCache(attachmentSender)) {
 | |
|     window.log.warn('Not sending saving attachment notification for', attachmentSender);
 | |
|     return;
 | |
|   }
 | |
|   const { expirationType, expireTimer } =
 | |
|     DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
 | |
|   // DataExtractionNotification are expiring with a forced DaR timer if a DaS is set.
 | |
|   // It's because we want the DataExtractionNotification to stay in the swarm as much as possible,
 | |
|   // but also expire on the recipient's side (and synced) once read.
 | |
|   const dataExtractionNotificationMessage = new DataExtractionNotificationMessage({
 | |
|     referencedAttachmentTimestamp,
 | |
|     timestamp: Date.now(),
 | |
|     expirationType,
 | |
|     expireTimer,
 | |
|   });
 | |
| 
 | |
|   const pubkey = PubKey.cast(conversationId);
 | |
|   window.log.info(
 | |
|     `Sending DataExtractionNotification to ${conversationId} about attachment: ${referencedAttachmentTimestamp}`
 | |
|   );
 | |
| 
 | |
|   try {
 | |
|     await getMessageQueue().sendToPubKey(
 | |
|       pubkey,
 | |
|       dataExtractionNotificationMessage,
 | |
|       SnodeNamespaces.UserMessages
 | |
|     );
 | |
|   } catch (e) {
 | |
|     window.log.warn('failed to send data extraction notification', e);
 | |
|   }
 | |
| };
 |