Ignore duplicate stories in sync messages.

This commit is contained in:
Alex Hart 2022-05-12 11:45:19 -03:00 committed by Cody Henthorne
parent 0fe0765e63
commit 9ed3f95ab8
6 changed files with 73 additions and 38 deletions

View file

@ -1,37 +0,0 @@
package org.thoughtcrime.securesms.database
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.signal.core.util.money.FiatMoney
import org.thoughtcrime.securesms.database.model.DonationReceiptRecord
import java.math.BigDecimal
import java.util.Currency
class DonationReceiptDatabaseTest {
private val records = listOf(
DonationReceiptRecord.createForBoost(FiatMoney(BigDecimal.valueOf(100), Currency.getInstance("USD"))),
DonationReceiptRecord.createForBoost(FiatMoney(BigDecimal.valueOf(200), Currency.getInstance("USD")))
)
@Test
fun givenNoReceipts_whenICheckHasReceipts_thenIExpectFalse() {
assertFalse(SignalDatabase.donationReceipts.hasReceipts())
}
@Test
fun givenOneReceipt_whenICheckHasReceipts_thenIExpectTrue() {
SignalDatabase.donationReceipts.addReceipt(records.first())
assertTrue(SignalDatabase.donationReceipts.hasReceipts())
}
@Test
fun givenMultipleReceipts_whenICheckHasReceipts_thenIExpectTrue() {
records.forEach {
SignalDatabase.donationReceipts.addReceipt(it)
}
assertTrue(SignalDatabase.donationReceipts.hasReceipts())
}
}

View file

@ -191,4 +191,51 @@ class MmsDatabaseTest_stories {
assertEquals(unviewedIds.reversed() + interspersedIds.reversed(), resultOrderedIds) assertEquals(unviewedIds.reversed() + interspersedIds.reversed(), resultOrderedIds)
} }
@Test
fun givenNoStories_whenICheckIsOutgoingStoryAlreadyInDatabase_thenIExpectFalse() {
// WHEN
val result = mms.isOutgoingStoryAlreadyInDatabase(recipients[0], 200)
// THEN
assertFalse(result)
}
@Test
fun givenNoOutgoingStories_whenICheckIsOutgoingStoryAlreadyInDatabase_thenIExpectFalse() {
// GIVEN
MmsHelper.insert(
IncomingMediaMessage(
from = recipients[0],
sentTimeMillis = 200,
serverTimeMillis = 2,
receivedTimeMillis = 2,
storyType = StoryType.STORY_WITH_REPLIES,
),
-1L
)
// WHEN
val result = mms.isOutgoingStoryAlreadyInDatabase(recipients[0], 200)
// THEN
assertFalse(result)
}
@Test
fun givenOutgoingStoryExistsForRecipientAndTime_whenICheckIsOutgoingStoryAlreadyInDatabase_thenIExpectTrue() {
// GIVEN
MmsHelper.insert(
recipient = myStory,
sentTimeMillis = 200,
storyType = StoryType.STORY_WITH_REPLIES,
threadId = -1L
)
// WHEN
val result = mms.isOutgoingStoryAlreadyInDatabase(myStory.id, 200)
// THEN
assertTrue(result)
}
} }

View file

@ -203,6 +203,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract @NonNull MessageDatabase.Reader getUnreadStories(@NonNull RecipientId recipientId, int limit); public abstract @NonNull MessageDatabase.Reader getUnreadStories(@NonNull RecipientId recipientId, int limit);
public abstract @Nullable ParentStoryId.GroupReply getParentStoryIdForGroupReply(long messageId); public abstract @Nullable ParentStoryId.GroupReply getParentStoryIdForGroupReply(long messageId);
public abstract void deleteGroupStoryReplies(long parentStoryId); public abstract void deleteGroupStoryReplies(long parentStoryId);
public abstract boolean isOutgoingStoryAlreadyInDatabase(@NonNull RecipientId recipientId, long sentTimestamp);
public abstract @NonNull StoryViewState getStoryViewState(@NonNull RecipientId recipientId); public abstract @NonNull StoryViewState getStoryViewState(@NonNull RecipientId recipientId);
public abstract void updateViewedStories(@NonNull Set<SyncMessageId> syncMessageIds); public abstract void updateViewedStories(@NonNull Set<SyncMessageId> syncMessageIds);

View file

@ -695,6 +695,22 @@ public class MmsDatabase extends MessageDatabase {
} }
} }
@Override
public boolean isOutgoingStoryAlreadyInDatabase(@NonNull RecipientId recipientId, long sentTimestamp) {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
String[] projection = new String[]{"COUNT(*)"};
String where = RECIPIENT_ID + " = ? AND " + STORY_TYPE + " > 0 AND " + DATE_SENT + " = ? AND (" + getOutgoingTypeClause() + ")";
String[] whereArgs = SqlUtil.buildArgs(recipientId, sentTimestamp);
try (Cursor cursor = database.query(TABLE_NAME, projection, where, whereArgs, null, null, null, "1")) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0) > 0;
}
}
return false;
}
@Override @Override
public @NonNull MessageId getStoryId(@NonNull RecipientId authorId, long sentTimestamp) throws NoSuchMessageException { public @NonNull MessageId getStoryId(@NonNull RecipientId authorId, long sentTimestamp) throws NoSuchMessageException {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase(); SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();

View file

@ -1417,6 +1417,10 @@ public class SmsDatabase extends MessageDatabase {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public boolean isOutgoingStoryAlreadyInDatabase(@NonNull RecipientId recipientId, long sentTimestamp) {
throw new UnsupportedOperationException();
}
@Override @Override
public @NonNull MessageId getStoryId(@NonNull RecipientId authorId, long sentTimestamp) throws NoSuchMessageException { public @NonNull MessageId getStoryId(@NonNull RecipientId authorId, long sentTimestamp) throws NoSuchMessageException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View file

@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.database.SentStorySyncManifest;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.StickerDatabase; import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.DistributionListId;
import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.database.model.MessageId; import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageLogEntry; import org.thoughtcrime.securesms.database.model.MessageLogEntry;
@ -2062,6 +2061,11 @@ public final class MessageContentProcessor {
@NonNull List<LinkPreview> linkPreviews) @NonNull List<LinkPreview> linkPreviews)
throws MmsException throws MmsException
{ {
if (SignalDatabase.mms().isOutgoingStoryAlreadyInDatabase(recipient.getId(), sentAtTimestamp)) {
warn(sentAtTimestamp, "Already inserted this story.");
return;
}
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipient, OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipient,
textStoryBody, textStoryBody,
pendingAttachments, pendingAttachments,