package de.thedevstack.xmpp.mamloader; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smackx.forward.packet.Forwarded; import org.jivesoftware.smackx.mam.MamManager; import org.jivesoftware.smackx.mam.MamManager.MamQueryResult; import org.jxmpp.jid.BareJid; import org.jxmpp.jid.Jid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; public class MamLoadClient { private static final int LIMIT_PER_REQUEST = 50; private AbstractXMPPConnection connection; private MamManager mamManager; private boolean debug; public MamLoadClient(boolean debug) { this.debug = debug; } public void connectAndLogin(String username, String password) throws SmackException, IOException, XMPPException, InterruptedException { BareJid userJid = JidCreate.bareFrom(username); this.connectAndLogin(userJid.getLocalpartOrThrow().toString(), password, userJid.getDomain().toString()); } private void connectAndLogin(String username, String password, String host) throws SmackException, IOException, XMPPException, InterruptedException { XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword(username, password) .setXmppDomain(host) .setHost(host) .setDebuggerEnabled(this.debug) //.setCustomSSLContext(SSLHelper.createNaiveSSLContext()) .setResource("MAMLoader_" + UUID.randomUUID()) .setSendPresence(false) .build(); connection = new XMPPTCPConnection(config); connection.connect(); connection.login(); mamManager = MamManager.getInstanceFor(connection); } public void disconnect() { this.connection.disconnect(); } public List loadHistory(String jid) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { return this.loadHistory(jid, null, null); } public List loadHistory(String jid, Date start) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { return this.loadHistory(jid, start, null); } public List loadHistory(String jid, Date start, Date end) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { List allMessages = new ArrayList<>(); if (mamManager.isSupported()) { Jid withJid = JidCreate.bareFrom(jid); MamQueryResult archive = mamManager.queryArchive(null, start, end, withJid, null); allMessages.addAll(archive.forwardedMessages); while (!archive.mamFin.isComplete()) { archive = mamManager.pageNext(archive, LIMIT_PER_REQUEST); allMessages.addAll(archive.forwardedMessages); } allMessages = this.filterAndSort(allMessages); } return allMessages; } public List loadHistory(String jid, int limit) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException, XmppStringprepException { List allMessages = new ArrayList<>(); if (mamManager.isSupported()) { Jid withJid = JidCreate.bareFrom(jid); MamQueryResult archive = mamManager.mostRecentPage(withJid, LIMIT_PER_REQUEST); allMessages.addAll(archive.forwardedMessages); while (!archive.mamFin.isComplete() && limit > allMessages.size()) { int requestLimit = limit - allMessages.size(); archive = mamManager.pagePrevious(archive, (requestLimit < LIMIT_PER_REQUEST ? requestLimit : LIMIT_PER_REQUEST)); allMessages.addAll(archive.forwardedMessages); } allMessages = this.filterAndSort(allMessages); } return allMessages; } private List filterAndSort(List messages) { return messages.stream() .filter(forwarded -> forwarded.getForwardedStanza() instanceof Message && ((Message)forwarded.getForwardedStanza()).getBody() != null) .sorted(new Comparator() { @Override public int compare(Forwarded o1, Forwarded o2) { return o1.getDelayInformation().getStamp().compareTo(o2.getDelayInformation().getStamp()); } }) .collect(Collectors.toList()); } }