Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
171 commits
Select commit Hold shift + click to select a range
7427b3b
init
Delphington Feb 5, 2025
eb04dff
feat: struct of bot with command
Delphington Feb 6, 2025
a2611c0
feat: action command start
Delphington Feb 6, 2025
521b81f
feat: action command help
Delphington Feb 6, 2025
2c6202c
feat: logic of all commands
Delphington Feb 6, 2025
eb1ee86
refactoring
Delphington Feb 6, 2025
b413fd2
feat: github API
Delphington Feb 7, 2025
3e82ee3
feat: github API
Delphington Feb 7, 2025
76b85f4
feat: separate SchedulerConfig
Delphington Feb 7, 2025
d96fcdc
feat: separate SchedulerConfig
Delphington Feb 7, 2025
3bf98ed
feat: add token github
Delphington Feb 7, 2025
4360b2b
feat: add stackOverFlow API
Delphington Feb 8, 2025
6b2479e
feat: API bot
Delphington Feb 9, 2025
87db130
feat: API Scrapper
Delphington Feb 9, 2025
d515878
refactoring: API Bot
Delphington Feb 9, 2025
6f41ddf
refactoring: API Bot
Delphington Feb 9, 2025
d0e6090
refactoring: API Bot
Delphington Feb 9, 2025
bf7ba93
refactoring: API Scrapping
Delphington Feb 9, 2025
b741d5d
refactoring: API Scrapping
Delphington Feb 10, 2025
79b8b3a
feat: logic service Scrapping
Delphington Feb 10, 2025
7ffcb1b
feat: ScraperClient TelegramBotClient
Delphington Feb 10, 2025
8f22858
feat: logic with chat
Delphington Feb 11, 2025
4ce0a08
feat: update logic startCommand and HelpCommand
Delphington Feb 11, 2025
c64699c
feat: update logic trackCommand
Delphington Feb 11, 2025
1ce4636
feat: update logic untrackCommand
Delphington Feb 11, 2025
314c08e
feat: update logic listCommand
Delphington Feb 11, 2025
6513ec6
refactoring
Delphington Feb 11, 2025
d36c1ab
feat: valid for command
Delphington Feb 12, 2025
0d128f3
feat: send info to UpdateController
Delphington Feb 12, 2025
b80d0f0
feat: update info from stackOverFlow
Delphington Feb 12, 2025
3793574
feat: tags and links
Delphington Feb 14, 2025
b7d86f2
refactoring
Delphington Feb 14, 2025
ecd5044
refactoring
Delphington Feb 14, 2025
ab358c7
refactoring
Delphington Feb 15, 2025
a18d0b0
refactoring
Delphington Feb 15, 2025
db25980
feat: test for Controllers Scrapper
Delphington Feb 22, 2025
c0e4276
refactoring
Delphington Feb 22, 2025
d86cabe
feat: test command
Delphington Feb 22, 2025
d6eacd1
feat: test bot
Delphington Feb 23, 2025
02548d5
feat: test scapper
Delphington Feb 23, 2025
450c470
feat: Structural logging Bot
Delphington Feb 23, 2025
140c816
feat: test scrapper
Delphington Feb 23, 2025
3803e9c
feat: Structural logging scrapper
Delphington Feb 23, 2025
b7fda68
update README.md
Delphington Feb 23, 2025
c38425a
feat: checkstyle
Delphington Feb 25, 2025
b1f3b22
refactoring: checkstyle
Delphington Feb 25, 2025
c8dddee
refactoring: checkstyle
Delphington Feb 25, 2025
3d0f1cd
refactoring: checkstyle
Delphington Feb 25, 2025
42f7165
refactoring: checkstyle
Delphington Feb 25, 2025
bce6fff
refactoring: checkstyle
Delphington Feb 25, 2025
c413c21
refactoring: checkstyle
Delphington Feb 25, 2025
99ddb04
refactoring
Delphington Feb 25, 2025
5b3b538
refactoring
Delphington Feb 25, 2025
7509752
refactoring: test
Delphington Feb 25, 2025
519a3f4
update
Delphington Mar 1, 2025
29ef281
feat: additional info about GitHub and StackOverFlow
Delphington Mar 6, 2025
f94cc18
feat: DB chat
Delphington Mar 6, 2025
5037f10
feat: DB link
Delphington Mar 7, 2025
b653c22
refactoring
Delphington Mar 7, 2025
36b3a5a
feat: scheduler BD
Delphington Mar 7, 2025
50d9a82
refactoring
Delphington Mar 7, 2025
bf8b0c9
feat: jdbc chat
Delphington Mar 8, 2025
6749be5
feat: jdbc link
Delphington Mar 9, 2025
c7ca93b
feat: pagination
Delphington Mar 9, 2025
657ef4a
feat: The interface for the scrapper -> bot notification sending serv…
Delphington Mar 9, 2025
43fe2ea
feat: migrations
Delphington Mar 9, 2025
be72b65
refactoring
Delphington Mar 9, 2025
5180703
refactoring
Delphington Mar 9, 2025
a31bd82
feat: command /tag
Delphington Mar 10, 2025
322820c
feat: tests of DAO
Delphington Mar 11, 2025
ce2ccbf
feat: split BD add new tables
Delphington Mar 14, 2025
a8fc16d
feat: jdbc Module
Delphington Mar 14, 2025
917a5cb
feat: tag with ORM
Delphington Mar 15, 2025
9d4f16b
feat: tag with JDBC
Delphington Mar 15, 2025
9ac0a48
feat: tag with Spring Jdbc
Delphington Mar 15, 2025
4eb6500
feat: refactoring
Delphington Mar 15, 2025
c05adec
feat: refactoring
Delphington Mar 15, 2025
393ecdf
feat: refactoring
Delphington Mar 15, 2025
585f181
feat: refactoring
Delphington Mar 16, 2025
aacfecf
refactoring
Delphington Mar 16, 2025
e8ff51e
refactoring
Delphington Mar 16, 2025
6892a82
refactoring
Delphington Mar 16, 2025
057aa60
refactoring
Delphington Mar 16, 2025
bf3d969
refactoring
Delphington Mar 16, 2025
057c133
refactoring
Delphington Mar 16, 2025
02330b7
refactoring
Delphington Mar 16, 2025
3ca902f
refactoring
Delphington Mar 16, 2025
ff13b4b
refactoring
Delphington Mar 16, 2025
4411bdd
refactoring
Delphington Mar 17, 2025
04a7d38
feat: test for DAO
Delphington Mar 17, 2025
b8a825a
refactoring
Delphington Mar 17, 2025
7b21e08
feat: add tests
Delphington Mar 18, 2025
854f786
refactoring
Delphington Mar 20, 2025
289749e
fix: PR
Delphington Apr 1, 2025
fecbd55
fix: PR
Delphington Apr 7, 2025
fd6c26b
fix: PR
Delphington Apr 7, 2025
397376a
refactoring
Delphington Apr 7, 2025
a68968f
refactoring
Delphington Apr 7, 2025
35ab7b3
refactoring
Delphington Apr 7, 2025
dc4327e
feat: redis cache
Delphington Apr 8, 2025
5b5fdf5
feat: redis cache
Delphington Apr 8, 2025
69de138
feat: kafka
Delphington Apr 9, 2025
df0fcd9
feat: send message by time
Delphington Apr 10, 2025
f2c4285
feat: kafka topic for bad link
Delphington Apr 11, 2025
3da1f58
feat: add migrations filters
Delphington Apr 11, 2025
15d00aa
feat: bot filter module
Delphington Apr 12, 2025
cef1bf1
feat: scrapper filter module
Delphington Apr 12, 2025
3a7796e
feat: orm filter module
Delphington Apr 12, 2025
23f133d
feat: jdbc filter module
Delphington Apr 12, 2025
7be7cc5
feat: jdbc filter module
Delphington Apr 13, 2025
85520a2
refactoring
Delphington Apr 13, 2025
813a68a
fix: bugs
Delphington Apr 13, 2025
a208be6
refactoring
Delphington Apr 13, 2025
4490a76
refactoring
Delphington Apr 13, 2025
5e6c5d6
refactoring
Delphington Apr 13, 2025
902922b
feat: unit tests for command
Delphington Apr 16, 2025
c9d24df
feat: unit tests for redis
Delphington Apr 16, 2025
d84ca5a
feat: all init test for bot
Delphington Apr 16, 2025
bd2b5ea
test: integration Redis
Delphington Apr 16, 2025
4a11100
test: integration Redis
Delphington Apr 17, 2025
dee8b5e
refactoring
Delphington Apr 19, 2025
7f392c4
refactoring
Delphington Apr 19, 2025
9043757
refactoring
Delphington Apr 19, 2025
7ad7a20
test: Scraper Controllers
Delphington Apr 19, 2025
f384301
test: Scraper Dao
Delphington Apr 20, 2025
5d00a15
test: Scraper Dao
Delphington Apr 20, 2025
0a2084a
test: Scraper service
Delphington Apr 20, 2025
6ae45da
refactoring
Delphington Apr 20, 2025
2c81546
refactoring
Delphington Apr 20, 2025
beb8b57
refactoring
Delphington Apr 20, 2025
b39c260
test: scrapper
Delphington Apr 20, 2025
3cbe138
test: kafka
Delphington Apr 21, 2025
a943af0
refactoring
Delphington Apr 21, 2025
f1e1b3d
refactoring
Delphington Apr 22, 2025
38556d1
feat: timeout
Delphington Apr 23, 2025
ef6cbb2
feat: retry
Delphington Apr 24, 2025
a5b3e44
refactoring
Delphington Apr 24, 2025
20264d1
refactoring
Delphington Apr 24, 2025
c8d355c
fix: PR errors
Delphington Apr 24, 2025
0ce5cb3
feat: Rate Limiting
Delphington Apr 25, 2025
9163e2f
refactoring
Delphington Apr 25, 2025
a65369a
feat: decomposition ScrapperClient
Delphington Apr 25, 2025
fb2f2b7
feat: decomposition ScrapperClient
Delphington Apr 25, 2025
2b229f4
feat: CircuitBreaker first
Delphington Apr 28, 2025
7ce5d01
feat: CircuitBreaker
Delphington Apr 28, 2025
8d48fac
Revert "feat: CircuitBreaker"
Delphington May 3, 2025
89f2cc6
feat: CircuitBreaker
Delphington May 3, 2025
59b1ab4
feat: CircuitBreaker kafka/http
Delphington May 4, 2025
5b66807
feat: CircuitBreaker kafka/http
Delphington May 4, 2025
840f977
refactoring
Delphington May 4, 2025
e7a623c
refactoring
Delphington May 4, 2025
3909d15
refactoring
Delphington May 4, 2025
2baed36
refactoring
Delphington May 4, 2025
e442cca
refactoring
Delphington May 4, 2025
d52eb7e
refactoring
Delphington May 4, 2025
84f99e9
refactoring
Delphington May 4, 2025
54a03c5
refactoring
Delphington May 4, 2025
60df3c9
fix: PR
Delphington May 4, 2025
f64d33a
fix: PR
Delphington May 4, 2025
ad1bc1f
fix: PR
Delphington May 4, 2025
059d49f
fix: PR
Delphington May 4, 2025
64816ab
fix: PR
Delphington May 4, 2025
61b8ef0
fix: PR
Delphington May 4, 2025
0095463
feat: retry test tgClient
Delphington May 7, 2025
1f208af
feat: fallback test tgClient
Delphington May 7, 2025
5fc5570
feat: bot retry tests
Delphington May 8, 2025
e7e8ee4
feat: bot CircuitBreaker tests
Delphington May 8, 2025
6d173fd
test: rate limit scrapper
Delphington May 8, 2025
f462a7c
refactoring
Delphington May 8, 2025
68cf8f9
refactoring
Delphington May 8, 2025
991421b
refactoring
Delphington May 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ on:

