Send stories to groups capability

This commit is contained in:
Josh Perez 2022-08-08 23:26:21 -04:00 committed by GitHub
parent 62962e4950
commit 2f5dd73e58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 308 additions and 163 deletions

View file

@ -18,12 +18,15 @@ import {
conversationQueueJobEnum,
} from '../jobs/conversationJobQueue';
import { formatJobForInsert } from '../jobs/formatJobForInsert';
import { getRecipients } from './getRecipients';
import { getSignalConnections } from './getSignalConnections';
import { incrementMessageCounter } from './incrementMessageCounter';
import { isGroupV2 } from './whatTypeOfConversation';
import { isNotNil } from './isNotNil';
export async function sendStoryMessage(
listIds: Array<string>,
conversationIds: Array<string>,
attachment: AttachmentType
): Promise<void> {
const { messaging } = window.textsecure;
@ -41,9 +44,9 @@ export async function sendStoryMessage(
)
).filter(isNotNil);
if (!distributionLists.length) {
log.info(
'stories.sendStoryMessage: no distribution lists found for',
if (!distributionLists.length && !conversationIds.length) {
log.warn(
'stories.sendStoryMessage: Dropping send. no conversations to send to and no distribution lists found for',
listIds
);
return;
@ -127,43 +130,115 @@ export async function sendStoryMessage(
// * Gather all the job data we'll be sending to the sendStory job
// * Create the message for each distribution list
const messagesToSave: Array<MessageAttributesType> = await Promise.all(
distributionLists.map(async distributionList => {
const sendStateByConversationId = sendStateByListId.get(
distributionList.id
);
if (!sendStateByConversationId) {
log.warn(
'stories.sendStoryMessage: No sendStateByConversationId for distribution list',
const distributionListMessages: Array<MessageAttributesType> =
await Promise.all(
distributionLists.map(async distributionList => {
const sendStateByConversationId = sendStateByListId.get(
distributionList.id
);
if (!sendStateByConversationId) {
log.warn(
'stories.sendStoryMessage: No sendStateByConversationId for distribution list',
distributionList.id
);
}
return window.Signal.Migrations.upgradeMessageSchema({
attachments,
conversationId: ourConversation.id,
expireTimer: DAY / SECOND,
id: UUID.generate().toString(),
readStatus: ReadStatus.Read,
received_at: incrementMessageCounter(),
received_at_ms: timestamp,
seenStatus: SeenStatus.NotApplicable,
sendStateByConversationId,
sent_at: timestamp,
source: window.textsecure.storage.user.getNumber(),
sourceUuid: window.textsecure.storage.user.getUuid()?.toString(),
storyDistributionListId: distributionList.id,
timestamp,
type: 'story',
});
})
);
const groupV2MessagesByConversationId = new Map<
string,
MessageAttributesType
>();
await Promise.all(
conversationIds.map(async conversationId => {
const group = window.ConversationController.get(conversationId);
if (!group) {
log.warn(
'stories.sendStoryMessage: No group found for id',
conversationId
);
return;
}
return window.Signal.Migrations.upgradeMessageSchema({
attachments,
conversationId: ourConversation.id,
expireTimer: DAY / SECOND,
id: UUID.generate().toString(),
readStatus: ReadStatus.Read,
received_at: incrementMessageCounter(),
received_at_ms: timestamp,
seenStatus: SeenStatus.NotApplicable,
sendStateByConversationId,
sent_at: timestamp,
source: window.textsecure.storage.user.getNumber(),
sourceUuid: window.textsecure.storage.user.getUuid()?.toString(),
storyDistributionListId: distributionList.id,
timestamp,
type: 'story',
});
if (!isGroupV2(group.attributes)) {
log.warn(
'stories.sendStoryMessage: Conversation we tried to send to is not a groupV2',
conversationId
);
return;
}
const myId = window.ConversationController.getOurConversationIdOrThrow();
const sendState = {
status: SendStatus.Pending,
updatedAt: timestamp,
};
const sendStateByConversationId = getRecipients(group.attributes).reduce(
(acc, id) => {
const conversation = window.ConversationController.get(id);
if (!conversation) {
return acc;
}
return {
...acc,
[conversation.id]: sendState,
};
},
{
[myId]: sendState,
}
);
const messageAttributes =
await window.Signal.Migrations.upgradeMessageSchema({
attachments,
conversationId,
expireTimer: DAY / SECOND,
id: UUID.generate().toString(),
readStatus: ReadStatus.Read,
received_at: incrementMessageCounter(),
received_at_ms: timestamp,
seenStatus: SeenStatus.NotApplicable,
sendStateByConversationId,
sent_at: timestamp,
source: window.textsecure.storage.user.getNumber(),
sourceUuid: window.textsecure.storage.user.getUuid()?.toString(),
timestamp,
type: 'story',
});
groupV2MessagesByConversationId.set(conversationId, messageAttributes);
})
);
// For distribution lists:
// * Save the message model
// * Add the message to the conversation
await Promise.all(
messagesToSave.map(messageAttributes => {
distributionListMessages.map(messageAttributes => {
const model = new window.Whisper.Message(messageAttributes);
const message = window.MessageController.register(model.id, model);
@ -177,13 +252,14 @@ export async function sendStoryMessage(
})
);
// * Send to the distribution lists
// * Place into job queue
// * Save the job
await conversationJobQueue.add(
{
type: conversationQueueJobEnum.enum.Story,
conversationId: ourConversation.id,
messageIds: messagesToSave.map(m => m.id),
messageIds: distributionListMessages.map(m => m.id),
timestamp,
},
async jobToInsert => {
@ -191,4 +267,45 @@ export async function sendStoryMessage(
await dataInterface.insertJob(formatJobForInsert(jobToInsert));
}
);
// * Send to groups
// * Save the message models
// * Add message to group conversation
await Promise.all(
conversationIds.map(conversationId => {
const messageAttributes =
groupV2MessagesByConversationId.get(conversationId);
if (!messageAttributes) {
log.warn(
'stories.sendStoryMessage: Trying to send a group story but it did not exist? This is unexpected. Not sending.',
conversationId
);
return;
}
return conversationJobQueue.add(
{
type: conversationQueueJobEnum.enum.Story,
conversationId,
messageIds: [messageAttributes.id],
timestamp,
},
async jobToInsert => {
const model = new window.Whisper.Message(messageAttributes);
const message = window.MessageController.register(model.id, model);
const conversation = message.getConversation();
conversation?.addSingleMessage(model, { isJustSent: true });
log.info(`stories.sendStoryMessage: saving message ${message.id}`);
await dataInterface.saveMessage(message.attributes, {
forceSave: true,
jobToInsert,
ourUuid: window.textsecure.storage.user.getCheckedUuid().toString(),
});
}
);
})
);
}