Skip to content

Commit a1751b7

Browse files
authored
Merge pull request #2 from Delphington/backend_4
Backend 4
2 parents 525f1e9 + 991421b commit a1751b7

265 files changed

Lines changed: 15072 additions & 110 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ on:
66

77
jobs:
88
build:
9-
runs-on: ubuntu-latest
9+
runs-on: edu-self-hosted
10+
container:
11+
image: maven:3-eclipse-temurin-24
12+
timeout-minutes: 10
1013
name: Build
1114
permissions:
1215
contents: read
@@ -37,7 +40,10 @@ jobs:
3740

3841
linter:
3942
name: linter
40-
runs-on: ubuntu-latest
43+
runs-on: edu-self-hosted
44+
container:
45+
image: maven:3-eclipse-temurin-24
46+
timeout-minutes: 10
4147
permissions:
4248
contents: read
4349
packages: write

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
# Link Tracker
44

5+
----
6+
7+
Чтобы бот заработал нужно в переменные среды загрузить TELEGRAM_TOKEN
8+
9+
----
10+
511
<!-- этот файл можно и нужно менять -->
612

713
Проект сделан в рамках курса Академия Бэкенда.

bot/pom.xml

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<groupId>backend.academy</groupId>
77
<artifactId>root</artifactId>
88
<version>${revision}</version>
9+
910
</parent>
1011

1112
<artifactId>bot</artifactId>
@@ -43,11 +44,11 @@
4344
<artifactId>spring-boot-starter-data-redis</artifactId>
4445
</dependency>
4546

46-
<!-- Kafka -->
47-
<!-- <dependency>-->
48-
<!-- <groupId>org.springframework.kafka</groupId>-->
49-
<!-- <artifactId>spring-kafka</artifactId>-->
50-
<!-- </dependency>-->
47+
<!-- Kafka-->
48+
<dependency>
49+
<groupId>org.springframework.kafka</groupId>
50+
<artifactId>spring-kafka</artifactId>
51+
</dependency>
5152

5253
<!-- Actuator -->
5354
<dependency>
@@ -87,6 +88,7 @@
8788
<artifactId>spring-boot-starter-test</artifactId>
8889
<scope>test</scope>
8990
</dependency>
91+
9092
<dependency>
9193
<groupId>io.projectreactor</groupId>
9294
<artifactId>reactor-test</artifactId>
@@ -112,11 +114,55 @@
112114
<artifactId>kafka</artifactId>
113115
<scope>test</scope>
114116
</dependency>
115-
<!-- <dependency>-->
116-
<!-- <groupId>org.springframework.kafka</groupId>-->
117-
<!-- <artifactId>spring-kafka-test</artifactId>-->
118-
<!-- <scope>test</scope>-->
119-
<!-- </dependency>-->
117+
<dependency>
118+
<groupId>org.springframework.kafka</groupId>
119+
<artifactId>spring-kafka-test</artifactId>
120+
<scope>test</scope>
121+
</dependency>
122+
<dependency>
123+
<groupId>org.glassfish.jaxb</groupId>
124+
<artifactId>jaxb-runtime</artifactId>
125+
<scope>test</scope>
126+
</dependency>
127+
128+
<dependency>
129+
<groupId>commons-io</groupId>
130+
<artifactId>commons-io</artifactId>
131+
<version>2.16.1</version>
132+
</dependency>
133+
<dependency>
134+
<groupId>io.github.resilience4j</groupId>
135+
<artifactId>resilience4j-spring-boot3</artifactId>
136+
</dependency>
137+
<dependency>
138+
<groupId>io.github.resilience4j</groupId>
139+
<artifactId>resilience4j-reactor</artifactId>
140+
</dependency>
141+
142+
<dependency>
143+
<groupId>org.springframework.retry</groupId>
144+
<artifactId>spring-retry</artifactId>
145+
</dependency>
146+
147+
<dependency>
148+
<groupId>org.aspectj</groupId>
149+
<artifactId>aspectjweaver</artifactId>
150+
<version>1.9.20.1</version>
151+
</dependency>
152+
153+
<dependency>
154+
<groupId>com.bucket4j</groupId>
155+
<artifactId>bucket4j-core</artifactId>
156+
<version>8.7.0</version>
157+
</dependency>
158+
159+
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-contract-wiremock -->
160+
<dependency>
161+
<groupId>org.springframework.cloud</groupId>
162+
<artifactId>spring-cloud-contract-wiremock</artifactId>
163+
<version>4.2.1</version>
164+
</dependency>
165+
120166
</dependencies>
121167

