Управление уведомлениями

This commit is contained in:
upagge 2020-09-20 22:18:45 +03:00
parent 3f4a310ae5
commit 0892d5786f
No known key found for this signature in database
GPG Key ID: 15CD012E46F6BA34
40 changed files with 622 additions and 397 deletions

View File

@ -5,5 +5,6 @@
<include file="liquibase/v.2.0.0/2020-09-06-create-table.xml"/>
<include file="liquibase/v.2.0.0/2020-09-15-fix-task-comments.xml"/>
<include file="liquibase/v.2.0.0/2020-09-20-setting-notify.xml"/>
</databaseChangeLog>

View File

@ -0,0 +1,18 @@
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="2020-09-20-create-table-setting-notify" author="upagge">
<createTable tableName="setting_notify">
<column name="login" type="varchar(64)">
<constraints primaryKey="true" nullable="false" deleteCascade="true" references="person(login)"
foreignKeyName="setting_notify_login_person_login"/>
</column>
<column name="start_receiving" type="datetime">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>

View File

@ -18,7 +18,7 @@
</appender>
<root level="info">
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@ -0,0 +1,39 @@
package org.sadtech.bot.vcs.core.domain.entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDateTime;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
@Getter
@Setter
@Entity
@Table(name = "setting_notify")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class NotifySetting {
/**
* Логин пользователя, которому принадлежат настройки
*/
@Id
@Column(name = "login")
@EqualsAndHashCode.Include
private String login;
/**
* Дата, после которой пользователю будут поступать уведомления.
*/
@Column(name = "start_receiving")
private LocalDateTime startReceiving;
}

View File

