2019-11-18 23:51:27 +01:00
|
|
|
package org.mercury_im.messenger;
|
2019-11-08 00:47:17 +01:00
|
|
|
|
2020-05-31 22:32:33 +02:00
|
|
|
import org.jivesoftware.smack.SmackConfiguration;
|
2020-06-04 23:49:03 +02:00
|
|
|
import org.jivesoftware.smack.SmackException;
|
|
|
|
import org.jivesoftware.smack.XMPPException;
|
2020-06-05 00:22:48 +02:00
|
|
|
import org.jivesoftware.smack.chat2.ChatManager;
|
2020-06-04 23:49:03 +02:00
|
|
|
import org.jivesoftware.smack.roster.Roster;
|
|
|
|
import org.jivesoftware.smack.roster.RosterEntry;
|
|
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
|
|
import org.jxmpp.jid.impl.JidCreate;
|
|
|
|
import org.jxmpp.stringprep.XmppStringprepException;
|
2019-12-09 15:49:59 +01:00
|
|
|
import org.mercury_im.messenger.data.repository.Repositories;
|
2020-06-04 23:49:03 +02:00
|
|
|
import org.mercury_im.messenger.entity.contact.Peer;
|
|
|
|
import org.mercury_im.messenger.exception.ConnectionNotFoundException;
|
|
|
|
import org.mercury_im.messenger.exception.ContactAlreadyAddedException;
|
|
|
|
import org.mercury_im.messenger.xmpp.MercuryConnection;
|
2020-01-05 15:54:44 +01:00
|
|
|
import org.mercury_im.messenger.xmpp.MercuryConnectionManager;
|
2019-11-12 00:07:57 +01:00
|
|
|
|
2020-06-04 23:49:03 +02:00
|
|
|
import java.util.UUID;
|
2019-12-21 03:24:00 +01:00
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
2019-11-12 00:07:57 +01:00
|
|
|
|
2019-12-02 02:31:32 +01:00
|
|
|
import javax.inject.Inject;
|
2020-01-06 01:27:11 +01:00
|
|
|
import javax.inject.Singleton;
|
2019-12-02 02:31:32 +01:00
|
|
|
|
2020-06-04 23:49:03 +02:00
|
|
|
import io.reactivex.Completable;
|
2019-12-22 05:48:07 +01:00
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
|
|
|
|
2020-01-06 01:27:11 +01:00
|
|
|
@Singleton
|
2020-05-11 16:31:07 +02:00
|
|
|
public class Messenger {
|
2019-11-12 00:07:57 +01:00
|
|
|
|
2019-12-09 13:50:26 +01:00
|
|
|
public static final String TAG = "MercuryIM";
|
2019-12-21 03:24:00 +01:00
|
|
|
private static final Logger LOGGER = Logger.getLogger(Messenger.class.getName());
|
2019-12-09 13:50:26 +01:00
|
|
|
|
2020-01-05 15:54:44 +01:00
|
|
|
private final MercuryConnectionManager connectionManager;
|
|
|
|
private final Repositories repositories;
|
2020-01-04 22:56:34 +01:00
|
|
|
|
2019-12-22 05:48:07 +01:00
|
|
|
private CompositeDisposable disposable = new CompositeDisposable();
|
|
|
|
|
2020-05-31 22:32:33 +02:00
|
|
|
static {
|
|
|
|
SmackConfiguration.DEBUG = true;
|
|
|
|
}
|
|
|
|
|
2019-12-02 02:31:32 +01:00
|
|
|
@Inject
|
2020-01-06 01:27:11 +01:00
|
|
|
public Messenger(Repositories repositories, MercuryConnectionManager connectionManager) {
|
2019-12-09 15:49:59 +01:00
|
|
|
this.repositories = repositories;
|
2020-01-06 01:27:11 +01:00
|
|
|
this.connectionManager = connectionManager;
|
2020-01-04 22:56:34 +01:00
|
|
|
performInitialLogin();
|
2019-12-22 05:48:07 +01:00
|
|
|
}
|
|
|
|
|
2020-01-05 15:54:44 +01:00
|
|
|
public MercuryConnectionManager getConnectionManager() {
|
|
|
|
return connectionManager;
|
|
|
|
}
|
|
|
|
|
2020-01-04 22:56:34 +01:00
|
|
|
public void performInitialLogin() {
|
2020-01-06 01:27:11 +01:00
|
|
|
LOGGER.log(Level.INFO, "Perform initial login.");
|
2019-12-22 05:48:07 +01:00
|
|
|
disposable.add(repositories.getAccountRepository().observeAllAccounts().firstOrError()
|
2020-05-31 22:32:33 +02:00
|
|
|
.subscribeOn(Schedulers.io())
|
2020-06-06 16:45:20 +02:00
|
|
|
.subscribe(connectionManager::doRegisterConnections));
|
2019-11-18 00:04:28 +01:00
|
|
|
}
|
2019-12-09 13:50:26 +01:00
|
|
|
|
2020-06-04 23:49:03 +02:00
|
|
|
public Completable addContact(UUID accountId, String contactAddress) {
|
|
|
|
return Completable.fromAction(() -> doAddContact(accountId, contactAddress));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void doAddContact(UUID accountId, String contactAddress)
|
|
|
|
throws ConnectionNotFoundException, XmppStringprepException, ContactAlreadyAddedException,
|
|
|
|
SmackException.NotLoggedInException, XMPPException.XMPPErrorException,
|
|
|
|
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
|
2020-06-05 00:22:48 +02:00
|
|
|
MercuryConnection connection = getConnection(accountId);
|
2020-06-04 23:49:03 +02:00
|
|
|
|
|
|
|
EntityBareJid jid = JidCreate.entityBareFrom(contactAddress);
|
|
|
|
Roster roster = Roster.getInstanceFor(connection.getConnection());
|
|
|
|
if (roster.getEntry(jid) != null) {
|
|
|
|
throw new ContactAlreadyAddedException(jid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (roster.isSubscriptionPreApprovalSupported()) {
|
|
|
|
LOGGER.log(Level.INFO, "Pre-Approval supported.");
|
|
|
|
try {
|
|
|
|
roster.preApproveAndCreateEntry(jid, null, null);
|
|
|
|
} catch (SmackException.FeatureNotSupportedException e) {
|
|
|
|
throw new AssertionError("pre-approval failed even though the feature is announced.");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
roster.createItemAndRequestSubscription(jid, null, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Completable deleteContact(Peer contact) {
|
|
|
|
return Completable.fromAction(() -> doDeleteContact(contact));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void doDeleteContact(Peer contact)
|
|
|
|
throws ConnectionNotFoundException, XmppStringprepException,
|
|
|
|
SmackException.NotLoggedInException, XMPPException.XMPPErrorException,
|
|
|
|
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
|
2020-06-05 00:22:48 +02:00
|
|
|
MercuryConnection connection = getConnection(contact.getAccount().getId());
|
2020-06-04 23:49:03 +02:00
|
|
|
|
|
|
|
Roster roster = Roster.getInstanceFor(connection.getConnection());
|
|
|
|
EntityBareJid jid = JidCreate.entityBareFrom(contact.getAddress());
|
|
|
|
RosterEntry entry = roster.getEntry(jid);
|
|
|
|
if (entry != null) {
|
|
|
|
roster.removeEntry(entry);
|
|
|
|
} else {
|
|
|
|
throw new IllegalStateException("Contact " + jid.toString() + " not in roster!");
|
|
|
|
}
|
|
|
|
}
|
2020-06-05 00:22:48 +02:00
|
|
|
|
|
|
|
public Completable sendMessage(Peer peer, String body) {
|
|
|
|
return Completable.fromAction(() -> doSendMessage(peer, body));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void doSendMessage(Peer contact, String body) throws ConnectionNotFoundException,
|
|
|
|
SmackException.NotConnectedException, InterruptedException {
|
|
|
|
MercuryConnection connection = getConnection(contact.getAccount().getId());
|
|
|
|
ChatManager chatManager = ChatManager.getInstanceFor(connection.getConnection());
|
|
|
|
chatManager.chatWith(JidCreate.entityBareFromOrThrowUnchecked(contact.getAddress()))
|
|
|
|
.send(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
private MercuryConnection getConnection(UUID accountId) throws ConnectionNotFoundException {
|
|
|
|
MercuryConnection connection = getConnectionManager().getConnection(accountId);
|
|
|
|
if (connection == null) {
|
|
|
|
throw new ConnectionNotFoundException(accountId);
|
|
|
|
}
|
|
|
|
return connection;
|
|
|
|
}
|
2019-11-08 00:47:17 +01:00
|
|
|
}
|