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.model.MessageEmbedded;
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.Transformer;
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.receipts.Received;
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 java.time.Instant;
import java.util.concurrent.ExecutionException;
@ -430,4 +432,27 @@ public class TransformationTest {
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;
import com.google.common.collect.ImmutableList;
import java.util.List;
public class MessageContent {
public final String language;
@ -24,4 +27,7 @@ public class MessageContent {
public static MessageContent file(final String 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.reactions.Reactions;
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 java.time.Instant;
import java.util.Arrays;
@ -38,7 +39,8 @@ public class Transformation {
Displayed.class,
Replace.class,
Reactions.class,
Reply.class);
Reply.class,
Retract.class);
public final Instant receivedAt;
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.reactions.Reactions;
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 java.util.Arrays;
import java.util.Collection;
@ -74,6 +75,8 @@ public class Transformer {
}
final Replace messageCorrection = transformation.getExtension(Replace.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 boolean identifiableSender =
@ -85,10 +88,21 @@ public class Transformer {
&& identifiableSender;
final boolean isMessageCorrection =
Objects.nonNull(messageCorrection)
&& messageCorrection.getId() != null
&& Objects.nonNull(messageCorrection.getId())
&& identifiableSender;
if (contents.isEmpty()) {
final boolean isRetraction =
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);
transformMessageState(chat, transformation);
if (isReaction) {

View file

@ -1,5 +1,6 @@
package im.conversations.android.xmpp.model;
import com.google.common.base.Preconditions;
import eu.siacs.conversations.xml.Element;
import im.conversations.android.xmpp.ExtensionFactory;
@ -10,6 +11,11 @@ public class Extension extends Element {
}
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;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension;
@XmlElement
public class Retract extends Extension {
public Retract() {
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;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension;
@XmlElement
public class Retracted extends Extension {
public Retracted() {