@ -1,59 +1,39 @@
package org.sadtech.bot.vcs.core.utils;
package org.sadtech.bot.vcs.core.domain.notify;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.utils.MessageUtils;
import org.sadtech.bot.vcs.core.utils.Smile;
import org.sadtech.bot.vcs.core.utils.UpdateDataComparator;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Set;
/**
* Генерирует сообщения для отправки.
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge [07.02.2020]
* @author upagge 20.09.2020
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Message {
@Getter
public class GoodMorningNotify extends Notify {
private static final UpdateDataComparator COMPARATOR = new UpdateDataComparator();
private static final Integer PR_COUNT = 4;
private static final String DONATION_LINK = "https://www.tinkoff.ru/sl/1T9s4esiMf";
@NonNull
public static String goodMorningStatistic(List<PullRequest> pullRequestsReviews, List<PullRequest> pullRequestsNeedWork) {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
.append("Самые старые:").append(Smile.BR);
List<PullRequest> oldPr = pullRequestsReviews.stream()
.sorted(COMPARATOR)
.limit(PR_COUNT)
.collect(Collectors.toList());
oldPr.forEach(pullRequest -> message.append(topPr(pullRequest)));
} else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);
}
if (!pullRequestsNeedWork.isEmpty()) {
message.append(Smile.BR).append(Smile.DANGEROUS).append("Требуется доработать ").append(pullRequestsNeedWork.size()).append(" ПР:").append(Smile.BR);
message.append(needWorkPr(pullRequestsNeedWork)).append(Smile.BR);
}
if (dayX()) {
message.append(Smile.BR).append(Smile.FUN).append(" Кстати, поздравляю, сегодня день З").append(Smile.BR)
.append(Smile.DANGEROUS).append("Хостинг оплачен до 5 октября! Прошу неравнодушных ").append(link("задонатить", DONATION_LINK))
.append(Smile.BR);
}
message
.append(Smile.BR).append("Удачного дня ").append(Smile.FLOWER).append(Smile.TWO_BR);
return message.toString();
}
private final List<PullRequest> pullRequestsReviews;
private final List<PullRequest> pullRequestsNeedWork;
@NonNull
public static String goodWeekEnd() {
return "Ну вот и все! Веселых выходных " + Smile.MIG + Smile.BR +
"До понедельника" + Smile.BUY + Smile.TWO_BR;
@Builder
protected GoodMorningNotify(
Set<String> logins,
List<PullRequest> pullRequestsReviews,
List<PullRequest> pullRequestsNeedWork
) {
super(logins);
this.pullRequestsReviews = pullRequestsReviews;
this.pullRequestsNeedWork = pullRequestsNeedWork;
}
private static String needWorkPr(@NonNull List<PullRequest> pullRequestsNeedWork) {
@ -66,20 +46,28 @@ public final class Message {
return message.toString();
}
private static String topPr(PullRequest pullRequest) {
return Smile.statusPr(pullRequest.getUpdateDate()) + " " +
link(pullRequest.getTitle(), pullRequest.getUrl()) +
Smile.BR;
}
private static boolean dayX() {
int dayOfMonth = LocalDate.now().getDayOfMonth();
return dayOfMonth == 20 || dayOfMonth == 5;
}
@NonNull
private static String link(String name, String url) {
return "[" + name + "](" + url + ")";
}
@Override
public String generateMessage() {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
.append("Самые старые:").append(Smile.BR)
.append(MessageUtils.pullRequestForReview(pullRequestsReviews));
} else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);
}
if (!pullRequestsNeedWork.isEmpty()) {
message.append(Smile.BR).append(Smile.DANGEROUS).append("Требуется доработать ").append(pullRequestsNeedWork.size()).append(" ПР:").append(Smile.BR);
message.append(needWorkPr(pullRequestsNeedWork)).append(Smile.BR);
}
message
.append(Smile.BR).append("Удачного дня ").append(Smile.FLOWER).append(Smile.TWO_BR);
return message.toString();
}
}

View File

@ -1,27 +1,18 @@
package org.sadtech.bot.vcs.core.domain.notify;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.Set;
@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Setter
public abstract class Notify {
protected final NotifyType type;
protected final LocalDateTime localDateTime = LocalDateTime.now();
protected final Set<Long> telegramIds;
protected Set<String> logins;
@Setter
@EqualsAndHashCode.Include
protected Long id;
protected Notify(NotifyType type, Set<Long> telegramIds) {
this.type = type;
this.telegramIds = telegramIds;
protected Notify(Set<String> logins) {
this.logins = logins;
}
public abstract String generateMessage();

View File

@ -1,17 +0,0 @@
package org.sadtech.bot.vcs.core.domain.notify;
public enum NotifyType {
STATUS_PR,
UPDATE_PR,
REVIEWERS,
NEW_PR,
CONFLICT_PR,
NEW_COMMENT,
NEW_ANSWERS_COMMENT,
NEW_TASK,
DELETED_TASK,
RESOLVED_TASK,
OPEN_TASK;
}

View File

@ -0,0 +1,28 @@
package org.sadtech.bot.vcs.core.domain.notify;
import lombok.Builder;
import lombok.Getter;
import java.util.Set;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
@Getter
public class SimpleTextNotify extends Notify {
private final String message;
@Builder
private SimpleTextNotify(Set<String> logins, String message) {
super(logins);
this.message = message;
}
@Override
public String generateMessage() {
return message;
}
}

View File

@ -5,7 +5,6 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.Answer;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -23,12 +22,12 @@ public class AnswerCommentNotify extends Notify {
@Builder
protected AnswerCommentNotify(
Set<Long> telegramIds,
Set<String> logins,
String youMessage,
String url,
List<Answer> answers
) {
super(NotifyType.NEW_ANSWERS_COMMENT, telegramIds);
super(logins);
this.youMessage = youMessage;
this.url = url;
this.answers = answers;
@ -46,4 +45,5 @@ public class AnswerCommentNotify extends Notify {
Smile.BELL, url, Smile.HR, youMessage.substring(0, Math.min(youMessage.length(), 180)), Smile.HR, answerText
);
}
}

View File

@ -4,7 +4,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -20,12 +19,12 @@ public class CommentNotify extends Notify {
@Builder
private CommentNotify(
Set<Long> telegramIds,
Set<String> logins,
String url,
String authorName,
String message
) {
super(NotifyType.NEW_COMMENT, telegramIds);
super(logins);
this.authorName = authorName;
this.message = message;
this.url = url;
@ -39,6 +38,7 @@ public class CommentNotify extends Notify {
Smile.BELL, url, Smile.HR, authorName, message.replaceAll("@[\\w]+", "")
);
}
}

View File

@ -2,7 +2,6 @@ package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -13,11 +12,11 @@ public class ConflictPrNotify extends PrNotify {
@Builder
private ConflictPrNotify(
Set<Long> telegramIds,
Set<String> logins,
String name,
String url
) {
super(NotifyType.CONFLICT_PR, telegramIds, name, url);
super(logins, name, url);
}
@Override
@ -29,4 +28,5 @@ public class ConflictPrNotify extends PrNotify {
Smile.DANGEROUS, Smile.HR, title, url
);
}
}

View File

@ -3,7 +3,6 @@ package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -18,12 +17,12 @@ public class NewPrNotify extends PrNotify {
@Builder
private NewPrNotify(
Set<Long> telegramIds,
Set<String> logins,
String title,
String url,
String description,
String author) {
super(NotifyType.NEW_PR, telegramIds, title, url);
super(logins, title, url);
this.description = description;
this.author = author;
}
@ -39,4 +38,5 @@ public class NewPrNotify extends PrNotify {
Smile.AUTHOR, author
);
}
}

View File

@ -3,7 +3,6 @@ package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import java.util.Set;
@ -14,8 +13,8 @@ public abstract class PrNotify extends Notify {
protected final String title;
protected final String url;
protected PrNotify(NotifyType type, Set<Long> telegramIds, String title, String url) {
super(type, telegramIds);
protected PrNotify(Set<String> logins, String title, String url) {
super(logins);
this.title = title;
this.url = url;
}

View File

@ -3,7 +3,6 @@ package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.domain.util.ReviewerChange;
import org.sadtech.bot.vcs.core.utils.Smile;
@ -24,11 +23,11 @@ public class ReviewersPrNotify extends PrNotify {
@Builder
private ReviewersPrNotify(
Set<Long> telegramIds,
Set<String> logins,
String title,
String url,
List<ReviewerChange> reviewerChanges) {
super(NotifyType.REVIEWERS, telegramIds, title, url);
super(logins, title, url);
this.reviewerChanges = reviewerChanges;
}
@ -68,4 +67,5 @@ public class ReviewersPrNotify extends PrNotify {
"[" + title + "](" + url + ")" + Smile.HR +
createMessage;
}
}

View File

@ -4,7 +4,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.PullRequestStatus;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -19,12 +18,12 @@ public class StatusPrNotify extends PrNotify {
@Builder
private StatusPrNotify(
Set<Long> telegramIds,
Set<String> logins,
String name,
String url,
PullRequestStatus oldStatus,
PullRequestStatus newStatus) {
super(NotifyType.STATUS_PR, telegramIds, name, url);
super(logins, name, url);
this.oldStatus = oldStatus;
this.newStatus = newStatus;
}

View File

@ -3,7 +3,6 @@ package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -17,10 +16,10 @@ public class UpdatePrNotify extends PrNotify {
@Builder
private UpdatePrNotify(
Set<Long> telegramIds,
Set<String> logins,
String name,
String url, String author) {
super(NotifyType.UPDATE_PR, telegramIds, name, url);
super(logins, name, url);
this.author = author;
}

View File

@ -1,7 +1,6 @@
package org.sadtech.bot.vcs.core.domain.notify.task;
import lombok.Builder;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -16,12 +15,12 @@ public class TaskCloseNotify extends TaskNotify {
@Builder
protected TaskCloseNotify(
Set<Long> telegramIds,
Set<String> logins,
String authorName,
String url,
String messageTask
) {
super(NotifyType.RESOLVED_TASK, telegramIds, authorName, url, messageTask);
super(logins, authorName, url, messageTask);
}
@Override

View File

@ -2,7 +2,6 @@ package org.sadtech.bot.vcs.core.domain.notify.task;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
@ -18,12 +17,12 @@ public class TaskNewNotify extends TaskNotify {
@Builder
protected TaskNewNotify(
Set<Long> telegramIds,
Set<String> logins,
String authorName,
String url,
String messageTask
) {
super(NotifyType.NEW_TASK, telegramIds, authorName, url, messageTask);
super(logins, authorName, url, messageTask);
}
@Override

View File

@ -3,7 +3,6 @@ package org.sadtech.bot.vcs.core.domain.notify.task;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.domain.notify.NotifyType;
import java.util.Set;
@ -16,13 +15,12 @@ public abstract class TaskNotify extends Notify {
protected final String messageTask;
protected TaskNotify(
NotifyType type,
Set<Long> telegramIds,
Set<String> logins,
String authorName,
String url,
String messageTask
) {
super(type, telegramIds);
super(logins);
this.authorName = authorName;
this.url = url;
this.messageTask = messageTask;

View File

@ -1,16 +0,0 @@
package org.sadtech.bot.vcs.core.repository;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import java.util.List;
public interface NotifyRepository {
<T extends Notify> T add(@NonNull T notify);
List<Notify> getAll();
void deleteAll(@NonNull List<Notify> notifies);
}

View File

@ -0,0 +1,20 @@
package org.sadtech.bot.vcs.core.repository;
import lombok.NonNull;
import org.sadtech.basic.context.repository.SimpleManagerRepository;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import java.util.Set;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
public interface NotifySettingRepository extends SimpleManagerRepository<NotifySetting, String> {
boolean isNotification(@NonNull String login);
Set<String> isNotification(@NonNull Set<String> logins);
}

View File

@ -1,35 +0,0 @@
package org.sadtech.bot.vcs.core.repository.impl;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.repository.NotifyRepository;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
public class NotifyRepositoryImpl implements NotifyRepository {
private final List<Notify> list = new ArrayList<>();
private long count = 0;
@Override
public <T extends Notify> T add(@NonNull T notify) {
notify.setId(count++);
list.add(notify);
return notify;
}
@Override
public List<Notify> getAll() {
return new ArrayList<>(list);
}
@Override
public void deleteAll(@NonNull List<Notify> notifies) {
list.removeAll(notifies);
}
}

View File

@ -0,0 +1,38 @@
package org.sadtech.bot.vcs.core.repository.impl;
import lombok.NonNull;
import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.sadtech.bot.vcs.core.repository.NotifySettingRepository;
import org.sadtech.bot.vcs.core.repository.jpa.NotifySettingJpaRepository;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.Set;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
@Repository
public class NotifySettingRepositoryImpl extends AbstractSimpleManagerRepository<NotifySetting, String> implements NotifySettingRepository {
private final NotifySettingJpaRepository jpaRepository;
public NotifySettingRepositoryImpl(NotifySettingJpaRepository jpaRepository) {
super(jpaRepository);
this.jpaRepository = jpaRepository;
}
@Override
public boolean isNotification(@NonNull String login) {
return jpaRepository.findByLoginAndStartReceivingAfter(login, LocalDateTime.now());
}
@Override
public Set<String> isNotification(@NonNull Set<String> logins) {
return jpaRepository.findAllByLoginInAndStartReceivingAfter(logins, LocalDateTime.now());
}
}

View File

@ -0,0 +1,23 @@
package org.sadtech.bot.vcs.core.repository.jpa;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.time.LocalDateTime;
import java.util.Set;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
public interface NotifySettingJpaRepository extends JpaRepository<NotifySetting, String> {
boolean findByLoginAndStartReceivingAfter(String login, LocalDateTime date);
@Query("SELECT n.login FROM NotifySetting n WHERE n.login IN :logins AND n.startReceiving < :date")
Set<String> findAllByLoginInAndStartReceivingAfter(@Param("logins") Set<String> logins, @Param("date") LocalDateTime date);
}

View File

@ -1,15 +1,15 @@
package org.sadtech.bot.vcs.core.scheduler;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.MessageSend;
import org.sadtech.bot.vcs.core.domain.PullRequestStatus;
import org.sadtech.bot.vcs.core.domain.ReviewerStatus;
import org.sadtech.bot.vcs.core.domain.entity.Person;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.sadtech.bot.vcs.core.domain.notify.GoodMorningNotify;
import org.sadtech.bot.vcs.core.domain.notify.SimpleTextNotify;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.PullRequestsService;
import org.sadtech.bot.vcs.core.utils.Message;
import org.sadtech.bot.vcs.core.utils.Smile;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@ -26,13 +26,13 @@ import java.util.stream.Collectors;
public class NotificationScheduler {
private static final Set<String> tksLoginNotify = new HashSet<>(Arrays.asList(
"mstruchkov", "dganin", "emukhin", "ktorgaeva", "imescheryakov", "kkeglev"
"mstruchkov", "emukhin", "ktorgaeva", "imescheryakov", "kkeglev"
));
private static final Set<PullRequestStatus> statuses = Collections.singleton(PullRequestStatus.OPEN);
private final PersonService personService;
private final PullRequestsService pullRequestsService;
private final MessageSendService messageSendService;
private final NotifyService notifyService;
// Утреннее сообщение
@Scheduled(cron = "0 15 8 * * MON-FRI")
@ -42,44 +42,53 @@ public class NotificationScheduler {
List<PullRequest> pullRequestsReviews = pullRequestsService.getAllByReviewerAndStatuses(
user.getLogin(),
ReviewerStatus.NEEDS_WORK,
statuses
Collections.singleton(PullRequestStatus.OPEN)
);
List<PullRequest> pullRequestsNeedWork = pullRequestsService.getAllByAuthorAndReviewerStatus(user.getLogin(), ReviewerStatus.UNAPPROVED);
messageSendService.add(
MessageSend.builder()
.telegramId(user.getTelegramId())
.message(Message.goodMorningStatistic(pullRequestsReviews, pullRequestsNeedWork))
notifyService.send(
GoodMorningNotify.builder()
.pullRequestsNeedWork(pullRequestsNeedWork)
.pullRequestsReviews(pullRequestsReviews)
.logins(Collections.singleton(user.getLogin()))
.build()
);
}
}
@Scheduled(cron = "0 25 10 * * MON-FRI")
@Scheduled(cron = "0 29 10 * * MON-FRI")
public void tks() {
List<Person> usersTks = personService.getAllRegister().stream()
.filter(user -> tksLoginNotify.contains(user.getLogin()))
.collect(Collectors.toList());
for (Person person : usersTks) {
messageSendService.add(
MessageSend.builder()
.telegramId(person.getTelegramId())
.message("☎️ Скоро созвон" + Smile.HR + "https://meet.google.com/czs-vigu-mte")
.build()
);
}
notifyService.send(
SimpleTextNotify
.builder()
.logins(
usersTks.stream()
.map(Person::getLogin)
.collect(Collectors.toSet())
)
.message("☎️ Внимание созвон" + Smile.HR + "https://meet.google.com/czs-vigu-mte")
.build()
);
}
@Scheduled(cron = "0 0 18 * * FRI")
public void goodWeekEnd() {
List<Person> allRegister = personService.getAllRegister();
for (Person user : allRegister) {
messageSendService.add(
MessageSend.builder()
.telegramId(user.getTelegramId())
.message(Message.goodWeekEnd())
.build()
);
}
notifyService.send(
SimpleTextNotify.builder()
.message("Ну вот и все! Веселых выходных " + Smile.MIG + Smile.BR +
"До понедельника" + Smile.BUY + Smile.TWO_BR)
.logins(
allRegister.stream()
.map(Person::getLogin)
.collect(Collectors.toSet())
)
.build()
);
}
}

View File

@ -1,49 +0,0 @@
package org.sadtech.bot.vcs.core.scheduler;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.MessageSend;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* Парсер изменений. Отслеживает изменения, которые были добавлены и добавляет событие на отправку уведомления
* пользователю.
*
* @author upagge
*/
@Service
@RequiredArgsConstructor
public class NotifyParsingScheduler {
private final MessageSendService messageSendService;
private final NotifyService notifyService;
/**
* Проверяет наличие новых изменений. Если изменения найдены, то создает новое сообщение и отправляет
* его в сервис отправки сообщений {@link MessageSendService}
*/
@Scheduled(cron = "*/15 * * * * *")
public void parsing() {
final List<Notify> newNotify = notifyService.getNew().stream()
.filter(notify -> notify.getTelegramIds() != null && !notify.getTelegramIds().isEmpty())
.collect(Collectors.toList());
for (Notify notify : newNotify) {
final String message = notify.generateMessage();
notify.getTelegramIds().forEach(
telegramId -> messageSendService.add(
MessageSend.builder()
.telegramId(telegramId)
.message(message)
.build()
)
);
}
}
}

