feat: block sending disappearing messages of the wrong type in different conversations,

improved disappear after send or read logic, disable legacy sending for now
pull/2660/head
William Grant 2 years ago
parent 7d0673f7f2
commit 255b6225c9

@ -96,7 +96,10 @@ import {
import { sogsV3FetchPreviewAndSaveIt } from '../session/apis/open_group_api/sogsv3/sogsV3FetchFile'; import { sogsV3FetchPreviewAndSaveIt } from '../session/apis/open_group_api/sogsv3/sogsV3FetchFile';
import { Reaction } from '../types/Reaction'; import { Reaction } from '../types/Reaction';
import { Reactions } from '../util/reactions'; import { Reactions } from '../util/reactions';
import { DisappearingMessageConversationType } from '../util/expiringMessages'; import {
DisappearingMessageConversationType,
DisappearingMessageType,
} from '../util/expiringMessages';
export class ConversationModel extends Backbone.Model<ConversationAttributes> { export class ConversationModel extends Backbone.Model<ConversationAttributes> {
public updateLastMessage: () => any; public updateLastMessage: () => any;
@ -558,12 +561,14 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (this.isPublic() && !this.isOpenGroupV2()) { if (this.isPublic() && !this.isOpenGroupV2()) {
throw new Error('Only opengroupv2 are supported now'); throw new Error('Only opengroupv2 are supported now');
} }
// an OpenGroupV2 message is just a visible message // an OpenGroupV2 message is just a visible message
const chatMessageParams: VisibleMessageParams = { const chatMessageParams: VisibleMessageParams = {
body, body,
identifier: id, identifier: id,
timestamp: sentAt, timestamp: sentAt,
attachments, attachments,
// TODO not supported in open groups
expirationType, expirationType,
expireTimer, expireTimer,
preview: preview ? [preview] : [], preview: preview ? [preview] : [],
@ -617,10 +622,11 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const destinationPubkey = new PubKey(destination); const destinationPubkey = new PubKey(destination);
// TODO check expiration types per different conversation setting
if (this.isPrivate()) { if (this.isPrivate()) {
if (this.isMe()) { if (this.isMe()) {
if (!this.isDisappearingMode('deleteAfterSend')) {
return;
}
chatMessageParams.syncTarget = this.id; chatMessageParams.syncTarget = this.id;
const chatMessageMe = new VisibleMessage(chatMessageParams); const chatMessageMe = new VisibleMessage(chatMessageParams);
@ -639,17 +645,21 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
expirationType, expirationType,
expireTimer, expireTimer,
}); });
// we need the return await so that errors are caught in the catch {} // we need the return await so that errors are caught in the catch {}
await getMessageQueue().sendToPubKey(destinationPubkey, groupInviteMessage); await getMessageQueue().sendToPubKey(destinationPubkey, groupInviteMessage);
return; return;
} }
const chatMessagePrivate = new VisibleMessage(chatMessageParams);
const chatMessagePrivate = new VisibleMessage(chatMessageParams);
await getMessageQueue().sendToPubKey(destinationPubkey, chatMessagePrivate); await getMessageQueue().sendToPubKey(destinationPubkey, chatMessagePrivate);
return; return;
} }
if (this.isMediumGroup()) { if (this.isMediumGroup()) {
if (!this.isDisappearingMode('deleteAfterSend')) {
return;
}
const chatMessageMediumGroup = new VisibleMessage(chatMessageParams); const chatMessageMediumGroup = new VisibleMessage(chatMessageParams);
const closedGroupVisibleMessage = new ClosedGroupVisibleMessage({ const closedGroupVisibleMessage = new ClosedGroupVisibleMessage({
chatMessage: chatMessageMediumGroup, chatMessage: chatMessageMediumGroup,
@ -2216,6 +2226,22 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
return []; return [];
} }
private isDisappearingMode(mode: DisappearingMessageType) {
// TODO support legacy mode
const success =
this.get('expirationType') &&
this.get('expirationType') !== 'off' &&
mode === 'deleteAfterRead'
? this.get('expirationType') === 'deleteAfterRead'
: this.get('expirationType') === 'deleteAfterSend';
if (!success) {
window.log.info(`WIP: This message should be disappear after ${mode}`, this);
}
return success;
}
} }
const throttledAllConversationsDispatch = debounce( const throttledAllConversationsDispatch = debounce(

@ -789,6 +789,7 @@ export async function handleDataExtractionNotification(
unread: 1, // 1 means unread unread: 1, // 1 means unread
expirationType: expirationType !== 'off' ? expirationType : undefined, expirationType: expirationType !== 'off' ? expirationType : undefined,
expireTimer: convo.get('expireTimer') ? convo.get('expireTimer') : 0, expireTimer: convo.get('expireTimer') ? convo.get('expireTimer') : 0,
// TODO should this only be for delete after send?
expirationStartTimestamp: setExpirationStartTimestamp(expirationType), expirationStartTimestamp: setExpirationStartTimestamp(expirationType),
}); });
convo.updateLastMessage(); convo.updateLastMessage();

@ -1,5 +1,6 @@
import { SignalService } from '../../../protobuf'; import { SignalService } from '../../../protobuf';
import { DisappearingMessageType } from '../../../util/expiringMessages'; import { DisappearingMessageType } from '../../../util/expiringMessages';
import { DURATION, TTL_DEFAULT } from '../../constants';
import { ContentMessage } from './ContentMessage'; import { ContentMessage } from './ContentMessage';
import { MessageParams } from './Message'; import { MessageParams } from './Message';
@ -31,4 +32,15 @@ export class ExpirableMessage extends ContentMessage {
public getDisappearingMessageType(): DisappearingMessageType | undefined { public getDisappearingMessageType(): DisappearingMessageType | undefined {
return this.expirationType; return this.expirationType;
} }
public ttl(): number {
switch (this.expirationType) {
case 'deleteAfterSend':
return this.expireTimer ? this.expireTimer * DURATION.SECONDS : TTL_DEFAULT.TTL_MAX;
case 'deleteAfterRead':
return TTL_DEFAULT.TTL_MAX;
default:
return TTL_DEFAULT.TTL_MAX;
}
}
} }

@ -64,10 +64,10 @@ export class ExpirationTimerUpdateMessage extends DataMessage {
data.syncTarget = this.syncTarget; data.syncTarget = this.syncTarget;
} }
// TODO Legacy support remove 2 weeks after the release // TODO should only happen in legacy mode and should be cancelled out once we have trigger the unix timestamp
if (this.expireTimer) { // if (this.expireTimer) {
data.expireTimer = this.expireTimer; // data.expireTimer = this.expireTimer;
} // }
return data; return data;
} }

