Первая рабочая версия
This commit is contained in:
commit
487aef5f71
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**
|
||||
!**/src/test/**
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
/.mvn/wrapper/
|
||||
/mvnw
|
||||
/mvnw.cmd
|
101
pom.xml
Normal file
101
pom.xml
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.2.4.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.tsc.bitbucketbot</groupId>
|
||||
<artifactId>bitbucketbot</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>bitbucketbot</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.sadtech.telegram</groupId>
|
||||
<artifactId>telegram-bot</artifactId>
|
||||
<version>0.0.1-DEVELOPER</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.liquibase/liquibase-core -->
|
||||
<dependency>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-core</artifactId>
|
||||
<version>3.8.5</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.9</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,13 @@
|
||||
package com.tsc.bitbucketbot;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class BitbucketbotApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BitbucketbotApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/com/tsc/bitbucketbot/bitbucket/LinkJson.java
Normal file
17
src/main/java/com/tsc/bitbucketbot/bitbucket/LinkJson.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class LinkJson {
|
||||
|
||||
private List<SelfJson> self;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class PullRequestJson {
|
||||
|
||||
private Long id;
|
||||
private Integer version;
|
||||
private PullRequestState state;
|
||||
private String title;
|
||||
private String description;
|
||||
private LinkJson links;
|
||||
private UserDecisionJson author;
|
||||
private List<UserDecisionJson> reviewers;
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [01.02.2020]
|
||||
*/
|
||||
public enum PullRequestState {
|
||||
|
||||
OPEN, MERGED, DECLINED
|
||||
|
||||
}
|
15
src/main/java/com/tsc/bitbucketbot/bitbucket/SelfJson.java
Normal file
15
src/main/java/com/tsc/bitbucketbot/bitbucket/SelfJson.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class SelfJson {
|
||||
|
||||
private String href;
|
||||
|
||||
}
|
21
src/main/java/com/tsc/bitbucketbot/bitbucket/Sheet.java
Normal file
21
src/main/java/com/tsc/bitbucketbot/bitbucket/Sheet.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public abstract class Sheet<T> {
|
||||
|
||||
private Integer size;
|
||||
private Integer limit;
|
||||
private Boolean isLastPage;
|
||||
private List<T> values;
|
||||
private Integer nextPageStart;
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.BitbucketUserRole;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class UserDecisionJson {
|
||||
|
||||
private UserJson user;
|
||||
private BitbucketUserRole role;
|
||||
private Boolean approved;
|
||||
private UserPullRequestStatus status;
|
||||
|
||||
}
|
16
src/main/java/com/tsc/bitbucketbot/bitbucket/UserJson.java
Normal file
16
src/main/java/com/tsc/bitbucketbot/bitbucket/UserJson.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class UserJson {
|
||||
|
||||
private String name;
|
||||
private String displayName;
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.bitbucket;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public enum UserPullRequestStatus {
|
||||
|
||||
UNAPPROVED, APPROVED, NEEDS_WORK
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.bitbucket.sheet;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.PullRequestJson;
|
||||
import com.tsc.bitbucketbot.bitbucket.Sheet;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
public class PullRequestSheetJson extends Sheet<PullRequestJson> {
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.tsc.bitbucketbot.bitbucket.sheet;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.Sheet;
|
||||
import com.tsc.bitbucketbot.bitbucket.UserJson;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
public class UserSheetJson extends Sheet<UserJson> {
|
||||
|
||||
}
|
99
src/main/java/com/tsc/bitbucketbot/config/AppConfig.java
Normal file
99
src/main/java/com/tsc/bitbucketbot/config/AppConfig.java
Normal file
@ -0,0 +1,99 @@
|
||||
package com.tsc.bitbucketbot.config;
|
||||
|
||||
import org.sadtech.autoresponder.repository.UnitPointerRepository;
|
||||
import org.sadtech.autoresponder.repository.UnitPointerRepositoryMap;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerCheck;
|
||||
import org.sadtech.social.bot.service.action.AnswerSaveAction;
|
||||
import org.sadtech.social.core.domain.content.Mail;
|
||||
import org.sadtech.social.core.repository.impl.local.MailRepositoryList;
|
||||
import org.sadtech.social.core.service.MailService;
|
||||
import org.sadtech.social.core.service.MessageService;
|
||||
import org.sadtech.social.core.service.impl.MailServiceImpl;
|
||||
import org.sadtech.social.core.service.sender.Sending;
|
||||
import org.sadtech.telegram.bot.TelegramConfig;
|
||||
import org.sadtech.telegram.bot.autoresponder.MessageAutoresponderTelegram;
|
||||
import org.sadtech.telegram.bot.listen.EventDistributor;
|
||||
import org.sadtech.telegram.bot.listen.EventDistributorImpl;
|
||||
import org.sadtech.telegram.bot.listen.TelegramConnect;
|
||||
import org.sadtech.telegram.bot.listen.TelegramSender;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public MailService messageService() {
|
||||
return new MailServiceImpl(new MailRepositoryList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UnitPointerRepository unitPointerRepository() {
|
||||
return new UnitPointerRepositoryMap();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageAutoresponderTelegram messageAutoresponderTelegram(
|
||||
AnswerCheck checkMenu,
|
||||
Sending sending,
|
||||
MessageService<Mail> messageService,
|
||||
UnitPointerRepository unitPointerRepository
|
||||
) {
|
||||
final MessageAutoresponderTelegram messageAutoresponderTelegram = new MessageAutoresponderTelegram(
|
||||
Collections.singleton(checkMenu),
|
||||
sending,
|
||||
messageService,
|
||||
unitPointerRepository
|
||||
);
|
||||
messageAutoresponderTelegram.initSaveAction(new AnswerSaveAction<>());
|
||||
return messageAutoresponderTelegram;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.setPoolSize(5);
|
||||
return taskScheduler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Sending sending(
|
||||
TelegramConnect telegramConnect
|
||||
) {
|
||||
return new TelegramSender(telegramConnect);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TelegramConnect telegramConnect(
|
||||
TelegramConfig telegramConfig
|
||||
) {
|
||||
return new TelegramConnect(telegramConfig);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("bitbucketbot.telegram")
|
||||
public TelegramConfig telegramConfig() {
|
||||
return new TelegramConfig();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EventDistributor eventDistributor(
|
||||
TelegramConnect telegramConnect,
|
||||
MailService mailService
|
||||
) {
|
||||
return new EventDistributorImpl(telegramConnect, mailService);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.tsc.bitbucketbot.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties("bitbucketbot.bitbucket")
|
||||
public class BitbucketConfig {
|
||||
|
||||
private String token;
|
||||
private String url;
|
||||
|
||||
}
|
170
src/main/java/com/tsc/bitbucketbot/config/unit/EntranceUser.java
Normal file
170
src/main/java/com/tsc/bitbucketbot/config/unit/EntranceUser.java
Normal file
@ -0,0 +1,170 @@
|
||||
package com.tsc.bitbucketbot.config.unit;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.AuthType;
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import lombok.NonNull;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerProcessing;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerSave;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerText;
|
||||
import org.sadtech.social.bot.service.save.LocalPreservable;
|
||||
import org.sadtech.social.bot.service.save.Preservable;
|
||||
import org.sadtech.social.core.domain.BoxAnswer;
|
||||
import org.sadtech.social.core.domain.content.Message;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
@Configuration
|
||||
public class EntranceUser {
|
||||
|
||||
@Bean
|
||||
public Preservable<String> authBitbucketPreservable() {
|
||||
return new LocalPreservable<>();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerText entranceText(
|
||||
AnswerSave<String> saveLogin
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(BoxAnswer.of("Пришлите ваш логин в bitbucket"))
|
||||
.nextUnit(saveLogin)
|
||||
.phrase("Войти")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerSave<String> saveLogin(
|
||||
AnswerText savePasswordText,
|
||||
Preservable<String> authBitbucketPreservable
|
||||
) {
|
||||
return AnswerSave.<String>builder()
|
||||
.preservable(authBitbucketPreservable)
|
||||
.key(AuthType.LOGIN.name())
|
||||
.preservableData(Message::getText)
|
||||
.nextUnit(savePasswordText)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerText savePasswordText(
|
||||
AnswerSave<String> savePassword
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(BoxAnswer.of("Пришлите ваш пароль в bitbucket"))
|
||||
.nextUnit(savePassword)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerSave<String> savePassword(
|
||||
Preservable<String> authBitbucketPreservable,
|
||||
AnswerText saveTokenText
|
||||
) {
|
||||
return AnswerSave.<String>builder()
|
||||
.preservable(authBitbucketPreservable)
|
||||
.key(AuthType.PASSWORD.name())
|
||||
.preservableData(Message::getText)
|
||||
.nextUnit(saveTokenText)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerText saveTokenText(
|
||||
AnswerSave<String> saveToken
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(BoxAnswer.of("Пришлите ваш токен в bitbucket.\nПолучить можно здесь: http://192.168.236.164:7990/plugins/servlet/access-tokens/manage"))
|
||||
.nextUnit(saveToken)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerSave<String> saveToken(
|
||||
Preservable<String> authBitbucketPreservable,
|
||||
AnswerSave<String> saveTelegramId
|
||||
) {
|
||||
return AnswerSave.<String>builder()
|
||||
.preservable(authBitbucketPreservable)
|
||||
.key(AuthType.TOKEN.name())
|
||||
.preservableData(Message::getText)
|
||||
.nextUnit(saveTelegramId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerSave<String> saveTelegramId(
|
||||
Preservable<String> authBitbucketPreservable,
|
||||
AnswerProcessing<Message> auth
|
||||
) {
|
||||
return AnswerSave.<String>builder()
|
||||
.preservable(authBitbucketPreservable)
|
||||
.key(AuthType.TELEGRAM_ID.name())
|
||||
.preservableData(Message::getText)
|
||||
.hidden(true)
|
||||
.nextUnit(auth)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerProcessing<Message> auth(
|
||||
Preservable<String> authBitbucketPreservable,
|
||||
UserService userService
|
||||
) {
|
||||
return AnswerProcessing.builder()
|
||||
.processingData(message -> {
|
||||
final Optional<String> optLogin = authBitbucketPreservable.getByKey(message.getPersonId(), AuthType.LOGIN.name());
|
||||
final Optional<String> optPassword = authBitbucketPreservable.getByKey(message.getPersonId(), AuthType.PASSWORD.name());
|
||||
final Optional<String> optToken = authBitbucketPreservable.getByKey(message.getPersonId(), AuthType.TOKEN.name());
|
||||
if (optLogin.isPresent() && optPassword.isPresent() && optToken.isPresent()) {
|
||||
try {
|
||||
HttpClient httpClient = HttpClientBuilder.create().build();
|
||||
String encoding = Base64.getEncoder().encodeToString((optLogin.get() + ":" + optPassword.get()).getBytes());
|
||||
HttpGet httpPost = new HttpGet("http://192.168.236.164:7990/");
|
||||
httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoding);
|
||||
HttpResponse response = httpClient.execute(httpPost);
|
||||
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||
return registerNewUser(userService, optLogin.get(), message.getPersonId(), optToken.get());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
BoxAnswer.of("Не удалось авторизоваться");
|
||||
}
|
||||
}
|
||||
return BoxAnswer.of("Не удалось авторизоваться");
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private BoxAnswer registerNewUser(@NonNull UserService userService, @NonNull String login, @NonNull Long telegramId, @NonNull String token) {
|
||||
final Optional<User> optUser = userService.getByLogin(login);
|
||||
if (optUser.isPresent()) {
|
||||
final User user = optUser.get();
|
||||
if (user.getTelegramId() == null) {
|
||||
user.setTelegramId(telegramId);
|
||||
user.setToken(token);
|
||||
userService.update(user);
|
||||
return BoxAnswer.of("Регистрация прошла успешно");
|
||||
} else {
|
||||
return BoxAnswer.of("Пользоватль с таким логином уже зарегистрирован");
|
||||
}
|
||||
} else {
|
||||
return BoxAnswer.of("Необходимо либо создать пр, либо быть ревьювером текущего ПР, чтобы пройти регистрацию");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.tsc.bitbucketbot.config.unit;
|
||||
|
||||
import org.sadtech.social.bot.domain.unit.AnswerCheck;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerText;
|
||||
import org.sadtech.social.bot.domain.unit.MainUnit;
|
||||
import org.sadtech.social.core.domain.BoxAnswer;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
@Configuration
|
||||
public class PanelUnit {
|
||||
|
||||
@Bean
|
||||
public AnswerText textEntranceAdmin(
|
||||
MainUnit checkPasswordEntranceAdmin
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(BoxAnswer.of("Введите пароль"))
|
||||
.phrase("Панель управления")
|
||||
.nextUnit(checkPasswordEntranceAdmin)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerCheck checkPasswordEntranceAdmin(
|
||||
@Value("${bitbucketbot.panel.password}") String password
|
||||
){
|
||||
return AnswerCheck.builder()
|
||||
.check(message -> password.equals(message.getText()))
|
||||
.unitFalse(AnswerText.of("Пароль неверный"))
|
||||
// .unitTrue()
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.tsc.bitbucketbot.config.unit;
|
||||
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerCheck;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerText;
|
||||
import org.sadtech.social.bot.domain.unit.MainUnit;
|
||||
import org.sadtech.social.core.domain.BoxAnswer;
|
||||
import org.sadtech.social.core.utils.KeyBoards;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Configuration
|
||||
public class UnitConfig {
|
||||
|
||||
@Bean
|
||||
public AnswerCheck checkMenu(
|
||||
UserService userService,
|
||||
@Value("${bitbucketbot.telegram.admin-chatid}") Long adminChatId,
|
||||
AnswerText menu
|
||||
) {
|
||||
return AnswerCheck.builder()
|
||||
.check(message -> !userService.existsByTelegramId(message.getPersonId()) || message.getPersonId().equals(adminChatId))
|
||||
.unitTrue(menu)
|
||||
.unitFalse(AnswerText.of("Вы уже получаете уведомления"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnswerText menu(
|
||||
MainUnit entranceText,
|
||||
MainUnit textEntranceAdmin
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(
|
||||
BoxAnswer.builder()
|
||||
.message("Привет. Я помогаю сотрудникам ТСК отслеживать события в Bitbucket. Если хочешь войти, обращайся к @upagge")
|
||||
.keyBoard(KeyBoards.verticalMenuString("Войти", "Панель управления"))
|
||||
.build()
|
||||
)
|
||||
.nextUnit(entranceText)
|
||||
.nextUnit(textEntranceAdmin)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/com/tsc/bitbucketbot/domain/AuthBitbucket.java
Normal file
17
src/main/java/com/tsc/bitbucketbot/domain/AuthBitbucket.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import org.junit.experimental.theories.DataPoints;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Data
|
||||
public class AuthBitbucket {
|
||||
|
||||
private String login;
|
||||
private String token;
|
||||
|
||||
}
|
12
src/main/java/com/tsc/bitbucketbot/domain/AuthType.java
Normal file
12
src/main/java/com/tsc/bitbucketbot/domain/AuthType.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public enum AuthType {
|
||||
|
||||
TOKEN, LOGIN, TELEGRAM_ID, PASSWORD
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public enum BitbucketUserRole {
|
||||
|
||||
AUTHOR, REVIEWER
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public enum PullRequestStatus {
|
||||
|
||||
OPEN, MERGED, DECLINED
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
/**
|
||||
* TODO: Добавить комментарий енума.
|
||||
*
|
||||
* @author upagge [01.02.2020]
|
||||
*/
|
||||
public enum ReviewerStatus {
|
||||
|
||||
NEEDS_WORK, APPROVED, UNAPPROVED
|
||||
|
||||
}
|
13
src/main/java/com/tsc/bitbucketbot/domain/UserAuth.java
Normal file
13
src/main/java/com/tsc/bitbucketbot/domain/UserAuth.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.tsc.bitbucketbot.domain;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
public class UserAuth {
|
||||
|
||||
private String login;
|
||||
private String password;
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.tsc.bitbucketbot.domain.entity;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.PullRequestStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@ToString
|
||||
public class PullRequest {
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "autor_login")
|
||||
private User author;
|
||||
|
||||
@OneToMany(mappedBy = "pullRequestId", cascade = CascadeType.ALL)
|
||||
private List<Reviewer> reviewers;
|
||||
|
||||
@Column(name = "url")
|
||||
private String url;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "status")
|
||||
private PullRequestStatus status;
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.tsc.bitbucketbot.domain.entity;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.ReviewerStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [01.02.2020]
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "reviewer")
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class Reviewer {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
// @OneToMany(fetch = FetchType.LAZY)
|
||||
// @JoinColumn(name = "pull_request_id")
|
||||
@Column(name = "pull_request_id")
|
||||
private Long pullRequestId;
|
||||
|
||||
// @OneToMany(fetch = FetchType.LAZY)
|
||||
// @JoinColumn(name = "user_login")
|
||||
@Column(name = "user_login")
|
||||
private String user;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "status")
|
||||
private ReviewerStatus status;
|
||||
|
||||
|
||||
}
|
48
src/main/java/com/tsc/bitbucketbot/domain/entity/User.java
Normal file
48
src/main/java/com/tsc/bitbucketbot/domain/entity/User.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.tsc.bitbucketbot.domain.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Builder
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "`user`")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(of = "login")
|
||||
@ToString
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@Column(name = "login")
|
||||
private String login;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "token")
|
||||
private String token;
|
||||
|
||||
@Column(name = "telegram_id")
|
||||
private Long telegramId;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.tsc.bitbucketbot.repository;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.PullRequest;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание интерфейса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public interface PullRequestsRepository extends JpaRepository<PullRequest, Long> {
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.tsc.bitbucketbot.repository;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
|
||||
boolean existsByTelegramId(Long chatId);
|
||||
|
||||
@Query("SELECT u FROM User u WHERE u.telegramId IS NOT NULL AND u.token IS NOT NULL")
|
||||
List<User> findAllRegistered();
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.tsc.bitbucketbot.scheduler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.sadtech.telegram.bot.autoresponder.MessageAutoresponderTelegram;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SchedulerNewMessage {
|
||||
|
||||
private final MessageAutoresponderTelegram messageAutoresponderTelegram;
|
||||
|
||||
@Scheduled(fixedRate = 3000)
|
||||
public void scan() {
|
||||
messageAutoresponderTelegram.checkNewMessage();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.tsc.bitbucketbot.scheduler;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.Sheet;
|
||||
import com.tsc.bitbucketbot.bitbucket.UserJson;
|
||||
import com.tsc.bitbucketbot.bitbucket.sheet.UserSheetJson;
|
||||
import com.tsc.bitbucketbot.config.BitbucketConfig;
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import com.tsc.bitbucketbot.service.Utils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SchedulerNewUser {
|
||||
|
||||
public static final String URL = "http://192.168.236.164:7990/rest/api/1.0/admin/users";
|
||||
private final UserService userService;
|
||||
private final ConversionService conversionService;
|
||||
private final BitbucketConfig bitbucketConfig;
|
||||
|
||||
@Scheduled(fixedRate = 86400000)
|
||||
private void scan() {
|
||||
Optional<UserSheetJson> sheetJson = Utils.urlToJson(URL, bitbucketConfig.getToken(), UserSheetJson.class);
|
||||
while (sheetJson.isPresent() && sheetJson.get().getValues()!=null && !sheetJson.get().getValues().isEmpty()) {
|
||||
final UserSheetJson sheetUsers = sheetJson.get();
|
||||
final List<UserJson> users = sheetUsers.getValues();
|
||||
final Set<String> logins = users.stream().map(UserJson::getName).collect(Collectors.toSet());
|
||||
final Set<String> existsLogins = userService.existsByLogin(logins);
|
||||
final Set<User> newUsers = users.stream()
|
||||
.filter(userJson -> !existsLogins.contains(userJson.getName()))
|
||||
.map(userJson -> conversionService.convert(userJson, User.class))
|
||||
.collect(Collectors.toSet());
|
||||
if (!newUsers.isEmpty()) {
|
||||
userService.addAll(newUsers);
|
||||
}
|
||||
if (sheetUsers.getNextPageStart() != null) {
|
||||
sheetJson = Utils.urlToJson(URL + sheetUsers.getNextPageStart(), bitbucketConfig.getToken(), UserSheetJson.class);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
package com.tsc.bitbucketbot.scheduler;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.PullRequestJson;
|
||||
import com.tsc.bitbucketbot.bitbucket.UserDecisionJson;
|
||||
import com.tsc.bitbucketbot.bitbucket.UserPullRequestStatus;
|
||||
import com.tsc.bitbucketbot.bitbucket.sheet.PullRequestSheetJson;
|
||||
import com.tsc.bitbucketbot.config.BitbucketConfig;
|
||||
import com.tsc.bitbucketbot.domain.ReviewerStatus;
|
||||
import com.tsc.bitbucketbot.domain.entity.PullRequest;
|
||||
import com.tsc.bitbucketbot.domain.entity.Reviewer;
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import com.tsc.bitbucketbot.service.PullRequestsService;
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import com.tsc.bitbucketbot.service.Utils;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.sadtech.social.core.domain.BoxAnswer;
|
||||
import org.sadtech.social.core.service.sender.Sending;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SchedulerPullRequest {
|
||||
|
||||
private static final String URL = "http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=50&state=OPEN";
|
||||
private final BitbucketConfig bitbucketConfig;
|
||||
private final PullRequestsService pullRequestsService;
|
||||
private final UserService userService;
|
||||
private final ConversionService conversionService;
|
||||
private final Sending sending;
|
||||
|
||||
@Scheduled(fixedRate = 15000)
|
||||
public void checkNewPullRequest() {
|
||||
final List<User> users = userService.getAllRegistered();
|
||||
for (User user : users) {
|
||||
Optional<PullRequestSheetJson> sheetJson = Utils.urlToJson(URL, user.getToken(), PullRequestSheetJson.class);
|
||||
while (sheetJson.isPresent() && sheetJson.get().getValues() != null && !sheetJson.get().getValues().isEmpty()) {
|
||||
final PullRequestSheetJson pullRequestBitbucketSheet = sheetJson.get();
|
||||
final Set<Long> pullRequestBitbucketId = pullRequestBitbucketSheet.getValues().stream()
|
||||
.map(PullRequestJson::getId)
|
||||
.collect(Collectors.toSet());
|
||||
Set<Long> existsId = pullRequestsService.existsAllById(pullRequestBitbucketId);
|
||||
final Set<PullRequestJson> newPullRequestBitbucket = pullRequestBitbucketSheet.getValues().stream()
|
||||
.filter(pullRequestJson -> !existsId.contains(pullRequestJson.getId()))
|
||||
.collect(Collectors.toSet());
|
||||
pullRequestsService.addAll(
|
||||
newPullRequestBitbucket.stream()
|
||||
.map(pullRequestJson -> conversionService.convert(pullRequestJson, PullRequest.class))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
final List<PullRequest> newPullRequests = new ArrayList<>();
|
||||
for (PullRequestJson pullRequestJson : newPullRequestBitbucket) {
|
||||
final List<Reviewer> reviewers = pullRequestJson.getReviewers().stream()
|
||||
.map(reviewer -> testConvert(pullRequestJson, reviewer))
|
||||
.collect(Collectors.toList());
|
||||
pullRequestsService.addReviewer(pullRequestJson.getId(), reviewers).ifPresent(newPullRequests::add);
|
||||
}
|
||||
sendNotification(newPullRequests);
|
||||
if (pullRequestBitbucketSheet.getNextPageStart() != null) {
|
||||
sheetJson = Utils.urlToJson(URL + pullRequestBitbucketSheet.getNextPageStart(), bitbucketConfig.getToken(), PullRequestSheetJson.class);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Reviewer testConvert(PullRequestJson pullRequestJson, UserDecisionJson reviewer) {
|
||||
final Reviewer newReviewer = new Reviewer();
|
||||
newReviewer.setPullRequestId(pullRequestJson.getId());
|
||||
newReviewer.setUser(reviewer.getUser().getName());
|
||||
newReviewer.setStatus(convertStatusReviewer(reviewer.getStatus()));
|
||||
return newReviewer;
|
||||
}
|
||||
|
||||
private ReviewerStatus convertStatusReviewer(UserPullRequestStatus status) {
|
||||
switch (status) {
|
||||
case APPROVED:
|
||||
return ReviewerStatus.APPROVED;
|
||||
case NEEDS_WORK:
|
||||
return ReviewerStatus.UNAPPROVED;
|
||||
case UNAPPROVED:
|
||||
return ReviewerStatus.NEEDS_WORK;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendNotification(@NonNull List<PullRequest> newPullRequests) {
|
||||
if (!newPullRequests.isEmpty()) {
|
||||
Map<Long, StringBuilder> map = new HashMap<>();
|
||||
newPullRequests.forEach(
|
||||
pullRequest -> pullRequest.getReviewers().forEach(
|
||||
reviewer -> test(pullRequest, reviewer, map)
|
||||
)
|
||||
);
|
||||
map.forEach((key, value) -> sending.send(key, BoxAnswer.of(value.toString())));
|
||||
}
|
||||
}
|
||||
|
||||
private void test(PullRequest pullRequest, Reviewer reviewer, Map<Long, StringBuilder> map) {
|
||||
userService.getByLogin(reviewer.getUser()).ifPresent(
|
||||
user -> {
|
||||
final Long telegramId = user.getTelegramId();
|
||||
if (telegramId != null) {
|
||||
if (!map.containsKey(telegramId)) {
|
||||
map.put(telegramId, new StringBuilder("У вас есть новые ПР:\n\n"));
|
||||
}
|
||||
map.get(telegramId).append(pullRequest.getName()).append("\nАвтор: ").append(pullRequest.getAuthor().getName()).append("\nСсылка: ").append(pullRequest.getUrl()).append("\n-- -- -- -- --\n\n");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.tsc.bitbucketbot.service;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.PullRequest;
|
||||
import com.tsc.bitbucketbot.domain.entity.Reviewer;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
public interface PullRequestsService {
|
||||
|
||||
Set<Long> existsById(@NonNull final Set<Long> idList);
|
||||
|
||||
Set<Long> existsAllById(@NonNull Set<Long> pullRequestJsonId);
|
||||
|
||||
List<PullRequest> addAll(Set<PullRequest> pullRequests);
|
||||
|
||||
Optional<PullRequest> addReviewer(@NonNull Long pullRequestJsonId, @NonNull List<Reviewer> reviewers);
|
||||
}
|
33
src/main/java/com/tsc/bitbucketbot/service/UserService.java
Normal file
33
src/main/java/com/tsc/bitbucketbot/service/UserService.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.tsc.bitbucketbot.service;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание интерфейса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
boolean existsByTelegramId(@NonNull final Long chatId);
|
||||
|
||||
User add(@NonNull final User user);
|
||||
|
||||
List<User> getAll();
|
||||
|
||||
Optional<User> getByLogin(String login);
|
||||
|
||||
Optional<User> update(User user);
|
||||
|
||||
Set<String> existsByLogin(@NonNull Set<String> logins);
|
||||
|
||||
List<User> addAll(@NonNull Set<User> users);
|
||||
|
||||
List<User> getAllRegistered();
|
||||
|
||||
}
|
59
src/main/java/com/tsc/bitbucketbot/service/Utils.java
Normal file
59
src/main/java/com/tsc/bitbucketbot/service/Utils.java
Normal file
@ -0,0 +1,59 @@
|
||||
package com.tsc.bitbucketbot.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Optional;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Service
|
||||
public class Utils {
|
||||
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
public static <T> Optional<T> urlToJson(@NonNull String urlValue, String token, Class<T> classOfT) {
|
||||
StringBuilder sb = null;
|
||||
URL url;
|
||||
URLConnection urlCon;
|
||||
try {
|
||||
url = new URL(urlValue);
|
||||
urlCon = url.openConnection();
|
||||
if (token != null) {
|
||||
urlCon.setRequestProperty("Authorization", "Bearer " + token);
|
||||
}
|
||||
BufferedReader in;
|
||||
if (urlCon.getHeaderField("Content-Encoding") != null
|
||||
&& urlCon.getHeaderField("Content-Encoding").equals("gzip")) {
|
||||
in = new BufferedReader(new InputStreamReader(new GZIPInputStream(urlCon.getInputStream())));
|
||||
} else {
|
||||
|
||||
in = new BufferedReader(new InputStreamReader(urlCon.getInputStream()));
|
||||
}
|
||||
String inputLine;
|
||||
sb = new StringBuilder();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
sb.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
if (sb != null) {
|
||||
return Optional.of(gson.fromJson(sb.toString(), classOfT));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.tsc.bitbucketbot.service.converter;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.PullRequestJson;
|
||||
import com.tsc.bitbucketbot.bitbucket.PullRequestState;
|
||||
import com.tsc.bitbucketbot.bitbucket.UserJson;
|
||||
import com.tsc.bitbucketbot.domain.PullRequestStatus;
|
||||
import com.tsc.bitbucketbot.domain.entity.PullRequest;
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [01.02.2020]
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PullRequestJsonConverter implements Converter<PullRequestJson, PullRequest> {
|
||||
|
||||
private final UserJsonConverter userJsonConverter;
|
||||
private final UserService userService;
|
||||
|
||||
@Override
|
||||
public PullRequest convert(PullRequestJson json) {
|
||||
return PullRequest.builder()
|
||||
.id(json.getId())
|
||||
.author(this.convertUser(json.getAuthor().getUser()))
|
||||
.name(json.getTitle())
|
||||
.url(json.getLinks().getSelf().get(0).getHref())
|
||||
.status(convertPullRequestStatus(json.getState()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private User convertUser(UserJson userJson) {
|
||||
return userService.getByLogin(userJson.getName()).orElse(userJsonConverter.convert(userJson));
|
||||
}
|
||||
|
||||
private PullRequestStatus convertPullRequestStatus(PullRequestState state) {
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
return PullRequestStatus.OPEN;
|
||||
case MERGED:
|
||||
return PullRequestStatus.MERGED;
|
||||
case DECLINED:
|
||||
return PullRequestStatus.DECLINED;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// private List<Reviewer> convertReviewers(PullRequest pullRequest, List<UserDecisionJson> jsonReviewers) {
|
||||
// return jsonReviewers.stream()
|
||||
// .map(
|
||||
// jsonReviewer -> {
|
||||
// final Reviewer reviewer = new Reviewer();
|
||||
// reviewer.setReviewerKey(new ReviewerKey(convertUser(jsonReviewer.getUser()).getLogin()));
|
||||
// reviewer.setStatus(convertStatusReviewer(jsonReviewer.getStatus()));
|
||||
// return reviewer;
|
||||
// }
|
||||
// )
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.tsc.bitbucketbot.service.converter;
|
||||
|
||||
import com.tsc.bitbucketbot.bitbucket.UserJson;
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [02.02.2020]
|
||||
*/
|
||||
@Service
|
||||
public class UserJsonConverter implements Converter<UserJson, User> {
|
||||
|
||||
@Override
|
||||
public User convert(UserJson source) {
|
||||
return User.builder()
|
||||
.name(source.getDisplayName())
|
||||
.login(source.getName())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.tsc.bitbucketbot.service.impl;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.PullRequest;
|
||||
import com.tsc.bitbucketbot.domain.entity.Reviewer;
|
||||
import com.tsc.bitbucketbot.repository.PullRequestsRepository;
|
||||
import com.tsc.bitbucketbot.service.PullRequestsService;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [31.01.2020]
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PullRequestsServiceImpl implements PullRequestsService {
|
||||
|
||||
private final PullRequestsRepository pullRequestsRepository;
|
||||
|
||||
@Override
|
||||
public Set<Long> existsById(@NonNull Set<Long> idList) {
|
||||
return idList.stream()
|
||||
.filter(pullRequestsRepository::existsById)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> existsAllById(@NonNull Set<Long> pullRequestJsonId) {
|
||||
return pullRequestJsonId.stream().filter(pullRequestsRepository::existsById).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PullRequest> addAll(Set<PullRequest> pullRequests) {
|
||||
return pullRequestsRepository.saveAll(pullRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Optional<PullRequest> addReviewer(@NonNull Long pullRequestId, @NonNull List<Reviewer> reviewers) {
|
||||
final Optional<PullRequest> optPullRequest = pullRequestsRepository.findById(pullRequestId);
|
||||
if (optPullRequest.isPresent()) {
|
||||
final PullRequest pullRequest = optPullRequest.get();
|
||||
pullRequest.setReviewers(reviewers);
|
||||
return Optional.of(pullRequestsRepository.save(pullRequest));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.tsc.bitbucketbot.service.impl;
|
||||
|
||||
import com.tsc.bitbucketbot.domain.entity.User;
|
||||
import com.tsc.bitbucketbot.repository.UserRepository;
|
||||
import com.tsc.bitbucketbot.service.UserService;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [30.01.2020]
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public boolean existsByTelegramId(@NonNull Long chatId) {
|
||||
return userRepository.existsByTelegramId(chatId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User add(@NonNull User user) {
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> getAll() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> getByLogin(String login) {
|
||||
return userRepository.findById(login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> update(User user) {
|
||||
if (userRepository.existsById(user.getLogin())) {
|
||||
return Optional.of(userRepository.save(user));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> existsByLogin(@NonNull Set<String> logins) {
|
||||
return logins.stream().filter(userRepository::existsById).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> addAll(@NonNull Set<User> users) {
|
||||
return userRepository.saveAll(users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> getAllRegistered() {
|
||||
return userRepository.findAllRegistered();
|
||||
}
|
||||
|
||||
}
|
32
src/main/resources/application.yaml
Normal file
32
src/main/resources/application.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/bitbucket_bot
|
||||
username: postgres
|
||||
driver-class-name: org.postgresql.Driver
|
||||
password:
|
||||
liquibase:
|
||||
change-log: classpath:liquibase/change-log.xml
|
||||
jpa:
|
||||
show-sql: false
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
lob:
|
||||
non_contextual_creation: true
|
||||
bitbucketbot:
|
||||
panel:
|
||||
password: mnbyNie832r
|
||||
telegram:
|
||||
bot-username: bitbucket_sadtech_bot
|
||||
bot-token: 1096235968:AAHvIy_mlZJXiNc9aDQWtCuiksz9YGknoXE
|
||||
admin-chatid: 3000811
|
||||
proxy-config:
|
||||
host: 54.39.16.26
|
||||
port: 62509
|
||||
type: SOCKS5
|
||||
bitbucket:
|
||||
token: Nzg5NjUyNDQwMzk2OlA+6naQz02+GxOG0Q9li/jnsn7E
|
||||
url: http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=50
|
8
src/main/resources/liquibase/change-log.xml
Normal file
8
src/main/resources/liquibase/change-log.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
|
||||
<include file="liquibase/change-set/create-table.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
56
src/main/resources/liquibase/change-set/create-table.xml
Normal file
56
src/main/resources/liquibase/change-set/create-table.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
|
||||
<changeSet id="create-table" author="upagge">
|
||||
<createTable tableName="user">
|
||||
<column name="login" type="varchar(50)">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="name" type="varchar(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="token" type="varchar(200)"/>
|
||||
<column name="telegram_id" type="integer">
|
||||
<constraints unique="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<createTable tableName="pull_request">
|
||||
<column name="id" type="integer">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="autor_login" type="varchar(100)">
|
||||
<constraints nullable="false"
|
||||
foreignKeyName="login"
|
||||
references="user(login)"/>
|
||||
</column>
|
||||
<column name="status" type="varchar(50)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="url" type="varchar(500)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="varchar(100)"/>
|
||||
</createTable>
|
||||
|
||||
<createTable tableName="reviewer">
|
||||
<column name="id" type="integer" autoIncrement="true">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="pull_request_id" type="integer">
|
||||
<constraints nullable="false" foreignKeyName="fk_pull_request_id" references="pull_request(id)"/>
|
||||
</column>
|
||||
<column name="user_login" type="varchar(100)">
|
||||
<constraints nullable="false"
|
||||
foreignKeyName="fk_user_login"
|
||||
references="user(login)"/>
|
||||
</column>
|
||||
<column name="status" type="varchar(50)"/>
|
||||
</createTable>
|
||||
<addUniqueConstraint tableName="reviewer" columnNames="pull_request_id, user_login"/>
|
||||
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
Loading…
Reference in New Issue
Block a user