jobs:
build:
runs-on: ubuntu-latest
runs-on: edu-self-hosted
container:
image: maven:3-eclipse-temurin-24
timeout-minutes: 10
name: Build
permissions:
contents: read
Expand Down Expand Up @@ -37,7 +40,10 @@ jobs:

linter:
name: linter
runs-on: ubuntu-latest
runs-on: edu-self-hosted
container:
image: maven:3-eclipse-temurin-24
timeout-minutes: 10
permissions:
contents: read
packages: write
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

# Link Tracker

----

Чтобы бот заработал нужно в переменные среды загрузить TELEGRAM_TOKEN

----

<!-- этот файл можно и нужно менять -->

Проект сделан в рамках курса Академия Бэкенда.
Expand Down
67 changes: 56 additions & 11 deletions bot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<groupId>backend.academy</groupId>
<artifactId>root</artifactId>
<version>${revision}</version>

</parent>

<artifactId>bot</artifactId>
Expand Down Expand Up @@ -43,11 +44,11 @@
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- Kafka -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.kafka</groupId>-->
<!-- <artifactId>spring-kafka</artifactId>-->
<!-- </dependency>-->
<!-- Kafka-->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>

<!-- Actuator -->
<dependency>
Expand Down Expand Up @@ -87,6 +88,7 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
Expand All @@ -112,11 +114,55 @@
<artifactId>kafka</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.kafka</groupId>-->
<!-- <artifactId>spring-kafka-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.1</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-reactor</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20.1</version>
</dependency>

