destinationServiceId in Sent
This commit is contained in:
parent
af4ad55c68
commit
f90c2b7479
20 changed files with 322 additions and 104 deletions
|
@ -457,18 +457,27 @@ message SyncMessage {
|
||||||
message Sent {
|
message Sent {
|
||||||
message UnidentifiedDeliveryStatus {
|
message UnidentifiedDeliveryStatus {
|
||||||
optional string destination = 1;
|
optional string destination = 1;
|
||||||
optional string destinationUuid = 3;
|
oneof destinationServiceId {
|
||||||
|
string destinationAci = 3;
|
||||||
|
string destinationPni = 4;
|
||||||
|
}
|
||||||
optional bool unidentified = 2;
|
optional bool unidentified = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StoryMessageRecipient {
|
message StoryMessageRecipient {
|
||||||
optional string destinationUuid = 1;
|
oneof destinationServiceId {
|
||||||
|
string destinationAci = 1;
|
||||||
|
string destinationPni = 4;
|
||||||
|
}
|
||||||
repeated string distributionListIds = 2;
|
repeated string distributionListIds = 2;
|
||||||
optional bool isAllowedToReply = 3;
|
optional bool isAllowedToReply = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional string destination = 1;
|
optional string destination = 1;
|
||||||
optional string destinationUuid = 7;
|
oneof destinationServiceId {
|
||||||
|
string destinationAci = 7;
|
||||||
|
string destinationPni = 11;
|
||||||
|
}
|
||||||
optional uint64 timestamp = 2;
|
optional uint64 timestamp = 2;
|
||||||
optional DataMessage message = 3;
|
optional DataMessage message = 3;
|
||||||
optional uint64 expirationStartTimestamp = 4;
|
optional uint64 expirationStartTimestamp = 4;
|
||||||
|
|
|
@ -149,6 +149,7 @@ import { themeChanged } from './shims/themeChanged';
|
||||||
import { createIPCEvents } from './util/createIPCEvents';
|
import { createIPCEvents } from './util/createIPCEvents';
|
||||||
import { RemoveAllConfiguration } from './types/RemoveAllConfiguration';
|
import { RemoveAllConfiguration } from './types/RemoveAllConfiguration';
|
||||||
import { isValidUuid, UUIDKind, UUID } from './types/UUID';
|
import { isValidUuid, UUIDKind, UUID } from './types/UUID';
|
||||||
|
import type { TaggedUUIDStringType } from './types/UUID';
|
||||||
import * as log from './logging/log';
|
import * as log from './logging/log';
|
||||||
import { loadRecentEmojis } from './util/loadRecentEmojis';
|
import { loadRecentEmojis } from './util/loadRecentEmojis';
|
||||||
import { deleteAllLogs } from './util/deleteAllLogs';
|
import { deleteAllLogs } from './util/deleteAllLogs';
|
||||||
|
@ -2463,7 +2464,9 @@ export async function startApp(): Promise<void> {
|
||||||
message: data.message,
|
message: data.message,
|
||||||
// 'message' event: for 1:1 converations, the conversation is same as sender
|
// 'message' event: for 1:1 converations, the conversation is same as sender
|
||||||
destination: data.source,
|
destination: data.source,
|
||||||
destinationUuid: data.sourceUuid,
|
destinationUuid: {
|
||||||
|
aci: data.sourceUuid,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { PROFILE_KEY_UPDATE } = Proto.DataMessage.Flags;
|
const { PROFILE_KEY_UPDATE } = Proto.DataMessage.Flags;
|
||||||
|
@ -2699,11 +2702,9 @@ export async function startApp(): Promise<void> {
|
||||||
result: SendStateByConversationId,
|
result: SendStateByConversationId,
|
||||||
{ destinationUuid, destination, isAllowedToReplyToStory }
|
{ destinationUuid, destination, isAllowedToReplyToStory }
|
||||||
) => {
|
) => {
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.get(
|
||||||
uuid: destinationUuid,
|
destinationUuid?.aci || destinationUuid?.pni || destination
|
||||||
e164: destination,
|
);
|
||||||
reason: 'createSentMessage',
|
|
||||||
});
|
|
||||||
if (!conversation || conversation.id === ourId) {
|
if (!conversation || conversation.id === ourId) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2729,7 +2730,12 @@ export async function startApp(): Promise<void> {
|
||||||
if (unidentifiedStatus.length) {
|
if (unidentifiedStatus.length) {
|
||||||
unidentifiedDeliveries = unidentifiedStatus
|
unidentifiedDeliveries = unidentifiedStatus
|
||||||
.filter(item => Boolean(item.unidentified))
|
.filter(item => Boolean(item.unidentified))
|
||||||
.map(item => item.destinationUuid || item.destination)
|
.map(
|
||||||
|
item =>
|
||||||
|
item.destinationUuid?.aci ||
|
||||||
|
item.destinationUuid?.pni ||
|
||||||
|
item.destination
|
||||||
|
)
|
||||||
.filter(isNotNil);
|
.filter(isNotNil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2770,7 +2776,7 @@ export async function startApp(): Promise<void> {
|
||||||
}: {
|
}: {
|
||||||
message: ProcessedDataMessage;
|
message: ProcessedDataMessage;
|
||||||
destination?: string;
|
destination?: string;
|
||||||
destinationUuid?: string;
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
}): MessageDescriptor => {
|
}): MessageDescriptor => {
|
||||||
if (message.groupV2) {
|
if (message.groupV2) {
|
||||||
const { id } = message.groupV2;
|
const { id } = message.groupV2;
|
||||||
|
@ -2810,11 +2816,9 @@ export async function startApp(): Promise<void> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.get(
|
||||||
uuid: destinationUuid,
|
destinationUuid?.aci || destinationUuid?.pni || destination
|
||||||
e164: destination,
|
);
|
||||||
reason: `getMessageDescriptor(${message.timestamp}): private`,
|
|
||||||
});
|
|
||||||
strictAssert(conversation, 'Destination conversation cannot be created');
|
strictAssert(conversation, 'Destination conversation cannot be created');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -82,7 +82,12 @@ const deleteStoryForEveryoneJobDataSchema = z.object({
|
||||||
updatedStoryRecipients: z
|
updatedStoryRecipients: z
|
||||||
.array(
|
.array(
|
||||||
z.object({
|
z.object({
|
||||||
destinationUuid: z.string(),
|
// TODO: DESKTOP-5630
|
||||||
|
destinationUuid: z.string().optional(),
|
||||||
|
legacyDestinationUuid: z.string().optional(),
|
||||||
|
|
||||||
|
destinationAci: z.string().optional(),
|
||||||
|
destinationPni: z.string().optional(),
|
||||||
distributionListIds: z.array(z.string()),
|
distributionListIds: z.array(z.string()),
|
||||||
isAllowedToReply: z.boolean(),
|
isAllowedToReply: z.boolean(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -36,6 +36,7 @@ import { strictAssert } from '../../util/assert';
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { isStory } from '../../messages/helpers';
|
import { isStory } from '../../messages/helpers';
|
||||||
import { sendToGroup } from '../../util/sendToGroup';
|
import { sendToGroup } from '../../util/sendToGroup';
|
||||||
|
import { getTaggedConversationUuid } from '../../util/getConversationUuid';
|
||||||
|
|
||||||
export async function sendDeleteForEveryone(
|
export async function sendDeleteForEveryone(
|
||||||
conversation: ConversationModel,
|
conversation: ConversationModel,
|
||||||
|
@ -139,7 +140,9 @@ export async function sendDeleteForEveryone(
|
||||||
proto.dataMessage
|
proto.dataMessage
|
||||||
).finish(),
|
).finish(),
|
||||||
destination: conversation.get('e164'),
|
destination: conversation.get('e164'),
|
||||||
destinationUuid: conversation.get('uuid'),
|
destinationUuid: getTaggedConversationUuid(
|
||||||
|
conversation.attributes
|
||||||
|
),
|
||||||
expirationStartTimestamp: null,
|
expirationStartTimestamp: null,
|
||||||
options: sendOptions,
|
options: sendOptions,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|
|
@ -239,8 +239,18 @@ export async function sendDeleteStoryForEveryone(
|
||||||
await handleMessageSend(
|
await handleMessageSend(
|
||||||
messaging.sendSyncMessage({
|
messaging.sendSyncMessage({
|
||||||
destination: undefined,
|
destination: undefined,
|
||||||
destinationUuid,
|
destinationUuid: {
|
||||||
storyMessageRecipients: updatedStoryRecipients,
|
aci: destinationUuid,
|
||||||
|
},
|
||||||
|
storyMessageRecipients: updatedStoryRecipients?.map(
|
||||||
|
({ destinationUuid: legacyDestinationUuid, ...rest }) => {
|
||||||
|
return {
|
||||||
|
// The field was renamed.
|
||||||
|
legacyDestinationUuid,
|
||||||
|
...rest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
),
|
||||||
expirationStartTimestamp: null,
|
expirationStartTimestamp: null,
|
||||||
isUpdate: true,
|
isUpdate: true,
|
||||||
options,
|
options,
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { handleMessageSend } from '../../util/handleMessageSend';
|
||||||
import { isConversationAccepted } from '../../util/isConversationAccepted';
|
import { isConversationAccepted } from '../../util/isConversationAccepted';
|
||||||
import { isConversationUnregistered } from '../../util/isConversationUnregistered';
|
import { isConversationUnregistered } from '../../util/isConversationUnregistered';
|
||||||
import { DurationInSeconds } from '../../util/durations';
|
import { DurationInSeconds } from '../../util/durations';
|
||||||
|
import { getTaggedConversationUuid } from '../../util/getConversationUuid';
|
||||||
|
|
||||||
export async function sendDirectExpirationTimerUpdate(
|
export async function sendDirectExpirationTimerUpdate(
|
||||||
conversation: ConversationModel,
|
conversation: ConversationModel,
|
||||||
|
@ -107,7 +108,7 @@ export async function sendDirectExpirationTimerUpdate(
|
||||||
proto.dataMessage
|
proto.dataMessage
|
||||||
).finish(),
|
).finish(),
|
||||||
destination: conversation.get('e164'),
|
destination: conversation.get('e164'),
|
||||||
destinationUuid: conversation.get('uuid'),
|
destinationUuid: getTaggedConversationUuid(conversation.attributes),
|
||||||
expirationStartTimestamp: null,
|
expirationStartTimestamp: null,
|
||||||
options: sendOptions,
|
options: sendOptions,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { handleMultipleSendErrors } from './handleMultipleSendErrors';
|
||||||
import { isGroupV2, isMe } from '../../util/whatTypeOfConversation';
|
import { isGroupV2, isMe } from '../../util/whatTypeOfConversation';
|
||||||
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
||||||
import { sendContentMessageToGroup } from '../../util/sendToGroup';
|
import { sendContentMessageToGroup } from '../../util/sendToGroup';
|
||||||
|
import { getTaggedConversationUuid } from '../../util/getConversationUuid';
|
||||||
import { distributionListToSendTarget } from '../../util/distributionListToSendTarget';
|
import { distributionListToSendTarget } from '../../util/distributionListToSendTarget';
|
||||||
import { uploadAttachment } from '../../util/uploadAttachment';
|
import { uploadAttachment } from '../../util/uploadAttachment';
|
||||||
import { SendMessageChallengeError } from '../../textsecure/Errors';
|
import { SendMessageChallengeError } from '../../textsecure/Errors';
|
||||||
|
@ -548,8 +549,17 @@ export async function sendStory(
|
||||||
// Build up the sync message's storyMessageRecipients and send it
|
// Build up the sync message's storyMessageRecipients and send it
|
||||||
const storyMessageRecipients: StoryMessageRecipientsType = [];
|
const storyMessageRecipients: StoryMessageRecipientsType = [];
|
||||||
recipientsByUuid.forEach((distributionListIds, destinationUuid) => {
|
recipientsByUuid.forEach((distributionListIds, destinationUuid) => {
|
||||||
|
const recipient = window.ConversationController.get(destinationUuid);
|
||||||
|
if (!recipient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const taggedUuid = getTaggedConversationUuid(recipient.attributes);
|
||||||
|
if (!taggedUuid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
storyMessageRecipients.push({
|
storyMessageRecipients.push({
|
||||||
destinationUuid,
|
destinationAci: taggedUuid.aci,
|
||||||
|
destinationPni: taggedUuid.pni,
|
||||||
distributionListIds: Array.from(distributionListIds),
|
distributionListIds: Array.from(distributionListIds),
|
||||||
isAllowedToReply: canReplyUuids.has(destinationUuid),
|
isAllowedToReply: canReplyUuids.has(destinationUuid),
|
||||||
});
|
});
|
||||||
|
@ -567,7 +577,7 @@ export async function sendStory(
|
||||||
await messaging.sendSyncMessage({
|
await messaging.sendSyncMessage({
|
||||||
// Note: these two fields will be undefined if we're sending to a group
|
// Note: these two fields will be undefined if we're sending to a group
|
||||||
destination: conversation.get('e164'),
|
destination: conversation.get('e164'),
|
||||||
destinationUuid: conversation.get('uuid'),
|
destinationUuid: getTaggedConversationUuid(conversation.attributes),
|
||||||
storyMessage: originalStoryMessage,
|
storyMessage: originalStoryMessage,
|
||||||
storyMessageRecipients,
|
storyMessageRecipients,
|
||||||
expirationStartTimestamp: null,
|
expirationStartTimestamp: null,
|
||||||
|
|
|
@ -49,6 +49,7 @@ import { SendMessageProtoError } from '../textsecure/Errors';
|
||||||
import * as expirationTimer from '../util/expirationTimer';
|
import * as expirationTimer from '../util/expirationTimer';
|
||||||
import { getUserLanguages } from '../util/userLanguages';
|
import { getUserLanguages } from '../util/userLanguages';
|
||||||
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
||||||
|
import { getTaggedConversationUuid } from '../util/getConversationUuid';
|
||||||
|
|
||||||
import type { ReactionType } from '../types/Reactions';
|
import type { ReactionType } from '../types/Reactions';
|
||||||
import { UUID, UUIDKind } from '../types/UUID';
|
import { UUID, UUIDKind } from '../types/UUID';
|
||||||
|
@ -1823,7 +1824,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
...encodedContent,
|
...encodedContent,
|
||||||
timestamp,
|
timestamp,
|
||||||
destination: conv.get('e164'),
|
destination: conv.get('e164'),
|
||||||
destinationUuid: conv.get('uuid'),
|
destinationUuid: getTaggedConversationUuid(conv.attributes),
|
||||||
expirationStartTimestamp:
|
expirationStartTimestamp:
|
||||||
this.get('expirationStartTimestamp') || null,
|
this.get('expirationStartTimestamp') || null,
|
||||||
conversationIdsSentTo,
|
conversationIdsSentTo,
|
||||||
|
@ -2221,14 +2222,16 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
unidentifiedStatus.forEach(
|
unidentifiedStatus.forEach(
|
||||||
({ destinationUuid, destination, unidentified }) => {
|
({ destinationUuid, destination, unidentified }) => {
|
||||||
const identifier = destinationUuid || destination;
|
const identifier =
|
||||||
|
destinationUuid?.aci || destinationUuid?.pni || destination;
|
||||||
if (!identifier) {
|
if (!identifier) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { conversation: destinationConversation } =
|
const { conversation: destinationConversation } =
|
||||||
window.ConversationController.maybeMergeContacts({
|
window.ConversationController.maybeMergeContacts({
|
||||||
aci: destinationUuid,
|
aci: destinationUuid?.aci,
|
||||||
|
pni: destinationUuid?.pni,
|
||||||
e164: destination || undefined,
|
e164: destination || undefined,
|
||||||
reason: `handleDataMessage(${initialMessage.timestamp})`,
|
reason: `handleDataMessage(${initialMessage.timestamp})`,
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import getGuid from 'uuid/v4';
|
import { UUID } from '../types/UUID';
|
||||||
|
|
||||||
import { processSyncMessage } from '../textsecure/processSyncMessage';
|
import { processSyncMessage } from '../textsecure/processSyncMessage';
|
||||||
|
|
||||||
describe('processSyncMessage', () => {
|
describe('processSyncMessage', () => {
|
||||||
it('should normalize UUIDs in sent', () => {
|
const destinationUuid = UUID.generate().toString();
|
||||||
const destinationUuid = getGuid();
|
|
||||||
|
|
||||||
|
it('should normalize UUIDs in sent (aci)', () => {
|
||||||
const out = processSyncMessage({
|
const out = processSyncMessage({
|
||||||
sent: {
|
sent: {
|
||||||
destinationUuid: destinationUuid.toUpperCase(),
|
destinationAci: destinationUuid.toUpperCase(),
|
||||||
|
|
||||||
unidentifiedStatus: [
|
unidentifiedStatus: [
|
||||||
{
|
{
|
||||||
destinationUuid: destinationUuid.toUpperCase(),
|
destinationAci: destinationUuid.toUpperCase(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -24,11 +24,51 @@ describe('processSyncMessage', () => {
|
||||||
|
|
||||||
assert.deepStrictEqual(out, {
|
assert.deepStrictEqual(out, {
|
||||||
sent: {
|
sent: {
|
||||||
destinationUuid,
|
destinationUuid: {
|
||||||
|
aci: destinationUuid,
|
||||||
|
pni: undefined,
|
||||||
|
},
|
||||||
|
|
||||||
|
storyMessageRecipients: undefined,
|
||||||
|
unidentifiedStatus: [
|
||||||
|
{
|
||||||
|
destinationUuid: {
|
||||||
|
aci: destinationUuid,
|
||||||
|
pni: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should normalize UUIDs in sent (pni)', () => {
|
||||||
|
const out = processSyncMessage({
|
||||||
|
sent: {
|
||||||
|
destinationPni: destinationUuid.toUpperCase(),
|
||||||
|
|
||||||
unidentifiedStatus: [
|
unidentifiedStatus: [
|
||||||
{
|
{
|
||||||
destinationUuid,
|
destinationPni: destinationUuid.toUpperCase(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepStrictEqual(out, {
|
||||||
|
sent: {
|
||||||
|
destinationUuid: {
|
||||||
|
aci: undefined,
|
||||||
|
pni: destinationUuid,
|
||||||
|
},
|
||||||
|
|
||||||
|
storyMessageRecipients: undefined,
|
||||||
|
unidentifiedStatus: [
|
||||||
|
{
|
||||||
|
destinationUuid: {
|
||||||
|
aci: undefined,
|
||||||
|
pni: destinationUuid,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -52,7 +52,7 @@ import { bytesToUuid } from '../Crypto';
|
||||||
import type { DownloadedAttachmentType } from '../types/Attachment';
|
import type { DownloadedAttachmentType } from '../types/Attachment';
|
||||||
import { Address } from '../types/Address';
|
import { Address } from '../types/Address';
|
||||||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||||
import type { UUIDStringType } from '../types/UUID';
|
import type { UUIDStringType, TaggedUUIDStringType } from '../types/UUID';
|
||||||
import { UUID, UUIDKind } from '../types/UUID';
|
import { UUID, UUIDKind } from '../types/UUID';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
|
||||||
|
@ -2028,8 +2028,9 @@ export default class MessageReceiver
|
||||||
|
|
||||||
let p: Promise<void> = Promise.resolve();
|
let p: Promise<void> = Promise.resolve();
|
||||||
if (msg.flags && msg.flags & Proto.DataMessage.Flags.END_SESSION) {
|
if (msg.flags && msg.flags & Proto.DataMessage.Flags.END_SESSION) {
|
||||||
if (destinationUuid) {
|
const anyUuid = destinationUuid?.aci ?? destinationUuid?.pni;
|
||||||
p = this.handleEndSession(envelope, new UUID(destinationUuid));
|
if (anyUuid) {
|
||||||
|
p = this.handleEndSession(envelope, new UUID(anyUuid));
|
||||||
} else if (destination) {
|
} else if (destination) {
|
||||||
const theirUuid = UUID.lookup(destination);
|
const theirUuid = UUID.lookup(destination);
|
||||||
if (theirUuid) {
|
if (theirUuid) {
|
||||||
|
@ -2061,8 +2062,7 @@ export default class MessageReceiver
|
||||||
const ev = new SentEvent(
|
const ev = new SentEvent(
|
||||||
{
|
{
|
||||||
destination: dropNull(destination),
|
destination: dropNull(destination),
|
||||||
destinationUuid:
|
destinationUuid,
|
||||||
dropNull(destinationUuid) || envelope.destinationUuid.toString(),
|
|
||||||
timestamp: timestamp?.toNumber(),
|
timestamp: timestamp?.toNumber(),
|
||||||
serverTimestamp: envelope.serverTimestamp,
|
serverTimestamp: envelope.serverTimestamp,
|
||||||
device: envelope.sourceDevice,
|
device: envelope.sourceDevice,
|
||||||
|
@ -2168,7 +2168,9 @@ export default class MessageReceiver
|
||||||
if (sentMessage && message.groupV2) {
|
if (sentMessage && message.groupV2) {
|
||||||
const ev = new SentEvent(
|
const ev = new SentEvent(
|
||||||
{
|
{
|
||||||
destinationUuid: envelope.destinationUuid.toString(),
|
destinationUuid: {
|
||||||
|
aci: envelope.destinationUuid.toString(),
|
||||||
|
},
|
||||||
device: envelope.sourceDevice,
|
device: envelope.sourceDevice,
|
||||||
isRecipientUpdate: Boolean(sentMessage.isRecipientUpdate),
|
isRecipientUpdate: Boolean(sentMessage.isRecipientUpdate),
|
||||||
message,
|
message,
|
||||||
|
@ -2183,10 +2185,7 @@ export default class MessageReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
destinationUuid: normalizeUuid(
|
destinationUuid,
|
||||||
destinationUuid,
|
|
||||||
'handleStoryMessage.destinationUuid'
|
|
||||||
),
|
|
||||||
isAllowedToReplyToStory: Boolean(isAllowedToReply),
|
isAllowedToReplyToStory: Boolean(isAllowedToReply),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@ -2202,25 +2201,26 @@ export default class MessageReceiver
|
||||||
const { storyMessageRecipients } = sentMessage;
|
const { storyMessageRecipients } = sentMessage;
|
||||||
const recipients = storyMessageRecipients ?? [];
|
const recipients = storyMessageRecipients ?? [];
|
||||||
|
|
||||||
const isAllowedToReply = new Map<string, boolean>();
|
const isAllowedToReply = new Map<UUIDStringType, boolean>();
|
||||||
const distributionListToSentUuid = new Map<string, Set<string>>();
|
const distributionListToSentUuid = new Map<
|
||||||
|
string,
|
||||||
|
Map<UUIDStringType, TaggedUUIDStringType>
|
||||||
|
>();
|
||||||
|
|
||||||
recipients.forEach(recipient => {
|
recipients.forEach(recipient => {
|
||||||
const { destinationUuid } = recipient;
|
const { destinationUuid } = recipient;
|
||||||
if (!destinationUuid) {
|
if (!destinationUuid?.aci && !destinationUuid?.pni) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedDestinationUuid = normalizeUuid(
|
const destinationUuidString =
|
||||||
destinationUuid,
|
destinationUuid?.aci || destinationUuid?.pni;
|
||||||
'handleStoryMessage.destinationUuid'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (recipient.distributionListIds) {
|
if (recipient.distributionListIds) {
|
||||||
recipient.distributionListIds.forEach(listId => {
|
recipient.distributionListIds.forEach(listId => {
|
||||||
const sentUuids: Set<string> =
|
const sentUuids: Map<UUIDStringType, TaggedUUIDStringType> =
|
||||||
distributionListToSentUuid.get(listId) || new Set();
|
distributionListToSentUuid.get(listId) || new Map();
|
||||||
sentUuids.add(normalizedDestinationUuid);
|
sentUuids.set(destinationUuidString, destinationUuid);
|
||||||
distributionListToSentUuid.set(listId, sentUuids);
|
distributionListToSentUuid.set(listId, sentUuids);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -2232,7 +2232,7 @@ export default class MessageReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllowedToReply.set(
|
isAllowedToReply.set(
|
||||||
normalizedDestinationUuid,
|
destinationUuidString,
|
||||||
recipient.isAllowedToReply !== false
|
recipient.isAllowedToReply !== false
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -2240,14 +2240,22 @@ export default class MessageReceiver
|
||||||
distributionListToSentUuid.forEach((sentToUuids, listId) => {
|
distributionListToSentUuid.forEach((sentToUuids, listId) => {
|
||||||
const ev = new SentEvent(
|
const ev = new SentEvent(
|
||||||
{
|
{
|
||||||
destinationUuid: envelope.destinationUuid.toString(),
|
destinationUuid: {
|
||||||
|
aci: envelope.destinationUuid.toString(),
|
||||||
|
pni: undefined,
|
||||||
|
},
|
||||||
timestamp: envelope.timestamp,
|
timestamp: envelope.timestamp,
|
||||||
serverTimestamp: envelope.serverTimestamp,
|
serverTimestamp: envelope.serverTimestamp,
|
||||||
device: envelope.sourceDevice,
|
device: envelope.sourceDevice,
|
||||||
unidentifiedStatus: Array.from(sentToUuids).map(
|
unidentifiedStatus: Array.from(sentToUuids.values()).map(
|
||||||
destinationUuid => ({
|
destinationUuid => ({
|
||||||
destinationUuid,
|
destinationUuid,
|
||||||
isAllowedToReplyToStory: isAllowedToReply.get(destinationUuid),
|
isAllowedToReplyToStory: Boolean(
|
||||||
|
(destinationUuid.aci &&
|
||||||
|
isAllowedToReply.get(destinationUuid.aci)) ||
|
||||||
|
(destinationUuid.pni &&
|
||||||
|
isAllowedToReply.get(destinationUuid.pni))
|
||||||
|
),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
message,
|
message,
|
||||||
|
@ -2867,11 +2875,15 @@ export default class MessageReceiver
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDestination(sentMessage: Proto.SyncMessage.ISent) {
|
private getDestination(sentMessage: ProcessedSent) {
|
||||||
if (sentMessage.message && sentMessage.message.groupV2) {
|
if (sentMessage.message && sentMessage.message.groupV2) {
|
||||||
return `groupv2(${this.getGroupId(sentMessage.message)})`;
|
return `groupv2(${this.getGroupId(sentMessage.message)})`;
|
||||||
}
|
}
|
||||||
return sentMessage.destination || sentMessage.destinationUuid;
|
return (
|
||||||
|
sentMessage.destination ||
|
||||||
|
sentMessage.destinationUuid?.aci ||
|
||||||
|
sentMessage.destinationUuid?.pni
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleSyncMessage(
|
private async handleSyncMessage(
|
||||||
|
@ -3067,8 +3079,7 @@ export default class MessageReceiver
|
||||||
const ev = new SentEvent(
|
const ev = new SentEvent(
|
||||||
{
|
{
|
||||||
destination: dropNull(destination),
|
destination: dropNull(destination),
|
||||||
destinationUuid:
|
destinationUuid,
|
||||||
dropNull(destinationUuid) || envelope.destinationUuid.toString(),
|
|
||||||
timestamp: envelope.timestamp,
|
timestamp: envelope.timestamp,
|
||||||
serverTimestamp: envelope.serverTimestamp,
|
serverTimestamp: envelope.serverTimestamp,
|
||||||
device: envelope.sourceDevice,
|
device: envelope.sourceDevice,
|
||||||
|
|
|
@ -17,6 +17,7 @@ import type { ConversationModel } from '../models/conversations';
|
||||||
import { GLOBAL_ZONE } from '../SignalProtocolStore';
|
import { GLOBAL_ZONE } from '../SignalProtocolStore';
|
||||||
import { assertDev, strictAssert } from '../util/assert';
|
import { assertDev, strictAssert } from '../util/assert';
|
||||||
import { parseIntOrThrow } from '../util/parseIntOrThrow';
|
import { parseIntOrThrow } from '../util/parseIntOrThrow';
|
||||||
|
import { getTaggedConversationUuid } from '../util/getConversationUuid';
|
||||||
import { Address } from '../types/Address';
|
import { Address } from '../types/Address';
|
||||||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||||
import { SenderKeys } from '../LibSignalStores';
|
import { SenderKeys } from '../LibSignalStores';
|
||||||
|
@ -24,7 +25,7 @@ import type {
|
||||||
TextAttachmentType,
|
TextAttachmentType,
|
||||||
UploadedAttachmentType,
|
UploadedAttachmentType,
|
||||||
} from '../types/Attachment';
|
} from '../types/Attachment';
|
||||||
import type { UUID } from '../types/UUID';
|
import type { UUID, TaggedUUIDStringType } from '../types/UUID';
|
||||||
import type {
|
import type {
|
||||||
ChallengeType,
|
ChallengeType,
|
||||||
GetGroupLogOptionsType,
|
GetGroupLogOptionsType,
|
||||||
|
@ -1205,7 +1206,7 @@ export default class MessageSender {
|
||||||
encodedEditMessage?: Uint8Array;
|
encodedEditMessage?: Uint8Array;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
destination: string | undefined;
|
destination: string | undefined;
|
||||||
destinationUuid: string | null | undefined;
|
destinationUuid: TaggedUUIDStringType | undefined;
|
||||||
expirationStartTimestamp: number | null;
|
expirationStartTimestamp: number | null;
|
||||||
conversationIdsSentTo?: Iterable<string>;
|
conversationIdsSentTo?: Iterable<string>;
|
||||||
conversationIdsWithSealedSender?: Set<string>;
|
conversationIdsWithSealedSender?: Set<string>;
|
||||||
|
@ -1230,8 +1231,10 @@ export default class MessageSender {
|
||||||
if (destination) {
|
if (destination) {
|
||||||
sentMessage.destination = destination;
|
sentMessage.destination = destination;
|
||||||
}
|
}
|
||||||
if (destinationUuid) {
|
if (destinationUuid?.aci) {
|
||||||
sentMessage.destinationUuid = destinationUuid;
|
sentMessage.destinationAci = destinationUuid.aci;
|
||||||
|
} else if (destinationUuid?.pni) {
|
||||||
|
sentMessage.destinationPni = destinationUuid.pni;
|
||||||
}
|
}
|
||||||
if (expirationStartTimestamp) {
|
if (expirationStartTimestamp) {
|
||||||
sentMessage.expirationStartTimestamp = Long.fromNumber(
|
sentMessage.expirationStartTimestamp = Long.fromNumber(
|
||||||
|
@ -1262,9 +1265,11 @@ export default class MessageSender {
|
||||||
if (e164) {
|
if (e164) {
|
||||||
status.destination = e164;
|
status.destination = e164;
|
||||||
}
|
}
|
||||||
const uuid = conv.get('uuid');
|
const taggedUuid = getTaggedConversationUuid(conv.attributes);
|
||||||
if (uuid) {
|
if (taggedUuid?.aci) {
|
||||||
status.destinationUuid = uuid;
|
status.destinationAci = taggedUuid.aci;
|
||||||
|
} else if (taggedUuid?.pni) {
|
||||||
|
status.destinationPni = taggedUuid.pni;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status.unidentified =
|
status.unidentified =
|
||||||
|
|
21
ts/textsecure/Types.d.ts
vendored
21
ts/textsecure/Types.d.ts
vendored
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import type { SignalService as Proto } from '../protobuf';
|
import type { SignalService as Proto } from '../protobuf';
|
||||||
import type { IncomingWebSocketRequest } from './WebsocketResources';
|
import type { IncomingWebSocketRequest } from './WebsocketResources';
|
||||||
import type { UUID, UUIDStringType } from '../types/UUID';
|
import type { UUID, UUIDStringType, TaggedUUIDStringType } from '../types/UUID';
|
||||||
import type { TextAttachmentType } from '../types/Attachment';
|
import type { TextAttachmentType } from '../types/Attachment';
|
||||||
import type { GiftBadgeStates } from '../components/conversation/Message';
|
import type { GiftBadgeStates } from '../components/conversation/Message';
|
||||||
import type { MIMEType } from '../types/MIME';
|
import type { MIMEType } from '../types/MIME';
|
||||||
|
@ -222,18 +222,31 @@ export type ProcessedDataMessage = {
|
||||||
|
|
||||||
export type ProcessedUnidentifiedDeliveryStatus = Omit<
|
export type ProcessedUnidentifiedDeliveryStatus = Omit<
|
||||||
Proto.SyncMessage.Sent.IUnidentifiedDeliveryStatus,
|
Proto.SyncMessage.Sent.IUnidentifiedDeliveryStatus,
|
||||||
'destinationUuid'
|
'destinationAci' | 'destinationPni'
|
||||||
> & {
|
> & {
|
||||||
destinationUuid?: string;
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
isAllowedToReplyToStory?: boolean;
|
isAllowedToReplyToStory?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ProcessedStoryMessageRecipient = Omit<
|
||||||
|
Proto.SyncMessage.Sent.IStoryMessageRecipient,
|
||||||
|
'destinationAci' | 'destinationPni'
|
||||||
|
> & {
|
||||||
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
|
};
|
||||||
|
|
||||||
export type ProcessedSent = Omit<
|
export type ProcessedSent = Omit<
|
||||||
Proto.SyncMessage.ISent,
|
Proto.SyncMessage.ISent,
|
||||||
'destinationId' | 'unidentifiedStatus'
|
| 'destinationId'
|
||||||
|
| 'unidentifiedStatus'
|
||||||
|
| 'storyMessageRecipients'
|
||||||
|
| 'destinationAci'
|
||||||
|
| 'destinationPni'
|
||||||
> & {
|
> & {
|
||||||
destinationId?: string;
|
destinationId?: string;
|
||||||
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
unidentifiedStatus?: Array<ProcessedUnidentifiedDeliveryStatus>;
|
unidentifiedStatus?: Array<ProcessedUnidentifiedDeliveryStatus>;
|
||||||
|
storyMessageRecipients?: Array<ProcessedStoryMessageRecipient>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ProcessedSyncMessage = Omit<Proto.ISyncMessage, 'sent'> & {
|
export type ProcessedSyncMessage = Omit<Proto.ISyncMessage, 'sent'> & {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import type { PublicKey } from '@signalapp/libsignal-client';
|
import type { PublicKey } from '@signalapp/libsignal-client';
|
||||||
|
|
||||||
import type { SignalService as Proto } from '../protobuf';
|
import type { SignalService as Proto } from '../protobuf';
|
||||||
import type { UUIDStringType } from '../types/UUID';
|
import type { UUIDStringType, TaggedUUIDStringType } from '../types/UUID';
|
||||||
import type {
|
import type {
|
||||||
ProcessedEnvelope,
|
ProcessedEnvelope,
|
||||||
ProcessedDataMessage,
|
ProcessedDataMessage,
|
||||||
|
@ -193,7 +193,7 @@ export class RetryRequestEvent extends ConfirmableEvent {
|
||||||
|
|
||||||
export type SentEventData = Readonly<{
|
export type SentEventData = Readonly<{
|
||||||
destination?: string;
|
destination?: string;
|
||||||
destinationUuid?: string;
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
timestamp?: number;
|
timestamp?: number;
|
||||||
serverTimestamp?: number;
|
serverTimestamp?: number;
|
||||||
device: number | undefined;
|
device: number | undefined;
|
||||||
|
|
|
@ -1,30 +1,50 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { SignalService as Proto } from '../protobuf';
|
import type { SignalService as Proto } from '../protobuf';
|
||||||
import { normalizeUuid } from '../util/normalizeUuid';
|
import { normalizeUuid } from '../util/normalizeUuid';
|
||||||
import type {
|
import type { ProcessedSent, ProcessedSyncMessage } from './Types.d';
|
||||||
ProcessedUnidentifiedDeliveryStatus,
|
import type { TaggedUUIDStringType } from '../types/UUID';
|
||||||
ProcessedSent,
|
|
||||||
ProcessedSyncMessage,
|
|
||||||
} from './Types.d';
|
|
||||||
|
|
||||||
import UnidentifiedDeliveryStatus = Proto.SyncMessage.Sent.IUnidentifiedDeliveryStatus;
|
type ProtoUUIDTriple = Readonly<{
|
||||||
|
destinationAci?: string | null;
|
||||||
|
destinationPni?: string | null;
|
||||||
|
}>;
|
||||||
|
|
||||||
function processUnidentifiedDeliveryStatus(
|
function toTaggedUuid({
|
||||||
status: UnidentifiedDeliveryStatus
|
destinationAci,
|
||||||
): ProcessedUnidentifiedDeliveryStatus {
|
destinationPni,
|
||||||
const { destinationUuid } = status;
|
}: ProtoUUIDTriple): TaggedUUIDStringType | undefined {
|
||||||
|
if (destinationAci) {
|
||||||
|
return {
|
||||||
|
aci: normalizeUuid(destinationAci, 'syncMessage.sent.destinationAci'),
|
||||||
|
pni: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (destinationPni) {
|
||||||
|
return {
|
||||||
|
aci: undefined,
|
||||||
|
pni: normalizeUuid(destinationPni, 'syncMessage.sent.destinationPni'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processProtoWithDestinationUuid<Input extends ProtoUUIDTriple>(
|
||||||
|
input: Input
|
||||||
|
): Omit<Input, keyof ProtoUUIDTriple> & {
|
||||||
|
destinationUuid?: TaggedUUIDStringType;
|
||||||
|
} {
|
||||||
|
const { destinationAci, destinationPni, ...remaining } = input;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...status,
|
...remaining,
|
||||||
|
|
||||||
destinationUuid: destinationUuid
|
destinationUuid: toTaggedUuid({
|
||||||
? normalizeUuid(
|
destinationAci,
|
||||||
destinationUuid,
|
destinationPni,
|
||||||
'syncMessage.sent.unidentifiedStatus.destinationUuid'
|
}),
|
||||||
)
|
|
||||||
: undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,17 +55,26 @@ function processSent(
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { destinationUuid, unidentifiedStatus } = sent;
|
const {
|
||||||
|
destinationAci,
|
||||||
|
destinationPni,
|
||||||
|
unidentifiedStatus,
|
||||||
|
storyMessageRecipients,
|
||||||
|
...remaining
|
||||||
|
} = sent;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...sent,
|
...remaining,
|
||||||
|
|
||||||
destinationUuid: destinationUuid
|
|
||||||
? normalizeUuid(destinationUuid, 'syncMessage.sent.destinationUuid')
|
|
||||||
: undefined,
|
|
||||||
|
|
||||||
|
destinationUuid: toTaggedUuid({
|
||||||
|
destinationAci,
|
||||||
|
destinationPni,
|
||||||
|
}),
|
||||||
unidentifiedStatus: unidentifiedStatus
|
unidentifiedStatus: unidentifiedStatus
|
||||||
? unidentifiedStatus.map(processUnidentifiedDeliveryStatus)
|
? unidentifiedStatus.map(processProtoWithDestinationUuid)
|
||||||
|
: undefined,
|
||||||
|
storyMessageRecipients: storyMessageRecipients
|
||||||
|
? storyMessageRecipients.map(processProtoWithDestinationUuid)
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,8 @@ export enum ResolvedSendStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StoryMessageRecipientsType = Array<{
|
export type StoryMessageRecipientsType = Array<{
|
||||||
destinationUuid: string;
|
destinationAci?: string;
|
||||||
|
destinationPni?: string;
|
||||||
distributionListIds: Array<string>;
|
distributionListIds: Array<string>;
|
||||||
isAllowedToReply: boolean;
|
isAllowedToReply: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
|
@ -8,6 +8,17 @@ import { strictAssert } from '../util/assert';
|
||||||
export type UUIDStringType =
|
export type UUIDStringType =
|
||||||
`${string}-${string}-${string}-${string}-${string}`;
|
`${string}-${string}-${string}-${string}-${string}`;
|
||||||
|
|
||||||
|
export type TaggedUUIDStringType = Readonly<
|
||||||
|
| {
|
||||||
|
aci: UUIDStringType;
|
||||||
|
pni?: undefined;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
aci?: undefined;
|
||||||
|
pni: UUIDStringType;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export enum UUIDKind {
|
export enum UUIDKind {
|
||||||
ACI = 'ACI',
|
ACI = 'ACI',
|
||||||
PNI = 'PNI',
|
PNI = 'PNI',
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { getMessageById } from '../messages/getMessageById';
|
||||||
import { strictAssert } from './assert';
|
import { strictAssert } from './assert';
|
||||||
import { repeat, zipObject } from './iterables';
|
import { repeat, zipObject } from './iterables';
|
||||||
import { isOlderThan } from './timestamp';
|
import { isOlderThan } from './timestamp';
|
||||||
|
import { getTaggedConversationUuid } from './getConversationUuid';
|
||||||
|
|
||||||
export async function deleteStoryForEveryone(
|
export async function deleteStoryForEveryone(
|
||||||
stories: ReadonlyArray<StoryDataType>,
|
stories: ReadonlyArray<StoryDataType>,
|
||||||
|
@ -157,8 +158,17 @@ export async function deleteStoryForEveryone(
|
||||||
const newStoryMessageRecipients: StoryMessageRecipientsType = [];
|
const newStoryMessageRecipients: StoryMessageRecipientsType = [];
|
||||||
|
|
||||||
newStoryRecipients.forEach((recipientData, destinationUuid) => {
|
newStoryRecipients.forEach((recipientData, destinationUuid) => {
|
||||||
|
const recipient = window.ConversationController.get(destinationUuid);
|
||||||
|
if (!recipient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const taggedUuid = getTaggedConversationUuid(recipient.attributes);
|
||||||
|
if (!taggedUuid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
newStoryMessageRecipients.push({
|
newStoryMessageRecipients.push({
|
||||||
destinationUuid,
|
destinationAci: taggedUuid.aci,
|
||||||
|
destinationPni: taggedUuid.pni,
|
||||||
distributionListIds: Array.from(recipientData.distributionListIds),
|
distributionListIds: Array.from(recipientData.distributionListIds),
|
||||||
isAllowedToReply: recipientData.isAllowedToReply,
|
isAllowedToReply: recipientData.isAllowedToReply,
|
||||||
});
|
});
|
||||||
|
|
49
ts/util/getConversationUuid.ts
Normal file
49
ts/util/getConversationUuid.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { UUIDKind } from '../types/UUID';
|
||||||
|
import type { UUIDStringType, TaggedUUIDStringType } from '../types/UUID';
|
||||||
|
import type { ConversationAttributesType } from '../model-types.d';
|
||||||
|
import { strictAssert } from './assert';
|
||||||
|
|
||||||
|
export type MinimalConversationType = Pick<
|
||||||
|
ConversationAttributesType,
|
||||||
|
'uuid' | 'pni'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function getConversationUuid(
|
||||||
|
{ uuid, pni }: MinimalConversationType,
|
||||||
|
uuidKind = UUIDKind.ACI
|
||||||
|
): UUIDStringType | undefined {
|
||||||
|
if (uuidKind === UUIDKind.PNI) {
|
||||||
|
return pni;
|
||||||
|
}
|
||||||
|
|
||||||
|
strictAssert(
|
||||||
|
uuidKind === UUIDKind.ACI,
|
||||||
|
'getConversationUuid accepts either ACI or PNI uuid kind'
|
||||||
|
);
|
||||||
|
|
||||||
|
// When we know only PNI - we put PNI into both `uuid` and `pni` fields.
|
||||||
|
if (pni === uuid) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTaggedConversationUuid(
|
||||||
|
attributes: MinimalConversationType
|
||||||
|
): TaggedUUIDStringType | undefined {
|
||||||
|
const aci = getConversationUuid(attributes, UUIDKind.ACI);
|
||||||
|
if (aci) {
|
||||||
|
return { aci, pni: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
const pni = getConversationUuid(attributes, UUIDKind.PNI);
|
||||||
|
if (pni) {
|
||||||
|
return { aci: undefined, pni };
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
|
@ -57,12 +57,15 @@ export async function onStoryRecipientUpdate(
|
||||||
Set<string>
|
Set<string>
|
||||||
>();
|
>();
|
||||||
data.storyMessageRecipients.forEach(item => {
|
data.storyMessageRecipients.forEach(item => {
|
||||||
if (!item.destinationUuid) {
|
const { destinationAci, destinationPni } = item;
|
||||||
|
|
||||||
|
const destinationId = destinationAci || destinationPni;
|
||||||
|
if (!destinationId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const convo = window.ConversationController.get(
|
const convo = window.ConversationController.get(
|
||||||
normalizeUuid(item.destinationUuid, `${logId}.destinationUuid`)
|
normalizeUuid(destinationId, `${logId}.destinationId`)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!convo || !item.distributionListIds) {
|
if (!convo || !item.distributionListIds) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as log from '../logging/log';
|
||||||
import { SendMessageProtoError } from '../textsecure/Errors';
|
import { SendMessageProtoError } from '../textsecure/Errors';
|
||||||
import { getSendOptions } from './getSendOptions';
|
import { getSendOptions } from './getSendOptions';
|
||||||
import { handleMessageSend } from './handleMessageSend';
|
import { handleMessageSend } from './handleMessageSend';
|
||||||
|
import { getTaggedConversationUuid } from './getConversationUuid';
|
||||||
|
|
||||||
import type { CallbackResultType } from '../textsecure/Types.d';
|
import type { CallbackResultType } from '../textsecure/Types.d';
|
||||||
import type { ConversationModel } from '../models/conversations';
|
import type { ConversationModel } from '../models/conversations';
|
||||||
|
@ -77,7 +78,7 @@ export async function wrapWithSyncMessageSend({
|
||||||
await handleMessageSend(
|
await handleMessageSend(
|
||||||
sender.sendSyncMessage({
|
sender.sendSyncMessage({
|
||||||
destination: conversation.get('e164'),
|
destination: conversation.get('e164'),
|
||||||
destinationUuid: conversation.get('uuid'),
|
destinationUuid: getTaggedConversationUuid(conversation.attributes),
|
||||||
encodedDataMessage: dataMessage,
|
encodedDataMessage: dataMessage,
|
||||||
expirationStartTimestamp: null,
|
expirationStartTimestamp: null,
|
||||||
options,
|
options,
|
||||||
|
|
Loading…
Reference in a new issue