diff --git a/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java b/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java index a65bccc..049576f 100644 --- a/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java +++ b/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java @@ -13,7 +13,7 @@ public class AppConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.setPoolSize(7); + taskScheduler.setPoolSize(10); return taskScheduler; } diff --git a/src/main/java/com/tsc/bitbucketbot/config/InitConfig.java b/src/main/java/com/tsc/bitbucketbot/config/InitConfig.java new file mode 100644 index 0000000..7a44231 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/config/InitConfig.java @@ -0,0 +1,16 @@ +package com.tsc.bitbucketbot.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "bitbucketbot.init") +public class InitConfig { + + private Long startCommentId; + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/Answer.java b/src/main/java/com/tsc/bitbucketbot/domain/Answer.java new file mode 100644 index 0000000..56d1f52 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/domain/Answer.java @@ -0,0 +1,19 @@ +package com.tsc.bitbucketbot.domain; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class Answer { + + private final String authorName; + private final String message; + + public static Answer of(@NonNull String name, @NonNull String message) { + return new Answer(name, message); + } + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/change/AnswerCommentChange.java b/src/main/java/com/tsc/bitbucketbot/domain/change/AnswerCommentChange.java new file mode 100644 index 0000000..5d68eb4 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/domain/change/AnswerCommentChange.java @@ -0,0 +1,33 @@ +package com.tsc.bitbucketbot.domain.change; + +import com.tsc.bitbucketbot.domain.Answer; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Singular; + +import java.util.List; +import java.util.Set; + +@Getter +@EqualsAndHashCode(callSuper = true) +public class AnswerCommentChange extends Change { + + private final String youMessage; + private final String url; + private final List answers; + + @Builder + protected AnswerCommentChange( + @Singular("telegramId") Set telegramId, + String youMessage, + String url, + List answers + ) { + super(ChangeType.NEW_ANSWERS_COMMENT, telegramId); + this.youMessage = youMessage; + this.url = url; + this.answers = answers; + } + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/change/ChangeType.java b/src/main/java/com/tsc/bitbucketbot/domain/change/ChangeType.java index 29397a2..8a0319d 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/change/ChangeType.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/change/ChangeType.java @@ -2,6 +2,12 @@ package com.tsc.bitbucketbot.domain.change; public enum ChangeType { - STATUS_PR, UPDATE_PR, REVIEWERS, NEW_PR, CONFLICT_PR + STATUS_PR, + UPDATE_PR, + REVIEWERS, + NEW_PR, + CONFLICT_PR, + NEW_COMMENT, + NEW_ANSWERS_COMMENT } diff --git a/src/main/java/com/tsc/bitbucketbot/domain/change/CommentChange.java b/src/main/java/com/tsc/bitbucketbot/domain/change/CommentChange.java new file mode 100644 index 0000000..29cb9e9 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/domain/change/CommentChange.java @@ -0,0 +1,30 @@ +package com.tsc.bitbucketbot.domain.change; + +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Singular; + +import java.util.Set; + +@Getter +@EqualsAndHashCode(callSuper = true) +public class CommentChange extends PrChange { + + private final String authorName; + private final String message; + + @Builder + private CommentChange( + @Singular("telegramId") Set telegramId, + String name, + String url, + String authorName, + String message + ) { + super(ChangeType.NEW_COMMENT, telegramId, name, url); + this.authorName = authorName; + this.message = message; + } + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/entity/Comment.java b/src/main/java/com/tsc/bitbucketbot/domain/entity/Comment.java index cf15c81..1445a84 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/entity/Comment.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/entity/Comment.java @@ -15,7 +15,7 @@ import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Set; @Getter @@ -30,17 +30,19 @@ public class Comment { @Id @Column(name = "id") -// @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "url") private String url; + @Column(name = "pr_url") + private String prUrl; + @Column(name = "telegram") private Long telegram; @Column(name = "date") - private LocalDate date; + private LocalDateTime date; @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "comment_tree", joinColumns = @JoinColumn(name = "parent_id")) diff --git a/src/main/java/com/tsc/bitbucketbot/repository/jpa/CommentRepository.java b/src/main/java/com/tsc/bitbucketbot/repository/jpa/CommentRepository.java index c19b116..7d37f8f 100644 --- a/src/main/java/com/tsc/bitbucketbot/repository/jpa/CommentRepository.java +++ b/src/main/java/com/tsc/bitbucketbot/repository/jpa/CommentRepository.java @@ -3,7 +3,7 @@ package com.tsc.bitbucketbot.repository.jpa; import com.tsc.bitbucketbot.domain.entity.Comment; import org.springframework.data.jpa.repository.JpaRepository; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -11,6 +11,6 @@ public interface CommentRepository extends JpaRepository { Optional findFirstByOrderByIdDesc(); - List findByDateBetween(LocalDate dateFrom, LocalDate dateTo); + List findByDateBetween(LocalDateTime dateFrom, LocalDateTime dateTo); } diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerChangeParsing.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerChangeParsing.java index 94aedaf..0fb3914 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerChangeParsing.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerChangeParsing.java @@ -1,6 +1,9 @@ package com.tsc.bitbucketbot.scheduler; +import com.tsc.bitbucketbot.domain.MessageSend; +import com.tsc.bitbucketbot.domain.change.AnswerCommentChange; import com.tsc.bitbucketbot.domain.change.Change; +import com.tsc.bitbucketbot.domain.change.CommentChange; import com.tsc.bitbucketbot.domain.change.ConflictPrChange; import com.tsc.bitbucketbot.domain.change.NewPrChange; import com.tsc.bitbucketbot.domain.change.ReviewersPrChange; @@ -25,23 +28,21 @@ public class SchedulerChangeParsing { private final MessageSendService messageSendService; private final ChangeService changeService; - // @Scheduled(cron = "0 * * * * *") - @Scheduled(fixedRate = 5000) + @Scheduled(cron = "30 */1 * * * MON-FRI") public void parsing() { final List newChange = changeService.getNew().stream() .filter(change -> change.getTelegramId() != null && !change.getTelegramId().isEmpty()) .collect(Collectors.toList()); for (Change change : newChange) { final String message = generateMessage(change); - System.out.println(message); -// change.getTelegramId().forEach( -// telegramId -> messageSendService.add( -// MessageSend.builder() -// .telegramId(telegramId) -// .message(message) -// .build() -// ) -// ); + change.getTelegramId().forEach( + telegramId -> messageSendService.add( + MessageSend.builder() + .telegramId(telegramId) + .message(message) + .build() + ) + ); } } @@ -63,6 +64,12 @@ public class SchedulerChangeParsing { case CONFLICT_PR: message = Message.generate(((ConflictPrChange) change)); break; + case NEW_COMMENT: + message = Message.generate(((CommentChange) change)); + break; + case NEW_ANSWERS_COMMENT: + message = Message.generate(((AnswerCommentChange) change)); + break; default: throw new NotFoundException("Нет обработчика для типа " + change.getType().name()); } diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerComments.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerComments.java index b6c79da..c3b4c4c 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerComments.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerComments.java @@ -1,17 +1,18 @@ package com.tsc.bitbucketbot.scheduler; import com.tsc.bitbucketbot.config.BitbucketConfig; -import com.tsc.bitbucketbot.domain.MessageSend; +import com.tsc.bitbucketbot.domain.Answer; import com.tsc.bitbucketbot.domain.Pagination; +import com.tsc.bitbucketbot.domain.change.AnswerCommentChange; +import com.tsc.bitbucketbot.domain.change.CommentChange; import com.tsc.bitbucketbot.domain.entity.Comment; import com.tsc.bitbucketbot.domain.entity.PullRequest; import com.tsc.bitbucketbot.dto.bitbucket.CommentJson; +import com.tsc.bitbucketbot.service.ChangeService; import com.tsc.bitbucketbot.service.CommentService; -import com.tsc.bitbucketbot.service.MessageSendService; import com.tsc.bitbucketbot.service.PullRequestsService; import com.tsc.bitbucketbot.service.UserService; import com.tsc.bitbucketbot.service.Utils; -import com.tsc.bitbucketbot.utils.Message; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,7 +20,8 @@ import org.springframework.data.domain.Page; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -33,17 +35,17 @@ import java.util.stream.Collectors; public class SchedulerComments { private static final Integer COUNT = 100; - private static final Integer NO_COMMENT = 100; + private static final Integer NO_COMMENT = 30; private static final Pattern PATTERN = Pattern.compile("@[\\w]+"); private final CommentService commentService; private final PullRequestsService pullRequestsService; - private final MessageSendService messageSendService; private final UserService userService; + private final ChangeService changeService; private final BitbucketConfig bitbucketConfig; - @Scheduled(cron = "0 */5 8-18 * * MON-FRI") + @Scheduled(cron = "0 */4 8-18 * * MON-FRI") public void newComments() { log.info("Начало сканирования комментариев"); long commentId = commentService.getLastCommentId() + 1; @@ -58,7 +60,7 @@ public class SchedulerComments { if (optCommentJson.isPresent()) { final CommentJson commentJson = optCommentJson.get(); notification(commentJson, pullRequest); - saveComments(commentJson, commentUrl); + saveComments(commentJson, commentUrl, pullRequest.getUrl()); count = 0; break; } @@ -73,7 +75,7 @@ public class SchedulerComments { @Scheduled(cron = "0 */1 8-18 * * MON-FRI") public void oldComments() { - @NonNull final List comments = commentService.getAllBetweenDate(LocalDate.now().minusDays(10), LocalDate.now()); + @NonNull final List comments = commentService.getAllBetweenDate(LocalDateTime.now().minusDays(10), LocalDateTime.now()); for (Comment comment : comments) { final Optional optCommentJson = Utils.urlToJson( comment.getUrl(), @@ -83,19 +85,23 @@ public class SchedulerComments { if (optCommentJson.isPresent()) { final CommentJson commentJson = optCommentJson.get(); final Set oldAnswerIds = comment.getAnswers(); - final List answerJsons = commentJson.getComments().stream() + final List newAnswers = commentJson.getComments().stream() .filter(answerJson -> !oldAnswerIds.contains(answerJson.getId())) .collect(Collectors.toList()); - if (!answerJsons.isEmpty()) { - userService.getTelegramIdByLogin(commentJson.getAuthor().getName()).ifPresent( - telegramAuthorComment -> messageSendService.add( - MessageSend.builder() - .telegramId(telegramAuthorComment) - .message(Message.answerComment(commentJson.getText(), answerJsons)) - .build() - ) + if (!newAnswers.isEmpty()) { + changeService.add( + AnswerCommentChange.builder() + .telegramId(userService.getTelegramIdByLogin(commentJson.getAuthor().getName()).orElse(null)) + .url(comment.getPrUrl()) + .youMessage(commentJson.getText()) + .answers( + newAnswers.stream() + .map(json -> Answer.of(json.getAuthor().getName(), json.getText())) + .collect(Collectors.toList()) + ) + .build() ); - comment.getAnswers().addAll(answerJsons.stream().map(CommentJson::getId).collect(Collectors.toList())); + comment.getAnswers().addAll(newAnswers.stream().map(CommentJson::getId).collect(Collectors.toList())); commentService.save(comment); } } @@ -103,11 +109,12 @@ public class SchedulerComments { } @NonNull - private void saveComments(CommentJson comment, String commentUrl) { + private void saveComments(CommentJson comment, String commentUrl, String prUrl) { final Comment newComment = new Comment(); newComment.setId(comment.getId()); - newComment.setDate(LocalDate.now()); + newComment.setDate(LocalDateTime.now()); newComment.setUrl(commentUrl); + newComment.setPrUrl(prUrl); userService.getTelegramIdByLogin(comment.getAuthor().getName()).ifPresent(newComment::setTelegram); commentService.save(newComment); } @@ -126,17 +133,21 @@ public class SchedulerComments { private void notificationPersonal(@NonNull CommentJson comment, @NonNull PullRequest pullRequest) { Matcher matcher = PATTERN.matcher(comment.getText()); + Set recipientsLogins = new HashSet<>(); while (matcher.find()) { final String login = matcher.group(0).replace("@", ""); - userService.getTelegramIdByLogin(login).ifPresent( - telegramId -> messageSendService.add( - MessageSend.builder() - .telegramId(telegramId) - .message(Message.personalNotify(comment, pullRequest.getName(), pullRequest.getUrl())) - .build() - ) - ); + recipientsLogins.add(login); } + final List recipientsIds = userService.getAllTelegramIdByLogin(recipientsLogins); + changeService.add( + CommentChange.builder() + .authorName(comment.getAuthor().getName()) + .name(pullRequest.getName()) + .url(pullRequest.getUrl()) + .telegramId(recipientsIds) + .message(comment.getText()) + .build() + ); } } diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNotification.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNotification.java index f433142..a32b76f 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNotification.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNotification.java @@ -43,26 +43,18 @@ public class SchedulerNotification { } } - // @Scheduled(cron = "0 0 18 * * FRI") -// @Scheduled(fixedRate = 30000) + @Scheduled(cron = "0 0 18 * * FRI") public void goodWeekEnd() { -// List allRegister = userService.getAllRegister(); -// for (User user : allRegister) { -// messageSendService.add( -// MessageSend.builder() -// .telegramId(user.getTelegramId()) -// .message(Message.goodWeekEnd()) -// .build() -// ); -// reportService.generateReport(user.getLogin()); -// } - final User user = userService.getByLogin("mstruchkov").get(); - messageSendService.add( - MessageSend.builder() - .telegramId(user.getTelegramId()) - .message(reportService.generateReport(user.getLogin())) - .build() - ); + List allRegister = userService.getAllRegister(); + for (User user : allRegister) { + messageSendService.add( + MessageSend.builder() + .telegramId(user.getTelegramId()) + .message(Message.goodWeekEnd()) + .build() + ); + reportService.generateReport(user.getLogin()); + } } } diff --git a/src/main/java/com/tsc/bitbucketbot/service/CommentService.java b/src/main/java/com/tsc/bitbucketbot/service/CommentService.java index 2f309fa..0f59a68 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/CommentService.java +++ b/src/main/java/com/tsc/bitbucketbot/service/CommentService.java @@ -5,7 +5,7 @@ import com.tsc.bitbucketbot.domain.entity.Comment; import lombok.NonNull; import org.springframework.data.domain.Page; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; public interface CommentService { @@ -15,7 +15,7 @@ public interface CommentService { Page getAll(@NonNull Pagination pagination); @NonNull - List getAllBetweenDate(LocalDate dateFrom, LocalDate dateTo); + List getAllBetweenDate(LocalDateTime dateFrom, LocalDateTime dateTo); void save(@NonNull Comment comment); diff --git a/src/main/java/com/tsc/bitbucketbot/service/impl/CommentServiceImpl.java b/src/main/java/com/tsc/bitbucketbot/service/impl/CommentServiceImpl.java index 313373e..6b8f584 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/impl/CommentServiceImpl.java +++ b/src/main/java/com/tsc/bitbucketbot/service/impl/CommentServiceImpl.java @@ -1,5 +1,6 @@ package com.tsc.bitbucketbot.service.impl; +import com.tsc.bitbucketbot.config.InitConfig; import com.tsc.bitbucketbot.domain.Pagination; import com.tsc.bitbucketbot.domain.entity.Comment; import com.tsc.bitbucketbot.repository.jpa.CommentRepository; @@ -10,7 +11,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Service @@ -18,10 +19,15 @@ import java.util.List; public class CommentServiceImpl implements CommentService { private final CommentRepository commentRepository; + private final InitConfig initConfig; @Override public Long getLastCommentId() { - return commentRepository.findFirstByOrderByIdDesc().map(Comment::getId).orElse(0L); + return commentRepository.findFirstByOrderByIdDesc().map(Comment::getId).orElse(getInitCommentId()); + } + + private Long getInitCommentId() { + return initConfig.getStartCommentId() != null ? initConfig.getStartCommentId() : 0L; } @Override @@ -30,7 +36,7 @@ public class CommentServiceImpl implements CommentService { } @Override - public @NonNull List getAllBetweenDate(LocalDate dateFrom, LocalDate dateTo) { + public @NonNull List getAllBetweenDate(LocalDateTime dateFrom, LocalDateTime dateTo) { return commentRepository.findByDateBetween(dateFrom, dateTo); } diff --git a/src/main/java/com/tsc/bitbucketbot/utils/Message.java b/src/main/java/com/tsc/bitbucketbot/utils/Message.java index f05cf23..7cc11cd 100644 --- a/src/main/java/com/tsc/bitbucketbot/utils/Message.java +++ b/src/main/java/com/tsc/bitbucketbot/utils/Message.java @@ -1,5 +1,7 @@ package com.tsc.bitbucketbot.utils; +import com.tsc.bitbucketbot.domain.change.AnswerCommentChange; +import com.tsc.bitbucketbot.domain.change.CommentChange; import com.tsc.bitbucketbot.domain.change.ConflictPrChange; import com.tsc.bitbucketbot.domain.change.NewPrChange; import com.tsc.bitbucketbot.domain.change.ReviewersPrChange; @@ -148,19 +150,19 @@ public class Message { comment.getAuthor().getName() + ": " + comment.getText().replaceAll("@[\\w]+", ""); } - public static String personalNotify(@NonNull CommentJson comment, @NonNull String namePr, @NonNull String urlPr) { - return Smile.BELL + " *Новое упоминание* | " + comment.getAuthor().getName() + Smile.BR + - link(namePr, urlPr) + + public static String generate(@NonNull CommentChange commentChange) { + return Smile.BELL + " *Новое упоминание* | " + commentChange.getAuthorName() + Smile.BR + + link(commentChange.getName(), commentChange.getUrl()) + Smile.HR + - comment.getText().replaceAll("@[\\w]+", ""); + commentChange.getMessage().replaceAll("@[\\w]+", ""); } - public static String answerComment(@NonNull String commentMessage, @NonNull List answerJsons) { + public static String generate(@NonNull AnswerCommentChange answerCommentChange) { final StringBuilder message = new StringBuilder(); - message.append(Smile.BELL).append("Новые ответы на ваш комментарий").append(Smile.HR) - .append(commentMessage, 0, Math.min(commentMessage.length(), 180)).append(Smile.HR); - answerJsons.forEach(answerJson -> message.append(answerJson.getAuthor().getName()).append(": ") - .append(answerJson.getText(), 0, Math.min(answerJson.getText().length(), 500)).append(Smile.TWO_BR)); + message.append(Smile.BELL).append("Новые ответы на ваш комментарий").append(" | ").append(link("ПР", answerCommentChange.getUrl())).append(Smile.HR) + .append(answerCommentChange.getYouMessage(), 0, Math.min(answerCommentChange.getYouMessage().length(), 180)).append(Smile.HR); + answerCommentChange.getAnswers().forEach(answer -> message.append(answer.getAuthorName()).append(": ") + .append(answer.getMessage(), 0, Math.min(answer.getMessage().length(), 500)).append(Smile.TWO_BR)); return message.toString(); } diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index 999e5a5..a7d173b 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -17,6 +17,8 @@ spring: lob: non_contextual_creation: true bitbucketbot: + init: + start-comment-id: server-send: url: http://188.225.35.149:8080/api/send bitbucket: diff --git a/src/main/resources/liquibase/change-set/v2.0.0.xml b/src/main/resources/liquibase/change-set/v2.0.0.xml index 742d149..8129fe1 100644 --- a/src/main/resources/liquibase/change-set/v2.0.0.xml +++ b/src/main/resources/liquibase/change-set/v2.0.0.xml @@ -15,4 +15,10 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index e106cf3..0335154 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -18,7 +18,7 @@ - + \ No newline at end of file