From bffc868472c8ac2c0d69326a94b185abef149932 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:07:52 +0300 Subject: [PATCH 01/34] feat: add BotClient in scrapper --- api_dto/pom.xml | 33 +++++++++++++++++ .../java/api_dto/bot}/ApiErrorResponse.java | 5 ++- .../java/api_dto/bot}/LinkUpdateRequest.java | 7 ++-- .../api_dto/scrapper}/AddLinkRequest.java | 2 +- .../api_dto/scrapper}/ApiErrorResponse.java | 5 ++- .../java/api_dto/scrapper}/LinkResponse.java | 4 +-- .../api_dto/scrapper}/ListLinksResponse.java | 4 +-- .../api_dto/scrapper}/RemoveLinkRequest.java | 2 +- bot/pom.xml | 5 +++ .../bot/api/controller/UpdateController.java | 5 ++- .../api/exception/ExceptionApiHandler.java | 25 ++++++------- .../bot/{api => }/client/AbstractClient.java | 2 +- .../bot/{api => }/client/ScrapperClient.java | 2 +- ...ClientConfig.java => BotClientConfig.java} | 4 +-- pom.xml | 1 + scrapper/pom.xml | 6 ++++ .../java/edu/java/api/client/BotClient.java | 12 ------- .../java/api/controller/ChatController.java | 2 +- .../java/api/controller/LinkController.java | 14 ++++---- .../chat/ChatExceptionApiHandler.java | 21 +++++++---- .../link/LinkExceptionApiHandler.java | 21 +++++++---- .../edu/java/client/bot/BotApiException.java | 15 ++++++++ .../java/edu/java/client/bot/BotClient.java | 35 +++++++++++++++++++ .../client/{ => sources}/GithubClient.java | 3 +- .../{ => sources}/ResponseException.java | 2 +- .../{ => sources}/StackoverflowClient.java | 3 +- .../edu/java/configuration/ClientConfig.java | 11 +++--- .../edu/java/client/GithubClientTest.java | 2 ++ .../edu/java/client/ObjectMapperTest.java | 28 +++++++++++++++ .../java/client/StackoverflowClientTest.java | 2 ++ 30 files changed, 202 insertions(+), 81 deletions(-) create mode 100644 api_dto/pom.xml rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/bot}/ApiErrorResponse.java (79%) rename {bot/src/main/java/edu/java/bot/api/dto => api_dto/src/main/java/edu/java/api_dto/bot}/LinkUpdateRequest.java (78%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/AddLinkRequest.java (86%) rename {bot/src/main/java/edu/java/bot/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/ApiErrorResponse.java (78%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/LinkResponse.java (81%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/ListLinksResponse.java (76%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/RemoveLinkRequest.java (86%) rename bot/src/main/java/edu/java/bot/{api => }/client/AbstractClient.java (92%) rename bot/src/main/java/edu/java/bot/{api => }/client/ScrapperClient.java (88%) rename bot/src/main/java/edu/java/bot/configuration/{ClientConfig.java => BotClientConfig.java} (89%) delete mode 100644 scrapper/src/main/java/edu/java/api/client/BotClient.java create mode 100644 scrapper/src/main/java/edu/java/client/bot/BotApiException.java create mode 100644 scrapper/src/main/java/edu/java/client/bot/BotClient.java rename scrapper/src/main/java/edu/java/client/{ => sources}/GithubClient.java (94%) rename scrapper/src/main/java/edu/java/client/{ => sources}/ResponseException.java (62%) rename scrapper/src/main/java/edu/java/client/{ => sources}/StackoverflowClient.java (95%) create mode 100644 scrapper/src/test/java/edu/java/client/ObjectMapperTest.java diff --git a/api_dto/pom.xml b/api_dto/pom.xml new file mode 100644 index 0000000..25f8f90 --- /dev/null +++ b/api_dto/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + edu.java + root + ${revision} + + + api_dto + ${revision} + + + + com.fasterxml.jackson.core + jackson-databind + 2.15.3 + + + org.springframework.boot + spring-boot-starter-validation + + + + + 21 + 21 + UTF-8 + + + diff --git a/scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java b/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java similarity index 79% rename from scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java rename to api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java index e04ccab..943c66b 100644 --- a/scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -8,7 +8,6 @@ public record ApiErrorResponse( String code, String exceptionName, String exceptionMessage, - - StackTraceElement[] stacktrace + String[] stacktrace ) { } diff --git a/bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java similarity index 78% rename from bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java rename to api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java index 3598f86..8d2c6b6 100644 --- a/bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java @@ -1,14 +1,15 @@ -package edu.java.bot.api.dto; +package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkUpdateRequest( - long id, + Long id, @URL String url, String description, - long[] tgChatIds + Long[] tgChatIds ) { } + diff --git a/scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java similarity index 86% rename from scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java index 35e5038..2399b04 100644 --- a/scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java similarity index 78% rename from bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java index 364072c..45c7228 100644 --- a/bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -8,7 +8,6 @@ public record ApiErrorResponse( String code, String exceptionName, String exceptionMessage, - - StackTraceElement[] stacktrace + String[] stacktrace ) { } diff --git a/scrapper/src/main/java/edu/java/api/dto/LinkResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java similarity index 81% rename from scrapper/src/main/java/edu/java/api/dto/LinkResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java index ce13424..bd2d1f5 100644 --- a/scrapper/src/main/java/edu/java/api/dto/LinkResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java @@ -1,11 +1,11 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkResponse( - long id, + Long id, @URL String url ) { diff --git a/scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java similarity index 76% rename from scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java index a6707c5..5ff4bda 100644 --- a/scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java @@ -1,10 +1,10 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public record ListLinksResponse( LinkResponse[] links, - int size + Integer size ) { } diff --git a/scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java similarity index 86% rename from scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java index 318f8f2..049848a 100644 --- a/scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/bot/pom.xml b/bot/pom.xml index ed1d026..e1391fc 100644 --- a/bot/pom.xml +++ b/bot/pom.xml @@ -128,6 +128,11 @@ kafka test + + edu.java + api_dto + 0.1 + diff --git a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java index f30e7ea..92fbab4 100644 --- a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java +++ b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java @@ -1,7 +1,7 @@ package edu.java.bot.api.controller; -import edu.java.bot.api.dto.ApiErrorResponse; -import edu.java.bot.api.dto.LinkUpdateRequest; +import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.api_dto.bot.LinkUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -29,5 +29,4 @@ public class UpdateController { public ResponseEntity sendUpdate(@Valid @RequestBody LinkUpdateRequest request) { return ResponseEntity.ok().build(); } - } diff --git a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java index 31c0eeb..c75a289 100644 --- a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java +++ b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java @@ -1,13 +1,13 @@ package edu.java.bot.api.exception; -import edu.java.bot.api.dto.ApiErrorResponse; +import edu.java.api_dto.bot.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -@RestControllerAdvice -public class ExceptionApiHandler { +@RestControllerAdvice public class ExceptionApiHandler { @ExceptionHandler(ChatNotExistException.class) public ResponseEntity chatNotExistException(ChatNotExistException exception) { @@ -16,24 +16,19 @@ public ResponseEntity chatNotExistException(ChatNotExistExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toArray(String[]::new) ); - return ResponseEntity - .status(HttpStatus.NOT_FOUND) - .body(error); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); } - @ExceptionHandler(Exception.class) - public ResponseEntity anyException(Exception exception) { + @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toArray(String[]::new) ); - return ResponseEntity - .status(HttpStatus.BAD_REQUEST) - .body(error); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); } } diff --git a/bot/src/main/java/edu/java/bot/api/client/AbstractClient.java b/bot/src/main/java/edu/java/bot/client/AbstractClient.java similarity index 92% rename from bot/src/main/java/edu/java/bot/api/client/AbstractClient.java rename to bot/src/main/java/edu/java/bot/client/AbstractClient.java index 5ebef97..1c43082 100644 --- a/bot/src/main/java/edu/java/bot/api/client/AbstractClient.java +++ b/bot/src/main/java/edu/java/bot/client/AbstractClient.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.client; +package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java similarity index 88% rename from bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java rename to bot/src/main/java/edu/java/bot/client/ScrapperClient.java index d6dbbec..e815705 100644 --- a/bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.client; +package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java b/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java similarity index 89% rename from bot/src/main/java/edu/java/bot/configuration/ClientConfig.java rename to bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java index ccb6a51..9771a8a 100644 --- a/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java @@ -1,7 +1,7 @@ package edu.java.bot.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.bot.api.client.ScrapperClient; +import edu.java.bot.client.ScrapperClient; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -9,7 +9,7 @@ @Configuration @RequiredArgsConstructor -public class ClientConfig { +public class BotClientConfig { @Value("${resources.base-url.scrapper}") private String scrapperUrl; private final ObjectMapper objectMapper; diff --git a/pom.xml b/pom.xml index e813daf..88935b8 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ bot scrapper + api_dto diff --git a/scrapper/pom.xml b/scrapper/pom.xml index c3f876f..741d2ea 100644 --- a/scrapper/pom.xml +++ b/scrapper/pom.xml @@ -127,6 +127,12 @@ kafka test + + edu.java + api_dto + 0.1 + compile + diff --git a/scrapper/src/main/java/edu/java/api/client/BotClient.java b/scrapper/src/main/java/edu/java/api/client/BotClient.java deleted file mode 100644 index 023466f..0000000 --- a/scrapper/src/main/java/edu/java/api/client/BotClient.java +++ /dev/null @@ -1,12 +0,0 @@ -package edu.java.api.client; - -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import lombok.NonNull; - -public class BotClient extends AbstractClient { - - public BotClient(@NonNull String baseUrl, ObjectMapper mapper) { - super(baseUrl, mapper); - } -} diff --git a/scrapper/src/main/java/edu/java/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/api/controller/ChatController.java index 92849c1..6af0583 100644 --- a/scrapper/src/main/java/edu/java/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/api/controller/ChatController.java @@ -1,6 +1,6 @@ package edu.java.api.controller; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/scrapper/src/main/java/edu/java/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/api/controller/LinkController.java index 5829aed..c349e7e 100644 --- a/scrapper/src/main/java/edu/java/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/api/controller/LinkController.java @@ -1,10 +1,10 @@ package edu.java.api.controller; -import edu.java.api.dto.AddLinkRequest; -import edu.java.api.dto.ApiErrorResponse; -import edu.java.api.dto.LinkResponse; -import edu.java.api.dto.ListLinksResponse; -import edu.java.api.dto.RemoveLinkRequest; +import edu.java.api_dto.scrapper.AddLinkRequest; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.api_dto.scrapper.LinkResponse; +import edu.java.api_dto.scrapper.ListLinksResponse; +import edu.java.api_dto.scrapper.RemoveLinkRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -59,7 +59,7 @@ public ResponseEntity addLink( TODO: добавление ссылки может быть брошено LinkAdditionException */ - return ResponseEntity.ok(new LinkResponse(0, "")); + return ResponseEntity.ok(new LinkResponse(0L, "")); } @Operation(summary = "Убрать отслеживание ссылки") @@ -83,6 +83,6 @@ public ResponseEntity deleteLink( TODO: удаление ссылки может быть брошено LinkNotFoundException */ - return ResponseEntity.ok(new LinkResponse(0, "")); + return ResponseEntity.ok(new LinkResponse(0L, "")); } } diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java index 4483f07..cc5bcda 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java @@ -1,6 +1,7 @@ package edu.java.api.exception.chat; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -16,7 +17,9 @@ public ResponseEntity chatRegistrationException(ChatRegistrati HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.BAD_REQUEST) @@ -30,7 +33,9 @@ public ResponseEntity chatNotFoundException(ChatNotFoundExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.NOT_FOUND) @@ -40,14 +45,16 @@ public ResponseEntity chatNotFoundException(ChatNotFoundExcept @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity - .status(HttpStatus.BAD_REQUEST) + .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(error); } } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java index 7be1029..2fffd1b 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java @@ -1,6 +1,7 @@ package edu.java.api.exception.link; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -16,7 +17,9 @@ public ResponseEntity linkAdditionException(LinkAdditionExcept HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.BAD_REQUEST) @@ -30,7 +33,9 @@ public ResponseEntity linkNotFoundException(LinkNotFoundExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.NOT_FOUND) @@ -40,14 +45,16 @@ public ResponseEntity linkNotFoundException(LinkNotFoundExcept @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity - .status(HttpStatus.BAD_REQUEST) + .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(error); } } diff --git a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/client/bot/BotApiException.java new file mode 100644 index 0000000..0c892a8 --- /dev/null +++ b/scrapper/src/main/java/edu/java/client/bot/BotApiException.java @@ -0,0 +1,15 @@ +package edu.java.client.bot; + +import edu.java.api_dto.bot.ApiErrorResponse; +import lombok.Getter; + +@Getter +public class BotApiException extends Exception { + private final ApiErrorResponse error; + + public BotApiException(ApiErrorResponse error) { + super("%s: %s. %s - %s\n%s".formatted(error.code(), error.description(), + error.exceptionName(), error.exceptionMessage(), String.join("\n", error.stacktrace()))); + this.error = error; + } +} diff --git a/scrapper/src/main/java/edu/java/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/client/bot/BotClient.java new file mode 100644 index 0000000..119f896 --- /dev/null +++ b/scrapper/src/main/java/edu/java/client/bot/BotClient.java @@ -0,0 +1,35 @@ +package edu.java.client.bot; + +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.client.AbstractClient; +import lombok.NonNull; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ClientResponse; +import reactor.core.publisher.Mono; + +public class BotClient extends AbstractClient { + + public BotClient(@NonNull String baseUrl, ObjectMapper mapper) { + super(baseUrl, mapper); + } + + public void sendUpdate(LinkUpdateRequest request) { + client.post() + .uri("/update") + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), LinkUpdateRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + private Mono getException(ClientResponse response) { + return response + .bodyToMono(ApiErrorResponse.class) + .map(BotApiException::new); + } +} diff --git a/scrapper/src/main/java/edu/java/client/GithubClient.java b/scrapper/src/main/java/edu/java/client/sources/GithubClient.java similarity index 94% rename from scrapper/src/main/java/edu/java/client/GithubClient.java rename to scrapper/src/main/java/edu/java/client/sources/GithubClient.java index 007f4cf..3f8995b 100644 --- a/scrapper/src/main/java/edu/java/client/GithubClient.java +++ b/scrapper/src/main/java/edu/java/client/sources/GithubClient.java @@ -1,8 +1,9 @@ -package edu.java.client; +package edu.java.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.client.AbstractClient; import edu.java.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; diff --git a/scrapper/src/main/java/edu/java/client/ResponseException.java b/scrapper/src/main/java/edu/java/client/sources/ResponseException.java similarity index 62% rename from scrapper/src/main/java/edu/java/client/ResponseException.java rename to scrapper/src/main/java/edu/java/client/sources/ResponseException.java index c72808b..498ce2a 100644 --- a/scrapper/src/main/java/edu/java/client/ResponseException.java +++ b/scrapper/src/main/java/edu/java/client/sources/ResponseException.java @@ -1,4 +1,4 @@ -package edu.java.client; +package edu.java.client.sources; public class ResponseException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/StackoverflowClient.java b/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java similarity index 95% rename from scrapper/src/main/java/edu/java/client/StackoverflowClient.java rename to scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java index f9afbe5..c23d881 100644 --- a/scrapper/src/main/java/edu/java/client/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java @@ -1,8 +1,9 @@ -package edu.java.client; +package edu.java.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.client.AbstractClient; import edu.java.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; diff --git a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java b/scrapper/src/main/java/edu/java/configuration/ClientConfig.java index 7d36ea2..275b10e 100644 --- a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java +++ b/scrapper/src/main/java/edu/java/configuration/ClientConfig.java @@ -1,9 +1,9 @@ package edu.java.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api.client.BotClient; -import edu.java.client.GithubClient; -import edu.java.client.StackoverflowClient; +import edu.java.client.bot.BotClient; +import edu.java.client.sources.GithubClient; +import edu.java.client.sources.StackoverflowClient; import lombok.RequiredArgsConstructor; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Value; @@ -41,9 +41,6 @@ public StackoverflowClient stackoverflowClient() { @Bean public BotClient botClient() { - return new BotClient( - botUrl, - objectMapper - ); + return new BotClient(botUrl, objectMapper); } } diff --git a/scrapper/src/test/java/edu/java/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/client/GithubClientTest.java index ded166b..fc12e2a 100644 --- a/scrapper/src/test/java/edu/java/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/client/GithubClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; +import edu.java.client.sources.GithubClient; +import edu.java.client.sources.ResponseException; import edu.java.configuration.ObjectMapperConfig; import edu.java.dto.GithubResponse; import java.util.List; diff --git a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java new file mode 100644 index 0000000..1de6bf1 --- /dev/null +++ b/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java @@ -0,0 +1,28 @@ +package edu.java.client; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.configuration.ObjectMapperConfig; +import edu.java.dto.GithubResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.time.OffsetDateTime; + +public class ObjectMapperTest { + + private final ObjectMapper mapper; + + public ObjectMapperTest() { + this.mapper = new ObjectMapperConfig().objectMapper(); + } + + @Test + void objectMapperTest() throws JsonProcessingException { + GithubResponse object = new GithubResponse(0L, "example", + new GithubResponse.Actor("cyberpanncake"), + new GithubResponse.Repository("Torzhkova-Tinkoff-JavaBackendCourse-Spring"), + OffsetDateTime.now()); + String json = mapper.writeValueAsString(object); + Assertions.assertTrue(json.contains("created_at")); + } +} diff --git a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java index 95e2757..3c4fd9b 100644 --- a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; +import edu.java.client.sources.ResponseException; +import edu.java.client.sources.StackoverflowClient; import edu.java.configuration.ObjectMapperConfig; import edu.java.dto.StackoverflowResponse; import java.util.Map; From 94053cc0b7ce812b4e4312be2bd493aeaf574de1 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:13:35 +0300 Subject: [PATCH 02/34] fix: rename class and move some classes in new directory --- .../{BotClientConfig.java => ClientConfig.java} | 2 +- .../edu/java/{ => scrapper}/ScrapperApplication.java | 4 ++-- .../{ => scrapper}/api/controller/ChatController.java | 2 +- .../{ => scrapper}/api/controller/LinkController.java | 2 +- .../api/exception/chat/ChatExceptionApiHandler.java | 2 +- .../api/exception/chat/ChatNotFoundException.java | 2 +- .../api/exception/chat/ChatRegistrationException.java | 2 +- .../api/exception/link/LinkAdditionException.java | 2 +- .../api/exception/link/LinkExceptionApiHandler.java | 2 +- .../api/exception/link/LinkNotFoundException.java | 2 +- .../edu/java/{ => scrapper}/client/AbstractClient.java | 2 +- .../{ => scrapper}/client/bot/BotApiException.java | 2 +- .../edu/java/{ => scrapper}/client/bot/BotClient.java | 4 ++-- .../{ => scrapper}/client/sources/GithubClient.java | 6 +++--- .../client/sources/ResponseException.java | 2 +- .../client/sources/StackoverflowClient.java | 6 +++--- .../configuration/ApplicationConfig.java | 2 +- .../{ => scrapper}/configuration/ClientConfig.java | 8 ++++---- .../configuration/ObjectMapperConfig.java | 2 +- .../edu/java/{ => scrapper}/dto/GithubResponse.java | 2 +- .../java/{ => scrapper}/dto/StackoverflowResponse.java | 2 +- .../{ => scrapper}/shedule/LinkUpdaterScheduler.java | 2 +- .../java/{ => scrapper}/client/GithubClientTest.java | 10 +++++----- .../java/{ => scrapper}/client/ObjectMapperTest.java | 6 +++--- .../{ => scrapper}/client/StackoverflowClientTest.java | 10 +++++----- 25 files changed, 44 insertions(+), 44 deletions(-) rename bot/src/main/java/edu/java/bot/configuration/{BotClientConfig.java => ClientConfig.java} (95%) rename scrapper/src/main/java/edu/java/{ => scrapper}/ScrapperApplication.java (85%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/controller/ChatController.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/controller/LinkController.java (99%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatExceptionApiHandler.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatNotFoundException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatRegistrationException.java (57%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkAdditionException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkExceptionApiHandler.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkNotFoundException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/AbstractClient.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/bot/BotApiException.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/bot/BotClient.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/GithubClient.java (90%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/ResponseException.java (56%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/StackoverflowClient.java (90%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ApplicationConfig.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ClientConfig.java (87%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ObjectMapperConfig.java (94%) rename scrapper/src/main/java/edu/java/{ => scrapper}/dto/GithubResponse.java (94%) rename scrapper/src/main/java/edu/java/{ => scrapper}/dto/StackoverflowResponse.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/shedule/LinkUpdaterScheduler.java (93%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/GithubClientTest.java (94%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/ObjectMapperTest.java (85%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/StackoverflowClientTest.java (94%) diff --git a/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java b/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java similarity index 95% rename from bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java rename to bot/src/main/java/edu/java/bot/configuration/ClientConfig.java index 9771a8a..0f74021 100644 --- a/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java @@ -9,7 +9,7 @@ @Configuration @RequiredArgsConstructor -public class BotClientConfig { +public class ClientConfig { @Value("${resources.base-url.scrapper}") private String scrapperUrl; private final ObjectMapper objectMapper; diff --git a/scrapper/src/main/java/edu/java/ScrapperApplication.java b/scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java similarity index 85% rename from scrapper/src/main/java/edu/java/ScrapperApplication.java rename to scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java index fadceb1..22cb3aa 100644 --- a/scrapper/src/main/java/edu/java/ScrapperApplication.java +++ b/scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java @@ -1,6 +1,6 @@ -package edu.java; +package edu.java.scrapper; -import edu.java.configuration.ApplicationConfig; +import edu.java.scrapper.configuration.ApplicationConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/scrapper/src/main/java/edu/java/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/controller/ChatController.java rename to scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index 6af0583..f1696a2 100644 --- a/scrapper/src/main/java/edu/java/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,4 +1,4 @@ -package edu.java.api.controller; +package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.ApiErrorResponse; import io.swagger.v3.oas.annotations.Operation; diff --git a/scrapper/src/main/java/edu/java/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java similarity index 99% rename from scrapper/src/main/java/edu/java/api/controller/LinkController.java rename to scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index c349e7e..f72fdb9 100644 --- a/scrapper/src/main/java/edu/java/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -1,4 +1,4 @@ -package edu.java.api.controller; +package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.AddLinkRequest; import edu.java.api_dto.scrapper.ApiErrorResponse; diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index cc5bcda..c8344dd 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; import edu.java.api_dto.scrapper.ApiErrorResponse; import java.util.Arrays; diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java index 35cf0c7..647066d 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; public class ChatNotFoundException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java similarity index 57% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java index d804ca0..eba10b2 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; public class ChatRegistrationException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java index f5c22de..dbe67a6 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; public class LinkAdditionException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java index 2fffd1b..3392519 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; import edu.java.api_dto.scrapper.ApiErrorResponse; import java.util.Arrays; diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java index 879f43e..655dc36 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; public class LinkNotFoundException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/AbstractClient.java b/scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/AbstractClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java index 195245b..e73da2f 100644 --- a/scrapper/src/main/java/edu/java/client/AbstractClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java @@ -1,4 +1,4 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/bot/BotApiException.java rename to scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java index 0c892a8..3e78df3 100644 --- a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java @@ -1,4 +1,4 @@ -package edu.java.client.bot; +package edu.java.scrapper.client.bot; import edu.java.api_dto.bot.ApiErrorResponse; import lombok.Getter; diff --git a/scrapper/src/main/java/edu/java/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/bot/BotClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java index 119f896..4ea3155 100644 --- a/scrapper/src/main/java/edu/java/client/bot/BotClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java @@ -1,9 +1,9 @@ -package edu.java.client.bot; +package edu.java.scrapper.client.bot; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.api_dto.bot.ApiErrorResponse; import edu.java.api_dto.bot.LinkUpdateRequest; -import edu.java.client.AbstractClient; +import edu.java.scrapper.client.AbstractClient; import lombok.NonNull; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; diff --git a/scrapper/src/main/java/edu/java/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java similarity index 90% rename from scrapper/src/main/java/edu/java/client/sources/GithubClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index 3f8995b..a5ad13b 100644 --- a/scrapper/src/main/java/edu/java/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -1,10 +1,10 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.client.AbstractClient; +import edu.java.scrapper.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/client/sources/ResponseException.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java similarity index 56% rename from scrapper/src/main/java/edu/java/client/sources/ResponseException.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java index 498ce2a..c28d33c 100644 --- a/scrapper/src/main/java/edu/java/client/sources/ResponseException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java @@ -1,4 +1,4 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; public class ResponseException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java similarity index 90% rename from scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java index c23d881..c5739f3 100644 --- a/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java @@ -1,10 +1,10 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import edu.java.dto.StackoverflowResponse; +import edu.java.scrapper.client.AbstractClient; +import edu.java.scrapper.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java similarity index 92% rename from scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java index 1760267..7574e4e 100644 --- a/scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java @@ -1,4 +1,4 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import jakarta.validation.constraints.NotNull; import java.time.Duration; diff --git a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java similarity index 87% rename from scrapper/src/main/java/edu/java/configuration/ClientConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java index 275b10e..63595c0 100644 --- a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java @@ -1,9 +1,9 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.bot.BotClient; -import edu.java.client.sources.GithubClient; -import edu.java.client.sources.StackoverflowClient; +import edu.java.scrapper.client.bot.BotClient; +import edu.java.scrapper.client.sources.GithubClient; +import edu.java.scrapper.client.sources.StackoverflowClient; import lombok.RequiredArgsConstructor; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Value; diff --git a/scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java similarity index 94% rename from scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java index 6d2f3be..daac430 100644 --- a/scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java @@ -1,4 +1,4 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/scrapper/src/main/java/edu/java/dto/GithubResponse.java b/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java similarity index 94% rename from scrapper/src/main/java/edu/java/dto/GithubResponse.java rename to scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java index b122ce0..a6e0ee7 100644 --- a/scrapper/src/main/java/edu/java/dto/GithubResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java @@ -1,4 +1,4 @@ -package edu.java.dto; +package edu.java.scrapper.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java b/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java similarity index 92% rename from scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java rename to scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java index 4a0a8d0..15fceb9 100644 --- a/scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java @@ -1,4 +1,4 @@ -package edu.java.dto; +package edu.java.scrapper.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java similarity index 93% rename from scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java rename to scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java index b04b193..a7e2a78 100644 --- a/scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java @@ -1,4 +1,4 @@ -package edu.java.shedule; +package edu.java.scrapper.shedule; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/scrapper/src/test/java/edu/java/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java similarity index 94% rename from scrapper/src/test/java/edu/java/client/GithubClientTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java index fc12e2a..ea5a5c4 100644 --- a/scrapper/src/test/java/edu/java/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java @@ -1,12 +1,12 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; -import edu.java.client.sources.GithubClient; -import edu.java.client.sources.ResponseException; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.client.sources.GithubClient; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.GithubResponse; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java similarity index 85% rename from scrapper/src/test/java/edu/java/client/ObjectMapperTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java index 1de6bf1..741ca3d 100644 --- a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java @@ -1,9 +1,9 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.GithubResponse; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java similarity index 94% rename from scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java index 3c4fd9b..a2a5d80 100644 --- a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java @@ -1,12 +1,12 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; -import edu.java.client.sources.ResponseException; -import edu.java.client.sources.StackoverflowClient; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.StackoverflowClient; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.StackoverflowResponse; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.AfterEach; From db1b677c6acd25693ae7303ef1be7692e4e0d048 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:46:29 +0300 Subject: [PATCH 03/34] feat: add ScrapperClient in bot --- .../java/bot/client/ScrapperApiException.java | 15 ++++ .../edu/java/bot/client/ScrapperClient.java | 77 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 bot/src/main/java/edu/java/bot/client/ScrapperApiException.java diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java new file mode 100644 index 0000000..1fa2b6c --- /dev/null +++ b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java @@ -0,0 +1,15 @@ +package edu.java.bot.client; + +import edu.java.api_dto.scrapper.ApiErrorResponse; +import lombok.Getter; + +@Getter +public class ScrapperApiException extends Exception { + private final ApiErrorResponse error; + + public ScrapperApiException(ApiErrorResponse error) { + super("%s: %s. %s - %s\n%s".formatted(error.code(), error.description(), + error.exceptionName(), error.exceptionMessage(), String.join("\n", error.stacktrace()))); + this.error = error; + } +} diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java index e815705..577ca9c 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,10 +1,87 @@ package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.api_dto.scrapper.AddLinkRequest; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.api_dto.scrapper.LinkResponse; +import edu.java.api_dto.scrapper.ListLinksResponse; +import edu.java.api_dto.scrapper.RemoveLinkRequest; import lombok.NonNull; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ClientResponse; +import reactor.core.publisher.Mono; public class ScrapperClient extends AbstractClient { + private static final String CHAT_BASE_URL = "/tg-chat"; + private static final String LINK_BASE_URL = "/links"; + private static final String ID_PATH = "/{id}"; + private static final String CHAT_HEADER = "Tg-Chat-Id"; + public ScrapperClient(@NonNull String baseUrl, ObjectMapper mapper) { super(baseUrl, mapper); } + + public void registerChat(long id) { + client.post() + .uri(uriBuilder -> uriBuilder + .path(CHAT_BASE_URL + ID_PATH) + .build(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + public void deleteChat(long id) { + client.delete() + .uri(uriBuilder -> uriBuilder + .path(CHAT_BASE_URL + ID_PATH) + .build(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + public ListLinksResponse getLinks(long id) { + return client.get() + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(ListLinksResponse.class) + .block(); + } + + public LinkResponse addLink(long id, AddLinkRequest request) { + return client.post() + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), AddLinkRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(LinkResponse.class) + .block(); + } + + public LinkResponse deleteLink(long id, RemoveLinkRequest request) { + return client.method(HttpMethod.DELETE) + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), RemoveLinkRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(LinkResponse.class) + .block(); + } + + private Mono getException(ClientResponse response) { + return response + .bodyToMono(ApiErrorResponse.class) + .map(ScrapperApiException::new); + } } From 45c978fe69c0719cb587a867a783e4c61b825995 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:58:04 +0300 Subject: [PATCH 04/34] fix: change url type in api dto from String to URI --- .../java/edu/java/api_dto/bot/LinkUpdateRequest.java | 5 ++--- .../java/edu/java/api_dto/scrapper/LinkResponse.java | 5 ++--- .../java/scrapper/api/controller/LinkController.java | 10 ++++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java index 8d2c6b6..bd2d278 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java @@ -1,13 +1,12 @@ package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.hibernate.validator.constraints.URL; +import java.net.URI; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkUpdateRequest( Long id, - @URL - String url, + URI url, String description, Long[] tgChatIds ) { diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java index bd2d1f5..91ca8c0 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java @@ -1,12 +1,11 @@ package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.hibernate.validator.constraints.URL; +import java.net.URI; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkResponse( Long id, - @URL - String url + URI url ) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index f72fdb9..080211b 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -11,6 +11,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; +import java.net.URI; +import java.net.URISyntaxException; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -54,12 +56,12 @@ public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat public ResponseEntity addLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody AddLinkRequest request - ) { + ) throws URISyntaxException { /* TODO: добавление ссылки может быть брошено LinkAdditionException */ - return ResponseEntity.ok(new LinkResponse(0L, "")); + return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); } @Operation(summary = "Убрать отслеживание ссылки") @@ -78,11 +80,11 @@ public ResponseEntity addLink( public ResponseEntity deleteLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody RemoveLinkRequest request - ) { + ) throws URISyntaxException { /* TODO: удаление ссылки может быть брошено LinkNotFoundException */ - return ResponseEntity.ok(new LinkResponse(0L, "")); + return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); } } From 0773cc6f5bdf34012be4ac618ac0f7bc6f55b7b0 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 14:16:34 +0300 Subject: [PATCH 05/34] fix: restructuring packages --- .../{ => client}/service/ScrapperService.java | 2 +- .../java/edu/java/bot/command/Command.java | 16 ------------- .../bot/configuration/TelegramBotConfig.java | 4 ++-- .../TgBotController.java} | 10 ++++---- .../command/AbstractCommand.java | 14 +++++------ .../command/AbstractServiceCommand.java | 4 ++-- .../java/bot/telegram/command/Command.java | 16 +++++++++++++ .../{ => telegram}/command/CommandUtils.java | 8 +++---- .../command/components/HelpCommand.java | 10 ++++---- .../command/components/ListCommand.java | 17 ++++++------- .../command/components/StartCommand.java | 10 ++++---- .../command/components/TrackCommand.java | 16 ++++++------- .../command/components/UntrackCommand.java | 16 ++++++------- .../exception/UnregisteredUserException.java | 2 +- .../exception/command/CommandException.java | 2 +- .../command/CommandNotExistException.java | 2 +- .../command/NotCommandException.java | 2 +- .../exception/link/LinkException.java | 2 +- .../link/LinkRegistrationException.java | 2 +- .../exception/link/NotLinkException.java | 2 +- .../parameter/ParameterException.java | 2 +- .../WrongNumberParametersException.java | 2 +- .../main/java/edu/java/bot/utils/Link.java | 2 +- .../java/edu/java/bot/BotApplicationTest.java | 24 +++++++++---------- .../edu/java/bot/TestScrapperService.java | 2 +- .../scrapper/client/sources/GithubClient.java | 2 +- .../client/sources/StackoverflowClient.java | 2 +- .../sources}/dto/GithubResponse.java | 2 +- .../sources}/dto/StackoverflowResponse.java | 2 +- .../scrapper/client/GithubClientTest.java | 2 +- .../scrapper/client/ObjectMapperTest.java | 2 +- .../client/StackoverflowClientTest.java | 2 +- 32 files changed, 102 insertions(+), 101 deletions(-) rename bot/src/main/java/edu/java/bot/{ => client}/service/ScrapperService.java (98%) delete mode 100644 bot/src/main/java/edu/java/bot/command/Command.java rename bot/src/main/java/edu/java/bot/{controller/Controller.java => telegram/TgBotController.java} (89%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/AbstractCommand.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/AbstractServiceCommand.java (77%) create mode 100644 bot/src/main/java/edu/java/bot/telegram/command/Command.java rename bot/src/main/java/edu/java/bot/{ => telegram}/command/CommandUtils.java (72%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/HelpCommand.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/ListCommand.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/StartCommand.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/TrackCommand.java (70%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/UntrackCommand.java (70%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/UnregisteredUserException.java (84%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/CommandException.java (73%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/CommandNotExistException.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/NotCommandException.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/LinkException.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/LinkRegistrationException.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/NotLinkException.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/parameter/ParameterException.java (73%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/parameter/WrongNumberParametersException.java (76%) rename scrapper/src/main/java/edu/java/scrapper/{ => client/sources}/dto/GithubResponse.java (91%) rename scrapper/src/main/java/edu/java/scrapper/{ => client/sources}/dto/StackoverflowResponse.java (89%) diff --git a/bot/src/main/java/edu/java/bot/service/ScrapperService.java b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java similarity index 98% rename from bot/src/main/java/edu/java/bot/service/ScrapperService.java rename to bot/src/main/java/edu/java/bot/client/service/ScrapperService.java index 1deaa2f..f3d8c22 100644 --- a/bot/src/main/java/edu/java/bot/service/ScrapperService.java +++ b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java @@ -1,4 +1,4 @@ -package edu.java.bot.service; +package edu.java.bot.client.service; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/bot/src/main/java/edu/java/bot/command/Command.java b/bot/src/main/java/edu/java/bot/command/Command.java deleted file mode 100644 index 807b41a..0000000 --- a/bot/src/main/java/edu/java/bot/command/Command.java +++ /dev/null @@ -1,16 +0,0 @@ -package edu.java.bot.command; - -import com.pengrad.telegrambot.model.Update; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.parameter.ParameterException; - -public interface Command { - - String getName(); - - String getDescription(); - - String execute(Update update) throws UnregisteredUserException, ParameterException, CommandException, LinkException; -} diff --git a/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java b/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java index c4e25ce..51f91c5 100644 --- a/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java @@ -3,8 +3,8 @@ import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.model.BotCommand; import com.pengrad.telegrambot.request.SetMyCommands; -import edu.java.bot.command.Command; -import edu.java.bot.command.components.HelpCommand; +import edu.java.bot.telegram.command.Command; +import edu.java.bot.telegram.command.components.HelpCommand; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; diff --git a/bot/src/main/java/edu/java/bot/controller/Controller.java b/bot/src/main/java/edu/java/bot/telegram/TgBotController.java similarity index 89% rename from bot/src/main/java/edu/java/bot/controller/Controller.java rename to bot/src/main/java/edu/java/bot/telegram/TgBotController.java index d9a1c1d..8b1753a 100644 --- a/bot/src/main/java/edu/java/bot/controller/Controller.java +++ b/bot/src/main/java/edu/java/bot/telegram/TgBotController.java @@ -1,4 +1,4 @@ -package edu.java.bot.controller; +package edu.java.bot.telegram; import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.TelegramException; @@ -6,10 +6,10 @@ import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.response.SendResponse; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.Command; import edu.java.bot.configuration.ApplicationConfig; import edu.java.bot.configuration.TelegramBotConfig; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.Command; import java.time.LocalDateTime; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -18,12 +18,12 @@ @Component @Slf4j -public class Controller { +public class TgBotController { private final TelegramBot bot; private final TelegramBotConfig botConfig; @Autowired - public Controller(ApplicationConfig config, TelegramBotConfig botConfig) { + public TgBotController(ApplicationConfig config, TelegramBotConfig botConfig) { this.botConfig = botConfig; bot = botConfig.telegramBot(config); bot.setUpdatesListener(this::processUpdates, this::processException); diff --git a/bot/src/main/java/edu/java/bot/command/AbstractCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java similarity index 74% rename from bot/src/main/java/edu/java/bot/command/AbstractCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java index 6d1d6e6..a7a897c 100644 --- a/bot/src/main/java/edu/java/bot/command/AbstractCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; import com.pengrad.telegrambot.model.Update; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.command.CommandNotExistException; -import edu.java.bot.exception.command.NotCommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.parameter.ParameterException; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.command.CommandNotExistException; +import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index 028ee0b..a78798c 100644 --- a/bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,6 +1,6 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/Command.java b/bot/src/main/java/edu/java/bot/telegram/command/Command.java new file mode 100644 index 0000000..1d90049 --- /dev/null +++ b/bot/src/main/java/edu/java/bot/telegram/command/Command.java @@ -0,0 +1,16 @@ +package edu.java.bot.telegram.command; + +import com.pengrad.telegrambot.model.Update; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; + +public interface Command { + + String getName(); + + String getDescription(); + + String execute(Update update) throws UnregisteredUserException, ParameterException, CommandException, LinkException; +} diff --git a/bot/src/main/java/edu/java/bot/command/CommandUtils.java b/bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java similarity index 72% rename from bot/src/main/java/edu/java/bot/command/CommandUtils.java rename to bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java index 666fc21..3eb2d27 100644 --- a/bot/src/main/java/edu/java/bot/command/CommandUtils.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java @@ -1,8 +1,8 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.parameter.WrongNumberParametersException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; public class CommandUtils { diff --git a/bot/src/main/java/edu/java/bot/command/components/HelpCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java similarity index 76% rename from bot/src/main/java/edu/java/bot/command/components/HelpCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java index 6360263..b0a1895 100644 --- a/bot/src/main/java/edu/java/bot/command/components/HelpCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java @@ -1,9 +1,9 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.Command; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.parameter.ParameterException; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.Command; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.parameter.ParameterException; import java.util.List; import java.util.stream.Collectors; import org.springframework.core.annotation.Order; diff --git a/bot/src/main/java/edu/java/bot/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/components/ListCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 1f7a377..79c9498 100644 --- a/bot/src/main/java/edu/java/bot/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,15 +1,16 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; -import java.util.List; -import java.util.stream.Collectors; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.stream.Collectors; + @Component @Order(5) public class ListCommand extends AbstractServiceCommand { diff --git a/bot/src/main/java/edu/java/bot/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/components/StartCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index 120ae79..e4f0af0 100644 --- a/bot/src/main/java/edu/java/bot/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,9 +1,9 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.parameter.ParameterException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java similarity index 70% rename from bot/src/main/java/edu/java/bot/command/components/TrackCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 466f995..670a538 100644 --- a/bot/src/main/java/edu/java/bot/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.utils.Link; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java similarity index 70% rename from bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 3e65102..40d974d 100644 --- a/bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.utils.Link; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java b/bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java similarity index 84% rename from bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java index c8760df..3f94199 100644 --- a/bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception; +package edu.java.bot.telegram.exception; public class UnregisteredUserException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/command/CommandException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java similarity index 73% rename from bot/src/main/java/edu/java/bot/exception/command/CommandException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java index 2bc19fe..25f1725 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/CommandException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public abstract class CommandException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java similarity index 77% rename from bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java index 6e6c488..e73c5b9 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public class CommandNotExistException extends CommandException { public CommandNotExistException() { diff --git a/bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java index 65def43..e1c5919 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public class NotCommandException extends CommandException { public NotCommandException() { diff --git a/bot/src/main/java/edu/java/bot/exception/link/LinkException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java similarity index 74% rename from bot/src/main/java/edu/java/bot/exception/link/LinkException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java index 483556e..ffcba12 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/LinkException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public abstract class LinkException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java index 2c3b5ff..1d9c9b3 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public class LinkRegistrationException extends LinkException { public LinkRegistrationException(String message) { diff --git a/bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java similarity index 74% rename from bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java index b3124f9..f04851c 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public class NotLinkException extends LinkException { public NotLinkException(String message) { diff --git a/bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java similarity index 73% rename from bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java index 017af07..5cb975c 100644 --- a/bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.parameter; +package edu.java.bot.telegram.exception.parameter; public abstract class ParameterException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java index f9c4147..9b4417f 100644 --- a/bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.parameter; +package edu.java.bot.telegram.exception.parameter; public class WrongNumberParametersException extends ParameterException { diff --git a/bot/src/main/java/edu/java/bot/utils/Link.java b/bot/src/main/java/edu/java/bot/utils/Link.java index 0421d92..25504af 100644 --- a/bot/src/main/java/edu/java/bot/utils/Link.java +++ b/bot/src/main/java/edu/java/bot/utils/Link.java @@ -1,6 +1,6 @@ package edu.java.bot.utils; -import edu.java.bot.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.link.NotLinkException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index 65f3332..74221c2 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -3,19 +3,19 @@ import com.pengrad.telegrambot.model.Message; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.User; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.Command; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.Command; import edu.java.bot.configuration.TelegramBotConfig; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.command.CommandNotExistException; -import edu.java.bot.exception.command.NotCommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.exception.parameter.WrongNumberParametersException; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.command.CommandNotExistException; +import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; diff --git a/bot/src/test/java/edu/java/bot/TestScrapperService.java b/bot/src/test/java/edu/java/bot/TestScrapperService.java index 6eb3f3c..b5a827c 100644 --- a/bot/src/test/java/edu/java/bot/TestScrapperService.java +++ b/bot/src/test/java/edu/java/bot/TestScrapperService.java @@ -1,6 +1,6 @@ package edu.java.bot; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; import java.util.List; import lombok.Setter; diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index a5ad13b..dd696e8 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.client.AbstractClient; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java index c5739f3..7625599 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.client.AbstractClient; -import edu.java.scrapper.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java similarity index 91% rename from scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java index a6e0ee7..2ddb643 100644 --- a/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java @@ -1,4 +1,4 @@ -package edu.java.scrapper.dto; +package edu.java.scrapper.client.sources.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java similarity index 89% rename from scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java index 15fceb9..b3ac47e 100644 --- a/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java @@ -1,4 +1,4 @@ -package edu.java.scrapper.dto; +package edu.java.scrapper.client.sources.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java index ea5a5c4..277b85e 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java @@ -6,7 +6,7 @@ import edu.java.scrapper.client.sources.GithubClient; import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java index 741ca3d..6af27ca 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java index a2a5d80..de5909d 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java @@ -6,7 +6,7 @@ import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.client.sources.StackoverflowClient; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.AfterEach; From e881ed5368f802a9762b31c9c1007cd8318df602 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 14:37:44 +0300 Subject: [PATCH 06/34] feat: add domain dto for scrapper --- .../java/bot/telegram/command/components/ListCommand.java | 5 ++--- .../main/java/edu/java/scrapper/api/domain/dto/Chat.java | 4 ++++ .../main/java/edu/java/scrapper/api/domain/dto/Link.java | 7 +++++++ .../java/edu/java/scrapper/api/domain/dto/Subcription.java | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 79c9498..1f6cd78 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -5,11 +5,10 @@ import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - import java.util.List; import java.util.stream.Collectors; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; @Component @Order(5) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java new file mode 100644 index 0000000..4245a36 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Chat(long id, long tgId) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java new file mode 100644 index 0000000..b6422a2 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java @@ -0,0 +1,7 @@ +package edu.java.scrapper.api.domain.dto; + +import java.net.URI; +import java.time.OffsetDateTime; + +public record Link(long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java new file mode 100644 index 0000000..7eb3981 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Subcription(long chatId, long linkId) { +} From df95c39f77b639c5756bb07d2e931dc8ab08166f Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 23:28:12 +0300 Subject: [PATCH 07/34] feat: add repos and services for dto with tests --- .../java/scrapper/api/domain/dto/Chat.java | 2 +- .../java/scrapper/api/domain/dto/Link.java | 2 +- .../scrapper/api/domain/dto/Subcription.java | 4 - .../scrapper/api/domain/dto/Subscription.java | 4 + .../api/domain/repository/ChatRepository.java | 15 +++ .../api/domain/repository/LinkRepository.java | 20 ++++ .../repository/SubscriptionRepository.java | 24 ++++ .../jdbc/AbstractJdbcRepository.java | 11 ++ .../repository/jdbc/JdbcChatRepository.java | 51 ++++++++ .../repository/jdbc/JdbcLinkRepository.java | 69 +++++++++++ .../jdbc/JdbcSubscriptionRepository.java | 91 +++++++++++++++ .../chat/ChatAlreadyRegisteredException.java | 4 + .../chat/ChatExceptionApiHandler.java | 8 +- .../chat/ChatRegistrationException.java | 4 - .../scrapper/api/service/ChatService.java | 10 ++ .../scrapper/api/service/LinkService.java | 16 +++ .../scrapper/api/service/LinkUpdater.java | 5 + .../scrapper/api/service/ScrapperService.java | 21 ++++ .../api/service/jdbc/JdbcChatService.java | 52 +++++++++ .../api/service/jdbc/JdbcLinkService.java | 79 +++++++++++++ .../api/service/jdbc/JdbcLinkUpdater.java | 26 +++++ scrapper/src/main/resources/application.yml | 9 +- .../domain/repository/ChatRepositoryTest.java | 75 ++++++++++++ .../domain/repository/LinkRepositoryTest.java | 88 ++++++++++++++ .../SubscriptionRepositoryTest.java | 109 ++++++++++++++++++ .../jdbc/JdbcChatRepositoryTest.java | 14 +++ .../jdbc/JdbcLinkRepositoryTest.java | 14 +++ .../jdbc/JdbcSubscriptionRepositoryTest.java | 15 +++ 28 files changed, 825 insertions(+), 17 deletions(-) delete mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java delete mode 100644 scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java index 4245a36..92db131 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java @@ -1,4 +1,4 @@ package edu.java.scrapper.api.domain.dto; -public record Chat(long id, long tgId) { +public record Chat(Long id, long tgId) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java index b6422a2..f96249d 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java @@ -3,5 +3,5 @@ import java.net.URI; import java.time.OffsetDateTime; -public record Link(long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { +public record Link(Long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java deleted file mode 100644 index 7eb3981..0000000 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java +++ /dev/null @@ -1,4 +0,0 @@ -package edu.java.scrapper.api.domain.dto; - -public record Subcription(long chatId, long linkId) { -} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java new file mode 100644 index 0000000..8ce08d3 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Subscription(long chatId, long linkId) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java new file mode 100644 index 0000000..61c36ff --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java @@ -0,0 +1,15 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Chat; +import java.util.List; +import java.util.Optional; + +public interface ChatRepository { + Optional findByTgId(long tgId); + + Chat add(long tgId); + + void remove(long tgId); + + List findAll(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java new file mode 100644 index 0000000..1924aab --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java @@ -0,0 +1,20 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Link; +import java.net.URI; +import java.util.List; +import java.util.Optional; + +public interface LinkRepository { + Optional findById(long id); + + Optional findByUrl(URI url); + + Link add(Link link); + + void remove(URI url); + + void remove(long id); + + List findAll(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java new file mode 100644 index 0000000..c99a9cd --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java @@ -0,0 +1,24 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import java.net.URI; +import java.util.List; +import java.util.Optional; + +public interface SubscriptionRepository { + Optional find(long tgId, URI url); + + Subscription add(Subscription subscription); + + void remove(Subscription subscription); + + List findAll(); + + List findAllByChat(long chatId); + + boolean linkNotFollowedByAnyone(long linkId); + + List findAllLinksByChat(Chat chat); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java new file mode 100644 index 0000000..2820fe6 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java @@ -0,0 +1,11 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import org.springframework.jdbc.core.simple.JdbcClient; + +public abstract class AbstractJdbcRepository { + protected final JdbcClient client; + + public AbstractJdbcRepository(JdbcClient client) { + this.client = client; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java new file mode 100644 index 0000000..d1a1000 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java @@ -0,0 +1,51 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.repository.ChatRepository; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcChatRepository extends AbstractJdbcRepository implements ChatRepository { + + public JdbcChatRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional findByTgId(long tgId) { + return client.sql("select * from chat where tg_id = ?") + .param(tgId) + .query(Chat.class) + .optional(); + } + + @Override + public Chat add(long tgId) { + GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); + client.sql("insert into chat (tg_id) values (?)") + .param(tgId) + .update(keyHolder, "id"); + long id = keyHolder.getKey().longValue(); + return new Chat(id, tgId); + } + + @Override + public void remove(long tgId) { + client.sql("delete from chat where tg_id = ?") + .param(tgId) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from chat") + .query(Chat.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java new file mode 100644 index 0000000..ce81751 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java @@ -0,0 +1,69 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.repository.LinkRepository; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcLinkRepository extends AbstractJdbcRepository implements LinkRepository { + + public JdbcLinkRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional findById(long id) { + return client.sql("select * from link where id = ?") + .param(id) + .query(Link.class) + .optional(); + } + + @Override + public Optional findByUrl(URI url) { + return client.sql("select * from link where url = ?") + .param(url.toString()) + .query(Link.class) + .optional(); + } + + @Override + public Link add(Link link) { + GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); + client.sql("insert into link (url, last_update, last_check) values (?, ?, ?)") + .param(link.url().toString()) + .param(link.lastUpdate()) + .param(link.lastCheck()) + .update(keyHolder, "id"); + long id = keyHolder.getKey().longValue(); + return new Link(id, link.url(), link.lastUpdate(), link.lastCheck()); + } + + @Override + public void remove(URI url) { + client.sql("delete from link where url = ?") + .param(url.toString()) + .update(); + } + + @Override + public void remove(long id) { + client.sql("delete from link where id = ?") + .param(id) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from link") + .query(Link.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java new file mode 100644 index 0000000..2c1abb9 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -0,0 +1,91 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.SubscriptionRepository; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcSubscriptionRepository extends AbstractJdbcRepository implements SubscriptionRepository { + + public JdbcSubscriptionRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional find(long tgId, URI url) { + return client.sql(""" + select subscription.chat_id, subscription.link_id + from subscription + inner join chat on subscription.chat_id = chat.id + inner join link on subscription.link_id = link.id + where + chat.tg_id = ? + and link.url = ?""") + .param(tgId) + .param(url.toString()) + .query(Subscription.class) + .optional(); + } + + @Override + public Subscription add(Subscription subscription) { + client.sql("insert into subscription (chat_id, link_id) values (?, ?)") + .param(subscription.chatId()) + .param(subscription.linkId()) + .update(); + return subscription; + } + + @Override + public void remove(Subscription subscription) { + client.sql("delete from subscription where chat_id = ? and link_id = ?") + .param(subscription.chatId()) + .param(subscription.linkId()) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from subscription") + .query(Subscription.class) + .list(); + } + + @Override + public List findAllByChat(long chatId) { + return client.sql("select * from subscription where chat_id = ?") + .param(chatId) + .query(Subscription.class) + .list(); + } + + @Override + public boolean linkNotFollowedByAnyone(long linkId) { + List subscriptions = client.sql("select * from subscription where link_id = ?") + .param(linkId) + .query(Subscription.class) + .list(); + return subscriptions.isEmpty(); + } + + @Override + public List findAllLinksByChat(Chat chat) { + return client.sql(""" + select link.id, link.url + from link + inner join subscription on link.id = subscription.link_id + where + subscription.chat_id = ?""") + .param(chat.id()) + .query(Link.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java new file mode 100644 index 0000000..f0333fc --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.exception.chat; + +public class ChatAlreadyRegisteredException extends Exception { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index c8344dd..811b2e6 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -10,10 +10,10 @@ @RestControllerAdvice public class ChatExceptionApiHandler { - @ExceptionHandler(ChatRegistrationException.class) - public ResponseEntity chatRegistrationException(ChatRegistrationException exception) { + @ExceptionHandler(ChatAlreadyRegisteredException.class) + public ResponseEntity chatRegistrationException(ChatAlreadyRegisteredException exception) { ApiErrorResponse error = new ApiErrorResponse( - "Чат с уже зарегистрирован", + "Чат уже зарегистрирован", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), @@ -29,7 +29,7 @@ public ResponseEntity chatRegistrationException(ChatRegistrati @ExceptionHandler(ChatNotFoundException.class) public ResponseEntity chatNotFoundException(ChatNotFoundException exception) { ApiErrorResponse error = new ApiErrorResponse( - "Чат с id не найден", + "Чат не найден", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java deleted file mode 100644 index eba10b2..0000000 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java +++ /dev/null @@ -1,4 +0,0 @@ -package edu.java.scrapper.api.exception.chat; - -public class ChatRegistrationException extends Exception { -} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java new file mode 100644 index 0000000..1eb5ee4 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java @@ -0,0 +1,10 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; + +public interface ChatService { + void register(long tgId) throws ChatAlreadyRegisteredException; + + void unregister(long tgId) throws ChatNotFoundException; +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java new file mode 100644 index 0000000..fd58f07 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java @@ -0,0 +1,16 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import java.net.URI; +import java.util.List; + +public interface LinkService { + Link add(long tgId, URI url) throws ChatNotFoundException, LinkAdditionException; + + Link remove(long tgId, URI url) throws LinkNotFoundException, ChatNotFoundException; + + List listAll(long tgId) throws ChatNotFoundException; +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java new file mode 100644 index 0000000..502bf89 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java @@ -0,0 +1,5 @@ +package edu.java.scrapper.api.service; + +public interface LinkUpdater { + int update(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java new file mode 100644 index 0000000..455271f --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java @@ -0,0 +1,21 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.domain.repository.ChatRepository; +import edu.java.scrapper.api.domain.repository.LinkRepository; +import edu.java.scrapper.api.domain.repository.SubscriptionRepository; + +public abstract class ScrapperService { + protected final ChatRepository chatRepo; + protected final LinkRepository linkRepo; + protected final SubscriptionRepository subscriptionRepo; + + protected ScrapperService( + ChatRepository chatRepo, + LinkRepository linkRepo, + SubscriptionRepository subscriptionRepo + ) { + this.chatRepo = chatRepo; + this.linkRepo = linkRepo; + this.subscriptionRepo = subscriptionRepo; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java new file mode 100644 index 0000000..a7d5781 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -0,0 +1,52 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.service.ChatService; +import edu.java.scrapper.api.service.ScrapperService; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcChatService extends ScrapperService implements ChatService { + + @Autowired + protected JdbcChatService( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public void register(long tgId) throws ChatAlreadyRegisteredException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isPresent()) { + throw new ChatAlreadyRegisteredException(); + } + chatRepo.add(tgId); + } + + @Override + public void unregister(long tgId) throws ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + List subscriptions = subscriptionRepo.findAllByChat(chat.get().id()); + for (Subscription subscription : subscriptions) { + subscriptionRepo.remove(subscription); + if (subscriptionRepo.linkNotFollowedByAnyone(subscription.linkId())) { + linkRepo.remove(subscription.linkId()); + } + } + chatRepo.remove(tgId); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java new file mode 100644 index 0000000..3c0a1b0 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -0,0 +1,79 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import edu.java.scrapper.api.service.LinkService; +import edu.java.scrapper.api.service.ScrapperService; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcLinkService extends ScrapperService implements LinkService { + + @Autowired + protected JdbcLinkService( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public Link add(long tgId, URI url) throws ChatNotFoundException, LinkAdditionException { + Optional subscription = subscriptionRepo.find(tgId, url); + if (subscription.isPresent()) { + throw new LinkAdditionException(); + } + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + Optional link = linkRepo.findByUrl(url); + if (link.isEmpty()) { + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + link = Optional.of(linkRepo.add(new Link(null, url, now, now))); + } + subscriptionRepo.add(new Subscription(chat.get().id(), link.get().id())); + return link.get(); + } + + @Override + public Link remove(long tgId, URI url) throws LinkNotFoundException, ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + Optional subscription = subscriptionRepo.find(tgId, url); + if (subscription.isEmpty()) { + throw new LinkNotFoundException(); + } + Link link = linkRepo.findById(subscription.get().linkId()).get(); + subscriptionRepo.remove(subscription.get()); + if (subscriptionRepo.linkNotFollowedByAnyone(link.id())) { + linkRepo.remove(link.id()); + } + return link; + } + + @Override + public List listAll(long tgId) throws ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + return subscriptionRepo.findAllLinksByChat(chat.get()); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java new file mode 100644 index 0000000..14fbde1 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -0,0 +1,26 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.service.LinkUpdater; +import edu.java.scrapper.api.service.ScrapperService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { + + @Autowired + protected JdbcLinkUpdater( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public int update() { + return 0; + } +} diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index 8fa269c..f4fa721 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -14,9 +14,12 @@ spring: application: name: scrapper liquibase: - enabled: true - autoconfigure: - exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + enabled: false + datasource: + driver-class-name: org.postgresql.Driver + url: "jdbc:postgresql://localhost:5432/scrapper" + username: "postgres" + password: "postgres" jackson: property-naming-strategy: SNAKE_CASE diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java new file mode 100644 index 0000000..77c65db --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java @@ -0,0 +1,75 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Chat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class ChatRepositoryTest extends IntegrationTest { + private static final long TG_ID = 11111; + private final ChatRepository repo; + + protected ChatRepositoryTest(ChatRepository repo) { + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Chat actual = repo.add(TG_ID); + Assertions.assertEquals(TG_ID, actual.tgId()); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + repo.add(TG_ID); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(TG_ID)); + } + + @Test + @Transactional + @Rollback + void findByTgIdTest() { + Chat expected = repo.add(TG_ID); + Chat actual = repo.findByTgId(TG_ID).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findByTgIdNotExistTest() { + Optional actual = repo.findByTgId(TG_ID); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + repo.add(TG_ID); + repo.remove(TG_ID); + Optional actual = repo.findByTgId(TG_ID); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + List expected = new ArrayList<>(); + expected.add(repo.add(TG_ID)); + expected.add(repo.add(22222)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java new file mode 100644 index 0000000..457c069 --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java @@ -0,0 +1,88 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Link; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class LinkRepositoryTest extends IntegrationTest { + private static final URI URL = + URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring/"); + private static final OffsetDateTime NOW = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + private final LinkRepository repo; + + protected LinkRepositoryTest(LinkRepository repo) { + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Link expected = new Link(null, URL, NOW, NOW); + Link actual = repo.add(expected); + Assertions.assertEquals(expected.url(), actual.url()); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + Link link = new Link(null, URL, NOW, NOW); + repo.add(link); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(link)); + } + + @Test + @Transactional + @Rollback + void findByUrlTest() { + Link link = new Link(null, URL, NOW, NOW); + Link expected = repo.add(link); + Link actual = repo.findByUrl(URL).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findByUrlNotExistTest() { + Optional actual = repo.findByUrl(URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + Link link = new Link(null, URL, NOW, NOW); + repo.add(link); + repo.remove(URL); + Optional actual = repo.findByUrl(URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + Link link1 = new Link(null, URL, NOW, NOW); + URI url2 = URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse/"); + Link link2 = new Link(null, url2, NOW, NOW); + List expected = new ArrayList<>(); + expected.add(repo.add(link1)); + expected.add(repo.add(link2)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java new file mode 100644 index 0000000..30ca69d --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java @@ -0,0 +1,109 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class SubscriptionRepositoryTest extends IntegrationTest { + private static final long TG_ID = 11111; + private static final URI URL = + URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring/"); + private static final OffsetDateTime NOW = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + private final ChatRepository chatRepo; + private final LinkRepository linkRepo; + private final SubscriptionRepository repo; + + protected SubscriptionRepositoryTest(ChatRepository chatRepo, + LinkRepository linkRepo, SubscriptionRepository repo) { + this.chatRepo = chatRepo; + this.linkRepo = linkRepo; + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription expected = new Subscription(chat.id(), link.id()); + Subscription actual = repo.add(expected); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + repo.add(subscription); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(subscription)); + } + + @Test + @Transactional + @Rollback + void findTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + Subscription expected = repo.add(subscription); + Subscription actual = repo.find(TG_ID, URL).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findNotExistTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + Optional actual = repo.find(TG_ID, URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + repo.add(subscription); + repo.remove(subscription); + Optional actual = repo.find(TG_ID, URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + Chat chat1 = chatRepo.add(TG_ID); + Chat chat2 = chatRepo.add(22222); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription1 = new Subscription(chat1.id(), link.id()); + Subscription subscription2 = new Subscription(chat2.id(), link.id()); + List expected = new ArrayList<>(); + expected.add(repo.add(subscription1)); + expected.add(repo.add(subscription2)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java new file mode 100644 index 0000000..82f2c30 --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java @@ -0,0 +1,14 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.ChatRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcChatRepositoryTest extends ChatRepositoryTest { + + @Autowired + protected JdbcChatRepositoryTest(JdbcChatRepository repo) { + super(repo); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java new file mode 100644 index 0000000..367d6fc --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java @@ -0,0 +1,14 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.LinkRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcLinkRepositoryTest extends LinkRepositoryTest { + + @Autowired + protected JdbcLinkRepositoryTest(JdbcLinkRepository repo) { + super(repo); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java new file mode 100644 index 0000000..9f95afa --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java @@ -0,0 +1,15 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.SubscriptionRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcSubscriptionRepositoryTest extends SubscriptionRepositoryTest { + + @Autowired + protected JdbcSubscriptionRepositoryTest(JdbcSubscriptionRepository repo, JdbcChatRepository chatRepo, + JdbcLinkRepository linkRepo) { + super(chatRepo, linkRepo, repo); + } +} From fcf6f8ebf33a3083bbc172e7aa194d72246ccd7a Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 23:57:26 +0300 Subject: [PATCH 08/34] feat: replace todo with services calls in scrapper controllers --- .../api/controller/ChatController.java | 22 +++++----- .../api/controller/LinkController.java | 44 +++++++++++-------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index f1696a2..7926fba 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,6 +1,9 @@ package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.service.ChatService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -17,6 +20,11 @@ @RestController @RequestMapping("/tg-chat") public class ChatController { + private final ChatService service; + + public ChatController(ChatService service) { + this.service = service; + } @Operation(summary = "Зарегистрировать чат") @ApiResponses(value = { @@ -26,11 +34,8 @@ public class ChatController { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @PostMapping("/{id}") - public ResponseEntity registerChat(@PathVariable @Positive long id) { - /* - TODO: регистрация чата - может быть брошено ChatRegistrationException - */ + public ResponseEntity registerChat(@PathVariable @Positive long id) throws ChatAlreadyRegisteredException { + service.register(id); return ResponseEntity.ok().build(); } @@ -45,11 +50,8 @@ public ResponseEntity registerChat(@PathVariable @Positive long id) { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @DeleteMapping("/{id}") - public ResponseEntity deleteChat(@PathVariable @Positive long id) { - /* - TODO: удаление чата - может быть брошено ChatNotFoundException - */ + public ResponseEntity deleteChat(@PathVariable @Positive long id) throws ChatNotFoundException { + service.unregister(id); return ResponseEntity.ok().build(); } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index 080211b..a57af05 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -5,6 +5,11 @@ import edu.java.api_dto.scrapper.LinkResponse; import edu.java.api_dto.scrapper.ListLinksResponse; import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import edu.java.scrapper.api.service.LinkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,7 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; import java.net.URI; -import java.net.URISyntaxException; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -25,6 +30,11 @@ @RestController @RequestMapping("/links") public class LinkController { + private final LinkService service; + + public LinkController(LinkService service) { + this.service = service; + } @Operation(summary = "Получить все отслеживаемые ссылки") @ApiResponses(value = { @@ -36,11 +46,15 @@ public class LinkController { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @GetMapping - public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat-Id") long chatId) { - /* - TODO: получение списка ссылок - */ - return ResponseEntity.ok(new ListLinksResponse(new LinkResponse[0], 1)); + public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat-Id") long chatId) + throws ChatNotFoundException { + List links = service.listAll(chatId); + return ResponseEntity.ok(new ListLinksResponse( + links.stream() + .map(l -> new LinkResponse(l.id(), l.url())) + .toArray(LinkResponse[]::new), + links.size() + )); } @Operation(summary = "Добавить отслеживание ссылки") @@ -56,12 +70,9 @@ public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat public ResponseEntity addLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody AddLinkRequest request - ) throws URISyntaxException { - /* - TODO: добавление ссылки - может быть брошено LinkAdditionException - */ - return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); + ) throws LinkAdditionException, ChatNotFoundException { + Link link = service.add(chatId, URI.create(request.link())); + return ResponseEntity.ok(new LinkResponse(link.id(), link.url())); } @Operation(summary = "Убрать отслеживание ссылки") @@ -80,11 +91,8 @@ public ResponseEntity addLink( public ResponseEntity deleteLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody RemoveLinkRequest request - ) throws URISyntaxException { - /* - TODO: удаление ссылки - может быть брошено LinkNotFoundException - */ - return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); + ) throws ChatNotFoundException, LinkNotFoundException { + Link link = service.remove(chatId, URI.create(request.link())); + return ResponseEntity.ok(new LinkResponse(link.id(), link.url())); } } From 45cf0328359b038b565f2f1fc4fc15e05b75e5fe Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Thu, 21 Mar 2024 20:26:47 +0300 Subject: [PATCH 09/34] fix: db port and sql queries --- .../domain/repository/jdbc/JdbcSubscriptionRepository.java | 4 ++-- scrapper/src/main/resources/application.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java index 2c1abb9..31e8f7d 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -22,7 +22,7 @@ public JdbcSubscriptionRepository(JdbcClient client) { @Override public Optional find(long tgId, URI url) { return client.sql(""" - select subscription.chat_id, subscription.link_id + select subscription.* from subscription inner join chat on subscription.chat_id = chat.id inner join link on subscription.link_id = link.id @@ -79,7 +79,7 @@ public boolean linkNotFollowedByAnyone(long linkId) { @Override public List findAllLinksByChat(Chat chat) { return client.sql(""" - select link.id, link.url + select link.* from link inner join subscription on link.id = subscription.link_id where diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index f4fa721..b65ec42 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -17,7 +17,7 @@ spring: enabled: false datasource: driver-class-name: org.postgresql.Driver - url: "jdbc:postgresql://localhost:5432/scrapper" + url: "jdbc:postgresql://localhost:5433/scrapper" username: "postgres" password: "postgres" From b810ece4830d26653bcc236712c2d3a6e98eeeb9 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Thu, 21 Mar 2024 23:50:01 +0300 Subject: [PATCH 10/34] feat: start link source parsers realization --- bot/pom.xml | 2 +- .../bot/api/controller/UpdateController.java | 4 +-- .../api/exception/ExceptionApiHandler.java | 2 +- .../java/bot/client/ScrapperApiException.java | 2 +- .../edu/java/bot/client/ScrapperClient.java | 10 +++--- .../bot/telegram/command/AbstractCommand.java | 2 +- .../java/bot/telegram/command/Command.java | 2 +- .../command/components/TrackCommand.java | 12 ++++--- .../command/components/UntrackCommand.java | 12 ++++--- .../main/java/edu/java/bot/utils/Link.java | 24 ------------- .../java/edu/java/bot/BotApplicationTest.java | 6 ++-- {api_dto => dto}/pom.xml | 2 +- .../java/dto/api}/bot/ApiErrorResponse.java | 2 +- .../java/dto/api}/bot/LinkUpdateRequest.java | 2 +- .../dto/api}/scrapper/AddLinkRequest.java | 2 +- .../dto/api}/scrapper/ApiErrorResponse.java | 2 +- .../java/dto/api}/scrapper/LinkResponse.java | 2 +- .../dto/api}/scrapper/ListLinksResponse.java | 2 +- .../dto/api}/scrapper/RemoveLinkRequest.java | 2 +- .../java/edu/java/dto/utils/LinkInfo.java | 7 ++++ .../java/edu/java/dto/utils/LinkParser.java | 35 ++++++++++++++++++ .../dto/utils/exception}/LinkException.java | 4 ++- .../exception}/LinkRegistrationException.java | 5 ++- .../utils/exception}/NotLinkException.java | 5 ++- .../SourceNotSupportedException.java | 10 ++++++ .../dto/utils/sources/info/GithubInfo.java | 19 ++++++++++ .../dto/utils/sources/info/SourceInfo.java | 5 +++ .../utils/sources/info/StackoverflowInfo.java | 13 +++++++ .../utils/sources/parsers/SourceParser.java | 36 +++++++++++++++++++ pom.xml | 2 +- scrapper/pom.xml | 2 +- .../api/controller/ChatController.java | 2 +- .../api/controller/LinkController.java | 10 +++--- .../api/domain/repository/LinkRepository.java | 5 +++ .../repository/jdbc/JdbcLinkRepository.java | 18 ++++++++++ .../chat/ChatExceptionApiHandler.java | 2 +- .../link/LinkExceptionApiHandler.java | 2 +- .../scrapper/api/service/ScrapperService.java | 5 ++- .../api/service/jdbc/JdbcChatService.java | 4 ++- .../api/service/jdbc/JdbcLinkService.java | 4 ++- .../api/service/jdbc/JdbcLinkUpdater.java | 20 +++++++++-- .../scrapper/client/bot/BotApiException.java | 2 +- .../java/scrapper/client/bot/BotClient.java | 4 +-- scrapper/src/main/resources/application.yml | 2 +- 44 files changed, 238 insertions(+), 79 deletions(-) delete mode 100644 bot/src/main/java/edu/java/bot/utils/Link.java rename {api_dto => dto}/pom.xml (96%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/bot/ApiErrorResponse.java (89%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/bot/LinkUpdateRequest.java (88%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/AddLinkRequest.java (86%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/ApiErrorResponse.java (88%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/LinkResponse.java (84%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/ListLinksResponse.java (84%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/RemoveLinkRequest.java (86%) create mode 100644 dto/src/main/java/edu/java/dto/utils/LinkInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/LinkParser.java rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/LinkException.java (64%) rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/LinkRegistrationException.java (63%) rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/NotLinkException.java (63%) create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java diff --git a/bot/pom.xml b/bot/pom.xml index e1391fc..21aab18 100644 --- a/bot/pom.xml +++ b/bot/pom.xml @@ -130,7 +130,7 @@ edu.java - api_dto + dto 0.1 diff --git a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java index 92fbab4..e2fd998 100644 --- a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java +++ b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java @@ -1,7 +1,7 @@ package edu.java.bot.api.controller; -import edu.java.api_dto.bot.ApiErrorResponse; -import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.dto.api.bot.ApiErrorResponse; +import edu.java.dto.api.bot.LinkUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java index c75a289..57cfcb0 100644 --- a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java +++ b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.bot.api.exception; -import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.dto.api.bot.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java index 1fa2b6c..cbb465a 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java @@ -1,6 +1,6 @@ package edu.java.bot.client; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import lombok.Getter; @Getter diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java index 577ca9c..07037a7 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,11 +1,11 @@ package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api_dto.scrapper.AddLinkRequest; -import edu.java.api_dto.scrapper.ApiErrorResponse; -import edu.java.api_dto.scrapper.LinkResponse; -import edu.java.api_dto.scrapper.ListLinksResponse; -import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.dto.api.scrapper.AddLinkRequest; +import edu.java.dto.api.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.LinkResponse; +import edu.java.dto.api.scrapper.ListLinksResponse; +import edu.java.dto.api.scrapper.RemoveLinkRequest; import lombok.NonNull; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatusCode; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java index a7a897c..9b4f36b 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java @@ -5,8 +5,8 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; -import edu.java.bot.telegram.exception.link.LinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.exception.LinkException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/Command.java b/bot/src/main/java/edu/java/bot/telegram/command/Command.java index 1d90049..874b01e 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/Command.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/Command.java @@ -3,8 +3,8 @@ import com.pengrad.telegrambot.model.Update; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.command.CommandException; -import edu.java.bot.telegram.exception.link.LinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.exception.LinkException; public interface Command { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 670a538..72d88b2 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -4,10 +4,11 @@ import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.bot.utils.Link; +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -31,10 +32,11 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException { + throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, + SourceNotSupportedException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - Link.parse(link); + new LinkParser(null).parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 40d974d..c566083 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -4,10 +4,11 @@ import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.bot.utils.Link; +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -31,10 +32,11 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException { + throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, + SourceNotSupportedException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - Link.parse(link); + new LinkParser(null).parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/utils/Link.java b/bot/src/main/java/edu/java/bot/utils/Link.java deleted file mode 100644 index 25504af..0000000 --- a/bot/src/main/java/edu/java/bot/utils/Link.java +++ /dev/null @@ -1,24 +0,0 @@ -package edu.java.bot.utils; - -import edu.java.bot.telegram.exception.link.NotLinkException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; - -public class Link { - private Link() { - } - - public static URL parse(String link) throws NotLinkException { - String url = link.toLowerCase(); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - throw new NotLinkException("У ссылки отсутствует протокол"); - } - try { - return new URI(link).toURL(); - } catch (MalformedURLException | URISyntaxException e) { - throw new NotLinkException("Неверная ссылка"); - } - } -} diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index 74221c2..e9e79ee 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -11,9 +11,9 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; -import edu.java.bot.telegram.exception.link.LinkException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.dto.utils.exception.LinkException; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; diff --git a/api_dto/pom.xml b/dto/pom.xml similarity index 96% rename from api_dto/pom.xml rename to dto/pom.xml index 25f8f90..a9c9b8f 100644 --- a/api_dto/pom.xml +++ b/dto/pom.xml @@ -9,7 +9,7 @@ ${revision} - api_dto + dto ${revision} diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java b/dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java similarity index 89% rename from api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java rename to dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java index 943c66b..c760ecd 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java +++ b/dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.bot; +package edu.java.dto.api.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java b/dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java similarity index 88% rename from api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java rename to dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java index bd2d278..410fa0d 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java +++ b/dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.bot; +package edu.java.dto.api.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.net.URI; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java b/dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java similarity index 86% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java rename to dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java index 2399b04..a45ba0c 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java similarity index 88% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java index 45c7228..47752f1 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java similarity index 84% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java index 91ca8c0..bf3d094 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.net.URI; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java similarity index 84% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java index 5ff4bda..6393dce 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java b/dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java similarity index 86% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java rename to dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java index 049848a..1ed7b78 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/dto/src/main/java/edu/java/dto/utils/LinkInfo.java b/dto/src/main/java/edu/java/dto/utils/LinkInfo.java new file mode 100644 index 0000000..f024812 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/LinkInfo.java @@ -0,0 +1,7 @@ +package edu.java.dto.utils; + +import edu.java.dto.utils.sources.info.SourceInfo; +import java.net.URI; + +public record LinkInfo(URI url, SourceInfo source) { +} diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java new file mode 100644 index 0000000..e4dd733 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -0,0 +1,35 @@ +package edu.java.dto.utils; + +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.parsers.SourceParser; +import java.net.URI; +import java.net.URISyntaxException; + +public class LinkParser { + private final SourceParser parser; + + public LinkParser(SourceParser parser) { + this.parser = parser; + } + + public LinkInfo parse(String link) throws NotLinkException, SourceNotSupportedException { + String url = link.toLowerCase(); + if (!url.startsWith("http://") && !url.startsWith("https://")) { + throw new NotLinkException("У ссылки отсутствует протокол"); + } + URI parsedUrl; + try { + parsedUrl = new URI(link); + } catch (URISyntaxException e) { + throw new NotLinkException("Неверная ссылка"); + } + try { + SourceInfo source = parser.parse(parsedUrl); + return new LinkInfo(parsedUrl, source); + } catch (SourceNotSupportedException e) { + throw new SourceNotSupportedException("Данный ресурс не поддерживается"); + } + } +} diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java b/dto/src/main/java/edu/java/dto/utils/exception/LinkException.java similarity index 64% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java rename to dto/src/main/java/edu/java/dto/utils/exception/LinkException.java index ffcba12..7a005b5 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/LinkException.java @@ -1,6 +1,8 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public abstract class LinkException extends Exception { + public LinkException() { + } public LinkException(String message) { super(message); diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java b/dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java similarity index 63% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java rename to dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java index 1d9c9b3..ce9eca7 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java @@ -1,6 +1,9 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public class LinkRegistrationException extends LinkException { + public LinkRegistrationException() { + } + public LinkRegistrationException(String message) { super(message); } diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java b/dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java similarity index 63% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java rename to dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java index f04851c..8205cc3 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java @@ -1,6 +1,9 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public class NotLinkException extends LinkException { + public NotLinkException() { + } + public NotLinkException(String message) { super(message); } diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java new file mode 100644 index 0000000..a12cc2c --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public class SourceNotSupportedException extends LinkException { + public SourceNotSupportedException() { + } + + public SourceNotSupportedException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java new file mode 100644 index 0000000..011d85d --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java @@ -0,0 +1,19 @@ +package edu.java.dto.utils.sources.info; + +public class GithubInfo extends SourceInfo { + private final String author; + private final String repository; + + public GithubInfo(String author, String repository) { + this.author = author; + this.repository = repository; + } + + public String getAuthor() { + return author; + } + + public String getRepository() { + return repository; + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java new file mode 100644 index 0000000..aeeff17 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java @@ -0,0 +1,5 @@ +package edu.java.dto.utils.sources.info; + +public abstract class SourceInfo { + +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java new file mode 100644 index 0000000..b9269f8 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java @@ -0,0 +1,13 @@ +package edu.java.dto.utils.sources.info; + +public class StackoverflowInfo extends SourceInfo { + private final long questionId; + + public StackoverflowInfo(long questionId) { + this.questionId = questionId; + } + + public long getQuestionId() { + return questionId; + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java new file mode 100644 index 0000000..ae915d9 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java @@ -0,0 +1,36 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.SourceInfo; +import java.net.URI; +import java.util.Set; + +public abstract class SourceParser { + protected SourceParser next; + + public void setNext(SourceParser next) { + this.next = next; + } + + public SourceInfo parse(URI url) throws SourceNotSupportedException { + try { + return parseSource(url); + } catch (SourceNotSupportedException e) { + if (next != null) { + return parse(url); + } + throw e; + } + } + + abstract SourceInfo parseSource(URI url) throws SourceNotSupportedException; + + public static SourceParser buildChain(Set parsers) { + SourceParser first = null; + for (SourceParser parser : parsers) { + parser.setNext(first); + first = parser; + } + return first; + } +} diff --git a/pom.xml b/pom.xml index 88935b8..02e04cf 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ bot scrapper - api_dto + dto diff --git a/scrapper/pom.xml b/scrapper/pom.xml index f1e90e3..b8833da 100644 --- a/scrapper/pom.xml +++ b/scrapper/pom.xml @@ -140,7 +140,7 @@ edu.java - api_dto + dto 0.1 compile diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index 7926fba..25fff0f 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.controller; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.service.ChatService; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index a57af05..6f40192 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -1,10 +1,10 @@ package edu.java.scrapper.api.controller; -import edu.java.api_dto.scrapper.AddLinkRequest; -import edu.java.api_dto.scrapper.ApiErrorResponse; -import edu.java.api_dto.scrapper.LinkResponse; -import edu.java.api_dto.scrapper.ListLinksResponse; -import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.dto.api.scrapper.AddLinkRequest; +import edu.java.dto.api.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.LinkResponse; +import edu.java.dto.api.scrapper.ListLinksResponse; +import edu.java.dto.api.scrapper.RemoveLinkRequest; import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.exception.link.LinkAdditionException; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java index 1924aab..d9a323f 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java @@ -2,6 +2,7 @@ import edu.java.scrapper.api.domain.dto.Link; import java.net.URI; +import java.time.OffsetDateTime; import java.util.List; import java.util.Optional; @@ -17,4 +18,8 @@ public interface LinkRepository { void remove(long id); List findAll(); + + List findAllWithLastCheckOlderThan(OffsetDateTime time); + + void update(Link link); } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java index ce81751..7601691 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java @@ -3,6 +3,7 @@ import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.domain.repository.LinkRepository; import java.net.URI; +import java.time.OffsetDateTime; import java.util.List; import java.util.Optional; import org.springframework.jdbc.core.simple.JdbcClient; @@ -66,4 +67,21 @@ public List findAll() { .query(Link.class) .list(); } + + @Override + public List findAllWithLastCheckOlderThan(OffsetDateTime time) { + return client.sql("select * from link where link.last_check < ?") + .param(time) + .query(Link.class) + .list(); + } + + @Override + public void update(Link link) { + client.sql("update link set last_update = ?, last_check = ? where id = ?") + .param(link.lastUpdate()) + .param(link.lastCheck()) + .param(link.id()) + .update(); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index 811b2e6..3a14e19 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.exception.chat; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java index 3392519..d17e833 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.exception.link; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java index 455271f..3e79981 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java @@ -3,17 +3,20 @@ import edu.java.scrapper.api.domain.repository.ChatRepository; import edu.java.scrapper.api.domain.repository.LinkRepository; import edu.java.scrapper.api.domain.repository.SubscriptionRepository; +import edu.java.scrapper.configuration.ApplicationConfig; public abstract class ScrapperService { + protected final ApplicationConfig config; protected final ChatRepository chatRepo; protected final LinkRepository linkRepo; protected final SubscriptionRepository subscriptionRepo; protected ScrapperService( - ChatRepository chatRepo, + ApplicationConfig config, ChatRepository chatRepo, LinkRepository linkRepo, SubscriptionRepository subscriptionRepo ) { + this.config = config; this.chatRepo = chatRepo; this.linkRepo = linkRepo; this.subscriptionRepo = subscriptionRepo; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index a7d5781..da3b543 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -9,6 +9,7 @@ import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.service.ChatService; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; @@ -19,10 +20,11 @@ public class JdbcChatService extends ScrapperService implements ChatService { @Autowired protected JdbcChatService( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java index 3c0a1b0..d8be5b7 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -11,6 +11,7 @@ import edu.java.scrapper.api.exception.link.LinkNotFoundException; import edu.java.scrapper.api.service.LinkService; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; import java.net.URI; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -25,10 +26,11 @@ public class JdbcLinkService extends ScrapperService implements LinkService { @Autowired protected JdbcLinkService( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index 14fbde1..f832dc7 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -1,10 +1,17 @@ package edu.java.scrapper.api.service.jdbc; +import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; import edu.java.scrapper.api.service.LinkUpdater; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -13,14 +20,23 @@ public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { @Autowired protected JdbcLinkUpdater( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override public int update() { - return 0; + Duration checkDelay = config.scheduler().forceCheckDelay(); + OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS) + .minus(checkDelay); + List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck); + int countUpdates = 0; + for (Link link : linksNeedToCheck) { + + } + return countUpdates; } } diff --git a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java index 3e78df3..378c9be 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java @@ -1,6 +1,6 @@ package edu.java.scrapper.client.bot; -import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.dto.api.bot.ApiErrorResponse; import lombok.Getter; @Getter diff --git a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java index 4ea3155..6cba112 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java @@ -1,8 +1,8 @@ package edu.java.scrapper.client.bot; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api_dto.bot.ApiErrorResponse; -import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.dto.api.bot.ApiErrorResponse; +import edu.java.dto.api.bot.LinkUpdateRequest; import edu.java.scrapper.client.AbstractClient; import lombok.NonNull; import org.springframework.http.HttpStatusCode; diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index b65ec42..170d0be 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -2,7 +2,7 @@ app: scheduler: enable: true interval: 10000 - force-check-delay: 10000 + force-check-delay: 300000 resources: base-url: From c32e393a621ce4ba6de2f391f919ecb2ade301a1 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 17:44:00 +0300 Subject: [PATCH 11/34] feat: github and stackoverflow link parsers realizations --- .../bot/client/service/ScrapperService.java | 2 +- .../java/bot/configuration/CommandConfig.java | 21 +++++++ .../command/AbstractServiceCommand.java | 5 +- .../command/components/ListCommand.java | 5 +- .../command/components/StartCommand.java | 5 +- .../command/components/TrackCommand.java | 14 ++--- .../command/components/UntrackCommand.java | 14 ++--- .../java/edu/java/dto/utils/LinkParser.java | 56 +++++++++++++++---- .../exception/BadSourceUrlException.java | 10 ++++ .../dto/utils/exception/SourceException.java | 10 ++++ .../SourceNotSupportedException.java | 2 +- .../dto/utils/sources/info/GithubInfo.java | 18 +++--- .../utils/sources/parsers/GithubParser.java | 31 ++++++++++ .../utils/sources/parsers/SourceParser.java | 9 +-- .../sources/parsers/StackoverflowParser.java | 30 ++++++++++ 15 files changed, 185 insertions(+), 47 deletions(-) create mode 100644 bot/src/main/java/edu/java/bot/configuration/CommandConfig.java create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/SourceException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java diff --git a/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java index f3d8c22..abbce8d 100644 --- a/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java +++ b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java @@ -15,7 +15,7 @@ public ScrapperService() { public boolean isUserRegistered(Long userId) { // TODO: добавить работу с БД через scrapper log.info("%s. Проверка регистрации пользователя %d".formatted(LocalDateTime.now(), userId)); - return false; + return true; } public void registerUser(Long userId) { diff --git a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java new file mode 100644 index 0000000..5dd6c9a --- /dev/null +++ b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java @@ -0,0 +1,21 @@ +package edu.java.bot.configuration; + +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.sources.parsers.GithubParser; +import edu.java.dto.utils.sources.parsers.SourceParser; +import edu.java.dto.utils.sources.parsers.StackoverflowParser; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CommandConfig { + + @Bean + public LinkParser linkParser() { + return new LinkParser(SourceParser.buildChain(Set.of( + new GithubParser(), + new StackoverflowParser() + ))); + } +} diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index a78798c..2f43d5f 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,12 +1,15 @@ package edu.java.bot.telegram.command; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; + protected final CommandConfig config; - public AbstractServiceCommand(ScrapperService service) { + public AbstractServiceCommand(ScrapperService service, CommandConfig config) { this.service = service; + this.config = config; } public void setService(ScrapperService service) { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 1f6cd78..4029579 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,6 +1,7 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; @@ -14,8 +15,8 @@ @Order(5) public class ListCommand extends AbstractServiceCommand { - public ListCommand(ScrapperService service) { - super(service); + public ListCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index e4f0af0..3fed484 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,6 +1,7 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.parameter.ParameterException; @@ -11,8 +12,8 @@ @Order(1) public class StartCommand extends AbstractServiceCommand { - public StartCommand(ScrapperService service) { - super(service); + public StartCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 72d88b2..f4766ab 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,14 +1,13 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; -import edu.java.dto.utils.exception.NotLinkException; -import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -16,8 +15,8 @@ @Order(3) public class TrackCommand extends AbstractServiceCommand { - public TrackCommand(ScrapperService service) { - super(service); + public TrackCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override @@ -32,11 +31,10 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, - SourceNotSupportedException { + throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - new LinkParser(null).parse(link); + config.linkParser().parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index c566083..75d5cd9 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,14 +1,13 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; -import edu.java.dto.utils.exception.NotLinkException; -import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -16,8 +15,8 @@ @Order(4) public class UntrackCommand extends AbstractServiceCommand { - public UntrackCommand(ScrapperService service) { - super(service); + public UntrackCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override @@ -32,11 +31,10 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, - SourceNotSupportedException { + throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - new LinkParser(null).parse(link); + config.linkParser().parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java index e4dd733..9a892ef 100644 --- a/dto/src/main/java/edu/java/dto/utils/LinkParser.java +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -1,34 +1,68 @@ package edu.java.dto.utils; import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceException; import edu.java.dto.utils.exception.SourceNotSupportedException; import edu.java.dto.utils.sources.info.SourceInfo; import edu.java.dto.utils.sources.parsers.SourceParser; +import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; public class LinkParser { + private static final String NOT_LINK_MESSAGE = "Неверная ссылка"; + private final SourceParser parser; + public LinkParser() { + parser = null; + } + public LinkParser(SourceParser parser) { this.parser = parser; } - public LinkInfo parse(String link) throws NotLinkException, SourceNotSupportedException { - String url = link.toLowerCase(); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - throw new NotLinkException("У ссылки отсутствует протокол"); - } - URI parsedUrl; + public LinkInfo parse(String link) throws NotLinkException, SourceException { + URI uri = tryMakeURI(link); + checkIsLinkAvailable(uri); + SourceInfo sourceInfo = tryParseSource(uri); + return new LinkInfo(uri, sourceInfo); + } + + private static URI tryMakeURI(String link) throws NotLinkException { try { - parsedUrl = new URI(link); + return new URI(link); } catch (URISyntaxException e) { - throw new NotLinkException("Неверная ссылка"); + throw new NotLinkException(NOT_LINK_MESSAGE); } + } + + private static void checkIsLinkAvailable(URI uri) throws NotLinkException { + HttpURLConnection connection = null; + try { + URL url = uri.toURL(); + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("HEAD"); + int response = connection.getResponseCode(); + if (response != HttpURLConnection.HTTP_OK) { + throw new NotLinkException("Ссылка не существует или недоступна"); + } + } catch (NotLinkException e) { + throw e; + } catch (Exception e) { + throw new NotLinkException(NOT_LINK_MESSAGE); + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } + + private SourceInfo tryParseSource(URI uri) throws SourceException { try { - SourceInfo source = parser.parse(parsedUrl); - return new LinkInfo(parsedUrl, source); - } catch (SourceNotSupportedException e) { + return parser.parse(uri); + } catch (NullPointerException | SourceNotSupportedException e) { throw new SourceNotSupportedException("Данный ресурс не поддерживается"); } } diff --git a/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java b/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java new file mode 100644 index 0000000..21bc38a --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public class BadSourceUrlException extends SourceException { + public BadSourceUrlException() { + } + + public BadSourceUrlException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java new file mode 100644 index 0000000..6a1b06f --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public abstract class SourceException extends LinkException { + public SourceException() { + } + + public SourceException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java index a12cc2c..7dc2801 100644 --- a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java @@ -1,6 +1,6 @@ package edu.java.dto.utils.exception; -public class SourceNotSupportedException extends LinkException { +public class SourceNotSupportedException extends SourceException { public SourceNotSupportedException() { } diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java index 011d85d..9262dfb 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java @@ -1,19 +1,19 @@ package edu.java.dto.utils.sources.info; public class GithubInfo extends SourceInfo { - private final String author; - private final String repository; + private final String owner; + private final String repo; - public GithubInfo(String author, String repository) { - this.author = author; - this.repository = repository; + public GithubInfo(String owner, String repo) { + this.owner = owner; + this.repo = repo; } - public String getAuthor() { - return author; + public String getOwner() { + return owner; } - public String getRepository() { - return repository; + public String getRepo() { + return repo; } } diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java new file mode 100644 index 0000000..62ec730 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java @@ -0,0 +1,31 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.BadSourceUrlException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.GithubInfo; +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GithubParser extends SourceParser { + private static final String BASE_PATTERN = "^https?://github.com"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.)?$"; + + @Override + GithubInfo parseSource(URI uri) throws SourceException { + String link = uri.toString(); + Pattern pattern = Pattern.compile(LINK_PATTERN); + Matcher matcher = pattern.matcher(link); + if (matcher.find()) { + String owner = matcher.group(1); + String repo = matcher.group(2); + return new GithubInfo(owner, repo); + } + if (link.matches(BASE_PATTERN + ".*")) { + throw new BadSourceUrlException("Некорретная ссылка для GitHub, требуется формат\n" + + "\"http(-s)://github.com/{owner}/{repo}[/...]\""); + } + throw new SourceNotSupportedException(); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java index ae915d9..9a72fcf 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java @@ -1,5 +1,6 @@ package edu.java.dto.utils.sources.parsers; +import edu.java.dto.utils.exception.SourceException; import edu.java.dto.utils.exception.SourceNotSupportedException; import edu.java.dto.utils.sources.info.SourceInfo; import java.net.URI; @@ -12,18 +13,18 @@ public void setNext(SourceParser next) { this.next = next; } - public SourceInfo parse(URI url) throws SourceNotSupportedException { + public SourceInfo parse(URI uri) throws SourceException { try { - return parseSource(url); + return parseSource(uri); } catch (SourceNotSupportedException e) { if (next != null) { - return parse(url); + return next.parse(uri); } throw e; } } - abstract SourceInfo parseSource(URI url) throws SourceNotSupportedException; + abstract SourceInfo parseSource(URI uri) throws SourceException; public static SourceParser buildChain(Set parsers) { SourceParser first = null; diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java new file mode 100644 index 0000000..b463a67 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java @@ -0,0 +1,30 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.BadSourceUrlException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StackoverflowParser extends SourceParser { + private static final String BASE_PATTERN = "^https?://stackoverflow.com/questions"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)(/.)?$"; + + @Override + StackoverflowInfo parseSource(URI uri) throws SourceException { + String link = uri.toString(); + Pattern pattern = Pattern.compile(LINK_PATTERN); + Matcher matcher = pattern.matcher(link); + if (matcher.find()) { + long questionId = Long.parseLong(matcher.group(1)); + return new StackoverflowInfo(questionId); + } + if (link.matches(BASE_PATTERN + ".*")) { + throw new BadSourceUrlException("Некорретная ссылка для Stackoverflow, требуется формат\n" + + "\"http(-s)://stackoverflow.com/{questionId}[/...]\""); + } + throw new SourceNotSupportedException(); + } +} From 9f5d0b0b0b70f9fc352d4ab42ac4c552fcc7f48c Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 17:57:27 +0300 Subject: [PATCH 12/34] fix: change tests according to source parsers --- .../java/edu/java/bot/BotApplicationTest.java | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index e9e79ee..51bea96 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -11,12 +11,14 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.dto.utils.exception.BadSourceUrlException; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import edu.java.dto.utils.exception.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -122,10 +124,10 @@ void helpTest() throws UnregisteredUserException, ParameterException, CommandExc void trackTest() throws UnregisteredUserException, ParameterException, CommandException, LinkException { service.setUserRegistered(true); service.setLinks(List.of()); - setMessage("/track https://github.com/cyberpanncake"); + setMessage("/track https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); String expected = "Ссылка добавлена в отслеживаемые"; - String actual = command.execute(updateMock); + String actual = command.execute(updateMock); Assertions.assertEquals(expected, actual); } @@ -138,18 +140,36 @@ void notLinkExceptionTest() throws CommandException { Assertions.assertThrows(NotLinkException.class, () -> command.execute(updateMock)); } + @Test + void sourceNotSupportedExceptionTest() throws CommandException { + service.setUserRegistered(true); + service.setLinks(List.of()); + setMessage("/track https://google.com"); + Command command = AbstractCommand.parse(updateMock, config.commands()); + Assertions.assertThrows(SourceNotSupportedException.class, () -> command.execute(updateMock)); + } + + @Test + void badSourceUrlExceptionTest() throws CommandException { + service.setUserRegistered(true); + service.setLinks(List.of()); + setMessage("/track https://github.com/cyberpanncake"); + Command command = AbstractCommand.parse(updateMock, config.commands()); + Assertions.assertThrows(BadSourceUrlException.class, () -> command.execute(updateMock)); + } + @Test void unregisteredUserExceptionTest() throws CommandException { service.setUserRegistered(false); service.setLinks(List.of()); - setMessage("/track https://github.com/cyberpanncake"); + setMessage("/track https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); Assertions.assertThrows(UnregisteredUserException.class, () -> command.execute(updateMock)); } @Test void linkRegisteredExceptionTest() throws CommandException { - String link = "https://github.com/cyberpanncake"; + String link = "https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"; service.setUserRegistered(true); service.setLinks(List.of(link)); setMessage("/track " + link); @@ -159,7 +179,7 @@ void linkRegisteredExceptionTest() throws CommandException { @Test void untrackTest() throws UnregisteredUserException, ParameterException, CommandException, LinkException { - String link = "https://github.com/cyberpanncake"; + String link = "https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"; service.setUserRegistered(true); service.setLinks(List.of(link)); setMessage("/untrack " + link); @@ -173,7 +193,7 @@ void untrackTest() throws UnregisteredUserException, ParameterException, Command void linkNotRegisteredExceptionTest() throws CommandException { service.setUserRegistered(true); service.setLinks(List.of()); - setMessage("/untrack https://github.com/cyberpanncake"); + setMessage("/untrack https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); Assertions.assertThrows(LinkRegistrationException.class, () -> command.execute(updateMock)); } From 7ad203158144b8477d079f36735e9de81a379744 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 18:11:54 +0300 Subject: [PATCH 13/34] feat: add setting to link parser, allows set http response check --- .../edu/java/bot/configuration/CommandConfig.java | 2 +- dto/src/main/java/edu/java/dto/utils/LinkParser.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java index 5dd6c9a..94af187 100644 --- a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java @@ -16,6 +16,6 @@ public LinkParser linkParser() { return new LinkParser(SourceParser.buildChain(Set.of( new GithubParser(), new StackoverflowParser() - ))); + )), true); } } diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java index 9a892ef..b1e2eef 100644 --- a/dto/src/main/java/edu/java/dto/utils/LinkParser.java +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -12,20 +12,24 @@ public class LinkParser { private static final String NOT_LINK_MESSAGE = "Неверная ссылка"; - private final SourceParser parser; + private final boolean checkIsLinkAvailable; - public LinkParser() { + public LinkParser(boolean checkLinkAvailable) { + this.checkIsLinkAvailable = checkLinkAvailable; parser = null; } - public LinkParser(SourceParser parser) { + public LinkParser(SourceParser parser, boolean checkIsLinkAvailable) { this.parser = parser; + this.checkIsLinkAvailable = checkIsLinkAvailable; } public LinkInfo parse(String link) throws NotLinkException, SourceException { URI uri = tryMakeURI(link); - checkIsLinkAvailable(uri); + if (checkIsLinkAvailable) { + checkIsLinkAvailable(uri); + } SourceInfo sourceInfo = tryParseSource(uri); return new LinkInfo(uri, sourceInfo); } From f1b16f8aa062c29ae27463636a8040a8178a47a0 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 21:55:22 +0300 Subject: [PATCH 14/34] fix: parsers regex --- .../java/edu/java/dto/utils/sources/parsers/GithubParser.java | 2 +- .../edu/java/dto/utils/sources/parsers/StackoverflowParser.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java index 62ec730..6e344c7 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java @@ -10,7 +10,7 @@ public class GithubParser extends SourceParser { private static final String BASE_PATTERN = "^https?://github.com"; - private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.)?$"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.*)?$"; @Override GithubInfo parseSource(URI uri) throws SourceException { diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java index b463a67..3cd5935 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java @@ -10,7 +10,7 @@ public class StackoverflowParser extends SourceParser { private static final String BASE_PATTERN = "^https?://stackoverflow.com/questions"; - private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)(/.)?$"; + private static final String LINK_PATTERN = BASE_PATTERN + "/([0-9]+?)(/.*)?$"; @Override StackoverflowInfo parseSource(URI uri) throws SourceException { From 75533c3489a05050bc8fba95d109b6006ac5b87e Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 22:24:17 +0300 Subject: [PATCH 15/34] feat: tasks 3-4 (getting updates from sources and sending them to the bot) --- .../repository/SubscriptionRepository.java | 6 +- .../jdbc/JdbcSubscriptionRepository.java | 27 ++++++- .../api/service/jdbc/JdbcChatService.java | 2 +- .../api/service/jdbc/JdbcLinkUpdater.java | 75 +++++++++++++++++-- .../scrapper/client/sources/GithubClient.java | 6 +- .../configuration/LinkParserConfig.java | 21 ++++++ .../shedule/LinkUpdaterScheduler.java | 10 ++- .../scrapper/shedule/update/dto/Update.java | 13 ++++ .../shedule/update/sources/GithubUpdater.java | 22 ++++++ .../shedule/update/sources/SourceUpdater.java | 28 +++++++ .../update/sources/StackoverflowUpdater.java | 22 ++++++ 11 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java index c99a9cd..63c98d9 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java @@ -16,9 +16,13 @@ public interface SubscriptionRepository { List findAll(); - List findAllByChat(long chatId); + List findAllByChat(Chat chat); + + List findAllByLink(Link link); boolean linkNotFollowedByAnyone(long linkId); List findAllLinksByChat(Chat chat); + + List findAllChatsByLink(Link link); } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java index 31e8f7d..91b9f27 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -60,13 +60,23 @@ public List findAll() { } @Override - public List findAllByChat(long chatId) { + public List findAllByChat(Chat chat) { return client.sql("select * from subscription where chat_id = ?") - .param(chatId) + .param(chat.id()) + .query(Subscription.class) + .list(); + } + + @SuppressWarnings("MultipleStringLiterals") + @Override + public List findAllByLink(Link link) { + return client.sql("select * from subscription where link_id = ?") + .param(link.id()) .query(Subscription.class) .list(); } + @SuppressWarnings("MultipleStringLiterals") @Override public boolean linkNotFollowedByAnyone(long linkId) { List subscriptions = client.sql("select * from subscription where link_id = ?") @@ -88,4 +98,17 @@ public List findAllLinksByChat(Chat chat) { .query(Link.class) .list(); } + + @Override + public List findAllChatsByLink(Link link) { + return client.sql(""" + select chat.* + from chat + inner join subscription on chat.id = subscription.chat_id + where + subscription.link_id = ?""") + .param(link.id()) + .query(Chat.class) + .list(); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index da3b543..7d001a0 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -42,7 +42,7 @@ public void unregister(long tgId) throws ChatNotFoundException { if (chat.isEmpty()) { throw new ChatNotFoundException(); } - List subscriptions = subscriptionRepo.findAllByChat(chat.get().id()); + List subscriptions = subscriptionRepo.findAllByChat(chat.get()); for (Subscription subscription : subscriptions) { subscriptionRepo.remove(subscription); if (subscriptionRepo.linkNotFollowedByAnyone(subscription.linkId())) { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index f832dc7..7bf9108 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -1,42 +1,107 @@ package edu.java.scrapper.api.service.jdbc; +import edu.java.dto.api.bot.LinkUpdateRequest; +import edu.java.dto.utils.LinkInfo; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.scrapper.api.domain.dto.Chat; import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; import edu.java.scrapper.api.service.LinkUpdater; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.configuration.ApplicationConfig; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.configuration.LinkParserConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import edu.java.scrapper.shedule.update.sources.SourceUpdater; import java.time.Duration; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { + private final ClientConfig clientConfig; + private final LinkParserConfig parserConfig; @Autowired protected JdbcLinkUpdater( - ApplicationConfig config, + ApplicationConfig config, LinkParserConfig parserConfig, + ClientConfig clientConfig, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { super(config, chatRepo, linkRepo, subscriptionRepo); + this.parserConfig = parserConfig; + this.clientConfig = clientConfig; } @Override public int update() { Duration checkDelay = config.scheduler().forceCheckDelay(); - OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS) - .minus(checkDelay); - List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck); + OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck.minus(checkDelay)); int countUpdates = 0; for (Link link : linksNeedToCheck) { - + linkRepo.update(new Link(link.id(), link.url(), link.lastUpdate(), lastCheck)); + try { + LinkInfo linkInfo = parserConfig.linkParser().parse(link.url().toString()); + Optional update = getUpdateFromSource(linkInfo); + if (update.isPresent() && update.get().getCreatedAt().isAfter(link.lastUpdate())) { + countUpdates++; + linkRepo.update(new Link(link.id(), link.url(), update.get().getCreatedAt(), lastCheck)); + processLinkUpdate(update.get(), link); + } + } catch (NotLinkException | SourceException | ResponseException e) { + removeCorruptedLinkWithSubscriptions(link); + } } return countUpdates; } + + private void processLinkUpdate(Update update, Link link) throws SourceException, NotLinkException { + List subscribers = subscriptionRepo.findAllChatsByLink(link); + if (subscribers.isEmpty()) { + linkRepo.remove(link.url()); + return; + } + clientConfig.botClient().sendUpdate(new LinkUpdateRequest( + link.id(), + link.url(), + "Новое обновление по ссылке\n%s\nСоздано в %s" + .formatted(link.url(), update.getCreatedAt()), + subscribers.stream().map(Chat::tgId).toArray(Long[]::new) + )); + } + + private Optional getUpdateFromSource(LinkInfo linkInfo) throws ResponseException { + SourceUpdater updater = SourceUpdater.getUpdaterForSource(clientConfig, linkInfo.source()); + if (updater != null) { + return updater.getUpdate(linkInfo.source()); + } + return Optional.empty(); + } + + private void removeCorruptedLinkWithSubscriptions(Link link) { + List subscribers = subscriptionRepo.findAllChatsByLink(link); + for (Chat subscriber : subscribers) { + Subscription subscription = new Subscription(subscriber.id(), link.id()); + subscriptionRepo.remove(subscription); + } + linkRepo.remove(link.url()); + clientConfig.botClient().sendUpdate(new LinkUpdateRequest( + link.id(), + link.url(), + "Ссылка\n" + link.url() + "\n больше не доступна, поэтому она удалена из Ваших подписок", + subscribers.stream().map(Chat::tgId).toArray(Long[]::new) + )); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index dd696e8..365e794 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -15,12 +15,12 @@ public GithubClient(String baseUrl, ObjectMapper mapper) { super(baseUrl, mapper); } - public Optional getUpdate(String author, String repository) throws ResponseException { + public Optional getUpdate(String owner, String repo) throws ResponseException { Mono jsonNodeMono = client.get() .uri(uriBuilder -> uriBuilder - .path("/repos/{author}/{repo}/events") + .path("/repos/{owner}/{repo}/events") .queryParam("per_page", 1) - .build(author, repository)) + .build(owner, repo)) .retrieve() .bodyToMono(JsonNode.class); try { diff --git a/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java new file mode 100644 index 0000000..852f10f --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java @@ -0,0 +1,21 @@ +package edu.java.scrapper.configuration; + +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.sources.parsers.GithubParser; +import edu.java.dto.utils.sources.parsers.SourceParser; +import edu.java.dto.utils.sources.parsers.StackoverflowParser; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LinkParserConfig { + + @Bean + public LinkParser linkParser() { + return new LinkParser(SourceParser.buildChain(Set.of( + new GithubParser(), + new StackoverflowParser() + )), false); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java index a7e2a78..b399eaf 100644 --- a/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java @@ -1,6 +1,8 @@ package edu.java.scrapper.shedule; +import edu.java.scrapper.api.service.LinkUpdater; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -9,9 +11,15 @@ @ConditionalOnProperty(value = "app.scheduler.enable", matchIfMissing = true) @Slf4j public class LinkUpdaterScheduler { + private final LinkUpdater updater; + + @Autowired + public LinkUpdaterScheduler(LinkUpdater updater) { + this.updater = updater; + } @Scheduled(fixedDelayString = "${app.scheduler.interval}") public void update() { - log.info("Обновление"); + updater.update(); } } diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java new file mode 100644 index 0000000..fee75d9 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java @@ -0,0 +1,13 @@ +package edu.java.scrapper.shedule.update.dto; + +import java.time.OffsetDateTime; +import lombok.Getter; + +@Getter +public class Update { + protected final OffsetDateTime createdAt; + + public Update(OffsetDateTime createdAt) { + this.createdAt = createdAt; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java new file mode 100644 index 0000000..dd1e1b3 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java @@ -0,0 +1,22 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.GithubInfo; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.dto.GithubResponse; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public class GithubUpdater extends SourceUpdater { + public GithubUpdater(ClientConfig config) { + super(config); + } + + @Override + public Optional getUpdate(SourceInfo sourceInfo) throws ResponseException { + GithubInfo info = (GithubInfo) sourceInfo; + Optional response = config.githubClient().getUpdate(info.getOwner(), info.getRepo()); + return response.map(stackoverflowResponse -> new Update(stackoverflowResponse.createdAt())); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java new file mode 100644 index 0000000..a3c5e57 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java @@ -0,0 +1,28 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.GithubInfo; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public abstract class SourceUpdater { + protected final ClientConfig config; + + protected SourceUpdater(ClientConfig config) { + this.config = config; + } + + public abstract Optional getUpdate(SourceInfo sourceInfo) throws ResponseException; + + public static SourceUpdater getUpdaterForSource(ClientConfig config, SourceInfo sourceInfo) { + if (sourceInfo instanceof GithubInfo) { + return new GithubUpdater(config); + } else if (sourceInfo instanceof StackoverflowInfo) { + return new StackoverflowUpdater(config); + } + return null; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java new file mode 100644 index 0000000..b4b6a19 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java @@ -0,0 +1,22 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public class StackoverflowUpdater extends SourceUpdater { + public StackoverflowUpdater(ClientConfig config) { + super(config); + } + + @Override + public Optional getUpdate(SourceInfo sourceInfo) throws ResponseException { + StackoverflowInfo info = (StackoverflowInfo) sourceInfo; + Optional response = config.stackoverflowClient().getUpdate(info.getQuestionId()); + return response.map(stackoverflowResponse -> new Update(stackoverflowResponse.lastActivityDate())); + } +} From f6a83081617b17b655c4fe0401defe641a77a880 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Fri, 5 Apr 2024 00:09:49 +0300 Subject: [PATCH 16/34] fix: remove config injection in commands, add bean injection instead --- .../bot/telegram/command/AbstractServiceCommand.java | 5 +---- .../bot/telegram/command/components/ListCommand.java | 5 ++--- .../bot/telegram/command/components/StartCommand.java | 5 ++--- .../bot/telegram/command/components/TrackCommand.java | 10 ++++++---- .../telegram/command/components/UntrackCommand.java | 10 ++++++---- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index 2f43d5f..a78798c 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,15 +1,12 @@ package edu.java.bot.telegram.command; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; - protected final CommandConfig config; - public AbstractServiceCommand(ScrapperService service, CommandConfig config) { + public AbstractServiceCommand(ScrapperService service) { this.service = service; - this.config = config; } public void setService(ScrapperService service) { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 4029579..1f6cd78 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,7 +1,6 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; @@ -15,8 +14,8 @@ @Order(5) public class ListCommand extends AbstractServiceCommand { - public ListCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public ListCommand(ScrapperService service) { + super(service); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index 3fed484..e4f0af0 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,7 +1,6 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.parameter.ParameterException; @@ -12,8 +11,8 @@ @Order(1) public class StartCommand extends AbstractServiceCommand { - public StartCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public StartCommand(ScrapperService service) { + super(service); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index f4766ab..09a061c 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,11 +1,11 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.LinkParser; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import org.springframework.core.annotation.Order; @@ -14,9 +14,11 @@ @Component @Order(3) public class TrackCommand extends AbstractServiceCommand { + private final LinkParser parser; - public TrackCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public TrackCommand(ScrapperService service, LinkParser parser) { + super(service); + this.parser = parser; } @Override @@ -34,7 +36,7 @@ protected String doAction(Long userId, String[] params) throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - config.linkParser().parse(link); + parser.parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 75d5cd9..c828b4f 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,11 +1,11 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.LinkParser; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import org.springframework.core.annotation.Order; @@ -14,9 +14,11 @@ @Component @Order(4) public class UntrackCommand extends AbstractServiceCommand { + private final LinkParser parser; - public UntrackCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public UntrackCommand(ScrapperService service, LinkParser parser) { + super(service); + this.parser = parser; } @Override @@ -34,7 +36,7 @@ protected String doAction(Long userId, String[] params) throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - config.linkParser().parse(link); + parser.parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); From a939667312f6d1ca00fc790cc1a5fe184bd27e34 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Fri, 5 Apr 2024 00:21:20 +0300 Subject: [PATCH 17/34] fix: add transactional annotations to jdbc services --- .../edu/java/scrapper/api/service/jdbc/JdbcChatService.java | 2 ++ .../edu/java/scrapper/api/service/jdbc/JdbcLinkService.java | 2 ++ .../edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index 7d001a0..47a2b31 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -14,7 +14,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcChatService extends ScrapperService implements ChatService { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java index d8be5b7..ce6a854 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -20,7 +20,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcLinkService extends ScrapperService implements LinkService { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index 7bf9108..7342648 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -26,7 +26,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { private final ClientConfig clientConfig; From 9fee4f640f49be3da48532b43d3986d66f0d8952 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:07:52 +0300 Subject: [PATCH 18/34] feat: add BotClient in scrapper --- api_dto/pom.xml | 33 +++++++++++++++++ .../java/api_dto/bot}/ApiErrorResponse.java | 5 ++- .../java/api_dto/bot}/LinkUpdateRequest.java | 7 ++-- .../api_dto/scrapper}/AddLinkRequest.java | 2 +- .../api_dto/scrapper}/ApiErrorResponse.java | 5 ++- .../java/api_dto/scrapper}/LinkResponse.java | 4 +-- .../api_dto/scrapper}/ListLinksResponse.java | 4 +-- .../api_dto/scrapper}/RemoveLinkRequest.java | 2 +- bot/pom.xml | 5 +++ .../bot/api/controller/UpdateController.java | 5 ++- .../api/exception/ExceptionApiHandler.java | 25 ++++++------- .../bot/{api => }/client/AbstractClient.java | 2 +- .../bot/{api => }/client/ScrapperClient.java | 2 +- ...ClientConfig.java => BotClientConfig.java} | 4 +-- pom.xml | 1 + scrapper/pom.xml | 6 ++++ .../java/edu/java/api/client/BotClient.java | 12 ------- .../java/api/controller/ChatController.java | 2 +- .../java/api/controller/LinkController.java | 14 ++++---- .../chat/ChatExceptionApiHandler.java | 21 +++++++---- .../link/LinkExceptionApiHandler.java | 21 +++++++---- .../edu/java/client/bot/BotApiException.java | 15 ++++++++ .../java/edu/java/client/bot/BotClient.java | 35 +++++++++++++++++++ .../client/{ => sources}/GithubClient.java | 3 +- .../{ => sources}/ResponseException.java | 2 +- .../{ => sources}/StackoverflowClient.java | 3 +- .../edu/java/configuration/ClientConfig.java | 11 +++--- .../edu/java/client/GithubClientTest.java | 2 ++ .../edu/java/client/ObjectMapperTest.java | 28 +++++++++++++++ .../java/client/StackoverflowClientTest.java | 2 ++ 30 files changed, 202 insertions(+), 81 deletions(-) create mode 100644 api_dto/pom.xml rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/bot}/ApiErrorResponse.java (79%) rename {bot/src/main/java/edu/java/bot/api/dto => api_dto/src/main/java/edu/java/api_dto/bot}/LinkUpdateRequest.java (78%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/AddLinkRequest.java (86%) rename {bot/src/main/java/edu/java/bot/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/ApiErrorResponse.java (78%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/LinkResponse.java (81%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/ListLinksResponse.java (76%) rename {scrapper/src/main/java/edu/java/api/dto => api_dto/src/main/java/edu/java/api_dto/scrapper}/RemoveLinkRequest.java (86%) rename bot/src/main/java/edu/java/bot/{api => }/client/AbstractClient.java (92%) rename bot/src/main/java/edu/java/bot/{api => }/client/ScrapperClient.java (88%) rename bot/src/main/java/edu/java/bot/configuration/{ClientConfig.java => BotClientConfig.java} (89%) delete mode 100644 scrapper/src/main/java/edu/java/api/client/BotClient.java create mode 100644 scrapper/src/main/java/edu/java/client/bot/BotApiException.java create mode 100644 scrapper/src/main/java/edu/java/client/bot/BotClient.java rename scrapper/src/main/java/edu/java/client/{ => sources}/GithubClient.java (94%) rename scrapper/src/main/java/edu/java/client/{ => sources}/ResponseException.java (62%) rename scrapper/src/main/java/edu/java/client/{ => sources}/StackoverflowClient.java (95%) create mode 100644 scrapper/src/test/java/edu/java/client/ObjectMapperTest.java diff --git a/api_dto/pom.xml b/api_dto/pom.xml new file mode 100644 index 0000000..25f8f90 --- /dev/null +++ b/api_dto/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + edu.java + root + ${revision} + + + api_dto + ${revision} + + + + com.fasterxml.jackson.core + jackson-databind + 2.15.3 + + + org.springframework.boot + spring-boot-starter-validation + + + + + 21 + 21 + UTF-8 + + + diff --git a/scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java b/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java similarity index 79% rename from scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java rename to api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java index e04ccab..943c66b 100644 --- a/scrapper/src/main/java/edu/java/api/dto/ApiErrorResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -8,7 +8,6 @@ public record ApiErrorResponse( String code, String exceptionName, String exceptionMessage, - - StackTraceElement[] stacktrace + String[] stacktrace ) { } diff --git a/bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java similarity index 78% rename from bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java rename to api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java index 3598f86..8d2c6b6 100644 --- a/bot/src/main/java/edu/java/bot/api/dto/LinkUpdateRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java @@ -1,14 +1,15 @@ -package edu.java.bot.api.dto; +package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkUpdateRequest( - long id, + Long id, @URL String url, String description, - long[] tgChatIds + Long[] tgChatIds ) { } + diff --git a/scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java similarity index 86% rename from scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java index 35e5038..2399b04 100644 --- a/scrapper/src/main/java/edu/java/api/dto/AddLinkRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java similarity index 78% rename from bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java index 364072c..45c7228 100644 --- a/bot/src/main/java/edu/java/bot/api/dto/ApiErrorResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -8,7 +8,6 @@ public record ApiErrorResponse( String code, String exceptionName, String exceptionMessage, - - StackTraceElement[] stacktrace + String[] stacktrace ) { } diff --git a/scrapper/src/main/java/edu/java/api/dto/LinkResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java similarity index 81% rename from scrapper/src/main/java/edu/java/api/dto/LinkResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java index ce13424..bd2d1f5 100644 --- a/scrapper/src/main/java/edu/java/api/dto/LinkResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java @@ -1,11 +1,11 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkResponse( - long id, + Long id, @URL String url ) { diff --git a/scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java similarity index 76% rename from scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java index a6707c5..5ff4bda 100644 --- a/scrapper/src/main/java/edu/java/api/dto/ListLinksResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java @@ -1,10 +1,10 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public record ListLinksResponse( LinkResponse[] links, - int size + Integer size ) { } diff --git a/scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java similarity index 86% rename from scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java rename to api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java index 318f8f2..049848a 100644 --- a/scrapper/src/main/java/edu/java/api/dto/RemoveLinkRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api.dto; +package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/bot/pom.xml b/bot/pom.xml index ed1d026..e1391fc 100644 --- a/bot/pom.xml +++ b/bot/pom.xml @@ -128,6 +128,11 @@ kafka test + + edu.java + api_dto + 0.1 + diff --git a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java index f30e7ea..92fbab4 100644 --- a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java +++ b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java @@ -1,7 +1,7 @@ package edu.java.bot.api.controller; -import edu.java.bot.api.dto.ApiErrorResponse; -import edu.java.bot.api.dto.LinkUpdateRequest; +import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.api_dto.bot.LinkUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -29,5 +29,4 @@ public class UpdateController { public ResponseEntity sendUpdate(@Valid @RequestBody LinkUpdateRequest request) { return ResponseEntity.ok().build(); } - } diff --git a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java index 31c0eeb..c75a289 100644 --- a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java +++ b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java @@ -1,13 +1,13 @@ package edu.java.bot.api.exception; -import edu.java.bot.api.dto.ApiErrorResponse; +import edu.java.api_dto.bot.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -@RestControllerAdvice -public class ExceptionApiHandler { +@RestControllerAdvice public class ExceptionApiHandler { @ExceptionHandler(ChatNotExistException.class) public ResponseEntity chatNotExistException(ChatNotExistException exception) { @@ -16,24 +16,19 @@ public ResponseEntity chatNotExistException(ChatNotExistExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toArray(String[]::new) ); - return ResponseEntity - .status(HttpStatus.NOT_FOUND) - .body(error); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); } - @ExceptionHandler(Exception.class) - public ResponseEntity anyException(Exception exception) { + @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toArray(String[]::new) ); - return ResponseEntity - .status(HttpStatus.BAD_REQUEST) - .body(error); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); } } diff --git a/bot/src/main/java/edu/java/bot/api/client/AbstractClient.java b/bot/src/main/java/edu/java/bot/client/AbstractClient.java similarity index 92% rename from bot/src/main/java/edu/java/bot/api/client/AbstractClient.java rename to bot/src/main/java/edu/java/bot/client/AbstractClient.java index 5ebef97..1c43082 100644 --- a/bot/src/main/java/edu/java/bot/api/client/AbstractClient.java +++ b/bot/src/main/java/edu/java/bot/client/AbstractClient.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.client; +package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java similarity index 88% rename from bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java rename to bot/src/main/java/edu/java/bot/client/ScrapperClient.java index d6dbbec..e815705 100644 --- a/bot/src/main/java/edu/java/bot/api/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,4 +1,4 @@ -package edu.java.bot.api.client; +package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java b/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java similarity index 89% rename from bot/src/main/java/edu/java/bot/configuration/ClientConfig.java rename to bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java index ccb6a51..9771a8a 100644 --- a/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java @@ -1,7 +1,7 @@ package edu.java.bot.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.bot.api.client.ScrapperClient; +import edu.java.bot.client.ScrapperClient; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -9,7 +9,7 @@ @Configuration @RequiredArgsConstructor -public class ClientConfig { +public class BotClientConfig { @Value("${resources.base-url.scrapper}") private String scrapperUrl; private final ObjectMapper objectMapper; diff --git a/pom.xml b/pom.xml index e813daf..88935b8 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ bot scrapper + api_dto diff --git a/scrapper/pom.xml b/scrapper/pom.xml index 3370247..f1e90e3 100644 --- a/scrapper/pom.xml +++ b/scrapper/pom.xml @@ -138,6 +138,12 @@ kafka test + + edu.java + api_dto + 0.1 + compile + diff --git a/scrapper/src/main/java/edu/java/api/client/BotClient.java b/scrapper/src/main/java/edu/java/api/client/BotClient.java deleted file mode 100644 index 023466f..0000000 --- a/scrapper/src/main/java/edu/java/api/client/BotClient.java +++ /dev/null @@ -1,12 +0,0 @@ -package edu.java.api.client; - -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import lombok.NonNull; - -public class BotClient extends AbstractClient { - - public BotClient(@NonNull String baseUrl, ObjectMapper mapper) { - super(baseUrl, mapper); - } -} diff --git a/scrapper/src/main/java/edu/java/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/api/controller/ChatController.java index 92849c1..6af0583 100644 --- a/scrapper/src/main/java/edu/java/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/api/controller/ChatController.java @@ -1,6 +1,6 @@ package edu.java.api.controller; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/scrapper/src/main/java/edu/java/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/api/controller/LinkController.java index 5829aed..c349e7e 100644 --- a/scrapper/src/main/java/edu/java/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/api/controller/LinkController.java @@ -1,10 +1,10 @@ package edu.java.api.controller; -import edu.java.api.dto.AddLinkRequest; -import edu.java.api.dto.ApiErrorResponse; -import edu.java.api.dto.LinkResponse; -import edu.java.api.dto.ListLinksResponse; -import edu.java.api.dto.RemoveLinkRequest; +import edu.java.api_dto.scrapper.AddLinkRequest; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.api_dto.scrapper.LinkResponse; +import edu.java.api_dto.scrapper.ListLinksResponse; +import edu.java.api_dto.scrapper.RemoveLinkRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -59,7 +59,7 @@ public ResponseEntity addLink( TODO: добавление ссылки может быть брошено LinkAdditionException */ - return ResponseEntity.ok(new LinkResponse(0, "")); + return ResponseEntity.ok(new LinkResponse(0L, "")); } @Operation(summary = "Убрать отслеживание ссылки") @@ -83,6 +83,6 @@ public ResponseEntity deleteLink( TODO: удаление ссылки может быть брошено LinkNotFoundException */ - return ResponseEntity.ok(new LinkResponse(0, "")); + return ResponseEntity.ok(new LinkResponse(0L, "")); } } diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java index 4483f07..cc5bcda 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java @@ -1,6 +1,7 @@ package edu.java.api.exception.chat; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -16,7 +17,9 @@ public ResponseEntity chatRegistrationException(ChatRegistrati HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.BAD_REQUEST) @@ -30,7 +33,9 @@ public ResponseEntity chatNotFoundException(ChatNotFoundExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.NOT_FOUND) @@ -40,14 +45,16 @@ public ResponseEntity chatNotFoundException(ChatNotFoundExcept @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity - .status(HttpStatus.BAD_REQUEST) + .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(error); } } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java index 7be1029..2fffd1b 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java @@ -1,6 +1,7 @@ package edu.java.api.exception.link; -import edu.java.api.dto.ApiErrorResponse; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -16,7 +17,9 @@ public ResponseEntity linkAdditionException(LinkAdditionExcept HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.BAD_REQUEST) @@ -30,7 +33,9 @@ public ResponseEntity linkNotFoundException(LinkNotFoundExcept HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity .status(HttpStatus.NOT_FOUND) @@ -40,14 +45,16 @@ public ResponseEntity linkNotFoundException(LinkNotFoundExcept @ExceptionHandler(Exception.class) public ResponseEntity anyException(Exception exception) { ApiErrorResponse error = new ApiErrorResponse( - "Неверные параметры запроса", - HttpStatus.BAD_REQUEST.toString(), + "Произошла непредвиденная ошибка на стороне сервера", + HttpStatus.INTERNAL_SERVER_ERROR.toString(), exception.getClass().getName(), exception.getMessage(), - exception.getStackTrace() + Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .toArray(String[]::new) ); return ResponseEntity - .status(HttpStatus.BAD_REQUEST) + .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(error); } } diff --git a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/client/bot/BotApiException.java new file mode 100644 index 0000000..0c892a8 --- /dev/null +++ b/scrapper/src/main/java/edu/java/client/bot/BotApiException.java @@ -0,0 +1,15 @@ +package edu.java.client.bot; + +import edu.java.api_dto.bot.ApiErrorResponse; +import lombok.Getter; + +@Getter +public class BotApiException extends Exception { + private final ApiErrorResponse error; + + public BotApiException(ApiErrorResponse error) { + super("%s: %s. %s - %s\n%s".formatted(error.code(), error.description(), + error.exceptionName(), error.exceptionMessage(), String.join("\n", error.stacktrace()))); + this.error = error; + } +} diff --git a/scrapper/src/main/java/edu/java/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/client/bot/BotClient.java new file mode 100644 index 0000000..119f896 --- /dev/null +++ b/scrapper/src/main/java/edu/java/client/bot/BotClient.java @@ -0,0 +1,35 @@ +package edu.java.client.bot; + +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.client.AbstractClient; +import lombok.NonNull; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ClientResponse; +import reactor.core.publisher.Mono; + +public class BotClient extends AbstractClient { + + public BotClient(@NonNull String baseUrl, ObjectMapper mapper) { + super(baseUrl, mapper); + } + + public void sendUpdate(LinkUpdateRequest request) { + client.post() + .uri("/update") + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), LinkUpdateRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + private Mono getException(ClientResponse response) { + return response + .bodyToMono(ApiErrorResponse.class) + .map(BotApiException::new); + } +} diff --git a/scrapper/src/main/java/edu/java/client/GithubClient.java b/scrapper/src/main/java/edu/java/client/sources/GithubClient.java similarity index 94% rename from scrapper/src/main/java/edu/java/client/GithubClient.java rename to scrapper/src/main/java/edu/java/client/sources/GithubClient.java index 007f4cf..3f8995b 100644 --- a/scrapper/src/main/java/edu/java/client/GithubClient.java +++ b/scrapper/src/main/java/edu/java/client/sources/GithubClient.java @@ -1,8 +1,9 @@ -package edu.java.client; +package edu.java.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.client.AbstractClient; import edu.java.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; diff --git a/scrapper/src/main/java/edu/java/client/ResponseException.java b/scrapper/src/main/java/edu/java/client/sources/ResponseException.java similarity index 62% rename from scrapper/src/main/java/edu/java/client/ResponseException.java rename to scrapper/src/main/java/edu/java/client/sources/ResponseException.java index c72808b..498ce2a 100644 --- a/scrapper/src/main/java/edu/java/client/ResponseException.java +++ b/scrapper/src/main/java/edu/java/client/sources/ResponseException.java @@ -1,4 +1,4 @@ -package edu.java.client; +package edu.java.client.sources; public class ResponseException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/StackoverflowClient.java b/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java similarity index 95% rename from scrapper/src/main/java/edu/java/client/StackoverflowClient.java rename to scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java index f9afbe5..c23d881 100644 --- a/scrapper/src/main/java/edu/java/client/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java @@ -1,8 +1,9 @@ -package edu.java.client; +package edu.java.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.client.AbstractClient; import edu.java.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; diff --git a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java b/scrapper/src/main/java/edu/java/configuration/ClientConfig.java index 7d36ea2..275b10e 100644 --- a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java +++ b/scrapper/src/main/java/edu/java/configuration/ClientConfig.java @@ -1,9 +1,9 @@ package edu.java.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api.client.BotClient; -import edu.java.client.GithubClient; -import edu.java.client.StackoverflowClient; +import edu.java.client.bot.BotClient; +import edu.java.client.sources.GithubClient; +import edu.java.client.sources.StackoverflowClient; import lombok.RequiredArgsConstructor; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Value; @@ -41,9 +41,6 @@ public StackoverflowClient stackoverflowClient() { @Bean public BotClient botClient() { - return new BotClient( - botUrl, - objectMapper - ); + return new BotClient(botUrl, objectMapper); } } diff --git a/scrapper/src/test/java/edu/java/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/client/GithubClientTest.java index ded166b..fc12e2a 100644 --- a/scrapper/src/test/java/edu/java/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/client/GithubClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; +import edu.java.client.sources.GithubClient; +import edu.java.client.sources.ResponseException; import edu.java.configuration.ObjectMapperConfig; import edu.java.dto.GithubResponse; import java.util.List; diff --git a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java new file mode 100644 index 0000000..1de6bf1 --- /dev/null +++ b/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java @@ -0,0 +1,28 @@ +package edu.java.client; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.configuration.ObjectMapperConfig; +import edu.java.dto.GithubResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.time.OffsetDateTime; + +public class ObjectMapperTest { + + private final ObjectMapper mapper; + + public ObjectMapperTest() { + this.mapper = new ObjectMapperConfig().objectMapper(); + } + + @Test + void objectMapperTest() throws JsonProcessingException { + GithubResponse object = new GithubResponse(0L, "example", + new GithubResponse.Actor("cyberpanncake"), + new GithubResponse.Repository("Torzhkova-Tinkoff-JavaBackendCourse-Spring"), + OffsetDateTime.now()); + String json = mapper.writeValueAsString(object); + Assertions.assertTrue(json.contains("created_at")); + } +} diff --git a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java index 95e2757..3c4fd9b 100644 --- a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; +import edu.java.client.sources.ResponseException; +import edu.java.client.sources.StackoverflowClient; import edu.java.configuration.ObjectMapperConfig; import edu.java.dto.StackoverflowResponse; import java.util.Map; From cfc3ef7eaf0c69447a1210e94f91d11ac98d77d8 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:13:35 +0300 Subject: [PATCH 19/34] fix: rename class and move some classes in new directory --- .../{BotClientConfig.java => ClientConfig.java} | 2 +- .../edu/java/{ => scrapper}/ScrapperApplication.java | 4 ++-- .../{ => scrapper}/api/controller/ChatController.java | 2 +- .../{ => scrapper}/api/controller/LinkController.java | 2 +- .../api/exception/chat/ChatExceptionApiHandler.java | 2 +- .../api/exception/chat/ChatNotFoundException.java | 2 +- .../api/exception/chat/ChatRegistrationException.java | 2 +- .../api/exception/link/LinkAdditionException.java | 2 +- .../api/exception/link/LinkExceptionApiHandler.java | 2 +- .../api/exception/link/LinkNotFoundException.java | 2 +- .../edu/java/{ => scrapper}/client/AbstractClient.java | 2 +- .../{ => scrapper}/client/bot/BotApiException.java | 2 +- .../edu/java/{ => scrapper}/client/bot/BotClient.java | 4 ++-- .../{ => scrapper}/client/sources/GithubClient.java | 6 +++--- .../client/sources/ResponseException.java | 2 +- .../client/sources/StackoverflowClient.java | 6 +++--- .../configuration/ApplicationConfig.java | 2 +- .../{ => scrapper}/configuration/ClientConfig.java | 8 ++++---- .../configuration/ObjectMapperConfig.java | 2 +- .../edu/java/{ => scrapper}/dto/GithubResponse.java | 2 +- .../java/{ => scrapper}/dto/StackoverflowResponse.java | 2 +- .../{ => scrapper}/shedule/LinkUpdaterScheduler.java | 2 +- .../java/{ => scrapper}/client/GithubClientTest.java | 10 +++++----- .../java/{ => scrapper}/client/ObjectMapperTest.java | 6 +++--- .../{ => scrapper}/client/StackoverflowClientTest.java | 10 +++++----- 25 files changed, 44 insertions(+), 44 deletions(-) rename bot/src/main/java/edu/java/bot/configuration/{BotClientConfig.java => ClientConfig.java} (95%) rename scrapper/src/main/java/edu/java/{ => scrapper}/ScrapperApplication.java (85%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/controller/ChatController.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/controller/LinkController.java (99%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatExceptionApiHandler.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatNotFoundException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/chat/ChatRegistrationException.java (57%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkAdditionException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkExceptionApiHandler.java (98%) rename scrapper/src/main/java/edu/java/{ => scrapper}/api/exception/link/LinkNotFoundException.java (55%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/AbstractClient.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/bot/BotApiException.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/bot/BotClient.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/GithubClient.java (90%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/ResponseException.java (56%) rename scrapper/src/main/java/edu/java/{ => scrapper}/client/sources/StackoverflowClient.java (90%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ApplicationConfig.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ClientConfig.java (87%) rename scrapper/src/main/java/edu/java/{ => scrapper}/configuration/ObjectMapperConfig.java (94%) rename scrapper/src/main/java/edu/java/{ => scrapper}/dto/GithubResponse.java (94%) rename scrapper/src/main/java/edu/java/{ => scrapper}/dto/StackoverflowResponse.java (92%) rename scrapper/src/main/java/edu/java/{ => scrapper}/shedule/LinkUpdaterScheduler.java (93%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/GithubClientTest.java (94%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/ObjectMapperTest.java (85%) rename scrapper/src/test/java/edu/java/{ => scrapper}/client/StackoverflowClientTest.java (94%) diff --git a/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java b/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java similarity index 95% rename from bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java rename to bot/src/main/java/edu/java/bot/configuration/ClientConfig.java index 9771a8a..0f74021 100644 --- a/bot/src/main/java/edu/java/bot/configuration/BotClientConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/ClientConfig.java @@ -9,7 +9,7 @@ @Configuration @RequiredArgsConstructor -public class BotClientConfig { +public class ClientConfig { @Value("${resources.base-url.scrapper}") private String scrapperUrl; private final ObjectMapper objectMapper; diff --git a/scrapper/src/main/java/edu/java/ScrapperApplication.java b/scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java similarity index 85% rename from scrapper/src/main/java/edu/java/ScrapperApplication.java rename to scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java index fadceb1..22cb3aa 100644 --- a/scrapper/src/main/java/edu/java/ScrapperApplication.java +++ b/scrapper/src/main/java/edu/java/scrapper/ScrapperApplication.java @@ -1,6 +1,6 @@ -package edu.java; +package edu.java.scrapper; -import edu.java.configuration.ApplicationConfig; +import edu.java.scrapper.configuration.ApplicationConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/scrapper/src/main/java/edu/java/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/controller/ChatController.java rename to scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index 6af0583..f1696a2 100644 --- a/scrapper/src/main/java/edu/java/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,4 +1,4 @@ -package edu.java.api.controller; +package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.ApiErrorResponse; import io.swagger.v3.oas.annotations.Operation; diff --git a/scrapper/src/main/java/edu/java/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java similarity index 99% rename from scrapper/src/main/java/edu/java/api/controller/LinkController.java rename to scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index c349e7e..f72fdb9 100644 --- a/scrapper/src/main/java/edu/java/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -1,4 +1,4 @@ -package edu.java.api.controller; +package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.AddLinkRequest; import edu.java.api_dto.scrapper.ApiErrorResponse; diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index cc5bcda..c8344dd 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; import edu.java.api_dto.scrapper.ApiErrorResponse; import java.util.Arrays; diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java index 35cf0c7..647066d 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatNotFoundException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatNotFoundException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; public class ChatNotFoundException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java similarity index 57% rename from scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java index d804ca0..eba10b2 100644 --- a/scrapper/src/main/java/edu/java/api/exception/chat/ChatRegistrationException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.chat; +package edu.java.scrapper.api.exception.chat; public class ChatRegistrationException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java index f5c22de..dbe67a6 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkAdditionException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkAdditionException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; public class LinkAdditionException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java similarity index 98% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java index 2fffd1b..3392519 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; import edu.java.api_dto.scrapper.ApiErrorResponse; import java.util.Arrays; diff --git a/scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java similarity index 55% rename from scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java rename to scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java index 879f43e..655dc36 100644 --- a/scrapper/src/main/java/edu/java/api/exception/link/LinkNotFoundException.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkNotFoundException.java @@ -1,4 +1,4 @@ -package edu.java.api.exception.link; +package edu.java.scrapper.api.exception.link; public class LinkNotFoundException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/AbstractClient.java b/scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/AbstractClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java index 195245b..e73da2f 100644 --- a/scrapper/src/main/java/edu/java/client/AbstractClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/AbstractClient.java @@ -1,4 +1,4 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.NonNull; diff --git a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/bot/BotApiException.java rename to scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java index 0c892a8..3e78df3 100644 --- a/scrapper/src/main/java/edu/java/client/bot/BotApiException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java @@ -1,4 +1,4 @@ -package edu.java.client.bot; +package edu.java.scrapper.client.bot; import edu.java.api_dto.bot.ApiErrorResponse; import lombok.Getter; diff --git a/scrapper/src/main/java/edu/java/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java similarity index 92% rename from scrapper/src/main/java/edu/java/client/bot/BotClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java index 119f896..4ea3155 100644 --- a/scrapper/src/main/java/edu/java/client/bot/BotClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java @@ -1,9 +1,9 @@ -package edu.java.client.bot; +package edu.java.scrapper.client.bot; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.api_dto.bot.ApiErrorResponse; import edu.java.api_dto.bot.LinkUpdateRequest; -import edu.java.client.AbstractClient; +import edu.java.scrapper.client.AbstractClient; import lombok.NonNull; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; diff --git a/scrapper/src/main/java/edu/java/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java similarity index 90% rename from scrapper/src/main/java/edu/java/client/sources/GithubClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index 3f8995b..a5ad13b 100644 --- a/scrapper/src/main/java/edu/java/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -1,10 +1,10 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.client.AbstractClient; +import edu.java.scrapper.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/client/sources/ResponseException.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java similarity index 56% rename from scrapper/src/main/java/edu/java/client/sources/ResponseException.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java index 498ce2a..c28d33c 100644 --- a/scrapper/src/main/java/edu/java/client/sources/ResponseException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/ResponseException.java @@ -1,4 +1,4 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; public class ResponseException extends Exception { } diff --git a/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java similarity index 90% rename from scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java index c23d881..c5739f3 100644 --- a/scrapper/src/main/java/edu/java/client/sources/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java @@ -1,10 +1,10 @@ -package edu.java.client.sources; +package edu.java.scrapper.client.sources; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.AbstractClient; -import edu.java.dto.StackoverflowResponse; +import edu.java.scrapper.client.AbstractClient; +import edu.java.scrapper.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java similarity index 92% rename from scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java index 1760267..7574e4e 100644 --- a/scrapper/src/main/java/edu/java/configuration/ApplicationConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ApplicationConfig.java @@ -1,4 +1,4 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import jakarta.validation.constraints.NotNull; import java.time.Duration; diff --git a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java similarity index 87% rename from scrapper/src/main/java/edu/java/configuration/ClientConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java index 275b10e..63595c0 100644 --- a/scrapper/src/main/java/edu/java/configuration/ClientConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ClientConfig.java @@ -1,9 +1,9 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.client.bot.BotClient; -import edu.java.client.sources.GithubClient; -import edu.java.client.sources.StackoverflowClient; +import edu.java.scrapper.client.bot.BotClient; +import edu.java.scrapper.client.sources.GithubClient; +import edu.java.scrapper.client.sources.StackoverflowClient; import lombok.RequiredArgsConstructor; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Value; diff --git a/scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java similarity index 94% rename from scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java rename to scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java index 6d2f3be..daac430 100644 --- a/scrapper/src/main/java/edu/java/configuration/ObjectMapperConfig.java +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/ObjectMapperConfig.java @@ -1,4 +1,4 @@ -package edu.java.configuration; +package edu.java.scrapper.configuration; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/scrapper/src/main/java/edu/java/dto/GithubResponse.java b/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java similarity index 94% rename from scrapper/src/main/java/edu/java/dto/GithubResponse.java rename to scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java index b122ce0..a6e0ee7 100644 --- a/scrapper/src/main/java/edu/java/dto/GithubResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java @@ -1,4 +1,4 @@ -package edu.java.dto; +package edu.java.scrapper.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java b/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java similarity index 92% rename from scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java rename to scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java index 4a0a8d0..15fceb9 100644 --- a/scrapper/src/main/java/edu/java/dto/StackoverflowResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java @@ -1,4 +1,4 @@ -package edu.java.dto; +package edu.java.scrapper.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java similarity index 93% rename from scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java rename to scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java index b04b193..a7e2a78 100644 --- a/scrapper/src/main/java/edu/java/shedule/LinkUpdaterScheduler.java +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java @@ -1,4 +1,4 @@ -package edu.java.shedule; +package edu.java.scrapper.shedule; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/scrapper/src/test/java/edu/java/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java similarity index 94% rename from scrapper/src/test/java/edu/java/client/GithubClientTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java index fc12e2a..ea5a5c4 100644 --- a/scrapper/src/test/java/edu/java/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java @@ -1,12 +1,12 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; -import edu.java.client.sources.GithubClient; -import edu.java.client.sources.ResponseException; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.client.sources.GithubClient; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.GithubResponse; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java similarity index 85% rename from scrapper/src/test/java/edu/java/client/ObjectMapperTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java index 1de6bf1..741ca3d 100644 --- a/scrapper/src/test/java/edu/java/client/ObjectMapperTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java @@ -1,9 +1,9 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.GithubResponse; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.GithubResponse; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java similarity index 94% rename from scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java rename to scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java index 3c4fd9b..a2a5d80 100644 --- a/scrapper/src/test/java/edu/java/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java @@ -1,12 +1,12 @@ -package edu.java.client; +package edu.java.scrapper.client; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; -import edu.java.client.sources.ResponseException; -import edu.java.client.sources.StackoverflowClient; -import edu.java.configuration.ObjectMapperConfig; -import edu.java.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.StackoverflowClient; +import edu.java.scrapper.configuration.ObjectMapperConfig; +import edu.java.scrapper.dto.StackoverflowResponse; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.AfterEach; From 8a9391e277dbccc63511300930f7aaf75f2d7678 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:46:29 +0300 Subject: [PATCH 20/34] feat: add ScrapperClient in bot --- .../java/bot/client/ScrapperApiException.java | 15 ++++ .../edu/java/bot/client/ScrapperClient.java | 77 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 bot/src/main/java/edu/java/bot/client/ScrapperApiException.java diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java new file mode 100644 index 0000000..1fa2b6c --- /dev/null +++ b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java @@ -0,0 +1,15 @@ +package edu.java.bot.client; + +import edu.java.api_dto.scrapper.ApiErrorResponse; +import lombok.Getter; + +@Getter +public class ScrapperApiException extends Exception { + private final ApiErrorResponse error; + + public ScrapperApiException(ApiErrorResponse error) { + super("%s: %s. %s - %s\n%s".formatted(error.code(), error.description(), + error.exceptionName(), error.exceptionMessage(), String.join("\n", error.stacktrace()))); + this.error = error; + } +} diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java index e815705..577ca9c 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,10 +1,87 @@ package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.java.api_dto.scrapper.AddLinkRequest; +import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.api_dto.scrapper.LinkResponse; +import edu.java.api_dto.scrapper.ListLinksResponse; +import edu.java.api_dto.scrapper.RemoveLinkRequest; import lombok.NonNull; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ClientResponse; +import reactor.core.publisher.Mono; public class ScrapperClient extends AbstractClient { + private static final String CHAT_BASE_URL = "/tg-chat"; + private static final String LINK_BASE_URL = "/links"; + private static final String ID_PATH = "/{id}"; + private static final String CHAT_HEADER = "Tg-Chat-Id"; + public ScrapperClient(@NonNull String baseUrl, ObjectMapper mapper) { super(baseUrl, mapper); } + + public void registerChat(long id) { + client.post() + .uri(uriBuilder -> uriBuilder + .path(CHAT_BASE_URL + ID_PATH) + .build(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + public void deleteChat(long id) { + client.delete() + .uri(uriBuilder -> uriBuilder + .path(CHAT_BASE_URL + ID_PATH) + .build(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(Void.class) + .block(); + } + + public ListLinksResponse getLinks(long id) { + return client.get() + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(ListLinksResponse.class) + .block(); + } + + public LinkResponse addLink(long id, AddLinkRequest request) { + return client.post() + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), AddLinkRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(LinkResponse.class) + .block(); + } + + public LinkResponse deleteLink(long id, RemoveLinkRequest request) { + return client.method(HttpMethod.DELETE) + .uri(LINK_BASE_URL) + .header(CHAT_HEADER, String.valueOf(id)) + .accept(MediaType.APPLICATION_JSON) + .body(Mono.just(request), RemoveLinkRequest.class) + .retrieve() + .onStatus(HttpStatusCode::isError, this::getException) + .bodyToMono(LinkResponse.class) + .block(); + } + + private Mono getException(ClientResponse response) { + return response + .bodyToMono(ApiErrorResponse.class) + .map(ScrapperApiException::new); + } } From b0ba1a33e6ef52067a92df1279d4d1594b0c0678 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sat, 16 Mar 2024 23:58:04 +0300 Subject: [PATCH 21/34] fix: change url type in api dto from String to URI --- .../java/edu/java/api_dto/bot/LinkUpdateRequest.java | 5 ++--- .../java/edu/java/api_dto/scrapper/LinkResponse.java | 5 ++--- .../java/scrapper/api/controller/LinkController.java | 10 ++++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java index 8d2c6b6..bd2d278 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java +++ b/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java @@ -1,13 +1,12 @@ package edu.java.api_dto.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.hibernate.validator.constraints.URL; +import java.net.URI; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkUpdateRequest( Long id, - @URL - String url, + URI url, String description, Long[] tgChatIds ) { diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java index bd2d1f5..91ca8c0 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java +++ b/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java @@ -1,12 +1,11 @@ package edu.java.api_dto.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.hibernate.validator.constraints.URL; +import java.net.URI; @JsonIgnoreProperties(ignoreUnknown = true) public record LinkResponse( Long id, - @URL - String url + URI url ) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index f72fdb9..080211b 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -11,6 +11,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; +import java.net.URI; +import java.net.URISyntaxException; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -54,12 +56,12 @@ public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat public ResponseEntity addLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody AddLinkRequest request - ) { + ) throws URISyntaxException { /* TODO: добавление ссылки может быть брошено LinkAdditionException */ - return ResponseEntity.ok(new LinkResponse(0L, "")); + return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); } @Operation(summary = "Убрать отслеживание ссылки") @@ -78,11 +80,11 @@ public ResponseEntity addLink( public ResponseEntity deleteLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody RemoveLinkRequest request - ) { + ) throws URISyntaxException { /* TODO: удаление ссылки может быть брошено LinkNotFoundException */ - return ResponseEntity.ok(new LinkResponse(0L, "")); + return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); } } From 39750130084a6993cf1acaaa59231cc767aa5132 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 14:16:34 +0300 Subject: [PATCH 22/34] fix: restructuring packages --- .../{ => client}/service/ScrapperService.java | 2 +- .../java/edu/java/bot/command/Command.java | 16 ------------- .../bot/configuration/TelegramBotConfig.java | 4 ++-- .../TgBotController.java} | 10 ++++---- .../command/AbstractCommand.java | 14 +++++------ .../command/AbstractServiceCommand.java | 4 ++-- .../java/bot/telegram/command/Command.java | 16 +++++++++++++ .../{ => telegram}/command/CommandUtils.java | 8 +++---- .../command/components/HelpCommand.java | 10 ++++---- .../command/components/ListCommand.java | 17 ++++++------- .../command/components/StartCommand.java | 10 ++++---- .../command/components/TrackCommand.java | 16 ++++++------- .../command/components/UntrackCommand.java | 16 ++++++------- .../exception/UnregisteredUserException.java | 2 +- .../exception/command/CommandException.java | 2 +- .../command/CommandNotExistException.java | 2 +- .../command/NotCommandException.java | 2 +- .../exception/link/LinkException.java | 2 +- .../link/LinkRegistrationException.java | 2 +- .../exception/link/NotLinkException.java | 2 +- .../parameter/ParameterException.java | 2 +- .../WrongNumberParametersException.java | 2 +- .../main/java/edu/java/bot/utils/Link.java | 2 +- .../java/edu/java/bot/BotApplicationTest.java | 24 +++++++++---------- .../edu/java/bot/TestScrapperService.java | 2 +- .../scrapper/client/sources/GithubClient.java | 2 +- .../client/sources/StackoverflowClient.java | 2 +- .../sources}/dto/GithubResponse.java | 2 +- .../sources}/dto/StackoverflowResponse.java | 2 +- .../scrapper/client/GithubClientTest.java | 2 +- .../scrapper/client/ObjectMapperTest.java | 2 +- .../client/StackoverflowClientTest.java | 2 +- 32 files changed, 102 insertions(+), 101 deletions(-) rename bot/src/main/java/edu/java/bot/{ => client}/service/ScrapperService.java (98%) delete mode 100644 bot/src/main/java/edu/java/bot/command/Command.java rename bot/src/main/java/edu/java/bot/{controller/Controller.java => telegram/TgBotController.java} (89%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/AbstractCommand.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/AbstractServiceCommand.java (77%) create mode 100644 bot/src/main/java/edu/java/bot/telegram/command/Command.java rename bot/src/main/java/edu/java/bot/{ => telegram}/command/CommandUtils.java (72%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/HelpCommand.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/ListCommand.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/StartCommand.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/TrackCommand.java (70%) rename bot/src/main/java/edu/java/bot/{ => telegram}/command/components/UntrackCommand.java (70%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/UnregisteredUserException.java (84%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/CommandException.java (73%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/CommandNotExistException.java (77%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/command/NotCommandException.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/LinkException.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/LinkRegistrationException.java (76%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/link/NotLinkException.java (74%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/parameter/ParameterException.java (73%) rename bot/src/main/java/edu/java/bot/{ => telegram}/exception/parameter/WrongNumberParametersException.java (76%) rename scrapper/src/main/java/edu/java/scrapper/{ => client/sources}/dto/GithubResponse.java (91%) rename scrapper/src/main/java/edu/java/scrapper/{ => client/sources}/dto/StackoverflowResponse.java (89%) diff --git a/bot/src/main/java/edu/java/bot/service/ScrapperService.java b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java similarity index 98% rename from bot/src/main/java/edu/java/bot/service/ScrapperService.java rename to bot/src/main/java/edu/java/bot/client/service/ScrapperService.java index 1deaa2f..f3d8c22 100644 --- a/bot/src/main/java/edu/java/bot/service/ScrapperService.java +++ b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java @@ -1,4 +1,4 @@ -package edu.java.bot.service; +package edu.java.bot.client.service; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/bot/src/main/java/edu/java/bot/command/Command.java b/bot/src/main/java/edu/java/bot/command/Command.java deleted file mode 100644 index 807b41a..0000000 --- a/bot/src/main/java/edu/java/bot/command/Command.java +++ /dev/null @@ -1,16 +0,0 @@ -package edu.java.bot.command; - -import com.pengrad.telegrambot.model.Update; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.parameter.ParameterException; - -public interface Command { - - String getName(); - - String getDescription(); - - String execute(Update update) throws UnregisteredUserException, ParameterException, CommandException, LinkException; -} diff --git a/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java b/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java index c4e25ce..51f91c5 100644 --- a/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/TelegramBotConfig.java @@ -3,8 +3,8 @@ import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.model.BotCommand; import com.pengrad.telegrambot.request.SetMyCommands; -import edu.java.bot.command.Command; -import edu.java.bot.command.components.HelpCommand; +import edu.java.bot.telegram.command.Command; +import edu.java.bot.telegram.command.components.HelpCommand; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; diff --git a/bot/src/main/java/edu/java/bot/controller/Controller.java b/bot/src/main/java/edu/java/bot/telegram/TgBotController.java similarity index 89% rename from bot/src/main/java/edu/java/bot/controller/Controller.java rename to bot/src/main/java/edu/java/bot/telegram/TgBotController.java index d9a1c1d..8b1753a 100644 --- a/bot/src/main/java/edu/java/bot/controller/Controller.java +++ b/bot/src/main/java/edu/java/bot/telegram/TgBotController.java @@ -1,4 +1,4 @@ -package edu.java.bot.controller; +package edu.java.bot.telegram; import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.TelegramException; @@ -6,10 +6,10 @@ import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.response.SendResponse; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.Command; import edu.java.bot.configuration.ApplicationConfig; import edu.java.bot.configuration.TelegramBotConfig; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.Command; import java.time.LocalDateTime; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -18,12 +18,12 @@ @Component @Slf4j -public class Controller { +public class TgBotController { private final TelegramBot bot; private final TelegramBotConfig botConfig; @Autowired - public Controller(ApplicationConfig config, TelegramBotConfig botConfig) { + public TgBotController(ApplicationConfig config, TelegramBotConfig botConfig) { this.botConfig = botConfig; bot = botConfig.telegramBot(config); bot.setUpdatesListener(this::processUpdates, this::processException); diff --git a/bot/src/main/java/edu/java/bot/command/AbstractCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java similarity index 74% rename from bot/src/main/java/edu/java/bot/command/AbstractCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java index 6d1d6e6..a7a897c 100644 --- a/bot/src/main/java/edu/java/bot/command/AbstractCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; import com.pengrad.telegrambot.model.Update; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.command.CommandNotExistException; -import edu.java.bot.exception.command.NotCommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.parameter.ParameterException; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.command.CommandNotExistException; +import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index 028ee0b..a78798c 100644 --- a/bot/src/main/java/edu/java/bot/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,6 +1,6 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/Command.java b/bot/src/main/java/edu/java/bot/telegram/command/Command.java new file mode 100644 index 0000000..1d90049 --- /dev/null +++ b/bot/src/main/java/edu/java/bot/telegram/command/Command.java @@ -0,0 +1,16 @@ +package edu.java.bot.telegram.command; + +import com.pengrad.telegrambot.model.Update; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; + +public interface Command { + + String getName(); + + String getDescription(); + + String execute(Update update) throws UnregisteredUserException, ParameterException, CommandException, LinkException; +} diff --git a/bot/src/main/java/edu/java/bot/command/CommandUtils.java b/bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java similarity index 72% rename from bot/src/main/java/edu/java/bot/command/CommandUtils.java rename to bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java index 666fc21..3eb2d27 100644 --- a/bot/src/main/java/edu/java/bot/command/CommandUtils.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/CommandUtils.java @@ -1,8 +1,8 @@ -package edu.java.bot.command; +package edu.java.bot.telegram.command; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.parameter.WrongNumberParametersException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; public class CommandUtils { diff --git a/bot/src/main/java/edu/java/bot/command/components/HelpCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java similarity index 76% rename from bot/src/main/java/edu/java/bot/command/components/HelpCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java index 6360263..b0a1895 100644 --- a/bot/src/main/java/edu/java/bot/command/components/HelpCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/HelpCommand.java @@ -1,9 +1,9 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.Command; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.parameter.ParameterException; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.Command; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.parameter.ParameterException; import java.util.List; import java.util.stream.Collectors; import org.springframework.core.annotation.Order; diff --git a/bot/src/main/java/edu/java/bot/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/components/ListCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 1f7a377..79c9498 100644 --- a/bot/src/main/java/edu/java/bot/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,15 +1,16 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; -import java.util.List; -import java.util.stream.Collectors; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.stream.Collectors; + @Component @Order(5) public class ListCommand extends AbstractServiceCommand { diff --git a/bot/src/main/java/edu/java/bot/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java similarity index 77% rename from bot/src/main/java/edu/java/bot/command/components/StartCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index 120ae79..e4f0af0 100644 --- a/bot/src/main/java/edu/java/bot/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,9 +1,9 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.parameter.ParameterException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java similarity index 70% rename from bot/src/main/java/edu/java/bot/command/components/TrackCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 466f995..670a538 100644 --- a/bot/src/main/java/edu/java/bot/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.utils.Link; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java similarity index 70% rename from bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java rename to bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 3e65102..40d974d 100644 --- a/bot/src/main/java/edu/java/bot/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,12 +1,12 @@ -package edu.java.bot.command.components; +package edu.java.bot.telegram.command.components; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.CommandUtils; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.CommandUtils; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.utils.Link; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; diff --git a/bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java b/bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java similarity index 84% rename from bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java index c8760df..3f94199 100644 --- a/bot/src/main/java/edu/java/bot/exception/UnregisteredUserException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/UnregisteredUserException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception; +package edu.java.bot.telegram.exception; public class UnregisteredUserException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/command/CommandException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java similarity index 73% rename from bot/src/main/java/edu/java/bot/exception/command/CommandException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java index 2bc19fe..25f1725 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/CommandException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public abstract class CommandException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java similarity index 77% rename from bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java index 6e6c488..e73c5b9 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/CommandNotExistException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/CommandNotExistException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public class CommandNotExistException extends CommandException { public CommandNotExistException() { diff --git a/bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java b/bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java index 65def43..e1c5919 100644 --- a/bot/src/main/java/edu/java/bot/exception/command/NotCommandException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/command/NotCommandException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.command; +package edu.java.bot.telegram.exception.command; public class NotCommandException extends CommandException { public NotCommandException() { diff --git a/bot/src/main/java/edu/java/bot/exception/link/LinkException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java similarity index 74% rename from bot/src/main/java/edu/java/bot/exception/link/LinkException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java index 483556e..ffcba12 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/LinkException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public abstract class LinkException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java index 2c3b5ff..1d9c9b3 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/LinkRegistrationException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public class LinkRegistrationException extends LinkException { public LinkRegistrationException(String message) { diff --git a/bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java b/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java similarity index 74% rename from bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java index b3124f9..f04851c 100644 --- a/bot/src/main/java/edu/java/bot/exception/link/NotLinkException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.link; +package edu.java.bot.telegram.exception.link; public class NotLinkException extends LinkException { public NotLinkException(String message) { diff --git a/bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java similarity index 73% rename from bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java index 017af07..5cb975c 100644 --- a/bot/src/main/java/edu/java/bot/exception/parameter/ParameterException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/ParameterException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.parameter; +package edu.java.bot.telegram.exception.parameter; public abstract class ParameterException extends Exception { diff --git a/bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java similarity index 76% rename from bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java rename to bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java index f9c4147..9b4417f 100644 --- a/bot/src/main/java/edu/java/bot/exception/parameter/WrongNumberParametersException.java +++ b/bot/src/main/java/edu/java/bot/telegram/exception/parameter/WrongNumberParametersException.java @@ -1,4 +1,4 @@ -package edu.java.bot.exception.parameter; +package edu.java.bot.telegram.exception.parameter; public class WrongNumberParametersException extends ParameterException { diff --git a/bot/src/main/java/edu/java/bot/utils/Link.java b/bot/src/main/java/edu/java/bot/utils/Link.java index 0421d92..25504af 100644 --- a/bot/src/main/java/edu/java/bot/utils/Link.java +++ b/bot/src/main/java/edu/java/bot/utils/Link.java @@ -1,6 +1,6 @@ package edu.java.bot.utils; -import edu.java.bot.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.link.NotLinkException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index 65f3332..74221c2 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -3,19 +3,19 @@ import com.pengrad.telegrambot.model.Message; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.User; -import edu.java.bot.command.AbstractCommand; -import edu.java.bot.command.AbstractServiceCommand; -import edu.java.bot.command.Command; +import edu.java.bot.telegram.command.AbstractCommand; +import edu.java.bot.telegram.command.AbstractServiceCommand; +import edu.java.bot.telegram.command.Command; import edu.java.bot.configuration.TelegramBotConfig; -import edu.java.bot.exception.UnregisteredUserException; -import edu.java.bot.exception.command.CommandException; -import edu.java.bot.exception.command.CommandNotExistException; -import edu.java.bot.exception.command.NotCommandException; -import edu.java.bot.exception.link.LinkException; -import edu.java.bot.exception.link.LinkRegistrationException; -import edu.java.bot.exception.link.NotLinkException; -import edu.java.bot.exception.parameter.ParameterException; -import edu.java.bot.exception.parameter.WrongNumberParametersException; +import edu.java.bot.telegram.exception.UnregisteredUserException; +import edu.java.bot.telegram.exception.command.CommandException; +import edu.java.bot.telegram.exception.command.CommandNotExistException; +import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.bot.telegram.exception.link.LinkException; +import edu.java.bot.telegram.exception.link.LinkRegistrationException; +import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; diff --git a/bot/src/test/java/edu/java/bot/TestScrapperService.java b/bot/src/test/java/edu/java/bot/TestScrapperService.java index 6eb3f3c..b5a827c 100644 --- a/bot/src/test/java/edu/java/bot/TestScrapperService.java +++ b/bot/src/test/java/edu/java/bot/TestScrapperService.java @@ -1,6 +1,6 @@ package edu.java.bot; -import edu.java.bot.service.ScrapperService; +import edu.java.bot.client.service.ScrapperService; import java.util.List; import lombok.Setter; diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index a5ad13b..dd696e8 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.client.AbstractClient; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java index c5739f3..7625599 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/StackoverflowClient.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.client.AbstractClient; -import edu.java.scrapper.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; import java.util.Optional; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; diff --git a/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java similarity index 91% rename from scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java index a6e0ee7..2ddb643 100644 --- a/scrapper/src/main/java/edu/java/scrapper/dto/GithubResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/GithubResponse.java @@ -1,4 +1,4 @@ -package edu.java.scrapper.dto; +package edu.java.scrapper.client.sources.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java similarity index 89% rename from scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java rename to scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java index 15fceb9..b3ac47e 100644 --- a/scrapper/src/main/java/edu/java/scrapper/dto/StackoverflowResponse.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/dto/StackoverflowResponse.java @@ -1,4 +1,4 @@ -package edu.java.scrapper.dto; +package edu.java.scrapper.client.sources.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java index ea5a5c4..277b85e 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/GithubClientTest.java @@ -6,7 +6,7 @@ import edu.java.scrapper.client.sources.GithubClient; import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java index 741ca3d..6af27ca 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/ObjectMapperTest.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.GithubResponse; +import edu.java.scrapper.client.sources.dto.GithubResponse; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.OffsetDateTime; diff --git a/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java index a2a5d80..de5909d 100644 --- a/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java +++ b/scrapper/src/test/java/edu/java/scrapper/client/StackoverflowClientTest.java @@ -6,7 +6,7 @@ import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.client.sources.StackoverflowClient; import edu.java.scrapper.configuration.ObjectMapperConfig; -import edu.java.scrapper.dto.StackoverflowResponse; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.AfterEach; From 90bb156d3c8404fb050c29fd30e69afb78c13f8f Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 14:37:44 +0300 Subject: [PATCH 23/34] feat: add domain dto for scrapper --- .../java/bot/telegram/command/components/ListCommand.java | 5 ++--- .../main/java/edu/java/scrapper/api/domain/dto/Chat.java | 4 ++++ .../main/java/edu/java/scrapper/api/domain/dto/Link.java | 7 +++++++ .../java/edu/java/scrapper/api/domain/dto/Subcription.java | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 79c9498..1f6cd78 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -5,11 +5,10 @@ import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - import java.util.List; import java.util.stream.Collectors; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; @Component @Order(5) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java new file mode 100644 index 0000000..4245a36 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Chat(long id, long tgId) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java new file mode 100644 index 0000000..b6422a2 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java @@ -0,0 +1,7 @@ +package edu.java.scrapper.api.domain.dto; + +import java.net.URI; +import java.time.OffsetDateTime; + +public record Link(long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java new file mode 100644 index 0000000..7eb3981 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Subcription(long chatId, long linkId) { +} From 1c5bc453130af270b6e3a0abb06cac9d2943f80b Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 23:28:12 +0300 Subject: [PATCH 24/34] feat: add repos and services for dto with tests --- .../java/scrapper/api/domain/dto/Chat.java | 2 +- .../java/scrapper/api/domain/dto/Link.java | 2 +- .../scrapper/api/domain/dto/Subcription.java | 4 - .../scrapper/api/domain/dto/Subscription.java | 4 + .../api/domain/repository/ChatRepository.java | 15 +++ .../api/domain/repository/LinkRepository.java | 20 ++++ .../repository/SubscriptionRepository.java | 24 ++++ .../jdbc/AbstractJdbcRepository.java | 11 ++ .../repository/jdbc/JdbcChatRepository.java | 51 ++++++++ .../repository/jdbc/JdbcLinkRepository.java | 69 +++++++++++ .../jdbc/JdbcSubscriptionRepository.java | 91 +++++++++++++++ .../chat/ChatAlreadyRegisteredException.java | 4 + .../chat/ChatExceptionApiHandler.java | 8 +- .../chat/ChatRegistrationException.java | 4 - .../scrapper/api/service/ChatService.java | 10 ++ .../scrapper/api/service/LinkService.java | 16 +++ .../scrapper/api/service/LinkUpdater.java | 5 + .../scrapper/api/service/ScrapperService.java | 21 ++++ .../api/service/jdbc/JdbcChatService.java | 52 +++++++++ .../api/service/jdbc/JdbcLinkService.java | 79 +++++++++++++ .../api/service/jdbc/JdbcLinkUpdater.java | 26 +++++ scrapper/src/main/resources/application.yml | 9 +- .../domain/repository/ChatRepositoryTest.java | 75 ++++++++++++ .../domain/repository/LinkRepositoryTest.java | 88 ++++++++++++++ .../SubscriptionRepositoryTest.java | 109 ++++++++++++++++++ .../jdbc/JdbcChatRepositoryTest.java | 14 +++ .../jdbc/JdbcLinkRepositoryTest.java | 14 +++ .../jdbc/JdbcSubscriptionRepositoryTest.java | 15 +++ 28 files changed, 825 insertions(+), 17 deletions(-) delete mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java delete mode 100644 scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java create mode 100644 scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java index 4245a36..92db131 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Chat.java @@ -1,4 +1,4 @@ package edu.java.scrapper.api.domain.dto; -public record Chat(long id, long tgId) { +public record Chat(Long id, long tgId) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java index b6422a2..f96249d 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Link.java @@ -3,5 +3,5 @@ import java.net.URI; import java.time.OffsetDateTime; -public record Link(long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { +public record Link(Long id, URI url, OffsetDateTime lastUpdate, OffsetDateTime lastCheck) { } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java deleted file mode 100644 index 7eb3981..0000000 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subcription.java +++ /dev/null @@ -1,4 +0,0 @@ -package edu.java.scrapper.api.domain.dto; - -public record Subcription(long chatId, long linkId) { -} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java new file mode 100644 index 0000000..8ce08d3 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/dto/Subscription.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.domain.dto; + +public record Subscription(long chatId, long linkId) { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java new file mode 100644 index 0000000..61c36ff --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/ChatRepository.java @@ -0,0 +1,15 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Chat; +import java.util.List; +import java.util.Optional; + +public interface ChatRepository { + Optional findByTgId(long tgId); + + Chat add(long tgId); + + void remove(long tgId); + + List findAll(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java new file mode 100644 index 0000000..1924aab --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java @@ -0,0 +1,20 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Link; +import java.net.URI; +import java.util.List; +import java.util.Optional; + +public interface LinkRepository { + Optional findById(long id); + + Optional findByUrl(URI url); + + Link add(Link link); + + void remove(URI url); + + void remove(long id); + + List findAll(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java new file mode 100644 index 0000000..c99a9cd --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java @@ -0,0 +1,24 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import java.net.URI; +import java.util.List; +import java.util.Optional; + +public interface SubscriptionRepository { + Optional find(long tgId, URI url); + + Subscription add(Subscription subscription); + + void remove(Subscription subscription); + + List findAll(); + + List findAllByChat(long chatId); + + boolean linkNotFollowedByAnyone(long linkId); + + List findAllLinksByChat(Chat chat); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java new file mode 100644 index 0000000..2820fe6 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/AbstractJdbcRepository.java @@ -0,0 +1,11 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import org.springframework.jdbc.core.simple.JdbcClient; + +public abstract class AbstractJdbcRepository { + protected final JdbcClient client; + + public AbstractJdbcRepository(JdbcClient client) { + this.client = client; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java new file mode 100644 index 0000000..d1a1000 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepository.java @@ -0,0 +1,51 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.repository.ChatRepository; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcChatRepository extends AbstractJdbcRepository implements ChatRepository { + + public JdbcChatRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional findByTgId(long tgId) { + return client.sql("select * from chat where tg_id = ?") + .param(tgId) + .query(Chat.class) + .optional(); + } + + @Override + public Chat add(long tgId) { + GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); + client.sql("insert into chat (tg_id) values (?)") + .param(tgId) + .update(keyHolder, "id"); + long id = keyHolder.getKey().longValue(); + return new Chat(id, tgId); + } + + @Override + public void remove(long tgId) { + client.sql("delete from chat where tg_id = ?") + .param(tgId) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from chat") + .query(Chat.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java new file mode 100644 index 0000000..ce81751 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java @@ -0,0 +1,69 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.repository.LinkRepository; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcLinkRepository extends AbstractJdbcRepository implements LinkRepository { + + public JdbcLinkRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional findById(long id) { + return client.sql("select * from link where id = ?") + .param(id) + .query(Link.class) + .optional(); + } + + @Override + public Optional findByUrl(URI url) { + return client.sql("select * from link where url = ?") + .param(url.toString()) + .query(Link.class) + .optional(); + } + + @Override + public Link add(Link link) { + GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); + client.sql("insert into link (url, last_update, last_check) values (?, ?, ?)") + .param(link.url().toString()) + .param(link.lastUpdate()) + .param(link.lastCheck()) + .update(keyHolder, "id"); + long id = keyHolder.getKey().longValue(); + return new Link(id, link.url(), link.lastUpdate(), link.lastCheck()); + } + + @Override + public void remove(URI url) { + client.sql("delete from link where url = ?") + .param(url.toString()) + .update(); + } + + @Override + public void remove(long id) { + client.sql("delete from link where id = ?") + .param(id) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from link") + .query(Link.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java new file mode 100644 index 0000000..2c1abb9 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -0,0 +1,91 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.SubscriptionRepository; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public class JdbcSubscriptionRepository extends AbstractJdbcRepository implements SubscriptionRepository { + + public JdbcSubscriptionRepository(JdbcClient client) { + super(client); + } + + @Override + public Optional find(long tgId, URI url) { + return client.sql(""" + select subscription.chat_id, subscription.link_id + from subscription + inner join chat on subscription.chat_id = chat.id + inner join link on subscription.link_id = link.id + where + chat.tg_id = ? + and link.url = ?""") + .param(tgId) + .param(url.toString()) + .query(Subscription.class) + .optional(); + } + + @Override + public Subscription add(Subscription subscription) { + client.sql("insert into subscription (chat_id, link_id) values (?, ?)") + .param(subscription.chatId()) + .param(subscription.linkId()) + .update(); + return subscription; + } + + @Override + public void remove(Subscription subscription) { + client.sql("delete from subscription where chat_id = ? and link_id = ?") + .param(subscription.chatId()) + .param(subscription.linkId()) + .update(); + } + + @Override + public List findAll() { + return client.sql("select * from subscription") + .query(Subscription.class) + .list(); + } + + @Override + public List findAllByChat(long chatId) { + return client.sql("select * from subscription where chat_id = ?") + .param(chatId) + .query(Subscription.class) + .list(); + } + + @Override + public boolean linkNotFollowedByAnyone(long linkId) { + List subscriptions = client.sql("select * from subscription where link_id = ?") + .param(linkId) + .query(Subscription.class) + .list(); + return subscriptions.isEmpty(); + } + + @Override + public List findAllLinksByChat(Chat chat) { + return client.sql(""" + select link.id, link.url + from link + inner join subscription on link.id = subscription.link_id + where + subscription.chat_id = ?""") + .param(chat.id()) + .query(Link.class) + .list(); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java new file mode 100644 index 0000000..f0333fc --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatAlreadyRegisteredException.java @@ -0,0 +1,4 @@ +package edu.java.scrapper.api.exception.chat; + +public class ChatAlreadyRegisteredException extends Exception { +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index c8344dd..811b2e6 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -10,10 +10,10 @@ @RestControllerAdvice public class ChatExceptionApiHandler { - @ExceptionHandler(ChatRegistrationException.class) - public ResponseEntity chatRegistrationException(ChatRegistrationException exception) { + @ExceptionHandler(ChatAlreadyRegisteredException.class) + public ResponseEntity chatRegistrationException(ChatAlreadyRegisteredException exception) { ApiErrorResponse error = new ApiErrorResponse( - "Чат с уже зарегистрирован", + "Чат уже зарегистрирован", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), @@ -29,7 +29,7 @@ public ResponseEntity chatRegistrationException(ChatRegistrati @ExceptionHandler(ChatNotFoundException.class) public ResponseEntity chatNotFoundException(ChatNotFoundException exception) { ApiErrorResponse error = new ApiErrorResponse( - "Чат с id не найден", + "Чат не найден", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java deleted file mode 100644 index eba10b2..0000000 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatRegistrationException.java +++ /dev/null @@ -1,4 +0,0 @@ -package edu.java.scrapper.api.exception.chat; - -public class ChatRegistrationException extends Exception { -} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java new file mode 100644 index 0000000..1eb5ee4 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ChatService.java @@ -0,0 +1,10 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; + +public interface ChatService { + void register(long tgId) throws ChatAlreadyRegisteredException; + + void unregister(long tgId) throws ChatNotFoundException; +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java new file mode 100644 index 0000000..fd58f07 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkService.java @@ -0,0 +1,16 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import java.net.URI; +import java.util.List; + +public interface LinkService { + Link add(long tgId, URI url) throws ChatNotFoundException, LinkAdditionException; + + Link remove(long tgId, URI url) throws LinkNotFoundException, ChatNotFoundException; + + List listAll(long tgId) throws ChatNotFoundException; +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java new file mode 100644 index 0000000..502bf89 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/LinkUpdater.java @@ -0,0 +1,5 @@ +package edu.java.scrapper.api.service; + +public interface LinkUpdater { + int update(); +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java new file mode 100644 index 0000000..455271f --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java @@ -0,0 +1,21 @@ +package edu.java.scrapper.api.service; + +import edu.java.scrapper.api.domain.repository.ChatRepository; +import edu.java.scrapper.api.domain.repository.LinkRepository; +import edu.java.scrapper.api.domain.repository.SubscriptionRepository; + +public abstract class ScrapperService { + protected final ChatRepository chatRepo; + protected final LinkRepository linkRepo; + protected final SubscriptionRepository subscriptionRepo; + + protected ScrapperService( + ChatRepository chatRepo, + LinkRepository linkRepo, + SubscriptionRepository subscriptionRepo + ) { + this.chatRepo = chatRepo; + this.linkRepo = linkRepo; + this.subscriptionRepo = subscriptionRepo; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java new file mode 100644 index 0000000..a7d5781 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -0,0 +1,52 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.service.ChatService; +import edu.java.scrapper.api.service.ScrapperService; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcChatService extends ScrapperService implements ChatService { + + @Autowired + protected JdbcChatService( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public void register(long tgId) throws ChatAlreadyRegisteredException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isPresent()) { + throw new ChatAlreadyRegisteredException(); + } + chatRepo.add(tgId); + } + + @Override + public void unregister(long tgId) throws ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + List subscriptions = subscriptionRepo.findAllByChat(chat.get().id()); + for (Subscription subscription : subscriptions) { + subscriptionRepo.remove(subscription); + if (subscriptionRepo.linkNotFollowedByAnyone(subscription.linkId())) { + linkRepo.remove(subscription.linkId()); + } + } + chatRepo.remove(tgId); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java new file mode 100644 index 0000000..3c0a1b0 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -0,0 +1,79 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import edu.java.scrapper.api.service.LinkService; +import edu.java.scrapper.api.service.ScrapperService; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcLinkService extends ScrapperService implements LinkService { + + @Autowired + protected JdbcLinkService( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public Link add(long tgId, URI url) throws ChatNotFoundException, LinkAdditionException { + Optional subscription = subscriptionRepo.find(tgId, url); + if (subscription.isPresent()) { + throw new LinkAdditionException(); + } + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + Optional link = linkRepo.findByUrl(url); + if (link.isEmpty()) { + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + link = Optional.of(linkRepo.add(new Link(null, url, now, now))); + } + subscriptionRepo.add(new Subscription(chat.get().id(), link.get().id())); + return link.get(); + } + + @Override + public Link remove(long tgId, URI url) throws LinkNotFoundException, ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + Optional subscription = subscriptionRepo.find(tgId, url); + if (subscription.isEmpty()) { + throw new LinkNotFoundException(); + } + Link link = linkRepo.findById(subscription.get().linkId()).get(); + subscriptionRepo.remove(subscription.get()); + if (subscriptionRepo.linkNotFollowedByAnyone(link.id())) { + linkRepo.remove(link.id()); + } + return link; + } + + @Override + public List listAll(long tgId) throws ChatNotFoundException { + Optional chat = chatRepo.findByTgId(tgId); + if (chat.isEmpty()) { + throw new ChatNotFoundException(); + } + return subscriptionRepo.findAllLinksByChat(chat.get()); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java new file mode 100644 index 0000000..14fbde1 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -0,0 +1,26 @@ +package edu.java.scrapper.api.service.jdbc; + +import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; +import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; +import edu.java.scrapper.api.service.LinkUpdater; +import edu.java.scrapper.api.service.ScrapperService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { + + @Autowired + protected JdbcLinkUpdater( + JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, + JdbcSubscriptionRepository subscriptionRepo + ) { + super(chatRepo, linkRepo, subscriptionRepo); + } + + @Override + public int update() { + return 0; + } +} diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index 8fa269c..f4fa721 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -14,9 +14,12 @@ spring: application: name: scrapper liquibase: - enabled: true - autoconfigure: - exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + enabled: false + datasource: + driver-class-name: org.postgresql.Driver + url: "jdbc:postgresql://localhost:5432/scrapper" + username: "postgres" + password: "postgres" jackson: property-naming-strategy: SNAKE_CASE diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java new file mode 100644 index 0000000..77c65db --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/ChatRepositoryTest.java @@ -0,0 +1,75 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Chat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class ChatRepositoryTest extends IntegrationTest { + private static final long TG_ID = 11111; + private final ChatRepository repo; + + protected ChatRepositoryTest(ChatRepository repo) { + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Chat actual = repo.add(TG_ID); + Assertions.assertEquals(TG_ID, actual.tgId()); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + repo.add(TG_ID); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(TG_ID)); + } + + @Test + @Transactional + @Rollback + void findByTgIdTest() { + Chat expected = repo.add(TG_ID); + Chat actual = repo.findByTgId(TG_ID).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findByTgIdNotExistTest() { + Optional actual = repo.findByTgId(TG_ID); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + repo.add(TG_ID); + repo.remove(TG_ID); + Optional actual = repo.findByTgId(TG_ID); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + List expected = new ArrayList<>(); + expected.add(repo.add(TG_ID)); + expected.add(repo.add(22222)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java new file mode 100644 index 0000000..457c069 --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/LinkRepositoryTest.java @@ -0,0 +1,88 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Link; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class LinkRepositoryTest extends IntegrationTest { + private static final URI URL = + URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring/"); + private static final OffsetDateTime NOW = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + private final LinkRepository repo; + + protected LinkRepositoryTest(LinkRepository repo) { + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Link expected = new Link(null, URL, NOW, NOW); + Link actual = repo.add(expected); + Assertions.assertEquals(expected.url(), actual.url()); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + Link link = new Link(null, URL, NOW, NOW); + repo.add(link); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(link)); + } + + @Test + @Transactional + @Rollback + void findByUrlTest() { + Link link = new Link(null, URL, NOW, NOW); + Link expected = repo.add(link); + Link actual = repo.findByUrl(URL).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findByUrlNotExistTest() { + Optional actual = repo.findByUrl(URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + Link link = new Link(null, URL, NOW, NOW); + repo.add(link); + repo.remove(URL); + Optional actual = repo.findByUrl(URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + Link link1 = new Link(null, URL, NOW, NOW); + URI url2 = URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse/"); + Link link2 = new Link(null, url2, NOW, NOW); + List expected = new ArrayList<>(); + expected.add(repo.add(link1)); + expected.add(repo.add(link2)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java new file mode 100644 index 0000000..30ca69d --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/SubscriptionRepositoryTest.java @@ -0,0 +1,109 @@ +package edu.java.scrapper.api.domain.repository; + +import edu.java.scrapper.IntegrationTest; +import edu.java.scrapper.api.domain.dto.Chat; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import java.net.URI; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class SubscriptionRepositoryTest extends IntegrationTest { + private static final long TG_ID = 11111; + private static final URI URL = + URI.create("https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring/"); + private static final OffsetDateTime NOW = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + private final ChatRepository chatRepo; + private final LinkRepository linkRepo; + private final SubscriptionRepository repo; + + protected SubscriptionRepositoryTest(ChatRepository chatRepo, + LinkRepository linkRepo, SubscriptionRepository repo) { + this.chatRepo = chatRepo; + this.linkRepo = linkRepo; + this.repo = repo; + } + + @Test + @Transactional + @Rollback + void addTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription expected = new Subscription(chat.id(), link.id()); + Subscription actual = repo.add(expected); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void addDuplicateExceptionTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + repo.add(subscription); + Assertions.assertThrows(DuplicateKeyException.class, () -> repo.add(subscription)); + } + + @Test + @Transactional + @Rollback + void findTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + Subscription expected = repo.add(subscription); + Subscription actual = repo.find(TG_ID, URL).get(); + Assertions.assertEquals(expected, actual); + } + + @Test + @Transactional + @Rollback + void findNotExistTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + Optional actual = repo.find(TG_ID, URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void deleteTest() { + Chat chat = chatRepo.add(TG_ID); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription = new Subscription(chat.id(), link.id()); + repo.add(subscription); + repo.remove(subscription); + Optional actual = repo.find(TG_ID, URL); + Assertions.assertTrue(actual.isEmpty()); + } + + @Test + @Transactional + @Rollback + void findAllTest() { + Chat chat1 = chatRepo.add(TG_ID); + Chat chat2 = chatRepo.add(22222); + Link link = linkRepo.add(new Link(null, URL, NOW, NOW)); + Subscription subscription1 = new Subscription(chat1.id(), link.id()); + Subscription subscription2 = new Subscription(chat2.id(), link.id()); + List expected = new ArrayList<>(); + expected.add(repo.add(subscription1)); + expected.add(repo.add(subscription2)); + List actual = repo.findAll(); + Assertions.assertEquals(expected, actual); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java new file mode 100644 index 0000000..82f2c30 --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcChatRepositoryTest.java @@ -0,0 +1,14 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.ChatRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcChatRepositoryTest extends ChatRepositoryTest { + + @Autowired + protected JdbcChatRepositoryTest(JdbcChatRepository repo) { + super(repo); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java new file mode 100644 index 0000000..367d6fc --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepositoryTest.java @@ -0,0 +1,14 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.LinkRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcLinkRepositoryTest extends LinkRepositoryTest { + + @Autowired + protected JdbcLinkRepositoryTest(JdbcLinkRepository repo) { + super(repo); + } +} diff --git a/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java new file mode 100644 index 0000000..9f95afa --- /dev/null +++ b/scrapper/src/test/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepositoryTest.java @@ -0,0 +1,15 @@ +package edu.java.scrapper.api.domain.repository.jdbc; + +import edu.java.scrapper.api.domain.repository.SubscriptionRepositoryTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcSubscriptionRepositoryTest extends SubscriptionRepositoryTest { + + @Autowired + protected JdbcSubscriptionRepositoryTest(JdbcSubscriptionRepository repo, JdbcChatRepository chatRepo, + JdbcLinkRepository linkRepo) { + super(chatRepo, linkRepo, repo); + } +} From 0585d705a87e3e2b1ce43ffeea938e6e32c626ff Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 17 Mar 2024 23:57:26 +0300 Subject: [PATCH 25/34] feat: replace todo with services calls in scrapper controllers --- .../api/controller/ChatController.java | 22 +++++----- .../api/controller/LinkController.java | 44 +++++++++++-------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index f1696a2..7926fba 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,6 +1,9 @@ package edu.java.scrapper.api.controller; import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.service.ChatService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -17,6 +20,11 @@ @RestController @RequestMapping("/tg-chat") public class ChatController { + private final ChatService service; + + public ChatController(ChatService service) { + this.service = service; + } @Operation(summary = "Зарегистрировать чат") @ApiResponses(value = { @@ -26,11 +34,8 @@ public class ChatController { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @PostMapping("/{id}") - public ResponseEntity registerChat(@PathVariable @Positive long id) { - /* - TODO: регистрация чата - может быть брошено ChatRegistrationException - */ + public ResponseEntity registerChat(@PathVariable @Positive long id) throws ChatAlreadyRegisteredException { + service.register(id); return ResponseEntity.ok().build(); } @@ -45,11 +50,8 @@ public ResponseEntity registerChat(@PathVariable @Positive long id) { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @DeleteMapping("/{id}") - public ResponseEntity deleteChat(@PathVariable @Positive long id) { - /* - TODO: удаление чата - может быть брошено ChatNotFoundException - */ + public ResponseEntity deleteChat(@PathVariable @Positive long id) throws ChatNotFoundException { + service.unregister(id); return ResponseEntity.ok().build(); } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index 080211b..a57af05 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -5,6 +5,11 @@ import edu.java.api_dto.scrapper.LinkResponse; import edu.java.api_dto.scrapper.ListLinksResponse; import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.exception.chat.ChatNotFoundException; +import edu.java.scrapper.api.exception.link.LinkAdditionException; +import edu.java.scrapper.api.exception.link.LinkNotFoundException; +import edu.java.scrapper.api.service.LinkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,7 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; import java.net.URI; -import java.net.URISyntaxException; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -25,6 +30,11 @@ @RestController @RequestMapping("/links") public class LinkController { + private final LinkService service; + + public LinkController(LinkService service) { + this.service = service; + } @Operation(summary = "Получить все отслеживаемые ссылки") @ApiResponses(value = { @@ -36,11 +46,15 @@ public class LinkController { schema = @Schema(implementation = ApiErrorResponse.class))}) }) @GetMapping - public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat-Id") long chatId) { - /* - TODO: получение списка ссылок - */ - return ResponseEntity.ok(new ListLinksResponse(new LinkResponse[0], 1)); + public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat-Id") long chatId) + throws ChatNotFoundException { + List links = service.listAll(chatId); + return ResponseEntity.ok(new ListLinksResponse( + links.stream() + .map(l -> new LinkResponse(l.id(), l.url())) + .toArray(LinkResponse[]::new), + links.size() + )); } @Operation(summary = "Добавить отслеживание ссылки") @@ -56,12 +70,9 @@ public ResponseEntity getLinks(@RequestHeader(name = "Tg-Chat public ResponseEntity addLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody AddLinkRequest request - ) throws URISyntaxException { - /* - TODO: добавление ссылки - может быть брошено LinkAdditionException - */ - return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); + ) throws LinkAdditionException, ChatNotFoundException { + Link link = service.add(chatId, URI.create(request.link())); + return ResponseEntity.ok(new LinkResponse(link.id(), link.url())); } @Operation(summary = "Убрать отслеживание ссылки") @@ -80,11 +91,8 @@ public ResponseEntity addLink( public ResponseEntity deleteLink( @RequestHeader(name = "Tg-Chat-Id") long chatId, @Valid @RequestBody RemoveLinkRequest request - ) throws URISyntaxException { - /* - TODO: удаление ссылки - может быть брошено LinkNotFoundException - */ - return ResponseEntity.ok(new LinkResponse(0L, new URI(""))); + ) throws ChatNotFoundException, LinkNotFoundException { + Link link = service.remove(chatId, URI.create(request.link())); + return ResponseEntity.ok(new LinkResponse(link.id(), link.url())); } } From 815dc97106269778e687aebe512bece84aabee1d Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Thu, 21 Mar 2024 20:26:47 +0300 Subject: [PATCH 26/34] fix: db port and sql queries --- .../domain/repository/jdbc/JdbcSubscriptionRepository.java | 4 ++-- scrapper/src/main/resources/application.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java index 2c1abb9..31e8f7d 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -22,7 +22,7 @@ public JdbcSubscriptionRepository(JdbcClient client) { @Override public Optional find(long tgId, URI url) { return client.sql(""" - select subscription.chat_id, subscription.link_id + select subscription.* from subscription inner join chat on subscription.chat_id = chat.id inner join link on subscription.link_id = link.id @@ -79,7 +79,7 @@ public boolean linkNotFollowedByAnyone(long linkId) { @Override public List findAllLinksByChat(Chat chat) { return client.sql(""" - select link.id, link.url + select link.* from link inner join subscription on link.id = subscription.link_id where diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index f4fa721..b65ec42 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -17,7 +17,7 @@ spring: enabled: false datasource: driver-class-name: org.postgresql.Driver - url: "jdbc:postgresql://localhost:5432/scrapper" + url: "jdbc:postgresql://localhost:5433/scrapper" username: "postgres" password: "postgres" From 3486b87e3d48770b723483401d5b495490a13878 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Thu, 21 Mar 2024 23:50:01 +0300 Subject: [PATCH 27/34] feat: start link source parsers realization --- bot/pom.xml | 2 +- .../bot/api/controller/UpdateController.java | 4 +-- .../api/exception/ExceptionApiHandler.java | 2 +- .../java/bot/client/ScrapperApiException.java | 2 +- .../edu/java/bot/client/ScrapperClient.java | 10 +++--- .../bot/telegram/command/AbstractCommand.java | 2 +- .../java/bot/telegram/command/Command.java | 2 +- .../command/components/TrackCommand.java | 12 ++++--- .../command/components/UntrackCommand.java | 12 ++++--- .../main/java/edu/java/bot/utils/Link.java | 24 ------------- .../java/edu/java/bot/BotApplicationTest.java | 6 ++-- {api_dto => dto}/pom.xml | 2 +- .../java/dto/api}/bot/ApiErrorResponse.java | 2 +- .../java/dto/api}/bot/LinkUpdateRequest.java | 2 +- .../dto/api}/scrapper/AddLinkRequest.java | 2 +- .../dto/api}/scrapper/ApiErrorResponse.java | 2 +- .../java/dto/api}/scrapper/LinkResponse.java | 2 +- .../dto/api}/scrapper/ListLinksResponse.java | 2 +- .../dto/api}/scrapper/RemoveLinkRequest.java | 2 +- .../java/edu/java/dto/utils/LinkInfo.java | 7 ++++ .../java/edu/java/dto/utils/LinkParser.java | 35 ++++++++++++++++++ .../dto/utils/exception}/LinkException.java | 4 ++- .../exception}/LinkRegistrationException.java | 5 ++- .../utils/exception}/NotLinkException.java | 5 ++- .../SourceNotSupportedException.java | 10 ++++++ .../dto/utils/sources/info/GithubInfo.java | 19 ++++++++++ .../dto/utils/sources/info/SourceInfo.java | 5 +++ .../utils/sources/info/StackoverflowInfo.java | 13 +++++++ .../utils/sources/parsers/SourceParser.java | 36 +++++++++++++++++++ pom.xml | 2 +- scrapper/pom.xml | 2 +- .../api/controller/ChatController.java | 2 +- .../api/controller/LinkController.java | 10 +++--- .../api/domain/repository/LinkRepository.java | 5 +++ .../repository/jdbc/JdbcLinkRepository.java | 18 ++++++++++ .../chat/ChatExceptionApiHandler.java | 2 +- .../link/LinkExceptionApiHandler.java | 2 +- .../scrapper/api/service/ScrapperService.java | 5 ++- .../api/service/jdbc/JdbcChatService.java | 4 ++- .../api/service/jdbc/JdbcLinkService.java | 4 ++- .../api/service/jdbc/JdbcLinkUpdater.java | 20 +++++++++-- .../scrapper/client/bot/BotApiException.java | 2 +- .../java/scrapper/client/bot/BotClient.java | 4 +-- scrapper/src/main/resources/application.yml | 2 +- 44 files changed, 238 insertions(+), 79 deletions(-) delete mode 100644 bot/src/main/java/edu/java/bot/utils/Link.java rename {api_dto => dto}/pom.xml (96%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/bot/ApiErrorResponse.java (89%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/bot/LinkUpdateRequest.java (88%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/AddLinkRequest.java (86%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/ApiErrorResponse.java (88%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/LinkResponse.java (84%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/ListLinksResponse.java (84%) rename {api_dto/src/main/java/edu/java/api_dto => dto/src/main/java/edu/java/dto/api}/scrapper/RemoveLinkRequest.java (86%) create mode 100644 dto/src/main/java/edu/java/dto/utils/LinkInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/LinkParser.java rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/LinkException.java (64%) rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/LinkRegistrationException.java (63%) rename {bot/src/main/java/edu/java/bot/telegram/exception/link => dto/src/main/java/edu/java/dto/utils/exception}/NotLinkException.java (63%) create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java diff --git a/bot/pom.xml b/bot/pom.xml index e1391fc..21aab18 100644 --- a/bot/pom.xml +++ b/bot/pom.xml @@ -130,7 +130,7 @@ edu.java - api_dto + dto 0.1 diff --git a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java index 92fbab4..e2fd998 100644 --- a/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java +++ b/bot/src/main/java/edu/java/bot/api/controller/UpdateController.java @@ -1,7 +1,7 @@ package edu.java.bot.api.controller; -import edu.java.api_dto.bot.ApiErrorResponse; -import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.dto.api.bot.ApiErrorResponse; +import edu.java.dto.api.bot.LinkUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java index c75a289..57cfcb0 100644 --- a/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java +++ b/bot/src/main/java/edu/java/bot/api/exception/ExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.bot.api.exception; -import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.dto.api.bot.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java index 1fa2b6c..cbb465a 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperApiException.java @@ -1,6 +1,6 @@ package edu.java.bot.client; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import lombok.Getter; @Getter diff --git a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java index 577ca9c..07037a7 100644 --- a/bot/src/main/java/edu/java/bot/client/ScrapperClient.java +++ b/bot/src/main/java/edu/java/bot/client/ScrapperClient.java @@ -1,11 +1,11 @@ package edu.java.bot.client; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api_dto.scrapper.AddLinkRequest; -import edu.java.api_dto.scrapper.ApiErrorResponse; -import edu.java.api_dto.scrapper.LinkResponse; -import edu.java.api_dto.scrapper.ListLinksResponse; -import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.dto.api.scrapper.AddLinkRequest; +import edu.java.dto.api.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.LinkResponse; +import edu.java.dto.api.scrapper.ListLinksResponse; +import edu.java.dto.api.scrapper.RemoveLinkRequest; import lombok.NonNull; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatusCode; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java index a7a897c..9b4f36b 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractCommand.java @@ -5,8 +5,8 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; -import edu.java.bot.telegram.exception.link.LinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.exception.LinkException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/bot/src/main/java/edu/java/bot/telegram/command/Command.java b/bot/src/main/java/edu/java/bot/telegram/command/Command.java index 1d90049..874b01e 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/Command.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/Command.java @@ -3,8 +3,8 @@ import com.pengrad.telegrambot.model.Update; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.command.CommandException; -import edu.java.bot.telegram.exception.link.LinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.exception.LinkException; public interface Command { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 670a538..72d88b2 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -4,10 +4,11 @@ import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.bot.utils.Link; +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -31,10 +32,11 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException { + throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, + SourceNotSupportedException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - Link.parse(link); + new LinkParser(null).parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 40d974d..c566083 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -4,10 +4,11 @@ import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.bot.utils.Link; +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -31,10 +32,11 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException { + throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, + SourceNotSupportedException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - Link.parse(link); + new LinkParser(null).parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/utils/Link.java b/bot/src/main/java/edu/java/bot/utils/Link.java deleted file mode 100644 index 25504af..0000000 --- a/bot/src/main/java/edu/java/bot/utils/Link.java +++ /dev/null @@ -1,24 +0,0 @@ -package edu.java.bot.utils; - -import edu.java.bot.telegram.exception.link.NotLinkException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; - -public class Link { - private Link() { - } - - public static URL parse(String link) throws NotLinkException { - String url = link.toLowerCase(); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - throw new NotLinkException("У ссылки отсутствует протокол"); - } - try { - return new URI(link).toURL(); - } catch (MalformedURLException | URISyntaxException e) { - throw new NotLinkException("Неверная ссылка"); - } - } -} diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index 74221c2..e9e79ee 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -11,9 +11,9 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; -import edu.java.bot.telegram.exception.link.LinkException; -import edu.java.bot.telegram.exception.link.LinkRegistrationException; -import edu.java.bot.telegram.exception.link.NotLinkException; +import edu.java.dto.utils.exception.LinkException; +import edu.java.dto.utils.exception.LinkRegistrationException; +import edu.java.dto.utils.exception.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; diff --git a/api_dto/pom.xml b/dto/pom.xml similarity index 96% rename from api_dto/pom.xml rename to dto/pom.xml index 25f8f90..a9c9b8f 100644 --- a/api_dto/pom.xml +++ b/dto/pom.xml @@ -9,7 +9,7 @@ ${revision} - api_dto + dto ${revision} diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java b/dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java similarity index 89% rename from api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java rename to dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java index 943c66b..c760ecd 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/ApiErrorResponse.java +++ b/dto/src/main/java/edu/java/dto/api/bot/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.bot; +package edu.java.dto.api.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java b/dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java similarity index 88% rename from api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java rename to dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java index bd2d278..410fa0d 100644 --- a/api_dto/src/main/java/edu/java/api_dto/bot/LinkUpdateRequest.java +++ b/dto/src/main/java/edu/java/dto/api/bot/LinkUpdateRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.bot; +package edu.java.dto.api.bot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.net.URI; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java b/dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java similarity index 86% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java rename to dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java index 2399b04..a45ba0c 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/AddLinkRequest.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/AddLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java similarity index 88% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java index 45c7228..47752f1 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/ApiErrorResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java similarity index 84% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java index 91ca8c0..bf3d094 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/LinkResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/LinkResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.net.URI; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java b/dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java similarity index 84% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java rename to dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java index 5ff4bda..6393dce 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/ListLinksResponse.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/ListLinksResponse.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java b/dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java similarity index 86% rename from api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java rename to dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java index 049848a..1ed7b78 100644 --- a/api_dto/src/main/java/edu/java/api_dto/scrapper/RemoveLinkRequest.java +++ b/dto/src/main/java/edu/java/dto/api/scrapper/RemoveLinkRequest.java @@ -1,4 +1,4 @@ -package edu.java.api_dto.scrapper; +package edu.java.dto.api.scrapper; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.URL; diff --git a/dto/src/main/java/edu/java/dto/utils/LinkInfo.java b/dto/src/main/java/edu/java/dto/utils/LinkInfo.java new file mode 100644 index 0000000..f024812 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/LinkInfo.java @@ -0,0 +1,7 @@ +package edu.java.dto.utils; + +import edu.java.dto.utils.sources.info.SourceInfo; +import java.net.URI; + +public record LinkInfo(URI url, SourceInfo source) { +} diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java new file mode 100644 index 0000000..e4dd733 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -0,0 +1,35 @@ +package edu.java.dto.utils; + +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.parsers.SourceParser; +import java.net.URI; +import java.net.URISyntaxException; + +public class LinkParser { + private final SourceParser parser; + + public LinkParser(SourceParser parser) { + this.parser = parser; + } + + public LinkInfo parse(String link) throws NotLinkException, SourceNotSupportedException { + String url = link.toLowerCase(); + if (!url.startsWith("http://") && !url.startsWith("https://")) { + throw new NotLinkException("У ссылки отсутствует протокол"); + } + URI parsedUrl; + try { + parsedUrl = new URI(link); + } catch (URISyntaxException e) { + throw new NotLinkException("Неверная ссылка"); + } + try { + SourceInfo source = parser.parse(parsedUrl); + return new LinkInfo(parsedUrl, source); + } catch (SourceNotSupportedException e) { + throw new SourceNotSupportedException("Данный ресурс не поддерживается"); + } + } +} diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java b/dto/src/main/java/edu/java/dto/utils/exception/LinkException.java similarity index 64% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java rename to dto/src/main/java/edu/java/dto/utils/exception/LinkException.java index ffcba12..7a005b5 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/LinkException.java @@ -1,6 +1,8 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public abstract class LinkException extends Exception { + public LinkException() { + } public LinkException(String message) { super(message); diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java b/dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java similarity index 63% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java rename to dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java index 1d9c9b3..ce9eca7 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/LinkRegistrationException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/LinkRegistrationException.java @@ -1,6 +1,9 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public class LinkRegistrationException extends LinkException { + public LinkRegistrationException() { + } + public LinkRegistrationException(String message) { super(message); } diff --git a/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java b/dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java similarity index 63% rename from bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java rename to dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java index f04851c..8205cc3 100644 --- a/bot/src/main/java/edu/java/bot/telegram/exception/link/NotLinkException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/NotLinkException.java @@ -1,6 +1,9 @@ -package edu.java.bot.telegram.exception.link; +package edu.java.dto.utils.exception; public class NotLinkException extends LinkException { + public NotLinkException() { + } + public NotLinkException(String message) { super(message); } diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java new file mode 100644 index 0000000..a12cc2c --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public class SourceNotSupportedException extends LinkException { + public SourceNotSupportedException() { + } + + public SourceNotSupportedException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java new file mode 100644 index 0000000..011d85d --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java @@ -0,0 +1,19 @@ +package edu.java.dto.utils.sources.info; + +public class GithubInfo extends SourceInfo { + private final String author; + private final String repository; + + public GithubInfo(String author, String repository) { + this.author = author; + this.repository = repository; + } + + public String getAuthor() { + return author; + } + + public String getRepository() { + return repository; + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java new file mode 100644 index 0000000..aeeff17 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/SourceInfo.java @@ -0,0 +1,5 @@ +package edu.java.dto.utils.sources.info; + +public abstract class SourceInfo { + +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java new file mode 100644 index 0000000..b9269f8 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/StackoverflowInfo.java @@ -0,0 +1,13 @@ +package edu.java.dto.utils.sources.info; + +public class StackoverflowInfo extends SourceInfo { + private final long questionId; + + public StackoverflowInfo(long questionId) { + this.questionId = questionId; + } + + public long getQuestionId() { + return questionId; + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java new file mode 100644 index 0000000..ae915d9 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java @@ -0,0 +1,36 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.SourceInfo; +import java.net.URI; +import java.util.Set; + +public abstract class SourceParser { + protected SourceParser next; + + public void setNext(SourceParser next) { + this.next = next; + } + + public SourceInfo parse(URI url) throws SourceNotSupportedException { + try { + return parseSource(url); + } catch (SourceNotSupportedException e) { + if (next != null) { + return parse(url); + } + throw e; + } + } + + abstract SourceInfo parseSource(URI url) throws SourceNotSupportedException; + + public static SourceParser buildChain(Set parsers) { + SourceParser first = null; + for (SourceParser parser : parsers) { + parser.setNext(first); + first = parser; + } + return first; + } +} diff --git a/pom.xml b/pom.xml index 88935b8..02e04cf 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ bot scrapper - api_dto + dto diff --git a/scrapper/pom.xml b/scrapper/pom.xml index f1e90e3..b8833da 100644 --- a/scrapper/pom.xml +++ b/scrapper/pom.xml @@ -140,7 +140,7 @@ edu.java - api_dto + dto 0.1 compile diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java index 7926fba..25fff0f 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/ChatController.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.controller; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import edu.java.scrapper.api.exception.chat.ChatAlreadyRegisteredException; import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.service.ChatService; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java index a57af05..6f40192 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/controller/LinkController.java @@ -1,10 +1,10 @@ package edu.java.scrapper.api.controller; -import edu.java.api_dto.scrapper.AddLinkRequest; -import edu.java.api_dto.scrapper.ApiErrorResponse; -import edu.java.api_dto.scrapper.LinkResponse; -import edu.java.api_dto.scrapper.ListLinksResponse; -import edu.java.api_dto.scrapper.RemoveLinkRequest; +import edu.java.dto.api.scrapper.AddLinkRequest; +import edu.java.dto.api.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.LinkResponse; +import edu.java.dto.api.scrapper.ListLinksResponse; +import edu.java.dto.api.scrapper.RemoveLinkRequest; import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.exception.link.LinkAdditionException; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java index 1924aab..d9a323f 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/LinkRepository.java @@ -2,6 +2,7 @@ import edu.java.scrapper.api.domain.dto.Link; import java.net.URI; +import java.time.OffsetDateTime; import java.util.List; import java.util.Optional; @@ -17,4 +18,8 @@ public interface LinkRepository { void remove(long id); List findAll(); + + List findAllWithLastCheckOlderThan(OffsetDateTime time); + + void update(Link link); } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java index ce81751..7601691 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcLinkRepository.java @@ -3,6 +3,7 @@ import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.domain.repository.LinkRepository; import java.net.URI; +import java.time.OffsetDateTime; import java.util.List; import java.util.Optional; import org.springframework.jdbc.core.simple.JdbcClient; @@ -66,4 +67,21 @@ public List findAll() { .query(Link.class) .list(); } + + @Override + public List findAllWithLastCheckOlderThan(OffsetDateTime time) { + return client.sql("select * from link where link.last_check < ?") + .param(time) + .query(Link.class) + .list(); + } + + @Override + public void update(Link link) { + client.sql("update link set last_update = ?, last_check = ? where id = ?") + .param(link.lastUpdate()) + .param(link.lastCheck()) + .param(link.id()) + .update(); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java index 811b2e6..3a14e19 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/chat/ChatExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.exception.chat; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java index 3392519..d17e833 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/exception/link/LinkExceptionApiHandler.java @@ -1,6 +1,6 @@ package edu.java.scrapper.api.exception.link; -import edu.java.api_dto.scrapper.ApiErrorResponse; +import edu.java.dto.api.scrapper.ApiErrorResponse; import java.util.Arrays; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java index 455271f..3e79981 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/ScrapperService.java @@ -3,17 +3,20 @@ import edu.java.scrapper.api.domain.repository.ChatRepository; import edu.java.scrapper.api.domain.repository.LinkRepository; import edu.java.scrapper.api.domain.repository.SubscriptionRepository; +import edu.java.scrapper.configuration.ApplicationConfig; public abstract class ScrapperService { + protected final ApplicationConfig config; protected final ChatRepository chatRepo; protected final LinkRepository linkRepo; protected final SubscriptionRepository subscriptionRepo; protected ScrapperService( - ChatRepository chatRepo, + ApplicationConfig config, ChatRepository chatRepo, LinkRepository linkRepo, SubscriptionRepository subscriptionRepo ) { + this.config = config; this.chatRepo = chatRepo; this.linkRepo = linkRepo; this.subscriptionRepo = subscriptionRepo; diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index a7d5781..da3b543 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -9,6 +9,7 @@ import edu.java.scrapper.api.exception.chat.ChatNotFoundException; import edu.java.scrapper.api.service.ChatService; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; @@ -19,10 +20,11 @@ public class JdbcChatService extends ScrapperService implements ChatService { @Autowired protected JdbcChatService( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java index 3c0a1b0..d8be5b7 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -11,6 +11,7 @@ import edu.java.scrapper.api.exception.link.LinkNotFoundException; import edu.java.scrapper.api.service.LinkService; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; import java.net.URI; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -25,10 +26,11 @@ public class JdbcLinkService extends ScrapperService implements LinkService { @Autowired protected JdbcLinkService( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index 14fbde1..f832dc7 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -1,10 +1,17 @@ package edu.java.scrapper.api.service.jdbc; +import edu.java.scrapper.api.domain.dto.Link; import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; import edu.java.scrapper.api.service.LinkUpdater; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.configuration.ApplicationConfig; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -13,14 +20,23 @@ public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { @Autowired protected JdbcLinkUpdater( + ApplicationConfig config, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { - super(chatRepo, linkRepo, subscriptionRepo); + super(config, chatRepo, linkRepo, subscriptionRepo); } @Override public int update() { - return 0; + Duration checkDelay = config.scheduler().forceCheckDelay(); + OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS) + .minus(checkDelay); + List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck); + int countUpdates = 0; + for (Link link : linksNeedToCheck) { + + } + return countUpdates; } } diff --git a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java index 3e78df3..378c9be 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotApiException.java @@ -1,6 +1,6 @@ package edu.java.scrapper.client.bot; -import edu.java.api_dto.bot.ApiErrorResponse; +import edu.java.dto.api.bot.ApiErrorResponse; import lombok.Getter; @Getter diff --git a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java index 4ea3155..6cba112 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/bot/BotClient.java @@ -1,8 +1,8 @@ package edu.java.scrapper.client.bot; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.java.api_dto.bot.ApiErrorResponse; -import edu.java.api_dto.bot.LinkUpdateRequest; +import edu.java.dto.api.bot.ApiErrorResponse; +import edu.java.dto.api.bot.LinkUpdateRequest; import edu.java.scrapper.client.AbstractClient; import lombok.NonNull; import org.springframework.http.HttpStatusCode; diff --git a/scrapper/src/main/resources/application.yml b/scrapper/src/main/resources/application.yml index b65ec42..170d0be 100644 --- a/scrapper/src/main/resources/application.yml +++ b/scrapper/src/main/resources/application.yml @@ -2,7 +2,7 @@ app: scheduler: enable: true interval: 10000 - force-check-delay: 10000 + force-check-delay: 300000 resources: base-url: From 638feb2a7b7e556d89c61107c721aa74a49f4f30 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 17:44:00 +0300 Subject: [PATCH 28/34] feat: github and stackoverflow link parsers realizations --- .../bot/client/service/ScrapperService.java | 2 +- .../java/bot/configuration/CommandConfig.java | 21 +++++++ .../command/AbstractServiceCommand.java | 5 +- .../command/components/ListCommand.java | 5 +- .../command/components/StartCommand.java | 5 +- .../command/components/TrackCommand.java | 14 ++--- .../command/components/UntrackCommand.java | 14 ++--- .../java/edu/java/dto/utils/LinkParser.java | 56 +++++++++++++++---- .../exception/BadSourceUrlException.java | 10 ++++ .../dto/utils/exception/SourceException.java | 10 ++++ .../SourceNotSupportedException.java | 2 +- .../dto/utils/sources/info/GithubInfo.java | 18 +++--- .../utils/sources/parsers/GithubParser.java | 31 ++++++++++ .../utils/sources/parsers/SourceParser.java | 9 +-- .../sources/parsers/StackoverflowParser.java | 30 ++++++++++ 15 files changed, 185 insertions(+), 47 deletions(-) create mode 100644 bot/src/main/java/edu/java/bot/configuration/CommandConfig.java create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/exception/SourceException.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java create mode 100644 dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java diff --git a/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java index f3d8c22..abbce8d 100644 --- a/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java +++ b/bot/src/main/java/edu/java/bot/client/service/ScrapperService.java @@ -15,7 +15,7 @@ public ScrapperService() { public boolean isUserRegistered(Long userId) { // TODO: добавить работу с БД через scrapper log.info("%s. Проверка регистрации пользователя %d".formatted(LocalDateTime.now(), userId)); - return false; + return true; } public void registerUser(Long userId) { diff --git a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java new file mode 100644 index 0000000..5dd6c9a --- /dev/null +++ b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java @@ -0,0 +1,21 @@ +package edu.java.bot.configuration; + +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.sources.parsers.GithubParser; +import edu.java.dto.utils.sources.parsers.SourceParser; +import edu.java.dto.utils.sources.parsers.StackoverflowParser; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CommandConfig { + + @Bean + public LinkParser linkParser() { + return new LinkParser(SourceParser.buildChain(Set.of( + new GithubParser(), + new StackoverflowParser() + ))); + } +} diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index a78798c..2f43d5f 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,12 +1,15 @@ package edu.java.bot.telegram.command; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; + protected final CommandConfig config; - public AbstractServiceCommand(ScrapperService service) { + public AbstractServiceCommand(ScrapperService service, CommandConfig config) { this.service = service; + this.config = config; } public void setService(ScrapperService service) { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 1f6cd78..4029579 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,6 +1,7 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; @@ -14,8 +15,8 @@ @Order(5) public class ListCommand extends AbstractServiceCommand { - public ListCommand(ScrapperService service) { - super(service); + public ListCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index e4f0af0..3fed484 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,6 +1,7 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.parameter.ParameterException; @@ -11,8 +12,8 @@ @Order(1) public class StartCommand extends AbstractServiceCommand { - public StartCommand(ScrapperService service) { - super(service); + public StartCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index 72d88b2..f4766ab 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,14 +1,13 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; -import edu.java.dto.utils.exception.NotLinkException; -import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -16,8 +15,8 @@ @Order(3) public class TrackCommand extends AbstractServiceCommand { - public TrackCommand(ScrapperService service) { - super(service); + public TrackCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override @@ -32,11 +31,10 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, - SourceNotSupportedException { + throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - new LinkParser(null).parse(link); + config.linkParser().parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index c566083..75d5cd9 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,14 +1,13 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; +import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; -import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; -import edu.java.dto.utils.exception.NotLinkException; -import edu.java.dto.utils.exception.SourceNotSupportedException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -16,8 +15,8 @@ @Order(4) public class UntrackCommand extends AbstractServiceCommand { - public UntrackCommand(ScrapperService service) { - super(service); + public UntrackCommand(ScrapperService service, CommandConfig config) { + super(service, config); } @Override @@ -32,11 +31,10 @@ public String getDescription() { @Override protected String doAction(Long userId, String[] params) - throws ParameterException, NotLinkException, UnregisteredUserException, LinkRegistrationException, - SourceNotSupportedException { + throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - new LinkParser(null).parse(link); + config.linkParser().parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java index e4dd733..9a892ef 100644 --- a/dto/src/main/java/edu/java/dto/utils/LinkParser.java +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -1,34 +1,68 @@ package edu.java.dto.utils; import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceException; import edu.java.dto.utils.exception.SourceNotSupportedException; import edu.java.dto.utils.sources.info.SourceInfo; import edu.java.dto.utils.sources.parsers.SourceParser; +import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; public class LinkParser { + private static final String NOT_LINK_MESSAGE = "Неверная ссылка"; + private final SourceParser parser; + public LinkParser() { + parser = null; + } + public LinkParser(SourceParser parser) { this.parser = parser; } - public LinkInfo parse(String link) throws NotLinkException, SourceNotSupportedException { - String url = link.toLowerCase(); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - throw new NotLinkException("У ссылки отсутствует протокол"); - } - URI parsedUrl; + public LinkInfo parse(String link) throws NotLinkException, SourceException { + URI uri = tryMakeURI(link); + checkIsLinkAvailable(uri); + SourceInfo sourceInfo = tryParseSource(uri); + return new LinkInfo(uri, sourceInfo); + } + + private static URI tryMakeURI(String link) throws NotLinkException { try { - parsedUrl = new URI(link); + return new URI(link); } catch (URISyntaxException e) { - throw new NotLinkException("Неверная ссылка"); + throw new NotLinkException(NOT_LINK_MESSAGE); } + } + + private static void checkIsLinkAvailable(URI uri) throws NotLinkException { + HttpURLConnection connection = null; + try { + URL url = uri.toURL(); + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("HEAD"); + int response = connection.getResponseCode(); + if (response != HttpURLConnection.HTTP_OK) { + throw new NotLinkException("Ссылка не существует или недоступна"); + } + } catch (NotLinkException e) { + throw e; + } catch (Exception e) { + throw new NotLinkException(NOT_LINK_MESSAGE); + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } + + private SourceInfo tryParseSource(URI uri) throws SourceException { try { - SourceInfo source = parser.parse(parsedUrl); - return new LinkInfo(parsedUrl, source); - } catch (SourceNotSupportedException e) { + return parser.parse(uri); + } catch (NullPointerException | SourceNotSupportedException e) { throw new SourceNotSupportedException("Данный ресурс не поддерживается"); } } diff --git a/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java b/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java new file mode 100644 index 0000000..21bc38a --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/BadSourceUrlException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public class BadSourceUrlException extends SourceException { + public BadSourceUrlException() { + } + + public BadSourceUrlException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java new file mode 100644 index 0000000..6a1b06f --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceException.java @@ -0,0 +1,10 @@ +package edu.java.dto.utils.exception; + +public abstract class SourceException extends LinkException { + public SourceException() { + } + + public SourceException(String message) { + super(message); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java index a12cc2c..7dc2801 100644 --- a/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java +++ b/dto/src/main/java/edu/java/dto/utils/exception/SourceNotSupportedException.java @@ -1,6 +1,6 @@ package edu.java.dto.utils.exception; -public class SourceNotSupportedException extends LinkException { +public class SourceNotSupportedException extends SourceException { public SourceNotSupportedException() { } diff --git a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java index 011d85d..9262dfb 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/info/GithubInfo.java @@ -1,19 +1,19 @@ package edu.java.dto.utils.sources.info; public class GithubInfo extends SourceInfo { - private final String author; - private final String repository; + private final String owner; + private final String repo; - public GithubInfo(String author, String repository) { - this.author = author; - this.repository = repository; + public GithubInfo(String owner, String repo) { + this.owner = owner; + this.repo = repo; } - public String getAuthor() { - return author; + public String getOwner() { + return owner; } - public String getRepository() { - return repository; + public String getRepo() { + return repo; } } diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java new file mode 100644 index 0000000..62ec730 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java @@ -0,0 +1,31 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.BadSourceUrlException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.GithubInfo; +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GithubParser extends SourceParser { + private static final String BASE_PATTERN = "^https?://github.com"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.)?$"; + + @Override + GithubInfo parseSource(URI uri) throws SourceException { + String link = uri.toString(); + Pattern pattern = Pattern.compile(LINK_PATTERN); + Matcher matcher = pattern.matcher(link); + if (matcher.find()) { + String owner = matcher.group(1); + String repo = matcher.group(2); + return new GithubInfo(owner, repo); + } + if (link.matches(BASE_PATTERN + ".*")) { + throw new BadSourceUrlException("Некорретная ссылка для GitHub, требуется формат\n" + + "\"http(-s)://github.com/{owner}/{repo}[/...]\""); + } + throw new SourceNotSupportedException(); + } +} diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java index ae915d9..9a72fcf 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/SourceParser.java @@ -1,5 +1,6 @@ package edu.java.dto.utils.sources.parsers; +import edu.java.dto.utils.exception.SourceException; import edu.java.dto.utils.exception.SourceNotSupportedException; import edu.java.dto.utils.sources.info.SourceInfo; import java.net.URI; @@ -12,18 +13,18 @@ public void setNext(SourceParser next) { this.next = next; } - public SourceInfo parse(URI url) throws SourceNotSupportedException { + public SourceInfo parse(URI uri) throws SourceException { try { - return parseSource(url); + return parseSource(uri); } catch (SourceNotSupportedException e) { if (next != null) { - return parse(url); + return next.parse(uri); } throw e; } } - abstract SourceInfo parseSource(URI url) throws SourceNotSupportedException; + abstract SourceInfo parseSource(URI uri) throws SourceException; public static SourceParser buildChain(Set parsers) { SourceParser first = null; diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java new file mode 100644 index 0000000..b463a67 --- /dev/null +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java @@ -0,0 +1,30 @@ +package edu.java.dto.utils.sources.parsers; + +import edu.java.dto.utils.exception.BadSourceUrlException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.dto.utils.exception.SourceNotSupportedException; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import java.net.URI; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StackoverflowParser extends SourceParser { + private static final String BASE_PATTERN = "^https?://stackoverflow.com/questions"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)(/.)?$"; + + @Override + StackoverflowInfo parseSource(URI uri) throws SourceException { + String link = uri.toString(); + Pattern pattern = Pattern.compile(LINK_PATTERN); + Matcher matcher = pattern.matcher(link); + if (matcher.find()) { + long questionId = Long.parseLong(matcher.group(1)); + return new StackoverflowInfo(questionId); + } + if (link.matches(BASE_PATTERN + ".*")) { + throw new BadSourceUrlException("Некорретная ссылка для Stackoverflow, требуется формат\n" + + "\"http(-s)://stackoverflow.com/{questionId}[/...]\""); + } + throw new SourceNotSupportedException(); + } +} From a3fdc9f19c17b31feca19251237ea32f640e8b94 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 17:57:27 +0300 Subject: [PATCH 29/34] fix: change tests according to source parsers --- .../java/edu/java/bot/BotApplicationTest.java | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/bot/src/test/java/edu/java/bot/BotApplicationTest.java b/bot/src/test/java/edu/java/bot/BotApplicationTest.java index e9e79ee..51bea96 100644 --- a/bot/src/test/java/edu/java/bot/BotApplicationTest.java +++ b/bot/src/test/java/edu/java/bot/BotApplicationTest.java @@ -11,12 +11,14 @@ import edu.java.bot.telegram.exception.command.CommandException; import edu.java.bot.telegram.exception.command.CommandNotExistException; import edu.java.bot.telegram.exception.command.NotCommandException; +import edu.java.dto.utils.exception.BadSourceUrlException; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import edu.java.dto.utils.exception.NotLinkException; import edu.java.bot.telegram.exception.parameter.ParameterException; import edu.java.bot.telegram.exception.parameter.WrongNumberParametersException; import java.util.List; +import edu.java.dto.utils.exception.SourceNotSupportedException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -122,10 +124,10 @@ void helpTest() throws UnregisteredUserException, ParameterException, CommandExc void trackTest() throws UnregisteredUserException, ParameterException, CommandException, LinkException { service.setUserRegistered(true); service.setLinks(List.of()); - setMessage("/track https://github.com/cyberpanncake"); + setMessage("/track https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); String expected = "Ссылка добавлена в отслеживаемые"; - String actual = command.execute(updateMock); + String actual = command.execute(updateMock); Assertions.assertEquals(expected, actual); } @@ -138,18 +140,36 @@ void notLinkExceptionTest() throws CommandException { Assertions.assertThrows(NotLinkException.class, () -> command.execute(updateMock)); } + @Test + void sourceNotSupportedExceptionTest() throws CommandException { + service.setUserRegistered(true); + service.setLinks(List.of()); + setMessage("/track https://google.com"); + Command command = AbstractCommand.parse(updateMock, config.commands()); + Assertions.assertThrows(SourceNotSupportedException.class, () -> command.execute(updateMock)); + } + + @Test + void badSourceUrlExceptionTest() throws CommandException { + service.setUserRegistered(true); + service.setLinks(List.of()); + setMessage("/track https://github.com/cyberpanncake"); + Command command = AbstractCommand.parse(updateMock, config.commands()); + Assertions.assertThrows(BadSourceUrlException.class, () -> command.execute(updateMock)); + } + @Test void unregisteredUserExceptionTest() throws CommandException { service.setUserRegistered(false); service.setLinks(List.of()); - setMessage("/track https://github.com/cyberpanncake"); + setMessage("/track https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); Assertions.assertThrows(UnregisteredUserException.class, () -> command.execute(updateMock)); } @Test void linkRegisteredExceptionTest() throws CommandException { - String link = "https://github.com/cyberpanncake"; + String link = "https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"; service.setUserRegistered(true); service.setLinks(List.of(link)); setMessage("/track " + link); @@ -159,7 +179,7 @@ void linkRegisteredExceptionTest() throws CommandException { @Test void untrackTest() throws UnregisteredUserException, ParameterException, CommandException, LinkException { - String link = "https://github.com/cyberpanncake"; + String link = "https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"; service.setUserRegistered(true); service.setLinks(List.of(link)); setMessage("/untrack " + link); @@ -173,7 +193,7 @@ void untrackTest() throws UnregisteredUserException, ParameterException, Command void linkNotRegisteredExceptionTest() throws CommandException { service.setUserRegistered(true); service.setLinks(List.of()); - setMessage("/untrack https://github.com/cyberpanncake"); + setMessage("/untrack https://github.com/cyberpanncake/Torzhkova-Tinkoff-JavaBackendCourse-Spring"); Command command = AbstractCommand.parse(updateMock, config.commands()); Assertions.assertThrows(LinkRegistrationException.class, () -> command.execute(updateMock)); } From 3c8d6a946e9c9507b8567601aec578fd7f8e6d7f Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 18:11:54 +0300 Subject: [PATCH 30/34] feat: add setting to link parser, allows set http response check --- .../edu/java/bot/configuration/CommandConfig.java | 2 +- dto/src/main/java/edu/java/dto/utils/LinkParser.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java index 5dd6c9a..94af187 100644 --- a/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java +++ b/bot/src/main/java/edu/java/bot/configuration/CommandConfig.java @@ -16,6 +16,6 @@ public LinkParser linkParser() { return new LinkParser(SourceParser.buildChain(Set.of( new GithubParser(), new StackoverflowParser() - ))); + )), true); } } diff --git a/dto/src/main/java/edu/java/dto/utils/LinkParser.java b/dto/src/main/java/edu/java/dto/utils/LinkParser.java index 9a892ef..b1e2eef 100644 --- a/dto/src/main/java/edu/java/dto/utils/LinkParser.java +++ b/dto/src/main/java/edu/java/dto/utils/LinkParser.java @@ -12,20 +12,24 @@ public class LinkParser { private static final String NOT_LINK_MESSAGE = "Неверная ссылка"; - private final SourceParser parser; + private final boolean checkIsLinkAvailable; - public LinkParser() { + public LinkParser(boolean checkLinkAvailable) { + this.checkIsLinkAvailable = checkLinkAvailable; parser = null; } - public LinkParser(SourceParser parser) { + public LinkParser(SourceParser parser, boolean checkIsLinkAvailable) { this.parser = parser; + this.checkIsLinkAvailable = checkIsLinkAvailable; } public LinkInfo parse(String link) throws NotLinkException, SourceException { URI uri = tryMakeURI(link); - checkIsLinkAvailable(uri); + if (checkIsLinkAvailable) { + checkIsLinkAvailable(uri); + } SourceInfo sourceInfo = tryParseSource(uri); return new LinkInfo(uri, sourceInfo); } From 0c3e3d4612407d8837b465e6622220420c3a0992 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 21:55:22 +0300 Subject: [PATCH 31/34] fix: parsers regex --- .../java/edu/java/dto/utils/sources/parsers/GithubParser.java | 2 +- .../edu/java/dto/utils/sources/parsers/StackoverflowParser.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java index 62ec730..6e344c7 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/GithubParser.java @@ -10,7 +10,7 @@ public class GithubParser extends SourceParser { private static final String BASE_PATTERN = "^https?://github.com"; - private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.)?$"; + private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)/(.+?)(/.*)?$"; @Override GithubInfo parseSource(URI uri) throws SourceException { diff --git a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java index b463a67..3cd5935 100644 --- a/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java +++ b/dto/src/main/java/edu/java/dto/utils/sources/parsers/StackoverflowParser.java @@ -10,7 +10,7 @@ public class StackoverflowParser extends SourceParser { private static final String BASE_PATTERN = "^https?://stackoverflow.com/questions"; - private static final String LINK_PATTERN = BASE_PATTERN + "/(.+?)(/.)?$"; + private static final String LINK_PATTERN = BASE_PATTERN + "/([0-9]+?)(/.*)?$"; @Override StackoverflowInfo parseSource(URI uri) throws SourceException { From 048e850c82ec314c143bb6cec5e28d07e6f50be0 Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Sun, 24 Mar 2024 22:24:17 +0300 Subject: [PATCH 32/34] feat: tasks 3-4 (getting updates from sources and sending them to the bot) --- .../repository/SubscriptionRepository.java | 6 +- .../jdbc/JdbcSubscriptionRepository.java | 27 ++++++- .../api/service/jdbc/JdbcChatService.java | 2 +- .../api/service/jdbc/JdbcLinkUpdater.java | 75 +++++++++++++++++-- .../scrapper/client/sources/GithubClient.java | 6 +- .../configuration/LinkParserConfig.java | 21 ++++++ .../shedule/LinkUpdaterScheduler.java | 10 ++- .../scrapper/shedule/update/dto/Update.java | 13 ++++ .../shedule/update/sources/GithubUpdater.java | 22 ++++++ .../shedule/update/sources/SourceUpdater.java | 28 +++++++ .../update/sources/StackoverflowUpdater.java | 22 ++++++ 11 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java create mode 100644 scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java index c99a9cd..63c98d9 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/SubscriptionRepository.java @@ -16,9 +16,13 @@ public interface SubscriptionRepository { List findAll(); - List findAllByChat(long chatId); + List findAllByChat(Chat chat); + + List findAllByLink(Link link); boolean linkNotFollowedByAnyone(long linkId); List findAllLinksByChat(Chat chat); + + List findAllChatsByLink(Link link); } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java index 31e8f7d..91b9f27 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/domain/repository/jdbc/JdbcSubscriptionRepository.java @@ -60,13 +60,23 @@ public List findAll() { } @Override - public List findAllByChat(long chatId) { + public List findAllByChat(Chat chat) { return client.sql("select * from subscription where chat_id = ?") - .param(chatId) + .param(chat.id()) + .query(Subscription.class) + .list(); + } + + @SuppressWarnings("MultipleStringLiterals") + @Override + public List findAllByLink(Link link) { + return client.sql("select * from subscription where link_id = ?") + .param(link.id()) .query(Subscription.class) .list(); } + @SuppressWarnings("MultipleStringLiterals") @Override public boolean linkNotFollowedByAnyone(long linkId) { List subscriptions = client.sql("select * from subscription where link_id = ?") @@ -88,4 +98,17 @@ public List findAllLinksByChat(Chat chat) { .query(Link.class) .list(); } + + @Override + public List findAllChatsByLink(Link link) { + return client.sql(""" + select chat.* + from chat + inner join subscription on chat.id = subscription.chat_id + where + subscription.link_id = ?""") + .param(link.id()) + .query(Chat.class) + .list(); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index da3b543..7d001a0 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -42,7 +42,7 @@ public void unregister(long tgId) throws ChatNotFoundException { if (chat.isEmpty()) { throw new ChatNotFoundException(); } - List subscriptions = subscriptionRepo.findAllByChat(chat.get().id()); + List subscriptions = subscriptionRepo.findAllByChat(chat.get()); for (Subscription subscription : subscriptions) { subscriptionRepo.remove(subscription); if (subscriptionRepo.linkNotFollowedByAnyone(subscription.linkId())) { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index f832dc7..7bf9108 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -1,42 +1,107 @@ package edu.java.scrapper.api.service.jdbc; +import edu.java.dto.api.bot.LinkUpdateRequest; +import edu.java.dto.utils.LinkInfo; +import edu.java.dto.utils.exception.NotLinkException; +import edu.java.dto.utils.exception.SourceException; +import edu.java.scrapper.api.domain.dto.Chat; import edu.java.scrapper.api.domain.dto.Link; +import edu.java.scrapper.api.domain.dto.Subscription; import edu.java.scrapper.api.domain.repository.jdbc.JdbcChatRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcLinkRepository; import edu.java.scrapper.api.domain.repository.jdbc.JdbcSubscriptionRepository; import edu.java.scrapper.api.service.LinkUpdater; import edu.java.scrapper.api.service.ScrapperService; +import edu.java.scrapper.client.sources.ResponseException; import edu.java.scrapper.configuration.ApplicationConfig; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.configuration.LinkParserConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import edu.java.scrapper.shedule.update.sources.SourceUpdater; import java.time.Duration; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { + private final ClientConfig clientConfig; + private final LinkParserConfig parserConfig; @Autowired protected JdbcLinkUpdater( - ApplicationConfig config, + ApplicationConfig config, LinkParserConfig parserConfig, + ClientConfig clientConfig, JdbcChatRepository chatRepo, JdbcLinkRepository linkRepo, JdbcSubscriptionRepository subscriptionRepo ) { super(config, chatRepo, linkRepo, subscriptionRepo); + this.parserConfig = parserConfig; + this.clientConfig = clientConfig; } @Override public int update() { Duration checkDelay = config.scheduler().forceCheckDelay(); - OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS) - .minus(checkDelay); - List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck); + OffsetDateTime lastCheck = OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS); + List linksNeedToCheck = linkRepo.findAllWithLastCheckOlderThan(lastCheck.minus(checkDelay)); int countUpdates = 0; for (Link link : linksNeedToCheck) { - + linkRepo.update(new Link(link.id(), link.url(), link.lastUpdate(), lastCheck)); + try { + LinkInfo linkInfo = parserConfig.linkParser().parse(link.url().toString()); + Optional update = getUpdateFromSource(linkInfo); + if (update.isPresent() && update.get().getCreatedAt().isAfter(link.lastUpdate())) { + countUpdates++; + linkRepo.update(new Link(link.id(), link.url(), update.get().getCreatedAt(), lastCheck)); + processLinkUpdate(update.get(), link); + } + } catch (NotLinkException | SourceException | ResponseException e) { + removeCorruptedLinkWithSubscriptions(link); + } } return countUpdates; } + + private void processLinkUpdate(Update update, Link link) throws SourceException, NotLinkException { + List subscribers = subscriptionRepo.findAllChatsByLink(link); + if (subscribers.isEmpty()) { + linkRepo.remove(link.url()); + return; + } + clientConfig.botClient().sendUpdate(new LinkUpdateRequest( + link.id(), + link.url(), + "Новое обновление по ссылке\n%s\nСоздано в %s" + .formatted(link.url(), update.getCreatedAt()), + subscribers.stream().map(Chat::tgId).toArray(Long[]::new) + )); + } + + private Optional getUpdateFromSource(LinkInfo linkInfo) throws ResponseException { + SourceUpdater updater = SourceUpdater.getUpdaterForSource(clientConfig, linkInfo.source()); + if (updater != null) { + return updater.getUpdate(linkInfo.source()); + } + return Optional.empty(); + } + + private void removeCorruptedLinkWithSubscriptions(Link link) { + List subscribers = subscriptionRepo.findAllChatsByLink(link); + for (Chat subscriber : subscribers) { + Subscription subscription = new Subscription(subscriber.id(), link.id()); + subscriptionRepo.remove(subscription); + } + linkRepo.remove(link.url()); + clientConfig.botClient().sendUpdate(new LinkUpdateRequest( + link.id(), + link.url(), + "Ссылка\n" + link.url() + "\n больше не доступна, поэтому она удалена из Ваших подписок", + subscribers.stream().map(Chat::tgId).toArray(Long[]::new) + )); + } } diff --git a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java index dd696e8..365e794 100644 --- a/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java +++ b/scrapper/src/main/java/edu/java/scrapper/client/sources/GithubClient.java @@ -15,12 +15,12 @@ public GithubClient(String baseUrl, ObjectMapper mapper) { super(baseUrl, mapper); } - public Optional getUpdate(String author, String repository) throws ResponseException { + public Optional getUpdate(String owner, String repo) throws ResponseException { Mono jsonNodeMono = client.get() .uri(uriBuilder -> uriBuilder - .path("/repos/{author}/{repo}/events") + .path("/repos/{owner}/{repo}/events") .queryParam("per_page", 1) - .build(author, repository)) + .build(owner, repo)) .retrieve() .bodyToMono(JsonNode.class); try { diff --git a/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java b/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java new file mode 100644 index 0000000..852f10f --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/configuration/LinkParserConfig.java @@ -0,0 +1,21 @@ +package edu.java.scrapper.configuration; + +import edu.java.dto.utils.LinkParser; +import edu.java.dto.utils.sources.parsers.GithubParser; +import edu.java.dto.utils.sources.parsers.SourceParser; +import edu.java.dto.utils.sources.parsers.StackoverflowParser; +import java.util.Set; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LinkParserConfig { + + @Bean + public LinkParser linkParser() { + return new LinkParser(SourceParser.buildChain(Set.of( + new GithubParser(), + new StackoverflowParser() + )), false); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java index a7e2a78..b399eaf 100644 --- a/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/LinkUpdaterScheduler.java @@ -1,6 +1,8 @@ package edu.java.scrapper.shedule; +import edu.java.scrapper.api.service.LinkUpdater; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -9,9 +11,15 @@ @ConditionalOnProperty(value = "app.scheduler.enable", matchIfMissing = true) @Slf4j public class LinkUpdaterScheduler { + private final LinkUpdater updater; + + @Autowired + public LinkUpdaterScheduler(LinkUpdater updater) { + this.updater = updater; + } @Scheduled(fixedDelayString = "${app.scheduler.interval}") public void update() { - log.info("Обновление"); + updater.update(); } } diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java new file mode 100644 index 0000000..fee75d9 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/dto/Update.java @@ -0,0 +1,13 @@ +package edu.java.scrapper.shedule.update.dto; + +import java.time.OffsetDateTime; +import lombok.Getter; + +@Getter +public class Update { + protected final OffsetDateTime createdAt; + + public Update(OffsetDateTime createdAt) { + this.createdAt = createdAt; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java new file mode 100644 index 0000000..dd1e1b3 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/GithubUpdater.java @@ -0,0 +1,22 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.GithubInfo; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.dto.GithubResponse; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public class GithubUpdater extends SourceUpdater { + public GithubUpdater(ClientConfig config) { + super(config); + } + + @Override + public Optional getUpdate(SourceInfo sourceInfo) throws ResponseException { + GithubInfo info = (GithubInfo) sourceInfo; + Optional response = config.githubClient().getUpdate(info.getOwner(), info.getRepo()); + return response.map(stackoverflowResponse -> new Update(stackoverflowResponse.createdAt())); + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java new file mode 100644 index 0000000..a3c5e57 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/SourceUpdater.java @@ -0,0 +1,28 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.GithubInfo; +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public abstract class SourceUpdater { + protected final ClientConfig config; + + protected SourceUpdater(ClientConfig config) { + this.config = config; + } + + public abstract Optional getUpdate(SourceInfo sourceInfo) throws ResponseException; + + public static SourceUpdater getUpdaterForSource(ClientConfig config, SourceInfo sourceInfo) { + if (sourceInfo instanceof GithubInfo) { + return new GithubUpdater(config); + } else if (sourceInfo instanceof StackoverflowInfo) { + return new StackoverflowUpdater(config); + } + return null; + } +} diff --git a/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java new file mode 100644 index 0000000..b4b6a19 --- /dev/null +++ b/scrapper/src/main/java/edu/java/scrapper/shedule/update/sources/StackoverflowUpdater.java @@ -0,0 +1,22 @@ +package edu.java.scrapper.shedule.update.sources; + +import edu.java.dto.utils.sources.info.SourceInfo; +import edu.java.dto.utils.sources.info.StackoverflowInfo; +import edu.java.scrapper.client.sources.ResponseException; +import edu.java.scrapper.client.sources.dto.StackoverflowResponse; +import edu.java.scrapper.configuration.ClientConfig; +import edu.java.scrapper.shedule.update.dto.Update; +import java.util.Optional; + +public class StackoverflowUpdater extends SourceUpdater { + public StackoverflowUpdater(ClientConfig config) { + super(config); + } + + @Override + public Optional getUpdate(SourceInfo sourceInfo) throws ResponseException { + StackoverflowInfo info = (StackoverflowInfo) sourceInfo; + Optional response = config.stackoverflowClient().getUpdate(info.getQuestionId()); + return response.map(stackoverflowResponse -> new Update(stackoverflowResponse.lastActivityDate())); + } +} From 071911187bcbd6709123a58356b822e649e557ab Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Fri, 5 Apr 2024 00:09:49 +0300 Subject: [PATCH 33/34] fix: remove config injection in commands, add bean injection instead --- .../bot/telegram/command/AbstractServiceCommand.java | 5 +---- .../bot/telegram/command/components/ListCommand.java | 5 ++--- .../bot/telegram/command/components/StartCommand.java | 5 ++--- .../bot/telegram/command/components/TrackCommand.java | 10 ++++++---- .../telegram/command/components/UntrackCommand.java | 10 ++++++---- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java index 2f43d5f..a78798c 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/AbstractServiceCommand.java @@ -1,15 +1,12 @@ package edu.java.bot.telegram.command; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; public abstract class AbstractServiceCommand extends AbstractCommand { protected ScrapperService service; - protected final CommandConfig config; - public AbstractServiceCommand(ScrapperService service, CommandConfig config) { + public AbstractServiceCommand(ScrapperService service) { this.service = service; - this.config = config; } public void setService(ScrapperService service) { diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java index 4029579..1f6cd78 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/ListCommand.java @@ -1,7 +1,6 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; @@ -15,8 +14,8 @@ @Order(5) public class ListCommand extends AbstractServiceCommand { - public ListCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public ListCommand(ScrapperService service) { + super(service); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java index 3fed484..e4f0af0 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/StartCommand.java @@ -1,7 +1,6 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.parameter.ParameterException; @@ -12,8 +11,8 @@ @Order(1) public class StartCommand extends AbstractServiceCommand { - public StartCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public StartCommand(ScrapperService service) { + super(service); } @Override diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java index f4766ab..09a061c 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/TrackCommand.java @@ -1,11 +1,11 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.LinkParser; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import org.springframework.core.annotation.Order; @@ -14,9 +14,11 @@ @Component @Order(3) public class TrackCommand extends AbstractServiceCommand { + private final LinkParser parser; - public TrackCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public TrackCommand(ScrapperService service, LinkParser parser) { + super(service); + this.parser = parser; } @Override @@ -34,7 +36,7 @@ protected String doAction(Long userId, String[] params) throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - config.linkParser().parse(link); + parser.parse(link); CommandUtils.checkUserRegistration(userId, service); if (service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка уже зарегистрирована"); diff --git a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java index 75d5cd9..c828b4f 100644 --- a/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java +++ b/bot/src/main/java/edu/java/bot/telegram/command/components/UntrackCommand.java @@ -1,11 +1,11 @@ package edu.java.bot.telegram.command.components; import edu.java.bot.client.service.ScrapperService; -import edu.java.bot.configuration.CommandConfig; import edu.java.bot.telegram.command.AbstractServiceCommand; import edu.java.bot.telegram.command.CommandUtils; import edu.java.bot.telegram.exception.UnregisteredUserException; import edu.java.bot.telegram.exception.parameter.ParameterException; +import edu.java.dto.utils.LinkParser; import edu.java.dto.utils.exception.LinkException; import edu.java.dto.utils.exception.LinkRegistrationException; import org.springframework.core.annotation.Order; @@ -14,9 +14,11 @@ @Component @Order(4) public class UntrackCommand extends AbstractServiceCommand { + private final LinkParser parser; - public UntrackCommand(ScrapperService service, CommandConfig config) { - super(service, config); + public UntrackCommand(ScrapperService service, LinkParser parser) { + super(service); + this.parser = parser; } @Override @@ -34,7 +36,7 @@ protected String doAction(Long userId, String[] params) throws ParameterException, UnregisteredUserException, LinkException { CommandUtils.checkParamsNumber(params, 1); String link = params[0]; - config.linkParser().parse(link); + parser.parse(link); CommandUtils.checkUserRegistration(userId, service); if (!service.isLinkRegistered(userId, link)) { throw new LinkRegistrationException("Ссылка не была зарегистрирована"); From 9fc97483de09b1cf2fd52c5c6c4867aeec38231d Mon Sep 17 00:00:00 2001 From: cyberpanncake Date: Fri, 5 Apr 2024 00:21:20 +0300 Subject: [PATCH 34/34] fix: add transactional annotations to jdbc services --- .../edu/java/scrapper/api/service/jdbc/JdbcChatService.java | 2 ++ .../edu/java/scrapper/api/service/jdbc/JdbcLinkService.java | 2 ++ .../edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java index 7d001a0..47a2b31 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcChatService.java @@ -14,7 +14,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcChatService extends ScrapperService implements ChatService { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java index d8be5b7..ce6a854 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkService.java @@ -20,7 +20,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcLinkService extends ScrapperService implements LinkService { diff --git a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java index 7bf9108..7342648 100644 --- a/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java +++ b/scrapper/src/main/java/edu/java/scrapper/api/service/jdbc/JdbcLinkUpdater.java @@ -26,7 +26,9 @@ import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional @Service public class JdbcLinkUpdater extends ScrapperService implements LinkUpdater { private final ClientConfig clientConfig;