2019-08-25 17:54:03 +02:00
|
|
|
package org.mercury_im.messenger.core.stores;
|
|
|
|
|
|
|
|
import org.jivesoftware.smack.chat2.Chat;
|
|
|
|
import org.jivesoftware.smack.chat2.ChatManager;
|
|
|
|
import org.jivesoftware.smack.packet.Message;
|
|
|
|
import org.jivesoftware.smackx.carbons.CarbonManager;
|
|
|
|
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
|
2019-10-28 14:56:56 +01:00
|
|
|
import org.jivesoftware.smackx.delay.DelayInformationManager;
|
2019-09-08 04:47:59 +02:00
|
|
|
import org.jivesoftware.smackx.delay.packet.DelayInformation;
|
|
|
|
import org.jivesoftware.smackx.mam.MamManager;
|
2019-10-28 14:56:56 +01:00
|
|
|
import org.jivesoftware.smackx.sid.element.OriginIdElement;
|
|
|
|
import org.jivesoftware.smackx.sid.element.StanzaIdElement;
|
2019-08-25 17:54:03 +02:00
|
|
|
import org.jxmpp.jid.EntityBareJid;
|
2019-10-28 14:56:56 +01:00
|
|
|
import org.jxmpp.jid.impl.JidCreate;
|
2019-09-23 23:55:57 +02:00
|
|
|
import org.mercury_im.messenger.core.NotificationManager;
|
2019-08-25 17:54:03 +02:00
|
|
|
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
2019-11-03 06:33:52 +01:00
|
|
|
import org.mercury_im.messenger.xmpp.model.ChatModel;
|
|
|
|
import org.mercury_im.messenger.xmpp.model.ContactModel;
|
|
|
|
import org.mercury_im.messenger.xmpp.model.EntityModel;
|
|
|
|
import org.mercury_im.messenger.xmpp.model.LastChatMessageRelation;
|
|
|
|
import org.mercury_im.messenger.xmpp.model.MessageModel;
|
|
|
|
import org.mercury_im.messenger.xmpp.repository.ChatRepository;
|
|
|
|
import org.mercury_im.messenger.xmpp.repository.MessageRepository;
|
|
|
|
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
|
|
|
|
import org.mercury_im.messenger.xmpp.util.ChatAndPossiblyContact;
|
2019-08-25 17:54:03 +02:00
|
|
|
|
2019-09-08 04:47:59 +02:00
|
|
|
import java.util.ArrayList;
|
2019-08-25 17:54:03 +02:00
|
|
|
import java.util.Date;
|
2019-09-08 04:47:59 +02:00
|
|
|
import java.util.List;
|
2019-08-25 17:54:03 +02:00
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
import io.reactivex.Completable;
|
2019-08-25 17:54:03 +02:00
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
|
|
|
|
|
|
|
public class PlainMessageStore {
|
|
|
|
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(PlainMessageStore.class.getName());
|
|
|
|
private static final CompositeDisposable disposable = new CompositeDisposable();
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
private final RosterRepository rosterRepository;
|
|
|
|
private final ChatRepository chatRepository;
|
2019-08-25 17:54:03 +02:00
|
|
|
private final MessageRepository messageRepository;
|
|
|
|
|
2019-09-23 23:55:57 +02:00
|
|
|
private final NotificationManager notificationManager;
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
public PlainMessageStore(RosterRepository rosterRepository, ChatRepository chatRepository, MessageRepository messageRepository, NotificationManager notificationManager) {
|
|
|
|
this.rosterRepository = rosterRepository;
|
|
|
|
this.chatRepository = chatRepository;
|
2019-08-25 17:54:03 +02:00
|
|
|
this.messageRepository = messageRepository;
|
2019-09-23 23:55:57 +02:00
|
|
|
this.notificationManager = notificationManager;
|
2019-08-25 17:54:03 +02:00
|
|
|
}
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
public void handleIncomingMessage(long accountId, EntityBareJid from, Message message, Chat chat) {
|
2019-08-25 17:54:03 +02:00
|
|
|
if (message.getBody() == null) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-23 23:55:57 +02:00
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
Completable.fromAction(() -> {
|
|
|
|
EntityModel entityModel = rosterRepository.getOrCreateEntity(accountId, from)
|
|
|
|
.blockingGet();
|
|
|
|
ContactModel contactModel = rosterRepository.getContact(accountId, entityModel.getJid()).blockingFirst().firstOrNull();
|
|
|
|
ChatModel chatModel = chatRepository.getChatWith(entityModel).blockingFirst().firstOr(() -> {
|
|
|
|
ChatModel freshChatModel = new ChatModel();
|
|
|
|
freshChatModel.setPeer(entityModel);
|
|
|
|
freshChatModel.setDisplayed(true);
|
|
|
|
return freshChatModel;
|
|
|
|
});
|
|
|
|
|
|
|
|
chatModel = chatRepository.upsert(chatModel).blockingGet();
|
|
|
|
|
|
|
|
MessageModel messageModel = setCommonMessageAttributes(message, chatModel);
|
|
|
|
messageModel.setSender(from);
|
|
|
|
messageModel.setIncoming(true);
|
|
|
|
|
|
|
|
final ChatModel fChatModel = chatModel;
|
|
|
|
disposable.add(messageRepository.insert(messageModel)
|
|
|
|
.subscribe(insertedMessageModel -> {
|
|
|
|
if (message.getBody() != null) {
|
|
|
|
notificationManager.chatMessageReceived(new ChatAndPossiblyContact(fChatModel, contactModel), message.getBody());
|
|
|
|
}
|
|
|
|
|
|
|
|
LastChatMessageRelation lastMessage = new LastChatMessageRelation();
|
|
|
|
lastMessage.setChat(fChatModel);
|
|
|
|
lastMessage.setMessage(insertedMessageModel);
|
|
|
|
}));
|
|
|
|
}).subscribeOn(Schedulers.io())
|
|
|
|
.subscribe();
|
2019-08-25 17:54:03 +02:00
|
|
|
}
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
public void handleOutgoingMessage(long accountId, EntityBareJid to, Message message, Chat chat) {
|
|
|
|
MessageModel model = setCommonMessageAttributes(message, null);
|
|
|
|
EntityModel entityModel = rosterRepository.getOrCreateEntity(accountId, to).blockingGet();
|
|
|
|
|
|
|
|
model.setIncoming(false);
|
|
|
|
model.setTimestamp(new Date());
|
|
|
|
model.setSender(entityModel.getAccount().getJid());
|
|
|
|
model.setRecipient(to);
|
|
|
|
|
|
|
|
ChatModel chatModel = chatRepository.getChatWith(entityModel).blockingFirst().firstOr(() -> {
|
|
|
|
ChatModel freshChatModel = new ChatModel();
|
|
|
|
freshChatModel.setPeer(entityModel);
|
|
|
|
freshChatModel.setDisplayed(true);
|
|
|
|
return freshChatModel;
|
|
|
|
});
|
|
|
|
|
|
|
|
model.setChat(chatModel);
|
|
|
|
|
|
|
|
disposable.add(messageRepository.upsert(model)
|
|
|
|
.subscribe(messageId ->
|
|
|
|
LOGGER.log(Level.INFO, "Inserted outgoing message " + messageId)));
|
2019-08-25 17:54:03 +02:00
|
|
|
}
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
public void handleCarbonCopy(long accountId, CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage) {
|
2019-08-25 17:54:03 +02:00
|
|
|
if (carbonCopy.getBody() == null) {
|
|
|
|
return;
|
|
|
|
}
|
2019-10-28 14:56:56 +01:00
|
|
|
MessageModel messageModel = new MessageModel();
|
|
|
|
messageModel.setSender(carbonCopy.getFrom() != null ? carbonCopy.getFrom().asEntityBareJidIfPossible() : null);
|
|
|
|
messageModel.setRecipient(carbonCopy.getTo() != null ? carbonCopy.getTo().asEntityBareJidIfPossible() : null);
|
2019-08-25 17:54:03 +02:00
|
|
|
|
|
|
|
messageModel.setIncoming(direction == CarbonExtension.Direction.received);
|
|
|
|
|
|
|
|
messageModel.setBody(carbonCopy.getBody());
|
2019-10-28 14:56:56 +01:00
|
|
|
messageModel.setTimestamp(new Date());
|
|
|
|
|
|
|
|
disposable.add(messageRepository.upsert(messageModel)
|
|
|
|
.subscribe(messageId ->
|
|
|
|
LOGGER.log(Level.INFO, "Inserted carbon message " + messageId)));
|
2019-08-25 17:54:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void registerForMercuryConnection(MercuryConnection connection) {
|
|
|
|
ChatManager chatManager = ChatManager.getInstanceFor(connection.getConnection());
|
|
|
|
CarbonManager carbonManager = CarbonManager.getInstanceFor(connection.getConnection());
|
|
|
|
|
|
|
|
// Add account ID to
|
|
|
|
chatManager.addIncomingListener((from, message, chat) ->
|
2019-10-28 14:56:56 +01:00
|
|
|
PlainMessageStore.this.handleIncomingMessage(
|
2019-08-25 17:54:03 +02:00
|
|
|
connection.getAccountId(), from, message, chat));
|
2019-10-28 14:56:56 +01:00
|
|
|
|
2019-08-25 17:54:03 +02:00
|
|
|
chatManager.addOutgoingListener((to, message, chat) ->
|
2019-10-28 14:56:56 +01:00
|
|
|
PlainMessageStore.this.handleOutgoingMessage(
|
2019-08-25 17:54:03 +02:00
|
|
|
connection.getAccountId(), to, message, chat));
|
2019-10-28 14:56:56 +01:00
|
|
|
|
2019-08-25 17:54:03 +02:00
|
|
|
carbonManager.addCarbonCopyReceivedListener((direction, carbonCopy, wrappingMessage) ->
|
2019-10-28 14:56:56 +01:00
|
|
|
PlainMessageStore.this.handleCarbonCopy(
|
2019-08-25 17:54:03 +02:00
|
|
|
connection.getAccountId(), direction, carbonCopy, wrappingMessage));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void dispose() {
|
|
|
|
disposable.clear();
|
|
|
|
}
|
2019-09-08 04:47:59 +02:00
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
public void handleMamResult(long accountId, EntityBareJid peerJid, MamManager.MamQuery query) {
|
2019-09-08 04:47:59 +02:00
|
|
|
List<MessageModel> messageModels = new ArrayList<>();
|
|
|
|
for (Message message : query.getMessages()) {
|
|
|
|
Date date = new Date();
|
|
|
|
DelayInformation delay = DelayInformation.from(message);
|
|
|
|
if (delay != null) {
|
|
|
|
date = delay.getStamp();
|
|
|
|
}
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
MessageModel messageModel = new MessageModel();
|
2019-09-08 04:47:59 +02:00
|
|
|
messageModel.setBody(message.getBody());
|
2019-10-28 14:56:56 +01:00
|
|
|
messageModel.setSender(message.getFrom().asEntityBareJidOrThrow());
|
|
|
|
messageModel.setRecipient(message.getTo().asEntityBareJidOrThrow());
|
2019-09-08 04:47:59 +02:00
|
|
|
messageModel.setIncoming(peerJid.equals(message.getFrom().asEntityBareJidOrThrow()));
|
2019-10-28 14:56:56 +01:00
|
|
|
messageModel.setTimestamp(date);
|
2019-09-08 04:47:59 +02:00
|
|
|
messageModels.add(messageModel);
|
|
|
|
}
|
|
|
|
|
2019-10-28 14:56:56 +01:00
|
|
|
disposable.add(messageRepository.upsert(messageModels).subscribe());
|
|
|
|
}
|
|
|
|
|
|
|
|
private MessageModel incomingMessageToModel(Message message, ChatModel chat) {
|
|
|
|
MessageModel model = setCommonMessageAttributes(message, chat);
|
|
|
|
model.setIncoming(true);
|
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
|
|
|
private MessageModel setCommonMessageAttributes(Message message, ChatModel chat) {
|
|
|
|
MessageModel model = new MessageModel();
|
|
|
|
|
|
|
|
model.setBody(message.getBody());
|
|
|
|
Date timestamp = DelayInformationManager.getDelayTimestamp(message);
|
|
|
|
model.setTimestamp(timestamp == null ? new Date() : timestamp);
|
|
|
|
model.setThread(message.getThread());
|
|
|
|
model.setLegacyId(message.getStanzaId());
|
|
|
|
model.setChat(chat);
|
|
|
|
model.setRecipient(message.getTo().asEntityBareJidOrThrow());
|
|
|
|
model.setSender(message.getFrom() != null ? message.getFrom().asEntityBareJidIfPossible() : null);
|
|
|
|
OriginIdElement originId = OriginIdElement.getOriginId(message);
|
|
|
|
model.setOriginId(originId != null ? originId.getId() : null);
|
|
|
|
StanzaIdElement stanzaId = StanzaIdElement.getStanzaId(message);
|
|
|
|
model.setStanzaId(stanzaId != null ? stanzaId.getId() : null);
|
|
|
|
model.setStanzaIdBy(stanzaId != null ? JidCreate.entityBareFromOrThrowUnchecked(stanzaId.getBy()) : null);
|
|
|
|
|
|
|
|
|
|
|
|
return model;
|
2019-09-08 04:47:59 +02:00
|
|
|
}
|
2019-08-25 17:54:03 +02:00
|
|
|
}
|