From 73643cc626e79fa39563cd0254830cfc9d081228 Mon Sep 17 00:00:00 2001 From: Struchkov Mark Date: Wed, 8 Feb 2023 00:46:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BE=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D1=8F=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../context/domain/entity/AppSetting.java | 7 + .../context/domain/entity/Discussion.java | 16 ++ .../notify/comment/NewCommentNotify.java | 9 +- .../domain/notify/level/DiscussionLevel.java | 7 + .../service/impl/DiscussionServiceImpl.java | 156 ++++++++++-------- .../core/service/parser/ProjectParser.java | 11 +- .../gitlab/scheduler/SchedulerService.java | 2 +- .../v.2.0.0/2022-12-03-create-tables.xml | 3 + .../notify/DiscussionNewNotifyGenerator.java | 20 ++- .../notify/NewCommentNotifyGenerator.java | 12 +- .../bot/gitlab/telegram/unit/MenuConfig.java | 19 ++- .../telegram/unit/command/AnswerNoteUnit.java | 55 +++--- 12 files changed, 191 insertions(+), 126 deletions(-) create mode 100644 bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/level/DiscussionLevel.java diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/AppSetting.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/AppSetting.java index ec68dfd..a2e0fab 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/AppSetting.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/entity/AppSetting.java @@ -1,7 +1,10 @@ package dev.struchkov.bot.gitlab.context.domain.entity; +import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Getter; @@ -34,4 +37,8 @@ public class AppSetting { @Column(name = "project_private_scan") private boolean projectPrivateScan; + @Enumerated(EnumType.STRING) + @Column(name = "discussion_notify_level") + private DiscussionLevel discussionNotifyLevel; + } 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 ef20605..2e144e4 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 @@ -17,6 +17,8 @@ import lombok.Setter; import java.util.List; import java.util.Optional; +import static dev.struchkov.haiti.utils.Checker.checkNotEmpty; + /** * @author upagge 11.02.2021 */ @@ -62,6 +64,20 @@ public class Discussion { this.notes = notes; } + public int getNoteSize() { + if (checkNotEmpty(notes)) { + return notes.size(); + } + return 0; + } + + public Optional getNoteByNumber(int number) { + if (checkNotEmpty(notes) && number < notes.size()) { + return Optional.of(notes.get(number)); + } + return Optional.empty(); + } + public Note getFirstNote() { return this.notes.get(0); } diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/comment/NewCommentNotify.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/comment/NewCommentNotify.java index a0ffd7f..6e9f2b6 100644 --- a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/comment/NewCommentNotify.java +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/comment/NewCommentNotify.java @@ -9,6 +9,7 @@ public final class NewCommentNotify implements Notify { public static final String TYPE = "NewCommentNotify"; + private final String mergeRequestName; private final String url; private final String discussionMessage; private final String discussionAuthor; @@ -16,17 +17,21 @@ public final class NewCommentNotify implements Notify { private final String previousAuthor; private final String authorName; private final String message; + private final int numberNotes; @Builder public NewCommentNotify( + String mergeRequestName, String url, String discussionMessage, String discussionAuthor, String previousMessage, String previousAuthor, String authorName, - String message + String message, + int numberNotes ) { + this.mergeRequestName = mergeRequestName; this.url = url; this.discussionMessage = discussionMessage; this.discussionAuthor = discussionAuthor; @@ -34,9 +39,9 @@ public final class NewCommentNotify implements Notify { this.previousAuthor = previousAuthor; this.authorName = authorName; this.message = message; + this.numberNotes = numberNotes; } - @Override public String getType() { return TYPE; diff --git a/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/level/DiscussionLevel.java b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/level/DiscussionLevel.java new file mode 100644 index 0000000..73ad8bd --- /dev/null +++ b/bot-context/src/main/java/dev/struchkov/bot/gitlab/context/domain/notify/level/DiscussionLevel.java @@ -0,0 +1,7 @@ +package dev.struchkov.bot.gitlab.context.domain.notify.level; + +public enum DiscussionLevel { + + WITHOUT_NOTIFY, NOTIFY_WITHOUT_CONTEXT, NOTIFY_WITH_CONTEXT + +} 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 834262b..e3eb3f8 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 @@ -70,7 +70,7 @@ public class DiscussionServiceImpl implements DiscussionService { if (isNeedNotifyNewNote(discussion)) { notifyNewDiscussion(discussion); } else { - notes.forEach(this::notificationPersonal); + notes.forEach(note -> notificationPersonal(discussion, note)); } final boolean resolved = discussion.getNotes().stream() @@ -81,6 +81,39 @@ public class DiscussionServiceImpl implements DiscussionService { return repository.save(discussion); } + @Override + @Transactional + public Discussion update(@NonNull Discussion discussion) { + final Discussion oldDiscussion = repository.findById(discussion.getId()) + .orElseThrow(notFoundException("Дискуссия не найдена")); + + discussion.setResponsible(oldDiscussion.getResponsible()); + discussion.setMergeRequest(oldDiscussion.getMergeRequest()); + + final Person responsiblePerson = discussion.getResponsible(); + if (checkNotNull(responsiblePerson)) { + for (Note note : discussion.getNotes()) { + if (responsiblePerson.getId().equals(note.getAuthor().getId())) { + note.setAuthor(responsiblePerson); + } + final Person resolvedBy = note.getResolvedBy(); + if (checkNotNull(resolvedBy)) { + if (responsiblePerson.getId().equals(resolvedBy.getId())) { + note.setResolvedBy(responsiblePerson); + } + } + } + } + notifyUpdateNote(oldDiscussion, discussion); + + final boolean resolved = discussion.getNotes().stream() + .allMatch(note -> note.isResolvable() && note.getResolved()); + + discussion.setResolved(resolved); + + return repository.save(discussion); + } + /** *

Уведомляет пользователя, если появился новый комментарий

*/ @@ -116,39 +149,6 @@ public class DiscussionServiceImpl implements DiscussionService { && FALSE.equals(firstNote.getResolved()); // Комментарий не отмечен как решенный } - @Override - @Transactional - public Discussion update(@NonNull Discussion discussion) { - final Discussion oldDiscussion = repository.findById(discussion.getId()) - .orElseThrow(notFoundException("Дискуссия не найдена")); - - discussion.setResponsible(oldDiscussion.getResponsible()); - discussion.setMergeRequest(oldDiscussion.getMergeRequest()); - - final Person responsiblePerson = discussion.getResponsible(); - if (checkNotNull(responsiblePerson)) { - for (Note note : discussion.getNotes()) { - if (responsiblePerson.getId().equals(note.getAuthor().getId())) { - note.setAuthor(responsiblePerson); - } - final Person resolvedBy = note.getResolvedBy(); - if (checkNotNull(resolvedBy)) { - if (responsiblePerson.getId().equals(resolvedBy.getId())) { - note.setResolvedBy(responsiblePerson); - } - } - } - } - notifyUpdateNote(oldDiscussion, discussion); - - final boolean resolved = discussion.getNotes().stream() - .allMatch(note -> note.isResolvable() && note.getResolved()); - - discussion.setResolved(resolved); - - return repository.save(discussion); - } - @Override public List updateAll(@NonNull List discussions) { return discussions.stream() @@ -178,39 +178,13 @@ public class DiscussionServiceImpl implements DiscussionService { if (userParticipatedInDiscussion) { notifyNewAnswer(discussion, newNote); } else { - notificationPersonal(newNote); + notificationPersonal(discussion, newNote); } } } } - private void notifyNewAnswer(Discussion discussion, Note note) { - if (!personInformation.getId().equals(note.getAuthor().getId())) { - final Note firstNote = discussion.getFirstNote(); - final Optional prevLastNote = discussion.getPrevLastNote(); - - - final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder(); - - if (prevLastNote.isPresent()) { - final Note prevNote = prevLastNote.get(); - notifyBuilder.previousMessage(prevNote.getBody()); - notifyBuilder.previousAuthor(prevNote.getAuthor().getName()); - } - - notifyService.send( - notifyBuilder - .url(note.getWebUrl()) - .discussionMessage(firstNote.getBody()) - .discussionAuthor(firstNote.getAuthor().getName()) - .message(note.getBody()) - .authorName(note.getAuthor().getName()) - .build() - ); - } - } - private void updateTask(Note note, Note oldNote) { if (isResolved(note, oldNote)) { final MergeRequestForDiscussion mergeRequest = oldNote.getDiscussion().getMergeRequest(); @@ -253,20 +227,18 @@ public class DiscussionServiceImpl implements DiscussionService { final String requestUrl = MessageFormat.format(gitlabProperty.getNewNoteUrl(), projectId, mergeRequest.getTwoId(), discussion.getId(), text); - RequestBody formBody = new FormBody.Builder().build(); + final RequestBody formBody = new FormBody.Builder().build(); - Request request = new Request.Builder() + final Request request = new Request.Builder() .post(formBody) .header(StringUtils.H_PRIVATE_TOKEN, personProperty.getToken()) .url(requestUrl) .build(); - try { client.newCall(request).execute(); } catch (IOException e) { log.error(e.getMessage(), e); } - } @Override @@ -319,10 +291,36 @@ public class DiscussionServiceImpl implements DiscussionService { log.debug("Конец очистки старых дискуссий"); } + private void notifyNewAnswer(Discussion discussion, Note note) { + if (!personInformation.getId().equals(note.getAuthor().getId())) { + final Note firstNote = discussion.getFirstNote(); + final Optional prevLastNote = discussion.getPrevLastNote(); + + final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder() + .mergeRequestName(discussion.getMergeRequest().getTitle()); + + if (prevLastNote.isPresent()) { + final Note prevNote = prevLastNote.get(); + notifyBuilder.previousMessage(prevNote.getBody()); + notifyBuilder.previousAuthor(prevNote.getAuthor().getName()); + } + + notifyService.send( + notifyBuilder + .url(note.getWebUrl()) + .discussionMessage(firstNote.getBody()) + .discussionAuthor(firstNote.getAuthor().getName()) + .message(note.getBody()) + .authorName(note.getAuthor().getName()) + .build() + ); + } + } + /** * Уведомляет пользователя, если его никнейм упоминается в комментарии. */ - protected void notificationPersonal(@NonNull Note note) { + protected void notificationPersonal(Discussion discussion, Note note) { final Matcher matcher = PATTERN.matcher(note.getBody()); final Set recipientsLogins = new HashSet<>(); while (matcher.find()) { @@ -330,13 +328,25 @@ public class DiscussionServiceImpl implements DiscussionService { recipientsLogins.add(login); } if (recipientsLogins.contains(personInformation.getUsername())) { - notifyService.send( - NewCommentNotify.builder() - .authorName(note.getAuthor().getName()) - .message(note.getBody()) - .url(note.getWebUrl()) - .build() - ); + final Optional prevLastNote = discussion.getPrevLastNote(); + final Note firstNote = discussion.getFirstNote(); + + final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder() + .mergeRequestName(discussion.getMergeRequest().getTitle()) + .url(note.getWebUrl()) + .discussionMessage(firstNote.getBody()) + .discussionAuthor(firstNote.getAuthor().getName()); + if (!firstNote.equals(note)) { + notifyBuilder.message(note.getBody()) + .authorName(note.getAuthor().getName()); + } + if (prevLastNote.isPresent()) { + final Note prevNote = prevLastNote.get(); + notifyBuilder.previousMessage(prevNote.getBody()); + notifyBuilder.previousAuthor(prevNote.getAuthor().getName()); + } + + notifyService.send(notifyBuilder.build()); } } diff --git a/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/ProjectParser.java b/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/ProjectParser.java index 8eb9acf..fc31a05 100644 --- a/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/ProjectParser.java +++ b/bot-core/src/main/java/dev/struchkov/bot/gitlab/core/service/parser/ProjectParser.java @@ -26,7 +26,6 @@ import java.util.stream.Collectors; import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; import static dev.struchkov.haiti.context.exception.ConvertException.convertException; import static dev.struchkov.haiti.utils.Checker.checkNotEmpty; -import static java.util.Collections.singleton; /** * Парсер проектов. @@ -88,7 +87,7 @@ public class ProjectParser { } } - public void parseByUrl(String projectUrl) { + public Project parseByUrl(String projectUrl) { final ProjectJson projectJson = HttpParse.request(projectUrl) .header(ACCEPT) .header(StringUtils.H_PRIVATE_TOKEN, personProperty.getToken()) @@ -96,14 +95,10 @@ public class ProjectParser { .orElseThrow(convertException("Ошибка получения репозитория.")); if (!projectService.existsById(projectJson.getId())) { createNewPersons(List.of(projectJson)); - final Project newProject = conversionService.convert(projectJson, Project.class); - projectService.create(newProject); + return projectService.create(newProject); } else { - final Set projectId = singleton(projectJson.getId()); - projectService.notification(true, projectId); - projectService.processing(true, projectId); - mergeRequestsService.notificationByProjectId(true, projectId); + return projectService.getByIdOrThrow(projectJson.getId()); } } diff --git a/gitlab-app/src/main/java/dev/struchkov/bot/gitlab/scheduler/SchedulerService.java b/gitlab-app/src/main/java/dev/struchkov/bot/gitlab/scheduler/SchedulerService.java index ae4648a..9116efe 100644 --- a/gitlab-app/src/main/java/dev/struchkov/bot/gitlab/scheduler/SchedulerService.java +++ b/gitlab-app/src/main/java/dev/struchkov/bot/gitlab/scheduler/SchedulerService.java @@ -32,7 +32,7 @@ public class SchedulerService { private final MergeRequestsService mergeRequestsService; private final DiscussionService discussionService; - @Scheduled(cron = "0 */2 * * * *") + @Scheduled(cron = "0 */1 * * * *") public void newMergeRequest() { log.info("Запуск процесса обновления данных c GitLab"); if (!settingService.isFirstStart()) { diff --git a/gitlab-app/src/main/resources/liquibase/v.2.0.0/2022-12-03-create-tables.xml b/gitlab-app/src/main/resources/liquibase/v.2.0.0/2022-12-03-create-tables.xml index 1d9369f..abef4c4 100644 --- a/gitlab-app/src/main/resources/liquibase/v.2.0.0/2022-12-03-create-tables.xml +++ b/gitlab-app/src/main/resources/liquibase/v.2.0.0/2022-12-03-create-tables.xml @@ -20,6 +20,9 @@ + + + diff --git a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/DiscussionNewNotifyGenerator.java b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/DiscussionNewNotifyGenerator.java index 2acf68f..dd28844 100644 --- a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/DiscussionNewNotifyGenerator.java +++ b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/service/notify/DiscussionNewNotifyGenerator.java @@ -9,8 +9,12 @@ import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; +import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE; import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer; -import static dev.struchkov.haiti.utils.Checker.checkNotNull; +import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton; +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.checkNotEmpty; import static dev.struchkov.haiti.utils.Strings.escapeMarkdown; @Component @@ -18,20 +22,26 @@ public class DiscussionNewNotifyGenerator implements NotifyBoxAnswerGenerator> notes = notify.getNotes(); - if (checkNotNull(notes)) { + if (checkNotEmpty(notes)) { builder.append("\n-- -- -- -- comments -- -- -- --\n") .append(convertNotes(notes)); } final String notifyMessage = builder.toString(); - return boxAnswer(notifyMessage); + return boxAnswer( + notifyMessage, + inlineKeyBoard( + simpleButton(Icons.VIEW, DELETE_MESSAGE), + urlButton(Icons.LINK, notify.getUrl()) + ) + ); } private String convertNotes(List> notes) { 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 2181bb6..0b9f41d 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 @@ -14,10 +14,12 @@ public class NewCommentNotifyGenerator implements NotifyBoxAnswerGenerator accessError() { @@ -134,7 +137,11 @@ public class MenuConfig { final String projectUrl = gitlabProperty.getProjectAddUrl() + link.getUrl().replace(gitlabProperty.getBaseUrl(), "") .substring(1) .replace("/", "%2F"); - projectParser.parseByUrl(projectUrl); + final Project project = projectParser.parseByUrl(projectUrl); + final Set projectId = singleton(project.getId()); + projectService.notification(true, projectId); + projectService.processing(true, projectId); + mergeRequestsService.notificationByProjectId(true, projectId); } return boxAnswer("\uD83D\uDC4D Projects added successfully!"); }) diff --git a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/unit/command/AnswerNoteUnit.java b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/unit/command/AnswerNoteUnit.java index 0dcc772..0848aad 100644 --- a/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/unit/command/AnswerNoteUnit.java +++ b/telegram-bot/src/main/java/dev/struchkov/bot/gitlab/telegram/unit/command/AnswerNoteUnit.java @@ -5,20 +5,19 @@ import dev.struchkov.bot.gitlab.context.domain.entity.Note; import dev.struchkov.bot.gitlab.context.service.AppSettingService; import dev.struchkov.bot.gitlab.context.service.DiscussionService; import dev.struchkov.bot.gitlab.context.service.NoteService; -import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.annotation.Unit; -import dev.struchkov.godfather.main.domain.content.Attachment; import dev.struchkov.godfather.main.domain.content.Mail; import dev.struchkov.godfather.simple.core.unit.AnswerText; import dev.struchkov.godfather.telegram.domain.attachment.LinkAttachment; -import dev.struchkov.godfather.telegram.domain.attachment.TelegramAttachmentType; import dev.struchkov.godfather.telegram.main.core.util.Attachments; +import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending; import dev.struchkov.haiti.utils.Checker; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.text.MessageFormat; import java.util.List; +import java.util.concurrent.ScheduledExecutorService; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,21 +34,24 @@ public class AnswerNoteUnit { private final AppSettingService settingService; private final NoteService noteService; private final DiscussionService discussionService; + private final ScheduledExecutorService scheduledExecutorService; + private final TelegramSending telegramSending; - @Unit(value = ANSWER_NOTE, main = true) + //TODO [07.02.2023|uPagge]: Можно возвращать ссылку на ответ + @Unit(value = ANSWER_NOTE, global = true) public AnswerText answerNote() { return AnswerText.builder() .triggerCheck( mail -> { - final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId()); - if (isAccess) { - final boolean isFirstStart = settingService.isFirstStart(); - if (!isFirstStart) { - final List forwardMails = mail.getForwardMail(); - if (Checker.checkNotNull(forwardMails) && forwardMails.size() == 1) { - final Mail forwardMail = forwardMails.get(0); - return Attachments.findFirstLink(forwardMail.getAttachments()).isPresent(); - } + final List forwardMails = mail.getForwardMail(); + if (Checker.checkNotNull(forwardMails) && forwardMails.size() == 1) { + final Mail forwardMail = forwardMails.get(0); + final boolean isLink = Attachments.findFirstLink(forwardMail.getAttachments()) + .isPresent(); + if (isLink) { + final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId()); + final boolean firstStart = settingService.isFirstStart(); + return isAccess && !firstStart; } } return false; @@ -57,20 +59,19 @@ public class AnswerNoteUnit { ) .answer( mail -> { - final List attachments = mail.getForwardMail().get(0).getAttachments(); - for (Attachment attachment : attachments) { - if (TelegramAttachmentType.LINK.name().equals(attachment.getType())) { - final String url = ((LinkAttachment) attachment).getUrl(); - final Matcher matcher = NOTE_LINK.matcher(url); - if (matcher.find()) { - final String noteText = url.substring(matcher.start(), matcher.end()); - final Long noteId = Long.valueOf(noteText.replaceAll("#note_", "")); - final Note note = noteService.getByIdOrThrow(noteId); - final String discussionId = note.getDiscussion().getId(); - discussionService.answer(discussionId, MessageFormat.format("@{0}, {1}", note.getAuthor().getUserName(), mail.getText())); - return BoxAnswer.builder().build(); - } - } + final String noteUrl = Attachments.findFirstLink(mail.getForwardMail().get(0).getAttachments()) + .map(LinkAttachment::getUrl) + .orElseThrow(); + final Matcher matcher = NOTE_LINK.matcher(noteUrl); + if (matcher.find()) { + final String noteText = noteUrl.substring(matcher.start(), matcher.end()); + final Long noteId = Long.valueOf(noteText.replace("#note_", "")); + final Note note = noteService.getByIdOrThrow(noteId); + final String discussionId = note.getDiscussion().getId(); + discussionService.answer(discussionId, MessageFormat.format("@{0}, {1}", note.getAuthor().getUserName(), mail.getText())); + return boxAnswer( + "\uD83D\uDC4D Response sent successfully" + ); } return boxAnswer("Error"); }