Flag deletes and replies to group stories as stories.
This commit is contained in:
parent
30b635cca2
commit
437d6c7a52
5 changed files with 59 additions and 15 deletions
|
@ -296,7 +296,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||||
.withExpiration(groupRecipient.getExpiresInSeconds())
|
.withExpiration(groupRecipient.getExpiresInSeconds())
|
||||||
.asGroupMessage(group)
|
.asGroupMessage(group)
|
||||||
.build();
|
.build();
|
||||||
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage, message.isUrgent());
|
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), null, destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage, message.isUrgent(), false);
|
||||||
} else {
|
} else {
|
||||||
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
|
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
|
||||||
}
|
}
|
||||||
|
@ -351,12 +351,14 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||||
|
|
||||||
return GroupSendUtil.sendResendableDataMessage(context,
|
return GroupSendUtil.sendResendableDataMessage(context,
|
||||||
groupRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
groupRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
||||||
|
null,
|
||||||
destinations,
|
destinations,
|
||||||
isRecipientUpdate,
|
isRecipientUpdate,
|
||||||
ContentHint.RESENDABLE,
|
ContentHint.RESENDABLE,
|
||||||
new MessageId(messageId, true),
|
new MessageId(messageId, true),
|
||||||
groupMessageBuilder.build(),
|
groupMessageBuilder.build(),
|
||||||
message.isUrgent());
|
message.isUrgent(),
|
||||||
|
message.getStoryType().isStory() || message.getParentStoryId() != null);
|
||||||
}
|
}
|
||||||
} catch (ServerRejectedException e) {
|
} catch (ServerRejectedException e) {
|
||||||
throw new UndeliverableMessageException(e);
|
throw new UndeliverableMessageException(e);
|
||||||
|
|
|
@ -238,12 +238,14 @@ public class ReactionSendJob extends BaseJob {
|
||||||
boolean includesSelf = nonSelfDestinations.size() != destinations.size();
|
boolean includesSelf = nonSelfDestinations.size() != destinations.size();
|
||||||
List<SendMessageResult> results = GroupSendUtil.sendResendableDataMessage(context,
|
List<SendMessageResult> results = GroupSendUtil.sendResendableDataMessage(context,
|
||||||
conversationRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
conversationRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
||||||
|
null,
|
||||||
nonSelfDestinations,
|
nonSelfDestinations,
|
||||||
false,
|
false,
|
||||||
ContentHint.RESENDABLE,
|
ContentHint.RESENDABLE,
|
||||||
messageId,
|
messageId,
|
||||||
dataMessage,
|
dataMessage,
|
||||||
true);
|
true,
|
||||||
|
false);
|
||||||
|
|
||||||
if (includesSelf) {
|
if (includesSelf) {
|
||||||
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));
|
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.thoughtcrime.securesms.jobs;
|
package org.thoughtcrime.securesms.jobs;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
@ -10,8 +11,11 @@ import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||||
|
import org.thoughtcrime.securesms.database.model.StoryType;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
|
@ -29,6 +33,7 @@ import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -157,7 +162,10 @@ public class RemoteDeleteSendJob extends BaseJob {
|
||||||
List<Recipient> eligible = RecipientUtil.getEligibleForSending(Stream.of(recipients).map(Recipient::resolved).toList());
|
List<Recipient> eligible = RecipientUtil.getEligibleForSending(Stream.of(recipients).map(Recipient::resolved).toList());
|
||||||
List<RecipientId> skipped = Stream.of(SetUtil.difference(possible, eligible)).map(Recipient::getId).toList();
|
List<RecipientId> skipped = Stream.of(SetUtil.difference(possible, eligible)).map(Recipient::getId).toList();
|
||||||
|
|
||||||
GroupSendJobHelper.SendResult sendResult = deliver(conversationRecipient, eligible, targetSentTimestamp);
|
boolean isForStory = message.isMms() && (((MmsMessageRecord) message).getStoryType().isStory() || ((MmsMessageRecord) message).getParentStoryId() != null);
|
||||||
|
DistributionListId distributionListId = isForStory ? message.getRecipient().getDistributionListId().orElse(null) : null;
|
||||||
|
|
||||||
|
GroupSendJobHelper.SendResult sendResult = deliver(conversationRecipient, eligible, targetSentTimestamp, isForStory, distributionListId);
|
||||||
|
|
||||||
for (Recipient completion : sendResult.completed) {
|
for (Recipient completion : sendResult.completed) {
|
||||||
recipients.remove(completion.getId());
|
recipients.remove(completion.getId());
|
||||||
|
@ -196,7 +204,11 @@ public class RemoteDeleteSendJob extends BaseJob {
|
||||||
Log.w(TAG, "Failed to send remote delete to all recipients! (" + (initialRecipientCount - recipients.size() + "/" + initialRecipientCount + ")") );
|
Log.w(TAG, "Failed to send remote delete to all recipients! (" + (initialRecipientCount - recipients.size() + "/" + initialRecipientCount + ")") );
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull GroupSendJobHelper.SendResult deliver(@NonNull Recipient conversationRecipient, @NonNull List<Recipient> destinations, long targetSentTimestamp)
|
private @NonNull GroupSendJobHelper.SendResult deliver(@NonNull Recipient conversationRecipient,
|
||||||
|
@NonNull List<Recipient> destinations,
|
||||||
|
long targetSentTimestamp,
|
||||||
|
boolean isForStory,
|
||||||
|
@Nullable DistributionListId distributionListId)
|
||||||
throws IOException, UntrustedIdentityException
|
throws IOException, UntrustedIdentityException
|
||||||
{
|
{
|
||||||
SignalServiceDataMessage.Builder dataMessageBuilder = SignalServiceDataMessage.newBuilder()
|
SignalServiceDataMessage.Builder dataMessageBuilder = SignalServiceDataMessage.newBuilder()
|
||||||
|
@ -210,12 +222,14 @@ public class RemoteDeleteSendJob extends BaseJob {
|
||||||
SignalServiceDataMessage dataMessage = dataMessageBuilder.build();
|
SignalServiceDataMessage dataMessage = dataMessageBuilder.build();
|
||||||
List<SendMessageResult> results = GroupSendUtil.sendResendableDataMessage(context,
|
List<SendMessageResult> results = GroupSendUtil.sendResendableDataMessage(context,
|
||||||
conversationRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
conversationRecipient.getGroupId().map(GroupId::requireV2).orElse(null),
|
||||||
|
distributionListId,
|
||||||
destinations,
|
destinations,
|
||||||
false,
|
false,
|
||||||
ContentHint.RESENDABLE,
|
ContentHint.RESENDABLE,
|
||||||
new MessageId(messageId, isMms),
|
new MessageId(messageId, isMms),
|
||||||
dataMessage,
|
dataMessage,
|
||||||
true);
|
true,
|
||||||
|
isForStory);
|
||||||
|
|
||||||
return GroupSendJobHelper.getCompletedSends(destinations, results);
|
return GroupSendJobHelper.getCompletedSends(destinations, results);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMess
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
||||||
|
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||||
import org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException;
|
import org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException;
|
||||||
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
||||||
import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener;
|
import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener;
|
||||||
|
@ -82,19 +83,41 @@ public final class GroupSendUtil {
|
||||||
*
|
*
|
||||||
* @param groupId The groupId of the group you're sending to, or null if you're sending to a collection of recipients not joined by a group.
|
* @param groupId The groupId of the group you're sending to, or null if you're sending to a collection of recipients not joined by a group.
|
||||||
* @param isRecipientUpdate True if you've already sent this message to some recipients in the past, otherwise false.
|
* @param isRecipientUpdate True if you've already sent this message to some recipients in the past, otherwise false.
|
||||||
|
* @param isForStory True if the message is related to a story, and should be sent with the story flag on the envelope
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static List<SendMessageResult> sendResendableDataMessage(@NonNull Context context,
|
public static List<SendMessageResult> sendResendableDataMessage(@NonNull Context context,
|
||||||
@Nullable GroupId.V2 groupId,
|
@Nullable GroupId.V2 groupId,
|
||||||
|
@Nullable DistributionListId distributionListId,
|
||||||
@NonNull List<Recipient> allTargets,
|
@NonNull List<Recipient> allTargets,
|
||||||
boolean isRecipientUpdate,
|
boolean isRecipientUpdate,
|
||||||
ContentHint contentHint,
|
ContentHint contentHint,
|
||||||
@NonNull MessageId messageId,
|
@NonNull MessageId messageId,
|
||||||
@NonNull SignalServiceDataMessage message,
|
@NonNull SignalServiceDataMessage message,
|
||||||
boolean urgent)
|
boolean urgent,
|
||||||
|
boolean isForStory)
|
||||||
throws IOException, UntrustedIdentityException
|
throws IOException, UntrustedIdentityException
|
||||||
{
|
{
|
||||||
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, false, DataSendOperation.resendable(message, contentHint, messageId, urgent), null);
|
Preconditions.checkArgument(groupId == null || distributionListId == null, "Cannot supply both a groupId and a distributionListId!");
|
||||||
|
|
||||||
|
DistributionId distributionId = groupId != null ? getDistributionId(groupId) : getDistributionId(distributionListId);
|
||||||
|
|
||||||
|
return sendMessage(context, groupId, distributionId, messageId, allTargets, isRecipientUpdate, isForStory, DataSendOperation.resendable(message, contentHint, messageId, urgent, isForStory), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
public static List<SendMessageResult> sendResendableStoryRelatedMessage(@NonNull Context context,
|
||||||
|
@Nullable GroupId.V2 groupId,
|
||||||
|
@NonNull DistributionListId distributionListId,
|
||||||
|
@NonNull List<Recipient> allTargets,
|
||||||
|
boolean isRecipientUpdate,
|
||||||
|
ContentHint contentHint,
|
||||||
|
@NonNull MessageId messageId,
|
||||||
|
@NonNull SignalServiceDataMessage message,
|
||||||
|
boolean urgent)
|
||||||
|
throws IOException, UntrustedIdentityException
|
||||||
|
{
|
||||||
|
return sendMessage(context, groupId, getDistributionId(distributionListId), messageId, allTargets, isRecipientUpdate, true, DataSendOperation.resendable(message, contentHint, messageId, urgent, true), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -441,21 +464,23 @@ public final class GroupSendUtil {
|
||||||
private final MessageId relatedMessageId;
|
private final MessageId relatedMessageId;
|
||||||
private final boolean resendable;
|
private final boolean resendable;
|
||||||
private final boolean urgent;
|
private final boolean urgent;
|
||||||
|
private final boolean isForStory;
|
||||||
|
|
||||||
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent) {
|
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent, boolean isForStory) {
|
||||||
return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent);
|
return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent, isForStory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
|
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
|
||||||
return new DataSendOperation(message, contentHint, false, null, urgent);
|
return new DataSendOperation(message, contentHint, false, null, urgent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent) {
|
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent, boolean isForStory) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.contentHint = contentHint;
|
this.contentHint = contentHint;
|
||||||
this.resendable = resendable;
|
this.resendable = resendable;
|
||||||
this.relatedMessageId = relatedMessageId;
|
this.relatedMessageId = relatedMessageId;
|
||||||
this.urgent = urgent;
|
this.urgent = urgent;
|
||||||
|
this.isForStory = isForStory;
|
||||||
|
|
||||||
if (resendable && relatedMessageId == null) {
|
if (resendable && relatedMessageId == null) {
|
||||||
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
|
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
|
||||||
|
@ -471,7 +496,7 @@ public final class GroupSendUtil {
|
||||||
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
||||||
{
|
{
|
||||||
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
|
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
|
||||||
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent);
|
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent, isForStory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -475,14 +475,15 @@ public class SignalServiceMessageSender {
|
||||||
ContentHint contentHint,
|
ContentHint contentHint,
|
||||||
SignalServiceDataMessage message,
|
SignalServiceDataMessage message,
|
||||||
SenderKeyGroupEvents sendEvents,
|
SenderKeyGroupEvents sendEvents,
|
||||||
boolean urgent)
|
boolean urgent,
|
||||||
|
boolean isForStory)
|
||||||
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
|
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
|
||||||
{
|
{
|
||||||
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
|
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
|
||||||
|
|
||||||
Content content = createMessageContent(message);
|
Content content = createMessageContent(message);
|
||||||
Optional<byte[]> groupId = message.getGroupId();
|
Optional<byte[]> groupId = message.getGroupId();
|
||||||
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents, urgent, false);
|
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents, urgent, isForStory);
|
||||||
|
|
||||||
sendEvents.onMessageSent();
|
sendEvents.onMessageSent();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue