parse message retractions

This commit is contained in:
Daniel Gultsch 2023-02-13 19:29:41 +01:00
parent 94c8b9ed04
commit 69d212141b
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
7 changed files with 70 additions and 5 deletions

View file

@ -11,6 +11,7 @@ import im.conversations.android.database.ConversationsDatabase;
import im.conversations.android.database.entity.AccountEntity; import im.conversations.android.database.entity.AccountEntity;
import im.conversations.android.database.model.MessageEmbedded; import im.conversations.android.database.model.MessageEmbedded;
import im.conversations.android.database.model.Modification; import im.conversations.android.database.model.Modification;
import im.conversations.android.database.model.PartType;
import im.conversations.android.transformer.Transformation; import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.Transformer; import im.conversations.android.transformer.Transformer;
import im.conversations.android.xmpp.model.correction.Replace; import im.conversations.android.xmpp.model.correction.Replace;
@ -19,6 +20,7 @@ import im.conversations.android.xmpp.model.reactions.Reaction;
import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.reactions.Reactions;
import im.conversations.android.xmpp.model.receipts.Received; import im.conversations.android.xmpp.model.receipts.Received;
import im.conversations.android.xmpp.model.reply.Reply; import im.conversations.android.xmpp.model.reply.Reply;
import im.conversations.android.xmpp.model.retract.Retract;
import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -430,4 +432,27 @@ public class TransformationTest {
Assert.assertEquals(1L, message.states.size()); Assert.assertEquals(1L, message.states.size());
} }
@Test
public void messageAndRetraction() {
final var m1 = new Message();
m1.setTo(ACCOUNT);
m1.setFrom(REMOTE.withResource("junit"));
m1.setId("m1");
m1.addExtension(new Body("It is raining outside"));
this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, null, null));
final var m2 = new Message();
m2.setTo(ACCOUNT);
m2.setFrom(REMOTE.withResource("junit"));
m2.addExtension(new Retract()).setId("m1");
this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, null, null));
final var messages = database.messageDao().getMessages(1L);
final var message = Iterables.getOnlyElement(messages);
Assert.assertEquals(Modification.RETRACTION, message.modification);
Assert.assertEquals(PartType.RETRACTION, Iterables.getOnlyElement(message.contents).type);
}
} }

View file

@ -1,5 +1,8 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import com.google.common.collect.ImmutableList;
import java.util.List;
public class MessageContent { public class MessageContent {
public final String language; public final String language;
@ -24,4 +27,7 @@ public class MessageContent {
public static MessageContent file(final String url) { public static MessageContent file(final String url) {
return new MessageContent(null, PartType.FILE, null, url); return new MessageContent(null, PartType.FILE, null, url);
} }
public static final List<MessageContent> RETRACTION =
ImmutableList.of(new MessageContent(null, PartType.RETRACTION, null, null));
} }

View file

@ -18,6 +18,7 @@ import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
import im.conversations.android.xmpp.model.oob.OutOfBandData; import im.conversations.android.xmpp.model.oob.OutOfBandData;
import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.reactions.Reactions;
import im.conversations.android.xmpp.model.reply.Reply; import im.conversations.android.xmpp.model.reply.Reply;
import im.conversations.android.xmpp.model.retract.Retract;
import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant; import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
@ -38,7 +39,8 @@ public class Transformation {
Displayed.class, Displayed.class,
Replace.class, Replace.class,
Reactions.class, Reactions.class,
Reply.class); Reply.class,
Retract.class);
public final Instant receivedAt; public final Instant receivedAt;
public final Jid to; public final Jid to;

View file

@ -21,6 +21,7 @@ import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
import im.conversations.android.xmpp.model.oob.OutOfBandData; import im.conversations.android.xmpp.model.oob.OutOfBandData;
import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.reactions.Reactions;
import im.conversations.android.xmpp.model.reply.Reply; import im.conversations.android.xmpp.model.reply.Reply;
import im.conversations.android.xmpp.model.retract.Retract;
import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.stanza.Message;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -74,6 +75,8 @@ public class Transformer {
} }
final Replace messageCorrection = transformation.getExtension(Replace.class); final Replace messageCorrection = transformation.getExtension(Replace.class);
final Reactions reactions = transformation.getExtension(Reactions.class); final Reactions reactions = transformation.getExtension(Reactions.class);
final Retract retract = transformation.getExtension(Retract.class);
// TODO we need to remove fallbacks for reactions, retractions and potentially other things
final List<MessageContent> contents = parseContent(transformation); final List<MessageContent> contents = parseContent(transformation);
final boolean identifiableSender = final boolean identifiableSender =
@ -85,10 +88,21 @@ public class Transformer {
&& identifiableSender; && identifiableSender;
final boolean isMessageCorrection = final boolean isMessageCorrection =
Objects.nonNull(messageCorrection) Objects.nonNull(messageCorrection)
&& messageCorrection.getId() != null && Objects.nonNull(messageCorrection.getId())
&& identifiableSender; && identifiableSender;
final boolean isRetraction =
if (contents.isEmpty()) { Objects.nonNull(retract) && Objects.nonNull(retract.getId()) && identifiableSender;
// TODO in a way it would be more appropriate to move this into the contents.isEmpty block
// but for that to work we would need to properly ignore the fallback body
if (isRetraction) {
final var messageIdentifier =
database.messageDao()
.getOrCreateVersion(
chat, transformation, retract.getId(), Modification.RETRACTION);
database.messageDao()
.insertMessageContent(messageIdentifier.version, MessageContent.RETRACTION);
return true;
} else if (contents.isEmpty()) {
LOGGER.info("Received message from {} w/o contents", transformation.from); LOGGER.info("Received message from {} w/o contents", transformation.from);
transformMessageState(chat, transformation); transformMessageState(chat, transformation);
if (isReaction) { if (isReaction) {

View file

@ -1,5 +1,6 @@
package im.conversations.android.xmpp.model; package im.conversations.android.xmpp.model;
import com.google.common.base.Preconditions;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import im.conversations.android.xmpp.ExtensionFactory; import im.conversations.android.xmpp.ExtensionFactory;
@ -10,6 +11,11 @@ public class Extension extends Element {
} }
public Extension(final Class<? extends Extension> clazz) { public Extension(final Class<? extends Extension> clazz) {
this(ExtensionFactory.id(clazz)); this(
Preconditions.checkNotNull(
ExtensionFactory.id(clazz),
String.format(
"%s does not seem to be annotated with @XmlElement",
clazz.getName())));
} }
} }

View file

@ -1,10 +1,20 @@
package im.conversations.android.xmpp.model.retract; package im.conversations.android.xmpp.model.retract;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension; import im.conversations.android.xmpp.model.Extension;
@XmlElement
public class Retract extends Extension { public class Retract extends Extension {
public Retract() { public Retract() {
super(Retract.class); super(Retract.class);
} }
public String getId() {
return this.getAttribute("id");
}
public void setId(final String id) {
this.setAttribute("id", id);
}
} }

View file

@ -1,7 +1,9 @@
package im.conversations.android.xmpp.model.retract; package im.conversations.android.xmpp.model.retract;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension; import im.conversations.android.xmpp.model.Extension;
@XmlElement
public class Retracted extends Extension { public class Retracted extends Extension {
public Retracted() { public Retracted() {