Process incoming story messages

This commit is contained in:
Josh Perez 2022-03-04 16:14:52 -05:00 committed by GitHub
parent df7cdfacc7
commit eb91eb6fec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
84 changed files with 4382 additions and 652 deletions

View file

@ -72,6 +72,7 @@ import type { Storage } from './Storage';
import { WarnOnlyError } from './Errors';
import * as Bytes from '../Bytes';
import type {
ProcessedAttachment,
ProcessedDataMessage,
ProcessedSyncMessage,
ProcessedSent,
@ -107,6 +108,7 @@ import {
GroupSyncEvent,
} from './messageReceiverEvents';
import * as log from '../logging/log';
import * as durations from '../util/durations';
import { areArraysMatchingSets } from '../util/areArraysMatchingSets';
const GROUPV1_ID_LENGTH = 16;
@ -1787,6 +1789,66 @@ export default class MessageReceiver
return this.dispatchAndWait(ev);
}
private async handleStoryMessage(
envelope: UnsealedEnvelope,
msg: Proto.IStoryMessage
): Promise<void> {
const logId = this.getEnvelopeId(envelope);
log.info('MessageReceiver.handleStoryMessage', logId);
const attachments: Array<ProcessedAttachment> = [];
if (msg.fileAttachment) {
const attachment = processAttachment(msg.fileAttachment);
attachments.push(attachment);
}
if (msg.textAttachment) {
log.error(
'MessageReceiver.handleStoryMessage: Got a textAttachment, cannot handle it',
logId
);
return;
}
const expireTimer = envelope.timestamp + durations.DAY - Date.now();
if (expireTimer <= 0) {
log.info(
'MessageReceiver.handleStoryMessage: story already expired',
logId
);
this.removeFromCache(envelope);
return;
}
const ev = new MessageEvent(
{
source: envelope.source,
sourceUuid: envelope.sourceUuid,
sourceDevice: envelope.sourceDevice,
timestamp: envelope.timestamp,
serverGuid: envelope.serverGuid,
serverTimestamp: envelope.serverTimestamp,
unidentifiedDeliveryReceived: Boolean(
envelope.unidentifiedDeliveryReceived
),
message: {
attachments,
expireTimer,
flags: 0,
isStory: true,
isViewOnce: false,
timestamp: envelope.timestamp,
},
receivedAtCounter: envelope.receivedAtCounter,
receivedAtDate: envelope.receivedAtDate,
},
this.removeFromCache.bind(this, envelope)
);
return this.dispatchAndWait(ev);
}
private async handleDataMessage(
envelope: UnsealedEnvelope,
msg: Proto.IDataMessage
@ -1794,14 +1856,6 @@ export default class MessageReceiver
const logId = this.getEnvelopeId(envelope);
log.info('MessageReceiver.handleDataMessage', logId);
if (msg.storyContext) {
log.info(
`MessageReceiver.handleDataMessage/${logId}: Dropping incoming dataMessage with storyContext field`
);
this.removeFromCache(envelope);
return undefined;
}
let p: Promise<void> = Promise.resolve();
// eslint-disable-next-line no-bitwise
const destination = envelope.sourceUuid;
@ -1993,11 +2047,7 @@ export default class MessageReceiver
return;
}
if (content.storyMessage) {
const logId = this.getEnvelopeId(envelope);
log.info(
`innerHandleContentMessage/${logId}: Dropping incoming message with storyMessage field`
);
this.removeFromCache(envelope);
await this.handleStoryMessage(envelope, content.storyMessage);
return;
}

View file

