From fb96b2a7e112a075a9c9bf133de690b4b297f6d7 Mon Sep 17 00:00:00 2001 From: blavenie <benoit.lavenier@e-is.pro> Date: Thu, 15 Dec 2016 08:31:39 +0100 Subject: [PATCH] - Notify user when new message --- .../duniter/core/client/model/ModelUtils.java | 20 +++++---- .../service/AbstractService.java | 2 +- .../user/model/UserEventCodes.java | 5 ++- .../service/BlockchainUserEventService.java | 45 ++----------------- .../user/service/MessageService.java | 23 +++++++++- .../user/service/UserService.java | 25 +++++++++++ .../i18n/duniter4j-es-user_en_GB.properties | 1 + .../i18n/duniter4j-es-user_fr_FR.properties | 1 + 8 files changed, 69 insertions(+), 53 deletions(-) diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java index 06f2cdd8..5b024359 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java @@ -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()); } } diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java index dce12461..852643dd 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java @@ -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) { diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java index e1a5053e..7f7ac356 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java @@ -38,6 +38,9 @@ public enum UserEventCodes { // TX TX_SENT, - TX_RECEIVED + TX_RECEIVED, + + // Message + MESSAGE_RECEIVED } diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/BlockchainUserEventService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/BlockchainUserEventService.java index 690a76bc..dec3f835 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/BlockchainUserEventService.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/BlockchainUserEventService.java @@ -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()); - } } diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/MessageService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/MessageService.java index 78053edf..e6cd1aa0 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/MessageService.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/MessageService.java @@ -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) { diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java index 003d7089..96b162cc 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java @@ -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 -- */ diff --git a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties index 4917ad91..d5b454c0 100644 --- a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties +++ b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties @@ -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= diff --git a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties index 03e86fc3..8e74a2b7 100644 --- a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties +++ b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties @@ -1,6 +1,7 @@ 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 -- GitLab