diff --git a/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java b/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java index 04e7e0c..a259e07 100644 --- a/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java +++ b/src/main/java/com/tsc/bitbucketbot/config/AppConfig.java @@ -64,7 +64,7 @@ public class AppConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.setPoolSize(5); + taskScheduler.setPoolSize(6); return taskScheduler; } diff --git a/src/main/java/com/tsc/bitbucketbot/domain/Pagination.java b/src/main/java/com/tsc/bitbucketbot/domain/Pagination.java new file mode 100644 index 0000000..c184060 --- /dev/null +++ b/src/main/java/com/tsc/bitbucketbot/domain/Pagination.java @@ -0,0 +1,24 @@ +package com.tsc.bitbucketbot.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * TODO: Добавить описание класса. + * + * @author upagge [03.02.2020] + */ +@Data +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class Pagination { + + private Integer page; + private Integer size; + + public static Pagination of(Integer page, Integer size) { + return new Pagination(page, size); + } + + +} diff --git a/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java b/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java index cfdb455..4923cf7 100644 --- a/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java +++ b/src/main/java/com/tsc/bitbucketbot/domain/entity/PullRequest.java @@ -14,6 +14,7 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -45,7 +46,7 @@ public class PullRequest { @JoinColumn(name = "autor_login") private User author; - @OneToMany(mappedBy = "pullRequestId", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "pullRequestId", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List reviewers; @Column(name = "url") diff --git a/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java b/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java index 2690022..c985301 100644 --- a/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java +++ b/src/main/java/com/tsc/bitbucketbot/repository/PullRequestsRepository.java @@ -3,7 +3,6 @@ package com.tsc.bitbucketbot.repository; import com.tsc.bitbucketbot.domain.entity.PullRequest; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; import java.util.Set; /** @@ -13,4 +12,6 @@ import java.util.Set; */ public interface PullRequestsRepository extends JpaRepository { + Set findAllByIdIn(Set ids); + } diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNewUser.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNewUser.java index 2c76ead..19bd06e 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNewUser.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerNewUser.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class SchedulerNewUser { - public static final String URL = "http://192.168.236.164:7990/rest/api/1.0/admin/users"; + private static final String URL = "http://192.168.236.164:7990/rest/api/1.0/admin/users"; private final UserService userService; private final ConversionService conversionService; private final BitbucketConfig bitbucketConfig; diff --git a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java index e1be70f..4295bd1 100644 --- a/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java +++ b/src/main/java/com/tsc/bitbucketbot/scheduler/SchedulerPullRequest.java @@ -2,9 +2,9 @@ package com.tsc.bitbucketbot.scheduler; import com.tsc.bitbucketbot.bitbucket.PullRequestJson; import com.tsc.bitbucketbot.bitbucket.UserDecisionJson; -import com.tsc.bitbucketbot.bitbucket.UserPullRequestStatus; import com.tsc.bitbucketbot.bitbucket.sheet.PullRequestSheetJson; import com.tsc.bitbucketbot.config.BitbucketConfig; +import com.tsc.bitbucketbot.domain.PullRequestStatus; import com.tsc.bitbucketbot.domain.ReviewerStatus; import com.tsc.bitbucketbot.domain.entity.PullRequest; import com.tsc.bitbucketbot.domain.entity.Reviewer; @@ -12,6 +12,7 @@ import com.tsc.bitbucketbot.domain.entity.User; import com.tsc.bitbucketbot.service.PullRequestsService; import com.tsc.bitbucketbot.service.UserService; import com.tsc.bitbucketbot.service.Utils; +import com.tsc.bitbucketbot.service.converter.PullRequestJsonConverter; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.sadtech.social.core.domain.BoxAnswer; @@ -20,7 +21,6 @@ import org.springframework.core.convert.ConversionService; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,7 +37,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class SchedulerPullRequest { - private static final String URL = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=50&state=OPEN"; + private static final String URL_NEW_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&state=OPEN"; + private static final String URL_OLD_PR = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400"; private final BitbucketConfig bitbucketConfig; private final PullRequestsService pullRequestsService; private final UserService userService; @@ -45,34 +46,34 @@ public class SchedulerPullRequest { private final Sending sending; @Scheduled(fixedRate = 15000) - public void checkNewPullRequest() { + public void checkOldPullRequest() { final List users = userService.getAllRegistered(); for (User user : users) { - Optional sheetJson = Utils.urlToJson(URL, user.getToken(), PullRequestSheetJson.class); + Optional sheetJson = Utils.urlToJson(URL_OLD_PR, user.getToken(), PullRequestSheetJson.class); while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) { final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get(); - final Set pullRequestBitbucketId = pullRequestBitbucketSheet.getValues().stream() - .map(PullRequestJson::getId) - .collect(Collectors.toSet()); - Set existsId = pullRequestsService.existsAllById(pullRequestBitbucketId); - final Set newPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() - .filter(pullRequestJson -> !existsId.contains(pullRequestJson.getId())) - .collect(Collectors.toSet()); - pullRequestsService.addAll( - newPullRequestBitbucket.stream() - .map(pullRequestJson -> conversionService.convert(pullRequestJson, PullRequest.class)) + Set existsId = pullRequestsService.existsById( + pullRequestBitbucketSheet.getValues().stream() + .map(PullRequestJson::getId) .collect(Collectors.toSet()) ); - final List newPullRequests = new ArrayList<>(); - for (PullRequestJson pullRequestJson : newPullRequestBitbucket) { - final List reviewers = pullRequestJson.getReviewers().stream() - .map(reviewer -> testConvert(pullRequestJson, reviewer)) - .collect(Collectors.toList()); - pullRequestsService.addReviewer(pullRequestJson.getId(), reviewers).ifPresent(newPullRequests::add); + final Map existsPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() + .filter(pullRequestJson -> existsId.contains(pullRequestJson.getId())) + .collect(Collectors.toMap(PullRequestJson::getId, pullRequestJson -> pullRequestJson)); + final Set pullRequests = pullRequestsService.getAllById(existsId); + if (!existsPullRequestBitbucket.isEmpty() && !pullRequests.isEmpty()) { + processingUpdate(existsPullRequestBitbucket, pullRequests); + } + + if (!existsPullRequestBitbucket.isEmpty()) { + pullRequestsService.updateAll( + existsPullRequestBitbucket.values().stream() + .map(pullRequestBitbucket -> conversionService.convert(pullRequestBitbucket, PullRequest.class)) + .collect(Collectors.toList()) + ); } - sendNotification(newPullRequests); if (pullRequestBitbucketSheet.getNextPageStart() != null) { - sheetJson = Utils.urlToJson(URL + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); + sheetJson = Utils.urlToJson(URL_OLD_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); } else { break; } @@ -80,24 +81,81 @@ public class SchedulerPullRequest { } } - private Reviewer testConvert(PullRequestJson pullRequestJson, UserDecisionJson reviewer) { - final Reviewer newReviewer = new Reviewer(); - newReviewer.setPullRequestId(pullRequestJson.getId()); - newReviewer.setUser(reviewer.getUser().getName()); - newReviewer.setStatus(convertStatusReviewer(reviewer.getStatus())); - return newReviewer; + private void processingUpdate(Map existsPullRequestBitbucket, Set pullRequests) { + for (PullRequest pullRequest : pullRequests) { + final PullRequestJson pullRequestBitbucket = existsPullRequestBitbucket.get(pullRequest.getId()); + final User author = pullRequest.getAuthor(); + if (author.getTelegramId() != null) { + sendStatusPR(pullRequest, pullRequestBitbucket); + sendReviewersPR(pullRequest, pullRequestBitbucket); + } + } } - private ReviewerStatus convertStatusReviewer(UserPullRequestStatus status) { - switch (status) { - case APPROVED: - return ReviewerStatus.APPROVED; - case NEEDS_WORK: - return ReviewerStatus.UNAPPROVED; - case UNAPPROVED: - return ReviewerStatus.NEEDS_WORK; + private void sendReviewersPR(PullRequest pullRequest, PullRequestJson pullRequestBitbucket) { + final Map oldReviewers = pullRequest.getReviewers().stream().collect(Collectors.toMap(Reviewer::getUser, reviewer -> reviewer)); + final List newReviewers = pullRequestBitbucket.getReviewers(); + for (UserDecisionJson newReviewer : newReviewers) { + if (oldReviewers.containsKey(newReviewer.getUser().getName())) { + final Reviewer oldReviewer = oldReviewers.get(newReviewer.getUser().getName()); + final ReviewerStatus oldStatus = oldReviewer.getStatus(); + final ReviewerStatus newStatus = PullRequestJsonConverter.convertStatusReviewer(newReviewer.getStatus()); + boolean flag = false; + StringBuilder stringBuilder = new StringBuilder("✏️ *Изменилось решение по вашему ПР*\n") + .append("[").append(pullRequest.getName()).append("](").append(pullRequest.getUrl()).append(")\n"); + if (!oldStatus.equals(newStatus)) { + flag = true; + stringBuilder.append("\uD83D\uDC68\u200D\uD83D\uDCBB️ ").append(oldReviewer.getUser()).append(" ") + .append(oldStatus).append(" -> ").append(newStatus).append("\n"); + } + if (flag) { + sending.send(pullRequest.getAuthor().getTelegramId(), BoxAnswer.of(stringBuilder.toString())); + } + } + } + } + + private void sendStatusPR(PullRequest pullRequest, PullRequestJson pullRequestBitbucket) { + final PullRequestStatus oldStatus = pullRequest.getStatus(); + final PullRequestStatus newStatus = PullRequestJsonConverter.convertPullRequestStatus(pullRequestBitbucket.getState()); + if (!oldStatus.equals(newStatus)) { + StringBuilder stringBuilder = new StringBuilder("✏️ *Изменился статус вашего ПР*\n") + .append("[").append(pullRequest.getName()).append("](").append(pullRequest.getUrl()).append(")\n") + .append(oldStatus.name()).append(" -> ").append(newStatus.name()) + .append("\n-- -- -- --\n") + .append("\uD83D\uDCCC: #pullRequest #change") + .append("\n\n"); + sending.send(pullRequest.getAuthor().getTelegramId(), BoxAnswer.of(stringBuilder.toString())); + } + } + + @Scheduled(fixedRate = 15000) + public void checkNewPullRequest() { + final List users = userService.getAllRegistered(); + for (User user : users) { + Optional sheetJson = Utils.urlToJson(URL_NEW_PR, user.getToken(), PullRequestSheetJson.class); + while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) { + final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get(); + final Set pullRequestBitbucketId = pullRequestBitbucketSheet.getValues().stream() + .map(PullRequestJson::getId) + .collect(Collectors.toSet()); + Set existsId = pullRequestsService.existsAllIdById(pullRequestBitbucketId); + final Set newPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream() + .filter(pullRequestJson -> !existsId.contains(pullRequestJson.getId())) + .collect(Collectors.toSet()); + final List newPullRequests = pullRequestsService.addAll( + newPullRequestBitbucket.stream() + .map(pullRequestJson -> conversionService.convert(pullRequestJson, PullRequest.class)) + .collect(Collectors.toSet()) + ); + sendNotification(newPullRequests); + if (pullRequestBitbucketSheet.getNextPageStart() != null) { + sheetJson = Utils.urlToJson(URL_NEW_PR + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class); + } else { + break; + } + } } - return null; } private void sendNotification(@NonNull List newPullRequests) { @@ -118,9 +176,14 @@ public class SchedulerPullRequest { final Long telegramId = user.getTelegramId(); if (telegramId != null) { if (!map.containsKey(telegramId)) { - map.put(telegramId, new StringBuilder("У вас есть новые ПР:\n\n")); + map.put(telegramId, new StringBuilder()); } - map.get(telegramId).append("*").append(pullRequest.getName()).append("*\n").append("Автор: ").append(pullRequest.getAuthor().getName()).append("\nСсылка: ").append(pullRequest.getUrl()).append("\n-- -- -- -- --\n\n"); + map.get(telegramId).append("\uD83C\uDF89 *Новый Pull Request*\n") + .append("[").append(pullRequest.getName()).append("](").append(pullRequest.getUrl()).append(")\n") + .append("\uD83D\uDC68\u200D\uD83D\uDCBB️: ").append(pullRequest.getAuthor().getName()) + .append("\n-- -- -- -- --\n") + .append("\uD83D\uDCCC: ").append("#").append(pullRequest.getAuthor().getLogin()).append(" #pullRequest") + .append("\n\n"); } } ); diff --git a/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java b/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java index 7b64ccc..c89fcc4 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java +++ b/src/main/java/com/tsc/bitbucketbot/service/PullRequestsService.java @@ -15,11 +15,14 @@ import java.util.Set; */ public interface PullRequestsService { - Set existsById(@NonNull final Set idList); + Set existsById(@NonNull final Set pullRequestId); - Set existsAllById(@NonNull Set pullRequestJsonId); + Set existsAllIdById(@NonNull Set pullRequestId); - List addAll(Set pullRequests); + Set getAllById(@NonNull Set pullRequestJsonId); + + List addAll(@NonNull Set pullRequests); + + List updateAll(@NonNull List pullRequests); - Optional addReviewer(@NonNull Long pullRequestJsonId, @NonNull List reviewers); } diff --git a/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java b/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java index 6ba32c9..11b52c8 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java +++ b/src/main/java/com/tsc/bitbucketbot/service/converter/PullRequestJsonConverter.java @@ -2,15 +2,22 @@ package com.tsc.bitbucketbot.service.converter; import com.tsc.bitbucketbot.bitbucket.PullRequestJson; import com.tsc.bitbucketbot.bitbucket.PullRequestState; +import com.tsc.bitbucketbot.bitbucket.UserDecisionJson; import com.tsc.bitbucketbot.bitbucket.UserJson; +import com.tsc.bitbucketbot.bitbucket.UserPullRequestStatus; import com.tsc.bitbucketbot.domain.PullRequestStatus; +import com.tsc.bitbucketbot.domain.ReviewerStatus; import com.tsc.bitbucketbot.domain.entity.PullRequest; +import com.tsc.bitbucketbot.domain.entity.Reviewer; import com.tsc.bitbucketbot.domain.entity.User; import com.tsc.bitbucketbot.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.stream.Collectors; + /** * TODO: Добавить описание класса. * @@ -31,6 +38,7 @@ public class PullRequestJsonConverter implements Converter convertReviewers(PullRequest pullRequest, List jsonReviewers) { -// return jsonReviewers.stream() -// .map( -// jsonReviewer -> { -// final Reviewer reviewer = new Reviewer(); -// reviewer.setReviewerKey(new ReviewerKey(convertUser(jsonReviewer.getUser()).getLogin())); -// reviewer.setStatus(convertStatusReviewer(jsonReviewer.getStatus())); -// return reviewer; -// } -// ) -// .collect(Collectors.toList()); -// } + private List convertReviewers(Long id, List jsonReviewers) { + return jsonReviewers.stream() + .map( + jsonReviewer -> { + final Reviewer reviewer = new Reviewer(); + reviewer.setPullRequestId(id); + reviewer.setUser(jsonReviewer.getUser().getName()); + reviewer.setStatus(convertStatusReviewer(jsonReviewer.getStatus())); + return reviewer; + } + ) + .collect(Collectors.toList()); + } + + public static ReviewerStatus convertStatusReviewer(UserPullRequestStatus status) { + switch (status) { + case APPROVED: + return ReviewerStatus.APPROVED; + case NEEDS_WORK: + return ReviewerStatus.UNAPPROVED; + case UNAPPROVED: + return ReviewerStatus.NEEDS_WORK; + } + return null; + } diff --git a/src/main/java/com/tsc/bitbucketbot/service/impl/PullRequestsServiceImpl.java b/src/main/java/com/tsc/bitbucketbot/service/impl/PullRequestsServiceImpl.java index e3e37a3..dfd9b1c 100644 --- a/src/main/java/com/tsc/bitbucketbot/service/impl/PullRequestsServiceImpl.java +++ b/src/main/java/com/tsc/bitbucketbot/service/impl/PullRequestsServiceImpl.java @@ -33,25 +33,23 @@ public class PullRequestsServiceImpl implements PullRequestsService { } @Override - public Set existsAllById(@NonNull Set pullRequestJsonId) { + public Set existsAllIdById(@NonNull Set pullRequestJsonId) { return pullRequestJsonId.stream().filter(pullRequestsRepository::existsById).collect(Collectors.toSet()); } @Override - public List addAll(Set pullRequests) { + public Set getAllById(@NonNull Set pullRequestJsonId) { + return pullRequestsRepository.findAllByIdIn(pullRequestJsonId); + } + + @Override + public List addAll(@NonNull Set pullRequests) { return pullRequestsRepository.saveAll(pullRequests); } @Override - @Transactional - public Optional addReviewer(@NonNull Long pullRequestId, @NonNull List reviewers) { - final Optional optPullRequest = pullRequestsRepository.findById(pullRequestId); - if (optPullRequest.isPresent()) { - final PullRequest pullRequest = optPullRequest.get(); - pullRequest.setReviewers(reviewers); - return Optional.of(pullRequestsRepository.save(pullRequest)); - } - return Optional.empty(); + public List updateAll(@NonNull List pullRequests) { + return pullRequestsRepository.saveAll(pullRequests); } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 1310325..bee6a93 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -7,7 +7,7 @@ spring: liquibase: change-log: classpath:liquibase/change-log.xml jpa: - show-sql: false + show-sql: true hibernate: ddl-auto: none database-platform: org.hibernate.dialect.PostgreSQLDialect @@ -17,15 +17,13 @@ spring: lob: non_contextual_creation: true bitbucketbot: - panel: - password: mnbyNie832r telegram: bot-username: bitbucket_sadtech_bot bot-token: 1096235968:AAHvIy_mlZJXiNc9aDQWtCuiksz9YGknoXE admin-chatid: 3000811 proxy-config: - host: 54.39.16.26 - port: 62509 + host: 167.172.171.134 + port: 1080 type: SOCKS5 bitbucket: token: Nzg5NjUyNDQwMzk2OlA+6naQz02+GxOG0Q9li/jnsn7E