Skip to content
Snippets Groups Projects
Commit fb96b2a7 authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

- Notify user when new message

parent 334bd4ee
No related branches found
No related tags found
No related merge requests found
Showing with 69 additions and 53 deletions
......@@ -145,16 +145,20 @@ public class ModelUtils {
return pubkey.substring(0, 8);
}
public static String joinPubkeys(Collection<String> pubkeys, boolean minify, String separator) {
Preconditions.checkArgument(CollectionUtils.isNotEmpty(pubkeys));
Preconditions.checkNotNull(separator);
public static String joinPubkeys(Set<String> pubkeys, String separator, boolean minify) {
Preconditions.checkNotNull(pubkeys);
Preconditions.checkArgument(pubkeys.size()>0);
if (pubkeys.size() == 1) {
String pubkey = pubkeys.iterator().next();
return (minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
}
StringBuilder sb = new StringBuilder();
for (String pubkey : pubkeys) {
sb.append(separator)
.append(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
}
pubkeys.stream().forEach((pubkey)-> {
sb.append(separator);
sb.append(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
});
return sb.toString().substring(separator.length());
return sb.substring(separator.length());
}
}
......@@ -233,7 +233,7 @@ public abstract class AbstractService implements Bean {
protected String getIssuer(JsonNode actualObj) {
return actualObj.get(Record.PROPERTY_ISSUER).asText();
return getMandatoryField(actualObj, Record.PROPERTY_ISSUER).asText();
}
protected JsonNode getMandatoryField(JsonNode actualObj, String fieldName) {
......
......@@ -38,6 +38,9 @@ public enum UserEventCodes {
// TX
TX_SENT,
TX_RECEIVED
TX_RECEIVED,
// Message
MESSAGE_RECEIVED
}
......@@ -204,8 +204,8 @@ public class BlockchainUserEventService extends AbstractService implements Chang
Set<String> senders = ImmutableSet.copyOf(tx.getIssuers());
// Received
String senderNames = getNamesFromPubkeys(senders, true);
String sendersPubkeys = joinPubkeys(senders, false);
String senderNames = userService.joinNamesFromPubkeys(senders, DEFAULT_PUBKEYS_SEPARATOR, true);
String sendersPubkeys = ModelUtils.joinPubkeys(senders, DEFAULT_PUBKEYS_SEPARATOR, false);
Set<String> receivers = new HashSet<>();
for (String output : tx.getOutputs()) {
String[] parts = output.split(":");
......@@ -220,8 +220,8 @@ public class BlockchainUserEventService extends AbstractService implements Chang
// Sent
if (CollectionUtils.isNotEmpty(receivers)) {
String receiverNames = getNamesFromPubkeys(receivers, true);
String receiverPubkeys = joinPubkeys(receivers, false);
String receiverNames = userService.joinNamesFromPubkeys(receivers, DEFAULT_PUBKEYS_SEPARATOR, true);
String receiverPubkeys = ModelUtils.joinPubkeys(receivers, DEFAULT_PUBKEYS_SEPARATOR, false);
for (String sender : senders) {
notifyUserEvent(block, sender, UserEventCodes.TX_SENT, I18n.n("duniter.user.event.tx.sent"), receiverPubkeys, receiverNames);
}
......@@ -249,42 +249,5 @@ public class BlockchainUserEventService extends AbstractService implements Chang
userEventService.deleteEventsByReference(new UserEvent.Reference(change.getIndex(), change.getType(), change.getId()));
}
private String getNamesFromPubkeys(Set<String> pubkeys, boolean minify) {
Preconditions.checkNotNull(pubkeys);
Preconditions.checkArgument(pubkeys.size()>0);
if (pubkeys.size() == 1) {
String pubkey = pubkeys.iterator().next();
String title = userService.getProfileTitle(pubkey);
return title != null ? title :
(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
}
Map<String, String> profileTitles = userService.getProfileTitles(pubkeys);
StringBuilder sb = new StringBuilder();
pubkeys.stream().forEach((pubkey)-> {
String title = profileTitles != null ? profileTitles.get(pubkey) : null;
sb.append(DEFAULT_PUBKEYS_SEPARATOR);
sb.append(title != null ? title :
(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey));
});
return sb.substring(DEFAULT_PUBKEYS_SEPARATOR.length());
}
private String joinPubkeys(Set<String> pubkeys, boolean minify) {
Preconditions.checkNotNull(pubkeys);
Preconditions.checkArgument(pubkeys.size()>0);
if (pubkeys.size() == 1) {
String pubkey = pubkeys.iterator().next();
return (minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
}
StringBuilder sb = new StringBuilder();
pubkeys.stream().forEach((pubkey)-> {
sb.append(DEFAULT_PUBKEYS_SEPARATOR);
sb.append(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
});
return sb.substring(DEFAULT_PUBKEYS_SEPARATOR.length());
}
}
......@@ -25,14 +25,17 @@ package org.duniter.elasticsearch.user.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import org.duniter.core.client.model.ModelUtils;
import org.duniter.core.client.model.elasticsearch.Record;
import org.duniter.core.exception.TechnicalException;
import org.duniter.core.service.CryptoService;
import org.duniter.elasticsearch.PluginSettings;
import org.duniter.elasticsearch.exception.InvalidSignatureException;
import org.duniter.elasticsearch.service.AbstractService;
import org.duniter.elasticsearch.service.BlockchainService;
import org.duniter.elasticsearch.user.model.Message;
import org.duniter.elasticsearch.user.model.UserEvent;
import org.duniter.elasticsearch.user.model.UserEventCodes;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequestBuilder;
......@@ -41,6 +44,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.nuiton.i18n.I18n;
import java.io.IOException;
import java.util.Map;
......@@ -54,10 +58,13 @@ public class MessageService extends AbstractService {
public static final String RECORD_TYPE = "record";
public static final String OUTBOX_TYPE = "outbox";
private final UserEventService userEventService;
@Inject
public MessageService(Client client, PluginSettings settings, CryptoService cryptoService, UserService userService) {
public MessageService(Client client, PluginSettings settings,
CryptoService cryptoService, UserEventService userEventService) {
super("duniter." + INDEX, client, settings, cryptoService);
this.userEventService = userEventService;
}
/**
......@@ -114,6 +121,8 @@ public class MessageService extends AbstractService {
JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
String issuer = getIssuer(actualObj);
String recipient = getMandatoryField(actualObj, Message.PROPERTY_RECIPIENT).asText();
Long time = getMandatoryField(actualObj, Message.PROPERTY_TIME).asLong();
if (logger.isDebugEnabled()) {
logger.debug(String.format("Indexing a message from issuer [%s]", issuer.substring(0, 8)));
......@@ -124,7 +133,17 @@ public class MessageService extends AbstractService {
.setRefresh(false)
.execute().actionGet();
return response.getId();
String messageId = response.getId();
// Notify recipient
userEventService.notifyUser(UserEvent.newBuilder(UserEvent.EventType.INFO, UserEventCodes.MESSAGE_RECEIVED.name())
.setRecipient(recipient)
.setMessage(I18n.n("duniter.user.event.message.received"), issuer, ModelUtils.minifyPubkey(issuer))
.setTime(time)
.setReference(INDEX, RECORD_TYPE, messageId)
.build());
return messageId;
}
public String indexOuboxFromJson(String recordJson) {
......
......@@ -25,7 +25,9 @@ package org.duniter.elasticsearch.user.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Preconditions;
import org.apache.commons.collections4.MapUtils;
import org.duniter.core.client.model.ModelUtils;
import org.duniter.core.client.model.elasticsearch.UserProfile;
import org.duniter.core.exception.TechnicalException;
import org.duniter.core.service.CryptoService;
......@@ -214,6 +216,29 @@ public class UserService extends AbstractService {
return result;
}
public String joinNamesFromPubkeys(Set<String> pubkeys, String separator, boolean minify) {
Preconditions.checkNotNull(pubkeys);
Preconditions.checkNotNull(separator);
Preconditions.checkArgument(pubkeys.size()>0);
if (pubkeys.size() == 1) {
String pubkey = pubkeys.iterator().next();
String title = getProfileTitle(pubkey);
return title != null ? title :
(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey);
}
Map<String, String> profileTitles = getProfileTitles(pubkeys);
StringBuilder sb = new StringBuilder();
pubkeys.stream().forEach((pubkey)-> {
String title = profileTitles != null ? profileTitles.get(pubkey) : null;
sb.append(separator);
sb.append(title != null ? title :
(minify ? ModelUtils.minifyPubkey(pubkey) : pubkey));
});
return sb.substring(separator.length());
}
/* -- Internal methods -- */
......
......@@ -4,6 +4,7 @@ duniter.event.NODE_STARTED=Node started on cluster Duniter4j ES [%s]
duniter.user.event.active=
duniter.user.event.join=
duniter.user.event.leave=
duniter.user.event.message.received=
duniter.user.event.ms.active=
duniter.user.event.ms.join=
duniter.user.event.ms.leave=
......
duniter.event.NODE_BMA_DOWN=Noeud Duniter [%1$s\:%2$s] non joignable, depuis le noeud ES API [%3$s]. Dernière connexion à %4$d. Indexation de blockchain en attente.
duniter.event.NODE_BMA_UP=Noeud Duniter [%1$s\:%2$s] à nouveau accessible.
duniter.event.NODE_STARTED=Noeud ES API démarré sur le cluster Duniter [%1$s]
duniter.user.event.message.received=Vous avez reçu un message de %2$s
duniter.user.event.ms.active=Votre adhésion comme membre a bien été renouvellée
duniter.user.event.ms.join=Vous êtes maintenant membre de la monnaie
duniter.user.event.ms.leave=Votre adhésion comme membre à expirée
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment