add model for MAM result + MAM manager

This commit is contained in:
Daniel Gultsch 2023-02-08 11:44:16 +01:00
parent ca0a0c07fc
commit 3f59dd2688
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
8 changed files with 84 additions and 20 deletions

View file

@ -91,6 +91,7 @@ public final class Namespace {
public static final String SASL_2 = "urn:xmpp:sasl:2";
public static final String STANZAS = "urn:ietf:params:xml:ns:xmpp-stanzas";
public static final String STANZA_IDS = "urn:xmpp:sid:0";
public static final String MESSAGE_ARCHIVE_MANAGEMENT = "urn:xmpp:mam:2";
public static final String STREAMS = "http://etherx.jabber.org/streams";
public static final String STREAM_MANAGEMENT = "urn:xmpp:sm:3";
public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0";

View file

@ -4,6 +4,7 @@ import android.content.Context;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.ImmutableClassToInstanceMap;
import im.conversations.android.xmpp.manager.AbstractManager;
import im.conversations.android.xmpp.manager.ArchiveManager;
import im.conversations.android.xmpp.manager.AvatarManager;
import im.conversations.android.xmpp.manager.AxolotlManager;
import im.conversations.android.xmpp.manager.BlockingManager;
@ -25,6 +26,7 @@ public final class Managers {
public static ClassToInstanceMap<AbstractManager> initialize(
final Context context, final XmppConnection connection) {
return new ImmutableClassToInstanceMap.Builder<AbstractManager>()
.put(ArchiveManager.class, new ArchiveManager(context, connection))
.put(AvatarManager.class, new AvatarManager(context, connection))
.put(AxolotlManager.class, new AxolotlManager(context, connection))
.put(BlockingManager.class, new BlockingManager(context, connection))

View file

@ -0,0 +1,25 @@
package im.conversations.android.xmpp.mam;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xmpp.model.Extension;
import im.conversations.android.xmpp.model.forward.Forwarded;
@XmlElement
public class Result extends Extension {
public Result() {
super(Result.class);
}
public Forwarded getForwarded() {
return this.getExtension(Forwarded.class);
}
public String getId() {
return this.getAttribute("id");
}
public String getQueryId() {
return this.getAttribute("queryid");
}
}

View file

@ -0,0 +1,5 @@
@XmlPackage(namespace = Namespace.MESSAGE_ARCHIVE_MANAGEMENT)
package im.conversations.android.xmpp.mam;
import eu.siacs.conversations.xml.Namespace;
import im.conversations.android.annotation.XmlPackage;

View file

@ -0,0 +1,32 @@
package im.conversations.android.xmpp.manager;
import android.content.Context;
import com.google.common.base.Preconditions;
import im.conversations.android.xmpp.XmppConnection;
import im.conversations.android.xmpp.mam.Result;
import im.conversations.android.xmpp.model.stanza.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ArchiveManager extends AbstractManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveManager.class);
public ArchiveManager(Context context, XmppConnection connection) {
super(context, connection);
}
public void handle(final Message message) {
final var result = message.getExtension(Result.class);
Preconditions.checkArgument(result != null, "The message needs to contain a MAM result");
final var from = message.getFrom();
final var queryId = result.getQueryId();
final var forwarded = result.getForwarded();
final var forwardedMessage = forwarded == null ? null : forwarded.getMessage();
if (forwardedMessage == null || queryId == null) {
LOGGER.info("Received invalid MAM result from {} ", from);
return;
}
// TODO
}
}

View file

@ -1,15 +1,13 @@
package im.conversations.android.xmpp.manager;
import android.content.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.XmppConnection;
import im.conversations.android.xmpp.model.state.ChatStateNotification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ChatStateManager extends AbstractManager{
public class ChatStateManager extends AbstractManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ChatStateManager.class);

View file

@ -3,6 +3,8 @@ package im.conversations.android.xmpp.processor;
import android.content.Context;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.XmppConnection;
import im.conversations.android.xmpp.mam.Result;
import im.conversations.android.xmpp.manager.ArchiveManager;
import im.conversations.android.xmpp.manager.CarbonsManager;
import im.conversations.android.xmpp.manager.ChatStateManager;
import im.conversations.android.xmpp.manager.PubSubManager;
@ -13,7 +15,6 @@ import im.conversations.android.xmpp.model.carbons.Sent;
import im.conversations.android.xmpp.model.pubsub.event.Event;
import im.conversations.android.xmpp.model.stanza.Message;
import im.conversations.android.xmpp.model.state.ChatStateNotification;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -52,22 +53,26 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume
return;
}
if (isRoot() && message.hasExtension(Result.class)) {
getManager(ArchiveManager.class).handle(message);
return;
}
final String id = message.getId();
final Jid from = message.getFrom();
LOGGER.info("Message received {}", message.getExtensionIds());
// TODO only do this if transformation was successful or nothing to transform
if (isRealtimeProcessor()) {
final var requests = message.getExtensions(DeliveryReceiptRequest.class);
getManager(ReceiptManager.class).received(from, id, requests);
final var chatState = message.getExtension(ChatStateNotification.class);
if (chatState != null) {
getManager(ChatStateManager.class).handle(from, chatState);
}
}
// TODO parse chat states
// TODO parse and validate stanza-id
// TODO collect Extensions that require transformation (everything that will end up in the
// message tables)
@ -79,13 +84,9 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume
return this.level == Level.ROOT;
}
private boolean isRealtimeProcessor() {
return this.level != Level.ARCHIVE;
}
public enum Level {
ROOT,
CARBON,
ARCHIVE
STANZA_CONTENT_ENCRYPTION
}
}