diff --git a/protos/SignalService.proto b/protos/SignalService.proto index 7527f6b54..d94cbdfc5 100644 --- a/protos/SignalService.proto +++ b/protos/SignalService.proto @@ -37,7 +37,9 @@ message Unsend { message MessageRequestResponse { // @required - required bool isApproved = 1; + required bool isApproved = 1; + optional bytes profileKey = 2; + optional DataMessage.LokiProfile profile = 3; } message Content { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index fd2fe7f21..96eddfe49 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -908,7 +908,7 @@ export class ConversationModel extends Backbone.Model { const messageRequestResponseParams: MessageRequestResponseParams = { timestamp, - // lokiProfile: UserUtils.getOurProfile(), // we can't curently include our profile in that response + lokiProfile: UserUtils.getOurProfile(), }; const messageRequestResponse = new MessageRequestResponse(messageRequestResponseParams); diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index 110a807c4..a61bc8eaa 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -27,6 +27,7 @@ import { } from '../interactions/conversations/unsendingInteractions'; import { ConversationTypeEnum } from '../models/conversationAttributes'; import { findCachedBlindedMatchOrLookupOnAllServers } from '../session/apis/open_group_api/sogsv3/knownBlindedkeys'; +import { appendFetchAvatarAndProfileJob } from './userProfileImageUpdates'; export async function handleSwarmContentMessage(envelope: EnvelopePlus, messageHash: string) { try { @@ -604,6 +605,11 @@ async function handleMessageRequestResponse( messageRequestResponse: SignalService.MessageRequestResponse ) { const { isApproved } = messageRequestResponse; + if (!isApproved) { + window?.log?.error('handleMessageRequestResponse: isApproved is false -- dropping message.'); + await removeFromCache(envelope); + return; + } if (!messageRequestResponse) { window?.log?.error('handleMessageRequestResponse: Invalid parameters -- dropping message.'); await removeFromCache(envelope); @@ -674,6 +680,14 @@ async function handleMessageRequestResponse( } } + if (messageRequestResponse.profile && !isEmpty(messageRequestResponse.profile)) { + void appendFetchAvatarAndProfileJob( + conversationToApprove, + messageRequestResponse.profile, + messageRequestResponse.profileKey + ); + } + if (!conversationToApprove || conversationToApprove.didApproveMe() === isApproved) { if (conversationToApprove) { await conversationToApprove.commit(); diff --git a/ts/session/messages/outgoing/controlMessage/MessageRequestResponse.ts b/ts/session/messages/outgoing/controlMessage/MessageRequestResponse.ts index 95bde6a94..60d6e13a5 100644 --- a/ts/session/messages/outgoing/controlMessage/MessageRequestResponse.ts +++ b/ts/session/messages/outgoing/controlMessage/MessageRequestResponse.ts @@ -1,18 +1,47 @@ +import ByteBuffer from 'bytebuffer'; +import { isEmpty } from 'lodash'; import { SignalService } from '../../../../protobuf'; +import { LokiProfile } from '../../../../types/Message'; import { ContentMessage } from '../ContentMessage'; import { MessageParams } from '../Message'; // tslint:disable-next-line: no-empty-interface -export interface MessageRequestResponseParams extends MessageParams {} +export interface MessageRequestResponseParams extends MessageParams { + lokiProfile?: LokiProfile; +} export class MessageRequestResponse extends ContentMessage { // we actually send a response only if it is an accept // private readonly isApproved: boolean; + private readonly profileKey?: Uint8Array; + private readonly displayName?: string; + private readonly avatarPointer?: string; constructor(params: MessageRequestResponseParams) { super({ timestamp: params.timestamp, } as MessageRequestResponseParams); + + if (params.lokiProfile && params.lokiProfile.profileKey) { + if ( + params.lokiProfile.profileKey instanceof Uint8Array || + (params.lokiProfile.profileKey as any) instanceof ByteBuffer + ) { + this.profileKey = new Uint8Array(params.lokiProfile.profileKey); + } else { + this.profileKey = new Uint8Array( + ByteBuffer.wrap(params.lokiProfile.profileKey).toArrayBuffer() + ); + } + } + + this.displayName = params.lokiProfile && params.lokiProfile.displayName; + + // no need to iclude the avatarPointer if there is no profileKey associated with it. + this.avatarPointer = + params.lokiProfile?.avatarPointer && !isEmpty(this.profileKey) + ? params.lokiProfile.avatarPointer + : undefined; } public contentProto(): SignalService.Content { @@ -22,8 +51,27 @@ export class MessageRequestResponse extends ContentMessage { } public messageRequestResponseProto(): SignalService.MessageRequestResponse { + let profileKey: Uint8Array | undefined; + let profile: SignalService.DataMessage.LokiProfile | undefined; + if (this.avatarPointer || this.displayName) { + profile = new SignalService.DataMessage.LokiProfile(); + + if (this.avatarPointer) { + profile.profilePicture = this.avatarPointer; + } + + if (this.displayName) { + profile.displayName = this.displayName; + } + } + + if (this.profileKey && this.profileKey.length) { + profileKey = this.profileKey; + } return new SignalService.MessageRequestResponse({ isApproved: true, + profileKey, + profile, }); } } diff --git a/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts b/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts index c5fe43d0c..166e6804b 100644 --- a/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/VisibleMessage.ts @@ -1,4 +1,5 @@ import ByteBuffer from 'bytebuffer'; +import { isEmpty } from 'lodash'; import { DataMessage } from '..'; import { SignalService } from '../../../../protobuf'; import { LokiProfile } from '../../../../types/Message'; @@ -108,7 +109,12 @@ export class VisibleMessage extends DataMessage { } this.displayName = params.lokiProfile && params.lokiProfile.displayName; - this.avatarPointer = params.lokiProfile && params.lokiProfile.avatarPointer; + // no need to iclude the avatarPointer if there is no profileKey associated with it. + this.avatarPointer = + params.lokiProfile?.avatarPointer && !isEmpty(this.profileKey) + ? params.lokiProfile.avatarPointer + : undefined; + this.preview = params.preview; this.reaction = params.reaction; this.syncTarget = params.syncTarget; @@ -149,6 +155,7 @@ export class VisibleMessage extends DataMessage { } dataMessage.profile = profile; } + if (this.profileKey && this.profileKey.length) { dataMessage.profileKey = this.profileKey; }