View File

@ -1,10 +1,11 @@
package org.sadtech.bot.vcs.core.service;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.MessageSend;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
@FunctionalInterface
public interface MessageSendService {
void add(@NonNull MessageSend messageSend);
void send(@NonNull Notify notify);
}

View File

@ -1,8 +1,10 @@
package org.sadtech.bot.vcs.core.service;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import java.util.List;
import java.util.Optional;
/**
* Сервис по работе с изменениями в битбакете.
@ -12,11 +14,18 @@ import java.util.List;
*/
public interface NotifyService {
<T extends Notify> void save(T notify);
<T extends Notify> void send(T notify);
/**
* Позволяет получить новые изменения.
* Сохранить настройки уведомлений
*/
List<Notify> getNew();
void saveSettings(@NonNull NotifySetting setting);
/**
* Получить настройки уведомлений по логину.
*
* @param login Логин пользователя
*/
Optional<NotifySetting> getSetting(@NonNull String login);
}

View File

@ -3,15 +3,14 @@ package org.sadtech.bot.vcs.core.service.impl;
import lombok.NonNull;
import org.sadtech.basic.core.service.AbstractSimpleManagerService;
import org.sadtech.bot.vcs.core.domain.Answer;
import org.sadtech.bot.vcs.core.domain.notify.comment.AnswerCommentNotify;
import org.sadtech.bot.vcs.core.domain.notify.comment.CommentNotify;
import org.sadtech.bot.vcs.core.domain.entity.Comment;
import org.sadtech.bot.vcs.core.domain.entity.Task;
import org.sadtech.bot.vcs.core.domain.notify.comment.AnswerCommentNotify;
import org.sadtech.bot.vcs.core.domain.notify.comment.CommentNotify;
import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.repository.CommentRepository;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.CommentService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.TaskService;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.convert.ConversionService;
@ -32,7 +31,6 @@ public class CommentServiceImpl extends AbstractSimpleManagerService<Comment, Lo
private static final Pattern PATTERN = Pattern.compile("@[\\w]+");
private final CommentRepository commentRepository;
private final PersonService personService;
private final NotifyService notifyService;
private final TaskService taskService;
@ -40,13 +38,11 @@ public class CommentServiceImpl extends AbstractSimpleManagerService<Comment, Lo
public CommentServiceImpl(
CommentRepository commentRepository,
PersonService personService,
NotifyService notifyService,
@Lazy TaskService taskService,
ConversionService conversionService
) {
super(commentRepository);
this.personService = personService;
this.commentRepository = commentRepository;
this.notifyService = notifyService;
this.taskService = taskService;
@ -78,12 +74,11 @@ public class CommentServiceImpl extends AbstractSimpleManagerService<Comment, Lo
final String login = matcher.group(0).replace("@", "");
recipientsLogins.add(login);
}
final Set<Long> recipientsIds = personService.getAllTelegramIdByLogin(recipientsLogins);
notifyService.save(
notifyService.send(
CommentNotify.builder()
.authorName(comment.getAuthor())
.url(comment.getUrl())
.telegramIds(recipientsIds)
.logins(recipientsLogins)
.message(comment.getMessage())
.build()
);
@ -132,11 +127,9 @@ public class CommentServiceImpl extends AbstractSimpleManagerService<Comment, Lo
.collect(Collectors.toList());
oldComment.getAnswers().clear();
oldComment.setAnswers(existsNewAnswersIds);
notifyService.save(
notifyService.send(
AnswerCommentNotify.builder()
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(newComment.getAuthor()))
)
.logins(Collections.singleton(newComment.getAuthor()))
.url(oldComment.getUrl())
.youMessage(newComment.getMessage())
.answers(

View File

@ -1,29 +1,40 @@
package org.sadtech.bot.vcs.core.service.impl;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.repository.NotifyRepository;
import org.sadtech.bot.vcs.core.repository.NotifySettingRepository;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Service
@RequiredArgsConstructor
public class NotifyServiceImpl implements NotifyService {
private final NotifyRepository notifyRepository;
private final NotifySettingRepository settingRepository;
private final MessageSendService messageSendService;
@Override
public <T extends Notify> void save(T notify) {
notifyRepository.add(notify);
public <T extends Notify> void send(T notify) {
final Set<String> recipientLogins = settingRepository.isNotification(notify.getLogins());
notify.setLogins(recipientLogins);
messageSendService.send(notify);
}
@Override
public List<Notify> getNew() {
final List<Notify> notifies = notifyRepository.getAll();
notifyRepository.deleteAll(notifies);
return notifies;
public void saveSettings(@NonNull NotifySetting setting) {
settingRepository.save(setting);
}
@Override
public Optional<NotifySetting> getSetting(@NonNull String login) {
return settingRepository.findById(login);
}
}

View File

@ -1,17 +1,20 @@
package org.sadtech.bot.vcs.core.service.impl;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.sadtech.basic.core.util.Assert;
import org.sadtech.bot.vcs.core.config.properties.BitbucketProperty;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.sadtech.bot.vcs.core.domain.entity.Person;
import org.sadtech.bot.vcs.core.exception.RegException;
import org.sadtech.bot.vcs.core.repository.PersonRepository;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.Utils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@ -20,12 +23,23 @@ import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class PersonServiceImpl implements PersonService {
private final PersonRepository personRepository;
private final BitbucketProperty bitbucketProperty;
private final NotifyService notifyService;
public PersonServiceImpl(
PersonRepository personRepository,
BitbucketProperty bitbucketProperty,
@Lazy NotifyService notifyService
) {
this.personRepository = personRepository;
this.bitbucketProperty = bitbucketProperty;
this.notifyService = notifyService;
}
@Override
public Optional<Person> getByLogin(String login) {
return personRepository.findByLogin(login);
@ -52,6 +66,9 @@ public class PersonServiceImpl implements PersonService {
Optional<Object> sheetJson = Utils.urlToJson(bitbucketProperty.getUrlPullRequestClose(), user.getToken(), Object.class);
if (sheetJson.isPresent()) {
oldUser.setTelegramId(user.getTelegramId());
defaultSettings(oldUser);
return personRepository.save(oldUser);
} else {
throw new RegException("Ваш токен не валиден");
@ -63,6 +80,13 @@ public class PersonServiceImpl implements PersonService {
throw new RegException("Пользователь не найден, подождите обновление базы пользователей!");
}
private void defaultSettings(Person person) {
final NotifySetting notifySetting = new NotifySetting();
notifySetting.setLogin(person.getLogin());
notifySetting.setStartReceiving(LocalDateTime.now());
notifyService.saveSettings(notifySetting);
}
@Override
public List<Person> getAllRegister() {
return personRepository.findAllByTelegramIdNotNullAndTokenNotNull();

View File

@ -11,21 +11,20 @@ import org.sadtech.basic.filter.criteria.CriteriaQuery;
import org.sadtech.bot.vcs.core.domain.IdAndStatusPr;
import org.sadtech.bot.vcs.core.domain.PullRequestStatus;
import org.sadtech.bot.vcs.core.domain.ReviewerStatus;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ConflictPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.NewPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ReviewersPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.StatusPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.UpdatePrNotify;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.domain.entity.PullRequestMini;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest_;
import org.sadtech.bot.vcs.core.domain.entity.Reviewer;
import org.sadtech.bot.vcs.core.domain.filter.PullRequestFilter;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ConflictPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.NewPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ReviewersPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.StatusPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.UpdatePrNotify;
import org.sadtech.bot.vcs.core.domain.util.ReviewerChange;
import org.sadtech.bot.vcs.core.exception.UpdateException;
import org.sadtech.bot.vcs.core.repository.PullRequestsRepository;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.PullRequestsService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@ -43,18 +42,16 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
private final NotifyService notifyService;
private final PullRequestsRepository pullRequestsRepository;
private final PersonService personService;
private final FilterService<PullRequest, PullRequestFilter> filterService;
protected PullRequestsServiceImpl(
PullRequestsRepository pullRequestsRepository,
NotifyService notifyService,
PersonService personService, @Qualifier("pullRequestFilterService") FilterService<PullRequest, PullRequestFilter> pullRequestsFilterService
@Qualifier("pullRequestFilterService") FilterService<PullRequest, PullRequestFilter> pullRequestsFilterService
) {
super(pullRequestsRepository);
this.notifyService = notifyService;
this.pullRequestsRepository = pullRequestsRepository;
this.personService = personService;
this.filterService = pullRequestsFilterService;
}
@ -64,26 +61,30 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
final PullRequest newPullRequest = pullRequestsRepository.save(pullRequest);
notifyService.save(
notifyService.send(
NewPrNotify.builder()
.author(newPullRequest.getAuthorLogin())
.description(newPullRequest.getDescription())
.title(newPullRequest.getTitle())
.url(newPullRequest.getUrl())
.telegramIds(getReviewerTelegrams(newPullRequest.getReviewers()))
.logins(
newPullRequest.getReviewers().stream()
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet())
)
.build()
);
return newPullRequest;
}
private Set<Long> getReviewerTelegrams(@NonNull List<Reviewer> reviewers) {
return personService.getAllTelegramIdByLogin(
reviewers.stream()
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet())
);
}
//
// private Set<Long> getReviewerTelegrams(@NonNull List<Reviewer> reviewers) {
// return personService.getAllTelegramIdByLogin(
// reviewers.stream()
// .map(Reviewer::getPersonLogin)
// .collect(Collectors.toSet())
// );
// }
@Override
public PullRequest update(@NonNull PullRequest pullRequest) {
@ -98,11 +99,15 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
final PullRequest newPullRequest = pullRequestsRepository.save(oldPullRequest);
if (!pullRequest.getBitbucketVersion().equals(newPullRequest.getBitbucketVersion())) {
notifyService.save(
notifyService.send(
UpdatePrNotify.builder()
.author(oldPullRequest.getAuthorLogin())
.name(newPullRequest.getTitle())
.telegramIds(getReviewerTelegrams(newPullRequest.getReviewers()))
.logins(
newPullRequest.getReviewers().stream()
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet())
)
.url(newPullRequest.getUrl())
.build()
);
@ -113,13 +118,11 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
private void updateConflict(PullRequest oldPullRequest, PullRequest pullRequest) {
if (!oldPullRequest.isConflict() && pullRequest.isConflict()) {
notifyService.save(
notifyService.send(
ConflictPrNotify.builder()
.name(pullRequest.getTitle())
.url(pullRequest.getUrl())
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(pullRequest.getAuthorLogin()))
)
.logins(Collections.singleton(pullRequest.getAuthorLogin()))
.build()
);
}
@ -130,17 +133,13 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
final PullRequestStatus oldStatus = oldPullRequest.getStatus();
final PullRequestStatus newStatus = newPullRequest.getStatus();
if (!oldStatus.equals(newStatus)) {
notifyService.save(
notifyService.send(
StatusPrNotify.builder()
.name(newPullRequest.getTitle())
.url(oldPullRequest.getUrl())
.newStatus(newStatus)
.oldStatus(oldStatus)
.telegramIds(
personService.getAllTelegramIdByLogin(
Collections.singleton(oldPullRequest.getAuthorLogin())
)
)
.logins(Collections.singleton(oldPullRequest.getAuthorLogin()))
.build()
);
oldPullRequest.setStatus(newStatus);
@ -179,13 +178,11 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
oldPullRequest.getReviewers()
.removeIf(reviewer -> oldIds.contains(reviewer.getPersonLogin()));
if (!reviewerChanges.isEmpty()) {
notifyService.save(
notifyService.send(
ReviewersPrNotify.builder()
.title(newPullRequest.getTitle())
.url(newPullRequest.getUrl())
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(newPullRequest.getAuthorLogin()))
)
.logins(Collections.singleton(newPullRequest.getAuthorLogin()))
.reviewerChanges(reviewerChanges)
.build()
);

View File

@ -5,18 +5,17 @@ import org.sadtech.basic.core.service.AbstractSimpleManagerService;
import org.sadtech.basic.core.util.Assert;
import org.sadtech.bot.vcs.core.domain.Answer;
import org.sadtech.bot.vcs.core.domain.TaskStatus;
import org.sadtech.bot.vcs.core.domain.entity.Comment;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.domain.entity.Task;
import org.sadtech.bot.vcs.core.domain.notify.comment.AnswerCommentNotify;
import org.sadtech.bot.vcs.core.domain.notify.comment.CommentNotify;
import org.sadtech.bot.vcs.core.domain.notify.task.TaskCloseNotify;
import org.sadtech.bot.vcs.core.domain.notify.task.TaskNewNotify;
import org.sadtech.bot.vcs.core.domain.entity.Comment;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.domain.entity.Task;
import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.repository.TaskRepository;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.CommentService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.PullRequestsService;
import org.sadtech.bot.vcs.core.service.TaskService;
import org.springframework.core.convert.ConversionService;
@ -40,7 +39,6 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
private final PullRequestsService pullRequestsService;
private final NotifyService notifyService;
private final PersonService personService;
private final CommentService commentService;
private final ConversionService conversionService;
@ -49,7 +47,6 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
TaskRepository taskRepository,
PullRequestsService pullRequestsService,
NotifyService notifyService,
PersonService personService,
CommentService commentService,
ConversionService conversionService
) {
@ -57,7 +54,6 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
this.taskRepository = taskRepository;
this.pullRequestsService = pullRequestsService;
this.notifyService = notifyService;
this.personService = personService;
this.commentService = commentService;
this.conversionService = conversionService;
}
@ -93,26 +89,22 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
if (!oldStatus.equals(newStatus)) {
switch (newStatus) {
case OPEN:
notifyService.save(
notifyService.send(
TaskNewNotify.builder()
.messageTask(task.getDescription())
.authorName(oldTask.getAuthor())
.url(oldTask.getUrl())
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(oldTask.getResponsible()))
)
.logins(Collections.singleton(oldTask.getResponsible()))
.build()
);
break;
case RESOLVED:
notifyService.save(
notifyService.send(
TaskCloseNotify.builder()
.messageTask(oldTask.getDescription())
.authorName(oldTask.getAuthor())
.url(oldTask.getUrl())
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(oldTask.getAuthor()))
)
.logins(Collections.singleton(oldTask.getAuthor()))
.build()
);
break;
@ -133,11 +125,9 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
.collect(Collectors.toList());
oldTask.getAnswers().clear();
oldTask.setAnswers(existsNewAnswersIds);
notifyService.save(
notifyService.send(
AnswerCommentNotify.builder()
.telegramIds(
personService.getAllTelegramIdByLogin(Collections.singleton(oldTask.getAuthor()))
)
.logins(Collections.singleton(oldTask.getAuthor()))
.url(task.getUrl())
.youMessage(oldTask.getDescription())
.answers(
@ -178,16 +168,12 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
final PullRequest pullRequest = pullRequestsService.getById(task.getPullRequestId())
.orElseThrow(() -> new NotFoundException("ПР не найден"));
notifyService.save(
notifyService.send(
TaskNewNotify.builder()
.authorName(task.getAuthor())
.messageTask(task.getDescription())
.url(task.getUrl())
.telegramIds(
personService.getAllTelegramIdByLogin(
Collections.singleton(pullRequest.getAuthorLogin())
)
)
.logins(Collections.singleton(pullRequest.getAuthorLogin()))
.build()
);
}
@ -199,12 +185,11 @@ public class TaskServiceImpl extends AbstractSimpleManagerService<Task, Long> im
final String login = matcher.group(0).replace("@", "");
recipientsLogins.add(login);
}
final Set<Long> recipientsIds = personService.getAllTelegramIdByLogin(recipientsLogins);
notifyService.save(
notifyService.send(
CommentNotify.builder()
.authorName(task.getAuthor())
.url(task.getUrl())
.telegramIds(recipientsIds)
.logins(recipientsLogins)
.message(task.getDescription())
.build()
);

View File

@ -0,0 +1,47 @@
package org.sadtech.bot.vcs.core.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Генерирует сообщения для отправки.
*
* @author upagge [07.02.2020]
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MessageUtils {
private static final UpdateDataComparator COMPARATOR = new UpdateDataComparator();
private static final Integer PR_COUNT = 4;
public static Optional<String> pullRequestForReview(@NonNull List<PullRequest> pullRequestsReviews) {
if (!pullRequestsReviews.isEmpty()) {
return Optional.of(
pullRequestsReviews.stream()
.sorted(COMPARATOR)
.limit(PR_COUNT)
.map(MessageUtils::topPr)
.collect(Collectors.joining("\n"))
);
}
return Optional.empty();
}
private static String topPr(PullRequest pullRequest) {
return Smile.statusPr(pullRequest.getUpdateDate()) + " " +
link(pullRequest.getTitle(), pullRequest.getUrl()) +
Smile.BR;
}
@NonNull
private static String link(String name, String url) {
return "[" + name + "](" + url + ")";
}
}

View File

@ -2,27 +2,34 @@ package org.sadtech.bot.vcs.telegram.service;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.MessageSend;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.service.sender.Sending;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* // TODO: 17.09.2020 Добавить описание.
*
* @author upagge 17.09.2020
*/
//@Profile("prod")
@Service
@RequiredArgsConstructor
public class MessageSendTelegramService implements MessageSendService {
private final Sending sending;
private final PersonService personService;
@Override
public void add(@NonNull MessageSend messageSend) {
sending.send(messageSend.getTelegramId(), BoxAnswer.of(messageSend.getMessage()));
public void send(@NonNull Notify notify) {
final Set<Long> telegramIds = personService.getAllTelegramIdByLogin(notify.getLogins());
telegramIds.forEach(
telegramId -> sending.send(telegramId, BoxAnswer.of(notify.generateMessage()))
);
}
}

View File

@ -1,22 +0,0 @@
package org.sadtech.bot.vcs.telegram.service;
import lombok.NonNull;
import org.sadtech.bot.vcs.core.domain.MessageSend;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.springframework.context.annotation.Profile;
/**
* // TODO: 17.09.2020 Добавить описание.
*
* @author upagge 17.09.2020
*/
//@Service
@Profile("dev")
public class MessageSendTestService implements MessageSendService {
@Override
public void add(@NonNull MessageSend messageSend) {
System.out.println(messageSend);
}
}

View File

@ -8,16 +8,14 @@ import org.sadtech.bot.vcs.core.domain.entity.PullRequest;
import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.core.service.PullRequestsService;
import org.sadtech.bot.vcs.core.utils.Smile;
import org.sadtech.bot.vcs.core.utils.MessageUtils;
import org.sadtech.social.bot.service.usercode.ProcessingData;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.domain.content.Message;
import org.springframework.stereotype.Component;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* // TODO: 17.09.2020 Добавить описание.
@ -35,27 +33,14 @@ public class PullRequestProcessing implements ProcessingData<Message> {
public BoxAnswer processing(Message message) {
final Person person = personService.getByTelegramId(message.getPersonId())
.orElseThrow(() -> new NotFoundException("Пользователь не найден"));
final List<PullRequest> pullRequests = pullRequestsService.getAllByReviewerAndStatuses(person.getLogin(), ReviewerStatus.NEEDS_WORK, Collections.singleton(PullRequestStatus.OPEN));
String messageAnswer;
if (pullRequests.isEmpty()) {
messageAnswer = "Все ПР проверены :)";
} else {
final String prAnswer = pullRequests.stream()
.map(this::convert)
.collect(Collectors.joining("\n"));
messageAnswer = MessageFormat.format(
"Вам необходимо посмотреть следующие ПР:{0}{1}",
Smile.HR, prAnswer
);
}
return BoxAnswer.of(messageAnswer);
}
private String convert(PullRequest pullRequest) {
return MessageFormat.format(
"- [{0}]({1})",
pullRequest.getTitle(),
pullRequest.getUrl()
final List<PullRequest> pullRequests = pullRequestsService.getAllByReviewerAndStatuses(
person.getLogin(),
ReviewerStatus.NEEDS_WORK,
Collections.singleton(PullRequestStatus.OPEN)
);
return BoxAnswer.of(
MessageUtils.pullRequestForReview(pullRequests)
.orElse("Все ПР проверены :)")
);
}

View File

@ -0,0 +1,101 @@
package org.sadtech.bot.vcs.telegram.unit;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.entity.NotifySetting;
import org.sadtech.bot.vcs.core.domain.entity.Person;
import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.service.NotifyService;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.social.bot.domain.unit.AnswerProcessing;
import org.sadtech.social.bot.domain.unit.AnswerText;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.domain.content.Message;
import org.sadtech.social.core.utils.KeyBoards;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
@Configuration
@RequiredArgsConstructor
public class NotifySettingUnit {
private final PersonService personService;
private final NotifyService notifyService;
@Bean
public AnswerText notifySetting(
AnswerProcessing<Message> disableNotifications
) {
return AnswerText.builder()
.boxAnswer(
BoxAnswer.builder()
.message("Вы можете полностью остановить уведомления от бота")
.keyBoard(
KeyBoards.verticalDuoMenuString(
Arrays.stream(DisableMenu.values())
.map(DisableMenu::getName)
.collect(Collectors.toList())
)
)
.build()
)
.phrase("Уведомления")
.nextUnit(disableNotifications)
.build();
}
@Bean
public AnswerProcessing<Message> disableNotifications() {
return AnswerProcessing.builder()
.processingData(
message -> {
final Person person = personService.getByTelegramId(message.getPersonId())
.orElseThrow(() -> new NotFoundException("Не найдено"));
final NotifySetting notifySetting = notifyService.getSetting(person.getLogin())
.orElseThrow(() -> new NotFoundException("Не найдено"));
notifySetting.setStartReceiving(
LocalDateTime.now().plusMinutes(DisableMenu.from(message.getText()).getMinutes())
);
notifyService.saveSettings(notifySetting);
return BoxAnswer.of("Настройки сохранены");
}
)
.build();
}
@Getter
@RequiredArgsConstructor
private enum DisableMenu {
TURN_ON("Включить", 0),
TURN_OFF("Выключить", 525600),
DISABLE_15_MIN("15 мин", 15),
DISABLE_2_HOUR("2 часа", 120),
DISABLE_30_MIN("30 мин", 30),
DISABLE_4_HOUR("4 часа", 240),
DISABLE_60_MIN("60 мин", 60),
DISABLE_8_HOUR("8 часов", 480);
private final String name;
private final int minutes;
public static DisableMenu from(@NonNull String name) {
return Arrays.stream(DisableMenu.values())
.filter(disableMenu -> disableMenu.getName().equals(name))
.findFirst()
.orElseThrow(() -> new NotFoundException("Не найдено"));
}
}
}

View File

@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.telegram.service.unit.PullRequestProcessing;
import org.sadtech.bot.vcs.telegram.service.unit.TaskProcessing;
import org.sadtech.bot.vcs.telegram.utils.GeneratorKeyBoards;
import org.sadtech.social.bot.domain.unit.AnswerCheck;
import org.sadtech.social.bot.domain.unit.AnswerProcessing;
import org.sadtech.social.bot.domain.unit.AnswerText;
@ -42,19 +43,37 @@ public class UnitConfig {
@Bean
public AnswerText menu(
AnswerProcessing<Message> getTasks,
AnswerProcessing<Message> getPr
AnswerProcessing<Message> getPr,
AnswerText settings
) {
return AnswerText.builder()
.boxAnswer(
BoxAnswer.builder()
.message("Привет, выбери пункт меню!")
.keyBoard(KeyBoards.verticalMenuString(
"Мои задачи", "Проверить ПР"
))
.keyBoard(GeneratorKeyBoards.menu())
.build()
)
.nextUnit(getTasks)
.nextUnit(getPr)
.nextUnit(settings)
.build();
}
@Bean
public AnswerText settings(
AnswerText notifySetting
) {
return AnswerText.builder()
.boxAnswer(
BoxAnswer.builder()
.message("Здесь вы можете персонализировать бота")
.keyBoard(
KeyBoards.verticalMenuString("Уведомления")
)
.build()
)
.phrase("Настройки")
.nextUnit(notifySetting)
.build();
}

View File

@ -0,0 +1,37 @@
package org.sadtech.bot.vcs.telegram.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.sadtech.social.core.domain.keyboard.KeyBoard;
import org.sadtech.social.core.domain.keyboard.KeyBoardLine;
import org.sadtech.social.core.domain.keyboard.button.KeyBoardButtonText;
/**
* // TODO: 20.09.2020 Добавить описание.
*
* @author upagge 20.09.2020
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class GeneratorKeyBoards {
public static KeyBoard menu() {
final KeyBoardButtonText tasks = KeyBoardButtonText.builder().label("Мои задачи").build();
final KeyBoardButtonText pr = KeyBoardButtonText.builder().label("Проверить ПР").build();
final KeyBoardButtonText settings = KeyBoardButtonText.builder().label("Настройки").build();
final KeyBoardLine oneLine = KeyBoardLine.builder()
.buttonKeyBoard(tasks)
.buttonKeyBoard(pr)
.build();
final KeyBoardLine twoLine = KeyBoardLine.builder()
.buttonKeyBoard(settings)
.build();
return KeyBoard.builder()
.lineKeyBoard(oneLine)
.lineKeyBoard(twoLine)
.build();
}
}