diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Discussion.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Discussion.java index d2634bb..16b8cfd 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Discussion.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/Discussion.java @@ -85,6 +85,13 @@ public class Discussion { return this.notes.get(0); } + public Optional getLastNote() { + if (this.notes.size() > 1) { + return Optional.ofNullable(this.notes.get(this.notes.size() - 1)); + } + return Optional.empty(); + } + public Optional getPrevLastNote() { final int size = notes.size(); if (size > 2) { diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/DiscussionNewNotify.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/DiscussionNewNotify.java index c953cab..882c1a3 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/DiscussionNewNotify.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/DiscussionNewNotify.java @@ -15,26 +15,24 @@ import static dev.struchkov.bot.gitlab.context.domain.notify.task.DiscussionNewN */ @Getter @FieldNames -public class DiscussionNewNotify extends TaskNotify { +public class DiscussionNewNotify extends ThreadNotify { public static final String TYPE = CLASS_NAME; private final String threadId; - private final String mrName; private final List> notes; @Builder public DiscussionNewNotify( String threadId, - String mrName, + String mergeRequestName, String authorName, String url, String discussionMessage, @Singular List> notes ) { - super(authorName, url, discussionMessage); + super(mergeRequestName, authorName, url, discussionMessage); this.threadId = threadId; - this.mrName = mrName; this.notes = notes; } diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskCloseNotify.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadCloseNotify.java similarity index 62% rename from bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskCloseNotify.java rename to bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadCloseNotify.java index bf43051..82f17f2 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskCloseNotify.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadCloseNotify.java @@ -11,24 +11,31 @@ import static dev.struchkov.bot.gitlab.context.domain.notify.task.TaskCloseNotif */ @Getter @FieldNames -public class TaskCloseNotify extends TaskNotify { +public class ThreadCloseNotify extends ThreadNotify { public static final String TYPE = CLASS_NAME; private final Long personTasks; private final Long personResolvedTasks; + private final String authorLastNote; + private final String messageLastNote; @Builder - protected TaskCloseNotify( + protected ThreadCloseNotify( + String mergeRequestName, String authorName, String url, String messageTask, Long personTasks, - Long personResolvedTasks + Long personResolvedTasks, + String authorLastNote, + String messageLastNote ) { - super(authorName, url, messageTask); + super(mergeRequestName, authorName, url, messageTask); this.personTasks = personTasks; this.personResolvedTasks = personResolvedTasks; + this.authorLastNote = authorLastNote; + this.messageLastNote = messageLastNote; } @Override diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskNotify.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadNotify.java similarity index 68% rename from bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskNotify.java rename to bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadNotify.java index cfe9db0..c8d34d2 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/TaskNotify.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/task/ThreadNotify.java @@ -4,17 +4,20 @@ import dev.struchkov.bot.gitlab.context.domain.notify.Notify; import lombok.Getter; @Getter -public abstract class TaskNotify implements Notify { +public abstract class ThreadNotify implements Notify { + protected final String mergeRequestName; protected final String authorName; protected final String url; protected final String messageTask; - protected TaskNotify( + protected ThreadNotify( + String mergeRequestName, String authorName, String url, String messageTask ) { + this.mergeRequestName = mergeRequestName; this.authorName = authorName; this.url = url; this.messageTask = messageTask; diff --git a/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/DiscussionServiceImpl.java b/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/DiscussionServiceImpl.java index 7dbbf9e..9114814 100644 --- a/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/DiscussionServiceImpl.java +++ b/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/impl/DiscussionServiceImpl.java @@ -9,7 +9,7 @@ import dev.struchkov.bot.gitlab.context.domain.entity.Person; import dev.struchkov.bot.gitlab.context.domain.notify.comment.NewCommentNotify; import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel; import dev.struchkov.bot.gitlab.context.domain.notify.task.DiscussionNewNotify; -import dev.struchkov.bot.gitlab.context.domain.notify.task.TaskCloseNotify; +import dev.struchkov.bot.gitlab.context.domain.notify.task.ThreadCloseNotify; import dev.struchkov.bot.gitlab.context.repository.DiscussionRepository; import dev.struchkov.bot.gitlab.context.service.AppSettingService; import dev.struchkov.bot.gitlab.context.service.DiscussionService; @@ -44,7 +44,9 @@ import static dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLev import static dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel.WITHOUT_NOTIFY; import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException; import static dev.struchkov.haiti.utils.Checker.checkNotNull; +import static dev.struchkov.haiti.utils.Checker.checkNull; import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; /** * Сервис для работы с дискуссиями. @@ -80,7 +82,7 @@ public class DiscussionServiceImpl implements DiscussionService { if (isNeedNotifyNewNote(discussion)) { notifyNewThread(discussion); } else { - notes.forEach(note -> notificationPersonal(discussion, note)); + notes.forEach(note -> notifyAboutPersonalAnswer(discussion, note)); } } else { discussion.setNotification(false); @@ -119,14 +121,14 @@ public class DiscussionServiceImpl implements DiscussionService { } } + final boolean resolved = discussion.getNotes().stream() + .allMatch(note -> note.isResolvable() && note.getResolved()); + discussion.setResolved(resolved); + if (oldDiscussion.isNotification()) { notifyUpdateNote(oldDiscussion, discussion); } - final boolean resolved = discussion.getNotes().stream() - .allMatch(note -> note.isResolvable() && note.getResolved()); - - discussion.setResolved(resolved); return repository.save(discussion); } @@ -148,7 +150,7 @@ public class DiscussionServiceImpl implements DiscussionService { } private void notifyUpdateNote(Discussion oldDiscussion, Discussion discussion) { - final Map noteMap = oldDiscussion + final Map oldNoteMap = oldDiscussion .getNotes().stream() .collect(Collectors.toMap(Note::getId, n -> n)); @@ -156,56 +158,73 @@ public class DiscussionServiceImpl implements DiscussionService { final boolean userParticipatedInDiscussion = oldDiscussion.getNotes().stream() .anyMatch(note -> personInformation.getId().equals(note.getAuthor().getId())); + final Note threadFirstNote = discussion.getFirstNote(); + if (TRUE.equals(discussion.getResolved())) { + notifyAboutCloseThread(threadFirstNote, oldNoteMap.get(threadFirstNote.getId()), discussion.getLastNote()); + } + for (Note newNote : discussion.getNotes()) { final Long newNoteId = newNote.getId(); - if (noteMap.containsKey(newNoteId)) { - final Note oldNote = noteMap.get(newNoteId); - - if (newNote.isResolvable()) { - updateTask(newNote, oldNote); - } - - } else { + if (!oldNoteMap.containsKey(newNoteId)) { if (userParticipatedInDiscussion) { - notifyNewAnswer(discussion, newNote); + notifyAboutNewAnswer(discussion, newNote); } else { - notificationPersonal(discussion, newNote); + notifyAboutPersonalAnswer(discussion, newNote); } } } } - private void updateTask(Note note, Note oldNote) { - if (isResolved(note, oldNote)) { - final MergeRequestForDiscussion mergeRequest = oldNote.getDiscussion().getMergeRequest(); - final List discussions = getAllByMergeRequestId(mergeRequest.getId()) - .stream() - .filter(discussion -> Objects.nonNull(discussion.getResponsible())) - .toList(); - final long allYouTasks = discussions.stream() - .filter(discussion -> personInformation.getId().equals(discussion.getFirstNote().getAuthor().getId())) - .count(); - final long resolvedYouTask = discussions.stream() - .filter(discussion -> personInformation.getId().equals(discussion.getFirstNote().getAuthor().getId()) && discussion.getResolved()) - .count(); - notifyService.send( - TaskCloseNotify.builder() + private void notifyAboutCloseThread(Note newNote, Note oldNote, Optional lastNote) { + final DiscussionLevel level = settingService.getLevelDiscussionNotify(); + if (!WITHOUT_NOTIFY.equals(level)) { + + if (isResolved(newNote, oldNote)) { + final MergeRequestForDiscussion mergeRequest = oldNote.getDiscussion().getMergeRequest(); + + final List discussions = getAllByMergeRequestId(mergeRequest.getId()) + .stream() + .filter(discussion -> Objects.nonNull(discussion.getResponsible())) + .toList(); + final long allYouTasks = discussions.stream() + .filter(discussion -> personInformation.getId().equals(discussion.getFirstNote().getAuthor().getId())) + .count(); + final long resolvedYouTask = discussions.stream() + .filter(discussion -> personInformation.getId().equals(discussion.getFirstNote().getAuthor().getId()) && discussion.getResolved()) + .count(); + + final ThreadCloseNotify.ThreadCloseNotifyBuilder notifyBuilder = ThreadCloseNotify.builder() + .mergeRequestName(mergeRequest.getTitle()) + .url(oldNote.getWebUrl()) + .personTasks(allYouTasks) + .personResolvedTasks(resolvedYouTask); + + if (NOTIFY_WITH_CONTEXT.equals(level)) { + notifyBuilder .authorName(oldNote.getAuthor().getName()) - .messageTask(oldNote.getBody()) - .url(oldNote.getWebUrl()) - .personTasks(allYouTasks) - .personResolvedTasks(resolvedYouTask) - .build() - ); + .messageTask(oldNote.getBody()); + + + lastNote.ifPresent( + note -> { + notifyBuilder.authorLastNote(note.getAuthor().getName()); + notifyBuilder.messageLastNote(note.getBody()); + } + ); + } + + notifyService.send(notifyBuilder.build()); + } + } } private boolean isResolved(Note note, Note oldNote) { - return oldNote.getResolvedBy() == null - && note.getResolvedBy() != null - && personInformation.getId().equals(oldNote.getAuthor().getId()) - && !note.getResolvedBy().getId().equals(oldNote.getAuthor().getId()); + return checkNull(oldNote.getResolvedBy()) // В старом комментарии не было отметки о решении + && checkNotNull(note.getResolvedBy()) // А в новом есть отметка + && personInformation.getId().equals(oldNote.getAuthor().getId()) // и решающий не является пользователем бота + && !note.getResolvedBy().getId().equals(oldNote.getAuthor().getId()); // и решающий не является автором треда } @@ -288,7 +307,7 @@ public class DiscussionServiceImpl implements DiscussionService { repository.notification(enable, discussionId); } - private void notifyNewAnswer(Discussion discussion, Note note) { + private void notifyAboutNewAnswer(Discussion discussion, Note note) { final DiscussionLevel discussionLevel = settingService.getLevelDiscussionNotify(); if (!WITHOUT_NOTIFY.equals(discussionLevel) @@ -322,7 +341,7 @@ public class DiscussionServiceImpl implements DiscussionService { /** * Уведомляет пользователя, если его никнейм упоминается в комментарии. */ - private void notificationPersonal(Discussion discussion, Note note) { + private void notifyAboutPersonalAnswer(Discussion discussion, Note note) { final DiscussionLevel discussionLevel = settingService.getLevelDiscussionNotify(); if (!WITHOUT_NOTIFY.equals(discussionLevel)) { final Matcher matcher = PATTERN.matcher(note.getBody()); @@ -372,10 +391,10 @@ public class DiscussionServiceImpl implements DiscussionService { final Note firstNote = discussion.getFirstNote(); final MergeRequestForDiscussion mergeRequest = discussion.getMergeRequest(); - DiscussionNewNotify.DiscussionNewNotifyBuilder messageBuilder = DiscussionNewNotify.builder() + final DiscussionNewNotify.DiscussionNewNotifyBuilder messageBuilder = DiscussionNewNotify.builder() .url(firstNote.getWebUrl()) .threadId(discussion.getId()) - .mrName(mergeRequest.getTitle()) + .mergeRequestName(mergeRequest.getTitle()) .authorName(firstNote.getAuthor().getName()); if (NOTIFY_WITH_CONTEXT.equals(discussionLevel)) { diff --git a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/NewCommentNotifyGenerator.java b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/NewCommentNotifyGenerator.java index df64778..4d082ce 100644 --- a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/NewCommentNotifyGenerator.java +++ b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/NewCommentNotifyGenerator.java @@ -24,26 +24,22 @@ public class NewCommentNotifyGenerator implements NotifyBoxAnswerGenerator> notes = notify.getNotes(); if (checkNotEmpty(notes)) { - builder.append("\n-- -- -- -- comments -- -- -- --\n") + builder.append("\n\n-- -- -- -- comments -- -- -- --\n") .append(convertNotes(notes)); } diff --git a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/ThreadCloseNotifyGenerate.java b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/ThreadCloseNotifyGenerate.java index ab23768..62dc03b 100644 --- a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/ThreadCloseNotifyGenerate.java +++ b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/ThreadCloseNotifyGenerate.java @@ -1,31 +1,55 @@ package dev.struchkov.bot.gitlab.telegram.service.notify; -import dev.struchkov.bot.gitlab.context.domain.notify.task.TaskCloseNotify; +import dev.struchkov.bot.gitlab.context.domain.notify.task.ThreadCloseNotify; import dev.struchkov.bot.gitlab.context.utils.Icons; import dev.struchkov.godfather.simple.domain.BoxAnswer; import org.springframework.stereotype.Component; -import static dev.struchkov.bot.gitlab.context.utils.Icons.link; +import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE; +import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton; import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer; +import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard; +import static dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton.urlButton; +import static dev.struchkov.haiti.utils.Checker.checkNotBlank; import static dev.struchkov.haiti.utils.Strings.escapeMarkdown; @Component -public class ThreadCloseNotifyGenerate implements NotifyBoxAnswerGenerator { +public class ThreadCloseNotifyGenerate implements NotifyBoxAnswerGenerator { @Override - public BoxAnswer generate(TaskCloseNotify notify) { + public BoxAnswer generate(ThreadCloseNotify notify) { - final StringBuilder builder = new StringBuilder(Icons.THREAD).append(" *Closed ").append(link("task", notify.getUrl())) - .append(Icons.HR) - .append("*").append(notify.getAuthorName()).append("*: ").append(escapeMarkdown(notify.getMessageTask())); + final StringBuilder builder = new StringBuilder(Icons.THREAD).append(" *Closed thread*") + .append("\n-- -- -- merge request -- -- --\n") + .append(escapeMarkdown(notify.getMergeRequestName())) + .append("\n"); + + if (checkNotBlank(notify.getAuthorName())) { + builder + .append("\n-- -- -- thread message -- -- --\n") + .append("*").append(escapeMarkdown(notify.getAuthorName())).append("*: ").append(escapeMarkdown(notify.getMessageTask())) + .append("\n"); + } + + if (checkNotBlank(notify.getAuthorLastNote())) { + builder + .append("\n-- -- -- last message -- -- -- --\n") + .append("*").append(escapeMarkdown(notify.getAuthorLastNote())).append("*: ").append(escapeMarkdown(notify.getMessageLastNote())); + } final String notifyMessage = builder.toString(); - return boxAnswer(notifyMessage); + return boxAnswer( + notifyMessage, + inlineKeyBoard( + simpleButton(Icons.VIEW, DELETE_MESSAGE), + urlButton(Icons.LINK, notify.getUrl()) + ) + ); } @Override public String getNotifyType() { - return TaskCloseNotify.TYPE; + return ThreadCloseNotify.TYPE; } }