diff --git a/bitbucket-app/pom.xml b/bitbucket-app/pom.xml
index f09c5fc..ca58b7a 100644
--- a/bitbucket-app/pom.xml
+++ b/bitbucket-app/pom.xml
@@ -31,6 +31,12 @@
2.1.0-SNAPSHOT
+
+ org.sadtech.bot.bitbucketbot
+ teamcity-core
+ 2.1.0-SNAPSHOT
+
+
org.sadtech.bot.bitbucketbot
bitbucket-sdk
diff --git a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/BitbucketbotApplication.java b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/BitbucketbotApplication.java
index cae8a5f..764f082 100644
--- a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/BitbucketbotApplication.java
+++ b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/BitbucketbotApplication.java
@@ -5,9 +5,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-@EnableJpaRepositories(basePackages = "org.sadtech.bot.vcs.core.repository.jpa")
+@EnableJpaRepositories(basePackages = {"org.sadtech.bot.vcs.core.repository.jpa", "org.sadtech.bot.vcs.teamcity.core.repository.jpa"})
@SpringBootApplication(scanBasePackages = "org.sadtech.bot.vcs")
-@EntityScan(basePackages = "org.sadtech.bot.vcs.core.domain.entity")
+@EntityScan(basePackages = {"org.sadtech.bot.vcs.core.domain.entity", "org.sadtech.bot.vcs.teamcity.core.domain.entity"})
public class BitbucketbotApplication {
public static void main(String[] args) {
diff --git a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/config/AppConfig.java b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/config/AppConfig.java
index 40000e5..8b505ef 100644
--- a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/config/AppConfig.java
+++ b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/config/AppConfig.java
@@ -24,7 +24,7 @@ public class AppConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
- taskScheduler.setPoolSize(10);
+ taskScheduler.setPoolSize(12);
return taskScheduler;
}
diff --git a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/service/converter/PullRequestJsonConverter.java b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/service/converter/PullRequestJsonConverter.java
index 92e7c1c..6c6bc7e 100644
--- a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/service/converter/PullRequestJsonConverter.java
+++ b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/service/converter/PullRequestJsonConverter.java
@@ -30,9 +30,9 @@ public class PullRequestJsonConverter implements Converter 180 ? description.substring(0, 180) + "..." : description;
+ private String convertString(String string, int length) {
+ if (string != null) {
+ return string.length() > length ? string.substring(0, length) + "..." : string;
}
return null;
}
diff --git a/bitbucket-app/src/main/resources/application-dev.yaml b/bitbucket-app/src/main/resources/application-dev.yaml
index bf3e7ab..c327b23 100644
--- a/bitbucket-app/src/main/resources/application-dev.yaml
+++ b/bitbucket-app/src/main/resources/application-dev.yaml
@@ -32,4 +32,8 @@ bitbucketbot:
url-pull-request-close: http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400
url-pull-request-comment: http://192.168.236.164:7990/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
url-pull-request: http://192.168.236.164:7990/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/overview
- url-users: http://192.168.236.164:7990/rest/api/1.0/admin/users
\ No newline at end of file
+ url-users: http://192.168.236.164:7990/rest/api/1.0/admin/users
+ teamcity:
+ token: ${TEAMCITY_ADMIN_TOKEN}
+ project-url: http://192.168.236.164:8111/app/rest/projects
+ build-url: http://192.168.236.164:8111/app/rest/builds/?locator=project:(id:{0}),branch:(default:any)
\ No newline at end of file
diff --git a/bitbucket-app/src/main/resources/application-prod.yaml b/bitbucket-app/src/main/resources/application-prod.yaml
index 00a8b35..52b67e4 100644
--- a/bitbucket-app/src/main/resources/application-prod.yaml
+++ b/bitbucket-app/src/main/resources/application-prod.yaml
@@ -32,4 +32,8 @@ bitbucketbot:
url-pull-request-close: http://localhost:7990/rest/api/1.0/dashboard/pull-requests?limit=150&closedSince=86400
url-pull-request-comment: http://localhost:7990/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
url-pull-request: http://localhost:7990/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/overview
- url-users: http://localhost:7990/rest/api/1.0/admin/users
\ No newline at end of file
+ url-users: http://localhost:7990/rest/api/1.0/admin/users
+ teamcity:
+ token: ${TEAMCITY_ADMIN_TOKEN}
+ project-url: http://localhost:8111/app/rest/projects
+ build-url: http://localhost:8111/app/rest/builds/?locator=project:(id:{0}),branch:(default:any)
\ No newline at end of file
diff --git a/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-09-20-teamcity.xml b/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-09-20-teamcity.xml
index 3db1f1d..6e6c2fa 100644
--- a/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-09-20-teamcity.xml
+++ b/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-09-20-teamcity.xml
@@ -3,12 +3,6 @@
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
-
-
-
-
-
-
@@ -24,15 +18,55 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/GoodMorningNotify.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/GoodMorningNotify.java
index 7b1b662..d10ae64 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/GoodMorningNotify.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/GoodMorningNotify.java
@@ -55,8 +55,8 @@ public class GoodMorningNotify extends Notify {
StringBuilder message = new StringBuilder().append(Smile.SUN).append(" *Доброе утро* ").append(Smile.SUN).append(Smile.HR);
if (!pullRequestsReviews.isEmpty()) {
message.append("Необходимо проверить ").append(pullRequestsReviews.size()).append(" ПР!").append(Smile.TWO_BR)
- .append("Самые старые:").append(Smile.BR)
- .append(MessageUtils.pullRequestForReview(pullRequestsReviews));
+ .append("Самые старые:").append(Smile.BR);
+ MessageUtils.pullRequestForReview(pullRequestsReviews).ifPresent(message::append);
} else {
message.append("Ты либо самый лучший работник, либо тебе не доверяют проверку ПР ").append(Smile.MEGA_FUN).append(Smile.TWO_BR)
.append("Поздравляю, у тебя ни одного ПР на проверку!").append(Smile.BR);
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/Notify.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/Notify.java
index 4663f5c..423ac9c 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/Notify.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/Notify.java
@@ -9,9 +9,11 @@ import java.util.Set;
@Setter
public abstract class Notify {
+ protected TypeNotify typeNotify;
protected Set logins;
protected Notify(Set logins) {
+ this.typeNotify = TypeNotify.PERSON;
this.logins = logins;
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/TypeNotify.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/TypeNotify.java
new file mode 100644
index 0000000..97a04f0
--- /dev/null
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/notify/TypeNotify.java
@@ -0,0 +1,13 @@
+package org.sadtech.bot.vcs.core.domain.notify;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public enum TypeNotify {
+
+ SERVICE,
+ PERSON
+
+}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/Utils.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/Utils.java
index cb14a6b..0266591 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/Utils.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/Utils.java
@@ -39,6 +39,7 @@ public class Utils {
Request request = new Request.Builder()
.url(urlValue)
.header("Authorization", "Bearer " + token)
+ .header("Accept", "text/html,application/xhtml+xml,application/json")
.build();
try (final Response execute = client.newCall(request).execute()) {
if (execute.isSuccessful() && execute.body() != null) {
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/TaskServiceImpl.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/TaskServiceImpl.java
index 83e0bc2..c9f7c0e 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/TaskServiceImpl.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/TaskServiceImpl.java
@@ -128,7 +128,7 @@ public class TaskServiceImpl extends AbstractSimpleManagerService im
notifyService.send(
AnswerCommentNotify.builder()
.logins(Collections.singleton(oldTask.getAuthor()))
- .url(task.getUrl())
+ .url(oldTask.getUrl())
.youMessage(oldTask.getDescription())
.answers(
newAnswers.stream()
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
index 2af8b6a..f43bac8 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
@@ -30,7 +30,10 @@ public enum Smile {
MEGA_FUN("\uD83D\uDE02"),
DANGEROUS("⚠️"),
BELL("\uD83D\uDECE"),
- HR("\n -- -- -- -- --\n");
+ HR("\n -- -- -- -- --\n"),
+ FAILURE("❌"),
+ SUCCESS("✅"),
+ BUILD("♻️");
@Getter
private String value;
diff --git a/pom.xml b/pom.xml
index 153aeba..3344f1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,7 @@
bot-core
bitbucket-app
bot-rest
+ teamcity
org.sadtech.bot.bitbucketbot
@@ -24,7 +25,7 @@
1.8
- 2.1.0-SNAPSHPOT>
+ 2.1.0-SNAPSHOT
0.1.0-SNAPSHOT
0.1.0-SNAPSHOT
@@ -32,6 +33,7 @@
6.0.0.Alpha5
3.8.5
42.2.9
+ 2.2
2.3.1.RELEASE
@@ -140,6 +142,12 @@
${jackson.version}
+
+ javax.persistence
+ javax.persistence-api
+ ${javax.persistance}
+
+
diff --git a/teamcity/pom.xml b/teamcity/pom.xml
new file mode 100644
index 0000000..d88de00
--- /dev/null
+++ b/teamcity/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ bitbucketbot
+ org.sadtech.bot.bitbucketbot
+ 2.1.0-SNAPSHOT
+
+ 4.0.0
+
+ teamcity
+ pom
+
+ teamcity-sdk
+ teamcity-core
+
+
+
+
+
+ org.sadtech.bot.bitbucketbot
+ teamcity-sdk
+ 2.1.0-SNAPSHOT
+
+
+
+
+
+
\ No newline at end of file
diff --git a/teamcity/teamcity-core/pom.xml b/teamcity/teamcity-core/pom.xml
new file mode 100644
index 0000000..c5035c3
--- /dev/null
+++ b/teamcity/teamcity-core/pom.xml
@@ -0,0 +1,43 @@
+
+
+
+ teamcity
+ org.sadtech.bot.bitbucketbot
+ 2.1.0-SNAPSHOT
+
+ 4.0.0
+
+ teamcity-core
+
+
+
+
+ org.sadtech.bot.bitbucketbot
+ bot-core
+
+
+
+ org.sadtech.bot.bitbucketbot
+ teamcity-sdk
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
\ No newline at end of file
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/config/property/TeamcityProperty.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/config/property/TeamcityProperty.java
new file mode 100644
index 0000000..1ef0bd0
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/config/property/TeamcityProperty.java
@@ -0,0 +1,23 @@
+package org.sadtech.bot.vcs.teamcity.core.config.property;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+@Component
+@ConfigurationProperties(prefix = "bitbucketbot.teamcity")
+public class TeamcityProperty {
+
+ private String token;
+ private String projectUrl;
+ private String buildUrl;
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/ServiceNotify.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/ServiceNotify.java
new file mode 100644
index 0000000..1b3b69c
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/ServiceNotify.java
@@ -0,0 +1,55 @@
+package org.sadtech.bot.vcs.teamcity.core.domain;
+
+import lombok.Builder;
+import lombok.Getter;
+import org.sadtech.bot.vcs.core.domain.notify.Notify;
+import org.sadtech.bot.vcs.core.domain.notify.TypeNotify;
+import org.sadtech.bot.vcs.core.utils.Smile;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildStatus;
+
+import java.text.MessageFormat;
+import java.util.Collections;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+public class ServiceNotify extends Notify {
+
+ private final Long chatId;
+ private final BuildShort buildShort;
+
+ @Builder
+ private ServiceNotify(Long chatId, BuildShort buildShort) {
+ super(Collections.emptySet());
+ this.chatId = chatId;
+ this.buildShort = buildShort;
+ this.typeNotify = TypeNotify.SERVICE;
+ }
+
+ @Override
+ public String generateMessage() {
+ return MessageFormat.format(
+ "{0} *Сборка* | {1,number,#}:{2,number,#} | {3}" +
+ "{4} [{5}]({6}) {4}" +
+ "{7} {8}",
+ Smile.BUILD,
+ buildShort.getId(),
+ buildShort.getNumber(),
+ buildShort.getProjectId(),
+ Smile.HR,
+ buildShort.getBuildTypeId(),
+ buildShort.getUrl(),
+ getSmile(buildShort),
+ buildShort.getStatus()
+ );
+ }
+
+ private String getSmile(BuildShort buildShort) {
+ return BuildStatus.SUCCESS.equals(buildShort.getStatus()) ? Smile.SUCCESS.getValue() : Smile.FAILURE.getValue();
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/BuildShort.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/BuildShort.java
new file mode 100644
index 0000000..e89ada0
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/BuildShort.java
@@ -0,0 +1,59 @@
+package org.sadtech.bot.vcs.teamcity.core.domain.entity;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildState;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildStatus;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "teamcity_build")
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class BuildShort {
+
+ @Id
+ @Column(name = "id")
+ @EqualsAndHashCode.Include
+ private Long id;
+
+ @Column(name = "project_id")
+ private String projectId;
+
+ @Column(name = "number")
+ private Integer number;
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = "state")
+ private BuildState state;
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = "status")
+ private BuildStatus status;
+
+ @Column(name = "branch_name")
+ private String branchName;
+
+ @Column(name = "build_type_id")
+ private String buildTypeId;
+
+ @Column(name = "api_url")
+ private String apiUrl;
+
+ @Column(name = "url")
+ private String url;
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcityProject.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcityProject.java
new file mode 100644
index 0000000..008c1ab
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcityProject.java
@@ -0,0 +1,38 @@
+package org.sadtech.bot.vcs.teamcity.core.domain.entity;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "teamcity_project")
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class TeamcityProject {
+
+ @Id
+ @Column(name = "id")
+ @EqualsAndHashCode.Include
+ private String id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "url")
+ private String url;
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcitySetting.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcitySetting.java
new file mode 100644
index 0000000..061c869
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/domain/entity/TeamcitySetting.java
@@ -0,0 +1,38 @@
+package org.sadtech.bot.vcs.teamcity.core.domain.entity;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "teamcity_setting")
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class TeamcitySetting {
+
+ @Id
+ @Column(name = "id")
+ @EqualsAndHashCode.Include
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "chat_id")
+ private Long chatId;
+
+ @Column(name = "project_id")
+ private String projectId;
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/BuildShortRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/BuildShortRepository.java
new file mode 100644
index 0000000..e9b976b
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/BuildShortRepository.java
@@ -0,0 +1,18 @@
+package org.sadtech.bot.vcs.teamcity.core.repository;
+
+import lombok.NonNull;
+import org.sadtech.basic.context.repository.SimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface BuildShortRepository extends SimpleManagerRepository {
+
+ Set exists(@NonNull Set buildIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcityProjectRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcityProjectRepository.java
new file mode 100644
index 0000000..05b2366
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcityProjectRepository.java
@@ -0,0 +1,19 @@
+package org.sadtech.bot.vcs.teamcity.core.repository;
+
+import lombok.NonNull;
+import org.sadtech.basic.context.repository.SimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcityProjectRepository extends SimpleManagerRepository {
+
+ List exists(@NonNull Set projectIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcitySettingRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcitySettingRepository.java
new file mode 100644
index 0000000..9839f3f
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/TeamcitySettingRepository.java
@@ -0,0 +1,18 @@
+package org.sadtech.bot.vcs.teamcity.core.repository;
+
+import lombok.NonNull;
+import org.sadtech.basic.context.repository.SimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcitySettingRepository extends SimpleManagerRepository {
+
+ List findAllByProjectId(@NonNull String projectId);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/BuildShortRepositoryImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/BuildShortRepositoryImpl.java
new file mode 100644
index 0000000..0c5f555
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/BuildShortRepositoryImpl.java
@@ -0,0 +1,32 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.sadtech.bot.vcs.teamcity.core.repository.BuildShortRepository;
+import org.sadtech.bot.vcs.teamcity.core.repository.jpa.BuildShortJpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Repository
+public class BuildShortRepositoryImpl extends AbstractSimpleManagerRepository implements BuildShortRepository {
+
+ private final BuildShortJpaRepository jpaRepository;
+
+ public BuildShortRepositoryImpl(BuildShortJpaRepository jpaRepository) {
+ super(jpaRepository);
+ this.jpaRepository = jpaRepository;
+ }
+
+ @Override
+ public Set exists(@NonNull Set buildIds) {
+ return jpaRepository.existsByIds(buildIds);
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcityProjectRepositoryImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcityProjectRepositoryImpl.java
new file mode 100644
index 0000000..b5c1f01
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcityProjectRepositoryImpl.java
@@ -0,0 +1,32 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.sadtech.bot.vcs.teamcity.core.repository.TeamcityProjectRepository;
+import org.sadtech.bot.vcs.teamcity.core.repository.jpa.TeamcityProjectJpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Repository
+public class TeamcityProjectRepositoryImpl extends AbstractSimpleManagerRepository implements TeamcityProjectRepository {
+
+ private final TeamcityProjectJpaRepository teamcityProjectJpaRepository;
+
+ public TeamcityProjectRepositoryImpl(TeamcityProjectJpaRepository teamcityProjectJpaRepository) {
+ super(teamcityProjectJpaRepository);
+ this.teamcityProjectJpaRepository = teamcityProjectJpaRepository;
+ }
+
+ @Override
+ public List exists(@NonNull Set projectIds) {
+ return teamcityProjectJpaRepository.existsAllById(projectIds);
+ }
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcitySettingRepositoryImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcitySettingRepositoryImpl.java
new file mode 100644
index 0000000..55beb00
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/impl/TeamcitySettingRepositoryImpl.java
@@ -0,0 +1,32 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
+import org.sadtech.bot.vcs.teamcity.core.repository.TeamcitySettingRepository;
+import org.sadtech.bot.vcs.teamcity.core.repository.jpa.TeamcitySettingJpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Repository
+public class TeamcitySettingRepositoryImpl extends AbstractSimpleManagerRepository implements TeamcitySettingRepository {
+
+ private final TeamcitySettingJpaRepository jpaRepository;
+
+ public TeamcitySettingRepositoryImpl(TeamcitySettingJpaRepository jpaRepository) {
+ super(jpaRepository);
+ this.jpaRepository = jpaRepository;
+ }
+
+ @Override
+ public List findAllByProjectId(@NonNull String projectId) {
+ return jpaRepository.findAllByProjectId(projectId);
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/BuildShortJpaRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/BuildShortJpaRepository.java
new file mode 100644
index 0000000..ae29c54
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/BuildShortJpaRepository.java
@@ -0,0 +1,20 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
+
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface BuildShortJpaRepository extends JpaRepository {
+
+ @Query("SELECT b.id FROM BuildShort b WHERE b.id IN :buildIds")
+ Set existsByIds(@Param("buildIds") Set buildIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcityProjectJpaRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcityProjectJpaRepository.java
new file mode 100644
index 0000000..50489de
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcityProjectJpaRepository.java
@@ -0,0 +1,21 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
+
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcityProjectJpaRepository extends JpaRepository {
+
+ @Query("SELECT t.id FROM TeamcityProject t WHERE t.id IN :projectIds")
+ List existsAllById(@Param("projectIds") Set projectIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcitySettingJpaRepository.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcitySettingJpaRepository.java
new file mode 100644
index 0000000..b10a6c1
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/repository/jpa/TeamcitySettingJpaRepository.java
@@ -0,0 +1,17 @@
+package org.sadtech.bot.vcs.teamcity.core.repository.jpa;
+
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcitySettingJpaRepository extends JpaRepository {
+
+ List findAllByProjectId(String projectId);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/scheduler/TeamcityProjectScheduler.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/scheduler/TeamcityProjectScheduler.java
new file mode 100644
index 0000000..a75269c
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/scheduler/TeamcityProjectScheduler.java
@@ -0,0 +1,31 @@
+package org.sadtech.bot.vcs.teamcity.core.scheduler;
+
+import lombok.RequiredArgsConstructor;
+import org.sadtech.bot.vcs.teamcity.core.service.parser.BuildShortParser;
+import org.sadtech.bot.vcs.teamcity.core.service.parser.TeamcityProjectParser;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Component
+@RequiredArgsConstructor
+public class TeamcityProjectScheduler {
+
+ private final TeamcityProjectParser projectParser;
+ private final BuildShortParser buildShortParser;
+
+ @Scheduled(cron = "0 */1 * * * *")
+ public void parseNewProject() {
+ projectParser.parseNewProject();
+ }
+
+ @Scheduled(cron = "0 */1 * * * *")
+ public void parseNewBuilds() {
+ buildShortParser.parseNewBuilds();
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/BuildShortService.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/BuildShortService.java
new file mode 100644
index 0000000..fd9a90a
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/BuildShortService.java
@@ -0,0 +1,17 @@
+package org.sadtech.bot.vcs.teamcity.core.service;
+
+import org.sadtech.basic.context.service.SimpleManagerService;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface BuildShortService extends SimpleManagerService {
+
+ Set exists(Set buildIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcityProjectService.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcityProjectService.java
new file mode 100644
index 0000000..6e29553
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcityProjectService.java
@@ -0,0 +1,19 @@
+package org.sadtech.bot.vcs.teamcity.core.service;
+
+import lombok.NonNull;
+import org.sadtech.basic.context.service.SimpleManagerService;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcityProjectService extends SimpleManagerService {
+
+ List exists(@NonNull Set projectIds);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcitySettingService.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcitySettingService.java
new file mode 100644
index 0000000..5ecfc8a
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/TeamcitySettingService.java
@@ -0,0 +1,18 @@
+package org.sadtech.bot.vcs.teamcity.core.service;
+
+import lombok.NonNull;
+import org.sadtech.basic.context.service.SimpleManagerService;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public interface TeamcitySettingService extends SimpleManagerService {
+
+ List getAllByProjectId(@NonNull String projectId);
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/BuildShotJsonToBuildShortConvert.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/BuildShotJsonToBuildShortConvert.java
new file mode 100644
index 0000000..038dd75
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/BuildShotJsonToBuildShortConvert.java
@@ -0,0 +1,31 @@
+package org.sadtech.bot.vcs.teamcity.core.service.convert;
+
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Component
+public class BuildShotJsonToBuildShortConvert implements Converter {
+
+ @Override
+ public BuildShort convert(BuildShortJson source) {
+ final BuildShort buildShort = new BuildShort();
+ buildShort.setApiUrl(source.getHref());
+ buildShort.setBranchName(source.getBranchName());
+ buildShort.setId(source.getId());
+ buildShort.setNumber(source.getNumber());
+ buildShort.setState(source.getState());
+ buildShort.setStatus(source.getStatus());
+ buildShort.setUrl(source.getWebUrl());
+ buildShort.setProjectId(source.getProjectId());
+ buildShort.setBuildTypeId(source.getBuildTypeId());
+ return buildShort;
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/TeamcityProjectJsonToTeamcityProjectConvert.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/TeamcityProjectJsonToTeamcityProjectConvert.java
new file mode 100644
index 0000000..42e5187
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/convert/TeamcityProjectJsonToTeamcityProjectConvert.java
@@ -0,0 +1,26 @@
+package org.sadtech.bot.vcs.teamcity.core.service.convert;
+
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Component
+public class TeamcityProjectJsonToTeamcityProjectConvert implements Converter {
+
+ @Override
+ public TeamcityProject convert(TeamcityProjectJson source) {
+ final TeamcityProject teamcityProject = new TeamcityProject();
+ teamcityProject.setId(source.getId());
+ teamcityProject.setDescription(source.getDescription());
+ teamcityProject.setName(source.getName());
+ teamcityProject.setUrl(source.getWebUrl());
+ return teamcityProject;
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/BuildShortServiceImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/BuildShortServiceImpl.java
new file mode 100644
index 0000000..e7af188
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/BuildShortServiceImpl.java
@@ -0,0 +1,61 @@
+package org.sadtech.bot.vcs.teamcity.core.service.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.core.service.AbstractSimpleManagerService;
+import org.sadtech.bot.vcs.core.service.NotifyService;
+import org.sadtech.bot.vcs.teamcity.core.domain.ServiceNotify;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.sadtech.bot.vcs.teamcity.core.repository.BuildShortRepository;
+import org.sadtech.bot.vcs.teamcity.core.service.BuildShortService;
+import org.sadtech.bot.vcs.teamcity.core.service.TeamcitySettingService;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Service
+public class BuildShortServiceImpl extends AbstractSimpleManagerService implements BuildShortService {
+
+ private final TeamcitySettingService teamcitySettingService;
+ private final BuildShortRepository buildShortRepository;
+ private final NotifyService notifyService;
+
+ public BuildShortServiceImpl(TeamcitySettingService teamcitySettingService, BuildShortRepository buildShortRepository, NotifyService notifyService) {
+ super(buildShortRepository);
+ this.teamcitySettingService = teamcitySettingService;
+ this.buildShortRepository = buildShortRepository;
+ this.notifyService = notifyService;
+ }
+
+ @Override
+ public Set exists(Set buildIds) {
+ return buildShortRepository.exists(buildIds);
+ }
+
+ @Override
+ public BuildShort create(@NonNull BuildShort buildShort) {
+ final BuildShort newBuildShort = buildShortRepository.save(buildShort);
+
+ teamcitySettingService.getAllByProjectId(buildShort.getProjectId())
+ .forEach(
+ teamcitySetting -> notifyService.send(
+ ServiceNotify.builder()
+ .buildShort(buildShort)
+ .chatId(teamcitySetting.getChatId())
+ .build()
+ )
+ );
+
+ return newBuildShort;
+ }
+
+ @Override
+ public BuildShort update(@NonNull BuildShort buildShort) {
+ return buildShortRepository.save(buildShort);
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcityProjectServiceImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcityProjectServiceImpl.java
new file mode 100644
index 0000000..b0d224f
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcityProjectServiceImpl.java
@@ -0,0 +1,43 @@
+package org.sadtech.bot.vcs.teamcity.core.service.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.core.service.AbstractSimpleManagerService;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.sadtech.bot.vcs.teamcity.core.repository.TeamcityProjectRepository;
+import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Service
+public class TeamcityProjectServiceImpl extends AbstractSimpleManagerService implements TeamcityProjectService {
+
+ private final TeamcityProjectRepository teamcityProjectRepository;
+
+ public TeamcityProjectServiceImpl(TeamcityProjectRepository teamcityProjectRepository) {
+ super(teamcityProjectRepository);
+ this.teamcityProjectRepository = teamcityProjectRepository;
+ }
+
+ @Override
+ public List exists(@NonNull Set projectIds) {
+ return teamcityProjectRepository.exists(projectIds);
+ }
+
+ @Override
+ public TeamcityProject create(@NonNull TeamcityProject teamcityProject) {
+ return teamcityProjectRepository.save(teamcityProject);
+ }
+
+ @Override
+ public TeamcityProject update(@NonNull TeamcityProject teamcityProject) {
+ return teamcityProjectRepository.save(teamcityProject);
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcitySettingServiceImpl.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcitySettingServiceImpl.java
new file mode 100644
index 0000000..354a70b
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/impl/TeamcitySettingServiceImpl.java
@@ -0,0 +1,42 @@
+package org.sadtech.bot.vcs.teamcity.core.service.impl;
+
+import lombok.NonNull;
+import org.sadtech.basic.core.service.AbstractSimpleManagerService;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcitySetting;
+import org.sadtech.bot.vcs.teamcity.core.repository.TeamcitySettingRepository;
+import org.sadtech.bot.vcs.teamcity.core.service.TeamcitySettingService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Service
+public class TeamcitySettingServiceImpl extends AbstractSimpleManagerService implements TeamcitySettingService {
+
+ private final TeamcitySettingRepository teamcitySettingRepository;
+
+ public TeamcitySettingServiceImpl(TeamcitySettingRepository teamcitySettingRepository) {
+ super(teamcitySettingRepository);
+ this.teamcitySettingRepository = teamcitySettingRepository;
+ }
+
+ @Override
+ public List getAllByProjectId(@NonNull String projectId) {
+ return teamcitySettingRepository.findAllByProjectId(projectId);
+ }
+
+ @Override
+ public TeamcitySetting create(@NonNull TeamcitySetting entity) {
+ return null;
+ }
+
+ @Override
+ public TeamcitySetting update(@NonNull TeamcitySetting entity) {
+ return null;
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/BuildShortParser.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/BuildShortParser.java
new file mode 100644
index 0000000..6370077
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/BuildShortParser.java
@@ -0,0 +1,71 @@
+package org.sadtech.bot.vcs.teamcity.core.service.parser;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+
+import lombok.RequiredArgsConstructor;
+import org.sadtech.basic.context.page.Sheet;
+import org.sadtech.basic.core.page.PaginationImpl;
+import org.sadtech.bot.vcs.core.service.Utils;
+import org.sadtech.bot.vcs.teamcity.core.config.property.TeamcityProperty;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.BuildShort;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.sadtech.bot.vcs.teamcity.core.service.BuildShortService;
+import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
+import org.sadtech.bot.vcs.teamcity.sdk.sheet.BuildShortJsonSheet;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class BuildShortParser {
+
+ private final BuildShortService buildShortService;
+ private final TeamcityProjectService projectService;
+ private final ConversionService conversionService;
+ private final TeamcityProperty teamcityProperty;
+
+ public void parseNewBuilds() {
+ final Sheet projectSheet = projectService.getAll(PaginationImpl.of(0, 100));
+ if (projectSheet.hasContent()) {
+ projectSheet.getContent().forEach(this::parse);
+ }
+ }
+
+ private void parse(TeamcityProject project) {
+ final Optional buildShortJsonSheet = Utils.urlToJson(
+ MessageFormat.format(
+ teamcityProperty.getBuildUrl(),
+ project.getId()
+ ),
+ teamcityProperty.getToken(),
+ BuildShortJsonSheet.class
+ );
+ if (buildShortJsonSheet.isPresent()) {
+ final List buildShortJsons = buildShortJsonSheet.get().getContent();
+ final Set buildIds = buildShortJsons.stream()
+ .map(BuildShortJson::getId)
+ .collect(Collectors.toSet());
+ final Set existsId = buildShortService.exists(buildIds);
+ final List buildShorts = buildShortJsons.stream()
+ .filter(json -> !existsId.contains(json.getId()))
+ .map(json -> conversionService.convert(json, BuildShort.class))
+ .peek(
+ buildShort -> buildShort.setProjectId(project.getId())
+ )
+ .collect(Collectors.toList());
+ buildShortService.createAll(buildShorts);
+ }
+ }
+
+}
diff --git a/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/TeamcityProjectParser.java b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/TeamcityProjectParser.java
new file mode 100644
index 0000000..3f9c0d8
--- /dev/null
+++ b/teamcity/teamcity-core/src/main/java/org/sadtech/bot/vcs/teamcity/core/service/parser/TeamcityProjectParser.java
@@ -0,0 +1,53 @@
+package org.sadtech.bot.vcs.teamcity.core.service.parser;
+
+import lombok.RequiredArgsConstructor;
+import org.sadtech.bot.vcs.core.service.Utils;
+import org.sadtech.bot.vcs.teamcity.core.config.property.TeamcityProperty;
+import org.sadtech.bot.vcs.teamcity.core.domain.entity.TeamcityProject;
+import org.sadtech.bot.vcs.teamcity.core.service.TeamcityProjectService;
+import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
+import org.sadtech.bot.vcs.teamcity.sdk.sheet.TeamcityProjectJsonSheet;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Component
+@RequiredArgsConstructor
+public class TeamcityProjectParser {
+
+ private final TeamcityProjectService teamcityProjectService;
+
+ private final TeamcityProperty teamcityProperty;
+
+ private final ConversionService conversionService;
+
+ public void parseNewProject() {
+ final Optional optTeamcityProjectJsonSheet = Utils.urlToJson(
+ teamcityProperty.getProjectUrl(),
+ teamcityProperty.getToken(),
+ TeamcityProjectJsonSheet.class
+ );
+ if (optTeamcityProjectJsonSheet.isPresent()) {
+ final List teamcityProjectJsons = optTeamcityProjectJsonSheet.get().getContent();
+ final Set projectIds = teamcityProjectJsons.stream()
+ .map(TeamcityProjectJson::getId)
+ .collect(Collectors.toSet());
+ final List exists = teamcityProjectService.exists(projectIds);
+ final List teamcityProjects = teamcityProjectJsons.stream()
+ .filter(json -> !exists.contains(json.getId()))
+ .map(json -> conversionService.convert(json, TeamcityProject.class))
+ .collect(Collectors.toList());
+ teamcityProjectService.createAll(teamcityProjects);
+ }
+ }
+
+}
diff --git a/teamcity/teamcity-sdk/pom.xml b/teamcity/teamcity-sdk/pom.xml
new file mode 100644
index 0000000..e011b73
--- /dev/null
+++ b/teamcity/teamcity-sdk/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ org.sadtech.bot.bitbucketbot
+ teamcity
+ 2.1.0-SNAPSHOT
+
+ 4.0.0
+
+ teamcity-sdk
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.11.2
+
+
+
+
+
\ No newline at end of file
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildShortJson.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildShortJson.java
new file mode 100644
index 0000000..cfa108d
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildShortJson.java
@@ -0,0 +1,25 @@
+package org.sadtech.bot.vcs.teamcity.sdk;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+public class BuildShortJson {
+
+ private Long id;
+ private String projectId;
+ private Integer number;
+ private BuildState state;
+ private BuildStatus status;
+ private String branchName;
+ private String buildTypeId;
+ private String href;
+ private String webUrl;
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildState.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildState.java
new file mode 100644
index 0000000..6c3732c
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildState.java
@@ -0,0 +1,15 @@
+package org.sadtech.bot.vcs.teamcity.sdk;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public enum BuildState {
+
+ @JsonProperty("finished")
+ FINISHED
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildStatus.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildStatus.java
new file mode 100644
index 0000000..bd6ac43
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/BuildStatus.java
@@ -0,0 +1,13 @@
+package org.sadtech.bot.vcs.teamcity.sdk;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+public enum BuildStatus {
+
+ SUCCESS,
+ FAILURE
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/Sheet.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/Sheet.java
new file mode 100644
index 0000000..16977fa
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/Sheet.java
@@ -0,0 +1,21 @@
+package org.sadtech.bot.vcs.teamcity.sdk;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+public abstract class Sheet {
+
+ private Integer count;
+
+ public abstract List getContent();
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/TeamcityProjectJson.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/TeamcityProjectJson.java
new file mode 100644
index 0000000..e862d52
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/TeamcityProjectJson.java
@@ -0,0 +1,20 @@
+package org.sadtech.bot.vcs.teamcity.sdk;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Getter
+@Setter
+public class TeamcityProjectJson {
+
+ private String id;
+ private String name;
+ private String description;
+ private String webUrl;
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/BuildShortJsonSheet.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/BuildShortJsonSheet.java
new file mode 100644
index 0000000..47575cd
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/BuildShortJsonSheet.java
@@ -0,0 +1,24 @@
+package org.sadtech.bot.vcs.teamcity.sdk.sheet;
+
+import lombok.Setter;
+import org.sadtech.bot.vcs.teamcity.sdk.BuildShortJson;
+import org.sadtech.bot.vcs.teamcity.sdk.Sheet;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Setter
+public class BuildShortJsonSheet extends Sheet {
+
+ private List build;
+
+ @Override
+ public List getContent() {
+ return build;
+ }
+
+}
diff --git a/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/TeamcityProjectJsonSheet.java b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/TeamcityProjectJsonSheet.java
new file mode 100644
index 0000000..a452b52
--- /dev/null
+++ b/teamcity/teamcity-sdk/src/main/java/org/sadtech/bot/vcs/teamcity/sdk/sheet/TeamcityProjectJsonSheet.java
@@ -0,0 +1,24 @@
+package org.sadtech.bot.vcs.teamcity.sdk.sheet;
+
+import lombok.Setter;
+import org.sadtech.bot.vcs.teamcity.sdk.Sheet;
+import org.sadtech.bot.vcs.teamcity.sdk.TeamcityProjectJson;
+
+import java.util.List;
+
+/**
+ * // TODO: 21.09.2020 Добавить описание.
+ *
+ * @author upagge 21.09.2020
+ */
+@Setter
+public class TeamcityProjectJsonSheet extends Sheet {
+
+ private List project;
+
+ @Override
+ public List getContent() {
+ return project;
+ }
+
+}
diff --git a/telegram-bot/pom.xml b/telegram-bot/pom.xml
index 948265c..71a541a 100644
--- a/telegram-bot/pom.xml
+++ b/telegram-bot/pom.xml
@@ -19,6 +19,12 @@
2.1.0-SNAPSHOT
+
+ org.sadtech.bot.bitbucketbot
+ teamcity-core
+ 2.1.0-SNAPSHOT
+
+
org.sadtech.telegram
telegram-bot
diff --git a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/MessageSendTelegramService.java b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/MessageSendTelegramService.java
index 70cded2..90acd63 100644
--- a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/MessageSendTelegramService.java
+++ b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/MessageSendTelegramService.java
@@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.notify.Notify;
import org.sadtech.bot.vcs.core.service.MessageSendService;
import org.sadtech.bot.vcs.core.service.PersonService;
+import org.sadtech.bot.vcs.teamcity.core.domain.ServiceNotify;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.service.sender.Sending;
import org.springframework.stereotype.Service;
@@ -26,10 +27,19 @@ public class MessageSendTelegramService implements MessageSendService {
@Override
public void send(@NonNull Notify notify) {
- final Set telegramIds = personService.getAllTelegramIdByLogin(notify.getLogins());
- telegramIds.forEach(
- telegramId -> sending.send(telegramId, BoxAnswer.of(notify.generateMessage()))
- );
+ switch (notify.getTypeNotify()) {
+ case PERSON:
+ final Set telegramIds = personService.getAllTelegramIdByLogin(notify.getLogins());
+ telegramIds.forEach(
+ telegramId -> sending.send(telegramId, BoxAnswer.of(notify.generateMessage()))
+ );
+ break;
+ case SERVICE:
+ ServiceNotify serviceNotify = (ServiceNotify) notify;
+ sending.send(serviceNotify.getChatId(), BoxAnswer.of(notify.generateMessage()));
+ break;
+ }
+
}
}