Compare commits
2 Commits
73643cc626
...
def5eaa205
Author | SHA1 | Date | |
---|---|---|---|
def5eaa205 | |||
215ac188ff |
@ -40,6 +40,9 @@ public class Discussion {
|
|||||||
@Column(name = "resolved")
|
@Column(name = "resolved")
|
||||||
private Boolean resolved;
|
private Boolean resolved;
|
||||||
|
|
||||||
|
@Column(name = "notification")
|
||||||
|
private boolean notification;
|
||||||
|
|
||||||
@ManyToOne(optional = false, cascade = CascadeType.REMOVE)
|
@ManyToOne(optional = false, cascade = CascadeType.REMOVE)
|
||||||
@JoinTable(
|
@JoinTable(
|
||||||
name = "discussion_merge_request",
|
name = "discussion_merge_request",
|
||||||
|
@ -45,4 +45,7 @@ public class MergeRequestForDiscussion {
|
|||||||
@Column(name = "web_url")
|
@Column(name = "web_url")
|
||||||
private String webUrl;
|
private String webUrl;
|
||||||
|
|
||||||
|
@Column(name = "notification")
|
||||||
|
private boolean notification;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ public final class NewCommentNotify implements Notify {
|
|||||||
|
|
||||||
public static final String TYPE = "NewCommentNotify";
|
public static final String TYPE = "NewCommentNotify";
|
||||||
|
|
||||||
|
private final String threadId;
|
||||||
private final String mergeRequestName;
|
private final String mergeRequestName;
|
||||||
private final String url;
|
private final String url;
|
||||||
private final String discussionMessage;
|
private final String discussionMessage;
|
||||||
@ -21,6 +22,7 @@ public final class NewCommentNotify implements Notify {
|
|||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public NewCommentNotify(
|
public NewCommentNotify(
|
||||||
|
String threadId,
|
||||||
String mergeRequestName,
|
String mergeRequestName,
|
||||||
String url,
|
String url,
|
||||||
String discussionMessage,
|
String discussionMessage,
|
||||||
@ -31,6 +33,7 @@ public final class NewCommentNotify implements Notify {
|
|||||||
String message,
|
String message,
|
||||||
int numberNotes
|
int numberNotes
|
||||||
) {
|
) {
|
||||||
|
this.threadId = threadId;
|
||||||
this.mergeRequestName = mergeRequestName;
|
this.mergeRequestName = mergeRequestName;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.discussionMessage = discussionMessage;
|
this.discussionMessage = discussionMessage;
|
||||||
|
@ -15,11 +15,13 @@ public class DiscussionNewNotify extends TaskNotify {
|
|||||||
|
|
||||||
public static final String TYPE = "DiscussionNewNotify";
|
public static final String TYPE = "DiscussionNewNotify";
|
||||||
|
|
||||||
|
private final String threadId;
|
||||||
private final String mrName;
|
private final String mrName;
|
||||||
private final List<Pair<String, String>> notes;
|
private final List<Pair<String, String>> notes;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public DiscussionNewNotify(
|
public DiscussionNewNotify(
|
||||||
|
String threadId,
|
||||||
String mrName,
|
String mrName,
|
||||||
String authorName,
|
String authorName,
|
||||||
String url,
|
String url,
|
||||||
@ -27,6 +29,7 @@ public class DiscussionNewNotify extends TaskNotify {
|
|||||||
@Singular List<Pair<String, String>> notes
|
@Singular List<Pair<String, String>> notes
|
||||||
) {
|
) {
|
||||||
super(authorName, url, discussionMessage);
|
super(authorName, url, discussionMessage);
|
||||||
|
this.threadId = threadId;
|
||||||
this.mrName = mrName;
|
this.mrName = mrName;
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,6 @@ public interface DiscussionRepository {
|
|||||||
|
|
||||||
void cleanOld();
|
void cleanOld();
|
||||||
|
|
||||||
|
void notification(boolean enable, String discussionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package dev.struchkov.bot.gitlab.context.service;
|
package dev.struchkov.bot.gitlab.context.service;
|
||||||
|
|
||||||
|
import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сервис отвечает за пользовательские настройки приложения.
|
* Сервис отвечает за пользовательские настройки приложения.
|
||||||
*
|
*
|
||||||
@ -33,4 +35,6 @@ public interface AppSettingService {
|
|||||||
|
|
||||||
boolean isPrivateProjectScan();
|
boolean isPrivateProjectScan();
|
||||||
|
|
||||||
|
DiscussionLevel getLevelDiscussionNotify();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -43,4 +43,6 @@ public interface DiscussionService {
|
|||||||
|
|
||||||
void cleanOld();
|
void cleanOld();
|
||||||
|
|
||||||
|
void notification(boolean enable, String discussionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public interface ProjectService {
|
public interface ProjectService {
|
||||||
|
|
||||||
Project create(@NonNull Project project);
|
Project create(@NonNull Project project, boolean sendNotify);
|
||||||
|
|
||||||
Project update(@NonNull Project project);
|
Project update(@NonNull Project project);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dev.struchkov.bot.gitlab.core.service.impl;
|
package dev.struchkov.bot.gitlab.core.service.impl;
|
||||||
|
|
||||||
import dev.struchkov.bot.gitlab.context.domain.entity.AppSetting;
|
import dev.struchkov.bot.gitlab.context.domain.entity.AppSetting;
|
||||||
|
import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel;
|
||||||
import dev.struchkov.bot.gitlab.context.repository.AppSettingRepository;
|
import dev.struchkov.bot.gitlab.context.repository.AppSettingRepository;
|
||||||
import dev.struchkov.bot.gitlab.context.service.AppSettingService;
|
import dev.struchkov.bot.gitlab.context.service.AppSettingService;
|
||||||
import dev.struchkov.haiti.context.exception.NotFoundException;
|
import dev.struchkov.haiti.context.exception.NotFoundException;
|
||||||
@ -79,6 +80,11 @@ public class AppSettingServiceImpl implements AppSettingService {
|
|||||||
return getAppSetting().isProjectPrivateScan();
|
return getAppSetting().isProjectPrivateScan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscussionLevel getLevelDiscussionNotify() {
|
||||||
|
return getAppSetting().getDiscussionNotifyLevel();
|
||||||
|
}
|
||||||
|
|
||||||
private AppSetting getAppSetting() {
|
private AppSetting getAppSetting() {
|
||||||
return appSettingRepository.findById(KEY)
|
return appSettingRepository.findById(KEY)
|
||||||
.orElseThrow(NOT_FOUND_SETTINGS);
|
.orElseThrow(NOT_FOUND_SETTINGS);
|
||||||
|
@ -7,9 +7,11 @@ import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequestForDiscussion;
|
|||||||
import dev.struchkov.bot.gitlab.context.domain.entity.Note;
|
import dev.struchkov.bot.gitlab.context.domain.entity.Note;
|
||||||
import dev.struchkov.bot.gitlab.context.domain.entity.Person;
|
import dev.struchkov.bot.gitlab.context.domain.entity.Person;
|
||||||
import dev.struchkov.bot.gitlab.context.domain.notify.comment.NewCommentNotify;
|
import dev.struchkov.bot.gitlab.context.domain.notify.comment.NewCommentNotify;
|
||||||
|
import dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel;
|
||||||
import dev.struchkov.bot.gitlab.context.domain.notify.task.DiscussionNewNotify;
|
import dev.struchkov.bot.gitlab.context.domain.notify.task.DiscussionNewNotify;
|
||||||
import dev.struchkov.bot.gitlab.context.domain.notify.task.TaskCloseNotify;
|
import dev.struchkov.bot.gitlab.context.domain.notify.task.TaskCloseNotify;
|
||||||
import dev.struchkov.bot.gitlab.context.repository.DiscussionRepository;
|
import dev.struchkov.bot.gitlab.context.repository.DiscussionRepository;
|
||||||
|
import dev.struchkov.bot.gitlab.context.service.AppSettingService;
|
||||||
import dev.struchkov.bot.gitlab.context.service.DiscussionService;
|
import dev.struchkov.bot.gitlab.context.service.DiscussionService;
|
||||||
import dev.struchkov.bot.gitlab.context.service.NotifyService;
|
import dev.struchkov.bot.gitlab.context.service.NotifyService;
|
||||||
import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty;
|
import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty;
|
||||||
@ -38,6 +40,8 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel.NOTIFY_WITH_CONTEXT;
|
||||||
|
import static dev.struchkov.bot.gitlab.context.domain.notify.level.DiscussionLevel.WITHOUT_NOTIFY;
|
||||||
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
|
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
|
||||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
@ -53,24 +57,33 @@ import static java.lang.Boolean.FALSE;
|
|||||||
public class DiscussionServiceImpl implements DiscussionService {
|
public class DiscussionServiceImpl implements DiscussionService {
|
||||||
|
|
||||||
protected static final Pattern PATTERN = Pattern.compile("@[\\w]+");
|
protected static final Pattern PATTERN = Pattern.compile("@[\\w]+");
|
||||||
|
private final OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
private final DiscussionRepository repository;
|
private final DiscussionRepository repository;
|
||||||
private final PersonInformation personInformation;
|
|
||||||
|
|
||||||
private final OkHttpClient client = new OkHttpClient();
|
private final NotifyService notifyService;
|
||||||
|
private final AppSettingService settingService;
|
||||||
|
|
||||||
|
private final PersonInformation personInformation;
|
||||||
private final GitlabProperty gitlabProperty;
|
private final GitlabProperty gitlabProperty;
|
||||||
private final PersonProperty personProperty;
|
private final PersonProperty personProperty;
|
||||||
private final NotifyService notifyService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public Discussion create(@NonNull Discussion discussion) {
|
public Discussion create(@NonNull Discussion discussion) {
|
||||||
final List<Note> notes = discussion.getNotes();
|
final List<Note> notes = discussion.getNotes();
|
||||||
|
|
||||||
if (isNeedNotifyNewNote(discussion)) {
|
final DiscussionLevel levelDiscussionNotify = settingService.getLevelDiscussionNotify();
|
||||||
notifyNewDiscussion(discussion);
|
if (!WITHOUT_NOTIFY.equals(levelDiscussionNotify)) {
|
||||||
|
discussion.setNotification(true);
|
||||||
|
|
||||||
|
if (isNeedNotifyNewNote(discussion)) {
|
||||||
|
notifyNewDiscussion(discussion);
|
||||||
|
} else {
|
||||||
|
notes.forEach(note -> notificationPersonal(discussion, note));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
notes.forEach(note -> notificationPersonal(discussion, note));
|
discussion.setNotification(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean resolved = discussion.getNotes().stream()
|
final boolean resolved = discussion.getNotes().stream()
|
||||||
@ -89,6 +102,7 @@ public class DiscussionServiceImpl implements DiscussionService {
|
|||||||
|
|
||||||
discussion.setResponsible(oldDiscussion.getResponsible());
|
discussion.setResponsible(oldDiscussion.getResponsible());
|
||||||
discussion.setMergeRequest(oldDiscussion.getMergeRequest());
|
discussion.setMergeRequest(oldDiscussion.getMergeRequest());
|
||||||
|
discussion.setNotification(oldDiscussion.isNotification());
|
||||||
|
|
||||||
final Person responsiblePerson = discussion.getResponsible();
|
final Person responsiblePerson = discussion.getResponsible();
|
||||||
if (checkNotNull(responsiblePerson)) {
|
if (checkNotNull(responsiblePerson)) {
|
||||||
@ -104,7 +118,10 @@ public class DiscussionServiceImpl implements DiscussionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyUpdateNote(oldDiscussion, discussion);
|
|
||||||
|
if (oldDiscussion.isNotification()) {
|
||||||
|
notifyUpdateNote(oldDiscussion, discussion);
|
||||||
|
}
|
||||||
|
|
||||||
final boolean resolved = discussion.getNotes().stream()
|
final boolean resolved = discussion.getNotes().stream()
|
||||||
.allMatch(note -> note.isResolvable() && note.getResolved());
|
.allMatch(note -> note.isResolvable() && note.getResolved());
|
||||||
@ -123,6 +140,7 @@ public class DiscussionServiceImpl implements DiscussionService {
|
|||||||
|
|
||||||
final MergeRequestForDiscussion mergeRequest = discussion.getMergeRequest();
|
final MergeRequestForDiscussion mergeRequest = discussion.getMergeRequest();
|
||||||
final DiscussionNewNotify.DiscussionNewNotifyBuilder notifyBuilder = DiscussionNewNotify.builder()
|
final DiscussionNewNotify.DiscussionNewNotifyBuilder notifyBuilder = DiscussionNewNotify.builder()
|
||||||
|
.threadId(discussion.getId())
|
||||||
.mrName(mergeRequest.getTitle())
|
.mrName(mergeRequest.getTitle())
|
||||||
.authorName(firstNote.getAuthor().getName())
|
.authorName(firstNote.getAuthor().getName())
|
||||||
.discussionMessage(firstNote.getBody())
|
.discussionMessage(firstNote.getBody())
|
||||||
@ -291,29 +309,40 @@ public class DiscussionServiceImpl implements DiscussionService {
|
|||||||
log.debug("Конец очистки старых дискуссий");
|
log.debug("Конец очистки старых дискуссий");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void notification(boolean enable, String discussionId) {
|
||||||
|
repository.notification(enable, discussionId);
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyNewAnswer(Discussion discussion, Note note) {
|
private void notifyNewAnswer(Discussion discussion, Note note) {
|
||||||
if (!personInformation.getId().equals(note.getAuthor().getId())) {
|
final DiscussionLevel discussionLevel = settingService.getLevelDiscussionNotify();
|
||||||
|
|
||||||
|
if (!WITHOUT_NOTIFY.equals(discussionLevel)
|
||||||
|
&& !personInformation.getId().equals(note.getAuthor().getId())) {
|
||||||
final Note firstNote = discussion.getFirstNote();
|
final Note firstNote = discussion.getFirstNote();
|
||||||
final Optional<Note> prevLastNote = discussion.getPrevLastNote();
|
|
||||||
|
|
||||||
final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder()
|
final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder()
|
||||||
|
.threadId(discussion.getId())
|
||||||
|
.url(note.getWebUrl())
|
||||||
.mergeRequestName(discussion.getMergeRequest().getTitle());
|
.mergeRequestName(discussion.getMergeRequest().getTitle());
|
||||||
|
|
||||||
if (prevLastNote.isPresent()) {
|
if (NOTIFY_WITH_CONTEXT.equals(discussionLevel)) {
|
||||||
final Note prevNote = prevLastNote.get();
|
final Optional<Note> prevLastNote = discussion.getPrevLastNote();
|
||||||
notifyBuilder.previousMessage(prevNote.getBody());
|
if (prevLastNote.isPresent()) {
|
||||||
notifyBuilder.previousAuthor(prevNote.getAuthor().getName());
|
final Note prevNote = prevLastNote.get();
|
||||||
|
notifyBuilder.previousMessage(prevNote.getBody());
|
||||||
|
notifyBuilder.previousAuthor(prevNote.getAuthor().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyBuilder
|
||||||
|
.discussionMessage(firstNote.getBody())
|
||||||
|
.discussionAuthor(firstNote.getAuthor().getName())
|
||||||
|
.message(note.getBody())
|
||||||
|
.authorName(note.getAuthor().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyService.send(
|
notifyService.send(notifyBuilder.build());
|
||||||
notifyBuilder
|
|
||||||
.url(note.getWebUrl())
|
|
||||||
.discussionMessage(firstNote.getBody())
|
|
||||||
.discussionAuthor(firstNote.getAuthor().getName())
|
|
||||||
.message(note.getBody())
|
|
||||||
.authorName(note.getAuthor().getName())
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,32 +350,43 @@ public class DiscussionServiceImpl implements DiscussionService {
|
|||||||
* Уведомляет пользователя, если его никнейм упоминается в комментарии.
|
* Уведомляет пользователя, если его никнейм упоминается в комментарии.
|
||||||
*/
|
*/
|
||||||
protected void notificationPersonal(Discussion discussion, Note note) {
|
protected void notificationPersonal(Discussion discussion, Note note) {
|
||||||
final Matcher matcher = PATTERN.matcher(note.getBody());
|
final DiscussionLevel discussionLevel = settingService.getLevelDiscussionNotify();
|
||||||
final Set<String> recipientsLogins = new HashSet<>();
|
if (!WITHOUT_NOTIFY.equals(discussionLevel)) {
|
||||||
while (matcher.find()) {
|
final Matcher matcher = PATTERN.matcher(note.getBody());
|
||||||
final String login = matcher.group(0).replace("@", "");
|
final Set<String> recipientsLogins = new HashSet<>();
|
||||||
recipientsLogins.add(login);
|
|
||||||
}
|
|
||||||
if (recipientsLogins.contains(personInformation.getUsername())) {
|
|
||||||
final Optional<Note> prevLastNote = discussion.getPrevLastNote();
|
|
||||||
final Note firstNote = discussion.getFirstNote();
|
|
||||||
|
|
||||||
final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder()
|
while (matcher.find()) {
|
||||||
.mergeRequestName(discussion.getMergeRequest().getTitle())
|
final String login = matcher.group(0).replace("@", "");
|
||||||
.url(note.getWebUrl())
|
recipientsLogins.add(login);
|
||||||
.discussionMessage(firstNote.getBody())
|
|
||||||
.discussionAuthor(firstNote.getAuthor().getName());
|
|
||||||
if (!firstNote.equals(note)) {
|
|
||||||
notifyBuilder.message(note.getBody())
|
|
||||||
.authorName(note.getAuthor().getName());
|
|
||||||
}
|
|
||||||
if (prevLastNote.isPresent()) {
|
|
||||||
final Note prevNote = prevLastNote.get();
|
|
||||||
notifyBuilder.previousMessage(prevNote.getBody());
|
|
||||||
notifyBuilder.previousAuthor(prevNote.getAuthor().getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyService.send(notifyBuilder.build());
|
if (recipientsLogins.contains(personInformation.getUsername())) {
|
||||||
|
final NewCommentNotify.NewCommentNotifyBuilder notifyBuilder = NewCommentNotify.builder()
|
||||||
|
.threadId(discussion.getId())
|
||||||
|
.mergeRequestName(discussion.getMergeRequest().getTitle())
|
||||||
|
.url(note.getWebUrl());
|
||||||
|
|
||||||
|
if (NOTIFY_WITH_CONTEXT.equals(discussionLevel)) {
|
||||||
|
final Optional<Note> prevLastNote = discussion.getPrevLastNote();
|
||||||
|
final Note firstNote = discussion.getFirstNote();
|
||||||
|
|
||||||
|
if (!firstNote.equals(note)) {
|
||||||
|
notifyBuilder.message(note.getBody())
|
||||||
|
.authorName(note.getAuthor().getName());
|
||||||
|
}
|
||||||
|
if (prevLastNote.isPresent()) {
|
||||||
|
final Note prevNote = prevLastNote.get();
|
||||||
|
notifyBuilder.previousMessage(prevNote.getBody());
|
||||||
|
notifyBuilder.previousAuthor(prevNote.getAuthor().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyBuilder
|
||||||
|
.discussionMessage(firstNote.getBody())
|
||||||
|
.discussionAuthor(firstNote.getAuthor().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyService.send(notifyBuilder.build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,13 @@ public class ProjectServiceImpl implements ProjectService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public Project create(@NonNull Project project) {
|
public Project create(@NonNull Project project, boolean sendNotify) {
|
||||||
final Project newProject = repository.save(project);
|
final Project newProject = repository.save(project);
|
||||||
|
|
||||||
final String authorName = personService.getByIdOrThrown(newProject.getCreatorId()).getName();
|
if (sendNotify) {
|
||||||
notifyAboutNewProject(newProject, authorName);
|
final String authorName = personService.getByIdOrThrown(newProject.getCreatorId()).getName();
|
||||||
|
notifyAboutNewProject(newProject, authorName);
|
||||||
|
}
|
||||||
|
|
||||||
return newProject;
|
return newProject;
|
||||||
}
|
}
|
||||||
@ -57,7 +59,7 @@ public class ProjectServiceImpl implements ProjectService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public List<Project> createAll(List<Project> newProjects) {
|
public List<Project> createAll(List<Project> newProjects) {
|
||||||
return newProjects.stream()
|
return newProjects.stream()
|
||||||
.map(this::create)
|
.map(newProject -> create(newProject, true))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ public class ProjectParser {
|
|||||||
if (!projectService.existsById(projectJson.getId())) {
|
if (!projectService.existsById(projectJson.getId())) {
|
||||||
createNewPersons(List.of(projectJson));
|
createNewPersons(List.of(projectJson));
|
||||||
final Project newProject = conversionService.convert(projectJson, Project.class);
|
final Project newProject = conversionService.convert(projectJson, Project.class);
|
||||||
return projectService.create(newProject);
|
return projectService.create(newProject, false);
|
||||||
} else {
|
} else {
|
||||||
return projectService.getByIdOrThrow(projectJson.getId());
|
return projectService.getByIdOrThrow(projectJson.getId());
|
||||||
}
|
}
|
||||||
|
@ -62,4 +62,9 @@ public class DiscussionRepositoryImpl implements DiscussionRepository {
|
|||||||
jpaRepository.removeAllByMergeRequestIsNull();
|
jpaRepository.removeAllByMergeRequestIsNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notification(boolean enable, String discussionId) {
|
||||||
|
jpaRepository.notification(enable, discussionId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,8 @@ public interface DiscussionJpaRepository extends JpaRepository<Discussion, Strin
|
|||||||
@Query("DELETE FROM Discussion d WHERE d.id = :id")
|
@Query("DELETE FROM Discussion d WHERE d.id = :id")
|
||||||
void deleteById(@Param("id") String id);
|
void deleteById(@Param("id") String id);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("UPDATE Discussion d SET d.notification = :enable WHERE d.id = :discussionId")
|
||||||
|
void notification(@Param("enable") boolean enable, @Param("discussionId") String discussionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,9 @@
|
|||||||
references="person(id)"/>
|
references="person(id)"/>
|
||||||
</column>
|
</column>
|
||||||
<column name="resolved" type="boolean"/>
|
<column name="resolved" type="boolean"/>
|
||||||
|
<column name="notification" type="boolean">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
</createTable>
|
</createTable>
|
||||||
|
|
||||||
<createIndex tableName="discussion" indexName="i_discussion_responsible_id">
|
<createIndex tableName="discussion" indexName="i_discussion_responsible_id">
|
||||||
|
@ -5,6 +5,7 @@ import dev.struchkov.bot.gitlab.telegram.unit.MenuConfig;
|
|||||||
import dev.struchkov.bot.gitlab.telegram.unit.command.AnswerNoteUnit;
|
import dev.struchkov.bot.gitlab.telegram.unit.command.AnswerNoteUnit;
|
||||||
import dev.struchkov.bot.gitlab.telegram.unit.command.DeleteMessageUnit;
|
import dev.struchkov.bot.gitlab.telegram.unit.command.DeleteMessageUnit;
|
||||||
import dev.struchkov.bot.gitlab.telegram.unit.command.DisableNotifyMrUnit;
|
import dev.struchkov.bot.gitlab.telegram.unit.command.DisableNotifyMrUnit;
|
||||||
|
import dev.struchkov.bot.gitlab.telegram.unit.command.DisableNotifyThreadUnit;
|
||||||
import dev.struchkov.bot.gitlab.telegram.unit.command.EnableProjectNotify;
|
import dev.struchkov.bot.gitlab.telegram.unit.command.EnableProjectNotify;
|
||||||
import dev.struchkov.bot.gitlab.telegram.unit.flow.InitSettingFlow;
|
import dev.struchkov.bot.gitlab.telegram.unit.flow.InitSettingFlow;
|
||||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||||
@ -80,9 +81,11 @@ public class TelegramBotConfig {
|
|||||||
AnswerNoteUnit commandUnit,
|
AnswerNoteUnit commandUnit,
|
||||||
DeleteMessageUnit deleteMessageUnit,
|
DeleteMessageUnit deleteMessageUnit,
|
||||||
DisableNotifyMrUnit disableNotifyMrUnit,
|
DisableNotifyMrUnit disableNotifyMrUnit,
|
||||||
|
DisableNotifyThreadUnit disableNotifyThreadUnit,
|
||||||
EnableProjectNotify enableProjectNotify
|
EnableProjectNotify enableProjectNotify
|
||||||
) {
|
) {
|
||||||
final List<Object> config = List.of(menuConfig, unitConfig, commandUnit, deleteMessageUnit, disableNotifyMrUnit, enableProjectNotify);
|
final List<Object> config = List.of(menuConfig, unitConfig, commandUnit, deleteMessageUnit, disableNotifyMrUnit,
|
||||||
|
disableNotifyThreadUnit, enableProjectNotify);
|
||||||
|
|
||||||
return new StorylineMailService(
|
return new StorylineMailService(
|
||||||
unitPointerService,
|
unitPointerService,
|
||||||
|
@ -9,6 +9,9 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_CONFIRMATION;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_VALUE_FALSE;
|
||||||
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
|
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
|
||||||
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
|
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
|
||||||
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
|
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
|
||||||
@ -39,7 +42,8 @@ public class DiscussionNewNotifyGenerator implements NotifyBoxAnswerGenerator<Di
|
|||||||
notifyMessage,
|
notifyMessage,
|
||||||
inlineKeyBoard(
|
inlineKeyBoard(
|
||||||
simpleButton(Icons.VIEW, DELETE_MESSAGE),
|
simpleButton(Icons.VIEW, DELETE_MESSAGE),
|
||||||
urlButton(Icons.LINK, notify.getUrl())
|
urlButton(Icons.LINK, notify.getUrl()),
|
||||||
|
simpleButton(Icons.DISABLE_NOTIFY, "[" + BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID + ":" + notify.getThreadId() + ";" + BUTTON_ARG_CONFIRMATION + ":" + BUTTON_VALUE_FALSE + "]")
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,38 +3,58 @@ package dev.struchkov.bot.gitlab.telegram.service.notify;
|
|||||||
import dev.struchkov.bot.gitlab.context.domain.notify.comment.NewCommentNotify;
|
import dev.struchkov.bot.gitlab.context.domain.notify.comment.NewCommentNotify;
|
||||||
import dev.struchkov.bot.gitlab.context.utils.Icons;
|
import dev.struchkov.bot.gitlab.context.utils.Icons;
|
||||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_CONFIRMATION;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_VALUE_FALSE;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
|
||||||
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
|
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
|
||||||
|
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
|
||||||
|
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
|
||||||
|
import static dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton.urlButton;
|
||||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||||
import static dev.struchkov.haiti.utils.Strings.escapeMarkdown;
|
import static dev.struchkov.haiti.utils.Strings.escapeMarkdown;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class NewCommentNotifyGenerator implements NotifyBoxAnswerGenerator<NewCommentNotify> {
|
public class NewCommentNotifyGenerator implements NotifyBoxAnswerGenerator<NewCommentNotify> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BoxAnswer generate(NewCommentNotify notify) {
|
public BoxAnswer generate(NewCommentNotify notify) {
|
||||||
final StringBuilder builder = new StringBuilder(Icons.COMMENT).append(" *New answer in Thread*")
|
final StringBuilder builder = new StringBuilder(Icons.COMMENT).append(" *New answer in Thread*")
|
||||||
.append(Icons.HR)
|
.append(Icons.HR)
|
||||||
.append(escapeMarkdown(notify.getMergeRequestName()));
|
.append(Icons.link(escapeMarkdown(notify.getMergeRequestName()), notify.getUrl()))
|
||||||
|
.append("\n");
|
||||||
|
|
||||||
if (checkNotNull(notify.getDiscussionMessage())) {
|
if (checkNotNull(notify.getDiscussionMessage())) {
|
||||||
builder.append("\n-- -- thread first message -- --\n")
|
builder.append("\n-- -- thread first message -- --\n")
|
||||||
.append("*").append(notify.getDiscussionAuthor()).append("*: ").append(escapeMarkdown(notify.getDiscussionMessage()));
|
.append("*").append(notify.getDiscussionAuthor()).append("*: ").append(escapeMarkdown(notify.getDiscussionMessage()))
|
||||||
|
.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkNotNull(notify.getPreviousMessage())) {
|
if (checkNotNull(notify.getPreviousMessage())) {
|
||||||
builder.append("\n-- -- -- previous message -- -- --\n")
|
builder.append("\n-- -- -- previous message -- -- --\n")
|
||||||
.append("*").append(notify.getPreviousAuthor()).append("*: ").append(escapeMarkdown(notify.getPreviousMessage()));
|
.append("*").append(notify.getPreviousAuthor()).append("*: ").append(escapeMarkdown(notify.getPreviousMessage()))
|
||||||
|
.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkNotNull(notify.getMessage())) {
|
if (checkNotNull(notify.getMessage())) {
|
||||||
builder.append("\n-- -- -- --- new answer --- -- -- --\n")
|
builder.append("\n-- -- -- --- new answer --- -- -- --\n")
|
||||||
.append("*").append(notify.getAuthorName()).append("*: ").append(escapeMarkdown(notify.getMessage()));
|
.append("*").append(notify.getAuthorName()).append("*: ").append(escapeMarkdown(notify.getMessage()))
|
||||||
|
.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
final String messageNotify = builder.toString();
|
final String messageNotify = builder.toString();
|
||||||
return boxAnswer(messageNotify);
|
return boxAnswer(
|
||||||
|
messageNotify,
|
||||||
|
inlineKeyBoard(
|
||||||
|
simpleButton(Icons.VIEW, DELETE_MESSAGE),
|
||||||
|
urlButton(Icons.LINK, notify.getUrl()),
|
||||||
|
simpleButton(Icons.DISABLE_NOTIFY, "[" + BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID + ":" + notify.getThreadId() + ";" + BUTTON_ARG_CONFIRMATION + ":" + BUTTON_VALUE_FALSE + "]")
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -14,7 +14,6 @@ import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -54,16 +53,13 @@ public class DisableNotifyMrUnit {
|
|||||||
public AnswerText<Mail> disableNotifyMr() {
|
public AnswerText<Mail> disableNotifyMr() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(mail -> {
|
.triggerCheck(mail -> {
|
||||||
final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId());
|
final boolean isDisableButtonClick = Attachments.findFirstButtonClick(mail.getAttachments())
|
||||||
if (isAccess) {
|
.flatMap(buttonClick -> buttonClick.getArgByType(BUTTON_ARG_DISABLE_NOTIFY_MR_ID))
|
||||||
|
.isPresent();
|
||||||
|
if (isDisableButtonClick) {
|
||||||
|
final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId());
|
||||||
final boolean isFirstStart = settingService.isFirstStart();
|
final boolean isFirstStart = settingService.isFirstStart();
|
||||||
if (!isFirstStart) {
|
return isAccess && !isFirstStart;
|
||||||
final Optional<ButtonClickAttachment> optButtonClick = Attachments.findFirstButtonClick(mail.getAttachments());
|
|
||||||
if (optButtonClick.isPresent()) {
|
|
||||||
final ButtonClickAttachment buttonClick = optButtonClick.get();
|
|
||||||
return buttonClick.getArgByType(BUTTON_ARG_DISABLE_NOTIFY_MR_ID).isPresent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
package dev.struchkov.bot.gitlab.telegram.unit.command;
|
||||||
|
|
||||||
|
import dev.struchkov.bot.gitlab.context.domain.PersonInformation;
|
||||||
|
import dev.struchkov.bot.gitlab.context.service.AppSettingService;
|
||||||
|
import dev.struchkov.bot.gitlab.context.service.DiscussionService;
|
||||||
|
import dev.struchkov.bot.gitlab.context.utils.Icons;
|
||||||
|
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||||
|
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||||
|
import dev.struchkov.godfather.simple.core.unit.AnswerText;
|
||||||
|
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
|
||||||
|
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment.Arg;
|
||||||
|
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
||||||
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_CONFIRMATION;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_VALUE_TRUE;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DELETE_MESSAGE;
|
||||||
|
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.DISABLE_NOTIFY_THREAD;
|
||||||
|
import static dev.struchkov.godfather.main.domain.BoxAnswer.replaceBoxAnswer;
|
||||||
|
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
|
||||||
|
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
|
||||||
|
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DisableNotifyThreadUnit {
|
||||||
|
|
||||||
|
public static final String WARNING_ABOUT_DISABLE_NOTIFY = Icons.DISABLE_NOTIFY + """
|
||||||
|
*Disabling notifications*
|
||||||
|
|
||||||
|
Are you sure you want to stop receiving notifications of new replies to this thread?
|
||||||
|
""";
|
||||||
|
public static final String SUCCESSFULLY_DISABLED = "Notifications successfully disabled for this thread";
|
||||||
|
|
||||||
|
private final DiscussionService discussionService;
|
||||||
|
private final PersonInformation personInformation;
|
||||||
|
private final AppSettingService settingService;
|
||||||
|
private final TelegramSending telegramSending;
|
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduledExecutorService;
|
||||||
|
|
||||||
|
@Unit(value = DISABLE_NOTIFY_THREAD, global = true)
|
||||||
|
public AnswerText<Mail> disableNotifyThread() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(mail -> {
|
||||||
|
final boolean isDisableButtonClick = Attachments.findFirstButtonClick(mail.getAttachments())
|
||||||
|
.flatMap(buttonClick -> buttonClick.getArgByType(BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID))
|
||||||
|
.isPresent();
|
||||||
|
if (isDisableButtonClick) {
|
||||||
|
final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId());
|
||||||
|
final boolean isFirstStart = settingService.isFirstStart();
|
||||||
|
return isAccess && !isFirstStart;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.answer(mail -> {
|
||||||
|
final ButtonClickAttachment clickButton = Attachments.findFirstButtonClick(mail.getAttachments()).orElseThrow();
|
||||||
|
final boolean confirmation = clickButton.getArgByType(BUTTON_ARG_CONFIRMATION)
|
||||||
|
.map(Arg::getValue)
|
||||||
|
.map(BUTTON_VALUE_TRUE::equals)
|
||||||
|
.orElseThrow();
|
||||||
|
final String discussionId = clickButton.getArgByType(BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID)
|
||||||
|
.map(Arg::getValue)
|
||||||
|
.map(String::valueOf)
|
||||||
|
.orElseThrow();
|
||||||
|
|
||||||
|
if (confirmation) {
|
||||||
|
discussionService.notification(false, discussionId);
|
||||||
|
scheduledExecutorService.schedule(() -> telegramSending.deleteMessage(mail.getPersonId(), clickButton.getMessageId()), 5, TimeUnit.SECONDS);
|
||||||
|
return replaceBoxAnswer(SUCCESSFULLY_DISABLED);
|
||||||
|
} else {
|
||||||
|
return replaceBoxAnswer(
|
||||||
|
WARNING_ABOUT_DISABLE_NOTIFY,
|
||||||
|
inlineKeyBoard(
|
||||||
|
simpleLine(
|
||||||
|
simpleButton(Icons.YES, "[" + BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID + ":" + discussionId + ";" + BUTTON_ARG_CONFIRMATION + ":" + BUTTON_VALUE_TRUE + "]"),
|
||||||
|
simpleButton(Icons.NO, DELETE_MESSAGE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@ public class Const {
|
|||||||
public static final String BUTTON_VALUE_TRUE = "t";
|
public static final String BUTTON_VALUE_TRUE = "t";
|
||||||
|
|
||||||
public static final String BUTTON_ARG_DISABLE_NOTIFY_MR_ID = "dis_mr_id";
|
public static final String BUTTON_ARG_DISABLE_NOTIFY_MR_ID = "dis_mr_id";
|
||||||
|
public static final String BUTTON_ARG_DISABLE_NOTIFY_THREAD_ID = "dis_th_id";
|
||||||
public static final String BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID = "ena_p_id";
|
public static final String BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID = "ena_p_id";
|
||||||
|
|
||||||
public static final String BUTTON_ARG_CONFIRMATION = "conf";
|
public static final String BUTTON_ARG_CONFIRMATION = "conf";
|
||||||
|
@ -30,6 +30,7 @@ public final class UnitName {
|
|||||||
// команды
|
// команды
|
||||||
public static final String DELETE_MESSAGE = "DELETE_MESSAGE";
|
public static final String DELETE_MESSAGE = "DELETE_MESSAGE";
|
||||||
public static final String DISABLE_NOTIFY_MR = "DISABLE_NOTIFY_MR";
|
public static final String DISABLE_NOTIFY_MR = "DISABLE_NOTIFY_MR";
|
||||||
|
public static final String DISABLE_NOTIFY_THREAD = "DISABLE_NOTIFY_THREAD";
|
||||||
public static final String ENABLE_NOTIFY_PROJECT = "ENABLE_NOTIFY_PROJECT";
|
public static final String ENABLE_NOTIFY_PROJECT = "ENABLE_NOTIFY_PROJECT";
|
||||||
|
|
||||||
private UnitName() {
|
private UnitName() {
|
||||||
|
Loading…
Reference in New Issue
Block a user