@ -191,6 +191,7 @@ export type MessageOptionsType = {
timestamp: number;
mentions?: BodyRangesType;
groupCallUpdate?: GroupCallUpdateType;
storyContextTimestamp?: number;
};
export type GroupSendOptionsType = {
attachments?: Array<AttachmentType>;
@ -208,6 +209,7 @@ export type GroupSendOptionsType = {
timestamp: number;
mentions?: BodyRangesType;
groupCallUpdate?: GroupCallUpdateType;
storyContextTimestamp?: number;
};
class Message {
@ -252,6 +254,8 @@ class Message {
groupCallUpdate?: GroupCallUpdateType;
storyContextTimestamp?: number;
constructor(options: MessageOptionsType) {
this.attachments = options.attachments || [];
this.body = options.body;
@ -270,6 +274,7 @@ class Message {
this.deletedForEveryoneTimestamp = options.deletedForEveryoneTimestamp;
this.mentions = options.mentions;
this.groupCallUpdate = options.groupCallUpdate;
this.storyContextTimestamp = options.storyContextTimestamp;
if (!(this.recipients instanceof Array)) {
throw new Error('Invalid recipient list');
@ -470,6 +475,18 @@ class Message {
proto.groupCallUpdate = groupCallUpdate;
}
if (this.storyContextTimestamp) {
const { StoryContext } = Proto.DataMessage;
const storyContext = new StoryContext();
storyContext.authorUuid = String(
window.textsecure.storage.user.getCheckedUuid()
);
storyContext.sentTimestamp = this.storyContextTimestamp;
proto.storyContext = storyContext;
}
this.dataMessage = proto;
return proto;
}
@ -779,6 +796,7 @@ export default class MessageSender {
quote,
reaction,
sticker,
storyContextTimestamp,
timestamp,
} = options;
@ -833,6 +851,7 @@ export default class MessageSender {
reaction,
recipients,
sticker,
storyContextTimestamp,
timestamp,
};
}
@ -1024,6 +1043,7 @@ export default class MessageSender {
groupId,
profileKey,
options,
storyContextTimestamp,
}: Readonly<{
identifier: string;
messageText: string | undefined;
@ -1038,6 +1058,7 @@ export default class MessageSender {
contentHint: number;
groupId: string | undefined;
profileKey?: Uint8Array;
storyContextTimestamp?: number;
options?: SendOptionsType;
}>): Promise<CallbackResultType> {
return this.sendMessage({
@ -1053,6 +1074,7 @@ export default class MessageSender {
deletedForEveryoneTimestamp,
expireTimer,
profileKey,
storyContextTimestamp,
},
contentHint,
groupId,

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { SignalService as Proto } from '../protobuf';
@ -183,6 +183,8 @@ export type ProcessedBodyRange = Proto.DataMessage.IBodyRange;
export type ProcessedGroupCallUpdate = Proto.DataMessage.IGroupCallUpdate;
export type ProcessedStoryContext = Proto.DataMessage.IStoryContext;
export type ProcessedDataMessage = {
body?: string;
attachments: ReadonlyArray<ProcessedAttachment>;
@ -197,11 +199,13 @@ export type ProcessedDataMessage = {
preview?: ReadonlyArray<ProcessedPreview>;
sticker?: ProcessedSticker;
requiredProtocolVersion?: number;
isStory?: boolean;
isViewOnce: boolean;
reaction?: ProcessedReaction;
delete?: ProcessedDelete;
bodyRanges?: ReadonlyArray<ProcessedBodyRange>;
groupCallUpdate?: ProcessedGroupCallUpdate;
storyContext?: ProcessedStoryContext;
};
export type ProcessedUnidentifiedDeliveryStatus = Omit<

View file

@ -661,6 +661,7 @@ export type CapabilitiesType = {
'gv1-migration': boolean;
senderKey: boolean;
changeNumber: boolean;
stories: boolean;
};
export type CapabilitiesUploadType = {
announcementGroup: true;
@ -668,6 +669,7 @@ export type CapabilitiesUploadType = {
'gv1-migration': true;
senderKey: true;
changeNumber: true;
stories: true;
};
type StickerPackManifestType = Uint8Array;
@ -1726,6 +1728,7 @@ export function initialize({
'gv1-migration': true,
senderKey: true,
changeNumber: true,
stories: true,
};
const { accessKey } = options;

View file

@ -280,6 +280,7 @@ export async function processDataMessage(
delete: processDelete(message.delete),
bodyRanges: message.bodyRanges ?? [],
groupCallUpdate: dropNull(message.groupCallUpdate),
storyContext: dropNull(message.storyContext),
};
const isEndSession = Boolean(result.flags & FLAGS.END_SESSION);