<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j-core</artifactId>
<version>8.7.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-contract-wiremock -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-wiremock</artifactId>
<version>4.2.1</version>
</dependency>

</dependencies>

<build>
Expand All @@ -125,7 +171,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<!-- To build OCI image: https://docs.spring.io/spring-boot/maven-plugin/build-image.html -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
Expand Down
8 changes: 7 additions & 1 deletion bot/src/main/java/backend/academy/bot/BotApplication.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package backend.academy.bot;

import backend.academy.bot.config.BotConfig;
import backend.academy.bot.limit.RateLimitProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableConfigurationProperties({BotConfig.class})
@EnableConfigurationProperties({BotConfig.class, RateLimitProperties.class})
@EnableScheduling
@EnableRetry
public class BotApplication {
public static void main(String[] args) {
SpringApplication.run(BotApplication.class, args);
Expand Down
31 changes: 31 additions & 0 deletions bot/src/main/java/backend/academy/bot/LinkTrackerBot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package backend.academy.bot;

import backend.academy.bot.listener.MessageListener;
import backend.academy.bot.processor.UserMessageProcessor;
import com.pengrad.telegrambot.TelegramBot;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Getter
@Component
public class LinkTrackerBot implements AutoCloseable {

private final TelegramBot telegramBot;
private final MessageListener messageListener;
private final UserMessageProcessor userMessageProcessor;

@PostConstruct
public void init() {
telegramBot.setUpdatesListener(messageListener);
// Регистрируем команды при запуске
userMessageProcessor.registerCommands();
}

@Override
public void close() {
telegramBot.shutdown();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package backend.academy.bot.api.controller;

import backend.academy.bot.api.dto.request.LinkUpdate;
import backend.academy.bot.notification.NotificationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@Slf4j
@RestController
public class UpdateController {

private final NotificationService notificationService;

@Operation(summary = "Отправить обновление")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Обновление обработано")})
@ResponseStatus(HttpStatus.OK)
@PostMapping("/updates")
public void update(@RequestBody @Valid LinkUpdate linkUpdate) {
log.info("Пришло обновление по ссылке");
notificationService.sendMessage(linkUpdate);
}

@PostMapping("/public")
public void update() {
log.info("Пришло обновление по ссылке");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package backend.academy.bot.api.dto.kafka;

public record BadLink(Long id, String url) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package backend.academy.bot.api.dto.request;

import jakarta.validation.constraints.NotNull;
import java.net.URI;
import java.util.List;

public record AddLinkRequest(
@NotNull(message = "URL не может быть пустым") URI link, List<String> tags, List<String> filters) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package backend.academy.bot.api.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import java.net.URI;
import java.util.List;

public record LinkUpdate(
@NotNull(message = "chatId не может быть null")
@Positive(message = "chatId может принимать только положительные значения")
Long id,
@NotNull(message = "URL не может быть null") URI url,
@NotNull(message = "description не может быть null") @NotBlank(message = "Описание не может быть пустым")
String description,
@NotNull(message = "Список ID чатов не может быть null") List<Long> tgChatIds) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package backend.academy.bot.api.dto.request;

import jakarta.validation.constraints.NotNull;
import java.net.URI;

public record RemoveLinkRequest(@NotNull(message = "URL не может быть пустым") URI link) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.academy.bot.api.dto.request.filter;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record FilterRequest(
@NotBlank @Size(max = 50, message = "Длина фильтра не должна превышать 50 символов") String filter) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.academy.bot.api.dto.request.tag;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record TagLinkRequest(
@NotBlank @Size(max = 50, message = "Длина тега не должна превышать 50 символов") String tag) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package backend.academy.bot.api.dto.request.tag;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.net.URI;

public record TagRemoveRequest(
@NotBlank @Size(max = 50, message = "Длина тега не должна превышать 50 символов") String tag,
@NotNull(message = "URL не может быть пустым") URI uri) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package backend.academy.bot.api.dto.response;

import jakarta.validation.constraints.NotBlank;
import java.util.List;

public record ApiErrorResponse(
@NotBlank(message = "description не может быть пустым") String description,
@NotBlank(message = "code не может быть пустым") String code,
String exceptionName,
String exceptionMessage,
List<String> stacktrace) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package backend.academy.bot.api.dto.response;

import java.net.URI;
import java.util.List;

public record LinkResponse(Long id, URI url, List<String> tags, List<String> filters) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package backend.academy.bot.api.dto.response;

import java.util.List;

public record ListLinksResponse(List<LinkResponse> links, Integer size) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package backend.academy.bot.api.dto.response;

import java.util.List;

public record TagListResponse(List<String> tags) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package backend.academy.bot.api.dto.response.filter;

import java.util.List;

public record FilterListResponse(List<FilterResponse> filterList) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.academy.bot.api.dto.response.filter;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record FilterResponse(
Long id, @NotBlank @Size(max = 50, message = "Длина фильтра не должна превышать 50 символов") String filter) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package backend.academy.bot.api.exception;

import backend.academy.bot.api.dto.response.ApiErrorResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ApiResponses(value = {@ApiResponse(responseCode = "400", description = "Некорректные параметры запроса")})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
log.error("GlobalExceptionHandler: ОШИБКА valid: {}", ex.getMessage());

return new ApiErrorResponse(
"Некорректные параметры запроса",
"VALIDATION_ERROR",
ex.getClass().getSimpleName(),
ex.getMessage(),
getStackTrace(ex));
}

@ApiResponses(value = {@ApiResponse(responseCode = "400", description = "Некорректные параметры запроса")})
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiErrorResponse handleSerializeException(HttpMessageNotReadableException ex) {
log.error("Ошибка десcериализации: {}", ex.getMessage());
List<String> stacktrace = getStackTrace(ex);
return new ApiErrorResponse(
"Некорректные параметры запроса", "BAD_REQUEST", ex.getClass().getName(), ex.getMessage(), stacktrace);
}

private List<String> getStackTrace(Exception ex) {
return Arrays.stream(ex.getStackTrace())
.map(StackTraceElement::toString)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.academy.bot.api.exception;

public class ResponseException extends RuntimeException {
public ResponseException(String message) {
super(message);
}
}
Loading
Loading