122168
<build>
@@ -125,7 +171,6 @@
125171
<groupId>org.apache.maven.plugins</groupId>
126172
<artifactId>maven-compiler-plugin</artifactId>
127173
</plugin>
128-
<!-- To build OCI image: https://docs.spring.io/spring-boot/maven-plugin/build-image.html -->
129174
<plugin>
130175
<groupId>org.springframework.boot</groupId>
131176
<artifactId>spring-boot-maven-plugin</artifactId>

bot/src/main/java/backend/academy/bot/BotApplication.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package backend.academy.bot;
22

3+
import backend.academy.bot.config.BotConfig;
4+
import backend.academy.bot.limit.RateLimitProperties;
35
import org.springframework.boot.SpringApplication;
46
import org.springframework.boot.autoconfigure.SpringBootApplication;
57
import org.springframework.boot.context.properties.EnableConfigurationProperties;
8+
import org.springframework.retry.annotation.EnableRetry;
9+
import org.springframework.scheduling.annotation.EnableScheduling;
610

711
@SpringBootApplication
8-
@EnableConfigurationProperties({BotConfig.class})
12+
@EnableConfigurationProperties({BotConfig.class, RateLimitProperties.class})
13+
@EnableScheduling
14+
@EnableRetry
915
public class BotApplication {
1016
public static void main(String[] args) {
1117
SpringApplication.run(BotApplication.class, args);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package backend.academy.bot;
2+
3+
import backend.academy.bot.listener.MessageListener;
4+
import backend.academy.bot.processor.UserMessageProcessor;
5+
import com.pengrad.telegrambot.TelegramBot;
6+
import jakarta.annotation.PostConstruct;
7+
import lombok.Getter;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.stereotype.Component;
10+
11+
@RequiredArgsConstructor
12+
@Getter
13+
@Component
14+
public class LinkTrackerBot implements AutoCloseable {
15+
16+
private final TelegramBot telegramBot;
17+
private final MessageListener messageListener;
18+
private final UserMessageProcessor userMessageProcessor;
19+
20+
@PostConstruct
21+
public void init() {
22+
telegramBot.setUpdatesListener(messageListener);
23+
// Регистрируем команды при запуске
24+
userMessageProcessor.registerCommands();
25+
}
26+
27+
@Override
28+
public void close() {
29+
telegramBot.shutdown();
30+
}
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package backend.academy.bot.api.controller;
2+
3+
import backend.academy.bot.api.dto.request.LinkUpdate;
4+
import backend.academy.bot.notification.NotificationService;
5+
import io.swagger.v3.oas.annotations.Operation;
6+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
7+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
8+
import jakarta.validation.Valid;
9+
import lombok.RequiredArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.web.bind.annotation.PostMapping;
13+
import org.springframework.web.bind.annotation.RequestBody;
14+
import org.springframework.web.bind.annotation.ResponseStatus;
15+
import org.springframework.web.bind.annotation.RestController;
16+
17+
@RequiredArgsConstructor
18+
@Slf4j
19+
@RestController
20+
public class UpdateController {
21+
22+
private final NotificationService notificationService;
23+
24+
@Operation(summary = "Отправить обновление")
25+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Обновление обработано")})
26+
@ResponseStatus(HttpStatus.OK)
27+
@PostMapping("/updates")
28+
public void update(@RequestBody @Valid LinkUpdate linkUpdate) {
29+
log.info("Пришло обновление по ссылке");
30+
notificationService.sendMessage(linkUpdate);
31+
}
32+
33+
@PostMapping("/public")
34+
public void update() {
35+
log.info("Пришло обновление по ссылке");
36+
}
37+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package backend.academy.bot.api.dto.kafka;
2+
3+
public record BadLink(Long id, String url) {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package backend.academy.bot.api.dto.request;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import java.net.URI;
5+
import java.util.List;
6+
7+
public record AddLinkRequest(
8+
@NotNull(message = "URL не может быть пустым") URI link, List<String> tags, List<String> filters) {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package backend.academy.bot.api.dto.request;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
5+
import jakarta.validation.constraints.Positive;
6+
import java.net.URI;
7+
import java.util.List;
8+
9+
public record LinkUpdate(
10+
@NotNull(message = "chatId не может быть null")
11+
@Positive(message = "chatId может принимать только положительные значения")
12+
Long id,
13+
@NotNull(message = "URL не может быть null") URI url,
14+
@NotNull(message = "description не может быть null") @NotBlank(message = "Описание не может быть пустым")
15+
String description,
16+
@NotNull(message = "Список ID чатов не может быть null") List<Long> tgChatIds) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package backend.academy.bot.api.dto.request;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import java.net.URI;
5+
6+
public record RemoveLinkRequest(@NotNull(message = "URL не может быть пустым") URI link) {}

0 commit comments

Comments
 (0)