Добавил возможность подписываться на новые репозитории
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Struchkov Mark 2023-01-25 15:07:00 +03:00
parent 91bd1bbc4b
commit f2ab675dd0
Signed by: upagge
GPG Key ID: D3018BE7BA428CA6
30 changed files with 433 additions and 184 deletions

View File

@ -28,4 +28,10 @@ public class AppSetting {
@Column(name = "enable_notify") @Column(name = "enable_notify")
private boolean enableNotify; private boolean enableNotify;
@Column(name = "project_private_scan")
private boolean projectPrivateScan;
@Column(name = "project_public_scan")
private boolean projectPublicScan;
} }

View File

@ -39,4 +39,10 @@ public class Project {
@Column(name = "web_url") @Column(name = "web_url")
private String webUrl; private String webUrl;
@Column(name = "notification")
private boolean notification;
@Column(name = "processing")
private boolean processing;
} }

View File

@ -1,5 +1,6 @@
package dev.struchkov.bot.gitlab.context.domain.notify; package dev.struchkov.bot.gitlab.context.domain.notify.project;
import dev.struchkov.bot.gitlab.context.domain.notify.Notify;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
@ -11,6 +12,7 @@ public final class NewProjectNotify implements Notify {
public static final String TYPE = "NewProjectNotify"; public static final String TYPE = "NewProjectNotify";
private final Long projectId;
private final String projectName; private final String projectName;
private final String projectUrl; private final String projectUrl;
private final String projectDescription; private final String projectDescription;
@ -18,11 +20,13 @@ public final class NewProjectNotify implements Notify {
@Builder @Builder
public NewProjectNotify( public NewProjectNotify(
Long projectId,
String projectName, String projectName,
String projectUrl, String projectUrl,
String projectDescription, String projectDescription,
String authorName String authorName
) { ) {
this.projectId = projectId;
this.projectName = projectName; this.projectName = projectName;
this.projectUrl = projectUrl; this.projectUrl = projectUrl;
this.projectDescription = projectDescription; this.projectDescription = projectDescription;

View File

@ -23,8 +23,14 @@ public interface ProjectRepository {
Page<Project> findAllById(Pageable pagination); Page<Project> findAllById(Pageable pagination);
Set<Long> findAllIds(); Set<Long> findAllIdByProcessingEnable();
Optional<String> findProjectNameById(Long projectId); Optional<String> findProjectNameById(Long projectId);
Set<Long> findAllIds();
void notification(boolean enable, Set<Long> projectIds);
void processing(boolean enable, Set<Long> projectIds);
} }

View File

@ -25,4 +25,12 @@ public interface AppSettingService {
void turnOnAllNotify(); void turnOnAllNotify();
void privateProjectScan(boolean enable);
void publicProjectScan(boolean enable);
boolean isPrivateProjectScan();
boolean isPublicProjectScan();
} }

View File

@ -25,8 +25,14 @@ public interface ProjectService {
ExistContainer<Project, Long> existsById(Set<Long> projectIds); ExistContainer<Project, Long> existsById(Set<Long> projectIds);
Set<Long> getAllIds(); Set<Long> getAllIdByProcessingEnable();
Optional<String> getProjectNameById(Long projectId); Optional<String> getProjectNameById(Long projectId);
Set<Long> getAllIds();
void notification(boolean enable, Set<Long> projectIds);
void processing(boolean enable, Set<Long> projectIds);
} }

View File

@ -25,6 +25,9 @@ public class Icons {
public static final String DISABLE_NOTIFY = "\uD83D\uDD15"; public static final String DISABLE_NOTIFY = "\uD83D\uDD15";
public static final String YES = ""; public static final String YES = "";
public static final String NO = ""; public static final String NO = "";
public static final String NOTIFY = "\uD83D\uDD14";
public static final String NO_PROCESSING = "\uD83D\uDDD1";
public static final String GOOD = "\uD83D\uDC4D";
private Icons() { private Icons() {
utilityClass(); utilityClass();

View File

@ -1,51 +0,0 @@
package dev.struchkov.bot.gitlab.context.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum Smile {
BR("\n"),
TWO_BR("\n\n"),
AUTHOR("\uD83D\uDC68\u200D\uD83D\uDCBB"),
PEN("✏️"),
FUN("\uD83C\uDF89"),
UPDATE("\uD83D\uDD04"),
SUN("\uD83D\uDD06"),
MIG("\uD83D\uDE09"),
BUY("\uD83D\uDC4B"),
FLOWER("\uD83C\uDF40"),
DAY_0("\uD83C\uDF15"),
DAY_1("\uD83C\uDF16"),
DAY_2("\uD83C\uDF17"),
DAY_3("\uD83C\uDF18"),
DAY_4("\uD83C\uDF11"),
DAY_5("\uD83C\uDF1A"),
TASK("\uD83D\uDCBC"),
TOP_ONE("\uD83C\uDF1F\uD83C\uDF1F\uD83C\uDF1F"),
TOP_TWO("\uD83D\uDE0E"),
TOP_THREE("\uD83E\uDD49"),
DANGEROUS("⚠️"),
COMMENT("\uD83D\uDCAC"),
ARROW(""),
SHORT_HR("\n-- -- --\n"),
HR("\n-- -- -- -- --\n"),
HR2("\n-- -- -- -- -- -- -- -- -- --\n"),
FAILURE(""),
SUCCESS(""),
BUILD("♻️"),
SMART("\uD83E\uDDE0"),
SADLY("\uD83D\uDE14"),
TREE("\uD83C\uDF33"),
TOP("\uD83D\uDD1D");
@Getter
private final String value;
@Override
public String toString() {
return value;
}
}

View File

@ -55,6 +55,30 @@ public class AppSettingServiceImpl implements AppSettingService {
log.info("Получение всех уведомлений активировано"); log.info("Получение всех уведомлений активировано");
} }
@Override
@Transactional
public void privateProjectScan(boolean enable) {
final AppSetting appSetting = getAppSetting();
appSetting.setProjectPrivateScan(enable);
}
@Override
@Transactional
public void publicProjectScan(boolean enable) {
final AppSetting appSetting = getAppSetting();
appSetting.setProjectPublicScan(enable);
}
@Override
public boolean isPrivateProjectScan() {
return getAppSetting().isProjectPrivateScan();
}
@Override
public boolean isPublicProjectScan() {
return getAppSetting().isProjectPublicScan();
}
private AppSetting getAppSetting() { private AppSetting getAppSetting() {
return appSettingRepository.findById(KEY) return appSettingRepository.findById(KEY)
.orElseThrow(NOT_FOUND_SETTINGS); .orElseThrow(NOT_FOUND_SETTINGS);

View File

@ -1,9 +1,8 @@
package dev.struchkov.bot.gitlab.core.service.impl; package dev.struchkov.bot.gitlab.core.service.impl;
import dev.struchkov.bot.gitlab.context.domain.ExistContainer; import dev.struchkov.bot.gitlab.context.domain.ExistContainer;
import dev.struchkov.bot.gitlab.context.domain.PersonInformation;
import dev.struchkov.bot.gitlab.context.domain.entity.Project; import dev.struchkov.bot.gitlab.context.domain.entity.Project;
import dev.struchkov.bot.gitlab.context.domain.notify.NewProjectNotify; import dev.struchkov.bot.gitlab.context.domain.notify.project.NewProjectNotify;
import dev.struchkov.bot.gitlab.context.repository.ProjectRepository; import dev.struchkov.bot.gitlab.context.repository.ProjectRepository;
import dev.struchkov.bot.gitlab.context.service.NotifyService; import dev.struchkov.bot.gitlab.context.service.NotifyService;
import dev.struchkov.bot.gitlab.context.service.PersonService; import dev.struchkov.bot.gitlab.context.service.PersonService;
@ -31,19 +30,14 @@ public class ProjectServiceImpl implements ProjectService {
private final NotifyService notifyService; private final NotifyService notifyService;
private final PersonService personService; private final PersonService personService;
private final PersonInformation personInformation;
@Override @Override
@Transactional @Transactional
public Project create(@NonNull Project project) { public Project create(@NonNull Project project) {
final Project newProject = repository.save(project); final Project newProject = repository.save(project);
final Long gitlabUserId = personInformation.getId(); final String authorName = personService.getByIdOrThrown(newProject.getCreatorId()).getName();
notifyAboutNewProject(newProject, authorName);
if (!gitlabUserId.equals(newProject.getCreatorId())) {
final String authorName = personService.getByIdOrThrown(newProject.getCreatorId()).getName();
notifyAboutNewProject(newProject, authorName);
}
return newProject; return newProject;
} }
@ -89,8 +83,8 @@ public class ProjectServiceImpl implements ProjectService {
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Set<Long> getAllIds() { public Set<Long> getAllIdByProcessingEnable() {
return repository.findAllIds(); return repository.findAllIdByProcessingEnable();
} }
@Override @Override
@ -98,9 +92,27 @@ public class ProjectServiceImpl implements ProjectService {
return repository.findProjectNameById(projectId); return repository.findProjectNameById(projectId);
} }
@Override
public Set<Long> getAllIds() {
return repository.findAllIds();
}
@Override
@Transactional
public void notification(boolean enable, @NonNull Set<Long> projectIds) {
repository.notification(enable, projectIds);
}
@Override
@Transactional
public void processing(boolean enable, @NonNull Set<Long> projectIds) {
repository.processing(enable, projectIds);
}
private void notifyAboutNewProject(Project newProject, String authorName) { private void notifyAboutNewProject(Project newProject, String authorName) {
notifyService.send( notifyService.send(
NewProjectNotify.builder() NewProjectNotify.builder()
.projectId(newProject.getId())
.projectDescription(newProject.getDescription()) .projectDescription(newProject.getDescription())
.projectName(newProject.getName()) .projectName(newProject.getName())
.projectUrl(newProject.getWebUrl()) .projectUrl(newProject.getWebUrl())

View File

@ -107,7 +107,7 @@ public class MergeRequestParser {
public void parsingNewMergeRequest() { public void parsingNewMergeRequest() {
log.debug("Старт обработки новых MR"); log.debug("Старт обработки новых MR");
final Set<Long> projectIds = projectService.getAllIds(); final Set<Long> projectIds = projectService.getAllIdByProcessingEnable();
final List<MergeRequestJson> mergeRequestJsons = getMergeRequests(projectIds); final List<MergeRequestJson> mergeRequestJsons = getMergeRequests(projectIds);

View File

@ -76,7 +76,7 @@ public class PipelineParser {
public void scanNewPipeline() { public void scanNewPipeline() {
log.debug("Старт обработки новых пайплайнов"); log.debug("Старт обработки новых пайплайнов");
final Set<Long> projectIds = projectService.getAllIds(); final Set<Long> projectIds = projectService.getAllIdByProcessingEnable();
final Map<Long, Long> pipelineProjectMap = getPipelineShortJsons(projectIds).stream() final Map<Long, Long> pipelineProjectMap = getPipelineShortJsons(projectIds).stream()
.collect(Collectors.toMap(PipelineShortJson::getId, PipelineShortJson::getProjectId)); .collect(Collectors.toMap(PipelineShortJson::getId, PipelineShortJson::getProjectId));

View File

@ -24,6 +24,7 @@ import java.util.stream.Collectors;
import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT; import static dev.struchkov.bot.gitlab.core.utils.HttpParse.ACCEPT;
import static dev.struchkov.haiti.context.exception.ConvertException.convertException; import static dev.struchkov.haiti.context.exception.ConvertException.convertException;
import static dev.struchkov.haiti.utils.Checker.checkNotEmpty;
/** /**
* Парсер проектов. * Парсер проектов.
@ -36,7 +37,7 @@ import static dev.struchkov.haiti.context.exception.ConvertException.convertExce
public class ProjectParser { public class ProjectParser {
public static final String PRIVATE = "&visibility=private"; public static final String PRIVATE = "&visibility=private";
public static final String OWNER = "&owned=true"; public static final String OWNER = "&visibility=public&owned=true";
private final ProjectService projectService; private final ProjectService projectService;
private final PersonService personService; private final PersonService personService;
@ -47,18 +48,22 @@ public class ProjectParser {
private final PersonProperty personProperty; private final PersonProperty personProperty;
public void parseAllPrivateProject() { public void parseAllPrivateProject() {
log.debug("Старт обработки приватных проектов");
parseProjects(PRIVATE); parseProjects(PRIVATE);
log.debug("Конец обработки приватных проектов");
} }
public void parseAllProjectOwner() { public void parseAllProjectOwner() {
log.debug("Старт обработки публичных проектов, в которых пользователь хозяин");
parseProjects(OWNER); parseProjects(OWNER);
log.debug("Конец обработки публичных проектов, в которых пользователь хозяин");
} }
private void parseProjects(String param) { private void parseProjects(String param) {
int page = 1; int page = 1;
List<ProjectJson> projectJsons = getProjectJsons(page, param); List<ProjectJson> projectJsons = getProjectJsons(page, param);
while (!projectJsons.isEmpty()) { while (checkNotEmpty(projectJsons)) {
final Set<Long> projectIds = projectJsons.stream() final Set<Long> projectIds = projectJsons.stream()
.map(ProjectJson::getId) .map(ProjectJson::getId)
@ -72,7 +77,7 @@ public class ProjectParser {
.map(json -> conversionService.convert(json, Project.class)) .map(json -> conversionService.convert(json, Project.class))
.toList(); .toList();
if (!newProjects.isEmpty()) { if (checkNotEmpty(newProjects)) {
projectService.createAll(newProjects); projectService.createAll(newProjects);
} }

View File

@ -47,8 +47,8 @@ public class ProjectRepositoryImpl implements ProjectRepository {
} }
@Override @Override
public Set<Long> findAllIds() { public Set<Long> findAllIdByProcessingEnable() {
return jpaRepository.findAllIds(); return jpaRepository.findAllIdByProcessingEnableTrue();
} }
@Override @Override
@ -56,4 +56,19 @@ public class ProjectRepositoryImpl implements ProjectRepository {
return jpaRepository.findProjectNameById(projectId); return jpaRepository.findProjectNameById(projectId);
} }
@Override
public Set<Long> findAllIds() {
return jpaRepository.findAllIds();
}
@Override
public void notification(boolean enable, Set<Long> projectIds) {
jpaRepository.notification(enable, projectIds);
}
@Override
public void processing(boolean enable, Set<Long> projectIds) {
jpaRepository.processing(enable, projectIds);
}
} }

View File

@ -2,6 +2,7 @@ package dev.struchkov.bot.gitlab.data.jpa;
import dev.struchkov.bot.gitlab.context.domain.entity.Project; import dev.struchkov.bot.gitlab.context.domain.entity.Project;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
@ -13,10 +14,21 @@ import java.util.Set;
*/ */
public interface ProjectJpaRepository extends JpaRepository<Project, Long> { public interface ProjectJpaRepository extends JpaRepository<Project, Long> {
@Query("SELECT p.id FROM Project p") @Query("SELECT p.id FROM Project p WHERE p.processing = true")
Set<Long> findAllIds(); Set<Long> findAllIdByProcessingEnableTrue();
@Query("SELECT p.name FROM Project p WHERE p.id = :projectId") @Query("SELECT p.name FROM Project p WHERE p.id = :projectId")
Optional<String> findProjectNameById(@Param("projectId") Long projectId); Optional<String> findProjectNameById(@Param("projectId") Long projectId);
@Query("SELECT p.id FROM Project p")
Set<Long> findAllIds();
@Modifying
@Query("UPDATE Project p SET p.notification = :enable WHERE p.id in :projectIds")
void notification(@Param("enable") boolean enable, @Param("projectIds") Set<Long> projectIds);
@Modifying
@Query("UPDATE Project p SET p.processing = :enable WHERE p.id in :projectIds")
void processing(@Param("enable") boolean enable, @Param("projectIds") Set<Long> projectIds);
} }

View File

@ -7,6 +7,7 @@ import dev.struchkov.bot.gitlab.context.service.PipelineService;
import dev.struchkov.bot.gitlab.core.service.parser.DiscussionParser; import dev.struchkov.bot.gitlab.core.service.parser.DiscussionParser;
import dev.struchkov.bot.gitlab.core.service.parser.MergeRequestParser; import dev.struchkov.bot.gitlab.core.service.parser.MergeRequestParser;
import dev.struchkov.bot.gitlab.core.service.parser.PipelineParser; import dev.struchkov.bot.gitlab.core.service.parser.PipelineParser;
import dev.struchkov.bot.gitlab.core.service.parser.ProjectParser;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -22,18 +23,25 @@ public class SchedulerService {
private final AppSettingService settingService; private final AppSettingService settingService;
private final PipelineParser pipelineParser;
private final MergeRequestParser mergeRequestParser; private final MergeRequestParser mergeRequestParser;
private final ProjectParser projectParser;
private final PipelineParser pipelineParser;
private final DiscussionParser discussionParser; private final DiscussionParser discussionParser;
private final PipelineService pipelineService; private final PipelineService pipelineService;
private final MergeRequestsService mergeRequestsService; private final MergeRequestsService mergeRequestsService;
private final DiscussionService discussionService; private final DiscussionService discussionService;
@Scheduled(cron = "0 */1 * * * *") @Scheduled(cron = "0 */2 * * * *")
public void newMergeRequest() { public void newMergeRequest() {
log.info("Запуск процесса обновления данных c GitLab"); log.info("Запуск процесса обновления данных c GitLab");
if (!settingService.isFirstStart()) { if (!settingService.isFirstStart()) {
if (settingService.isPrivateProjectScan()) {
projectParser.parseAllPrivateProject();
}
if (settingService.isPublicProjectScan()) {
projectParser.parseAllProjectOwner();
}
mergeRequestParser.parsingOldMergeRequest(); mergeRequestParser.parsingOldMergeRequest();
mergeRequestParser.parsingNewMergeRequest(); mergeRequestParser.parsingNewMergeRequest();
pipelineParser.scanOldPipeline(); pipelineParser.scanOldPipeline();

View File

@ -14,6 +14,12 @@
<column name="enable_notify" type="boolean" defaultValue="false"> <column name="enable_notify" type="boolean" defaultValue="false">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
<column name="project_private_scan" type="boolean" defaultValue="false">
<constraints nullable="false"/>
</column>
<column name="project_public_scan" type="boolean" defaultValue="false">
<constraints nullable="false"/>
</column>
</createTable> </createTable>
</changeSet> </changeSet>
@ -35,6 +41,12 @@
<column name="web_url" type="varchar(300)"> <column name="web_url" type="varchar(300)">
<constraints nullable="false" unique="true"/> <constraints nullable="false" unique="true"/>
</column> </column>
<column name="notification" type="boolean">
<constraints nullable="false"/>
</column>
<column name="processing" type="boolean">
<constraints nullable="false"/>
</column>
</createTable> </createTable>
</changeSet> </changeSet>

View File

@ -44,7 +44,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<godfather.telegram.core.version>0.0.48-SNAPSHOT</godfather.telegram.core.version> <godfather.telegram.core.version>0.0.49-SNAPSHOT</godfather.telegram.core.version>
<jakarta.persistance.version>3.1.0</jakarta.persistance.version> <jakarta.persistance.version>3.1.0</jakarta.persistance.version>

View File

@ -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.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;
import dev.struchkov.godfather.main.domain.content.Mail; import dev.struchkov.godfather.main.domain.content.Mail;
@ -78,9 +79,10 @@ public class TelegramBotConfig {
InitSettingFlow unitConfig, InitSettingFlow unitConfig,
AnswerNoteUnit commandUnit, AnswerNoteUnit commandUnit,
DeleteMessageUnit deleteMessageUnit, DeleteMessageUnit deleteMessageUnit,
DisableNotifyMrUnit disableNotifyMrUnit DisableNotifyMrUnit disableNotifyMrUnit,
EnableProjectNotify enableProjectNotify
) { ) {
final List<Object> config = List.of(menuConfig, unitConfig, commandUnit, deleteMessageUnit, disableNotifyMrUnit); final List<Object> config = List.of(menuConfig, unitConfig, commandUnit, deleteMessageUnit, disableNotifyMrUnit, enableProjectNotify);
return new StorylineMailService( return new StorylineMailService(
unitPointerService, unitPointerService,

View File

@ -1,7 +1,7 @@
package dev.struchkov.bot.gitlab.telegram.service.notify; 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.Smile; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.BoxAnswer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -14,7 +14,7 @@ public class NewCommentNotifyGenerator implements NotifyBoxAnswerGenerator<NewCo
@Override @Override
public BoxAnswer generate(NewCommentNotify notify) { public BoxAnswer generate(NewCommentNotify notify) {
final StringBuilder builder = new StringBuilder(Smile.COMMENT.getValue()).append(" [New answer in discussion](").append(notify.getUrl()).append(")"); final StringBuilder builder = new StringBuilder(Icons.COMMENT).append(" [New answer in discussion](").append(notify.getUrl()).append(")");
if (checkNotNull(notify.getDiscussionMessage())) { if (checkNotNull(notify.getDiscussionMessage())) {
builder.append("\n-- -- discussion first message -- --\n") builder.append("\n-- -- discussion first message -- --\n")

View File

@ -45,7 +45,7 @@ public class NewMrForAssigneeNotifyGenerator implements NotifyBoxAnswerGenerator
} }
builder builder
.append(Icons.TREE).append(": ").append(notify.getSourceBranch()).append(Icons.ARROW).append(notify.getTargetBranch()).append("\n") .append(Icons.TREE).append(": ").append(escapeMarkdown(notify.getSourceBranch())).append(Icons.ARROW).append(escapeMarkdown(notify.getTargetBranch())).append("\n")
.append(Icons.AUTHOR).append(": ").append(notify.getAuthor()).append("\n"); .append(Icons.AUTHOR).append(": ").append(notify.getAuthor()).append("\n");
final List<String> reviewers = notify.getReviewers(); final List<String> reviewers = notify.getReviewers();

View File

@ -44,7 +44,7 @@ public class NewMrForReviewNotifyGenerator implements NotifyBoxAnswerGenerator<N
} }
builder builder
.append(Icons.TREE).append(": ").append(notify.getSourceBranch()).append(Icons.ARROW).append(notify.getTargetBranch()).append("\n") .append(Icons.TREE).append(": ").append(escapeMarkdown(notify.getSourceBranch())).append(Icons.ARROW).append(escapeMarkdown(notify.getTargetBranch())).append("\n")
.append(Icons.AUTHOR).append(": ").append(notify.getAuthor()).append("\n"); .append(Icons.AUTHOR).append(": ").append(notify.getAuthor()).append("\n");
if (checkNotNull(notify.getAssignee())) { if (checkNotNull(notify.getAssignee())) {

View File

@ -1,15 +1,21 @@
package dev.struchkov.bot.gitlab.telegram.service.notify; package dev.struchkov.bot.gitlab.telegram.service.notify;
import dev.struchkov.bot.gitlab.context.domain.notify.NewProjectNotify; import dev.struchkov.bot.gitlab.context.domain.notify.project.NewProjectNotify;
import dev.struchkov.bot.gitlab.context.utils.Icons; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.telegram.utils.Const;
import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.haiti.utils.Strings; import dev.struchkov.haiti.utils.Strings;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Optional; import java.util.Optional;
import static dev.struchkov.bot.gitlab.context.utils.Icons.link; 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.simple.SimpleKeyBoardLine.simpleLine;
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.Strings.escapeMarkdown;
@Component @Component
public class NewProjectNotifyGenerator implements NotifyBoxAnswerGenerator<NewProjectNotify> { public class NewProjectNotifyGenerator implements NotifyBoxAnswerGenerator<NewProjectNotify> {
@ -17,24 +23,34 @@ public class NewProjectNotifyGenerator implements NotifyBoxAnswerGenerator<NewPr
@Override @Override
public BoxAnswer generate(NewProjectNotify notify) { public BoxAnswer generate(NewProjectNotify notify) {
final Optional<String> optDescription = Optional.ofNullable(notify.getProjectDescription()) final Optional<String> optDescription = Optional.ofNullable(notify.getProjectDescription())
.filter(Strings.EMPTY::equals)
.map(Strings::escapeMarkdown); .map(Strings::escapeMarkdown);
final StringBuilder builder = new StringBuilder(Icons.FUN).append("*New project*") final StringBuilder builder = new StringBuilder(Icons.FUN).append("* New project*")
.append(Icons.HR) .append(Icons.HR)
.append(link(notify.getProjectName(), notify.getProjectUrl())) .append(escapeMarkdown(notify.getProjectName()))
.append(Icons.HR); .append(Icons.HR);
if (optDescription.isPresent() || !Strings.EMPTY.equals(optDescription.get())) { if (optDescription.isPresent()) {
final String description = optDescription.get(); final String description = optDescription.get();
builder.append(description) builder.append(escapeMarkdown(description))
.append(Icons.HR); .append(Icons.HR);
} }
builder.append(Icons.AUTHOR).append(": ").append(notify.getAuthorName()); builder.append(Icons.AUTHOR).append(": ").append(escapeMarkdown(notify.getAuthorName()));
final String notifyMessage = builder.toString(); final String notifyMessage = builder.toString();
return boxAnswer(notifyMessage); return boxAnswer(
notifyMessage,
inlineKeyBoard(
simpleLine(urlButton(Icons.LINK, notify.getProjectUrl())),
simpleLine(
simpleButton(Icons.NOTIFY, "[" + Const.BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID + ":" + notify.getProjectId() + "]"),
simpleButton(Icons.DISABLE_NOTIFY, DELETE_MESSAGE)
)
)
);
} }
@Override @Override

View File

@ -2,7 +2,6 @@ package dev.struchkov.bot.gitlab.telegram.service.notify;
import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.UpdateMrNotify; import dev.struchkov.bot.gitlab.context.domain.notify.mergerequest.UpdateMrNotify;
import dev.struchkov.bot.gitlab.context.utils.Icons; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.context.utils.Smile;
import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.BoxAnswer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -25,11 +24,11 @@ public class UpdatePrNotifyGenerator implements NotifyBoxAnswerGenerator<UpdateM
public BoxAnswer generate(UpdateMrNotify notify) { public BoxAnswer generate(UpdateMrNotify notify) {
final StringBuilder builder = new StringBuilder(Icons.UPDATE).append(" *MergeRequest update*") final StringBuilder builder = new StringBuilder(Icons.UPDATE).append(" *MergeRequest update*")
.append(Smile.HR.getValue()) .append(Icons.HR)
.append(notify.getTitle()); .append(notify.getTitle());
if (notify.getAllTasks() > 0) { if (notify.getAllTasks() > 0) {
builder.append(Smile.HR.getValue()) builder.append(Icons.HR)
.append("All tasks: ").append(notify.getAllResolvedTasks()).append("/").append(notify.getAllTasks()); .append("All tasks: ").append(notify.getAllResolvedTasks()).append("/").append(notify.getAllTasks());
if (notify.getPersonTasks() > 0) { if (notify.getPersonTasks() > 0) {

View File

@ -5,10 +5,9 @@ import dev.struchkov.bot.gitlab.context.domain.entity.MergeRequest;
import dev.struchkov.bot.gitlab.context.service.AppSettingService; import dev.struchkov.bot.gitlab.context.service.AppSettingService;
import dev.struchkov.bot.gitlab.context.service.MergeRequestsService; import dev.struchkov.bot.gitlab.context.service.MergeRequestsService;
import dev.struchkov.bot.gitlab.context.service.NoteService; import dev.struchkov.bot.gitlab.context.service.NoteService;
import dev.struchkov.bot.gitlab.context.utils.Smile; import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty; import dev.struchkov.bot.gitlab.core.config.properties.GitlabProperty;
import dev.struchkov.bot.gitlab.core.service.parser.ProjectParser; import dev.struchkov.bot.gitlab.core.service.parser.ProjectParser;
import dev.struchkov.bot.gitlab.telegram.utils.Keys;
import dev.struchkov.bot.gitlab.telegram.utils.UnitName; import dev.struchkov.bot.gitlab.telegram.utils.UnitName;
import dev.struchkov.godfather.main.domain.BoxAnswer; import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.annotation.Unit; import dev.struchkov.godfather.main.domain.annotation.Unit;
@ -34,7 +33,6 @@ import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.GET_TASKS;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.SETTINGS; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.SETTINGS;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_ADD_NEW_PROJECT; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_ADD_NEW_PROJECT;
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.BoxAnswer.replaceBoxAnswer;
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton; 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.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard; import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
@ -65,7 +63,7 @@ public class MenuConfig {
.triggerCheck(mail -> !personInformation.getTelegramId().equals(mail.getPersonId())) .triggerCheck(mail -> !personInformation.getTelegramId().equals(mail.getPersonId()))
.answer(message -> { .answer(message -> {
final String messageText = new StringBuilder("\uD83D\uDEA8 *Попытка несанкционированного доступа к боту*") final String messageText = new StringBuilder("\uD83D\uDEA8 *Попытка несанкционированного доступа к боту*")
.append(Smile.HR.getValue()) .append(Icons.HR)
.append("\uD83E\uDDB9\u200D♂: ").append(message.getPersonId()).append("\n") .append("\uD83E\uDDB9\u200D♂: ").append(message.getPersonId()).append("\n")
.append("\uD83D\uDCAC: ").append(message.getText()) .append("\uD83D\uDCAC: ").append(message.getText())
.toString(); .toString();
@ -101,13 +99,6 @@ public class MenuConfig {
), ),
simpleLine(simpleButton("Settings", SETTINGS)) simpleLine(simpleButton("Settings", SETTINGS))
); );
final String personId = mail.getPersonId();
final var initSettingFinish = context.removeKey(personId, Keys.INIT_SETTING_FINISH);
if (initSettingFinish.isPresent()) {
context.removeKey(personId, Keys.INIT_SETTING_PRIVATE_PROJECT_MESSAGE_ID).ifPresent(messageId -> sending.deleteMessage(personId, messageId));
context.removeKey(personId, Keys.INIT_SETTING_PUBLIC_PROJECT_MESSAGE_ID).ifPresent(messageId -> sending.deleteMessage(personId, messageId));
return replaceBoxAnswer(messageText, generalMenuKeyBoard);
}
return boxAnswer(messageText, generalMenuKeyBoard); return boxAnswer(messageText, generalMenuKeyBoard);
} }
) )

View File

@ -0,0 +1,71 @@
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.ProjectService;
import dev.struchkov.bot.gitlab.context.utils.Icons;
import dev.struchkov.bot.gitlab.telegram.utils.UnitName;
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.Optional;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static dev.struchkov.bot.gitlab.telegram.utils.Const.BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID;
import static dev.struchkov.godfather.main.domain.BoxAnswer.replaceBoxAnswer;
@Component
@RequiredArgsConstructor
public class EnableProjectNotify {
private final ProjectService projectService;
private final AppSettingService settingService;
private final PersonInformation personInformation;
private final TelegramSending sending;
private final ScheduledExecutorService scheduledExecutorService;
@Unit(value = UnitName.ENABLE_NOTIFY_PROJECT, global = true)
public AnswerText<Mail> enableNotifyProject() {
return AnswerText.<Mail>builder()
.triggerCheck(mail -> {
final boolean isAccess = personInformation.getTelegramId().equals(mail.getPersonId());
if (isAccess) {
final boolean isFirstStart = settingService.isFirstStart();
if (!isFirstStart) {
final Optional<ButtonClickAttachment> optButtonClick = Attachments.findFirstButtonClick(mail.getAttachments());
if (optButtonClick.isPresent()) {
final ButtonClickAttachment buttonClick = optButtonClick.get();
return buttonClick.getArgByType(BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID).isPresent();
}
}
}
return false;
}).answer(
mail -> {
final ButtonClickAttachment buttonClick = Attachments.findFirstButtonClick(mail.getAttachments()).orElseThrow();
final Arg arg = buttonClick.getArgByType(BUTTON_ARG_ENABLE_NOTIFY_PROJECT_ID).orElseThrow();
final long projectId = Long.parseLong(arg.getValue());
final Set<Long> setProjectId = Set.of(projectId);
projectService.processing(true, setProjectId);
projectService.notification(true, setProjectId);
return replaceBoxAnswer(mail.getId(), Icons.GOOD + " you will now receive notifications!");
}
)
.<Integer>callBack(
sentBox -> scheduledExecutorService.schedule(() -> sending.deleteMessage(sentBox.getPersonId(), sentBox.getMessageId()), 5, TimeUnit.SECONDS)
)
.build();
}
}

View File

@ -10,7 +10,6 @@ import dev.struchkov.bot.gitlab.core.service.parser.DiscussionParser;
import dev.struchkov.bot.gitlab.core.service.parser.MergeRequestParser; import dev.struchkov.bot.gitlab.core.service.parser.MergeRequestParser;
import dev.struchkov.bot.gitlab.core.service.parser.PipelineParser; import dev.struchkov.bot.gitlab.core.service.parser.PipelineParser;
import dev.struchkov.bot.gitlab.core.service.parser.ProjectParser; import dev.struchkov.bot.gitlab.core.service.parser.ProjectParser;
import dev.struchkov.bot.gitlab.telegram.utils.Keys;
import dev.struchkov.godfather.main.domain.annotation.Unit; import dev.struchkov.godfather.main.domain.annotation.Unit;
import dev.struchkov.godfather.main.domain.content.Mail; import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.simple.core.unit.AnswerText; import dev.struchkov.godfather.simple.core.unit.AnswerText;
@ -22,12 +21,20 @@ 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.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.AUTO_PARSE_PRIVATE_PROJECT;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.AUTO_PARSE_PUBLIC_PROJECT;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSER_PRIVATE_PROJECT_NO; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSER_PRIVATE_PROJECT_NO;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSER_PRIVATE_PROJECT_YES; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSER_PRIVATE_PROJECT_YES;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSE_OWNER_PROJECT_NO; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSE_OWNER_PROJECT_NO;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSE_OWNER_PROJECT_YES; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.CHECK_PARSE_OWNER_PROJECT_YES;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.END_SETTING; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.END_SETTING;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.FIRST_START; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.FIRST_START;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_AUTO_PARSE_PRIVATE_PROJECT;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_AUTO_PARSE_PUBLIC_PROJECT;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_PARSER_PRIVATE_PROJECT; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_PARSER_PRIVATE_PROJECT;
import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_PARSE_OWNER_PROJECT; import static dev.struchkov.bot.gitlab.telegram.utils.UnitName.TEXT_PARSE_OWNER_PROJECT;
import static dev.struchkov.godfather.main.core.unit.UnitActiveType.AFTER; import static dev.struchkov.godfather.main.core.unit.UnitActiveType.AFTER;
@ -37,6 +44,7 @@ import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.s
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine; import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard; import static dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard.inlineKeyBoard;
import static dev.struchkov.godfather.telegram.simple.core.util.TriggerChecks.clickButtonRaw; import static dev.struchkov.godfather.telegram.simple.core.util.TriggerChecks.clickButtonRaw;
import static dev.struchkov.godfather.telegram.simple.core.util.TriggerChecks.isClickButton;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
/** /**
@ -65,6 +73,8 @@ public class InitSettingFlow {
private final PipelineService pipelineService; private final PipelineService pipelineService;
private final DiscussionService discussionService; private final DiscussionService discussionService;
private final ScheduledExecutorService scheduledExecutorService;
@Unit(value = FIRST_START, main = true) @Unit(value = FIRST_START, main = true)
public AnswerText<Mail> firstStart( public AnswerText<Mail> firstStart(
@Unit(value = TEXT_PARSER_PRIVATE_PROJECT) MainUnit<Mail> textParserPrivateProject @Unit(value = TEXT_PARSER_PRIVATE_PROJECT) MainUnit<Mail> textParserPrivateProject
@ -82,6 +92,7 @@ public class InitSettingFlow {
""" """
Hello! Hello!
This bot will help you keep your finger on the pulse of all your GitLab projects. This bot will help you keep your finger on the pulse of all your GitLab projects.
Press start to start initial setup 👇 Press start to start initial setup 👇
""", """,
inlineKeyBoard(simpleButton("start", TEXT_PARSER_PRIVATE_PROJECT)) inlineKeyBoard(simpleButton("start", TEXT_PARSER_PRIVATE_PROJECT))
@ -93,11 +104,16 @@ public class InitSettingFlow {
@Unit(value = TEXT_PARSER_PRIVATE_PROJECT) @Unit(value = TEXT_PARSER_PRIVATE_PROJECT)
public AnswerText<Mail> textParserPrivateProject( public AnswerText<Mail> textParserPrivateProject(
@Unit(CHECK_PARSER_PRIVATE_PROJECT_YES) MainUnit<Mail> checkParserPrivateProject @Unit(CHECK_PARSER_PRIVATE_PROJECT_YES) MainUnit<Mail> checkParserPrivateProjectYes,
@Unit(CHECK_PARSER_PRIVATE_PROJECT_NO) MainUnit<Mail> checkParserPrivateProjectNo
) { ) {
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.answer(() -> replaceBoxAnswer( .answer(() -> replaceBoxAnswer(
"Start tracking private projects?", """
I can scan all your private projects and put them on tracking. This will notify you of new merge requests and other events. Or you can add only the projects you want later manually one by one.
Add all available private projects?
""",
inlineKeyBoard( inlineKeyBoard(
simpleLine( simpleLine(
simpleButton("Yes", "YES"), simpleButton("Yes", "YES"),
@ -106,67 +122,63 @@ public class InitSettingFlow {
) )
) )
) )
.next(checkParserPrivateProject) .next(checkParserPrivateProjectYes)
.next(checkParserPrivateProjectNo)
.build(); .build();
} }
@Unit(CHECK_PARSER_PRIVATE_PROJECT_YES) @Unit(CHECK_PARSER_PRIVATE_PROJECT_YES)
public AnswerText<Mail> checkParserPrivateProjectYes( public AnswerText<Mail> checkParserPrivateProjectYes(
@Unit(TEXT_PARSE_OWNER_PROJECT) MainUnit<Mail> textParseOwnerProject @Unit(TEXT_AUTO_PARSE_PRIVATE_PROJECT) MainUnit<Mail> textAutoParsePrivateProject
) { ) {
final String step1 = """ final String step1 = """
-- -- -- -- --
🔘 Scanning of private projects has begun. 🔘 Scanning of private projects has begun.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step2 = """ final String step2 = """
-- -- -- -- -- 🟢 {0} private projects found.
🟢 Projects have been successfully added to tracking. Found: {0}
🔘 Scanning merge requests in found projects. 🔘 Scanning merge requests in found projects.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step3 = """ final String step3 = """
-- -- -- -- -- 🟢 {0} private projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1}
🔘 Scanning pipelines in found merge requests. 🔘 Scanning pipelines in found merge requests.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step4 = """ final String step4 = """
-- -- -- -- -- 🟢 {0} private projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1} 🟢 {2} pipelines found.
🟢 Pipelines have been successfully added. Found: {2}
🔘 Scanning threads in merge requests. 🔘 Scanning threads in merge requests.
Wait... Wait...
-- -- -- -- --
"""; """;
final String finalAnswer = """ final String finalAnswer = """
-- -- -- -- -- 🟢 {0} private projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1} 🟢 {2} pipelines found.
🟢 Pipelines have been successfully added. Found: {2} 🟢 {3} threads found.
🟢 Threads have been successfully added. Found: {3}
-- -- -- -- --
"""; """;
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.triggerCheck(clickButtonRaw("YES")) .triggerCheck(clickButtonRaw("YES"))
.answer(mail -> { .answer(mail -> {
final String personId = mail.getPersonId(); final String personId = mail.getPersonId();
final Integer messageId = Attachments.findFirstButtonClick(mail.getAttachments()) final String messageId = Attachments.findFirstButtonClick(mail.getAttachments())
.map(ButtonClickAttachment::getMessageId) .map(ButtonClickAttachment::getMessageId)
.orElseThrow(); .orElseThrow();
sending.replaceMessage(personId, messageId, boxAnswer(step1)); sending.replaceMessage(personId, messageId, boxAnswer(step1));
projectParser.parseAllPrivateProject(); projectParser.parseAllPrivateProject();
final int projectCount = projectService.getAllIds().size(); final Set<Long> projectIds = projectService.getAllIds();
projectService.notification(true, projectIds);
projectService.processing(true, projectIds);
final int projectCount = projectIds.size();
sending.replaceMessage(personId, messageId, boxAnswer(format(step2, projectCount))); sending.replaceMessage(personId, messageId, boxAnswer(format(step2, projectCount)));
mergeRequestParser.parsingNewMergeRequest(); mergeRequestParser.parsingNewMergeRequest();
@ -180,26 +192,63 @@ public class InitSettingFlow {
discussionParser.scanNewDiscussion(); discussionParser.scanNewDiscussion();
final int discussionCount = discussionService.getAllIds().size(); final int discussionCount = discussionService.getAllIds().size();
context.save(mail.getPersonId(), Keys.INIT_SETTING_PRIVATE_PROJECT_MESSAGE_ID, messageId);
return replaceBoxAnswer(format(finalAnswer, pipelineCount, mrCount, pipelineCount, discussionCount)); return replaceBoxAnswer(format(finalAnswer, pipelineCount, mrCount, pipelineCount, discussionCount));
}) })
.next(textParseOwnerProject) .<Integer>callBack(
sentBox -> scheduledExecutorService.schedule(() -> sending.deleteMessage(sentBox.getPersonId(), sentBox.getMessageId()), 10, TimeUnit.SECONDS)
)
.next(textAutoParsePrivateProject)
.build(); .build();
} }
@Unit(CHECK_PARSER_PRIVATE_PROJECT_NO) @Unit(CHECK_PARSER_PRIVATE_PROJECT_NO)
public AnswerText<Mail> checkParserPrivateProjectNo( public AnswerText<Mail> checkParserPrivateProjectNo(
@Unit(TEXT_PARSE_OWNER_PROJECT) MainUnit<Mail> textParseOwnerProject @Unit(TEXT_AUTO_PARSE_PRIVATE_PROJECT) MainUnit<Mail> textAutoParsePrivateProject
) { ) {
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.triggerPhrase("NO") .triggerPhrase("NO")
.answer(mail -> { .answer(replaceBoxAnswer("Okay, I won't scan private projects."))
final Integer messageId = Attachments.findFirstButtonClick(mail.getAttachments()) .<Integer>callBack(
.map(ButtonClickAttachment::getMessageId) sentBox -> scheduledExecutorService.schedule(() -> sending.deleteMessage(sentBox.getPersonId(), sentBox.getMessageId()), 10, TimeUnit.SECONDS)
.orElseThrow(); )
.next(textAutoParsePrivateProject)
.build();
}
context.save(mail.getPersonId(), Keys.INIT_SETTING_PRIVATE_PROJECT_MESSAGE_ID, messageId); @Unit(TEXT_AUTO_PARSE_PRIVATE_PROJECT)
replaceBoxAnswer("Okay, I won't scan private projects."); public AnswerText<Mail> textAutoParsePrivateProject(
@Unit(AUTO_PARSE_PRIVATE_PROJECT) MainUnit<Mail> autoParsePrivateProject
) {
return AnswerText.<Mail>builder()
.activeType(AFTER)
.answer(
boxAnswer(
"Do you want to enable automatic notification of new private projects available to you?",
inlineKeyBoard(
simpleLine(
simpleButton("Yes", "YES"),
simpleButton("No", "NO")
)
)
)
)
.next(autoParsePrivateProject)
.build();
}
@Unit(AUTO_PARSE_PRIVATE_PROJECT)
public AnswerText<Mail> autoParsePrivateProject(
@Unit(TEXT_PARSE_OWNER_PROJECT) MainUnit<Mail> textParseOwnerProject
) {
return AnswerText.<Mail>builder()
.triggerCheck(isClickButton())
.answer(mail -> {
final ButtonClickAttachment buttonClick = Attachments.findFirstButtonClick(mail.getAttachments()).orElseThrow();
if ("YES".equals(buttonClick.getRawCallBackData())) {
settingService.privateProjectScan(true);
} else {
settingService.privateProjectScan(false);
}
}) })
.next(textParseOwnerProject) .next(textParseOwnerProject)
.build(); .build();
@ -211,9 +260,14 @@ public class InitSettingFlow {
@Unit(CHECK_PARSE_OWNER_PROJECT_NO) MainUnit<Mail> checkParseOwnerProjectNo @Unit(CHECK_PARSE_OWNER_PROJECT_NO) MainUnit<Mail> checkParseOwnerProjectNo
) { ) {
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.activeType(AFTER)
.answer( .answer(
boxAnswer( replaceBoxAnswer(
"Start tracking public projects that you own?", """
Now do you want to track all available public projects *where you are the creator*?
(The process is similar to private projects)
""",
inlineKeyBoard( inlineKeyBoard(
simpleLine( simpleLine(
simpleButton("Yes", "YES"), simpleButton("Yes", "YES"),
@ -222,7 +276,6 @@ public class InitSettingFlow {
) )
) )
) )
.activeType(AFTER)
.next(checkParseOwnerProjectYes) .next(checkParseOwnerProjectYes)
.next(checkParseOwnerProjectNo) .next(checkParseOwnerProjectNo)
.build(); .build();
@ -230,93 +283,132 @@ public class InitSettingFlow {
@Unit(CHECK_PARSE_OWNER_PROJECT_YES) @Unit(CHECK_PARSE_OWNER_PROJECT_YES)
public AnswerText<Mail> checkParseOwnerProjectYes( public AnswerText<Mail> checkParseOwnerProjectYes(
@Unit(END_SETTING) MainUnit<Mail> endSetting @Unit(TEXT_AUTO_PARSE_PUBLIC_PROJECT) MainUnit<Mail> textAutoParsePublicProject
) { ) {
final String step1 = """ final String step1 = """
-- -- -- -- --
🔘 Scanning of public projects has begun. 🔘 Scanning of public projects has begun.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step2 = """ final String step2 = """
-- -- -- -- -- 🟢 {0} public projects found.
🟢 Projects have been successfully added to tracking. Found: {0}
🔘 Scanning merge requests in found projects. 🔘 Scanning merge requests in found projects.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step3 = """ final String step3 = """
-- -- -- -- -- 🟢 {0} public projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1}
🔘 Scanning pipelines in found merge requests. 🔘 Scanning pipelines in found merge requests.
Wait... Wait...
-- -- -- -- --
"""; """;
final String step4 = """ final String step4 = """
-- -- -- -- -- 🟢 {0} public projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1} 🟢 {2} pipelines found.
🟢 Pipelines have been successfully added. Found: {2}
🔘 Scanning threads in merge requests. 🔘 Scanning threads in merge requests.
Wait... Wait...
-- -- -- -- --
"""; """;
final String finalAnswer = """ final String finalAnswer = """
-- -- -- -- -- 🟢 {0} public projects found.
🟢 Projects have been successfully added to tracking. Found: {0} 🟢 {1} merge requests found.
🟢 Merge requests have been successfully added. Found: {1} 🟢 {2} pipelines found.
🟢 Pipelines have been successfully added. Found: {2} 🟢 {3} threads found.
🟢 Threads have been successfully added. Found: {3}
-- -- -- -- --
"""; """;
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.triggerCheck(clickButtonRaw("YES")) .triggerCheck(clickButtonRaw("YES"))
.answer(mail -> { .answer(mail -> {
final String personId = mail.getPersonId(); final String personId = mail.getPersonId();
final Integer messageId = Attachments.findFirstButtonClick(mail.getAttachments()) final String messageId = Attachments.findFirstButtonClick(mail.getAttachments())
.map(ButtonClickAttachment::getMessageId) .map(ButtonClickAttachment::getMessageId)
.orElseThrow(); .orElseThrow();
sending.replaceMessage(personId, messageId, boxAnswer(step1)); sending.replaceMessage(personId, messageId, boxAnswer(step1));
final int oldCountProjects = projectService.getAllIds().size();
projectParser.parseAllProjectOwner(); projectParser.parseAllProjectOwner();
final int projectCount = projectService.getAllIds().size(); final Set<Long> projectIds = projectService.getAllIds();
projectService.notification(true, projectIds);
projectService.processing(true, projectIds);
final int projectCount = projectIds.size() - oldCountProjects;
sending.replaceMessage(personId, messageId, boxAnswer(format(step2, projectCount))); sending.replaceMessage(personId, messageId, boxAnswer(format(step2, projectCount)));
final int oldCountMr = mergeRequestsService.getAllIds().size();
mergeRequestParser.parsingNewMergeRequest(); mergeRequestParser.parsingNewMergeRequest();
final int mrCount = mergeRequestsService.getAllIds().size(); final int mrCount = mergeRequestsService.getAllIds().size() - oldCountMr;
sending.replaceMessage(personId, messageId, boxAnswer(format(step3, projectCount, mrCount))); sending.replaceMessage(personId, messageId, boxAnswer(format(step3, projectCount, mrCount)));
final int oldCountPipelines = pipelineService.getAllIds().size();
pipelineParser.scanNewPipeline(); pipelineParser.scanNewPipeline();
final int pipelineCount = pipelineService.getAllIds().size(); final int pipelineCount = pipelineService.getAllIds().size() - oldCountPipelines;
sending.replaceMessage(personId, messageId, boxAnswer(format(step4, projectCount, mrCount, pipelineCount))); sending.replaceMessage(personId, messageId, boxAnswer(format(step4, projectCount, mrCount, pipelineCount)));
final int oldCountThreads = discussionService.getAllIds().size();
discussionParser.scanNewDiscussion(); discussionParser.scanNewDiscussion();
final int discussionCount = discussionService.getAllIds().size(); final int discussionCount = discussionService.getAllIds().size() - oldCountThreads;
context.save(mail.getPersonId(), Keys.INIT_SETTING_PUBLIC_PROJECT_MESSAGE_ID, messageId);
return replaceBoxAnswer(format(finalAnswer, pipelineCount, mrCount, pipelineCount, discussionCount)); return replaceBoxAnswer(format(finalAnswer, pipelineCount, mrCount, pipelineCount, discussionCount));
}) })
.next(endSetting) .<Integer>callBack(
sentBox -> scheduledExecutorService.schedule(() -> sending.deleteMessage(sentBox.getPersonId(), sentBox.getMessageId()), 10, TimeUnit.SECONDS)
)
.next(textAutoParsePublicProject)
.build(); .build();
} }
@Unit(CHECK_PARSE_OWNER_PROJECT_NO) @Unit(CHECK_PARSE_OWNER_PROJECT_NO)
public AnswerText<Mail> checkParseOwnerProjectNo( public AnswerText<Mail> checkParseOwnerProjectNo(
@Unit(END_SETTING) MainUnit<Mail> endSetting @Unit(TEXT_AUTO_PARSE_PUBLIC_PROJECT) MainUnit<Mail> textAutoParsePublicProject
) { ) {
return AnswerText.<Mail>builder() return AnswerText.<Mail>builder()
.triggerCheck(clickButtonRaw("NO")) .triggerCheck(clickButtonRaw("NO"))
.answer(replaceBoxAnswer("Okay, I won't scan public projects."))
.<Integer>callBack(
sentBox -> scheduledExecutorService.schedule(() -> sending.deleteMessage(sentBox.getPersonId(), sentBox.getMessageId()), 10, TimeUnit.SECONDS)
)
.next(textAutoParsePublicProject)
.build();
}
@Unit(TEXT_AUTO_PARSE_PUBLIC_PROJECT)
public AnswerText<Mail> textAutoParsePublicProject(
@Unit(AUTO_PARSE_PUBLIC_PROJECT) MainUnit<Mail> autoParsePublicProject
) {
return AnswerText.<Mail>builder()
.activeType(AFTER)
.answer(
boxAnswer(
"Do you want to enable automatic notification of new public projects available to you?",
inlineKeyBoard(
simpleLine(
simpleButton("Yes", "YES"),
simpleButton("No", "NO")
)
)
)
)
.next(autoParsePublicProject)
.build();
}
@Unit(AUTO_PARSE_PUBLIC_PROJECT)
public AnswerText<Mail> autoParsePublicProject(
@Unit(END_SETTING) MainUnit<Mail> endSetting
) {
return AnswerText.<Mail>builder()
.triggerCheck(isClickButton())
.answer(mail -> { .answer(mail -> {
final Integer messageId = Attachments.findFirstButtonClick(mail.getAttachments()) final ButtonClickAttachment buttonClick = Attachments.findFirstButtonClick(mail.getAttachments()).orElseThrow();
.map(ButtonClickAttachment::getMessageId) if ("YES".equals(buttonClick.getRawCallBackData())) {
.orElseThrow(); settingService.publicProjectScan(true);
context.save(mail.getPersonId(), Keys.INIT_SETTING_PUBLIC_PROJECT_MESSAGE_ID, messageId); } else {
return replaceBoxAnswer("Okay, I won't scan public projects."); settingService.publicProjectScan(false);
}
}) })
.next(endSetting) .next(endSetting)
.build(); .build();
@ -328,10 +420,9 @@ public class InitSettingFlow {
.activeType(AFTER) .activeType(AFTER)
.answer( .answer(
mail -> { mail -> {
context.save(mail.getPersonId(), Keys.INIT_SETTING_FINISH, Boolean.TRUE);
settingService.turnOnAllNotify(); settingService.turnOnAllNotify();
settingService.disableFirstStart(); settingService.disableFirstStart();
return boxAnswer(""" return replaceBoxAnswer("""
Configuration completed successfully Configuration completed successfully
Developer: [uPagge](https://mark.struchkov.dev) Developer: [uPagge](https://mark.struchkov.dev)
""", """,

View File

@ -9,6 +9,8 @@ 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_ENABLE_NOTIFY_PROJECT_ID = "ena_p_id";
public static final String BUTTON_ARG_CONFIRMATION = "conf"; public static final String BUTTON_ARG_CONFIRMATION = "conf";

View File

@ -1,13 +1,9 @@
package dev.struchkov.bot.gitlab.telegram.utils; package dev.struchkov.bot.gitlab.telegram.utils;
import dev.struchkov.godfather.main.domain.ContextKey;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
@UtilityClass @UtilityClass
public class Keys { public class Keys {
public static final ContextKey<Boolean> INIT_SETTING_FINISH = ContextKey.of("INIT_SETTING_FINISH", Boolean.class);
public static final ContextKey<Integer> INIT_SETTING_PRIVATE_PROJECT_MESSAGE_ID = ContextKey.of("INIT_SETTING_PRIVATE_PROJECT_MESSAGE_ID", Integer.class);
public static final ContextKey<Integer> INIT_SETTING_PUBLIC_PROJECT_MESSAGE_ID = ContextKey.of("INIT_SETTING_PUBLIC_PROJECT_MESSAGE_ID", Integer.class);
} }

View File

@ -20,10 +20,15 @@ public final class UnitName {
public static final String ACCESS_ERROR = "ACCESS_ERROR"; public static final String ACCESS_ERROR = "ACCESS_ERROR";
public static final String CHECK_PARSER_PRIVATE_PROJECT_NO = "CHECK_PARSER_PRIVATE_PROJECT_NO"; public static final String CHECK_PARSER_PRIVATE_PROJECT_NO = "CHECK_PARSER_PRIVATE_PROJECT_NO";
public static final String CHECK_PARSE_OWNER_PROJECT_NO = "CHECK_PARSE_OWNER_PROJECT_NO"; public static final String CHECK_PARSE_OWNER_PROJECT_NO = "CHECK_PARSE_OWNER_PROJECT_NO";
public static final String TEXT_AUTO_PARSE_PRIVATE_PROJECT = "TEXT_AUTO_PARSE_PRIVATE_PROJECT";
public static final String AUTO_PARSE_PRIVATE_PROJECT = "AUTO_PARSE_PRIVATE_PROJECT";
public static final String AUTO_PARSE_PUBLIC_PROJECT = "AUTO_PARSE_PUBLIC_PROJECT";
public static final String TEXT_AUTO_PARSE_PUBLIC_PROJECT = "TEXT_AUTO_PARSE_PUBLIC_PROJECT";
// команды // команды
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 ENABLE_NOTIFY_PROJECT = "ENABLE_NOTIFY_PROJECT";
private UnitName() { private UnitName() {
utilityClass(); utilityClass();