diff --git a/src/main/java/im/conversations/android/xmpp/Managers.java b/src/main/java/im/conversations/android/xmpp/Managers.java index da6a54fde..042a84287 100644 --- a/src/main/java/im/conversations/android/xmpp/Managers.java +++ b/src/main/java/im/conversations/android/xmpp/Managers.java @@ -18,6 +18,7 @@ import im.conversations.android.xmpp.manager.PresenceManager; import im.conversations.android.xmpp.manager.PubSubManager; import im.conversations.android.xmpp.manager.ReceiptManager; import im.conversations.android.xmpp.manager.RosterManager; +import im.conversations.android.xmpp.manager.StanzaIdManager; public final class Managers { @@ -40,6 +41,7 @@ public final class Managers { .put(PubSubManager.class, new PubSubManager(context, connection)) .put(ReceiptManager.class, new ReceiptManager(context, connection)) .put(RosterManager.class, new RosterManager(context, connection)) + .put(StanzaIdManager.class, new StanzaIdManager(context, connection)) .build(); } } diff --git a/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java b/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java new file mode 100644 index 000000000..7f7196869 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/manager/StanzaIdManager.java @@ -0,0 +1,44 @@ +package im.conversations.android.xmpp.manager; + +import android.content.Context; +import eu.siacs.conversations.xml.Namespace; +import eu.siacs.conversations.xmpp.Jid; +import im.conversations.android.xmpp.XmppConnection; +import im.conversations.android.xmpp.model.stanza.Message; +import im.conversations.android.xmpp.model.unique.StanzaId; + +public class StanzaIdManager extends AbstractManager { + + public StanzaIdManager(Context context, XmppConnection connection) { + super(context, connection); + } + + public String getStanzaId(final Message message) { + final Jid by; + if (message.getType() == Message.Type.GROUPCHAT) { + final var from = message.getFrom(); + if (from == null) { + return null; + } + by = from.asBareJid(); + } else { + by = connection.getBoundAddress().asBareJid(); + } + if (message.hasExtension(StanzaId.class) + && getManager(DiscoManager.class).hasFeature(by, Namespace.STANZA_IDS)) { + return getStanzaIdBy(message, by); + } else { + return null; + } + } + + private static String getStanzaIdBy(final Message message, final Jid by) { + for (final StanzaId stanzaId : message.getExtensions(StanzaId.class)) { + final var id = stanzaId.getId(); + if (by.equals(stanzaId.getBy()) && id != null) { + return id; + } + } + return null; + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/stanza/Message.java b/src/main/java/im/conversations/android/xmpp/model/stanza/Message.java index 8ae877fb2..e00318b9f 100644 --- a/src/main/java/im/conversations/android/xmpp/model/stanza/Message.java +++ b/src/main/java/im/conversations/android/xmpp/model/stanza/Message.java @@ -1,6 +1,7 @@ package im.conversations.android.xmpp.model.stanza; import im.conversations.android.annotation.XmlElement; +import java.util.Locale; @XmlElement public class Message extends Stanza { @@ -12,4 +13,25 @@ public class Message extends Stanza { public String getBody() { return this.findChildContent("body"); } + + public Type getType() { + final var value = this.getAttribute("type"); + if (value == null) { + return Type.NORMAL; + } else { + try { + return Type.valueOf(value.toUpperCase(Locale.ROOT)); + } catch (final IllegalArgumentException e) { + return null; + } + } + } + + public enum Type { + ERROR, + NORMAL, + GROUPCHAT, + HEADLINE, + CHAT + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java b/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java new file mode 100644 index 000000000..31a939621 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java @@ -0,0 +1,12 @@ +package im.conversations.android.xmpp.model.unique; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.Extension; + +@XmlElement +public class OriginId extends Extension { + + public OriginId() { + super(OriginId.class); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java b/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java new file mode 100644 index 000000000..23b0fdcac --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/unique/StanzaId.java @@ -0,0 +1,21 @@ +package im.conversations.android.xmpp.model.unique; + +import eu.siacs.conversations.xmpp.Jid; +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.Extension; + +@XmlElement +public class StanzaId extends Extension { + + public StanzaId() { + super(StanzaId.class); + } + + public Jid getBy() { + return this.getAttributeAsJid("by"); + } + + public String getId() { + return this.getAttribute("id"); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/unique/package-info.java b/src/main/java/im/conversations/android/xmpp/model/unique/package-info.java new file mode 100644 index 000000000..6ae2f7ece --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/unique/package-info.java @@ -0,0 +1,5 @@ +@XmlPackage(namespace = Namespace.STANZA_IDS) +package im.conversations.android.xmpp.model.unique; + +import eu.siacs.conversations.xml.Namespace; +import im.conversations.android.annotation.XmlPackage; diff --git a/src/main/java/im/conversations/android/xmpp/processor/MessageProcessor.java b/src/main/java/im/conversations/android/xmpp/processor/MessageProcessor.java index d345cc0b4..398fe6abe 100644 --- a/src/main/java/im/conversations/android/xmpp/processor/MessageProcessor.java +++ b/src/main/java/im/conversations/android/xmpp/processor/MessageProcessor.java @@ -9,6 +9,7 @@ import im.conversations.android.xmpp.manager.CarbonsManager; import im.conversations.android.xmpp.manager.ChatStateManager; import im.conversations.android.xmpp.manager.PubSubManager; import im.conversations.android.xmpp.manager.ReceiptManager; +import im.conversations.android.xmpp.manager.StanzaIdManager; import im.conversations.android.xmpp.model.DeliveryReceiptRequest; import im.conversations.android.xmpp.model.carbons.Received; import im.conversations.android.xmpp.model.carbons.Sent; @@ -59,9 +60,10 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume } final String id = message.getId(); + final String stanzaId = getManager(StanzaIdManager.class).getStanzaId(message); final Jid from = message.getFrom(); - LOGGER.info("Message received {}", message.getExtensionIds()); + LOGGER.info("Message with stanza-id {} received: {}", stanzaId, message.getExtensionIds()); // TODO only do this if transformation was successful or nothing to transform final var requests = message.getExtensions(DeliveryReceiptRequest.class); @@ -72,8 +74,7 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume getManager(ChatStateManager.class).handle(from, chatState); } - // TODO parse and validate stanza-id - + // TODO collect Extensions that require transformation (everything that will end up in the // message tables)