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

- Market/Registry: Add notification when replying to a comment

parent 1faa5f0c
No related branches found
No related tags found
No related merge requests found
...@@ -53,7 +53,7 @@ cluster.name: duniter4j-elasticsearch-TEST ...@@ -53,7 +53,7 @@ cluster.name: duniter4j-elasticsearch-TEST
# #
# Set the bind address to a specific IP (IPv4 or IPv6): # Set the bind address to a specific IP (IPv4 or IPv6):
# #
#network.host: 192.168.233.118 #network.host: 192.168.0.28
# #
# Set a custom port for HTTP: # Set a custom port for HTTP:
# #
...@@ -140,8 +140,8 @@ duniter.keyring.password: def ...@@ -140,8 +140,8 @@ duniter.keyring.password: def
# Enable security, to disable HTTP access to the default ES admin API # Enable security, to disable HTTP access to the default ES admin API
# #
duniter.security.enable: true
#duniter.security.enable: false #duniter.security.enable: false
duniter.security.enable: false
# #
# Security token prefix (default: 'duniter-') # Security token prefix (default: 'duniter-')
# #
......
...@@ -369,6 +369,10 @@ public abstract class AbstractService implements Bean { ...@@ -369,6 +369,10 @@ public abstract class AbstractService implements Bean {
return result.get(fieldName); return result.get(fieldName);
} }
protected <T> T getTypedFieldById(String index, String type, String docId, String fieldName) {
return (T)getFieldById(index, type, docId, fieldName);
}
/** /**
* Retrieve a document by id (safe mode) * Retrieve a document by id (safe mode)
* @param docId * @param docId
......
...@@ -6,5 +6,7 @@ package org.duniter.elasticsearch.gchange.model.event; ...@@ -6,5 +6,7 @@ package org.duniter.elasticsearch.gchange.model.event;
public enum GchangeEventCodes { public enum GchangeEventCodes {
NEW_COMMENT, NEW_COMMENT,
UPDATE_COMMENT UPDATE_COMMENT,
NEW_REPLY_COMMENT,
UPDATE_REPLY_COMMENT,
} }
...@@ -31,6 +31,7 @@ import org.duniter.core.client.model.bma.jackson.JacksonUtils; ...@@ -31,6 +31,7 @@ import org.duniter.core.client.model.bma.jackson.JacksonUtils;
import org.duniter.core.client.model.elasticsearch.RecordComment; import org.duniter.core.client.model.elasticsearch.RecordComment;
import org.duniter.core.exception.TechnicalException; import org.duniter.core.exception.TechnicalException;
import org.duniter.core.service.CryptoService; import org.duniter.core.service.CryptoService;
import org.duniter.core.util.StringUtils;
import org.duniter.core.util.websocket.WebsocketClientEndpoint; import org.duniter.core.util.websocket.WebsocketClientEndpoint;
import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.PluginSettings;
import org.duniter.elasticsearch.gchange.model.market.MarketRecord; import org.duniter.elasticsearch.gchange.model.market.MarketRecord;
...@@ -60,10 +61,14 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -60,10 +61,14 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
I18n.n("duniter.market.error.comment.recordNotFound"); I18n.n("duniter.market.error.comment.recordNotFound");
I18n.n("duniter.market.event.newComment"); I18n.n("duniter.market.event.newComment");
I18n.n("duniter.market.event.updateComment"); I18n.n("duniter.market.event.updateComment");
I18n.n("duniter.market.event.newReplyComment");
I18n.n("duniter.market.event.updateReplyComment");
I18n.n("duniter.registry.error.comment.recordNotFound"); I18n.n("duniter.registry.error.comment.recordNotFound");
I18n.n("duniter.registry.event.newComment"); I18n.n("duniter.registry.event.newComment");
I18n.n("duniter.registry.event.updateComment"); I18n.n("duniter.registry.event.updateComment");
I18n.n("duniter.registry.event.newReplyComment");
I18n.n("duniter.registry.event.updateReplyComment");
} }
public final UserService userService; public final UserService userService;
...@@ -76,6 +81,8 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -76,6 +81,8 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
public final boolean enable; public final boolean enable;
public final String recordType;
@Inject @Inject
public CommentUserEventService(Client client, PluginSettings settings, CryptoService cryptoService, public CommentUserEventService(Client client, PluginSettings settings, CryptoService cryptoService,
BlockchainService blockchainService, BlockchainService blockchainService,
...@@ -87,11 +94,13 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -87,11 +94,13 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
this.objectMapper = JacksonUtils.newObjectMapper(); this.objectMapper = JacksonUtils.newObjectMapper();
this.changeListenSources = ImmutableList.of( this.changeListenSources = ImmutableList.of(
new ChangeSource(MarketService.INDEX, MarketService.RECORD_COMMENT_TYPE), new ChangeSource(MarketService.INDEX, MarketService.RECORD_COMMENT_TYPE),
new ChangeSource(RegistryService.INDEX, MarketService.RECORD_COMMENT_TYPE)); new ChangeSource(RegistryService.INDEX, RegistryService.RECORD_COMMENT_TYPE));
ChangeService.registerListener(this); ChangeService.registerListener(this);
this.enable = pluginSettings.enableBlockchainSync(); this.enable = pluginSettings.enableBlockchainSync();
this.recordType = MarketService.RECORD_TYPE; // same as RegistryService.RECORD_TYPE
if (this.enable) { if (this.enable) {
blockchainService.registerConnectionListener(createConnectionListeners()); blockchainService.registerConnectionListener(createConnectionListeners());
} }
...@@ -107,19 +116,17 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -107,19 +116,17 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
try { try {
switch (change.getOperation()) { switch (change.getOperation()) {
case CREATE: case CREATE:
if (change.getSource() != null) { if (change.getSource() != null) {
RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class); RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class);
processCreateComment(change.getIndex(), MarketService.RECORD_TYPE, change.getId(), comment); processCreateComment(change.getIndex(), change.getType(), change.getId(), comment);
} }
break; break;
case INDEX: case INDEX:
if (change.getSource() != null) { if (change.getSource() != null) {
RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class); RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class);
processUpdateComment(change.getIndex(), MarketService.RECORD_TYPE, change.getId(), comment); processUpdateComment(change.getIndex(), change.getType(), change.getId(), comment);
} }
break; break;
...@@ -185,71 +192,73 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -185,71 +192,73 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
}; };
} }
private void processCreateComment(String index, String recordType, String commentId, RecordComment comment) { /**
* Send notification from a new comment
String issuer = comment.getIssuer(); *
String recordId = comment.getRecord(); * @param index
* @param type
* @param commentId
* @param comment
*/
private void processCreateComment(String index, String type, String commentId, RecordComment comment) {
// Notify issuer of record (is not same as comment writer) processUpdateOrCreateComment(index, type, commentId, comment,
Map<String, Object> recordFields = getFieldsById(index, recordType, recordId, GchangeEventCodes.NEW_COMMENT, String.format("duniter.%s.event.newComment", index.toLowerCase()),
MarketRecord.PROPERTY_TITLE, MarketRecord.PROPERTY_ISSUER); GchangeEventCodes.NEW_REPLY_COMMENT, String.format("duniter.%s.event.newReplyComment", index.toLowerCase()));
if (MapUtils.isEmpty(recordFields)) { // record not found }
logger.warn(I18n.t(String.format("duniter.%s.error.comment.recordNotFound", index.toLowerCase()), recordId));
}
String recordIssuer = recordFields.get(MarketRecord.PROPERTY_ISSUER).toString();
// Get user title /**
String issuerTitle = userService.getProfileTitle(issuer); * Same as processCreateComment(), but with other code and message.
*
* @param index
* @param type
* @param commentId
* @param comment
*/
private void processUpdateComment(String index, String type, String commentId, RecordComment comment) {
String recordTitle = recordFields.get(MarketRecord.PROPERTY_TITLE).toString(); processUpdateOrCreateComment(index, type, commentId, comment,
if (!issuer.equals(recordIssuer)) { GchangeEventCodes.UPDATE_COMMENT, String.format("duniter.%s.event.updateComment", index.toLowerCase()),
userEventService.notifyUser( GchangeEventCodes.UPDATE_REPLY_COMMENT, String.format("duniter.%s.event.updateReplyComment", index.toLowerCase()));
UserEvent.newBuilder(UserEvent.EventType.INFO, GchangeEventCodes.NEW_COMMENT.name())
.setMessage(
String.format("duniter.%s.event.newComment", index.toLowerCase()),
issuer,
issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
recordTitle
)
.setRecipient(recordIssuer)
.setReference(index, recordType, recordId)
.setReferenceAnchor(commentId)
.setTime(comment.getTime())
.build());
}
} }
/** /**
* Same as processCreateComment(), but with other code and message. * Same as processCreateComment(), but with other code and message.
* *
* @param index * @param index
* @param recordType * @param type
* @param commentId * @param commentId
* @param comment * @param comment
*/ */
private void processUpdateComment(String index, String recordType, String commentId, RecordComment comment) { private void processUpdateOrCreateComment(String index, String type, String commentId, RecordComment comment,
GchangeEventCodes eventCodeForRecordIssuer, String messageKeyForRecordIssuer,
String issuer = comment.getIssuer(); GchangeEventCodes eventCodeForParentCommentIssuer, String messageKeyForParentCommentIssuer) {
// Get record issuer
String recordId = comment.getRecord(); String recordId = comment.getRecord();
Map<String, Object> record = getFieldsById(index, this.recordType, recordId,
// Notify issuer of record (is not same as comment writer)
Map<String, Object> recordFields = getFieldsById(index, recordType, recordId,
MarketRecord.PROPERTY_TITLE, MarketRecord.PROPERTY_ISSUER); MarketRecord.PROPERTY_TITLE, MarketRecord.PROPERTY_ISSUER);
if (MapUtils.isEmpty(recordFields)) { // record not found
// Record not found : nothing to emit
if (MapUtils.isEmpty(record)) {
logger.warn(I18n.t(String.format("duniter.%s.error.comment.recordNotFound", index.toLowerCase()), recordId)); logger.warn(I18n.t(String.format("duniter.%s.error.comment.recordNotFound", index.toLowerCase()), recordId));
return; // no event to emit return;
} }
String recordIssuer = recordFields.get(MarketRecord.PROPERTY_ISSUER).toString();
// Get user title // Fetch record info
String recordIssuer = record.get(MarketRecord.PROPERTY_ISSUER).toString();
String recordTitle = record.get(MarketRecord.PROPERTY_TITLE).toString();
// Get comment issuer title
String issuer = comment.getIssuer();
String issuerTitle = userService.getProfileTitle(issuer); String issuerTitle = userService.getProfileTitle(issuer);
String recordTitle = recordFields.get(MarketRecord.PROPERTY_TITLE).toString(); // Notify issuer of record (is not same as comment writer)
if (!issuer.equals(recordIssuer)) { if (!issuer.equals(recordIssuer)) {
userEventService.notifyUser( userEventService.notifyUser(
UserEvent.newBuilder(UserEvent.EventType.INFO, GchangeEventCodes.UPDATE_COMMENT.name()) UserEvent.newBuilder(UserEvent.EventType.INFO, eventCodeForRecordIssuer.name())
.setMessage( .setMessage(
String.format("duniter.%s.event.updateComment", index.toLowerCase()), messageKeyForRecordIssuer,
issuer, issuer,
issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer), issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
recordTitle recordTitle
...@@ -261,6 +270,30 @@ public class CommentUserEventService extends AbstractService implements ChangeSe ...@@ -261,6 +270,30 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
.build()); .build());
} }
// Notify comment is a reply to another comment
if (StringUtils.isNotBlank(comment.getReplyTo())) {
String parentCommentIssuer = getTypedFieldById(index, type, commentId, RecordComment.PROPERTY_ISSUER);
if (StringUtils.isNotBlank(parentCommentIssuer) &&
!issuer.equals(parentCommentIssuer) &&
!recordIssuer.equals(parentCommentIssuer)) {
userEventService.notifyUser(
UserEvent.newBuilder(UserEvent.EventType.INFO, eventCodeForParentCommentIssuer.name())
.setMessage(
messageKeyForParentCommentIssuer,
issuer,
issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
recordTitle
)
.setRecipient(parentCommentIssuer)
.setReference(index, recordType, recordId)
.setReferenceAnchor(commentId)
.setTime(comment.getTime())
.build());
}
}
} }
......
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