@ -3,7 +3,6 @@ import { isEmpty } from 'lodash';
import { SignalService } from '../../../../protobuf'; import { SignalService } from '../../../../protobuf';
import { LokiProfile } from '../../../../types/Message'; import { LokiProfile } from '../../../../types/Message';
import { Reaction } from '../../../../types/Reaction'; import { Reaction } from '../../../../types/Reaction';
import { DURATION, TTL_DEFAULT } from '../../../constants';
import { ExpirableMessage, ExpirableMessageParams } from '../ExpirableMessage'; import { ExpirableMessage, ExpirableMessageParams } from '../ExpirableMessage';
interface AttachmentPointerCommon { interface AttachmentPointerCommon {
@ -123,9 +122,10 @@ export class VisibleMessage extends ExpirableMessage {
dataMessage.attachments = this.attachments || []; dataMessage.attachments = this.attachments || [];
if (this.expireTimer) { // TODO should only happen in legacy mode and should be cancelled out once we have trigger the unix timestamp
dataMessage.expireTimer = this.expireTimer; // if (this.expireTimer) {
} // dataMessage.expireTimer = this.expireTimer;
// }
if (this.preview) { if (this.preview) {
dataMessage.preview = this.preview; dataMessage.preview = this.preview;
@ -192,18 +192,6 @@ export class VisibleMessage extends ExpirableMessage {
public isEqual(comparator: VisibleMessage): boolean { public isEqual(comparator: VisibleMessage): boolean {
return this.identifier === comparator.identifier && this.timestamp === comparator.timestamp; return this.identifier === comparator.identifier && this.timestamp === comparator.timestamp;
} }
// TODO should this be on the Expirable message? Probably
public ttl(): number {
switch (this.expirationType) {
case 'deleteAfterSend':
return this.expireTimer ? this.expireTimer * DURATION.SECONDS : TTL_DEFAULT.TTL_MAX;
case 'deleteAfterRead':
return TTL_DEFAULT.TTL_MAX;
default:
return TTL_DEFAULT.TTL_MAX;
}
}
} }
export function buildProfileForOutgoingMessage(params: { lokiProfile?: LokiProfile }) { export function buildProfileForOutgoingMessage(params: { lokiProfile?: LokiProfile }) {

@ -111,6 +111,7 @@ export async function send(
found.set({ sent_at: networkTimestamp }); found.set({ sent_at: networkTimestamp });
await found.commit(); await found.commit();
} }
await MessageSender.sendMessageToSnode( await MessageSender.sendMessageToSnode(
recipient.key, recipient.key,
data, data,

@ -71,7 +71,7 @@ async function handleMessageSentSuccess(
!isClosedGroupMessage && !isClosedGroupMessage &&
!fetchedMessage.get('synced') && !fetchedMessage.get('synced') &&
!fetchedMessage.get('sentSync') && !fetchedMessage.get('sentSync') &&
// TODO not 100% sure about this. Might need to change for synced expiries // TODO not 100% on this. Handling syncing later
!fetchedMessage.get('expirationType'); !fetchedMessage.get('expirationType');
// A message is synced if we triggered a sync message (sentSync) // A message is synced if we triggered a sync message (sentSync)
@ -132,15 +132,21 @@ async function handleMessageSentSuccess(
sent_to: sentTo, sent_to: sentTo,
sent: true, sent: true,
sent_at: effectiveTimestamp, sent_at: effectiveTimestamp,
// TODO message status overrides this for some reason in the UI, message still disappears though
unread: fetchedMessage.get('expirationType') === 'deleteAfterRead' ? 1 : 0,
}); });
if (!shouldMarkMessageAsSynced) { if (
fetchedMessage.get('expirationType') === 'deleteAfterSend' &&
Boolean(fetchedMessage.get('expirationStartTimestamp')) === false
) {
const expirationType = fetchedMessage.get('expirationType'); const expirationType = fetchedMessage.get('expirationType');
if (expirationType && Boolean(fetchedMessage.get('expirationStartTimestamp')) === false) { if (expirationType === 'deleteAfterSend') {
// TODO message timer start is a few seconds less than the amount due to it's position in the pipeline, not sure on a fix yet
fetchedMessage.set({ fetchedMessage.set({
expirationStartTimestamp: setExpirationStartTimestamp( expirationStartTimestamp: setExpirationStartTimestamp(
expirationType, expirationType,
expirationType === 'deleteAfterSend' ? effectiveTimestamp : undefined fetchedMessage.get('sent_at')
), ),
}); });
} }
@ -179,6 +185,8 @@ async function handleMessageSentFailure(
sent: true, sent: true,
}); });
// We don't set the expirationStartTimestamp on a disappearing message here incase the user wishes to try and resend the message
await fetchedMessage.commit(); await fetchedMessage.commit();
await fetchedMessage.getConversation()?.updateLastMessage(); await fetchedMessage.getConversation()?.updateLastMessage();
} }

Loading…
Cancel
Save