From d665dd242b8d410c802c1ee80a310020f8cf4e0a Mon Sep 17 00:00:00 2001
From: Ray <113240139+Ray-Not@users.noreply.github.com>
Date: Tue, 2 May 2023 18:26:28 +0500
Subject: [PATCH 1/9] Create README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..dbfb550
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# JavaGuava
From 56bca09ecd5837cf9072fb6f4388ba84cf603899 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Mon, 15 May 2023 14:16:30 +0500
Subject: [PATCH 2/9] Add hw7
---
FP/.project | 18 ++
FP/bot/.classpath | 34 +++
FP/bot/.dbeaver/.credentials-config.json.bak | Bin 0 -> 112 bytes
FP/bot/.dbeaver/.data-sources.json.bak | 4 +
FP/bot/.dbeaver/.project-metadata.json.bak | 1 +
FP/bot/.dbeaver/data-sources.json | 6 +
FP/bot/.dbeaver/project-metadata.json | 1 +
FP/bot/.dbeaver/project-settings.json | 1 +
FP/bot/.gitignore | 1 +
FP/bot/.project | 24 ++
.../org.eclipse.core.resources.prefs | 6 +
FP/bot/.settings/org.eclipse.jdt.core.prefs | 9 +
FP/bot/.settings/org.eclipse.m2e.core.prefs | 4 +
FP/bot/pom.xml | 103 +++++++
.../tinkoff/edu/java/bot/BotApplication.java | 16 ++
.../java/bot/advice/AppExceptionHandler.java | 23 ++
.../edu/java/bot/client/ScrapperClient.java | 97 +++++++
.../bot/client/ScrapperClientException.java | 11 +
.../edu/java/bot/commands/Command.java | 20 ++
.../edu/java/bot/commands/CommandsEnum.java | 33 +++
.../edu/java/bot/commands/HelpCommand.java | 23 ++
.../edu/java/bot/commands/ListCommand.java | 48 ++++
.../edu/java/bot/commands/StartCommand.java | 55 ++++
.../edu/java/bot/commands/TrackCommand.java | 47 ++++
.../edu/java/bot/commands/UntrackCommand.java | 49 ++++
.../bot/configuration/ApplicationConfig.java | 12 +
.../bot/configuration/BotConfiguration.java | 66 +++++
.../configuration/ClientConfiguration.java | 27 ++
.../LinkParserConfiguration.java | 14 +
.../configuration/RabbitMQConfiguration.java | 80 ++++++
.../edu/java/bot/dto/AddLinkRequest.java | 6 +
.../edu/java/bot/dto/ApiErrorResponse.java | 7 +
.../tinkoff/edu/java/bot/dto/BotCommand.java | 8 +
.../ru/tinkoff/edu/java/bot/dto/Link.java | 10 +
.../edu/java/bot/dto/LinkResponse.java | 11 +
.../tinkoff/edu/java/bot/dto/LinkUpdate.java | 5 +
.../edu/java/bot/dto/ListLinkResponse.java | 6 +
.../edu/java/bot/dto/RemoveLinkRequest.java | 5 +
.../edu/java/bot/dto/SetCommandRequest.java | 7 +
.../tinkoff/edu/java/bot/dto/UserAddDto.java | 8 +
.../bot/exceptions/ChatNotFoundException.java | 10 +
.../LinkIsNotRegisteredToChatException.java | 10 +
.../edu/java/bot/rest/BotRestController.java | 30 +++
.../bot/service/ScrapperQueueListener.java | 32 +++
.../edu/java/bot/service/UpdateService.java | 8 +
.../java/bot/service/UpdateServiceImpl.java | 26 ++
.../ru/tinkoff/edu/java/bot/telegram/Bot.java | 53 ++++
.../bot/telegram/UserMessageProcessor.java | 67 +++++
.../edu/java/bot/telegram/UserState.java | 5 +
.../src/main/resources/application.properties | 13 +
FP/bot/src/test/java/bot/BotTest.java | 123 +++++++++
FP/docker-compose.yml | 60 +++++
FP/link-parser/.classpath | 41 +++
FP/link-parser/.gitignore | 1 +
FP/link-parser/.project | 23 ++
.../org.eclipse.core.resources.prefs | 6 +
.../.settings/org.eclipse.jdt.core.prefs | 9 +
.../.settings/org.eclipse.m2e.core.prefs | 4 +
FP/link-parser/pom.xml | 30 +++
.../java/link_parser/link/GitHub_Link.java | 5 +
.../java/link_parser/link/Parser_Link.java | 5 +
.../link_parser/link/StackOverflow_Link.java | 5 +
.../edu/java/link_parser/parser/Abstract.java | 27 ++
.../edu/java/link_parser/parser/Github.java | 31 +++
.../java/link_parser/parser/Link_Parser.java | 16 ++
.../link_parser/parser/StackOverflow.java | 34 +++
.../src/test/java/LinkParserTest.java | 99 +++++++
FP/migrations/01-schema-1.sql | 11 +
FP/migrations/02-schema-2.sql | 15 ++
FP/migrations/03-schema-3.sql | 10 +
FP/migrations/create.sql | 18 ++
FP/migrations/delete.sql | 3 +
FP/migrations/insert.sql | 37 +++
FP/migrations/master.xml | 13 +
FP/pom.xml | 123 +++++++++
FP/scrapper-jooq/.classpath | 28 ++
FP/scrapper-jooq/.gitignore | 1 +
FP/scrapper-jooq/.project | 23 ++
.../org.eclipse.core.resources.prefs | 4 +
.../.settings/org.eclipse.jdt.core.prefs | 9 +
.../.settings/org.eclipse.m2e.core.prefs | 4 +
FP/scrapper-jooq/pom.xml | 40 +++
.../src/main/java/JooqCodegen.java | 49 ++++
FP/scrapper/.classpath | 41 +++
FP/scrapper/.gitignore | 1 +
FP/scrapper/.project | 23 ++
.../org.eclipse.core.resources.prefs | 6 +
.../.settings/org.eclipse.jdt.core.prefs | 9 +
.../.settings/org.eclipse.m2e.core.prefs | 4 +
FP/scrapper/pom.xml | 120 +++++++++
.../java/scrapper/ScrapperApplication.java | 22 ++
.../scrapper/advice/AppExceptionHandler.java | 33 +++
.../edu/java/scrapper/client/BotClient.java | 38 +++
.../java/scrapper/client/GitHubClient.java | 47 ++++
.../scrapper/client/StackOverflowClient.java | 44 +++
.../configuration/ApplicationConfig.java | 26 ++
.../configuration/ClientConfiguration.java | 44 +++
.../configuration/HTTPConfiguration.java | 28 ++
.../LinkParserConfiguration.java | 14 +
.../configuration/RabbitMQConfiguration.java | 50 ++++
.../acess/JdbcAccessConfiguration.java | 99 +++++++
.../acess/JooqAccessConfiguration.java | 84 ++++++
.../acess/JpaAccessConfiguration.java | 61 +++++
.../edu/java/scrapper/dto/AddLinkRequest.java | 5 +
.../java/scrapper/dto/ApiErrorResponse.java | 6 +
.../edu/java/scrapper/dto/GitHubResponse.java | 25 ++
.../edu/java/scrapper/dto/LinkResponse.java | 5 +
.../edu/java/scrapper/dto/LinkUpdate.java | 5 +
.../java/scrapper/dto/ListLinkResponse.java | 8 +
.../java/scrapper/dto/RemoveLinkRequest.java | 5 +
.../java/scrapper/dto/StackOverflowItem.java | 8 +
.../scrapper/dto/StackOverflowResponse.java | 8 +
.../edu/java/scrapper/dto/UserAddDto.java | 8 +
.../BadResponseFromApiException.java | 12 +
.../exception/BotClientException.java | 11 +
.../exception/ChatAlreadyExistException.java | 11 +
.../exception/ChatNotFoundException.java | 12 +
.../exception/GitHubRequestException.java | 11 +
.../LinkIsAlreadyAddedException.java | 12 +
.../exception/LinkNotFoundException.java | 12 +
.../StackOverflowRequestException.java | 12 +
.../java/scrapper/mapper/LinkRowMapper.java | 27 ++
.../mapper/SubscriptionRowMapper.java | 20 ++
.../java/scrapper/mapper/UserRowMapper.java | 24 ++
.../java/scrapper/model/commonDto/Link.java | 31 +++
.../java/scrapper/model/commonDto/User.java | 32 +++
.../scrapper/model/jdbcAndJooq/Relation.java | 11 +
.../java/scrapper/model/jpa/LinkEntity.java | 40 +++
.../java/scrapper/model/jpa/UserEntity.java | 30 +++
.../jdbc/LinkJdbcTemplateRepository.java | 86 ++++++
.../SubscriptionJdbcTemplateRepository.java | 75 ++++++
.../jdbc/UserJdbcTemplateRepository.java | 59 ++++
.../jdbcAndJooqContract/LinkRepository.java | 21 ++
.../SubscriptionRepository.java | 19 ++
.../jdbcAndJooqContract/UserRepository.java | 13 +
.../repository/jooq/LinkJooqRepository.java | 98 +++++++
.../jooq/SubscriptionJooqRepository.java | 80 ++++++
.../repository/jooq/UserJooqRepository.java | 59 ++++
.../repository/jpa/JpaLinkRepository.java | 20 ++
.../repository/jpa/JpaUserRepository.java | 22 ++
.../scrapper/rest/ChatRestController.java | 30 +++
.../scrapper/rest/LinkRestController.java | 44 +++
.../schedule/LinkUpdateScheduler.java | 26 ++
.../edu/java/scrapper/schedule/Scheduler.java | 6 +
.../service/ScrapperQueueProducer.java | 26 ++
.../service/UpdateNotificationService.java | 8 +
.../service/contract/LinkUpdateService.java | 12 +
.../service/contract/SubscriptionService.java | 14 +
.../service/contract/TgChatService.java | 11 +
.../impl/LinkUpdateServiceImpl.java | 156 +++++++++++
.../impl/SubscriptionServiceImpl.java | 99 +++++++
.../jdbcAndJooq/impl/TgChatServiceImpl.java | 42 +++
.../jpa/impl/JpaLinkUpdateServiceImpl.java | 174 ++++++++++++
.../jpa/impl/JpaSubscriptionServiceImpl.java | 100 +++++++
.../jpa/impl/JpaTgChatServiceImpl.java | 43 +++
.../src/main/resources/application.properties | 23 ++
.../src/main/resources/logback-test.xml | 17 ++
.../src/test/java/scrapper/DatabaseTest.java | 38 +++
.../java/scrapper/IntegrationEnvironment.java | 54 ++++
.../scrapper/environment/DatabaseTest.java | 38 +++
.../environment/IntegrationEnvironment.java | 81 ++++++
.../environment/TestConfiguration.java | 8 +
.../test/java/scrapper/jdbc/JdbcLinkTest.java | 151 +++++++++++
.../scrapper/jdbc/JdbcSubscriptionTest.java | 251 ++++++++++++++++++
.../test/java/scrapper/jdbc/JdbcUserTest.java | 135 ++++++++++
165 files changed, 5391 insertions(+)
create mode 100644 FP/.project
create mode 100644 FP/bot/.classpath
create mode 100644 FP/bot/.dbeaver/.credentials-config.json.bak
create mode 100644 FP/bot/.dbeaver/.data-sources.json.bak
create mode 100644 FP/bot/.dbeaver/.project-metadata.json.bak
create mode 100644 FP/bot/.dbeaver/data-sources.json
create mode 100644 FP/bot/.dbeaver/project-metadata.json
create mode 100644 FP/bot/.dbeaver/project-settings.json
create mode 100644 FP/bot/.gitignore
create mode 100644 FP/bot/.project
create mode 100644 FP/bot/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/bot/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/bot/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/bot/pom.xml
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
create mode 100644 FP/bot/src/main/resources/application.properties
create mode 100644 FP/bot/src/test/java/bot/BotTest.java
create mode 100644 FP/docker-compose.yml
create mode 100644 FP/link-parser/.classpath
create mode 100644 FP/link-parser/.gitignore
create mode 100644 FP/link-parser/.project
create mode 100644 FP/link-parser/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/link-parser/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/link-parser/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/link-parser/pom.xml
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
create mode 100644 FP/link-parser/src/test/java/LinkParserTest.java
create mode 100644 FP/migrations/01-schema-1.sql
create mode 100644 FP/migrations/02-schema-2.sql
create mode 100644 FP/migrations/03-schema-3.sql
create mode 100644 FP/migrations/create.sql
create mode 100644 FP/migrations/delete.sql
create mode 100644 FP/migrations/insert.sql
create mode 100644 FP/migrations/master.xml
create mode 100644 FP/pom.xml
create mode 100644 FP/scrapper-jooq/.classpath
create mode 100644 FP/scrapper-jooq/.gitignore
create mode 100644 FP/scrapper-jooq/.project
create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/scrapper-jooq/pom.xml
create mode 100644 FP/scrapper-jooq/src/main/java/JooqCodegen.java
create mode 100644 FP/scrapper/.classpath
create mode 100644 FP/scrapper/.gitignore
create mode 100644 FP/scrapper/.project
create mode 100644 FP/scrapper/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/scrapper/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/scrapper/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/scrapper/pom.xml
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
create mode 100644 FP/scrapper/src/main/resources/application.properties
create mode 100644 FP/scrapper/src/main/resources/logback-test.xml
create mode 100644 FP/scrapper/src/test/java/scrapper/DatabaseTest.java
create mode 100644 FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
create mode 100644 FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
create mode 100644 FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
create mode 100644 FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
diff --git a/FP/.project b/FP/.project
new file mode 100644
index 0000000..89d138f
--- /dev/null
+++ b/FP/.project
@@ -0,0 +1,18 @@
+
+
+ project
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Nature
+ org.jkiss.dbeaver.DBeaverNature
+
+
diff --git a/FP/bot/.classpath b/FP/bot/.classpath
new file mode 100644
index 0000000..0b9fa8d
--- /dev/null
+++ b/FP/bot/.classpath
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/bot/.dbeaver/.credentials-config.json.bak
new file mode 100644
index 0000000000000000000000000000000000000000..8320c631e208c3ad7467cf2d9db83d85e90f14f8
GIT binary patch
literal 112
zcmV-$0FVC>%bw`qlvu4i=Wrho)ja=8tm(6RtT%VUiv(RbXd+9@8O^=>KI816Agz
S3>36s#U(-2xgbD9^um4;
+
+ bot
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.jkiss.dbeaver.DBeaverNature
+
+
diff --git a/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/bot/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/bot/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/=UTF-8
diff --git a/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/bot/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/bot/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/bot/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/bot/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
new file mode 100644
index 0000000..11dc02c
--- /dev/null
+++ b/FP/bot/pom.xml
@@ -0,0 +1,103 @@
+
+ 4.0.0
+
+ project
+ project
+ 0.0.1-SNAPSHOT
+
+ bot
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework
+ spring-context-indexer
+ true
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.0.2
+
+
+ com.github.pengrad
+ java-telegram-bot-api
+ 6.6.0
+
+
+ ru.tinkoff.edu
+ link-parser
+ 1.0-SNAPSHOT
+
+
+ org.springframework
+ spring-context
+ 6.0.3
+
+
+ org.springframework
+ spring-test
+ 6.0.6
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+
+
+ org.mockito
+ mockito-core
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
new file mode 100644
index 0000000..50cd2b8
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
@@ -0,0 +1,16 @@
+package ru.tinkoff.edu.java.bot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig;
+
+@SpringBootApplication
+@EnableConfigurationProperties(ApplicationConfig.class)
+public class BotApplication {
+ public static void main(String[] args) {
+ var ctx = SpringApplication.run(BotApplication.class, args);
+ ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
+
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
new file mode 100644
index 0000000..12c0975
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
@@ -0,0 +1,23 @@
+package ru.tinkoff.edu.java.bot.advice;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import ru.tinkoff.edu.java.bot.dto.ApiErrorResponse;
+import ru.tinkoff.edu.java.bot.exceptions.ChatNotFoundException;
+import ru.tinkoff.edu.java.bot.exceptions.LinkIsNotRegisteredToChatException;
+
+import java.util.Arrays;
+
+@RestControllerAdvice
+public class AppExceptionHandler {
+
+ @ExceptionHandler({LinkIsNotRegisteredToChatException.class, ChatNotFoundException.class})
+ @ResponseStatus(value = HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) {
+ return new ApiErrorResponse(
+ "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
+ }
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
new file mode 100644
index 0000000..f8ef3a4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
@@ -0,0 +1,97 @@
+package ru.tinkoff.edu.java.bot.client;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import ru.tinkoff.edu.java.bot.dto.*;
+
+
+public class ScrapperClient {
+
+ private final WebClient webClient;
+
+
+ //По умолчанию - webClient инжектится из ClientConfiguration c baseUrl по умолчанию
+ public ScrapperClient(WebClient webClient) {
+ this.webClient = webClient;
+ }
+
+ //Здесь webClient не инжектится, чтобы была возможность указать baseUrl.
+ public ScrapperClient(String baseUrl) {
+ this.webClient = WebClient.create(baseUrl);
+ }
+
+
+ public ListLinkResponse getLinks(Long tgChatId) {
+ ListLinkResponse response = webClient.get().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)).exchangeToMono(r -> {
+ if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
+ throw new ScrapperClientException("Чат с таким ID не зарегистрирован");
+ } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
+ throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
+ }
+ return r.bodyToMono(ListLinkResponse.class);
+ }).block();
+
+ return response;
+ }
+
+ public LinkResponse addLink(Long tgChatId, AddLinkRequest request) {
+ LinkResponse response = webClient.post().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId))
+ .bodyValue(request).exchangeToMono(r -> {
+ if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
+ throw new ScrapperClientException("Ссылка с таким URL уже добавлена");
+ } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
+ throw new ScrapperClientException("Чат с таким ID не зарегистрирован");
+ } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
+ throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
+ }
+ return r.bodyToMono(LinkResponse.class);
+ }).block();
+
+ return response;
+ }
+
+ public LinkResponse deleteLink(Long tgChatId, RemoveLinkRequest request) {
+ LinkResponse response = webClient.method(HttpMethod.DELETE).uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId))
+ .bodyValue(request).exchangeToMono(r -> {
+ if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
+ throw new ScrapperClientException("Некорректно указана ссылка");
+ } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
+ throw new ScrapperClientException("Ссылка с таким URL не найдена или чат с таким ID не зарегистрирован");
+ } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
+ throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
+ }
+ return r.bodyToMono(LinkResponse.class);
+ }).block();
+
+ return response;
+ }
+
+
+ public void registerChat(Long tgChatId, UserAddDto userAddDto) {
+ webClient.post().uri("/tg-chat/{id}", tgChatId).bodyValue(userAddDto).exchangeToMono(response -> {
+ if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) {
+ throw new ScrapperClientException("Некорректно указан ID или такой чат уже зарегистрирован");
+ } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
+ throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
+ }
+ return Mono.empty();
+ }).block();
+ }
+
+ public void deleteChat(Long tgChatId) {
+ webClient.delete().uri("/tg-chat/{id}", tgChatId).exchangeToMono(response -> {
+ if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) {
+ throw new ScrapperClientException("Некорректно указан ID");
+ } else if (response.statusCode().equals(HttpStatus.NOT_FOUND)) {
+ throw new ScrapperClientException("Чат с таким ID не найден");
+ } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
+ throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
+ }
+ return Mono.empty();
+ }).block();
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
new file mode 100644
index 0000000..9ef91d4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.client;
+
+public class ScrapperClientException extends RuntimeException{
+
+ public ScrapperClientException() {
+ }
+
+ public ScrapperClientException(String message) {
+ super(message);
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
new file mode 100644
index 0000000..a179c88
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import ru.tinkoff.edu.java.bot.dto.BotCommand;
+
+public interface Command {
+ String command();
+
+ String description();
+
+ String handle(Update update);
+
+ default boolean supports(Update update) {
+ return update.message().text().equals(command());
+ }
+
+ default BotCommand toApiCommand() {
+ return new BotCommand(command(), description());
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
new file mode 100644
index 0000000..1d3852c
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
@@ -0,0 +1,33 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum CommandsEnum {
+
+ START ("/start"),
+ HELP ("/help"),
+ LIST ("/list"),
+ TRACK ("/track"),
+ UNTRACK ("/untrack");
+
+ private static final Map BY_LABEL = new HashMap<>();
+
+ static {
+ for (CommandsEnum c : values()) {
+ BY_LABEL.put(c.label, c);
+ }
+ }
+
+ private final String label;
+
+ CommandsEnum(String command) {
+ this.label = command;
+ }
+
+ public static CommandsEnum valueOfLabel(String label) {
+ return BY_LABEL.get(label);
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
new file mode 100644
index 0000000..3849dc7
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
@@ -0,0 +1,23 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.stereotype.Component;
+
+@Component
+public class HelpCommand implements Command{
+ @Override
+ public String command() {
+ return "/help";
+ }
+
+ @Override
+ public String description() {
+ return "ввывести окно с командами";
+ }
+
+ @Override
+ public String handle(Update update) {
+ return "Help is executing...";
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
new file mode 100644
index 0000000..6a3176e
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
@@ -0,0 +1,48 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
+import ru.tinkoff.edu.java.bot.dto.Link;
+import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
+
+@Component
+public class ListCommand implements Command {
+
+ private final ScrapperClient scrapperClient;
+
+ public ListCommand(ScrapperClient scrapperClient) {
+ this.scrapperClient = scrapperClient;
+ }
+
+ @Override
+ public String command() {
+ return "/list";
+ }
+
+ @Override
+ public String description() {
+ return "показать список отслеживаемых ссылок";
+ }
+
+ @Override
+ public String handle(Update update) {
+ long chatId = update.message().chat().id();
+ try {
+ ListLinkResponse response = scrapperClient.getLinks(chatId);
+ StringBuilder msg = new StringBuilder();
+ if (response.size() == 0)
+ msg.append("Список отслеживаемых ссылок пуст!");
+ else {
+ msg.append("Ссылок отслеживается - ").append(response.size()).append("\n\n");
+ for (Link link : response.links()) {
+ msg.append(link.url()).append("\n\n");
+ }
+ }
+ return msg.toString();
+ } catch (ScrapperClientException e){
+ return e.getMessage();
+ }
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
new file mode 100644
index 0000000..9c9f497
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
@@ -0,0 +1,55 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
+import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
+import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
+import ru.tinkoff.edu.java.bot.dto.Link;
+import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
+import ru.tinkoff.edu.java.bot.dto.UserAddDto;
+
+@Component
+public class StartCommand implements Command {
+
+ private final ScrapperClient scrapperClient;
+
+ public StartCommand(ScrapperClient scrapperClient) {
+ this.scrapperClient = scrapperClient;
+ }
+
+
+ @Value("${tg.bot.token}")
+ private String token;
+
+
+ @Override
+ public String command() {
+ return "/start";
+ }
+
+ @Override
+ public String description() {
+ return "зарегистрировать пользователя";
+ }
+
+ @Override
+ public String handle(Update update) {
+ long chatId = update.message().chat().id();
+ try {
+ UserAddDto userAddDto = new UserAddDto(update.message().chat().username(), update.message().chat().firstName(), update.message().chat().lastName());
+ scrapperClient.registerChat(chatId, userAddDto);
+ return "Привет! Рад познакомиться, " + update.message().chat().firstName();
+ } catch (ScrapperClientException e) {
+
+ return e.getMessage();
+ }
+
+
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
new file mode 100644
index 0000000..a3eb9b4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
@@ -0,0 +1,47 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
+import ru.tinkoff.edu.java.bot.dto.AddLinkRequest;
+
+@Component
+public class TrackCommand implements Command {
+
+ private final LinkParser parser;
+
+ public TrackCommand(ScrapperClient scrapperClient, LinkParser parser) {
+ this.scrapperClient = scrapperClient;
+ this.parser = parser;
+ }
+
+ private final ScrapperClient scrapperClient;
+
+ @Override
+ public String command() {
+ return "/track";
+ }
+
+ @Override
+ public String description() {
+ return "начать отслеживание ссылки";
+ }
+
+ @Override
+ public String handle(Update update) {
+ long chatId = update.message().chat().id();
+ String msg;
+ try {
+ if (parser.parseUrl(update.message().text()) != null){
+ scrapperClient.addLink(chatId, new AddLinkRequest(update.message().text()));
+ msg = "Ссылка успешно добавлена";
+ } else msg = "Некорректная ссылка";
+ return msg;
+ } catch (ScrapperClientException e) {
+ return e.getMessage();
+ }
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
new file mode 100644
index 0000000..df1c58a
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
@@ -0,0 +1,49 @@
+package ru.tinkoff.edu.java.bot.commands;
+
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
+import ru.tinkoff.edu.java.bot.dto.AddLinkRequest;
+import ru.tinkoff.edu.java.bot.dto.RemoveLinkRequest;
+
+@Component
+public class UntrackCommand implements Command{
+
+ private final ScrapperClient scrapperClient;
+
+ private final Link_Parser parser;
+
+
+ public UntrackCommand(ScrapperClient scrapperClient, Link_Parser parser) {
+ this.scrapperClient = scrapperClient;
+ this.parser = parser;
+ }
+
+ @Override
+ public String command() {
+ return "/untrack";
+ }
+
+ @Override
+ public String description() {
+ return "прекратить отслеживание ссылки";
+ }
+
+ @Override
+ public String handle(Update update) {
+ long chatId = update.message().chat().id();
+ String msg;
+ try {
+ if (parser.parseUrl(update.message().text()) != null){
+ scrapperClient.deleteLink(chatId, new RemoveLinkRequest(update.message().text()));
+ msg = "Ссылка успешно удалена";
+ } else msg = "Некорректная ссылка";
+ return msg;
+ } catch (ScrapperClientException e) {
+ return e.getMessage();
+ }
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
new file mode 100644
index 0000000..02ab1d4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import jakarta.validation.constraints.NotNull;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+@Validated
+@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
+public record ApplicationConfig(@NotNull String test,
+ String queueName,
+ String exchangeName,
+ String routingKey) {}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
new file mode 100644
index 0000000..d20e877
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
@@ -0,0 +1,66 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import ru.tinkoff.edu.java.bot.commands.*;
+import ru.tinkoff.edu.java.bot.dto.BotCommand;
+import ru.tinkoff.edu.java.bot.dto.SetCommandRequest;
+import ru.tinkoff.edu.java.bot.telegram.Bot;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+
+@Configuration
+@Slf4j
+public class BotConfiguration {
+
+ @Value("${tg.bot.token}")
+ private String token;
+
+ @Value("${tg.api.baseUrl}")
+ private String tgApiBaseUrl;
+
+ private final HelpCommand helpCommand;
+ private final StartCommand startCommand;
+ private final ListCommand listCommand;
+ private final TrackCommand trackCommand;
+ private final UntrackCommand untrackCommand;
+
+ public BotConfiguration(HelpCommand helpCommand, StartCommand startCommand, ListCommand listCommand, TrackCommand trackCommand, UntrackCommand untrackCommand) {
+ this.helpCommand = helpCommand;
+ this.startCommand = startCommand;
+ this.listCommand = listCommand;
+ this.trackCommand = trackCommand;
+ this.untrackCommand = untrackCommand;
+ }
+
+ @Bean
+ public Bot bot() {
+ EnumMap commands = new EnumMap<>(CommandsEnum.class);
+
+
+ commands.put(CommandsEnum.HELP,helpCommand);
+ commands.put(CommandsEnum.LIST,listCommand);
+ commands.put(CommandsEnum.START,startCommand);
+ commands.put(CommandsEnum.TRACK,trackCommand);
+ commands.put(CommandsEnum.UNTRACK,untrackCommand);
+
+ List apiCommands = new ArrayList<>(commands.values().stream().map(Command::toApiCommand).toList());
+ WebClient botConfClient = WebClient.create(tgApiBaseUrl+token);
+ botConfClient.post().uri("/setMyCommands").bodyValue(new SetCommandRequest(apiCommands)).exchangeToMono(r ->{
+ if (!r.statusCode().equals(HttpStatus.OK)){
+ log.warn("Похоже, что API Telegram недоступен(");
+ }
+ return Mono.empty();
+ }).block();
+
+ return new Bot(token, commands);
+ }
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
new file mode 100644
index 0000000..f5d3a09
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
@@ -0,0 +1,27 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+
+
+@Configuration
+public class ClientConfiguration {
+
+ @Value("${scrapper.baseurl}")
+ private String scrapperBaseUrl;
+
+
+ @Bean
+ public WebClient webClient(){
+ return WebClient.create(scrapperBaseUrl);
+ }
+
+ //Регистрируем клиентов как бины
+ @Bean
+ public ScrapperClient scrapperClient() {
+ return new ScrapperClient(scrapperBaseUrl);
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
new file mode 100644
index 0000000..962ff14
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import parser.LinkParser;
+
+@Configuration
+public class LinkParserConfiguration {
+
+ @Bean
+ public LinkParser linkParser(){
+ return new LinkParser();
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
new file mode 100644
index 0000000..3f53ca7
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -0,0 +1,80 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.support.converter.ClassMapper;
+import org.springframework.amqp.support.converter.DefaultClassMapper;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
+import ru.tinkoff.edu.java.bot.service.ScrapperQueueListener;
+import ru.tinkoff.edu.java.bot.service.UpdateService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class RabbitMQConfiguration {
+
+ private final ApplicationConfig config;
+
+ public RabbitMQConfiguration(ApplicationConfig config) {
+ this.config = config;
+ }
+
+ @Bean
+ Queue queue() {
+ return QueueBuilder.durable(config.queueName())
+ .withArgument("x-dead-letter-exchange", config.exchangeName())
+ .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq")
+ .build();
+ }
+
+
+ @Bean
+ Queue deadLetterQueue() {
+ return new Queue(config.queueName() + ".dlq", true);
+ }
+
+ @Bean
+ DirectExchange exchange() {
+ return new DirectExchange(config.exchangeName());
+ }
+
+ @Bean
+ Binding binding(Queue queue, DirectExchange exchange) {
+ return BindingBuilder.bind(queue).to(exchange).with(config.routingKey());
+ }
+
+ @Bean
+ Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) {
+ return BindingBuilder.bind(deadLetterQueue).to(exchange).with(config.routingKey() + ".dlq");
+ }
+
+ @Bean
+ public ClassMapper classMapper() {
+ Map> mappings = new HashMap<>();
+ mappings.put("ru.tinkoff.edu.java.scrapper.dto.LinkUpdate", LinkUpdate.class);
+
+ DefaultClassMapper classMapper = new DefaultClassMapper();
+ classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.dto.*");
+ classMapper.setIdClassMapping(mappings);
+ return classMapper;
+ }
+
+ @Bean
+ public MessageConverter jsonMessageConverter(ClassMapper classMapper) {
+ Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
+ jsonConverter.setClassMapper(classMapper);
+ return jsonConverter;
+ }
+
+
+ @Bean
+ public ScrapperQueueListener scrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) {
+ return new ScrapperQueueListener(rabbitTemplate, updateService);
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
new file mode 100644
index 0000000..1ff0bee
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+
+public record AddLinkRequest(String link) {
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
new file mode 100644
index 0000000..d8d6113
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
@@ -0,0 +1,7 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+public record ApiErrorResponse(String description, String code, String exceptionName,
+ String exceptionMessage, String[] stacktrace) {
+
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
new file mode 100644
index 0000000..201c5c6
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+
+public record BotCommand(@JsonProperty("command") String command, @JsonProperty("description") String description) implements Serializable {
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
new file mode 100644
index 0000000..2ab0a84
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
@@ -0,0 +1,10 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import java.net.URI;
+
+public record Link (Long id, URI url){
+ @Override
+ public String toString() {
+ return "Link{" + "id=" + id + ", url='" + url + '\'' +'}';
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
new file mode 100644
index 0000000..396f750
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import java.net.URI;
+
+public record LinkResponse(long id, URI url) {
+
+ @Override
+ public String toString() {
+ return "LinkResponse{" + "id=" + id + ", url=" + url +'}';
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
new file mode 100644
index 0000000..8a92e00
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) {
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
new file mode 100644
index 0000000..5d23d7b
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import java.util.List;
+
+public record ListLinkResponse(List links, int size) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
new file mode 100644
index 0000000..7e58ba4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+public record RemoveLinkRequest(String link) {
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
new file mode 100644
index 0000000..799cdc3
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
@@ -0,0 +1,7 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public record SetCommandRequest(@JsonProperty("commands") List commands) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
new file mode 100644
index 0000000..d21ec6a
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.bot.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public record UserAddDto(@JsonProperty("username") String username,
+ @JsonProperty("first_name") String firstName,
+ @JsonProperty("last_name") String lastName) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
new file mode 100644
index 0000000..524f6f3
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
@@ -0,0 +1,10 @@
+package ru.tinkoff.edu.java.bot.exceptions;
+
+public class ChatNotFoundException extends RuntimeException {
+ public ChatNotFoundException() {
+ }
+
+ public ChatNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
new file mode 100644
index 0000000..98c36ae
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
@@ -0,0 +1,10 @@
+package ru.tinkoff.edu.java.bot.exceptions;
+
+public class LinkIsNotRegisteredToChatException extends RuntimeException {
+ public LinkIsNotRegisteredToChatException() {
+ }
+
+ public LinkIsNotRegisteredToChatException(String message) {
+ super(message);
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
new file mode 100644
index 0000000..604e19c
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
@@ -0,0 +1,30 @@
+package ru.tinkoff.edu.java.bot.rest;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
+import ru.tinkoff.edu.java.bot.service.UpdateService;
+import ru.tinkoff.edu.java.bot.service.UpdateServiceImpl;
+
+@RestController
+@Slf4j
+public class BotRestController {
+
+
+ private final UpdateService updateService;
+
+
+ public BotRestController(UpdateService updateService) {
+ this.updateService = updateService;
+ }
+
+ @PostMapping("updates")
+ public void sendUpdate(@RequestBody LinkUpdate request) {
+ log.info("Пришёл запрос на обновление: "+request);
+ updateService.updateLink(request);
+ }
+
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
new file mode 100644
index 0000000..cf4a7ae
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
@@ -0,0 +1,32 @@
+package ru.tinkoff.edu.java.bot.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
+
+@RabbitListener(queues = "${app.queue-name}")
+@Slf4j
+public class ScrapperQueueListener {
+
+
+ private final AmqpTemplate rabbitTemplate;
+
+ private final UpdateService updateService;
+
+
+ public ScrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) {
+ this.rabbitTemplate = rabbitTemplate;
+ this.updateService = updateService;
+ }
+
+ @RabbitHandler
+ public void receiver(LinkUpdate update) {
+ log.info("Сообщение об обновлении получено: "+update);
+// throw new RuntimeException("test exception");
+ updateService.updateLink(update);
+ }
+
+
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
new file mode 100644
index 0000000..ed22af0
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.bot.service;
+
+import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
+
+public interface UpdateService {
+
+void updateLink(LinkUpdate linkUpdate);
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
new file mode 100644
index 0000000..f3878a4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.bot.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
+import ru.tinkoff.edu.java.bot.telegram.Bot;
+
+@Service
+@Slf4j
+public class UpdateServiceImpl implements UpdateService{
+
+ private final Bot bot;
+
+ public UpdateServiceImpl(Bot bot) {
+ this.bot = bot;
+ }
+
+ public void updateLink(LinkUpdate linkUpdate) {
+ log.info("updateLink() method invocation in UpdateServiceImpl");
+ String message = "Вышло обновление по ссылке "+linkUpdate.url()+" \n"+linkUpdate.description();
+ for (Long chatId : linkUpdate.tgChatIds()) {
+ bot.sendMessage(chatId, message);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
new file mode 100644
index 0000000..50c8671
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
@@ -0,0 +1,53 @@
+package ru.tinkoff.edu.java.bot.telegram;
+
+import com.pengrad.telegrambot.TelegramBot;
+import com.pengrad.telegrambot.UpdatesListener;
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.request.SendMessage;
+import jakarta.annotation.PostConstruct;
+import ru.tinkoff.edu.java.bot.commands.Command;
+import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
+
+import java.util.EnumMap;
+
+public class Bot implements AutoCloseable {
+
+ private final TelegramBot bot;
+ private final UserMessageProcessor userMessageProcessor;
+
+
+
+ @PostConstruct
+ public void init(){
+ start();
+ }
+
+ public Bot(String token, EnumMap commands) {
+ System.out.println("Создание бота... Токен: " + token);
+ userMessageProcessor = new UserMessageProcessor(commands);
+ bot = new TelegramBot(token);
+ }
+
+ public void start() {
+ System.out.println("Бот запущен...");
+ bot.setUpdatesListener(updates -> {
+ for (Update update : updates) {
+ bot.execute(new SendMessage(update.message().chat().id(), userMessageProcessor.process(update)));
+
+ }
+ return UpdatesListener.CONFIRMED_UPDATES_ALL;
+ });
+ }
+
+
+ public void sendMessage(Long chatId, String msg) {
+ bot.execute(new SendMessage(chatId, msg));
+ }
+
+
+
+ @Override
+ public void close() throws Exception {
+ bot.removeGetUpdatesListener();
+ }
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
new file mode 100644
index 0000000..fb08682
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
@@ -0,0 +1,67 @@
+package ru.tinkoff.edu.java.bot.telegram;
+
+import com.pengrad.telegrambot.model.Update;
+import ru.tinkoff.edu.java.bot.commands.*;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class UserMessageProcessor {
+
+ private final Map userStateMap;
+
+ private final EnumMap commands;
+
+
+ public UserMessageProcessor(EnumMap commands) {
+ this.commands = commands;
+ userStateMap = new HashMap<>();
+ }
+
+ public String process(Update update) {
+ Command command;
+
+
+ userStateMap.putIfAbsent(update.message().chat().id(), UserState.TYPING_COMMAND);
+ switch (userStateMap.get(update.message().chat().id())) {
+ case TYPING_TRACKED -> {
+ userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
+ return commands.get(CommandsEnum.valueOfLabel("/track")).handle(update);
+ }
+ case TYPING_UNTRACKED -> {
+ userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
+ return commands.get(CommandsEnum.valueOfLabel("/untrack")).handle(update);
+ }
+ case TYPING_COMMAND -> {
+ userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
+ command = commands.get(CommandsEnum.valueOfLabel(update.message().text()));
+ if (command == null)
+ return "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд";
+ if (command instanceof TrackCommand) {
+ userStateMap.put(update.message().chat().id(), UserState.TYPING_TRACKED);
+ return "Отправьте ссылку, которую хотите начать отслеживать";
+ }
+ if (command instanceof UntrackCommand) {
+ userStateMap.put(update.message().chat().id(), UserState.TYPING_UNTRACKED);
+ return "Отправьте ссылку, которую хотите перестать отслеживать";
+ }
+ if (command instanceof HelpCommand){
+ StringBuilder text = new StringBuilder();
+ for (Command c : commands.values()) {
+ text.append(c.command()).append(" - ").append(c.description()).append("\n");
+ }
+ return text.toString();
+ }
+ return command.handle(update);
+ }
+ default -> {
+
+ return "Что-то пошло не так. Проблема на нашеё стороне";
+ }
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
new file mode 100644
index 0000000..70bc584
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.bot.telegram;
+
+public enum UserState {
+ TYPING_COMMAND, TYPING_TRACKED, TYPING_UNTRACKED
+}
diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties
new file mode 100644
index 0000000..9f20e72
--- /dev/null
+++ b/FP/bot/src/main/resources/application.properties
@@ -0,0 +1,13 @@
+app.test=beamer-bot
+server.port=8080
+springdoc.swagger-ui.path=/swagger-ui
+tg.bot.token=${TGBOTTOKEN}
+tg.api.baseUrl=https://api.telegram.org/bot
+spring.rabbitmq.host=localhost
+spring.rabbitmq.port=5672
+spring.rabbitmq.username=romanova
+spring.rabbitmq.password=12345654321
+spring.rabbitmq.listener.simple.default-requeue-rejected=false
+app.queue-name=scrapper-bot-queue
+app.exchange-name=scrapper-bot-exchange
+app.routing-key=scrapper-bot-key
\ No newline at end of file
diff --git a/FP/bot/src/test/java/bot/BotTest.java b/FP/bot/src/test/java/bot/BotTest.java
new file mode 100644
index 0000000..af954d2
--- /dev/null
+++ b/FP/bot/src/test/java/bot/BotTest.java
@@ -0,0 +1,123 @@
+package bot;
+
+import com.pengrad.telegrambot.model.Chat;
+import com.pengrad.telegrambot.model.Message;
+import com.pengrad.telegrambot.model.Update;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.test.util.ReflectionTestUtils;
+import ru.tinkoff.edu.java.bot.client.ScrapperClient;
+import ru.tinkoff.edu.java.bot.commands.Command;
+import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
+import ru.tinkoff.edu.java.bot.commands.ListCommand;
+import ru.tinkoff.edu.java.bot.dto.Link;
+import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
+import ru.tinkoff.edu.java.bot.telegram.UserMessageProcessor;
+import ru.tinkoff.edu.java.bot.telegram.UserState;
+
+import java.net.URI;
+import java.util.*;
+
+public class BotTest {
+
+ static UserMessageProcessor userMessageProcessor;
+
+ static ScrapperClient scrapperClient;
+
+ static Update updateForListCommand;
+ static Update updateForInvalidCommand;
+ static Message messageForListCommand;
+ static Message messageForInvalidCommand;
+
+ static Chat chat;
+
+ @BeforeAll
+ static void init() {
+ //инициализируем заглушки и входные дынные, т.к. у Update в нет сеттеров, то используем рефлексию,
+ //чтобы поместить туда нужный Message
+ scrapperClient = Mockito.mock(ScrapperClient.class);
+ updateForListCommand = new Update();
+ messageForListCommand = new Message();
+ chat = new Chat();
+ ReflectionTestUtils.setField(chat, "id", 42L);
+ ReflectionTestUtils.setField(messageForListCommand, "chat", chat);
+ ReflectionTestUtils.setField(messageForListCommand, "text", "/list");
+ ReflectionTestUtils.setField(updateForListCommand, "message", messageForListCommand);
+
+ updateForInvalidCommand = new Update();
+ messageForInvalidCommand = new Message();
+
+ ReflectionTestUtils.setField(messageForInvalidCommand, "chat", chat);
+ ReflectionTestUtils.setField(messageForInvalidCommand, "text", "Azazelo");
+ ReflectionTestUtils.setField(updateForInvalidCommand, "message", messageForInvalidCommand);
+ }
+
+ @Test
+ @DisplayName("Тест команды /list, когда список ссылок непустой")
+ public void listCommandTestNotEmpty() {
+
+ //имитируем нужное поведение клиента для Scrapper, т.к. реального запроса на Scrapper во время не происходит
+ List listLink = new ArrayList<>();
+ listLink.add(new Link(1L, URI.create("https://github.com/lwbeamer/asm-like-language")));
+ listLink.add(new Link(2L, URI.create("https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface")));
+ Mockito.when(scrapperClient.getLinks(42L)).thenReturn(
+ new ListLinkResponse(listLink, listLink.size())
+ );
+
+ EnumMap map = new EnumMap<>(CommandsEnum.class);
+ map.put(CommandsEnum.LIST, new ListCommand(scrapperClient));
+
+ userMessageProcessor = new UserMessageProcessor(map);
+
+ String expectedMessage = """
+ Ссылок отслеживается - 2
+
+ https://github.com/lwbeamer/asm-like-language
+
+ https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface
+
+ """;
+
+ Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand));
+ }
+
+
+ @Test
+ @DisplayName("Тест команды /list, когда список ссылок пустой")
+ public void listCommandTestEmpty() {
+ Mockito.when(scrapperClient.getLinks(42L)).thenReturn(
+ new ListLinkResponse(new ArrayList<>(), 0)
+ );
+
+
+ EnumMap map = new EnumMap<>(CommandsEnum.class);
+ map.put(CommandsEnum.LIST, new ListCommand(scrapperClient));
+
+ userMessageProcessor = new UserMessageProcessor(map);
+
+
+ String expectedMessage = "Список отслеживаемых ссылок пуст!";
+
+ Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand));
+ }
+
+ @Test
+ @DisplayName("Тест для проверки ввода неизвестной команды")
+ public void invalidCommandCheck() {
+ userMessageProcessor = new UserMessageProcessor(new EnumMap<>(CommandsEnum.class));
+
+ //Устанавливаем состояние перед тестом - пользователь в сосвтоянии "печатает команду"
+ Map userStateMap = new HashMap<>();
+ userStateMap.put(chat.id(), UserState.TYPING_COMMAND);
+ ReflectionTestUtils.setField(userMessageProcessor, "userStateMap", userStateMap);
+
+ String expectedMessage = "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд";
+
+ Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForInvalidCommand));
+
+ }
+
+}
\ No newline at end of file
diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml
new file mode 100644
index 0000000..c472659
--- /dev/null
+++ b/FP/docker-compose.yml
@@ -0,0 +1,60 @@
+services:
+ postgresql:
+ image: postgres:15
+ container_name: postgresql
+ ports:
+ - 5432:5432
+ environment:
+ - POSTGRES_USER=lwbeamer
+ - POSTGRES_PASSWORD=2281337
+ - POSTGRES_DB=scrapper
+ volumes:
+ - link-service-data:/var/lib/postgresql/data
+ networks:
+ - backend
+
+ liquibase-migrations:
+ image: liquibase/liquibase:4.18
+ depends_on:
+ - postgresql
+ command:
+ - --hub-mode=off
+ - --changelog-file=master.xml
+ - --driver=org.postgresql.Driver
+ - --url=jdbc:postgresql://postgresql:5432/scrapper
+ - --username=romanova
+ - --password=12345654321
+ - update
+ volumes:
+ - ./migrations:/liquibase/changelog
+ networks:
+ - backend
+
+volumes:
+ link-service-data:
+
+networks:
+ backend:
+ name: backend
+ rabbit:
+ image: rabbitmq:3-management
+ hostname: rabbitmq
+ container_name: rabbit
+ ports:
+ - 15672:15672
+ - 5672:5672
+ environment:
+ - RABBITMQ_DEFAULT_USER=romanova
+ - RABBITMQ_DEFAULT_PASS=12345654321
+ volumes:
+ - rabbitmq-state:/var/lib/rabbitmq
+ networks:
+ - backend
+
+volumes:
+ link-service-data:
+ rabbitmq-state:
+
+networks:
+ backend:
+ name: backend
\ No newline at end of file
diff --git a/FP/link-parser/.classpath b/FP/link-parser/.classpath
new file mode 100644
index 0000000..a08fc4f
--- /dev/null
+++ b/FP/link-parser/.classpath
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/link-parser/.gitignore b/FP/link-parser/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/link-parser/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/link-parser/.project b/FP/link-parser/.project
new file mode 100644
index 0000000..dec0f32
--- /dev/null
+++ b/FP/link-parser/.project
@@ -0,0 +1,23 @@
+
+
+ link-parser
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/link-parser/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/link-parser/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/=UTF-8
diff --git a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml
new file mode 100644
index 0000000..3cfd292
--- /dev/null
+++ b/FP/link-parser/pom.xml
@@ -0,0 +1,30 @@
+
+ 4.0.0
+
+ project
+ project
+ 0.0.1-SNAPSHOT
+
+ link-parser
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
new file mode 100644
index 0000000..e244c93
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.link_parser.link;
+
+public record GitHub_Link(String username, String repository) implements Parser_Link {
+
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
new file mode 100644
index 0000000..75db93c
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.link_parser.link;
+
+public sealed interface Parser_Link permits GitHub_Link, StackOverflow_Link {
+
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
new file mode 100644
index 0000000..1dad8ad
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.link_parser.link;
+
+public record StackOverflow_Link(long id) implements Parser_Link {
+
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
new file mode 100644
index 0000000..f3641fc
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
@@ -0,0 +1,27 @@
+package ru.tinkoff.edu.java.link_parser.parser;
+
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public abstract class Abstract {
+
+ Abstract nextParser;
+
+ public Abstract(Abstract nextParser) {
+ this.nextParser = nextParser;
+ }
+
+ public abstract Parser_Link parser_Link(String url);
+
+ public final URL tweakUrl(String urlString) {
+ URL url;
+ try{
+ url = new URL(urlString);
+ } catch (MalformedURLException e){
+ System.out.println("Incorrect URL");
+ return null;
+ }
+ return url;
+ }
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
new file mode 100644
index 0000000..13ae325
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
@@ -0,0 +1,31 @@
+package ru.tinkoff.edu.java.link_parser.parser;
+
+import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+
+import java.net.URL;
+
+
+public class Github extends Abstract {
+ public Github(Abstract nextParser) {
+ super(nextParser);
+ }
+
+ @Override
+ public Parser_Link parser_Link(String url) {
+ URL toParse = tweakUrl(url);
+ if (toParse == null) return null;
+
+ if (toParse.getHost().equals("github.com")) {
+ String[] tokens = toParse.getFile().substring(1).split("/");
+ if (tokens.length >= 2) {
+ return new GitHub_Link(tokens[0], tokens[1]);
+ } else return null;
+ }
+
+
+ if (nextParser != null) return nextParser.parser_Link(url);
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
new file mode 100644
index 0000000..fac1e3f
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
@@ -0,0 +1,16 @@
+package ru.tinkoff.edu.java.link_parser.parser;
+
+import ru.tinkoff.edu.java.link_parser.parser.Abstract;
+import ru.tinkoff.edu.java.link_parser.parser.Github;
+import ru.tinkoff.edu.java.link_parser.parser.StackOverflow;
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+
+public class Link_Parser {
+ public Parser_Link parseUrl(String url) {
+ Abstract parser1 = new Github(null);
+ Abstract parser2 = new StackOverflow(parser1);
+
+ return parser2.parser_Link(url);
+ }
+
+}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
new file mode 100644
index 0000000..e224578
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
@@ -0,0 +1,34 @@
+package ru.tinkoff.edu.java.link_parser.parser;
+
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
+import java.net.URL;
+public class StackOverflow extends Abstract {
+ public StackOverflow(Abstract nextParser) {
+ super(nextParser);
+ }
+
+ @Override
+ public Parser_Link parser_Link(String url) {
+
+ URL toParse = tweakUrl(url);
+ if (toParse == null) return null;
+
+
+ if (toParse.getHost().equals("stackoverflow.com")) {
+ String[] tokens = toParse.getFile().substring(1).split("/");
+ if (tokens.length >= 2 && tokens[0].equals("questions")) {
+ try {
+ return new StackOverflow_Link(Long.parseLong(tokens[1]));
+ } catch (NumberFormatException e) {
+ System.out.println("Incorrect question ID");
+ return null;
+ }
+ } else return null;
+ }
+
+ if (nextParser != null) return nextParser.parser_Link(url);
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/FP/link-parser/src/test/java/LinkParserTest.java b/FP/link-parser/src/test/java/LinkParserTest.java
new file mode 100644
index 0000000..bef7512
--- /dev/null
+++ b/FP/link-parser/src/test/java/LinkParserTest.java
@@ -0,0 +1,99 @@
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import ru.tinkoff.edu.java.link_parser.parser.*;
+import ru.tinkoff.edu.java.link_parser.link.*;
+
+public class LinkParserTest {
+
+ static String validGitHubLink;
+ static String validStackOverflowLink;
+ static String gitHubNotRepoLink;
+ static String stackOverflowNotQuestionLink;
+ static String emptyLink;
+ static String withoutProtocolLink;
+ static String unknownHostLink;
+ static String invalidLink;
+
+
+ @BeforeAll
+ static void init() {
+ validGitHubLink = "https://github.com/lwbeamer/asm-like-language";
+ validStackOverflowLink = "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file";
+ gitHubNotRepoLink = "https://github.com/issues";
+ stackOverflowNotQuestionLink = "https://stackoverflow.co/talent";
+ emptyLink = "";
+ withoutProtocolLink = "github.com/lwbeamer/asm-like-language";
+ unknownHostLink = "https://vk.com/feed";
+ invalidLink = "somethingNotValid";
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки валидной ссылки с GitHub")
+ void checkValidGitHubLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertEquals(new GitHub_Link("lwbeamer", "asm-like-language"), parser.parseUrl(validGitHubLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки валидной ссылки со StackOverflow")
+ void validStackOverflowLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertEquals(new StackOverflow_Link(2336692), parser.parseUrl(validStackOverflowLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки ссылки с GitHub, не являющейся репозиторием")
+ void gitHubNotRepoLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(gitHubNotRepoLink), "Тест не пройден, проверьте реузультат");
+ }
+
+ @Test
+ @DisplayName("Тест для проверки ссылки со StackOverflow, не являющейся вопросом")
+ void stackOverflowNotQuestionLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(stackOverflowNotQuestionLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки пустой ссылки")
+ void emptyLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(emptyLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки ссылки без указания протокола")
+ void withoutProtocolLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(withoutProtocolLink), "Тест не пройден, проверьте реузультат");
+ }
+
+ @Test
+ @DisplayName("Тест для проверки ссылки, не относящейся к отслеживаемым ресурсам")
+ void unknownHostLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(unknownHostLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+ @Test
+ @DisplayName("Тест для проверки непустой невалидной ссылки")
+ void invalidLink() {
+ Link_Parser parser = new Link_Parser();
+ Assertions.assertNull(parser.parseUrl(invalidLink), "Тест не пройден, проверьте реузультат");
+ }
+
+
+}
diff --git a/FP/migrations/01-schema-1.sql b/FP/migrations/01-schema-1.sql
new file mode 100644
index 0000000..838947b
--- /dev/null
+++ b/FP/migrations/01-schema-1.sql
@@ -0,0 +1,11 @@
+--liquibase formatted sql
+
+--changeset romanova:create-user-table-1
+CREATE TABLE "user" (
+ chat_id bigint PRIMARY KEY,
+ username text UNIQUE NOT NULL,
+ first_name text,
+ last_name text
+);
+
+--rollback DROP TABLE "user";
\ No newline at end of file
diff --git a/FP/migrations/02-schema-2.sql b/FP/migrations/02-schema-2.sql
new file mode 100644
index 0000000..0e40afb
--- /dev/null
+++ b/FP/migrations/02-schema-2.sql
@@ -0,0 +1,15 @@
+--liquibase formatted sql
+
+--changeset romanova:create-link-table-1
+CREATE TABLE "link" (
+ id bigserial PRIMARY KEY,
+ url text UNIQUE NOT NULL,
+ checked_at timestamp NOT NULL,
+ gh_pushed_at timestamp,
+ gh_description text,
+ gh_forks_count int,
+ so_answer_count int,
+ so_last_edit_date timestamp
+);
+
+--rollback DROP TABLE "link";
\ No newline at end of file
diff --git a/FP/migrations/03-schema-3.sql b/FP/migrations/03-schema-3.sql
new file mode 100644
index 0000000..c407b73
--- /dev/null
+++ b/FP/migrations/03-schema-3.sql
@@ -0,0 +1,10 @@
+--liquibase formatted sql
+
+--changeset romanova:create-user-link-table-1
+CREATE TABLE "user_link" (
+ link_id bigint REFERENCES "link" (id),
+ chat_id bigint REFERENCES "user" (chat_id),
+ PRIMARY KEY (link_id,chat_id)
+);
+
+--rollback DROP TABLE "user_link";
\ No newline at end of file
diff --git a/FP/migrations/create.sql b/FP/migrations/create.sql
new file mode 100644
index 0000000..a4e2a68
--- /dev/null
+++ b/FP/migrations/create.sql
@@ -0,0 +1,18 @@
+create table "user" (
+ chat_id bigint primary key,
+ username text unique not null,
+ first_name text,
+ last_name text
+);
+
+create table "link" (
+ id bigserial primary key,
+ url text unique not null,
+ updated_at timestamp not null
+);
+
+create table "user_link" (
+ link_id bigint references "link" (id),
+ chat_id bigint references "user" (chat_id),
+ primary key (link_id,chat_id)
+)
\ No newline at end of file
diff --git a/FP/migrations/delete.sql b/FP/migrations/delete.sql
new file mode 100644
index 0000000..1fb56bd
--- /dev/null
+++ b/FP/migrations/delete.sql
@@ -0,0 +1,3 @@
+drop table "user_link";
+drop table "user";
+drop table "link";
\ No newline at end of file
diff --git a/FP/migrations/insert.sql b/FP/migrations/insert.sql
new file mode 100644
index 0000000..30b59be
--- /dev/null
+++ b/FP/migrations/insert.sql
@@ -0,0 +1,37 @@
+insert into "user" (chat_id, username, first_name, last_name)
+values (42, 'testUser42', 'test', 'testov'),
+ (34, 'testUser34', 'test', 'testov'),
+ (65, 'testUser65', 'test', 'testov'),
+ (45, 'testUser45', 'test', 'testov'),
+ (523, 'testUser523', 'test', 'testov'),
+ (645, 'testUser645', 'test', 'testov'),
+ (7452, 'testUser7452', 'test', 'testov'),
+ (44562, 'testUser44562', 'test', 'testov'),
+ (423452, 'testUser423452', 'test', 'testov'),
+ (2, 'testUser2', 'test', 'testov');
+
+insert into "link" (url, updated_at)
+values ('https://stackoverflow.com/questions/14141266/postgresql-foreign-key-on-delete-cascade', '2022-05-19 15:13:27'),
+ ('https://github.com/linus/doctest','2022-01-31 13:13:50'),
+ ('https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file','2023-03-27 09:58:45');
+
+insert into "user_link" (link_id, chat_id)
+values (1,42),
+ (1,45),
+ (1,2),
+ (1,7452),
+ (2,44562),
+ (2,423452),
+ (2,645),
+ (2,523),
+ (3,34),
+ (3,65),
+ (3,7452),
+ (3,45),
+ (4,42),
+ (4,45),
+ (4,2),
+ (4,7452);
+
+
+
diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml
new file mode 100644
index 0000000..c566afc
--- /dev/null
+++ b/FP/migrations/master.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/pom.xml b/FP/pom.xml
new file mode 100644
index 0000000..a1baa3d
--- /dev/null
+++ b/FP/pom.xml
@@ -0,0 +1,123 @@
+
+ 4.0.0
+ project
+ project
+ 0.0.1-SNAPSHOT
+ pom
+
+ bot
+ link-parser
+ scrapper
+ scrapper-jooq
+
+
+ 3.0.1
+ 2022.0.0
+ 3.10.1
+ 23.1.0
+ UTF-8
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.version}
+ test
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring.test.version}
+ test
+
+
+
+
+
+
+
+ org.jetbrains
+ annotations
+ ${annotations.version}
+ provided
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+
+ true
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ repackage
+ build-info
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 17
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/scrapper-jooq/.classpath b/FP/scrapper-jooq/.classpath
new file mode 100644
index 0000000..ead1d0f
--- /dev/null
+++ b/FP/scrapper-jooq/.classpath
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/scrapper-jooq/.gitignore b/FP/scrapper-jooq/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/scrapper-jooq/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/scrapper-jooq/.project b/FP/scrapper-jooq/.project
new file mode 100644
index 0000000..f320f87
--- /dev/null
+++ b/FP/scrapper-jooq/.project
@@ -0,0 +1,23 @@
+
+
+ scrapper-jooq
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..609d3ca
--- /dev/null
+++ b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+encoding//src/main/resources=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/=UTF-8
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/FP/scrapper-jooq/pom.xml b/FP/scrapper-jooq/pom.xml
new file mode 100644
index 0000000..b6f0785
--- /dev/null
+++ b/FP/scrapper-jooq/pom.xml
@@ -0,0 +1,40 @@
+
+ 4.0.0
+
+ project
+ project
+ 0.0.1-SNAPSHOT
+
+ scrapper-jooq
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jooq
+
+
+ org.jooq
+ jooq-codegen
+
+
+ org.jooq
+ jooq-meta-extensions-liquibase
+ 3.18.3
+
+
+ org.jooq
+ jooq-postgres-extensions
+ 3.18.3
+
+
+ org.liquibase
+ liquibase-core
+
+
+
+
\ No newline at end of file
diff --git a/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/scrapper-jooq/src/main/java/JooqCodegen.java
new file mode 100644
index 0000000..ee35d24
--- /dev/null
+++ b/FP/scrapper-jooq/src/main/java/JooqCodegen.java
@@ -0,0 +1,49 @@
+import org.jooq.codegen.GenerationTool;
+import org.jooq.meta.jaxb.Configuration;
+import org.jooq.meta.jaxb.Database;
+import org.jooq.meta.jaxb.Generate;
+import org.jooq.meta.jaxb.Generator;
+import org.jooq.meta.jaxb.Property;
+import org.jooq.meta.jaxb.Target;
+
+public class JooqCodegen {
+ public static void main(String[] args) throws Exception {
+ Database database = new Database()
+ .withName("org.jooq.meta.extensions.liquibase.LiquibaseDatabase")
+ .withProperties(
+ new Property().withKey("rootPath").withValue("migrations"),
+ new Property().withKey("scripts").withValue("master.xml")
+ );
+
+ Generate options = new Generate()
+ .withGeneratedAnnotation(true)
+ .withGeneratedAnnotationDate(false)
+ .withNullableAnnotation(true)
+ .withNullableAnnotationType("org.jetbrains.annotations.Nullable")
+ .withNonnullAnnotation(true)
+ .withNonnullAnnotationType("org.jetbrains.annotations.NotNull")
+ .withJpaAnnotations(false)
+ .withValidationAnnotations(true)
+ .withSpringAnnotations(true)
+ .withConstructorPropertiesAnnotation(true)
+ .withConstructorPropertiesAnnotationOnPojos(true)
+ .withConstructorPropertiesAnnotationOnRecords(true)
+ .withFluentSetters(false)
+ .withDaos(false)
+ .withPojos(true);
+
+ Target target = new Target()
+ .withPackageName("ru.tinkoff.edu.java.scrapper.domain.jooq")
+ .withDirectory("scrapper/src/main/java");
+
+ Configuration configuration = new Configuration()
+ .withGenerator(
+ new Generator()
+ .withDatabase(database)
+ .withGenerate(options)
+ .withTarget(target)
+ );
+
+ GenerationTool.generate(configuration);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/.classpath b/FP/scrapper/.classpath
new file mode 100644
index 0000000..a08fc4f
--- /dev/null
+++ b/FP/scrapper/.classpath
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/scrapper/.gitignore b/FP/scrapper/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/scrapper/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/scrapper/.project b/FP/scrapper/.project
new file mode 100644
index 0000000..d56fd66
--- /dev/null
+++ b/FP/scrapper/.project
@@ -0,0 +1,23 @@
+
+
+ scrapper
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/scrapper/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/scrapper/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/=UTF-8
diff --git a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
new file mode 100644
index 0000000..1b0c4fa
--- /dev/null
+++ b/FP/scrapper/pom.xml
@@ -0,0 +1,120 @@
+
+
+ 4.0.0
+
+ project
+ project
+ 0.0.1-SNAPSHOT
+
+
+ scrapper
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework
+ spring-context-indexer
+ true
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.0.2
+
+
+ ru.tinkoff.edu
+ link-parser
+ 1.0-SNAPSHOT
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.testcontainers
+ postgresql
+ test
+
+
+ org.liquibase
+ liquibase-core
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.jooq
+ jooq
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
new file mode 100644
index 0000000..fef7338
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -0,0 +1,22 @@
+package ru.tinkoff.edu.java.scrapper;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl;
+
+
+@SpringBootApplication
+@EnableConfigurationProperties(ApplicationConfig.class)
+@EnableScheduling
+public class ScrapperApplication {
+ public static void main(String[] args) {
+ var ctx = SpringApplication.run(ScrapperApplication.class, args);
+ ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
new file mode 100644
index 0000000..2e1aacf
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
@@ -0,0 +1,33 @@
+package ru.tinkoff.edu.java.scrapper.advice;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.client.HttpClientErrorException;
+import ru.tinkoff.edu.java.scrapper.dto.ApiErrorResponse;
+import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
+import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
+import ru.tinkoff.edu.java.scrapper.exception.LinkIsAlreadyAddedException;
+import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
+
+import java.util.Arrays;
+
+@RestControllerAdvice
+public class AppExceptionHandler {
+
+ @ExceptionHandler({LinkNotFoundException.class, ChatNotFoundException.class})
+ @ResponseStatus(value = HttpStatus.NOT_FOUND)
+ public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) {
+ return new ApiErrorResponse(
+ "Error", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
+ }
+
+
+ @ExceptionHandler({ChatAlreadyExistException.class, LinkIsAlreadyAddedException.class})
+ @ResponseStatus(value = HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse handleBadRequestExceptions(RuntimeException exception) {
+ return new ApiErrorResponse(
+ "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
new file mode 100644
index 0000000..021e3ec
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
@@ -0,0 +1,38 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
+import ru.tinkoff.edu.java.scrapper.exception.BotClientException;
+import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
+
+@Slf4j
+public class BotClient {
+
+ @Value("${bot.baseurl}")
+ private String botBaseUrl;
+
+ private final WebClient webClient;
+
+ public BotClient(WebClient webClient) {
+ this.webClient = webClient;
+ }
+
+ public BotClient(String botBaseUrl) {
+ this.webClient = WebClient.create(botBaseUrl);
+ }
+
+ public void updateLink(LinkUpdate request) {
+ log.info("Sending update request to Bot");
+ webClient.post().uri("/updates").bodyValue(request).exchangeToMono(r -> {
+ if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
+ throw new BotClientException("Чат с таким ID не зарегистрирован");
+ }
+ return Mono.empty();
+ }).block();
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
new file mode 100644
index 0000000..156cf35
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
@@ -0,0 +1,47 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.reactive.function.client.WebClient;
+import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
+import org.springframework.http.HttpStatus;
+import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
+
+public class GitHubClient {
+
+
+ @Value("${gh.baseurl}")
+ private String gitHubBaseUrl;
+
+ private final WebClient webClient;
+
+ //для использования baseUrl по умолчанию (берётся из properties)
+ public GitHubClient() {
+ this.webClient = WebClient.create(gitHubBaseUrl);
+ }
+
+
+ //можно указать базовый URL
+ public GitHubClient(String baseUrl) {
+ this.webClient = WebClient.create(baseUrl);
+ }
+
+
+ public GitHubResponse fetchRepo(String owner, String repo) {
+ GitHubResponse response = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{
+ if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API");
+ return r.bodyToMono(GitHubResponse.class);
+ }).block();
+
+ return response;
+
+ }
+ public void strFetchRepo(String owner, String repo){
+ String strReponse = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{
+ if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API");
+ return r.bodyToMono(String.class);
+ }).block();
+
+ System.out.println(strReponse);
+
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
new file mode 100644
index 0000000..6651dd9
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
@@ -0,0 +1,44 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.http.HttpStatus;
+import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
+import ru.tinkoff.edu.java.scrapper.dto.StackOverflowResponse;
+import ru.tinkoff.edu.java.scrapper.exception.BadResponseFromApiException;
+import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
+import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
+import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
+
+public class StackOverflowClient {
+
+ @Value("${so.baseurl}")
+ private String stackOverflowBaseUrl;
+
+ private final WebClient webClient;
+
+
+ //для использования baseUrl по умолчанию (берётся из properties)
+ public StackOverflowClient() {
+ this.webClient = WebClient.create(stackOverflowBaseUrl);
+ }
+
+
+ //можно указать базовый URL
+ public StackOverflowClient(String baseUrl) {
+ this.webClient = WebClient.create(baseUrl);
+ }
+
+ public StackOverflowItem fetchQuestion(long id) {
+
+ StackOverflowResponse response = webClient.get().uri("/questions/{id}?order=desc&sort=activity&site=stackoverflow", id).exchangeToMono(r->{
+ if (!r.statusCode().equals(HttpStatus.OK)) throw new StackOverflowRequestException("Error with request to SO API");
+ return r.bodyToMono(StackOverflowResponse.class);
+ }).block();
+
+ if (response == null || response.items().size() == 0)
+ throw new BadResponseFromApiException("API StackOverflow returned bad response");
+
+ return response.items().get(0);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
new file mode 100644
index 0000000..856e54e
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.scrapper.configuration;
+
+import jakarta.validation.constraints.NotNull;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.validation.annotation.Validated;
+import ru.tinkoff.edu.java.scrapper.schedule.Scheduler;
+
+@Validated
+@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
+public record ApplicationConfig(@NotNull String test,
+ @NotNull Scheduler scheduler,
+ @NotNull AccessType dataBaseAccessType,
+ @NotNull Boolean useQueue,
+ String queueName,
+ String exchangeName,
+ String routingKey){
+
+ @Bean
+ public long schedulerIntervalMs(ApplicationConfig config) {
+ return config.scheduler().interval().toMillis();
+ }
+ public enum AccessType {
+ JDBC, JPA, JOOQ
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
new file mode 100644
index 0000000..8694acf
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
@@ -0,0 +1,44 @@
+package ru.tinkoff.edu.java.scrapper.configuration;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import org.springframework.web.reactive.function.client.WebClient;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+
+@Configuration
+public class ClientConfiguration {
+
+ @Value("${gh.baseurl}")
+ private String gitHubBaseUrl;
+
+ @Value("${so.baseurl}")
+ private String stackOverflowBaseUrl;
+
+ @Value("${bot.baseurl}")
+ private String botBaseUrl;
+
+
+ //Регистрируем клиентов как бины
+ @Bean
+ public GitHubClient gitHubClientService() {
+ return new GitHubClient(gitHubBaseUrl);
+ }
+
+ @Bean
+ public StackOverflowClient stackOverflowClientService() {
+ return new StackOverflowClient(stackOverflowBaseUrl);
+ }
+ @Bean
+ public WebClient ghWebClient(){
+ return WebClient.create(gitHubBaseUrl);
+ }
+
+ @Bean
+ public WebClient soWebClient(){
+ return WebClient.create(stackOverflowBaseUrl);
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
new file mode 100644
index 0000000..df6780e
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
@@ -0,0 +1,28 @@
+package ru.tinkoff.edu.java.scrapper.configuration;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+
+@Configuration
+@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "false")
+public class HTTPConfiguration {
+
+ @Value("${bot.baseurl}")
+ private String botBaseUrl;
+
+
+ @Bean
+ public BotClient botClient(){return new BotClient(botBaseUrl);}
+
+ @Bean
+ public WebClient botWebClient(){
+ return WebClient.create(botBaseUrl);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
new file mode 100644
index 0000000..e400f15
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.scrapper.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
+
+@Configuration
+public class LinkParserConfiguration {
+
+ @Bean
+ public Link_Parser linkParser(){
+ return new Link_Parser();
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
new file mode 100644
index 0000000..d8b1217
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -0,0 +1,50 @@
+package ru.tinkoff.edu.java.scrapper.configuration;
+
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.scrapper.service.ScrapperQueueProducer;
+
+@Configuration
+@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "true")
+public class RabbitMQConfiguration {
+
+ private final ApplicationConfig config;
+
+ public RabbitMQConfiguration(ApplicationConfig config) {
+ this.config = config;
+ }
+
+ @Bean
+ Queue queue() {
+ return QueueBuilder.durable(config.queueName())
+ .withArgument("x-dead-letter-exchange", config.exchangeName())
+ .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq")
+ .build();
+ }
+
+ @Bean
+ DirectExchange exchange() {
+ return new DirectExchange(config.exchangeName());
+ }
+
+ @Bean
+ Binding binding(Queue queue, DirectExchange exchange) {
+ return BindingBuilder.bind(queue).to(exchange).with(config.routingKey());
+ }
+
+ @Bean
+ public MessageConverter jsonMessageConverter() {
+ return new Jackson2JsonMessageConverter();
+ }
+
+
+ @Bean
+ public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) {
+ return new ScrapperQueueProducer(rabbitTemplate, config);
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
new file mode 100644
index 0000000..d70f747
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
@@ -0,0 +1,99 @@
+package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.link_parser.Link_Parser;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
+import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
+import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
+import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
+
+@Configuration
+@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jdbc")
+public class JdbcAccessConfiguration {
+
+ @Bean
+ public LinkRowMapper linkRowMapper() {
+ return new LinkRowMapper();
+ }
+
+ @Bean
+ public SubscriptionRowMapper subscriptionRowMapper() {
+ return new SubscriptionRowMapper();
+ }
+
+ @Bean
+ public UserRowMapper userRowMapper() {
+ return new UserRowMapper();
+ }
+
+ @Bean
+ public LinkRepository linkRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) {
+ return new LinkJdbcTemplateRepository(jdbcTemplate, linkRowMapper);
+ }
+
+ @Bean
+ public SubscriptionRepository subscriptionRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper) {
+ return new SubscriptionJdbcTemplateRepository(jdbcTemplate, subscriptionRowMapper, linkRowMapper());
+ }
+
+ @Bean
+ public UserRepository userRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) {
+ return new UserJdbcTemplateRepository(jdbcTemplate, userRowMapper);
+ }
+
+ @Bean
+ public LinkUpdateService linkUpdateService(
+ LinkRepository linkRepository,
+ SubscriptionRepository subscriptionRepository,
+ Link_Parser linkParser,
+ GitHubClient gitHubClient,
+ StackOverflowClient stackOverflowClient,
+ BotClient botClient
+ ) {
+ return new LinkUpdateServiceImpl(
+ linkRepository,
+ subscriptionRepository,
+ linkParser,
+ gitHubClient,
+ stackOverflowClient,
+ botClient);
+ }
+
+ @Bean
+ public SubscriptionService subscriptionService(
+ LinkRepository linkRepository,
+ SubscriptionRepository subscriptionRepository
+ ) {
+ return new SubscriptionServiceImpl(
+ linkRepository,
+ subscriptionRepository);
+ }
+
+ @Bean
+ public TgChatService tgChatService(
+ UserRepository userRepository,
+ SubscriptionRepository subscriptionRepository
+ ) {
+ return new TgChatServiceImpl(
+ userRepository,
+ subscriptionRepository);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
new file mode 100644
index 0000000..47864de
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
@@ -0,0 +1,84 @@
+package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
+
+import org.jooq.DSLContext;
+import org.jooq.impl.DSL;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.link_parser.Link_Parser;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jooq.LinkJooqRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jooq.SubscriptionJooqRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jooq.UserJooqRepository;
+import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
+@Configuration
+@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jooq")
+public class JooqAccessConfiguration {
+
+
+ @Bean
+ public LinkRepository linkRepository(DSLContext dslContext){
+ return new LinkJooqRepository(dslContext);
+ }
+
+ @Bean
+ public SubscriptionRepository subscriptionRepository(DSLContext dslContext){
+ return new SubscriptionJooqRepository(dslContext);
+ }
+
+
+ @Bean
+ public UserRepository userRepository(DSLContext dslContext){
+ return new UserJooqRepository(dslContext);
+ }
+
+ @Bean
+ public LinkUpdateService linkUpdateService(
+ LinkRepository linkRepository,
+ SubscriptionRepository subscriptionRepository,
+ LinkParser linkParser,
+ GitHubClient gitHubClient,
+ StackOverflowClient stackOverflowClient,
+ BotClient botClient
+ ) {
+ return new LinkUpdateServiceImpl(
+ linkRepository,
+ subscriptionRepository,
+ linkParser,
+ gitHubClient,
+ stackOverflowClient,
+ botClient);
+ }
+
+ @Bean
+ public SubscriptionService subscriptionService(
+ LinkRepository linkRepository,
+ SubscriptionRepository subscriptionRepository
+ ) {
+ return new SubscriptionServiceImpl(
+ linkRepository,
+ subscriptionRepository);
+ }
+
+ @Bean
+ public TgChatService tgChatService(
+ UserRepository userRepository,
+ SubscriptionRepository subscriptionRepository
+ ) {
+ return new TgChatServiceImpl(
+ userRepository,
+ subscriptionRepository);
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
new file mode 100644
index 0000000..ff97aba
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
@@ -0,0 +1,61 @@
+package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.link_parser.Link_Parser;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
+import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaLinkUpdateServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl;
+import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl;
+
+@Configuration
+@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jpa")
+public class JpaAccessConfiguration {
+
+ @Bean
+ public LinkUpdateService linkUpdateService(
+ JpaLinkRepository linkRepository,
+ Link_Parser linkParser,
+ GitHubClient gitHubClient,
+ StackOverflowClient stackOverflowClient,
+ BotClient botClient) {
+ return new JpaLinkUpdateServiceImpl(
+ linkRepository,
+ linkParser,
+ gitHubClient,
+ stackOverflowClient,
+ botClient
+ );
+ }
+
+ @Bean
+ public SubscriptionService subscriptionService(
+ JpaLinkRepository linkRepository,
+ JpaUserRepository userRepository) {
+ return new JpaSubscriptionServiceImpl(
+ linkRepository,
+ userRepository
+ );
+ }
+
+ @Bean
+ public TgChatService tgChatService(
+ JpaUserRepository userRepository) {
+ return new JpaTgChatServiceImpl(
+ userRepository
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
new file mode 100644
index 0000000..97985ba
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+public record AddLinkRequest(String link) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
new file mode 100644
index 0000000..7c065be
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+public record ApiErrorResponse(String description, String code, String exceptionName,
+ String exceptionMessage, String[] stacktrace) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
new file mode 100644
index 0000000..8f6367c
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
@@ -0,0 +1,25 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.OffsetDateTime;
+
+public record GitHubResponse(@JsonProperty("pushed") OffsetDateTime pushedAt,
+ @JsonProperty("updated") OffsetDateTime updatedAt,
+ @JsonProperty("full_name") String fullName,
+ @JsonProperty("description") String description,
+ @JsonProperty("forks_count") int forksCount
+) {
+
+
+@Override
+public String toString() {
+ return "GitHubResponse{" +
+ "pushedAt=" + pushedAt +
+ ", updatedAt=" + updatedAt +
+ ", fullName='" + fullName + '\'' +
+ ", description='" + description + '\'' +
+ ", forksCount=" + forksCount +
+ '}';
+}
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
new file mode 100644
index 0000000..cadc95f
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+public record LinkResponse(long id, String url) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
new file mode 100644
index 0000000..1b6410a
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
new file mode 100644
index 0000000..a142f3a
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import java.util.List;
+
+public record ListLinkResponse(List links, int size) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
new file mode 100644
index 0000000..09a3867
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+public record RemoveLinkRequest(String link) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
new file mode 100644
index 0000000..9e2f0b9
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.OffsetDateTime;
+public record StackOverflowItem(@JsonProperty("last_edit_date") OffsetDateTime lastActivityDate,
+ @JsonProperty("last_activity_date") OffsetDateTime lastEditDate) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
new file mode 100644
index 0000000..50227fc
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.OffsetDateTime;
+import java.util.List;
+public record StackOverflowResponse(List items) {
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
new file mode 100644
index 0000000..58d769c
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.scrapper.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public record UserAddDto(@JsonProperty("username") String username,
+ @JsonProperty("first_name") String firstName,
+ @JsonProperty("last_name") String lastName) {
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
new file mode 100644
index 0000000..d5be7a4
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class BadResponseFromApiException extends RuntimeException {
+
+ public BadResponseFromApiException() {
+ }
+
+ public BadResponseFromApiException(String message) {
+ super(message);
+ }
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
new file mode 100644
index 0000000..9ee4d12
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class BotClientException extends RuntimeException{
+
+ public BotClientException() {
+ }
+
+ public BotClientException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
new file mode 100644
index 0000000..5dd1124
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class ChatAlreadyExistException extends RuntimeException {
+
+ public ChatAlreadyExistException() {
+ }
+
+ public ChatAlreadyExistException(String message) {
+ super(message);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
new file mode 100644
index 0000000..29dc8cf
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class ChatNotFoundException extends RuntimeException {
+
+ public ChatNotFoundException(String message) {
+ super(message);
+ }
+
+ public ChatNotFoundException() {
+ }
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
new file mode 100644
index 0000000..9bf30c3
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class GitHubRequestException extends RuntimeException{
+
+ public GitHubRequestException() {
+ }
+
+ public GitHubRequestException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
new file mode 100644
index 0000000..58a7dfb
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class LinkIsAlreadyAddedException extends RuntimeException {
+
+
+ public LinkIsAlreadyAddedException(String message) {
+ super(message);
+ }
+
+ public LinkIsAlreadyAddedException() {
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
new file mode 100644
index 0000000..e5c5c62
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class LinkNotFoundException extends RuntimeException {
+
+ public LinkNotFoundException() {
+ }
+
+ public LinkNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
new file mode 100644
index 0000000..e714110
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exception;
+
+public class StackOverflowRequestException extends RuntimeException{
+
+ public StackOverflowRequestException() {
+ super();
+ }
+
+ public StackOverflowRequestException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
new file mode 100644
index 0000000..72df1e2
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
@@ -0,0 +1,27 @@
+package ru.tinkoff.edu.java.scrapper.mapper;
+
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import ru.tinkoff.edu.java.scrapper.model.User;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@Component
+public class LinkRowMapper implements RowMapper {
+
+ @Override
+ public Link mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Link link = new Link();
+ link.setId(rs.getLong("id"));
+ link.setUrl(rs.getString("url"));
+ link.setCheckedAt(rs.getTimestamp("checked_at"));
+ link.setGhPushedAt(rs.getTimestamp("gh_pushed_at"));
+ link.setGhDescription(rs.getString("gh_description"));
+ link.setGhForksCount(rs.getInt("gh_forks_count"));
+ link.setSoAnswerCount(rs.getInt("so_answer_count"));
+ link.setSoLastEditDate(rs.getTimestamp("so_last_edit_date"));
+ return link;
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
new file mode 100644
index 0000000..bd76b2b
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.scrapper.mapper;
+
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.scrapper.model.Relation;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@Component
+public class SubscriptionRowMapper implements RowMapper {
+
+ @Override
+ public Relation mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Relation relation = new Relation();
+ relation.setLinkId(rs.getLong("link_id"));
+ relation.setChatId(rs.getLong("chat_id"));
+
+ return relation;
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
new file mode 100644
index 0000000..4597040
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
@@ -0,0 +1,24 @@
+package ru.tinkoff.edu.java.scrapper.mapper;
+
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.scrapper.model.User;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+
+@Component
+public class UserRowMapper implements RowMapper {
+
+
+ @Override
+ public User mapRow(ResultSet rs, int rowNum) throws SQLException {
+ User user = new User();
+ user.setChatId(rs.getLong("chat_id"));
+ user.setUsername(rs.getString("username"));
+ user.setFirstName(rs.getString("first_name"));
+ user.setLastName(rs.getString("last_name"));
+ return user;
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
new file mode 100644
index 0000000..59b4a92
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
@@ -0,0 +1,31 @@
+package ru.tinkoff.edu.java.scrapper.model.commonDto;
+
+import lombok.Data;
+import java.sql.Timestamp;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+
+@Data
+public class Link {
+
+
+ private Long id;
+ private String url;
+ private Timestamp checkedAt;
+ private Timestamp ghPushedAt;
+ private String ghDescription;
+ private int ghForksCount;
+ private Timestamp soLastEditDate;
+ private int soAnswerCount;
+ public static Link fromEntity(LinkEntity linkEntity){
+ Link link = new Link();
+ link.setId(linkEntity.getId());
+ link.setUrl(linkEntity.getUrl());
+ link.setCheckedAt(linkEntity.getCheckedAt());
+ link.setGhDescription(linkEntity.getGhDescription());
+ link.setGhPushedAt(linkEntity.getGhPushedAt());
+ Integer forks = linkEntity.getGhForksCount(); if (forks == null) link.setGhForksCount(0); else link.setGhForksCount(forks);
+ Integer answers = linkEntity.getSoAnswerCount(); if (answers == null) link.setSoAnswerCount(0); else link.setSoAnswerCount(answers);
+ link.setSoLastEditDate(linkEntity.getSoLastEditDate());
+ return link;
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
new file mode 100644
index 0000000..74f7693
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
@@ -0,0 +1,32 @@
+package ru.tinkoff.edu.java.scrapper.model.commonDto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
+
+@Data
+@NoArgsConstructor
+public class User {
+
+ public User(Long chatId, String username, String firstName, String lastName) {
+ this.chatId = chatId;
+ this.username = username;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ private Long chatId;
+ private String username;
+ private String firstName;
+ private String lastName;
+ public static UserEntity toEntity(User user){
+ UserEntity userEntity = new UserEntity();
+
+ userEntity.setChatId(user.getChatId());
+ userEntity.setUsername(user.getUsername());
+ userEntity.setFirstName(user.getFirstName());
+ userEntity.setLastName(user.getLastName());
+
+ return userEntity;
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
new file mode 100644
index 0000000..abe684a
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq;
+
+import lombok.Data;
+
+@Data
+public class Relation {
+
+ private Long linkId;
+ private Long chatId;
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
new file mode 100644
index 0000000..bd4469b
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
@@ -0,0 +1,40 @@
+package ru.tinkoff.edu.java.scrapper.model.jpa;
+
+import jakarta.persistence.*;
+import lombok.Data;
+import java.sql.Timestamp;
+import java.util.List;
+
+@Entity
+@Table(name = "link")
+@Data
+public class LinkEntity {
+
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "url", unique = true, nullable = false)
+ private String url;
+
+ @Column(name = "checked_at", nullable = false)
+ private Timestamp checkedAt;
+
+ @Column(name = "gh_pushed_at")
+ private Timestamp ghPushedAt;
+
+ @Column(name = "gh_description")
+ private String ghDescription;
+
+ @Column(name = "gh_forks_count")
+ private Integer ghForksCount;
+
+ @Column(name = "so_last_edit_date")
+ private Timestamp soLastEditDate;
+
+ @Column(name = "so_answer_count")
+ private Integer soAnswerCount;
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
new file mode 100644
index 0000000..8f49d40
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
@@ -0,0 +1,30 @@
+package ru.tinkoff.edu.java.scrapper.model.jpa;
+
+import jakarta.persistence.*;
+import lombok.Data;
+import java.util.List;
+
+@Entity
+@Table(name = "\"user\"")
+@Data
+public class UserEntity {
+
+ @Id
+ @Column(name = "chat_id")
+ private Long chatId;
+
+ @Column(name = "username", unique = true, nullable = false)
+ private String username;
+
+ @Column(name = "first_name")
+ private String firstName;
+
+ @Column(name = "last_name")
+ private String lastName;
+
+ @ManyToMany(fetch = FetchType.LAZY)
+ @JoinTable(name = "user_link",
+ joinColumns = @JoinColumn(name = "chat_id"),
+ inverseJoinColumns = @JoinColumn(name = "link_id"))
+ private List links;
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
new file mode 100644
index 0000000..38d0931
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
@@ -0,0 +1,86 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbc;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.repository.LinkRepository;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@Slf4j
+public class LinkJdbcTemplateRepository implements LinkRepository {
+
+
+ private final JdbcTemplate jdbcTemplate;
+
+ private final LinkRowMapper linkRowMapper;
+
+ public LinkJdbcTemplateRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.linkRowMapper = linkRowMapper;
+ }
+
+
+ @Override
+ public List findAll() {
+ log.info("findAll() method invocation in linkRepo");
+ String sql = "select * from link";
+ return jdbcTemplate.query(sql, linkRowMapper);
+ }
+
+ @Override
+ public Link findByUrl(String url) {
+ log.info("findByUrl() method invocation in linkRepo");
+ String sql = "select * from link where link.url = ?";
+ List link = jdbcTemplate.query(sql, linkRowMapper, url);
+ return link.size() == 0 ? null : link.get(0);
+ }
+
+ @Override
+ public void add(Link link) {
+ log.info("add() method invocation in linkRepo");
+ String sql = "insert into link (url, updated_at) values(?, ?)";
+ jdbcTemplate.update(sql, link.getUrl(), link.getUpdatedAt());
+ }
+
+
+ @Override
+ public void updateDate(Link link) {
+ log.info("updateDate() method invocation in linkRepo");
+ String sql = "update link set updated_at = ? where id = ?";
+ jdbcTemplate.update(sql, link.getUpdatedAt(), link.getId());
+ }
+
+ @Override
+ public void remove(Long id) {
+ log.info("remove() method invocation in linkRepo");
+ String sql = "delete from link where link.id = ?";
+ jdbcTemplate.update(sql, id);
+ }
+
+ @Override
+ //поиск ссылок по критерию
+ public List findOldLinks(Long timeUpdateDelta) {
+ log.info("findOldLinks() method invocation in linkRepo");
+ Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDelta*1000);
+ String sql = "select * from link where link.updated_at < ? order by link.updated_at desc";
+ return jdbcTemplate.query(sql,linkRowMapper,compareDate);
+ }
+ @Override
+ public void updateGhLink(Link link) {
+ log.info("updateGhLink() method invocation in linkJdbcRepo");
+ String sql = "update link set gh_forks_count = ?, gh_description = ?, gh_pushed_at = ? where id = ?";
+ jdbcTemplate.update(sql, link.getGhForksCount(), link.getGhDescription(), link.getGhPushedAt(), link.getId());
+ }
+
+ @Override
+ public void updateSoLink(Link link) {
+ log.info("updateSoLastEditDate() method invocation in linkJdbcRepo");
+ String sql = "update link set so_last_edit_date = ?, so_answer_count = ? where id = ?";
+ jdbcTemplate.update(sql, link.getSoLastEditDate(), link.getSoAnswerCount(), link.getId());
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
new file mode 100644
index 0000000..fce7af7
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
@@ -0,0 +1,75 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbc;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
+import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import ru.tinkoff.edu.java.scrapper.model.Relation;
+import ru.tinkoff.edu.java.scrapper.model.User;
+import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository;
+
+import java.util.List;
+
+@Repository
+@Slf4j
+public class SubscriptionJdbcTemplateRepository implements SubscriptionRepository {
+
+ private final JdbcTemplate jdbcTemplate;
+
+ private final SubscriptionRowMapper subscriptionRowMapper;
+
+ private final LinkRowMapper linkRowMapper;
+
+ public SubscriptionJdbcTemplateRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper, LinkRowMapper linkRowMapper) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.subscriptionRowMapper = subscriptionRowMapper;
+ this.linkRowMapper = linkRowMapper;
+ }
+
+ @Override
+ public List findLinksByChat(Long chatId) {
+ log.info("findLinksByChat() method invocation in subscriptionRepo");
+ String sql = "select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?";
+ return jdbcTemplate.query(sql, linkRowMapper, chatId);
+ }
+
+ @Override
+ public List findChatsByLink(Long linkId) {
+ log.info("findChatsByLink() method invocation in subscriptionRepo");
+ String sql = "select * from user_link where user_link.link_id = ?";
+ return jdbcTemplate.query(sql, subscriptionRowMapper, linkId);
+ }
+
+ @Override
+ public Relation findSubscription(Long linkId, Long chatId) {
+ log.info("findSubscription() method invocation in subscriptionRepo");
+ String sql = "select * from user_link rel where rel.chat_id = ? and rel.link_id = ?";
+ List relation = jdbcTemplate.query(sql, subscriptionRowMapper, chatId, linkId);
+ return relation.size() == 0 ? null : relation.get(0);
+ }
+
+
+ @Override
+ public void addRelation(Relation relation) {
+ log.info("addRelation() method invocation in subscriptionRepo");
+ String sql = "insert into user_link (link_id, chat_id) values(?, ?)";
+ jdbcTemplate.update(sql, relation.getLinkId(), relation.getChatId());
+ }
+
+ @Override
+ public void remove(Long linkId, Long chatId) {
+ log.info("remove() method invocation in subscriptionRepo");
+ String sql = "delete from user_link where user_link.link_id = ? and user_link.chat_id = ?";
+ jdbcTemplate.update(sql, linkId, chatId);
+ }
+
+ @Override
+ public void removeAllByUser(Long chatId) {
+ log.info("removeAllByUser() method invocation in subscriptionRepo");
+ String sql = "delete from user_link where user_link.chat_id = ?";
+ jdbcTemplate.update(sql, chatId);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
new file mode 100644
index 0000000..d59d09c
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
@@ -0,0 +1,59 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbc;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.User;
+import ru.tinkoff.edu.java.scrapper.repository.UserRepository;
+
+import java.util.List;
+
+@Repository
+@Slf4j
+public class UserJdbcTemplateRepository implements UserRepository {
+
+
+ private final JdbcTemplate jdbcTemplate;
+
+ private final UserRowMapper userRowMapper;
+
+
+ public UserJdbcTemplateRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.userRowMapper = userRowMapper;
+ }
+
+ @Override
+ public List findAll(){
+ log.info("findAll() method invocation in userRepo");
+ String sql = "select * from \"user\"";
+ return jdbcTemplate.query(sql, userRowMapper);
+ }
+
+ @Override
+ public User findByChatId(Long id) {
+ log.info("findByChatId() method invocation in userRepo");
+ String sql = "select * from \"user\" where \"user\".chat_id = ?";
+ List user = jdbcTemplate.query(sql, userRowMapper, id);
+ return user.size() == 0 ? null : user.get(0);
+ }
+
+ @Override
+ public void add(User user){
+ log.info("add() method invocation in userRepo");
+ String sql = "insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)";
+ jdbcTemplate.update(sql, user.getChatId(), user.getUsername(), user.getFirstName(), user.getLastName());
+ }
+
+ @Override
+ public void remove(Long chatId){
+ log.info("remove() method invocation in userRepo");
+ String sql = "delete from \"user\" where \"user\".chat_id = ?";
+ jdbcTemplate.update(sql,chatId);
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
new file mode 100644
index 0000000..0298278
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
@@ -0,0 +1,21 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import java.util.List;
+
+
+public interface LinkRepository {
+ List findAll();
+
+
+ Link findByUrl(String url);
+ void add(Link link);
+
+ void updateCheckDate(Link link);
+ void remove(Long id);
+ List findOldLinks(Long timeUpdateDeltaInSeconds);
+
+ void updateGhLink(Link link);
+
+ void updateSoLink(Link link);
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
new file mode 100644
index 0000000..0dde7e4
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
@@ -0,0 +1,19 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
+
+import java.util.List;
+
+public interface SubscriptionRepository {
+
+ List findLinksByChat(Long chatId);
+
+ List findChatsByLink(Long linkId);
+
+ Relation findSubscription(Long linkId, Long chatId);
+ void addRelation(Relation relation);
+ void remove(Long linkId, Long chatId);
+
+ void removeAllByUser(Long chatId);
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
new file mode 100644
index 0000000..87cbf34
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
@@ -0,0 +1,13 @@
+package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+import java.util.List;
+
+public interface UserRepository {
+ List findAll();
+
+ User findByChatId(Long id);
+ void add(User user);
+ void remove(Long id);
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
new file mode 100644
index 0000000..7371ffd
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
@@ -0,0 +1,98 @@
+package ru.tinkoff.edu.java.scrapper.repository.jooq;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jooq.DSLContext;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
+import java.sql.Timestamp;
+import java.util.List;
+import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*;
+
+@Slf4j
+public class LinkJooqRepository implements LinkRepository {
+
+
+ private final DSLContext dslContext;
+
+
+
+ public LinkJooqRepository(DSLContext dslContext) {
+ this.dslContext = dslContext;
+ }
+
+ @Override
+ public List findAll() {
+ log.info("findAll() method invocation in linkJooqRepo");
+ return dslContext.selectFrom(LINK)
+ .fetchInto(Link.class);
+ }
+
+ @Override
+ public Link findByUrl(String url) {
+ log.info("findByUrl() method invocation in linkJooqRepo");
+ return dslContext.selectFrom(LINK)
+ .where(LINK.URL.eq(url))
+ .fetchOneInto(Link.class);
+ }
+
+ @Override
+ public void add(Link link) {
+ log.info("add() method invocation in linkJooqRepo");
+ dslContext.insertInto(LINK)
+ .set(LINK.URL, link.getUrl())
+ .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
+ .execute();
+ }
+
+ @Override
+ public void updateCheckDate(Link link) {
+ log.info("updateDate() method invocation in linkJooqRepo");
+ dslContext.update(LINK)
+ .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
+ .where(LINK.ID.eq(link.getId()))
+ .execute();
+ }
+
+ @Override
+ public void remove(Long id) {
+ log.info("remove() method invocation in linkJooqRepo");
+ dslContext.deleteFrom(LINK)
+ .where(LINK.ID.eq(id))
+ .execute();
+ }
+
+ @Override
+ public List findOldLinks(Long timeUpdateDeltaInSeconds) {
+ log.info("findOldLinks() method invocation in linkJooqRepo");
+ Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds * 1000);
+ return dslContext.selectFrom(LINK)
+ .where(LINK.CHECKED_AT.lessThan(compareDate.toLocalDateTime()))
+ .orderBy(LINK.CHECKED_AT.desc())
+ .fetchInto(Link.class);
+ }
+
+ @Override
+ public void updateGhLink(Link link) {
+ log.info("updateGhLink() method invocation in linkJooqRepo");
+ dslContext.update(LINK)
+ .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
+ .set(LINK.GH_FORKS_COUNT, link.getGhForksCount())
+ .set(LINK.GH_DESCRIPTION, link.getGhDescription())
+ .set(LINK.GH_PUSHED_AT, link.getGhPushedAt().toLocalDateTime())
+ .where(LINK.ID.eq(link.getId()))
+ .execute();
+ }
+
+ @Override
+ public void updateSoLink(Link link) {
+ log.info("updateSoLink() method invocation in linkJooqRepo");
+ dslContext.update(LINK)
+ .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
+ .set(LINK.SO_LAST_EDIT_DATE, link.getSoLastEditDate().toLocalDateTime())
+ .set(LINK.SO_ANSWER_COUNT, link.getSoAnswerCount())
+ .where(LINK.ID.eq(link.getId()))
+ .execute();
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
new file mode 100644
index 0000000..6463de4
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
@@ -0,0 +1,80 @@
+package ru.tinkoff.edu.java.scrapper.repository.jooq;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jooq.DSLContext;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import ru.tinkoff.edu.java.scrapper.model.Relation;
+import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository;
+
+import java.util.List;
+
+import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.UserLink.*;
+import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*;
+
+
+@Repository
+@Slf4j
+public class SubscriptionJooqRepository implements SubscriptionRepository {
+
+
+ private final DSLContext dslContext;
+
+
+ public SubscriptionJooqRepository(DSLContext dslContext) {
+ this.dslContext = dslContext;
+ }
+
+
+ @Override
+ public List findLinksByChat(Long chatId) {
+ log.info("findLinksByChat() method invocation in subscriptionJooqRepo");
+ return dslContext.select()
+ .from(LINK)
+ .join(USER_LINK).on(LINK.ID.eq(USER_LINK.LINK_ID))
+ .where(USER_LINK.CHAT_ID.eq(chatId))
+ .fetchInto(Link.class);
+ }
+
+ @Override
+ public List findChatsByLink(Long linkId) {
+ log.info("findChatsByLink() method invocation in subscriptionJooqRepo");
+ return dslContext.select()
+ .from(USER_LINK)
+ .where(USER_LINK.LINK_ID.eq(linkId))
+ .fetchInto(Relation.class);
+ }
+
+ @Override
+ public Relation findSubscription(Long linkId, Long chatId) {
+ log.info("findSubscription() method invocation in subscriptionJooqRepo");
+ return dslContext.select()
+ .from(USER_LINK)
+ .where(USER_LINK.CHAT_ID.eq(chatId).and(USER_LINK.LINK_ID.eq(linkId)))
+ .fetchOneInto(Relation.class);
+ }
+
+ @Override
+ public void addRelation(Relation relation) {
+ log.info("addRelation() method invocation in subscriptionJooqRepo");
+ dslContext.insertInto(USER_LINK, USER_LINK.LINK_ID, USER_LINK.CHAT_ID)
+ .values(relation.getLinkId(), relation.getChatId())
+ .execute();
+ }
+
+ @Override
+ public void remove(Long linkId, Long chatId) {
+ log.info("remove() method invocation in subscriptionJooqRepo");
+ dslContext.deleteFrom(USER_LINK)
+ .where(USER_LINK.LINK_ID.eq(linkId).and(USER_LINK.CHAT_ID.eq(chatId)))
+ .execute();
+ }
+
+ @Override
+ public void removeAllByUser(Long chatId) {
+ log.info("removeAllByUser() method invocation in subscriptionJooqRepo");
+ dslContext.deleteFrom(USER_LINK)
+ .where(USER_LINK.CHAT_ID.eq(chatId))
+ .execute();
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
new file mode 100644
index 0000000..d942314
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
@@ -0,0 +1,59 @@
+package ru.tinkoff.edu.java.scrapper.repository.jooq;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jooq.DSLContext;
+import org.springframework.stereotype.Repository;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
+import java.util.List;
+
+import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.User.*;
+
+@Repository
+@Slf4j
+public class UserJooqRepository implements UserRepository {
+
+ private final DSLContext dslContext;
+
+
+ public UserJooqRepository(DSLContext dslContext) {
+ this.dslContext = dslContext;
+ }
+
+ @Override
+ public List findAll() {
+ log.info("findAll() method invocation in userJooqRepo");
+
+ return dslContext.selectFrom(USER).fetchInto(User.class);
+ }
+
+ @Override
+ public User findByChatId(Long id) {
+ log.info("findByChatId() method invocation in userJooqRepo");
+
+ return dslContext.selectFrom(USER)
+ .where(USER.CHAT_ID.eq(id))
+ .fetchOneInto(User.class);
+ }
+
+ @Override
+ public void add(User user) {
+ log.info("add() method invocation in userJooqRepo");
+
+ dslContext.insertInto(USER)
+ .set(USER.CHAT_ID, user.getChatId())
+ .set(USER.USERNAME, user.getUsername())
+ .set(USER.FIRST_NAME, user.getFirstName())
+ .set(USER.LAST_NAME, user.getLastName())
+ .execute();
+ }
+
+ @Override
+ public void remove(Long chatId) {
+ log.info("remove() method invocation in userJooqRepo");
+
+ dslContext.deleteFrom(USER)
+ .where(USER.CHAT_ID.eq(chatId))
+ .execute();
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
new file mode 100644
index 0000000..2f1dab8
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.scrapper.repository.jpa;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Optional;
+
+public interface JpaLinkRepository extends JpaRepository {
+ Optional findByUrl(String url);
+
+ @Query("select u.chatId from UserEntity u join u.links l where l.id = :id")
+ List findChatIdsByLinkId(@Param("id") Long id);
+
+ List findByCheckedAtLessThanOrderByCheckedAtDesc(Timestamp compareDate);
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
new file mode 100644
index 0000000..cdcb762
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
@@ -0,0 +1,22 @@
+package ru.tinkoff.edu.java.scrapper.repository.jpa;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface JpaUserRepository extends JpaRepository {
+
+ @Query("select link from UserEntity u join u.links link where u.chatId = :chatId")
+ List findAllLinksByChat(@Param("chatId") Long chatId);
+
+
+ @Query("select u from UserEntity u join fetch u.links link where u.chatId = :chatId")
+ Optional findByChatIdWithLinks(@Param("chatId") Long chatId);
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
new file mode 100644
index 0000000..388ebac
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
@@ -0,0 +1,30 @@
+package ru.tinkoff.edu.java.scrapper.rest;
+
+import org.springframework.web.bind.annotation.*;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+import ru.tinkoff.edu.java.scrapper.dto.UserAddDto;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+
+@RestController
+@RequestMapping("/tg-chat")
+public class ChatRestController {
+
+
+ private final TgChatService chatService;
+
+ public ChatRestController(TgChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ @PostMapping(value = "{id}")
+ public void registerChat(@PathVariable Long id, @RequestBody UserAddDto userAddDto) {
+ chatService.register(new User(id, userAddDto.username(), userAddDto.firstName(), userAddDto.lastName()));
+ }
+
+ @DeleteMapping(value = "{id}")
+ public void deleteChat(@PathVariable Long id) {
+ chatService.unregister(id);
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
new file mode 100644
index 0000000..5aef3ac
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
@@ -0,0 +1,44 @@
+package ru.tinkoff.edu.java.scrapper.rest;
+
+import org.springframework.web.bind.annotation.*;
+import ru.tinkoff.edu.java.scrapper.dto.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.dto.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.dto.ListLinkResponse;
+import ru.tinkoff.edu.java.scrapper.dto.RemoveLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkService;
+import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
+import java.net.URI;
+import java.util.List;
+
+@RestController
+@RequestMapping("/links")
+public class LinkRestController {
+
+ private final SubscriptionService subscriptionService;
+
+ public LinkRestController(SubscriptionService subscriptionService) {
+ this.subscriptionService = subscriptionService;
+ }
+
+ @GetMapping
+ public ListLinkResponse getLinks(@RequestHeader("Tg-Chat-Id") Long chatId) {
+ List list = subscriptionService.getLinksByChat(chatId);
+ return new ListLinkResponse(list, list.size());
+ }
+
+ @PostMapping
+ public LinkResponse addLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody AddLinkRequest request) {
+ Link link = subscriptionService.subscribe(chatId, URI.create(request.link()));
+ return new LinkResponse(link.getId(), link.getUrl());
+ }
+
+ @DeleteMapping
+ public LinkResponse deleteLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody RemoveLinkRequest request) {
+ Link link = subscriptionService.unsubscribe(chatId, URI.create(request.link()));
+ if (link == null) throw new LinkNotFoundException("Ссылка с таким url не отслеживается!");
+ return new LinkResponse(link.getId(), link.getUrl());
+ }
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
new file mode 100644
index 0000000..eec99f7
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.scrapper.schedule;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+
+import java.util.List;
+
+@Slf4j
+@Component
+public class LinkUpdateScheduler {
+
+ private final LinkUpdateService linkUpdateService;
+
+
+ public LinkUpdateScheduler(LinkUpdateService linkUpdateService, Parser_Link linkParser) {
+ this.linkUpdateService = linkUpdateService;
+ }
+
+ @Scheduled(fixedDelayString = "#{@schedulerIntervalMs}")
+ public void update() {
+ log.info("update() method invocation in LinkUpdateScheduler");
+ linkUpdateService.updateLinks();
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
new file mode 100644
index 0000000..623f12b
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.scrapper.schedule;
+
+import java.time.Duration;
+
+public record Scheduler(Duration interval) {
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
new file mode 100644
index 0000000..91471de
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.scrapper.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.AmqpTemplate;
+import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
+
+@Slf4j
+//бин регистрируется в конфиге, т.к. его не нужно инициализировать в случае общения по HTTP
+public class ScrapperQueueProducer implements UpdateNotificationService {
+
+ private final AmqpTemplate rabbitTemplate;
+
+ private final ApplicationConfig config;
+
+
+ public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig config) {
+ this.rabbitTemplate = rabbitTemplate;
+ this.config = config;
+ }
+
+ public void updateLink(LinkUpdate update) {
+ rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update);
+ log.info("UpdateMessage " + update + " has been sent");
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
new file mode 100644
index 0000000..61ee96d
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
@@ -0,0 +1,8 @@
+package ru.tinkoff.edu.java.scrapper.service;
+
+import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
+
+public interface UpdateNotificationService {
+
+ void updateLink(LinkUpdate request);
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
new file mode 100644
index 0000000..10646d7
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.service.contract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import java.util.List;
+
+public interface LinkUpdateService {
+
+
+ List getOldLinks();
+
+ void updateLinks();
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
new file mode 100644
index 0000000..b35caad
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.scrapper.service.contract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import java.net.URI;
+import java.util.List;
+
+public interface SubscriptionService {
+
+ Link add(Long chatId, URI url);
+ Link remove(Long chatId, URI url);
+
+ List getAllByUser(Long chatId);
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
new file mode 100644
index 0000000..adf1fde
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.service.contract;
+
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+
+public interface TgChatService {
+
+ void register(User user);
+
+ void unregister(Long chatId);
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
new file mode 100644
index 0000000..983fdb9
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
@@ -0,0 +1,156 @@
+package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
+import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
+import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
+import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
+import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
+import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
+//import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+//import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
+//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
+//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+//import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+
+import java.sql.Timestamp;
+import java.time.ZoneOffset;
+import java.util.List;
+
+@Slf4j
+public class LinkUpdateServiceImpl implements LinkUpdateService {
+
+
+ @Value("${update.delta.time}")
+ private Long timeUpdateDeltaInSeconds;
+
+ private final LinkRepository linkRepository;
+
+ private final SubscriptionRepository subscriptionRepository;
+
+ private final Link_Parser linkParser;
+
+ private final GitHubClient gitHubClient;
+
+ private final StackOverflowClient stackOverflowClient;
+
+ private final BotClient botClient;
+
+
+ public LinkUpdateServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository, Link_Parser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) {
+ this.linkRepository = linkRepository;
+ this.subscriptionRepository = subscriptionRepository;
+ this.linkParser = linkParser;
+ this.gitHubClient = gitHubClient;
+ this.stackOverflowClient = stackOverflowClient;
+ this.botClient = botClient;
+ }
+
+ @Override
+ public List getOldLinks() {
+ return linkRepository.findOldLinks(timeUpdateDeltaInSeconds);
+ }
+
+
+ public void updateLinks() {
+ List oldLinks = getOldLinks();
+
+ for (Link link : oldLinks) {
+ Parser_Link result = linkParser.parseUrl(link.getUrl());
+ if (result instanceof GitHub_Link) {
+ try {
+ boolean isUpdated = false;
+ String updateDescription = "";
+
+
+ GitHubResponse response = gitHubClient.fetchRepo(((GithubParseResult) result).username(), ((GithubParseResult) result).repository());
+
+
+ if (response.forksCount() != link.getGhForksCount()) {
+ isUpdated = true;
+ if (response.forksCount() < link.getGhForksCount()) {
+ updateDescription += "В репозитории уменьшилось кол-во форков\n";
+ }
+ if (response.forksCount() > link.getGhForksCount()) {
+ updateDescription += "В репозитории появились новые форки\n";
+ }
+ link.setGhForksCount(response.forksCount());
+ }
+
+
+ if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) {
+ if (link.getGhDescription() != null) isUpdated = true;
+ link.setGhDescription(response.description());
+ updateDescription += "В репозитории изменилось описание\n";
+ }
+
+ if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) {
+ if (link.getGhPushedAt() != null) isUpdated = true;
+ link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli()));
+ updateDescription += "В репозитории появился новый commit\n";
+ }
+
+
+ linkRepository.updateCheckDate(link);
+
+ if (isUpdated) {
+ Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new);
+ botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chats));
+ }
+
+
+ } catch (GitHubRequestException e) {
+ log.warn(e.getMessage());
+ }
+
+ } else if (result instanceof StackOverflow_Link) {
+ try {
+
+ boolean isUpdated = false;
+ String updateDescription = "";
+
+
+ StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id());
+
+
+ if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) {
+ if (link.getSoLastEditDate() != null) isUpdated = true;
+ link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli()));
+ updateDescription += "Текст вопроса был изменён\n";
+ }
+
+ if (response.answerCount() != link.getSoAnswerCount()) {
+ isUpdated = true;
+ if (response.answerCount() < link.getSoAnswerCount()) {
+ updateDescription += "На вопрос уменьшилось кол-во ответов\n";
+ }
+ if (response.answerCount() > link.getSoAnswerCount()) {
+ updateDescription += "На вопрос появились новые ответы\n";
+ }
+ link.setSoAnswerCount(response.answerCount());
+ }
+
+ linkRepository.updateCheckDate(link);
+
+ if (isUpdated) {
+
+ Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new);
+ botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chats));
+ }
+
+ } catch (StackOverflowRequestException e) {
+ log.warn(e.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
new file mode 100644
index 0000000..4476e8b
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
@@ -0,0 +1,99 @@
+package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
+
+import java.net.URI;
+import java.sql.Timestamp;
+import java.util.List;
+
+
+@Slf4j
+public class SubscriptionServiceImpl implements SubscriptionService {
+
+
+ private final LinkRepository linkRepository;
+
+ private final SubscriptionRepository subscriptionRepository;
+
+
+
+ public SubscriptionServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository) {
+ this.linkRepository = linkRepository;
+ this.subscriptionRepository = subscriptionRepository;
+ }
+
+ @Override
+ @Transactional
+ public Link subscribe(Long chatId, URI url) {
+ log.info("subscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
+ Link link = linkRepository.findByUrl(url.toString());
+ if (link == null) {
+ link = new Link();
+ link.setUrl(url.toString());
+ link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
+ linkRepository.add(link);
+ //обращение ниже нужно, чтобы получить id из БД
+ link = linkRepository.findByUrl(link.getUrl());
+ }
+ Relation relation = subscriptionRepository.findSubscription(link.getId(), chatId);
+
+ if (relation == null) {
+ relation = new Relation();
+ relation.setChatId(chatId);
+ relation.setLinkId(link.getId());
+ subscriptionRepository.addRelation(relation);
+ }
+ return link;
+ }
+
+ @Override
+ @Transactional
+ public Link unsubscribe(Long chatId, URI url) {
+ log.info("unsubscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
+ Link link = linkRepository.findByUrl(url.toString());
+
+ if (link != null) {
+// linkRepository.remove(link.getId());
+ subscriptionRepository.remove(link.getId(), chatId);
+ }
+ return link;
+ }
+
+ @Override
+ public List getLinksByChat(Long chatId) {
+ log.info("getLinksByChat() method invocation in SubscriptionServiceImpl. chatId = "+chatId);
+ return subscriptionRepository.findLinksByChat(chatId);
+ }
+
+ @Override
+ public List getChatIdsByLink(Long linkId) {
+ log.info("getChatIdsByLink() method invocation in SubscriptionServiceImpl. linkId = "+linkId);
+ return null;
+ }
+
+ @Override
+ public Link add(Long chatId, URI url) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Link remove(Long chatId, URI url) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List getAllByUser(Long chatId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
new file mode 100644
index 0000000..84a130a
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
@@ -0,0 +1,42 @@
+package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+
+@Slf4j
+public class TgChatServiceImpl implements TgChatService {
+
+ private final UserRepository userRepository;
+
+ private final SubscriptionRepository subscriptionRepository;
+
+
+ public TgChatServiceImpl(UserRepository userRepository, SubscriptionRepository subscriptionRepository) {
+ this.userRepository = userRepository;
+ this.subscriptionRepository = subscriptionRepository;
+ }
+
+ @Override
+ public void register(User user) {
+ log.info("register() method invocation in TgChatServiceImpl. chatId = "+user.getChatId());
+ User userInBd = userRepository.findByChatId(user.getChatId());
+ if (userInBd != null) throw new ChatAlreadyExistException();
+ userRepository.add(user);
+ }
+
+ @Override
+ @Transactional
+ public void unregister(Long chatId) {
+ log.info("unregister() method invocation in TgChatServiceImpl. chatId = "+chatId);
+ userRepository.remove(chatId);
+ subscriptionRepository.removeAllByUser(chatId);
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
new file mode 100644
index 0000000..f27d081
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
@@ -0,0 +1,174 @@
+package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
+import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
+import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
+import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
+import ru.tinkoff.edu.java.scrapper.client.BotClient;
+import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
+import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
+import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
+import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
+import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
+import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
+import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
+import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
+
+import java.sql.Timestamp;
+import java.time.ZoneOffset;
+import java.util.List;
+
+@Slf4j
+public class JpaLinkUpdateServiceImpl implements LinkUpdateService {
+
+ @Value("${update.delta.time}")
+ private Long timeUpdateDeltaInSeconds;
+
+ private final JpaLinkRepository linkRepository;
+
+
+
+ private final Link_Parser linkParser;
+
+ private final GitHubClient gitHubClient;
+
+ private final StackOverflowClient stackOverflowClient;
+
+ private final BotClient botClient;
+
+
+ public JpaLinkUpdateServiceImpl(JpaLinkRepository linkRepository, LinkParser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) {
+ this.linkRepository = linkRepository;
+ this.linkParser = linkParser;
+ this.gitHubClient = gitHubClient;
+ this.stackOverflowClient = stackOverflowClient;
+ this.botClient = botClient;
+ }
+
+ @Override
+ public List getOldLinks() {
+ log.info("getOldLinks() method invocation in JpaLinkUpdateServiceImpl");
+ Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000);
+ return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate).stream().map(Link::fromEntity).toList();
+ }
+
+
+ public List getOldEntityLinks() {
+ Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000);
+ return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate);
+ }
+
+ @Override
+ @Transactional
+ public void updateLinks() {
+ log.info("updateLinks() method invocation in JpaLinkUpdateServiceImpl");
+ List oldLinks = getOldEntityLinks();
+
+ for (LinkEntity link : oldLinks) {
+ Parser_Link result = linkParser.parseUrl(link.getUrl());
+ if (result instanceof GitHub_Link) {
+ try {
+ boolean isUpdated = false;
+ String updateDescription = "";
+
+
+ System.out.println(link.getUrl());
+ GitHubResponse response = gitHubClient.fetchRepo(((GitHub_Link) result).username(), ((GithubParseResult) result).repository());
+ System.out.println(response);
+
+
+ if (link.getGhForksCount() == null || response.forksCount() != link.getGhForksCount()) {
+ isUpdated = true;
+ if (link.getGhForksCount() == null) {link.setGhForksCount(0); isUpdated = false;}
+ if (isUpdated && response.forksCount() < link.getGhForksCount()) {
+ updateDescription += "В репозитории уменьшилось кол-во форков\n";
+ }
+ if (isUpdated && response.forksCount() > link.getGhForksCount()) {
+ updateDescription += "В репозитории появились новые форки\n";
+ }
+ link.setGhForksCount(response.forksCount());
+ }
+
+
+ if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) {
+ if (link.getGhDescription() != null) isUpdated = true;
+ link.setGhDescription(response.description());
+ updateDescription += "В репозитории изменилось описание\n";
+ }
+
+ if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) {
+ if (link.getGhPushedAt() != null) isUpdated = true;
+ link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli()));
+ updateDescription += "В репозитории появился новый commit\n";
+ }
+
+ link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
+
+ linkRepository.save(link);
+
+ if (isUpdated) {
+ List chatsIds = linkRepository.findChatIdsByLinkId(link.getId());
+ botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chatsIds.toArray(new Long[0])));
+ }
+
+
+ } catch (GitHubRequestException e) {
+ log.warn(e.getMessage());
+ }
+
+ } else if (result instanceof StackOverflow_Link) {
+ try {
+
+ boolean isUpdated = false;
+ String updateDescription = "";
+
+
+ System.out.println(link.getUrl());
+ StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id());
+ System.out.println(response);
+
+
+
+ if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) {
+ if (link.getSoLastEditDate() != null) isUpdated = true;
+ link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli()));
+ updateDescription += "Текст вопроса был изменён\n";
+ }
+
+ if (link.getSoAnswerCount() == null || response.answerCount() != link.getSoAnswerCount()) {
+ isUpdated = true;
+ if (link.getSoAnswerCount() == null) {link.setSoAnswerCount(0); isUpdated = false;}
+ if (isUpdated && response.answerCount() < link.getSoAnswerCount()) {
+ updateDescription += "На вопрос уменьшилось кол-во ответов\n";
+ }
+ if (isUpdated && response.answerCount() > link.getSoAnswerCount()) {
+ updateDescription += "На вопрос появились новые ответы\n";
+ }
+ link.setSoAnswerCount(response.answerCount());
+ }
+
+
+ link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
+
+ linkRepository.save(link);
+
+ if (isUpdated) {
+ List chatsIds = linkRepository.findChatIdsByLinkId(link.getId());
+ botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chatsIds.toArray(new Long[0])));
+ }
+
+ } catch (StackOverflowRequestException e) {
+ log.warn(e.getMessage());
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
new file mode 100644
index 0000000..c5c9749
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
@@ -0,0 +1,100 @@
+package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
+import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
+import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
+import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
+import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
+
+import java.net.URI;
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+public class JpaSubscriptionServiceImpl implements SubscriptionService {
+
+ private final JpaLinkRepository linkRepository;
+
+ private final JpaUserRepository userRepository;
+
+ public JpaSubscriptionServiceImpl(JpaLinkRepository linkRepository, JpaUserRepository userRepository) {
+ this.linkRepository = linkRepository;
+ this.userRepository = userRepository;
+ }
+
+
+ @Override
+ @Transactional
+ public Link subscribe(Long chatId, URI url) {
+ log.info("subscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
+ Optional optionalLink = linkRepository.findByUrl(url.toString());
+ LinkEntity linkToAdd = new LinkEntity();
+ if (optionalLink.isEmpty()) {
+ linkToAdd.setUrl(url.toString());
+ } else {
+ linkToAdd = optionalLink.get();
+ }
+ linkToAdd.setCheckedAt(new Timestamp(System.currentTimeMillis()));
+ linkRepository.save(linkToAdd);
+
+ Optional optionalUser = userRepository.findById(chatId);
+ if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
+ UserEntity user = optionalUser.get();
+ List userLinks = user.getLinks();
+
+ if (!userLinks.contains(linkToAdd)) {
+ userLinks.add(linkToAdd);
+ }
+
+ userRepository.save(user);
+ return Link.fromEntity(linkToAdd);
+ }
+
+ @Override
+ @Transactional
+ public Link unsubscribe(Long chatId, URI url) {
+ log.info("unsubscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
+ Optional optionalUser = userRepository.findByChatIdWithLinks(chatId);
+ Optional optionalLink = linkRepository.findByUrl(url.toString());
+
+
+ if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой пользователь не зарегистрирован");
+
+ UserEntity user = optionalUser.get();
+
+ List userLinks = user.getLinks();
+
+ if (optionalLink.isEmpty() || !userLinks.contains(optionalLink.get()))
+ throw new LinkNotFoundException("Такая ссылка не отслеживается");
+
+ userLinks.remove(optionalLink.get());
+ userRepository.save(user);
+
+ return Link.fromEntity(optionalLink.get());
+ }
+
+ @Override
+ public List getLinksByChat(Long chatId) {
+ log.info("getAllByUser() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId);
+ Optional optionalUser = userRepository.findById(chatId);
+ if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
+ return userRepository.findAllLinksByChat(chatId).stream().map(Link::fromEntity).toList();
+ }
+
+
+ @Override
+ public List getChatIdsByLink(Long linkId) {
+ log.info("getChatIdsByLink() method invocation in JpaSubscriptionServiceImpl. linkId = "+linkId);
+ Optional optionalLink = linkRepository.findById(linkId);
+ if (optionalLink.isEmpty()) throw new LinkNotFoundException("Такая ссылка не отслеживается");
+ return linkRepository.findChatIdsByLinkId(linkId);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
new file mode 100644
index 0000000..b87e274
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
@@ -0,0 +1,43 @@
+package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
+import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
+import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
+import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
+import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
+import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
+
+import java.util.Optional;
+
+
+@Slf4j
+public class JpaTgChatServiceImpl implements TgChatService {
+
+ private final JpaUserRepository userRepository;
+
+ public JpaTgChatServiceImpl(JpaUserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @Override
+ public void register(User user) {
+ log.info("register() method invocation in JpaTgChatServiceImpl. User chatId = "+user.getChatId());
+ Optional optionalUser = userRepository.findById(user.getChatId());
+ if (optionalUser.isPresent()) throw new ChatAlreadyExistException("Такой чат уже зарегистрирован!");
+ userRepository.save(User.toEntity(user));
+ }
+
+ @Override
+ public void unregister(Long chatId) {
+ log.info("unregister() method invocation in JpaTgChatServiceImpl. User chatId = "+chatId);
+ Optional optionalUser = userRepository.findById(chatId);
+ if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
+ userRepository.delete(optionalUser.get());
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties
new file mode 100644
index 0000000..3761f00
--- /dev/null
+++ b/FP/scrapper/src/main/resources/application.properties
@@ -0,0 +1,23 @@
+server.port=8080
+app.test=beamer-scrapper
+gh.baseurl=https://api.github.com
+so.baseurl=https://api.stackexchange.com/2.3/
+bot.baseurl=http://localhost:8081
+app.scheduler.interval=61000
+update.delta.time=20
+springdoc.swagger-ui.path=/swagger-ui
+
+spring.datasource.driver-class-name=org.postgresql.Driver
+spring.datasource.url=jdbc:postgresql://localhost:5432/scrapper
+spring.datasource.username=romanova
+spring.datasource.password=12345654321
+spring.jpa.properties.hibernate.show_sql=true
+
+spring.rabbitmq.host=localhost
+spring.rabbitmq.port=5672
+spring.rabbitmq.username=romanova
+spring.rabbitmq.password=12345654321
+app.queue-name=scrapper-bot-queue
+app.exchange-name=scrapper-bot-exchange
+app.routing-key=scrapper-bot-key
+app.use-queue=true
diff --git a/FP/scrapper/src/main/resources/logback-test.xml b/FP/scrapper/src/main/resources/logback-test.xml
new file mode 100644
index 0000000..900637e
--- /dev/null
+++ b/FP/scrapper/src/main/resources/logback-test.xml
@@ -0,0 +1,17 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+.
diff --git a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
new file mode 100644
index 0000000..1c2378c
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
@@ -0,0 +1,38 @@
+package scrapper;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.sql.*;
+
+public class DatabaseTest extends IntegrationEnvironment{
+
+
+ @Test
+ @DisplayName("Тест для проверки запуска контейнера с PostgreSQL")
+ public void testIfContainerIsRunning() {
+ Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL");
+ }
+
+ @Test
+ @DisplayName("Тест для проверки успешного применения миграций")
+ void testMigrations() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getPassword());
+ Statement statement = conn.createStatement()) {
+
+ ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\"");
+ Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана");
+ ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\"");
+ Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана");
+ ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\"");
+ Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана");
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
new file mode 100644
index 0000000..2f0bdfa
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
@@ -0,0 +1,54 @@
+package scrapper;
+
+import liquibase.Contexts;
+import liquibase.LabelExpression;
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.DatabaseFactory;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.LiquibaseException;
+import liquibase.resource.DirectoryResourceAccessor;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+abstract class IntegrationEnvironment {
+
+ static final String IMAGE_VERSION = "postgres:15";
+
+ static final PostgreSQLContainer POSTGRES_CONTAINER;
+
+ static {
+ POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION)
+ .withDatabaseName("scrapper")
+ .withUsername("lwbeamer")
+ .withPassword("2281337");
+
+
+ POSTGRES_CONTAINER.start();
+ executeMigrations();
+ }
+
+ private static void executeMigrations() {
+ try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) {
+ Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn));
+ Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations");
+ Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database);
+ liquibase.update(new Contexts(), new LabelExpression());
+ } catch (SQLException | LiquibaseException e) {
+ throw new RuntimeException("Failed to execute migrations", e);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Changelog file not found",e);
+ }
+ }
+
+ public static void stopContainer() {
+ POSTGRES_CONTAINER.stop();
+ }
diff --git a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
new file mode 100644
index 0000000..d0ac18a
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
@@ -0,0 +1,38 @@
+package scrapper.environment;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.sql.*;
+
+public class DatabaseTest extends IntegrationEnvironment{
+
+
+ @Test
+ @DisplayName("Тест для проверки запуска контейнера с PostgreSQL")
+ public void testIfContainerIsRunning() {
+ Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL");
+ }
+
+ @Test
+ @DisplayName("Тест для проверки успешного применения миграций")
+ void testMigrations() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getPassword());
+ Statement statement = conn.createStatement()) {
+
+ ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\"");
+ Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана");
+ ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\"");
+ Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана");
+ ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\"");
+ Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана");
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
new file mode 100644
index 0000000..416b086
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
@@ -0,0 +1,81 @@
+package scrapper.environment;
+
+import liquibase.Contexts;
+import liquibase.LabelExpression;
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.DatabaseFactory;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.LiquibaseException;
+import liquibase.resource.DirectoryResourceAccessor;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
+import org.testcontainers.containers.PostgreSQLContainer;
+
+import javax.sql.DataSource;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+@ContextConfiguration(classes = IntegrationEnvironment.EnvironmentConfiguration.class)
+public abstract class IntegrationEnvironment {
+
+
+ @Configuration
+ static class EnvironmentConfiguration{
+ @Bean
+ public DataSource dataSource() {
+ return DataSourceBuilder.create()
+ .url(POSTGRES_CONTAINER.getJdbcUrl())
+ .username(POSTGRES_CONTAINER.getUsername())
+ .password(POSTGRES_CONTAINER.getPassword())
+ .build();
+ }
+
+ @Bean
+ public JdbcTemplate jdbcTemplate(DataSource dataSource){
+ return new JdbcTemplate(dataSource);
+ }
+
+ }
+
+ static final String IMAGE_VERSION = "postgres:15";
+
+ static final PostgreSQLContainer POSTGRES_CONTAINER;
+
+ static {
+ POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION)
+ .withDatabaseName("scrapper")
+ .withUsername("lwbeamer")
+ .withPassword("2281337");
+
+
+ POSTGRES_CONTAINER.start();
+ executeMigrations();
+ }
+
+ private static void executeMigrations() {
+ try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
+ IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) {
+ Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn));
+ Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations");
+ Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database);
+ liquibase.update(new Contexts(), new LabelExpression());
+ } catch (SQLException | LiquibaseException e) {
+ throw new RuntimeException("Failed to execute migrations", e);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Changelog file not found",e);
+ }
+ }
+
+ public static void stopContainer() {
+ POSTGRES_CONTAINER.stop();
+ }
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
new file mode 100644
index 0000000..a4ff395
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
@@ -0,0 +1,8 @@
+package scrapper.environment;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
+
+@EnableAutoConfiguration(exclude = { LiquibaseAutoConfiguration.class })
+public class TestConfiguration {
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
new file mode 100644
index 0000000..436f01a
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
@@ -0,0 +1,151 @@
+package scrapper.jdbc;
+
+import scrapper.environment.IntegrationEnvironment;
+import scrapper.environment.TestConfiguration;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
+import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import ru.tinkoff.edu.java.scrapper.repository.*;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
+public class JdbcLinkTest extends IntegrationEnvironment {
+
+ @Autowired
+ private LinkJdbcTemplateRepository linkRepository;
+
+ @Autowired
+ private LinkRowMapper linkRowMapper;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void addLinkTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
+
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ linkRepository.add(linkToAdd);
+
+ List addedLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertNotNull(addedLink.get(0));
+ Assertions.assertEquals("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file", addedLink.get(0).getUrl());
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void removeLinkTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
+
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
+
+ linkRepository.remove(afterInsertionLink.get(0).getId());
+
+ List afterRemovingLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
+
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 1);
+ Assertions.assertEquals(afterRemovingLink.size(), 0);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findAllTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ for (int i = 0; i < 10; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = linkRepository.findAll();
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 10);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findByUrlTest(){
+ List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ for (int i = 0; i < 10; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+ Link foundedByUrlLink = linkRepository.findByUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file0");
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 10);
+ Assertions.assertNotNull(foundedByUrlLink);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void updateDateTest(){
+ List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+ Timestamp timestampBefore = new Timestamp(System.currentTimeMillis());
+ linkToAdd.setUpdatedAt(timestampBefore);
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+
+
+ List linkBeforeUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+
+ Assertions.assertEquals(linkBeforeUpdate.get(0).getUpdatedAt(),timestampBefore);
+
+ linkBeforeUpdate.get(0).setUpdatedAt(new Timestamp(100000));
+
+ linkRepository.updateDate(linkBeforeUpdate.get(0));
+
+ List linkAfterUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(linkAfterUpdate.get(0).getUpdatedAt(),new Timestamp(100000));
+ }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
new file mode 100644
index 0000000..0813c59
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
@@ -0,0 +1,251 @@
+package scrapper.jdbc;
+
+import scrapper.environment.IntegrationEnvironment;
+import scrapper.environment.TestConfiguration;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
+import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
+import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.Link;
+import ru.tinkoff.edu.java.scrapper.model.Relation;
+import ru.tinkoff.edu.java.scrapper.model.User;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
+public class JdbcSubscriptionTest extends IntegrationEnvironment {
+
+ @Autowired
+ private SubscriptionJdbcTemplateRepository subscriptionRepository;
+
+ @Autowired
+ private LinkRowMapper linkRowMapper;
+
+ @Autowired
+ private SubscriptionRowMapper subscriptionRowMapper;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findLinksByChatTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith");
+
+ //всего добавим 20 ссылок
+ for (int i = 0; i < 20; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ //из 20-ти ссылок подпишемся лишь на 10
+ for (int i = 0; i < 10; i++) {
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
+ }
+
+ //на оставшиеся 10 подпишем другого пользователя
+ for (int i = 10; i < 20; i++) {
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L);
+ }
+
+ List userLinks = subscriptionRepository.findLinksByChat(42L);
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 20);
+ Assertions.assertEquals(userLinks.size(), 10);
+ }
+
+ @Test
+ @Transactional
+ @Rollback
+ public void removeRelationTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
+
+ for (int i = 0; i < 20; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ for (int i = 0; i < 10; i++) {
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
+ }
+
+ List userLinksBeforeRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ subscriptionRepository.remove(afterInsertionLink.get(0).getId(), 42L);
+ subscriptionRepository.remove(afterInsertionLink.get(4).getId(), 42L);
+ subscriptionRepository.remove(afterInsertionLink.get(6).getId(), 42L);
+
+ List userLinksAfterRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 20);
+ Assertions.assertEquals(userLinksBeforeRemove.size(), 10);
+ Assertions.assertEquals(userLinksAfterRemove.size(), 7);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void addRelationTest() {
+ List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
+
+ for (int i = 0; i < 20; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ for (int i = 0; i < 10; i++) {
+ Relation relation = new Relation();
+ relation.setLinkId(afterInsertionLink.get(i).getId());
+ relation.setChatId(42L);
+ subscriptionRepository.addRelation(relation);
+ }
+
+
+ List userLinks = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ Assertions.assertEquals(beforeAddLink.size(), 0);
+ Assertions.assertEquals(afterInsertionLink.size(), 20);
+ Assertions.assertEquals(userLinks.size(), 10);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findChatsByLinkTest() {
+ List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
+
+
+ for (int i = 0; i < 10; i++) {
+ User user = new User(42L + i, "robtop21" + i, "Robert", "Polson");
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
+ user.getChatId(),
+ user.getUsername(),
+ user.getFirstName(),
+ user.getLastName());
+ }
+
+
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+
+ for (int i = 0; i < 7; i++) {
+ Relation relation = new Relation();
+ relation.setLinkId(afterInsertionLink.get(0).getId());
+ relation.setChatId(42L + i);
+ subscriptionRepository.addRelation(relation);
+ }
+
+ List afterSubscribe = subscriptionRepository.findChatsByLink(afterInsertionLink.get(0).getId());
+
+ Assertions.assertEquals(beforeAddRelation.size(), 0);
+ Assertions.assertEquals(afterSubscribe.size(), 7);
+ }
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findSubscriptionTest() {
+ List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
+
+
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(0).getId(), 42L);
+
+ Relation relation = subscriptionRepository.findSubscription(afterInsertionLink.get(0).getId(), 42L);
+
+
+ Assertions.assertEquals(beforeAddRelation.size(),0);
+ Assertions.assertEquals(afterInsertionLink.size(),1);
+ Assertions.assertNotNull(relation);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void removeAllByUserTest(){
+ List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
+
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith");
+
+ //всего добавим 20 ссылок
+ for (int i = 0; i < 20; i++) {
+ Link linkToAdd = new Link();
+ linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
+ linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
+ jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
+ }
+
+ List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
+
+ //из 20-ти ссылок подпишемся лишь на 10
+ for (int i = 0; i < 10; i++) {
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
+ }
+
+ //на оставшиеся 10 подпишем другого пользователя
+ for (int i = 10; i < 20; i++) {
+ jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L);
+ }
+
+ List userLinksBeforeDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ subscriptionRepository.removeAllByUser(42L);
+
+ List userLinksAfterDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
+
+ Assertions.assertEquals(beforeAddRelation.size(),0);
+ Assertions.assertEquals(afterInsertionLink.size(), 20);
+ Assertions.assertEquals(userLinksBeforeDelete.size(), 10);
+ Assertions.assertEquals(userLinksAfterDelete.size(), 0);
+ }
+
+}
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
new file mode 100644
index 0000000..df7d245
--- /dev/null
+++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
@@ -0,0 +1,135 @@
+package scrapper.jdbc;
+
+import scrapper.environment.IntegrationEnvironment;
+import scrapper.environment.TestConfiguration;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.transaction.annotation.Transactional;
+import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
+import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
+import ru.tinkoff.edu.java.scrapper.model.User;
+import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository;
+
+import java.util.List;
+
+@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
+public class JdbcUserTest extends IntegrationEnvironment {
+
+ @Autowired
+ private UserJdbcTemplateRepository userRepository;
+
+ @Autowired
+ private UserRowMapper userRowMapper;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void addUserTest() {
+ List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+ User user = new User(42L, "robtop21", "Robert","Polson");
+
+
+ userRepository.add(user);
+
+ List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+ Assertions.assertEquals(beforeAddUser.size(), 0);
+ Assertions.assertEquals(afterAddUser.size(), 1);
+ Assertions.assertNotNull(afterAddUser.get(0));
+ Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void removeUserTest() {
+ List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+ User user = new User(42L, "robtop21", "Robert","Polson");
+
+
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
+ user.getChatId(),
+ user.getUsername(),
+ user.getFirstName(),
+ user.getLastName());
+
+
+ List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+ userRepository.remove(42L);
+
+ List afterRemoveUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+
+ Assertions.assertEquals(beforeAddUser.size(), 0);
+ Assertions.assertEquals(afterAddUser.size(), 1);
+ Assertions.assertNotNull(afterAddUser.get(0));
+ Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L);
+ Assertions.assertEquals(afterRemoveUser.size(), 0);
+ }
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findAllTest() {
+ List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+
+ for (int i = 0; i < 10; i++) {
+ User user = new User(42L + i, "robtop21" + i, "Robert","Polson");
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
+ user.getChatId(),
+ user.getUsername(),
+ user.getFirstName(),
+ user.getLastName());
+ }
+
+ List afterInsertionUser = userRepository.findAll();
+
+ Assertions.assertEquals(beforeAddUser.size(), 0);
+ Assertions.assertEquals(afterInsertionUser.size(), 10);
+ }
+
+
+ @Test
+ @Transactional
+ @Rollback
+ public void findByChatIdTest(){
+ List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+
+ for (int i = 0; i < 10; i++) {
+ User user = new User(42L + i, "robtop21" + i, "Robert","Polson");
+
+ jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
+ user.getChatId(),
+ user.getUsername(),
+ user.getFirstName(),
+ user.getLastName());
+ }
+
+ List afterInsertionUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
+
+ User foundedByIdUser = userRepository.findByChatId(42L);
+
+ Assertions.assertEquals(beforeAddUser.size(), 0);
+ Assertions.assertEquals(afterInsertionUser.size(), 10);
+ Assertions.assertNotNull(foundedByIdUser);
+
+ }
+
+
+}
\ No newline at end of file
From 616dc051d07b08fa47ae1f7fcd1a679557ad97d6 Mon Sep 17 00:00:00 2001
From: Ray <113240139+Ray-Not@users.noreply.github.com>
Date: Mon, 15 May 2023 12:26:38 +0300
Subject: [PATCH 3/9] Rew
---
FP/.project | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/FP/.project b/FP/.project
index 89d138f..7b5c63d 100644
--- a/FP/.project
+++ b/FP/.project
@@ -1,6 +1,6 @@
- project
+ FP
From 686e734b1e204252d352ba8ad1ab4e022a7366bc Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 03:02:02 +0500
Subject: [PATCH 4/9] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81?=
=?UTF-8?q?=20=D1=81=20hw5=20=D1=80=D0=B5=D0=BF=D1=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 7 +-
FP/.project | 18 --
FP/bot/.classpath | 34 ---
FP/bot/.dbeaver/.credentials-config.json.bak | Bin 112 -> 0 bytes
FP/bot/.dbeaver/.data-sources.json.bak | 4 -
FP/bot/.dbeaver/.project-metadata.json.bak | 1 -
FP/bot/.dbeaver/data-sources.json | 6 -
FP/bot/.dbeaver/project-metadata.json | 1 -
FP/bot/.dbeaver/project-settings.json | 1 -
FP/bot/.gitignore | 1 -
FP/bot/.project | 24 --
.../org.eclipse.core.resources.prefs | 6 -
FP/bot/.settings/org.eclipse.jdt.core.prefs | 9 -
FP/bot/.settings/org.eclipse.m2e.core.prefs | 4 -
FP/bot/pom.xml | 109 ++++----
.../tinkoff/edu/java/bot/BotApplication.java | 17 +-
.../java/bot/advice/AppExceptionHandler.java | 23 --
.../edu/java/bot/api/BotController.java | 14 +
.../exceptionHandler/BotExceptionHandler.java | 36 +++
.../java/bot/api/model/ApiErrorResponse.java | 11 +
.../edu/java/bot/api/model/LinkUpdate.java | 6 +
.../edu/java/bot/client/ScrapperClient.java | 97 -------
.../bot/client/ScrapperClientException.java | 11 -
.../edu/java/bot/commands/Command.java | 20 --
.../edu/java/bot/commands/CommandsEnum.java | 33 ---
.../edu/java/bot/commands/HelpCommand.java | 23 --
.../edu/java/bot/commands/ListCommand.java | 48 ----
.../edu/java/bot/commands/StartCommand.java | 55 ----
.../edu/java/bot/commands/TrackCommand.java | 47 ----
.../edu/java/bot/commands/UntrackCommand.java | 49 ----
.../bot/configuration/ApplicationConfig.java | 14 +-
.../bot/configuration/BotConfiguration.java | 66 -----
.../configuration/ClientConfiguration.java | 27 --
.../LinkParserConfiguration.java | 14 -
.../configuration/RabbitMQConfiguration.java | 8 +-
.../bot/configuration/configRecords/Bot.java | 4 +
.../configRecords/Scheduler.java | 5 +
.../edu/java/bot/dto/AddLinkRequest.java | 6 -
.../edu/java/bot/dto/ApiErrorResponse.java | 7 -
.../tinkoff/edu/java/bot/dto/BotCommand.java | 8 -
.../ru/tinkoff/edu/java/bot/dto/Link.java | 10 -
.../edu/java/bot/dto/LinkResponse.java | 11 -
.../tinkoff/edu/java/bot/dto/LinkUpdate.java | 5 -
.../edu/java/bot/dto/ListLinkResponse.java | 6 -
.../edu/java/bot/dto/RemoveLinkRequest.java | 5 -
.../edu/java/bot/dto/SetCommandRequest.java | 7 -
.../tinkoff/edu/java/bot/dto/UserAddDto.java | 8 -
.../bot/exceptions/ChatNotFoundException.java | 10 -
.../LinkIsNotRegisteredToChatException.java | 10 -
.../edu/java/bot/firstBot/BotMain.java | 36 +++
.../ru/tinkoff/edu/java/bot/firstBot/DB.java | 42 +++
.../edu/java/bot/firstBot/MessageHandler.java | 30 +++
.../edu/java/bot/firstBot/Updater.java | 39 +++
.../edu/java/bot/firstBot/commands/All.java | 7 +
.../edu/java/bot/firstBot/commands/Help.java | 11 +
.../edu/java/bot/firstBot/commands/List.java | 10 +
.../edu/java/bot/firstBot/commands/Start.java | 9 +
.../edu/java/bot/firstBot/commands/Track.java | 13 +
.../java/bot/firstBot/commands/Untrack.java | 14 +
.../edu/java/bot/rest/BotRestController.java | 30 ---
.../bot/schedule/LinkUpdaterScheduler.java | 17 ++
.../edu/java/bot/service/UpdateService.java | 8 -
.../java/bot/service/UpdateServiceImpl.java | 26 --
.../ru/tinkoff/edu/java/bot/telegram/Bot.java | 53 ----
.../bot/telegram/UserMessageProcessor.java | 67 -----
.../edu/java/bot/telegram/UserState.java | 5 -
.../src/main/resources/application.properties | 17 +-
FP/bot/src/main/resources/botapi.yml | 59 ++++
FP/bot/src/test/java/BotTest.java | 24 ++
FP/bot/src/test/java/bot/BotTest.java | 123 ---------
FP/docker-compose.yml | 68 +++--
FP/link-parser/.classpath | 41 ---
FP/link-parser/.gitignore | 1 -
FP/link-parser/.project | 23 --
.../org.eclipse.core.resources.prefs | 6 -
.../.settings/org.eclipse.jdt.core.prefs | 9 -
.../.settings/org.eclipse.m2e.core.prefs | 4 -
FP/link-parser/pom.xml | 46 ++--
.../java/link_parser/link/GitHub_Link.java | 5 -
.../java/link_parser/link/Parser_Link.java | 5 -
.../link_parser/link/StackOverflow_Link.java | 5 -
.../edu/java/link_parser/parser/Abstract.java | 27 --
.../edu/java/link_parser/parser/Github.java | 31 ---
.../java/link_parser/parser/Link_Parser.java | 16 --
.../link_parser/parser/StackOverflow.java | 34 ---
.../edu/java/linkparser/LinkParser.java | 18 ++
.../linkparser/absracts/AbstractParser.java | 20 ++
.../java/linkparser/absracts/GitParser.java | 20 ++
.../java/linkparser/absracts/OtherParser.java | 9 +
.../java/linkparser/absracts/StackParser.java | 19 ++
.../src/test/java/LinkParserTest.java | 103 +------
FP/migrations/01-schema-1.sql | 11 -
FP/migrations/02-schema-2.sql | 15 --
FP/migrations/03-schema-3.sql | 10 -
FP/migrations/create.sql | 18 --
FP/migrations/delete.sql | 3 -
FP/migrations/insert.sql | 37 ---
FP/migrations/master.xml | 13 -
FP/pom.xml | 151 +++++------
FP/scrapper-jooq/.classpath | 28 --
FP/scrapper-jooq/.gitignore | 1 -
FP/scrapper-jooq/.project | 23 --
.../org.eclipse.core.resources.prefs | 4 -
.../.settings/org.eclipse.jdt.core.prefs | 9 -
.../.settings/org.eclipse.m2e.core.prefs | 4 -
FP/scrapper-jooq/pom.xml | 40 ---
.../src/main/java/JooqCodegen.java | 49 ----
FP/scrapper/.classpath | 41 ---
FP/scrapper/.gitignore | 1 -
FP/scrapper/.project | 23 --
.../org.eclipse.core.resources.prefs | 6 -
.../.settings/org.eclipse.jdt.core.prefs | 9 -
.../.settings/org.eclipse.m2e.core.prefs | 4 -
FP/scrapper/pom.xml | 92 +++----
.../java/scrapper/ScrapperApplication.java | 19 +-
.../scrapper/advice/AppExceptionHandler.java | 33 ---
.../scrapper/api/ScrapperControllerLinks.java | 44 +++
.../scrapper/api/ScrapperControllerTg.java | 29 ++
.../scrapper/api/model/AddLinkRequest.java | 3 +
.../java/scrapper/api/model/ChatResponse.java | 3 +
.../scrapper/api/model/LinkChatResponse.java | 3 +
.../java/scrapper/api/model/LinkResponse.java | 3 +
.../scrapper/api/model/ListLinksResponse.java | 6 +
.../scrapper/api/model/RemoveLinkRequest.java | 3 +
.../scrapper/api/model/UpdateService.java | 4 +
.../edu/java/scrapper/client/BotClient.java | 38 ---
.../scrapper/client/ClientConfiguration.java | 57 ++++
.../java/scrapper/client/GitHubClient.java | 47 ----
.../java/scrapper/client/GitHubRecord.java | 19 ++
.../scrapper/client/StackOverflowClient.java | 44 ---
.../scrapper/client/StackOverflowRecord.java | 10 +
.../java/scrapper/client/WeatherRecord.java | 11 +
.../configuration/ApplicationConfig.java | 23 +-
.../configuration/ClientConfiguration.java | 44 ---
.../configuration/HTTPConfiguration.java | 28 --
.../LinkParserConfiguration.java | 14 -
.../configuration/RabbitMQConfiguration.java | 17 +-
.../acess/JdbcAccessConfiguration.java | 99 -------
.../acess/JooqAccessConfiguration.java | 84 ------
.../acess/JpaAccessConfiguration.java | 61 -----
.../edu/java/scrapper/dto/AddLinkRequest.java | 5 -
.../java/scrapper/dto/ApiErrorResponse.java | 6 -
.../edu/java/scrapper/dto/GitHubResponse.java | 25 --
.../edu/java/scrapper/dto/LinkResponse.java | 5 -
.../edu/java/scrapper/dto/LinkUpdate.java | 5 -
.../java/scrapper/dto/ListLinkResponse.java | 8 -
.../java/scrapper/dto/RemoveLinkRequest.java | 5 -
.../java/scrapper/dto/StackOverflowItem.java | 8 -
.../scrapper/dto/StackOverflowResponse.java | 8 -
.../edu/java/scrapper/dto/UserAddDto.java | 8 -
.../BadResponseFromApiException.java | 12 -
.../exception/BotClientException.java | 11 -
.../exception/ChatAlreadyExistException.java | 11 -
.../exception/ChatNotFoundException.java | 12 -
.../exception/GitHubRequestException.java | 11 -
.../LinkIsAlreadyAddedException.java | 12 -
.../exception/LinkNotFoundException.java | 12 -
.../StackOverflowRequestException.java | 12 -
.../exceptions/ScrapperExceptionHandler.java | 78 ++++++
.../EntryExsistException.java | 12 +
.../EntryNotExsistException.java | 12 +
.../customExceptions/NullDBException.java | 12 +
.../customExceptions/NullLinkException.java | 12 +
.../UnauthorizationException.java | 12 +
.../exceptions/model/ApiErrorResponse.java | 7 +
.../java/scrapper/jdbc/JdbcChatService.java | 26 ++
.../java/scrapper/jdbc/JdbcLinkService.java | 75 ++++++
.../java/scrapper/jdbc/config/jdbcBean.java | 25 ++
.../scrapper/jdbc/mappers/ChatMapper.java | 14 +
.../scrapper/jdbc/mappers/LinkChatMapper.java | 14 +
.../scrapper/jdbc/mappers/LinkMapper.java | 15 ++
.../jdbc/operations/ChatOperations.java | 50 ++++
.../jdbc/operations/LinkChatOperations.java | 61 +++++
.../jdbc/operations/LinkOperations.java | 83 ++++++
.../java/scrapper/mapper/LinkRowMapper.java | 27 --
.../mapper/SubscriptionRowMapper.java | 20 --
.../java/scrapper/mapper/UserRowMapper.java | 24 --
.../java/scrapper/model/commonDto/Link.java | 31 ---
.../java/scrapper/model/commonDto/User.java | 32 ---
.../scrapper/model/jdbcAndJooq/Relation.java | 11 -
.../java/scrapper/model/jpa/LinkEntity.java | 40 ---
.../java/scrapper/model/jpa/UserEntity.java | 30 ---
.../rabbitmq}/ScrapperQueueListener.java | 4 +-
.../ScrapperQueueProducer.java | 19 +-
.../jdbc/LinkJdbcTemplateRepository.java | 86 ------
.../SubscriptionJdbcTemplateRepository.java | 75 ------
.../jdbc/UserJdbcTemplateRepository.java | 59 ----
.../jdbcAndJooqContract/LinkRepository.java | 21 --
.../SubscriptionRepository.java | 19 --
.../jdbcAndJooqContract/UserRepository.java | 13 -
.../repository/jooq/LinkJooqRepository.java | 98 -------
.../jooq/SubscriptionJooqRepository.java | 80 ------
.../repository/jooq/UserJooqRepository.java | 59 ----
.../repository/jpa/JpaLinkRepository.java | 20 --
.../repository/jpa/JpaUserRepository.java | 22 --
.../scrapper/rest/ChatRestController.java | 30 ---
.../scrapper/rest/LinkRestController.java | 44 ---
.../schedule/LinkUpdateScheduler.java | 26 --
.../schedule/LinkUpdaterScheduler.java | 63 +++++
.../edu/java/scrapper/schedule/Scheduler.java | 3 +-
.../service/UpdateNotificationService.java | 8 -
.../service/contract/LinkUpdateService.java | 12 -
.../service/contract/SubscriptionService.java | 14 -
.../service/contract/TgChatService.java | 11 -
.../impl/LinkUpdateServiceImpl.java | 156 -----------
.../impl/SubscriptionServiceImpl.java | 99 -------
.../jdbcAndJooq/impl/TgChatServiceImpl.java | 42 ---
.../jpa/impl/JpaLinkUpdateServiceImpl.java | 174 ------------
.../jpa/impl/JpaSubscriptionServiceImpl.java | 100 -------
.../jpa/impl/JpaTgChatServiceImpl.java | 43 ---
.../src/main/resources/application.properties | 26 +-
.../src/main/resources/logback-test.xml | 17 --
.../src/main/resources/scrapperapi.yml | 184 +++++++++++++
FP/scrapper/src/test/java/BaseTest.java | 11 +
.../src/test/java/IntegrationEnvironment.java | 45 ++++
FP/scrapper/src/test/java/JdbcAddTest.java | 9 +
.../src/test/java/scrapper/DatabaseTest.java | 38 ---
.../java/scrapper/IntegrationEnvironment.java | 54 ----
.../scrapper/environment/DatabaseTest.java | 38 ---
.../environment/IntegrationEnvironment.java | 81 ------
.../environment/TestConfiguration.java | 8 -
.../test/java/scrapper/jdbc/JdbcLinkTest.java | 151 -----------
.../scrapper/jdbc/JdbcSubscriptionTest.java | 251 ------------------
.../test/java/scrapper/jdbc/JdbcUserTest.java | 135 ----------
README.md | 1 -
225 files changed, 1790 insertions(+), 4992 deletions(-)
delete mode 100644 FP/.project
delete mode 100644 FP/bot/.classpath
delete mode 100644 FP/bot/.dbeaver/.credentials-config.json.bak
delete mode 100644 FP/bot/.dbeaver/.data-sources.json.bak
delete mode 100644 FP/bot/.dbeaver/.project-metadata.json.bak
delete mode 100644 FP/bot/.dbeaver/data-sources.json
delete mode 100644 FP/bot/.dbeaver/project-metadata.json
delete mode 100644 FP/bot/.dbeaver/project-settings.json
delete mode 100644 FP/bot/.gitignore
delete mode 100644 FP/bot/.project
delete mode 100644 FP/bot/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/bot/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/bot/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
create mode 100644 FP/bot/src/main/resources/botapi.yml
create mode 100644 FP/bot/src/test/java/BotTest.java
delete mode 100644 FP/bot/src/test/java/bot/BotTest.java
delete mode 100644 FP/link-parser/.classpath
delete mode 100644 FP/link-parser/.gitignore
delete mode 100644 FP/link-parser/.project
delete mode 100644 FP/link-parser/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/link-parser/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/link-parser/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java
create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java
delete mode 100644 FP/migrations/01-schema-1.sql
delete mode 100644 FP/migrations/02-schema-2.sql
delete mode 100644 FP/migrations/03-schema-3.sql
delete mode 100644 FP/migrations/create.sql
delete mode 100644 FP/migrations/delete.sql
delete mode 100644 FP/migrations/insert.sql
delete mode 100644 FP/migrations/master.xml
delete mode 100644 FP/scrapper-jooq/.classpath
delete mode 100644 FP/scrapper-jooq/.gitignore
delete mode 100644 FP/scrapper-jooq/.project
delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/scrapper-jooq/pom.xml
delete mode 100644 FP/scrapper-jooq/src/main/java/JooqCodegen.java
delete mode 100644 FP/scrapper/.classpath
delete mode 100644 FP/scrapper/.gitignore
delete mode 100644 FP/scrapper/.project
delete mode 100644 FP/scrapper/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/scrapper/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/scrapper/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
rename FP/{bot/src/main/java/ru/tinkoff/edu/java/bot/service => scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq}/ScrapperQueueListener.java (95%)
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{service => rabbitmq}/ScrapperQueueProducer.java (50%)
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
delete mode 100644 FP/scrapper/src/main/resources/logback-test.xml
create mode 100644 FP/scrapper/src/main/resources/scrapperapi.yml
create mode 100644 FP/scrapper/src/test/java/BaseTest.java
create mode 100644 FP/scrapper/src/test/java/IntegrationEnvironment.java
create mode 100644 FP/scrapper/src/test/java/JdbcAddTest.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/DatabaseTest.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
diff --git a/.gitignore b/.gitignore
index 862eb15..d457c3c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Compiled class file
*.class
+
# Log file
*.log
@@ -23,4 +24,8 @@
hs_err_pid*
# idea
-.idea
\ No newline at end of file
+FP/.idea/
+
+# volumes
+FP/migrations/
+FP/rabbitmq/
\ No newline at end of file
diff --git a/FP/.project b/FP/.project
deleted file mode 100644
index 7b5c63d..0000000
--- a/FP/.project
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
- FP
-
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.m2e.core.maven2Nature
- org.jkiss.dbeaver.DBeaverNature
-
-
diff --git a/FP/bot/.classpath b/FP/bot/.classpath
deleted file mode 100644
index 0b9fa8d..0000000
--- a/FP/bot/.classpath
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/bot/.dbeaver/.credentials-config.json.bak
deleted file mode 100644
index 8320c631e208c3ad7467cf2d9db83d85e90f14f8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 112
zcmV-$0FVC>%bw`qlvu4i=Wrho)ja=8tm(6RtT%VUiv(RbXd+9@8O^=>KI816Agz
S3>36s#U(-2xgbD9^um4;
-
- bot
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
- org.jkiss.dbeaver.DBeaverNature
-
-
diff --git a/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/bot/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/bot/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,6 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/java=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/=UTF-8
diff --git a/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/bot/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/bot/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/bot/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/bot/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 11dc02c..60f49bd 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -1,23 +1,50 @@
-
- 4.0.0
-
- project
- project
- 0.0.1-SNAPSHOT
-
- bot
-
+
+
+
+ org.example
+ FP
+ 1.0
+
+
+ 4.0.0
+
+ bot
+
+
+ 3.0.1
+ 2.7.6
+
+
+
+
- org.springframework.boot
- spring-boot-starter-web
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.0.2
+
+
+ org.apache.commons
+ commons-lang3
+ 3.10
+
org.springframework.boot
spring-boot-starter-validation
+ ${starter-validation.version}
-
+
org.springframework.boot
- spring-boot-starter-webflux
+ spring-boot-starter-web
+ ${starter-web.version}
+
+
+ org.apache.logging.log4j
+ log4j-to-slf4j
+
+
org.springframework.boot
@@ -40,64 +67,22 @@
lombok
true
-
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.0.2
-
+
com.github.pengrad
java-telegram-bot-api
6.6.0
-
- ru.tinkoff.edu
- link-parser
- 1.0-SNAPSHOT
-
-
- org.springframework
- spring-context
- 6.0.3
-
-
- org.springframework
- spring-test
- 6.0.6
- test
-
+
org.junit.jupiter
- junit-jupiter-params
-
-
- org.mockito
- mockito-core
+ junit-jupiter
+ test
- org.springframework.boot
- spring-boot-starter-amqp
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
index 50cd2b8..312857e 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
@@ -4,13 +4,18 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.bot.firstBot.BotMain;
+
@SpringBootApplication
@EnableConfigurationProperties(ApplicationConfig.class)
-public class BotApplication {
- public static void main(String[] args) {
- var ctx = SpringApplication.run(BotApplication.class, args);
- ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
+public class BotApplication
+{
+ public static void main(String[] args){
+ var ctx = SpringApplication.run(BotApplication.class, args);
+ ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
- }
-}
\ No newline at end of file
+ BotMain bot = new BotMain(config.bot().token());
+ bot.start();
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
deleted file mode 100644
index 12c0975..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package ru.tinkoff.edu.java.bot.advice;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import ru.tinkoff.edu.java.bot.dto.ApiErrorResponse;
-import ru.tinkoff.edu.java.bot.exceptions.ChatNotFoundException;
-import ru.tinkoff.edu.java.bot.exceptions.LinkIsNotRegisteredToChatException;
-
-import java.util.Arrays;
-
-@RestControllerAdvice
-public class AppExceptionHandler {
-
- @ExceptionHandler({LinkIsNotRegisteredToChatException.class, ChatNotFoundException.class})
- @ResponseStatus(value = HttpStatus.BAD_REQUEST)
- public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) {
- return new ApiErrorResponse(
- "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
- }
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
new file mode 100644
index 0000000..25186cf
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.bot.api;
+
+import org.springframework.web.bind.annotation.*;
+import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
+
+@RestController
+@RequestMapping("/update")
+public class BotController {
+
+ @PostMapping
+ public String updateChat(@RequestBody LinkUpdate update) {
+ return update.toString();
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
new file mode 100644
index 0000000..732a56e
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
@@ -0,0 +1,36 @@
+package ru.tinkoff.edu.java.bot.api.exceptionHandler;
+
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import ru.tinkoff.edu.java.bot.api.model.ApiErrorResponse;
+
+@RestControllerAdvice
+public class BotExceptionHandler {
+
+ private String getDescription(String message) {
+ ApiErrorResponse errorObj = new ApiErrorResponse(
+ message,
+ null,
+ null,
+ null,
+ null
+ );
+ return errorObj.description();
+ }
+
+ @ExceptionHandler(HttpMessageNotReadableException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public String MessageNotReadable(HttpMessageNotReadableException Exception) {
+ return getDescription("Некорректные значения параметров или их нет!");
+ }
+
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public String MethodNotSupported(HttpRequestMethodNotSupportedException Exception) {
+ return getDescription("Метод не разрешен!");
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java
new file mode 100644
index 0000000..f43001e
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.api.model;
+
+import java.util.List;
+
+public record ApiErrorResponse(
+ String description,
+ String code,
+ String exceptionName,
+ String exceptionMessage,
+ List stacktrace
+) {}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
new file mode 100644
index 0000000..0f44607
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.bot.api.model;
+
+import java.util.List;
+
+public record LinkUpdate(long id, String url, String description, List tgChatIds) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
deleted file mode 100644
index f8ef3a4..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package ru.tinkoff.edu.java.bot.client;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
-import ru.tinkoff.edu.java.bot.dto.*;
-
-
-public class ScrapperClient {
-
- private final WebClient webClient;
-
-
- //По умолчанию - webClient инжектится из ClientConfiguration c baseUrl по умолчанию
- public ScrapperClient(WebClient webClient) {
- this.webClient = webClient;
- }
-
- //Здесь webClient не инжектится, чтобы была возможность указать baseUrl.
- public ScrapperClient(String baseUrl) {
- this.webClient = WebClient.create(baseUrl);
- }
-
-
- public ListLinkResponse getLinks(Long tgChatId) {
- ListLinkResponse response = webClient.get().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)).exchangeToMono(r -> {
- if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
- throw new ScrapperClientException("Чат с таким ID не зарегистрирован");
- } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
- throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
- }
- return r.bodyToMono(ListLinkResponse.class);
- }).block();
-
- return response;
- }
-
- public LinkResponse addLink(Long tgChatId, AddLinkRequest request) {
- LinkResponse response = webClient.post().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId))
- .bodyValue(request).exchangeToMono(r -> {
- if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
- throw new ScrapperClientException("Ссылка с таким URL уже добавлена");
- } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
- throw new ScrapperClientException("Чат с таким ID не зарегистрирован");
- } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
- throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
- }
- return r.bodyToMono(LinkResponse.class);
- }).block();
-
- return response;
- }
-
- public LinkResponse deleteLink(Long tgChatId, RemoveLinkRequest request) {
- LinkResponse response = webClient.method(HttpMethod.DELETE).uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId))
- .bodyValue(request).exchangeToMono(r -> {
- if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
- throw new ScrapperClientException("Некорректно указана ссылка");
- } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) {
- throw new ScrapperClientException("Ссылка с таким URL не найдена или чат с таким ID не зарегистрирован");
- } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
- throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
- }
- return r.bodyToMono(LinkResponse.class);
- }).block();
-
- return response;
- }
-
-
- public void registerChat(Long tgChatId, UserAddDto userAddDto) {
- webClient.post().uri("/tg-chat/{id}", tgChatId).bodyValue(userAddDto).exchangeToMono(response -> {
- if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) {
- throw new ScrapperClientException("Некорректно указан ID или такой чат уже зарегистрирован");
- } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
- throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
- }
- return Mono.empty();
- }).block();
- }
-
- public void deleteChat(Long tgChatId) {
- webClient.delete().uri("/tg-chat/{id}", tgChatId).exchangeToMono(response -> {
- if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) {
- throw new ScrapperClientException("Некорректно указан ID");
- } else if (response.statusCode().equals(HttpStatus.NOT_FOUND)) {
- throw new ScrapperClientException("Чат с таким ID не найден");
- } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
- throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже");
- }
- return Mono.empty();
- }).block();
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
deleted file mode 100644
index 9ef91d4..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.bot.client;
-
-public class ScrapperClientException extends RuntimeException{
-
- public ScrapperClientException() {
- }
-
- public ScrapperClientException(String message) {
- super(message);
- }
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
deleted file mode 100644
index a179c88..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import ru.tinkoff.edu.java.bot.dto.BotCommand;
-
-public interface Command {
- String command();
-
- String description();
-
- String handle(Update update);
-
- default boolean supports(Update update) {
- return update.message().text().equals(command());
- }
-
- default BotCommand toApiCommand() {
- return new BotCommand(command(), description());
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
deleted file mode 100644
index 1d3852c..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public enum CommandsEnum {
-
- START ("/start"),
- HELP ("/help"),
- LIST ("/list"),
- TRACK ("/track"),
- UNTRACK ("/untrack");
-
- private static final Map BY_LABEL = new HashMap<>();
-
- static {
- for (CommandsEnum c : values()) {
- BY_LABEL.put(c.label, c);
- }
- }
-
- private final String label;
-
- CommandsEnum(String command) {
- this.label = command;
- }
-
- public static CommandsEnum valueOfLabel(String label) {
- return BY_LABEL.get(label);
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
deleted file mode 100644
index 3849dc7..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import com.pengrad.telegrambot.request.SendMessage;
-import org.springframework.stereotype.Component;
-
-@Component
-public class HelpCommand implements Command{
- @Override
- public String command() {
- return "/help";
- }
-
- @Override
- public String description() {
- return "ввывести окно с командами";
- }
-
- @Override
- public String handle(Update update) {
- return "Help is executing...";
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
deleted file mode 100644
index 6a3176e..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
-import ru.tinkoff.edu.java.bot.dto.Link;
-import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
-
-@Component
-public class ListCommand implements Command {
-
- private final ScrapperClient scrapperClient;
-
- public ListCommand(ScrapperClient scrapperClient) {
- this.scrapperClient = scrapperClient;
- }
-
- @Override
- public String command() {
- return "/list";
- }
-
- @Override
- public String description() {
- return "показать список отслеживаемых ссылок";
- }
-
- @Override
- public String handle(Update update) {
- long chatId = update.message().chat().id();
- try {
- ListLinkResponse response = scrapperClient.getLinks(chatId);
- StringBuilder msg = new StringBuilder();
- if (response.size() == 0)
- msg.append("Список отслеживаемых ссылок пуст!");
- else {
- msg.append("Ссылок отслеживается - ").append(response.size()).append("\n\n");
- for (Link link : response.links()) {
- msg.append(link.url()).append("\n\n");
- }
- }
- return msg.toString();
- } catch (ScrapperClientException e){
- return e.getMessage();
- }
- }
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
deleted file mode 100644
index 9c9f497..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
-import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
-import com.pengrad.telegrambot.request.SendMessage;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
-import ru.tinkoff.edu.java.bot.dto.Link;
-import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
-import ru.tinkoff.edu.java.bot.dto.UserAddDto;
-
-@Component
-public class StartCommand implements Command {
-
- private final ScrapperClient scrapperClient;
-
- public StartCommand(ScrapperClient scrapperClient) {
- this.scrapperClient = scrapperClient;
- }
-
-
- @Value("${tg.bot.token}")
- private String token;
-
-
- @Override
- public String command() {
- return "/start";
- }
-
- @Override
- public String description() {
- return "зарегистрировать пользователя";
- }
-
- @Override
- public String handle(Update update) {
- long chatId = update.message().chat().id();
- try {
- UserAddDto userAddDto = new UserAddDto(update.message().chat().username(), update.message().chat().firstName(), update.message().chat().lastName());
- scrapperClient.registerChat(chatId, userAddDto);
- return "Привет! Рад познакомиться, " + update.message().chat().firstName();
- } catch (ScrapperClientException e) {
-
- return e.getMessage();
- }
-
-
- }
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
deleted file mode 100644
index a3eb9b4..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import com.pengrad.telegrambot.request.SendMessage;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
-import ru.tinkoff.edu.java.bot.dto.AddLinkRequest;
-
-@Component
-public class TrackCommand implements Command {
-
- private final LinkParser parser;
-
- public TrackCommand(ScrapperClient scrapperClient, LinkParser parser) {
- this.scrapperClient = scrapperClient;
- this.parser = parser;
- }
-
- private final ScrapperClient scrapperClient;
-
- @Override
- public String command() {
- return "/track";
- }
-
- @Override
- public String description() {
- return "начать отслеживание ссылки";
- }
-
- @Override
- public String handle(Update update) {
- long chatId = update.message().chat().id();
- String msg;
- try {
- if (parser.parseUrl(update.message().text()) != null){
- scrapperClient.addLink(chatId, new AddLinkRequest(update.message().text()));
- msg = "Ссылка успешно добавлена";
- } else msg = "Некорректная ссылка";
- return msg;
- } catch (ScrapperClientException e) {
- return e.getMessage();
- }
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
deleted file mode 100644
index df1c58a..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package ru.tinkoff.edu.java.bot.commands;
-
-import com.pengrad.telegrambot.model.Update;
-import com.pengrad.telegrambot.request.SendMessage;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-import ru.tinkoff.edu.java.bot.client.ScrapperClientException;
-import ru.tinkoff.edu.java.bot.dto.AddLinkRequest;
-import ru.tinkoff.edu.java.bot.dto.RemoveLinkRequest;
-
-@Component
-public class UntrackCommand implements Command{
-
- private final ScrapperClient scrapperClient;
-
- private final Link_Parser parser;
-
-
- public UntrackCommand(ScrapperClient scrapperClient, Link_Parser parser) {
- this.scrapperClient = scrapperClient;
- this.parser = parser;
- }
-
- @Override
- public String command() {
- return "/untrack";
- }
-
- @Override
- public String description() {
- return "прекратить отслеживание ссылки";
- }
-
- @Override
- public String handle(Update update) {
- long chatId = update.message().chat().id();
- String msg;
- try {
- if (parser.parseUrl(update.message().text()) != null){
- scrapperClient.deleteLink(chatId, new RemoveLinkRequest(update.message().text()));
- msg = "Ссылка успешно удалена";
- } else msg = "Некорректная ссылка";
- return msg;
- } catch (ScrapperClientException e) {
- return e.getMessage();
- }
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
index 02ab1d4..49ce5e3 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
@@ -2,11 +2,17 @@
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
+import ru.tinkoff.edu.java.bot.configuration.configRecords.Bot;
+import ru.tinkoff.edu.java.bot.configuration.configRecords.Scheduler;
@Validated
+@EnableScheduling
@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
-public record ApplicationConfig(@NotNull String test,
- String queueName,
- String exchangeName,
- String routingKey) {}
\ No newline at end of file
+public record ApplicationConfig(
+ @NotNull String test,
+ @NotNull Scheduler scheduler,
+ Bot bot
+) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
deleted file mode 100644
index d20e877..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package ru.tinkoff.edu.java.bot.configuration;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
-import ru.tinkoff.edu.java.bot.commands.*;
-import ru.tinkoff.edu.java.bot.dto.BotCommand;
-import ru.tinkoff.edu.java.bot.dto.SetCommandRequest;
-import ru.tinkoff.edu.java.bot.telegram.Bot;
-
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.List;
-
-@Configuration
-@Slf4j
-public class BotConfiguration {
-
- @Value("${tg.bot.token}")
- private String token;
-
- @Value("${tg.api.baseUrl}")
- private String tgApiBaseUrl;
-
- private final HelpCommand helpCommand;
- private final StartCommand startCommand;
- private final ListCommand listCommand;
- private final TrackCommand trackCommand;
- private final UntrackCommand untrackCommand;
-
- public BotConfiguration(HelpCommand helpCommand, StartCommand startCommand, ListCommand listCommand, TrackCommand trackCommand, UntrackCommand untrackCommand) {
- this.helpCommand = helpCommand;
- this.startCommand = startCommand;
- this.listCommand = listCommand;
- this.trackCommand = trackCommand;
- this.untrackCommand = untrackCommand;
- }
-
- @Bean
- public Bot bot() {
- EnumMap commands = new EnumMap<>(CommandsEnum.class);
-
-
- commands.put(CommandsEnum.HELP,helpCommand);
- commands.put(CommandsEnum.LIST,listCommand);
- commands.put(CommandsEnum.START,startCommand);
- commands.put(CommandsEnum.TRACK,trackCommand);
- commands.put(CommandsEnum.UNTRACK,untrackCommand);
-
- List apiCommands = new ArrayList<>(commands.values().stream().map(Command::toApiCommand).toList());
- WebClient botConfClient = WebClient.create(tgApiBaseUrl+token);
- botConfClient.post().uri("/setMyCommands").bodyValue(new SetCommandRequest(apiCommands)).exchangeToMono(r ->{
- if (!r.statusCode().equals(HttpStatus.OK)){
- log.warn("Похоже, что API Telegram недоступен(");
- }
- return Mono.empty();
- }).block();
-
- return new Bot(token, commands);
- }
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
deleted file mode 100644
index f5d3a09..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package ru.tinkoff.edu.java.bot.configuration;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.function.client.WebClient;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-
-
-@Configuration
-public class ClientConfiguration {
-
- @Value("${scrapper.baseurl}")
- private String scrapperBaseUrl;
-
-
- @Bean
- public WebClient webClient(){
- return WebClient.create(scrapperBaseUrl);
- }
-
- //Регистрируем клиентов как бины
- @Bean
- public ScrapperClient scrapperClient() {
- return new ScrapperClient(scrapperBaseUrl);
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
deleted file mode 100644
index 962ff14..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ru.tinkoff.edu.java.bot.configuration;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import parser.LinkParser;
-
-@Configuration
-public class LinkParserConfiguration {
-
- @Bean
- public LinkParser linkParser(){
- return new LinkParser();
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
index 3f53ca7..b944fc5 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -7,9 +7,7 @@
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
-import ru.tinkoff.edu.java.bot.service.ScrapperQueueListener;
-import ru.tinkoff.edu.java.bot.service.UpdateService;
+import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
import java.util.HashMap;
import java.util.Map;
@@ -55,10 +53,10 @@ Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) {
@Bean
public ClassMapper classMapper() {
Map> mappings = new HashMap<>();
- mappings.put("ru.tinkoff.edu.java.scrapper.dto.LinkUpdate", LinkUpdate.class);
+ mappings.put("ru.tinkoff.edu.java.bot.api.model.LinkUpdate", LinkUpdate.class);
DefaultClassMapper classMapper = new DefaultClassMapper();
- classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.dto.*");
+ classMapper.setTrustedPackages("ru.tinkoff.edu.java.bot.api.model.*");
classMapper.setIdClassMapping(mappings);
return classMapper;
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
new file mode 100644
index 0000000..37f4842
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
@@ -0,0 +1,4 @@
+package ru.tinkoff.edu.java.bot.configuration.configRecords;
+
+public record Bot(String token, String name) {
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java
new file mode 100644
index 0000000..08278f6
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.bot.configuration.configRecords;
+
+import java.time.Duration;
+
+public record Scheduler(Duration interval) {}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
deleted file mode 100644
index 1ff0bee..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-
-public record AddLinkRequest(String link) {
-
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
deleted file mode 100644
index d8d6113..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-public record ApiErrorResponse(String description, String code, String exceptionName,
- String exceptionMessage, String[] stacktrace) {
-
-
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
deleted file mode 100644
index 201c5c6..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.io.Serializable;
-
-public record BotCommand(@JsonProperty("command") String command, @JsonProperty("description") String description) implements Serializable {
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
deleted file mode 100644
index 2ab0a84..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import java.net.URI;
-
-public record Link (Long id, URI url){
- @Override
- public String toString() {
- return "Link{" + "id=" + id + ", url='" + url + '\'' +'}';
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
deleted file mode 100644
index 396f750..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import java.net.URI;
-
-public record LinkResponse(long id, URI url) {
-
- @Override
- public String toString() {
- return "LinkResponse{" + "id=" + id + ", url=" + url +'}';
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
deleted file mode 100644
index 8a92e00..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) {
-
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
deleted file mode 100644
index 5d23d7b..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import java.util.List;
-
-public record ListLinkResponse(List links, int size) {
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
deleted file mode 100644
index 7e58ba4..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-public record RemoveLinkRequest(String link) {
-
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
deleted file mode 100644
index 799cdc3..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.List;
-
-public record SetCommandRequest(@JsonProperty("commands") List commands) {
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
deleted file mode 100644
index d21ec6a..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.bot.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public record UserAddDto(@JsonProperty("username") String username,
- @JsonProperty("first_name") String firstName,
- @JsonProperty("last_name") String lastName) {
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
deleted file mode 100644
index 524f6f3..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ru.tinkoff.edu.java.bot.exceptions;
-
-public class ChatNotFoundException extends RuntimeException {
- public ChatNotFoundException() {
- }
-
- public ChatNotFoundException(String message) {
- super(message);
- }
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
deleted file mode 100644
index 98c36ae..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ru.tinkoff.edu.java.bot.exceptions;
-
-public class LinkIsNotRegisteredToChatException extends RuntimeException {
- public LinkIsNotRegisteredToChatException() {
- }
-
- public LinkIsNotRegisteredToChatException(String message) {
- super(message);
- }
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java
new file mode 100644
index 0000000..f758472
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java
@@ -0,0 +1,36 @@
+package ru.tinkoff.edu.java.bot.firstBot;
+
+import com.pengrad.telegrambot.TelegramBot;
+import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig;
+
+
+@EnableConfigurationProperties(ApplicationConfig.class)
+public class BotMain {
+
+ String token;
+ static TelegramBot bot;
+
+ public BotMain(String token) {
+ this.token = token;
+ }
+
+ public void start() {
+ bot = new TelegramBot(token);
+ bot.setUpdatesListener(new Updater(bot));
+ }
+
+ public void end() {
+ bot.removeGetUpdatesListener();
+ }
+
+ public static void apiCommand(long tgChatId, String command) {
+
+ MessageHandler handler = new MessageHandler();
+ String[] parse = command.split(" ");
+ if(parse.length > 1) command = handler.call_command(parse[0], parse[1]);
+ else command = handler.call_command(parse[0]);
+ bot.execute(new SendMessage(tgChatId, command));
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java
new file mode 100644
index 0000000..486a886
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java
@@ -0,0 +1,42 @@
+package ru.tinkoff.edu.java.bot.firstBot;
+
+import java.util.ArrayList;
+
+public class DB {
+
+ static ArrayList list = new ArrayList();
+
+ public static void addLink(String link) {
+ list.add(link);
+ }
+
+ public static void rmLink(String link) {
+ list.remove(link);
+ }
+
+ public static String getListParse() {
+
+ int i = 1;
+
+ String out_list = "";
+
+ for(String element: list){
+
+ out_list += element;
+
+ if(i != list.size()) {
+ out_list += ", ";
+ }
+ i++;
+ }
+ return out_list;
+ }
+
+ public static boolean listIsEmpty() {
+ return list.isEmpty();
+ }
+
+ public static boolean linkContain(String link) {
+ return list.contains(link);
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java
new file mode 100644
index 0000000..f003c84
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java
@@ -0,0 +1,30 @@
+package ru.tinkoff.edu.java.bot.firstBot;
+
+import ru.tinkoff.edu.java.bot.firstBot.commands.All;
+
+public class MessageHandler extends All {
+
+ public boolean is_command(String message) {
+ return message.startsWith("/");
+ }
+
+ public String call_command(String command, String arg) {
+ return switch (command) {
+ case "/start" -> start();
+ case "/help" -> help();
+ case "/track" -> track(arg);
+ case "/list" -> list();
+ case "/untrack" -> untrack(arg);
+ default -> unknow();
+ };
+ }
+
+ public String call_command(String command) {
+ return switch (command) {
+ case "/start" -> start();
+ case "/help" -> help();
+ case "/list" -> list();
+ default -> unknow();
+ };
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java
new file mode 100644
index 0000000..a01e4d9
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java
@@ -0,0 +1,39 @@
+package ru.tinkoff.edu.java.bot.firstBot;
+
+import com.pengrad.telegrambot.TelegramBot;
+import com.pengrad.telegrambot.UpdatesListener;
+import com.pengrad.telegrambot.model.Update;
+import com.pengrad.telegrambot.model.request.*;
+import com.pengrad.telegrambot.request.SendMessage;
+
+import java.util.List;
+
+public class Updater implements UpdatesListener {
+
+ MessageHandler handler = new MessageHandler();
+ String command;
+ TelegramBot bot;
+
+ public Updater(TelegramBot bot) {
+ this.bot = bot;
+ }
+
+ @Override
+ public int process(List updates) {
+ Update update = updates.get(0);
+ if(handler.is_command(update.message().text())) {
+ String[] parse = update.message().text().split(" ");
+ if(parse.length > 1) command = handler.call_command(parse[0], parse[1]);
+ else command = handler.call_command(parse[0]);
+ bot.execute(
+ new SendMessage(update.message().chat().id(), command)
+ .replyMarkup(new ReplyKeyboardMarkup(new String[][]{
+ {"/start", "/help"},
+ {"/track testlink", "/untrack testlink", "/list"}
+ }).resizeKeyboard(true)
+ ).parseMode(ParseMode.HTML)
+ );
+ }
+ return UpdatesListener.CONFIRMED_UPDATES_ALL;
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java
new file mode 100644
index 0000000..991b177
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java
@@ -0,0 +1,7 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+public class All implements List, Start, Track, Untrack, Help {
+ protected String unknow() {
+ return "Неизвестная команда";
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java
new file mode 100644
index 0000000..0761e05
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+public interface Help {
+ default String help() {
+ return "/start -- зарегистрировать пользователя\n" +
+ "/help -- вывести окно с командами\n" +
+ "/track [link] -- начать отслеживание ссылки\n" +
+ "/untrack [link] -- прекратить отслеживание ссылки\n" +
+ "/list -- показать список отслеживаемых ссылок";
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java
new file mode 100644
index 0000000..8673887
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java
@@ -0,0 +1,10 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+import ru.tinkoff.edu.java.bot.firstBot.DB;
+
+public interface List {
+ default String list() {
+ if(DB.listIsEmpty()) return "list пустой";
+ return "Отслеживаемые ссылки: " + DB.getListParse() + "";
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java
new file mode 100644
index 0000000..d58c89c
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java
@@ -0,0 +1,9 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+public interface Start {
+
+ default String start() {
+ return "Бот начал работу";
+ }
+}
+
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java
new file mode 100644
index 0000000..0f4669e
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java
@@ -0,0 +1,13 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+import ru.tinkoff.edu.java.bot.firstBot.DB;
+
+public interface Track {
+ default String track(String link) {
+ link = link.trim();
+ if(link.equals("")) return "ведите ссылку";
+ if(DB.linkContain(link)) return "Ссылка уже есть";
+ DB.addLink(link);
+ return "ссылка " + link + " добавлена";
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java
new file mode 100644
index 0000000..6550daf
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.bot.firstBot.commands;
+
+import ru.tinkoff.edu.java.bot.firstBot.DB;
+
+public interface Untrack {
+ default String untrack(String link) {
+ if(link.equals("")) return "ведите ссылку";
+ if(DB.linkContain(link)) {
+ DB.rmLink(link);
+ return "ссылка " + link + " удалена";
+ }
+ return "ссылки " + link + " нет в пуле";
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
deleted file mode 100644
index 604e19c..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package ru.tinkoff.edu.java.bot.rest;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
-import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
-import ru.tinkoff.edu.java.bot.service.UpdateService;
-import ru.tinkoff.edu.java.bot.service.UpdateServiceImpl;
-
-@RestController
-@Slf4j
-public class BotRestController {
-
-
- private final UpdateService updateService;
-
-
- public BotRestController(UpdateService updateService) {
- this.updateService = updateService;
- }
-
- @PostMapping("updates")
- public void sendUpdate(@RequestBody LinkUpdate request) {
- log.info("Пришёл запрос на обновление: "+request);
- updateService.updateLink(request);
- }
-
-
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java
new file mode 100644
index 0000000..1b2ff0f
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java
@@ -0,0 +1,17 @@
+package ru.tinkoff.edu.java.bot.schedule;
+
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+@Service
+public class LinkUpdaterScheduler {
+ private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+
+ @Scheduled(fixedDelayString = "${app.scheduler.interval}")
+ public void update() {
+ LOGGER.log(Level.INFO, "Info bot called");
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
deleted file mode 100644
index ed22af0..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.bot.service;
-
-import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
-
-public interface UpdateService {
-
-void updateLink(LinkUpdate linkUpdate);
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
deleted file mode 100644
index f3878a4..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ru.tinkoff.edu.java.bot.service;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
-import ru.tinkoff.edu.java.bot.telegram.Bot;
-
-@Service
-@Slf4j
-public class UpdateServiceImpl implements UpdateService{
-
- private final Bot bot;
-
- public UpdateServiceImpl(Bot bot) {
- this.bot = bot;
- }
-
- public void updateLink(LinkUpdate linkUpdate) {
- log.info("updateLink() method invocation in UpdateServiceImpl");
- String message = "Вышло обновление по ссылке "+linkUpdate.url()+" \n"+linkUpdate.description();
- for (Long chatId : linkUpdate.tgChatIds()) {
- bot.sendMessage(chatId, message);
- }
- }
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
deleted file mode 100644
index 50c8671..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package ru.tinkoff.edu.java.bot.telegram;
-
-import com.pengrad.telegrambot.TelegramBot;
-import com.pengrad.telegrambot.UpdatesListener;
-import com.pengrad.telegrambot.model.Update;
-import com.pengrad.telegrambot.request.SendMessage;
-import jakarta.annotation.PostConstruct;
-import ru.tinkoff.edu.java.bot.commands.Command;
-import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
-
-import java.util.EnumMap;
-
-public class Bot implements AutoCloseable {
-
- private final TelegramBot bot;
- private final UserMessageProcessor userMessageProcessor;
-
-
-
- @PostConstruct
- public void init(){
- start();
- }
-
- public Bot(String token, EnumMap commands) {
- System.out.println("Создание бота... Токен: " + token);
- userMessageProcessor = new UserMessageProcessor(commands);
- bot = new TelegramBot(token);
- }
-
- public void start() {
- System.out.println("Бот запущен...");
- bot.setUpdatesListener(updates -> {
- for (Update update : updates) {
- bot.execute(new SendMessage(update.message().chat().id(), userMessageProcessor.process(update)));
-
- }
- return UpdatesListener.CONFIRMED_UPDATES_ALL;
- });
- }
-
-
- public void sendMessage(Long chatId, String msg) {
- bot.execute(new SendMessage(chatId, msg));
- }
-
-
-
- @Override
- public void close() throws Exception {
- bot.removeGetUpdatesListener();
- }
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
deleted file mode 100644
index fb08682..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package ru.tinkoff.edu.java.bot.telegram;
-
-import com.pengrad.telegrambot.model.Update;
-import ru.tinkoff.edu.java.bot.commands.*;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class UserMessageProcessor {
-
- private final Map userStateMap;
-
- private final EnumMap commands;
-
-
- public UserMessageProcessor(EnumMap commands) {
- this.commands = commands;
- userStateMap = new HashMap<>();
- }
-
- public String process(Update update) {
- Command command;
-
-
- userStateMap.putIfAbsent(update.message().chat().id(), UserState.TYPING_COMMAND);
- switch (userStateMap.get(update.message().chat().id())) {
- case TYPING_TRACKED -> {
- userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
- return commands.get(CommandsEnum.valueOfLabel("/track")).handle(update);
- }
- case TYPING_UNTRACKED -> {
- userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
- return commands.get(CommandsEnum.valueOfLabel("/untrack")).handle(update);
- }
- case TYPING_COMMAND -> {
- userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND);
- command = commands.get(CommandsEnum.valueOfLabel(update.message().text()));
- if (command == null)
- return "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд";
- if (command instanceof TrackCommand) {
- userStateMap.put(update.message().chat().id(), UserState.TYPING_TRACKED);
- return "Отправьте ссылку, которую хотите начать отслеживать";
- }
- if (command instanceof UntrackCommand) {
- userStateMap.put(update.message().chat().id(), UserState.TYPING_UNTRACKED);
- return "Отправьте ссылку, которую хотите перестать отслеживать";
- }
- if (command instanceof HelpCommand){
- StringBuilder text = new StringBuilder();
- for (Command c : commands.values()) {
- text.append(c.command()).append(" - ").append(c.description()).append("\n");
- }
- return text.toString();
- }
- return command.handle(update);
- }
- default -> {
-
- return "Что-то пошло не так. Проблема на нашеё стороне";
- }
- }
-
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
deleted file mode 100644
index 70bc584..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.bot.telegram;
-
-public enum UserState {
- TYPING_COMMAND, TYPING_TRACKED, TYPING_UNTRACKED
-}
diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties
index 9f20e72..fedebeb 100644
--- a/FP/bot/src/main/resources/application.properties
+++ b/FP/bot/src/main/resources/application.properties
@@ -1,13 +1,6 @@
-app.test=beamer-bot
-server.port=8080
+app.test=123
springdoc.swagger-ui.path=/swagger-ui
-tg.bot.token=${TGBOTTOKEN}
-tg.api.baseUrl=https://api.telegram.org/bot
-spring.rabbitmq.host=localhost
-spring.rabbitmq.port=5672
-spring.rabbitmq.username=romanova
-spring.rabbitmq.password=12345654321
-spring.rabbitmq.listener.simple.default-requeue-rejected=false
-app.queue-name=scrapper-bot-queue
-app.exchange-name=scrapper-bot-exchange
-app.routing-key=scrapper-bot-key
\ No newline at end of file
+app.scheduler.interval=50000
+app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
+app.bot.name=@SFRETbot
+server.port=8081
diff --git a/FP/bot/src/main/resources/botapi.yml b/FP/bot/src/main/resources/botapi.yml
new file mode 100644
index 0000000..489441e
--- /dev/null
+++ b/FP/bot/src/main/resources/botapi.yml
@@ -0,0 +1,59 @@
+openapi: 3.0.1
+info:
+ title: Bot API
+ version: 1.0.0
+ contact:
+ name: Alexander Biryukov
+ url: https://github.com
+paths:
+ /updates:
+ post:
+ summary: Отправить обновление
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LinkUpdate'
+ required: true
+ responses:
+ '200':
+ description: Обновление обработано
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+components:
+ schemas:
+ ApiErrorResponse:
+ type: object
+ properties:
+ description:
+ type: string
+ code:
+ type: string
+ exceptionName:
+ type: string
+ exceptionMessage:
+ type: string
+ stacktrace:
+ type: array
+ items:
+ type: string
+ LinkUpdate:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ url:
+ type: string
+ format: uri
+ description:
+ type: string
+ tgChatIds:
+ type: array
+ items:
+ type: integer
+ format: int64
diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java
new file mode 100644
index 0000000..1548bc9
--- /dev/null
+++ b/FP/bot/src/test/java/BotTest.java
@@ -0,0 +1,24 @@
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import ru.tinkoff.edu.java.bot.firstBot.DB;
+import ru.tinkoff.edu.java.bot.firstBot.MessageHandler;
+
+
+public class BotTest {
+
+ String except_empty_list = "list пустой";
+ String except_unknow_command = "Неизвестная команда";
+ MessageHandler handler = new MessageHandler();
+
+ @Test
+ public void listTest() {
+ Assertions.assertEquals(handler.call_command("/list"), except_empty_list);
+ DB.addLink("link");
+ Assertions.assertNotEquals(handler.call_command("/list"), except_empty_list);
+ }
+
+ @Test
+ public void unknowCommandAndFormatTest() {
+ Assertions.assertEquals(handler.call_command("/uno"), except_unknow_command);
+ }
+}
diff --git a/FP/bot/src/test/java/bot/BotTest.java b/FP/bot/src/test/java/bot/BotTest.java
deleted file mode 100644
index af954d2..0000000
--- a/FP/bot/src/test/java/bot/BotTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package bot;
-
-import com.pengrad.telegrambot.model.Chat;
-import com.pengrad.telegrambot.model.Message;
-import com.pengrad.telegrambot.model.Update;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import org.springframework.test.util.ReflectionTestUtils;
-import ru.tinkoff.edu.java.bot.client.ScrapperClient;
-import ru.tinkoff.edu.java.bot.commands.Command;
-import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
-import ru.tinkoff.edu.java.bot.commands.ListCommand;
-import ru.tinkoff.edu.java.bot.dto.Link;
-import ru.tinkoff.edu.java.bot.dto.ListLinkResponse;
-import ru.tinkoff.edu.java.bot.telegram.UserMessageProcessor;
-import ru.tinkoff.edu.java.bot.telegram.UserState;
-
-import java.net.URI;
-import java.util.*;
-
-public class BotTest {
-
- static UserMessageProcessor userMessageProcessor;
-
- static ScrapperClient scrapperClient;
-
- static Update updateForListCommand;
- static Update updateForInvalidCommand;
- static Message messageForListCommand;
- static Message messageForInvalidCommand;
-
- static Chat chat;
-
- @BeforeAll
- static void init() {
- //инициализируем заглушки и входные дынные, т.к. у Update в нет сеттеров, то используем рефлексию,
- //чтобы поместить туда нужный Message
- scrapperClient = Mockito.mock(ScrapperClient.class);
- updateForListCommand = new Update();
- messageForListCommand = new Message();
- chat = new Chat();
- ReflectionTestUtils.setField(chat, "id", 42L);
- ReflectionTestUtils.setField(messageForListCommand, "chat", chat);
- ReflectionTestUtils.setField(messageForListCommand, "text", "/list");
- ReflectionTestUtils.setField(updateForListCommand, "message", messageForListCommand);
-
- updateForInvalidCommand = new Update();
- messageForInvalidCommand = new Message();
-
- ReflectionTestUtils.setField(messageForInvalidCommand, "chat", chat);
- ReflectionTestUtils.setField(messageForInvalidCommand, "text", "Azazelo");
- ReflectionTestUtils.setField(updateForInvalidCommand, "message", messageForInvalidCommand);
- }
-
- @Test
- @DisplayName("Тест команды /list, когда список ссылок непустой")
- public void listCommandTestNotEmpty() {
-
- //имитируем нужное поведение клиента для Scrapper, т.к. реального запроса на Scrapper во время не происходит
- List listLink = new ArrayList<>();
- listLink.add(new Link(1L, URI.create("https://github.com/lwbeamer/asm-like-language")));
- listLink.add(new Link(2L, URI.create("https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface")));
- Mockito.when(scrapperClient.getLinks(42L)).thenReturn(
- new ListLinkResponse(listLink, listLink.size())
- );
-
- EnumMap map = new EnumMap<>(CommandsEnum.class);
- map.put(CommandsEnum.LIST, new ListCommand(scrapperClient));
-
- userMessageProcessor = new UserMessageProcessor(map);
-
- String expectedMessage = """
- Ссылок отслеживается - 2
-
- https://github.com/lwbeamer/asm-like-language
-
- https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface
-
- """;
-
- Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand));
- }
-
-
- @Test
- @DisplayName("Тест команды /list, когда список ссылок пустой")
- public void listCommandTestEmpty() {
- Mockito.when(scrapperClient.getLinks(42L)).thenReturn(
- new ListLinkResponse(new ArrayList<>(), 0)
- );
-
-
- EnumMap map = new EnumMap<>(CommandsEnum.class);
- map.put(CommandsEnum.LIST, new ListCommand(scrapperClient));
-
- userMessageProcessor = new UserMessageProcessor(map);
-
-
- String expectedMessage = "Список отслеживаемых ссылок пуст!";
-
- Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand));
- }
-
- @Test
- @DisplayName("Тест для проверки ввода неизвестной команды")
- public void invalidCommandCheck() {
- userMessageProcessor = new UserMessageProcessor(new EnumMap<>(CommandsEnum.class));
-
- //Устанавливаем состояние перед тестом - пользователь в сосвтоянии "печатает команду"
- Map userStateMap = new HashMap<>();
- userStateMap.put(chat.id(), UserState.TYPING_COMMAND);
- ReflectionTestUtils.setField(userMessageProcessor, "userStateMap", userStateMap);
-
- String expectedMessage = "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд";
-
- Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForInvalidCommand));
-
- }
-
-}
\ No newline at end of file
diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml
index c472659..b9f4994 100644
--- a/FP/docker-compose.yml
+++ b/FP/docker-compose.yml
@@ -1,60 +1,52 @@
+version: '1.-'
+
services:
- postgresql:
- image: postgres:15
- container_name: postgresql
- ports:
- - 5432:5432
+ postgres:
+ container_name: postgres
+ image: postgres:15.2
environment:
- - POSTGRES_USER=lwbeamer
- - POSTGRES_PASSWORD=2281337
- - POSTGRES_DB=scrapper
+ POSTGRES_DB: scrapper
+ POSTGRES_USER: scrap_user
+ POSTGRES_PASSWORD: hard_password
volumes:
- - link-service-data:/var/lib/postgresql/data
+ - ./migrations/postgres_data:/var/lib/postgresql/data
+ ports:
+ - "5432:5432"
networks:
- backend
liquibase-migrations:
+ container_name: liquibase
image: liquibase/liquibase:4.18
- depends_on:
- - postgresql
+ deploy:
+ restart_policy:
+ condition: on-failure
+ delay: 10s
+ max_attempts: 10
command:
- --hub-mode=off
- --changelog-file=master.xml
- --driver=org.postgresql.Driver
- - --url=jdbc:postgresql://postgresql:5432/scrapper
- - --username=romanova
- - --password=12345654321
+ - --url=jdbc:postgresql://postgres:5432/scrapper
+ - --username=scrap_user
+ - --password=hard_password
+ - --logLevel=debug
- update
volumes:
- ./migrations:/liquibase/changelog
networks:
- backend
-
-volumes:
- link-service-data:
-
-networks:
- backend:
- name: backend
- rabbit:
- image: rabbitmq:3-management
- hostname: rabbitmq
- container_name: rabbit
+ rabbitmq:
+ image: rabbitmq:3-management-alpine
ports:
- - 15672:15672
- - 5672:5672
- environment:
- - RABBITMQ_DEFAULT_USER=romanova
- - RABBITMQ_DEFAULT_PASS=12345654321
+ - 5672:5672 # Порт для AMQP
+ - 15672:15672 # Порт для RabbitMQ Management UI
volumes:
- - rabbitmq-state:/var/lib/rabbitmq
- networks:
- - backend
-
-volumes:
- link-service-data:
- rabbitmq-state:
+ - ./rabbitmq:/var/lib/rabbitmq
+ environment:
+ - RABBITMQ_DEFAULT_USER=root
+ - RABBITMQ_DEFAULT_PASS=root
networks:
backend:
- name: backend
\ No newline at end of file
+ driver: bridge
\ No newline at end of file
diff --git a/FP/link-parser/.classpath b/FP/link-parser/.classpath
deleted file mode 100644
index a08fc4f..0000000
--- a/FP/link-parser/.classpath
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/link-parser/.gitignore b/FP/link-parser/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/link-parser/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/link-parser/.project b/FP/link-parser/.project
deleted file mode 100644
index dec0f32..0000000
--- a/FP/link-parser/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- link-parser
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/link-parser/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/link-parser/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,6 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/java=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/=UTF-8
diff --git a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml
index 3cfd292..088df38 100644
--- a/FP/link-parser/pom.xml
+++ b/FP/link-parser/pom.xml
@@ -1,30 +1,26 @@
-
- 4.0.0
-
- project
- project
- 0.0.1-SNAPSHOT
-
- link-parser
-
+
+
+
+ org.example
+ FP
+ 1.0
+
+
+ 4.0.0
+
+ link-parser
+
org.junit.jupiter
- junit-jupiter-params
+ junit-jupiter
+ test
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
-
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
-
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
deleted file mode 100644
index e244c93..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.link;
-
-public record GitHub_Link(String username, String repository) implements Parser_Link {
-
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
deleted file mode 100644
index 75db93c..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.link;
-
-public sealed interface Parser_Link permits GitHub_Link, StackOverflow_Link {
-
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
deleted file mode 100644
index 1dad8ad..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.link;
-
-public record StackOverflow_Link(long id) implements Parser_Link {
-
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
deleted file mode 100644
index f3641fc..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.parser;
-
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-public abstract class Abstract {
-
- Abstract nextParser;
-
- public Abstract(Abstract nextParser) {
- this.nextParser = nextParser;
- }
-
- public abstract Parser_Link parser_Link(String url);
-
- public final URL tweakUrl(String urlString) {
- URL url;
- try{
- url = new URL(urlString);
- } catch (MalformedURLException e){
- System.out.println("Incorrect URL");
- return null;
- }
- return url;
- }
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
deleted file mode 100644
index 13ae325..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.parser;
-
-import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-
-import java.net.URL;
-
-
-public class Github extends Abstract {
- public Github(Abstract nextParser) {
- super(nextParser);
- }
-
- @Override
- public Parser_Link parser_Link(String url) {
- URL toParse = tweakUrl(url);
- if (toParse == null) return null;
-
- if (toParse.getHost().equals("github.com")) {
- String[] tokens = toParse.getFile().substring(1).split("/");
- if (tokens.length >= 2) {
- return new GitHub_Link(tokens[0], tokens[1]);
- } else return null;
- }
-
-
- if (nextParser != null) return nextParser.parser_Link(url);
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
deleted file mode 100644
index fac1e3f..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.parser;
-
-import ru.tinkoff.edu.java.link_parser.parser.Abstract;
-import ru.tinkoff.edu.java.link_parser.parser.Github;
-import ru.tinkoff.edu.java.link_parser.parser.StackOverflow;
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-
-public class Link_Parser {
- public Parser_Link parseUrl(String url) {
- Abstract parser1 = new Github(null);
- Abstract parser2 = new StackOverflow(parser1);
-
- return parser2.parser_Link(url);
- }
-
-}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
deleted file mode 100644
index e224578..0000000
--- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package ru.tinkoff.edu.java.link_parser.parser;
-
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
-import java.net.URL;
-public class StackOverflow extends Abstract {
- public StackOverflow(Abstract nextParser) {
- super(nextParser);
- }
-
- @Override
- public Parser_Link parser_Link(String url) {
-
- URL toParse = tweakUrl(url);
- if (toParse == null) return null;
-
-
- if (toParse.getHost().equals("stackoverflow.com")) {
- String[] tokens = toParse.getFile().substring(1).split("/");
- if (tokens.length >= 2 && tokens[0].equals("questions")) {
- try {
- return new StackOverflow_Link(Long.parseLong(tokens[1]));
- } catch (NumberFormatException e) {
- System.out.println("Incorrect question ID");
- return null;
- }
- } else return null;
- }
-
- if (nextParser != null) return nextParser.parser_Link(url);
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java
new file mode 100644
index 0000000..1f217ea
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java
@@ -0,0 +1,18 @@
+package ru.tinkoff.edu.java.linkparser;
+
+import ru.tinkoff.edu.java.linkparser.absracts.*;
+
+public class LinkParser {
+
+ public String getLink(String link) {
+
+ AbstractParser gitParser = new GitParser();
+ AbstractParser stackParser = new StackParser();
+ AbstractParser otherParser = new OtherParser();
+
+ gitParser.setNextParser(stackParser);
+ stackParser.setNextParser(otherParser);
+
+ return gitParser.logParser(link);
+ }
+}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java
new file mode 100644
index 0000000..503e413
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.linkparser.absracts;
+
+public abstract class AbstractParser {
+
+ private AbstractParser nextParser;
+
+ public void setNextParser(AbstractParser nextParser) {
+ this.nextParser = nextParser;
+ }
+
+ public String logParser (String link) {
+ if(nextParser != null) {
+ if(this.parsAbstract(link) == null) return nextParser.logParser(link);
+ }
+ return this.parsAbstract(link);
+ }
+
+ abstract protected String parsAbstract(String link);
+
+}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java
new file mode 100644
index 0000000..9525306
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.linkparser.absracts;
+
+import java.util.Objects;
+
+public class GitParser extends AbstractParser {
+
+ @Override
+ protected String parsAbstract(String link) {
+
+ String[] parsed = link.split("/");
+
+ if (parsed.length < 2) return null;
+
+ if (!Objects.equals(parsed[2], "github.com")) return null;
+
+ if (parsed.length > 4) return parsed[3] + "/" + parsed[4];
+
+ return null;
+ }
+}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java
new file mode 100644
index 0000000..f3746fe
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java
@@ -0,0 +1,9 @@
+package ru.tinkoff.edu.java.linkparser.absracts;
+
+public class OtherParser extends AbstractParser {
+
+ @Override
+ protected String parsAbstract(String link) {
+ return null;
+ }
+}
diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java
new file mode 100644
index 0000000..571ea58
--- /dev/null
+++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java
@@ -0,0 +1,19 @@
+package ru.tinkoff.edu.java.linkparser.absracts;
+
+import java.util.Objects;
+
+public class StackParser extends AbstractParser {
+
+ @Override
+ protected String parsAbstract(String link) {
+
+ String[] parsed = link.split("/");
+
+ if (parsed.length < 5) return null;
+ if (!Objects.equals(parsed[2], "stackoverflow.com")) return null;
+ if (!Objects.equals(parsed[3], "questions")) return null;
+
+
+ return parsed[4];
+ }
+}
diff --git a/FP/link-parser/src/test/java/LinkParserTest.java b/FP/link-parser/src/test/java/LinkParserTest.java
index bef7512..7bd8349 100644
--- a/FP/link-parser/src/test/java/LinkParserTest.java
+++ b/FP/link-parser/src/test/java/LinkParserTest.java
@@ -1,99 +1,24 @@
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
-import ru.tinkoff.edu.java.link_parser.parser.*;
-import ru.tinkoff.edu.java.link_parser.link.*;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
public class LinkParserTest {
- static String validGitHubLink;
- static String validStackOverflowLink;
- static String gitHubNotRepoLink;
- static String stackOverflowNotQuestionLink;
- static String emptyLink;
- static String withoutProtocolLink;
- static String unknownHostLink;
- static String invalidLink;
-
-
- @BeforeAll
- static void init() {
- validGitHubLink = "https://github.com/lwbeamer/asm-like-language";
- validStackOverflowLink = "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file";
- gitHubNotRepoLink = "https://github.com/issues";
- stackOverflowNotQuestionLink = "https://stackoverflow.co/talent";
- emptyLink = "";
- withoutProtocolLink = "github.com/lwbeamer/asm-like-language";
- unknownHostLink = "https://vk.com/feed";
- invalidLink = "somethingNotValid";
- }
-
-
- @Test
- @DisplayName("Тест для проверки валидной ссылки с GitHub")
- void checkValidGitHubLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertEquals(new GitHub_Link("lwbeamer", "asm-like-language"), parser.parseUrl(validGitHubLink), "Тест не пройден, проверьте реузультат");
- }
+ String gitLink = "https://github.com/Ray-Not/JavaGuava";
+ String invalidLink = "https://gitrub.com/";
+ String invalidLink2 = "https://github.com/Ray-Not";
+ String expectGitLink = "Ray-Not/JavaGuava";
+ String stackLink = "https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c";
+ String expectStackLink = "1642028";
+ LinkParser pars = new LinkParser();
@Test
- @DisplayName("Тест для проверки валидной ссылки со StackOverflow")
- void validStackOverflowLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertEquals(new StackOverflow_Link(2336692), parser.parseUrl(validStackOverflowLink), "Тест не пройден, проверьте реузультат");
+ public void validGitPars(){
+ Assertions.assertNull(pars.getLink(invalidLink));
+ Assertions.assertNull(pars.getLink(invalidLink2));
+ Assertions.assertNotNull(pars.getLink(gitLink));
+ Assertions.assertEquals(pars.getLink(gitLink), expectGitLink);
+ Assertions.assertEquals(pars.getLink(stackLink), expectStackLink);
}
-
-
- @Test
- @DisplayName("Тест для проверки ссылки с GitHub, не являющейся репозиторием")
- void gitHubNotRepoLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(gitHubNotRepoLink), "Тест не пройден, проверьте реузультат");
- }
-
- @Test
- @DisplayName("Тест для проверки ссылки со StackOverflow, не являющейся вопросом")
- void stackOverflowNotQuestionLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(stackOverflowNotQuestionLink), "Тест не пройден, проверьте реузультат");
- }
-
-
- @Test
- @DisplayName("Тест для проверки пустой ссылки")
- void emptyLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(emptyLink), "Тест не пройден, проверьте реузультат");
- }
-
-
- @Test
- @DisplayName("Тест для проверки ссылки без указания протокола")
- void withoutProtocolLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(withoutProtocolLink), "Тест не пройден, проверьте реузультат");
- }
-
- @Test
- @DisplayName("Тест для проверки ссылки, не относящейся к отслеживаемым ресурсам")
- void unknownHostLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(unknownHostLink), "Тест не пройден, проверьте реузультат");
- }
-
-
- @Test
- @DisplayName("Тест для проверки непустой невалидной ссылки")
- void invalidLink() {
- Link_Parser parser = new Link_Parser();
- Assertions.assertNull(parser.parseUrl(invalidLink), "Тест не пройден, проверьте реузультат");
- }
-
-
}
diff --git a/FP/migrations/01-schema-1.sql b/FP/migrations/01-schema-1.sql
deleted file mode 100644
index 838947b..0000000
--- a/FP/migrations/01-schema-1.sql
+++ /dev/null
@@ -1,11 +0,0 @@
---liquibase formatted sql
-
---changeset romanova:create-user-table-1
-CREATE TABLE "user" (
- chat_id bigint PRIMARY KEY,
- username text UNIQUE NOT NULL,
- first_name text,
- last_name text
-);
-
---rollback DROP TABLE "user";
\ No newline at end of file
diff --git a/FP/migrations/02-schema-2.sql b/FP/migrations/02-schema-2.sql
deleted file mode 100644
index 0e40afb..0000000
--- a/FP/migrations/02-schema-2.sql
+++ /dev/null
@@ -1,15 +0,0 @@
---liquibase formatted sql
-
---changeset romanova:create-link-table-1
-CREATE TABLE "link" (
- id bigserial PRIMARY KEY,
- url text UNIQUE NOT NULL,
- checked_at timestamp NOT NULL,
- gh_pushed_at timestamp,
- gh_description text,
- gh_forks_count int,
- so_answer_count int,
- so_last_edit_date timestamp
-);
-
---rollback DROP TABLE "link";
\ No newline at end of file
diff --git a/FP/migrations/03-schema-3.sql b/FP/migrations/03-schema-3.sql
deleted file mode 100644
index c407b73..0000000
--- a/FP/migrations/03-schema-3.sql
+++ /dev/null
@@ -1,10 +0,0 @@
---liquibase formatted sql
-
---changeset romanova:create-user-link-table-1
-CREATE TABLE "user_link" (
- link_id bigint REFERENCES "link" (id),
- chat_id bigint REFERENCES "user" (chat_id),
- PRIMARY KEY (link_id,chat_id)
-);
-
---rollback DROP TABLE "user_link";
\ No newline at end of file
diff --git a/FP/migrations/create.sql b/FP/migrations/create.sql
deleted file mode 100644
index a4e2a68..0000000
--- a/FP/migrations/create.sql
+++ /dev/null
@@ -1,18 +0,0 @@
-create table "user" (
- chat_id bigint primary key,
- username text unique not null,
- first_name text,
- last_name text
-);
-
-create table "link" (
- id bigserial primary key,
- url text unique not null,
- updated_at timestamp not null
-);
-
-create table "user_link" (
- link_id bigint references "link" (id),
- chat_id bigint references "user" (chat_id),
- primary key (link_id,chat_id)
-)
\ No newline at end of file
diff --git a/FP/migrations/delete.sql b/FP/migrations/delete.sql
deleted file mode 100644
index 1fb56bd..0000000
--- a/FP/migrations/delete.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-drop table "user_link";
-drop table "user";
-drop table "link";
\ No newline at end of file
diff --git a/FP/migrations/insert.sql b/FP/migrations/insert.sql
deleted file mode 100644
index 30b59be..0000000
--- a/FP/migrations/insert.sql
+++ /dev/null
@@ -1,37 +0,0 @@
-insert into "user" (chat_id, username, first_name, last_name)
-values (42, 'testUser42', 'test', 'testov'),
- (34, 'testUser34', 'test', 'testov'),
- (65, 'testUser65', 'test', 'testov'),
- (45, 'testUser45', 'test', 'testov'),
- (523, 'testUser523', 'test', 'testov'),
- (645, 'testUser645', 'test', 'testov'),
- (7452, 'testUser7452', 'test', 'testov'),
- (44562, 'testUser44562', 'test', 'testov'),
- (423452, 'testUser423452', 'test', 'testov'),
- (2, 'testUser2', 'test', 'testov');
-
-insert into "link" (url, updated_at)
-values ('https://stackoverflow.com/questions/14141266/postgresql-foreign-key-on-delete-cascade', '2022-05-19 15:13:27'),
- ('https://github.com/linus/doctest','2022-01-31 13:13:50'),
- ('https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file','2023-03-27 09:58:45');
-
-insert into "user_link" (link_id, chat_id)
-values (1,42),
- (1,45),
- (1,2),
- (1,7452),
- (2,44562),
- (2,423452),
- (2,645),
- (2,523),
- (3,34),
- (3,65),
- (3,7452),
- (3,45),
- (4,42),
- (4,45),
- (4,2),
- (4,7452);
-
-
-
diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml
deleted file mode 100644
index c566afc..0000000
--- a/FP/migrations/master.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/FP/pom.xml b/FP/pom.xml
index a1baa3d..e38a124 100644
--- a/FP/pom.xml
+++ b/FP/pom.xml
@@ -1,85 +1,54 @@
-
- 4.0.0
- project
- project
- 0.0.1-SNAPSHOT
- pom
-
- bot
- link-parser
- scrapper
- scrapper-jooq
-
-
- 3.0.1
- 2022.0.0
- 3.10.1
- 23.1.0
- UTF-8
-
+
+
+ 4.0.0
-
-
-
- org.springframework.cloud
- spring-cloud-dependencies
- ${spring-cloud.version}
- pom
- import
-
+ org.example
-
- org.springframework.boot
- spring-boot-dependencies
- ${spring-boot.version}
- pom
- import
-
-
- org.junit.jupiter
- junit-jupiter-params
- ${junit.version}
- test
-
-
- org.mockito
- mockito-core
- ${mockito.version}
- test
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
- org.springframework.boot
- spring-boot-starter-test
- ${spring.test.version}
- test
-
-
-
+ FP
+
+ pom
+ 1.0
-
-
- org.jetbrains
- annotations
- ${annotations.version}
- provided
-
-
+
+ bot
+ link-parser
+ scrapper
+
+
+
+ UTF-8
+ 17
+ 17
+ 3.8.1
+ 3.0.1
+ 2022.0.0
+ 23.1.0
+ 5.8.1
+ 1.18.0
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+ false
+
+
org.springframework.boot
spring-boot-maven-plugin
- ${spring-boot.version}
+ ${spring-boot.version
true
@@ -108,16 +77,40 @@
17
true
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+ org.jetbrains
+ annotations
+ ${annotations.version}
+ provided
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
\ No newline at end of file
diff --git a/FP/scrapper-jooq/.classpath b/FP/scrapper-jooq/.classpath
deleted file mode 100644
index ead1d0f..0000000
--- a/FP/scrapper-jooq/.classpath
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/scrapper-jooq/.gitignore b/FP/scrapper-jooq/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/scrapper-jooq/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/scrapper-jooq/.project b/FP/scrapper-jooq/.project
deleted file mode 100644
index f320f87..0000000
--- a/FP/scrapper-jooq/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- scrapper-jooq
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 609d3ca..0000000
--- a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/resources=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/=UTF-8
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/FP/scrapper-jooq/pom.xml b/FP/scrapper-jooq/pom.xml
deleted file mode 100644
index b6f0785..0000000
--- a/FP/scrapper-jooq/pom.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
- 4.0.0
-
- project
- project
- 0.0.1-SNAPSHOT
-
- scrapper-jooq
-
- 17
- 17
- UTF-8
-
-
-
-
- org.springframework.boot
- spring-boot-starter-jooq
-
-
- org.jooq
- jooq-codegen
-
-
- org.jooq
- jooq-meta-extensions-liquibase
- 3.18.3
-
-
- org.jooq
- jooq-postgres-extensions
- 3.18.3
-
-
- org.liquibase
- liquibase-core
-
-
-
-
\ No newline at end of file
diff --git a/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/scrapper-jooq/src/main/java/JooqCodegen.java
deleted file mode 100644
index ee35d24..0000000
--- a/FP/scrapper-jooq/src/main/java/JooqCodegen.java
+++ /dev/null
@@ -1,49 +0,0 @@
-import org.jooq.codegen.GenerationTool;
-import org.jooq.meta.jaxb.Configuration;
-import org.jooq.meta.jaxb.Database;
-import org.jooq.meta.jaxb.Generate;
-import org.jooq.meta.jaxb.Generator;
-import org.jooq.meta.jaxb.Property;
-import org.jooq.meta.jaxb.Target;
-
-public class JooqCodegen {
- public static void main(String[] args) throws Exception {
- Database database = new Database()
- .withName("org.jooq.meta.extensions.liquibase.LiquibaseDatabase")
- .withProperties(
- new Property().withKey("rootPath").withValue("migrations"),
- new Property().withKey("scripts").withValue("master.xml")
- );
-
- Generate options = new Generate()
- .withGeneratedAnnotation(true)
- .withGeneratedAnnotationDate(false)
- .withNullableAnnotation(true)
- .withNullableAnnotationType("org.jetbrains.annotations.Nullable")
- .withNonnullAnnotation(true)
- .withNonnullAnnotationType("org.jetbrains.annotations.NotNull")
- .withJpaAnnotations(false)
- .withValidationAnnotations(true)
- .withSpringAnnotations(true)
- .withConstructorPropertiesAnnotation(true)
- .withConstructorPropertiesAnnotationOnPojos(true)
- .withConstructorPropertiesAnnotationOnRecords(true)
- .withFluentSetters(false)
- .withDaos(false)
- .withPojos(true);
-
- Target target = new Target()
- .withPackageName("ru.tinkoff.edu.java.scrapper.domain.jooq")
- .withDirectory("scrapper/src/main/java");
-
- Configuration configuration = new Configuration()
- .withGenerator(
- new Generator()
- .withDatabase(database)
- .withGenerate(options)
- .withTarget(target)
- );
-
- GenerationTool.generate(configuration);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/.classpath b/FP/scrapper/.classpath
deleted file mode 100644
index a08fc4f..0000000
--- a/FP/scrapper/.classpath
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/scrapper/.gitignore b/FP/scrapper/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/scrapper/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/scrapper/.project b/FP/scrapper/.project
deleted file mode 100644
index d56fd66..0000000
--- a/FP/scrapper/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- scrapper
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/scrapper/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/scrapper/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,6 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/java=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/=UTF-8
diff --git a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index 1b0c4fa..bbd37fb 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -2,27 +2,38 @@
- 4.0.0
- project
- project
- 0.0.1-SNAPSHOT
-
+ org.example
+ FP
+ 1.0
+
+
+ 4.0.0
+
+ scrapper
- scrapper
+
+ 3.0.1
+ 2.7.6
+
+
- org.springframework.boot
- spring-boot-starter-web
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.0.2
+
org.springframework.boot
spring-boot-starter-validation
+ ${starter-validation.version}
org.springframework.boot
- spring-boot-starter-webflux
+ spring-boot-starter-web
+ ${starter-web.version}
org.springframework.boot
@@ -45,25 +56,32 @@
lombok
true
+
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.0.2
+ org.example
+ link-parser
+ 1.0
+ compile
+
+
- ru.tinkoff.edu
- link-parser
- 1.0-SNAPSHOT
+ org.springframework.boot
+ spring-boot-starter-webflux
+ 3.0.5
+
+
+
+ org.example
+ bot
+ 1.0
+ compile
org.testcontainers
junit-jupiter
test
-
- org.springframework.boot
- spring-boot-starter-test
-
org.testcontainers
postgresql
@@ -74,6 +92,7 @@
liquibase-core
test
+
org.springframework.boot
spring-boot-starter-jdbc
@@ -84,37 +103,14 @@
runtime
- org.jooq
- jooq
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
+ org.junit.jupiter
+ junit-jupiter
+ test
- org.springframework.boot
- spring-boot-starter-amqp
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
index fef7338..959ba70 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -1,22 +1,21 @@
package ru.tinkoff.edu.java.scrapper;
import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
-import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl;
-
@SpringBootApplication
@EnableConfigurationProperties(ApplicationConfig.class)
-@EnableScheduling
+@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class ScrapperApplication {
- public static void main(String[] args) {
+
+ public static void main(String[] args) {
var ctx = SpringApplication.run(ScrapperApplication.class, args);
ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
- }
-}
\ No newline at end of file
+ System.out.println("----------------------------------------------------------------");
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
deleted file mode 100644
index 2e1aacf..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.advice;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import org.springframework.web.client.HttpClientErrorException;
-import ru.tinkoff.edu.java.scrapper.dto.ApiErrorResponse;
-import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
-import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
-import ru.tinkoff.edu.java.scrapper.exception.LinkIsAlreadyAddedException;
-import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
-
-import java.util.Arrays;
-
-@RestControllerAdvice
-public class AppExceptionHandler {
-
- @ExceptionHandler({LinkNotFoundException.class, ChatNotFoundException.class})
- @ResponseStatus(value = HttpStatus.NOT_FOUND)
- public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) {
- return new ApiErrorResponse(
- "Error", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
- }
-
-
- @ExceptionHandler({ChatAlreadyExistException.class, LinkIsAlreadyAddedException.class})
- @ResponseStatus(value = HttpStatus.BAD_REQUEST)
- public ApiErrorResponse handleBadRequestExceptions(RuntimeException exception) {
- return new ApiErrorResponse(
- "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new));
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
new file mode 100644
index 0000000..c4ad690
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
@@ -0,0 +1,44 @@
+package ru.tinkoff.edu.java.scrapper.api;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.tinkoff.edu.java.scrapper.api.model.*;
+import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService;
+
+import java.util.List;
+
+@RequestMapping("/links")
+@RestController
+public class ScrapperControllerLinks {
+ private final JdbcTemplate jdbcTemplate;
+ JdbcLinkService linkService = new JdbcLinkService();
+
+ public ScrapperControllerLinks(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @DeleteMapping
+ public void linksDelete(
+ @RequestHeader("Tg-Chat-Id") Long tgChatId,
+ @RequestBody RemoveLinkRequest removeLinkRequest
+ ) {
+ linkService.removeLink(jdbcTemplate, removeLinkRequest, tgChatId);
+ }
+
+ @GetMapping
+ public List linksGet(@RequestHeader("Tg-Chat-Id") Long tgChatId) {
+ return linkService.getLinks(jdbcTemplate, tgChatId);
+ }
+
+ @PostMapping
+ public void linksPost(
+ @RequestHeader("Tg-Chat-Id") Long tgChatId,
+ @RequestBody AddLinkRequest addLinkRequest
+ ) {
+ linkService.addLink(jdbcTemplate, addLinkRequest, tgChatId);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java
new file mode 100644
index 0000000..cc96bfb
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java
@@ -0,0 +1,29 @@
+package ru.tinkoff.edu.java.scrapper.api;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.bind.annotation.*;
+import ru.tinkoff.edu.java.scrapper.jdbc.JdbcChatService;
+import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService;
+
+@RequestMapping("/tg-chat")
+@RestController
+public class ScrapperControllerTg {
+
+ private final JdbcTemplate jdbcTemplate;
+ JdbcChatService chatService = new JdbcChatService();
+ public ScrapperControllerTg(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ @DeleteMapping("/{id}")
+ public void tgChatIdDelete(@PathVariable Long id) {
+ chatService.removeChat(jdbcTemplate, id);
+ }
+
+ @PostMapping("/{id}")
+ public void tgChatIdPost(@PathVariable long id) {
+ chatService.addChat(jdbcTemplate, id);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
new file mode 100644
index 0000000..7282291
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public record AddLinkRequest(String link) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java
new file mode 100644
index 0000000..eb09922
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public record ChatResponse(long chat_id, int id) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java
new file mode 100644
index 0000000..1f62147
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public record LinkChatResponse(int linkid, int chatid) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java
new file mode 100644
index 0000000..023172d
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public record LinkResponse(String url, int id) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java
new file mode 100644
index 0000000..9c9ed5b
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+import java.util.*;
+
+public record ListLinksResponse(List links, int size) {}
+
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java
new file mode 100644
index 0000000..3e2a8f0
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public record RemoveLinkRequest(String link) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
new file mode 100644
index 0000000..006d0b0
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
@@ -0,0 +1,4 @@
+package ru.tinkoff.edu.java.scrapper.api.model;
+
+public class UpdateService {
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
deleted file mode 100644
index 021e3ec..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.client;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
-import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
-import ru.tinkoff.edu.java.scrapper.exception.BotClientException;
-import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
-
-@Slf4j
-public class BotClient {
-
- @Value("${bot.baseurl}")
- private String botBaseUrl;
-
- private final WebClient webClient;
-
- public BotClient(WebClient webClient) {
- this.webClient = webClient;
- }
-
- public BotClient(String botBaseUrl) {
- this.webClient = WebClient.create(botBaseUrl);
- }
-
- public void updateLink(LinkUpdate request) {
- log.info("Sending update request to Bot");
- webClient.post().uri("/updates").bodyValue(request).exchangeToMono(r -> {
- if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) {
- throw new BotClientException("Чат с таким ID не зарегистрирован");
- }
- return Mono.empty();
- }).block();
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java
new file mode 100644
index 0000000..ee3e6b1
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java
@@ -0,0 +1,57 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
+
+import java.util.Objects;
+
+
+@Configuration
+public class ClientConfiguration {
+
+ private final String BASE_GIT_URL = "https://github.com/Ray-Not/JavaGuava";
+ private final String BASE_STACK_URL = "https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c";
+ @Value("${git.link}")
+ String gitLink;
+ @Value("${stack.link}")
+ String stackLink;
+ static WebClient.Builder builder = WebClient.builder();
+ LinkParser pars = new LinkParser();
+
+ @Bean
+ public WeatherRecord weatherClient() {
+ WeatherRecord weatherResponse = builder.build()
+ .get()
+ .uri("http://api.weatherapi.com/v1/current.json?key=3ff5d13401e44f30a14170938230204&q=Russia&aqi=no")
+ .retrieve()
+ .bodyToMono(WeatherRecord.class)
+ .block();
+ return weatherResponse;
+ }
+
+ public GitHubRecord gitHubClient(
+ String link
+ ) {
+ return builder.build()
+ .get()
+ .uri("https://api.github.com/repos/" + link)
+ .retrieve()
+ .bodyToMono(GitHubRecord.class)
+ .block();
+ }
+
+ public StackOverflowRecord stackOverflowClient(
+ String link
+ ) {
+ String params = "?order=desc&sort=activity&site=stackoverflow";
+ return builder.build()
+ .get()
+ .uri("https://api.stackexchange.com/2.3/questions/" + link + params)
+ .retrieve()
+ .bodyToMono(StackOverflowRecord.class)
+ .block();
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
deleted file mode 100644
index 156cf35..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.client;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.reactive.function.client.WebClient;
-import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
-import org.springframework.http.HttpStatus;
-import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
-
-public class GitHubClient {
-
-
- @Value("${gh.baseurl}")
- private String gitHubBaseUrl;
-
- private final WebClient webClient;
-
- //для использования baseUrl по умолчанию (берётся из properties)
- public GitHubClient() {
- this.webClient = WebClient.create(gitHubBaseUrl);
- }
-
-
- //можно указать базовый URL
- public GitHubClient(String baseUrl) {
- this.webClient = WebClient.create(baseUrl);
- }
-
-
- public GitHubResponse fetchRepo(String owner, String repo) {
- GitHubResponse response = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{
- if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API");
- return r.bodyToMono(GitHubResponse.class);
- }).block();
-
- return response;
-
- }
- public void strFetchRepo(String owner, String repo){
- String strReponse = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{
- if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API");
- return r.bodyToMono(String.class);
- }).block();
-
- System.out.println(strReponse);
-
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java
new file mode 100644
index 0000000..97ef980
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java
@@ -0,0 +1,19 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.OffsetDateTime;
+import java.util.HashMap;
+
+public record GitHubRecord(
+ @JsonProperty("full_name") String name,
+ @JsonProperty("owner") HashMap owner,
+ @JsonProperty("private") boolean is_private,
+ @JsonProperty("node_id") String node_id,
+ @JsonProperty("html_url") String url,
+ @JsonProperty("description") String description,
+ @JsonProperty("created_at") OffsetDateTime createdAt,
+ @JsonProperty("updated_at") OffsetDateTime updatedAt,
+ @JsonProperty("pushed_at") OffsetDateTime pushedAt
+
+) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
deleted file mode 100644
index 6651dd9..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.client;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.http.HttpStatus;
-import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
-import ru.tinkoff.edu.java.scrapper.dto.StackOverflowResponse;
-import ru.tinkoff.edu.java.scrapper.exception.BadResponseFromApiException;
-import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
-import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
-import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
-
-public class StackOverflowClient {
-
- @Value("${so.baseurl}")
- private String stackOverflowBaseUrl;
-
- private final WebClient webClient;
-
-
- //для использования baseUrl по умолчанию (берётся из properties)
- public StackOverflowClient() {
- this.webClient = WebClient.create(stackOverflowBaseUrl);
- }
-
-
- //можно указать базовый URL
- public StackOverflowClient(String baseUrl) {
- this.webClient = WebClient.create(baseUrl);
- }
-
- public StackOverflowItem fetchQuestion(long id) {
-
- StackOverflowResponse response = webClient.get().uri("/questions/{id}?order=desc&sort=activity&site=stackoverflow", id).exchangeToMono(r->{
- if (!r.statusCode().equals(HttpStatus.OK)) throw new StackOverflowRequestException("Error with request to SO API");
- return r.bodyToMono(StackOverflowResponse.class);
- }).block();
-
- if (response == null || response.items().size() == 0)
- throw new BadResponseFromApiException("API StackOverflow returned bad response");
-
- return response.items().get(0);
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java
new file mode 100644
index 0000000..6013400
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java
@@ -0,0 +1,10 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public record StackOverflowRecord(
+ @JsonProperty("has_more") boolean has_more,
+ @JsonProperty("items") List owner
+) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java
new file mode 100644
index 0000000..5ee9adc
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.client;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.HashMap;
+import java.util.List;
+
+public record WeatherRecord(
+ @JsonProperty("location") HashMap location,
+ @JsonProperty("current") HashMap current
+ ) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
index 856e54e..3a82d60 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -2,25 +2,14 @@
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
import ru.tinkoff.edu.java.scrapper.schedule.Scheduler;
@Validated
@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
-public record ApplicationConfig(@NotNull String test,
- @NotNull Scheduler scheduler,
- @NotNull AccessType dataBaseAccessType,
- @NotNull Boolean useQueue,
- String queueName,
- String exchangeName,
- String routingKey){
-
- @Bean
- public long schedulerIntervalMs(ApplicationConfig config) {
- return config.scheduler().interval().toMillis();
- }
- public enum AccessType {
- JDBC, JPA, JOOQ
- }
-}
\ No newline at end of file
+@EnableScheduling
+public record ApplicationConfig(
+ @NotNull String test,
+ @NotNull Scheduler scheduler
+) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
deleted file mode 100644
index 8694acf..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import org.springframework.web.reactive.function.client.WebClient;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-
-@Configuration
-public class ClientConfiguration {
-
- @Value("${gh.baseurl}")
- private String gitHubBaseUrl;
-
- @Value("${so.baseurl}")
- private String stackOverflowBaseUrl;
-
- @Value("${bot.baseurl}")
- private String botBaseUrl;
-
-
- //Регистрируем клиентов как бины
- @Bean
- public GitHubClient gitHubClientService() {
- return new GitHubClient(gitHubBaseUrl);
- }
-
- @Bean
- public StackOverflowClient stackOverflowClientService() {
- return new StackOverflowClient(stackOverflowBaseUrl);
- }
- @Bean
- public WebClient ghWebClient(){
- return WebClient.create(gitHubBaseUrl);
- }
-
- @Bean
- public WebClient soWebClient(){
- return WebClient.create(stackOverflowBaseUrl);
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
deleted file mode 100644
index df6780e..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.function.client.WebClient;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-
-@Configuration
-@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "false")
-public class HTTPConfiguration {
-
- @Value("${bot.baseurl}")
- private String botBaseUrl;
-
-
- @Bean
- public BotClient botClient(){return new BotClient(botBaseUrl);}
-
- @Bean
- public WebClient botWebClient(){
- return WebClient.create(botBaseUrl);
- }
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
deleted file mode 100644
index e400f15..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
-
-@Configuration
-public class LinkParserConfiguration {
-
- @Bean
- public Link_Parser linkParser(){
- return new Link_Parser();
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
index d8b1217..b0d9449 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -1,15 +1,17 @@
package ru.tinkoff.edu.java.scrapper.configuration;
import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.scrapper.service.ScrapperQueueProducer;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
-@Configuration
-@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "true")
+@SpringBootApplication
public class RabbitMQConfiguration {
private final ApplicationConfig config;
@@ -17,7 +19,6 @@ public class RabbitMQConfiguration {
public RabbitMQConfiguration(ApplicationConfig config) {
this.config = config;
}
-
@Bean
Queue queue() {
return QueueBuilder.durable(config.queueName())
@@ -41,10 +42,8 @@ public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
-
@Bean
public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) {
return new ScrapperQueueProducer(rabbitTemplate, config);
}
-
-}
\ No newline at end of file
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
deleted file mode 100644
index d70f747..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.jdbc.core.JdbcTemplate;
-import ru.tinkoff.edu.java.link_parser.Link_Parser;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
-import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
-import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
-import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
-
-@Configuration
-@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jdbc")
-public class JdbcAccessConfiguration {
-
- @Bean
- public LinkRowMapper linkRowMapper() {
- return new LinkRowMapper();
- }
-
- @Bean
- public SubscriptionRowMapper subscriptionRowMapper() {
- return new SubscriptionRowMapper();
- }
-
- @Bean
- public UserRowMapper userRowMapper() {
- return new UserRowMapper();
- }
-
- @Bean
- public LinkRepository linkRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) {
- return new LinkJdbcTemplateRepository(jdbcTemplate, linkRowMapper);
- }
-
- @Bean
- public SubscriptionRepository subscriptionRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper) {
- return new SubscriptionJdbcTemplateRepository(jdbcTemplate, subscriptionRowMapper, linkRowMapper());
- }
-
- @Bean
- public UserRepository userRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) {
- return new UserJdbcTemplateRepository(jdbcTemplate, userRowMapper);
- }
-
- @Bean
- public LinkUpdateService linkUpdateService(
- LinkRepository linkRepository,
- SubscriptionRepository subscriptionRepository,
- Link_Parser linkParser,
- GitHubClient gitHubClient,
- StackOverflowClient stackOverflowClient,
- BotClient botClient
- ) {
- return new LinkUpdateServiceImpl(
- linkRepository,
- subscriptionRepository,
- linkParser,
- gitHubClient,
- stackOverflowClient,
- botClient);
- }
-
- @Bean
- public SubscriptionService subscriptionService(
- LinkRepository linkRepository,
- SubscriptionRepository subscriptionRepository
- ) {
- return new SubscriptionServiceImpl(
- linkRepository,
- subscriptionRepository);
- }
-
- @Bean
- public TgChatService tgChatService(
- UserRepository userRepository,
- SubscriptionRepository subscriptionRepository
- ) {
- return new TgChatServiceImpl(
- userRepository,
- subscriptionRepository);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
deleted file mode 100644
index 47864de..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
-
-import org.jooq.DSLContext;
-import org.jooq.impl.DSL;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.link_parser.Link_Parser;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jooq.LinkJooqRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jooq.SubscriptionJooqRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jooq.UserJooqRepository;
-import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
-@Configuration
-@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jooq")
-public class JooqAccessConfiguration {
-
-
- @Bean
- public LinkRepository linkRepository(DSLContext dslContext){
- return new LinkJooqRepository(dslContext);
- }
-
- @Bean
- public SubscriptionRepository subscriptionRepository(DSLContext dslContext){
- return new SubscriptionJooqRepository(dslContext);
- }
-
-
- @Bean
- public UserRepository userRepository(DSLContext dslContext){
- return new UserJooqRepository(dslContext);
- }
-
- @Bean
- public LinkUpdateService linkUpdateService(
- LinkRepository linkRepository,
- SubscriptionRepository subscriptionRepository,
- LinkParser linkParser,
- GitHubClient gitHubClient,
- StackOverflowClient stackOverflowClient,
- BotClient botClient
- ) {
- return new LinkUpdateServiceImpl(
- linkRepository,
- subscriptionRepository,
- linkParser,
- gitHubClient,
- stackOverflowClient,
- botClient);
- }
-
- @Bean
- public SubscriptionService subscriptionService(
- LinkRepository linkRepository,
- SubscriptionRepository subscriptionRepository
- ) {
- return new SubscriptionServiceImpl(
- linkRepository,
- subscriptionRepository);
- }
-
- @Bean
- public TgChatService tgChatService(
- UserRepository userRepository,
- SubscriptionRepository subscriptionRepository
- ) {
- return new TgChatServiceImpl(
- userRepository,
- subscriptionRepository);
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
deleted file mode 100644
index ff97aba..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.configuration.database.acess;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.link_parser.Link_Parser;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
-import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaLinkUpdateServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl;
-import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl;
-
-@Configuration
-@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jpa")
-public class JpaAccessConfiguration {
-
- @Bean
- public LinkUpdateService linkUpdateService(
- JpaLinkRepository linkRepository,
- Link_Parser linkParser,
- GitHubClient gitHubClient,
- StackOverflowClient stackOverflowClient,
- BotClient botClient) {
- return new JpaLinkUpdateServiceImpl(
- linkRepository,
- linkParser,
- gitHubClient,
- stackOverflowClient,
- botClient
- );
- }
-
- @Bean
- public SubscriptionService subscriptionService(
- JpaLinkRepository linkRepository,
- JpaUserRepository userRepository) {
- return new JpaSubscriptionServiceImpl(
- linkRepository,
- userRepository
- );
- }
-
- @Bean
- public TgChatService tgChatService(
- JpaUserRepository userRepository) {
- return new JpaTgChatServiceImpl(
- userRepository
- );
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
deleted file mode 100644
index 97985ba..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-public record AddLinkRequest(String link) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
deleted file mode 100644
index 7c065be..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-public record ApiErrorResponse(String description, String code, String exceptionName,
- String exceptionMessage, String[] stacktrace) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
deleted file mode 100644
index 8f6367c..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.time.OffsetDateTime;
-
-public record GitHubResponse(@JsonProperty("pushed") OffsetDateTime pushedAt,
- @JsonProperty("updated") OffsetDateTime updatedAt,
- @JsonProperty("full_name") String fullName,
- @JsonProperty("description") String description,
- @JsonProperty("forks_count") int forksCount
-) {
-
-
-@Override
-public String toString() {
- return "GitHubResponse{" +
- "pushedAt=" + pushedAt +
- ", updatedAt=" + updatedAt +
- ", fullName='" + fullName + '\'' +
- ", description='" + description + '\'' +
- ", forksCount=" + forksCount +
- '}';
-}
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
deleted file mode 100644
index cadc95f..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-public record LinkResponse(long id, String url) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
deleted file mode 100644
index 1b6410a..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
deleted file mode 100644
index a142f3a..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import java.util.List;
-
-public record ListLinkResponse(List links, int size) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
deleted file mode 100644
index 09a3867..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-public record RemoveLinkRequest(String link) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
deleted file mode 100644
index 9e2f0b9..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.time.OffsetDateTime;
-public record StackOverflowItem(@JsonProperty("last_edit_date") OffsetDateTime lastActivityDate,
- @JsonProperty("last_activity_date") OffsetDateTime lastEditDate) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
deleted file mode 100644
index 50227fc..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.time.OffsetDateTime;
-import java.util.List;
-public record StackOverflowResponse(List items) {
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
deleted file mode 100644
index 58d769c..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public record UserAddDto(@JsonProperty("username") String username,
- @JsonProperty("first_name") String firstName,
- @JsonProperty("last_name") String lastName) {
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
deleted file mode 100644
index d5be7a4..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class BadResponseFromApiException extends RuntimeException {
-
- public BadResponseFromApiException() {
- }
-
- public BadResponseFromApiException(String message) {
- super(message);
- }
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
deleted file mode 100644
index 9ee4d12..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class BotClientException extends RuntimeException{
-
- public BotClientException() {
- }
-
- public BotClientException(String message) {
- super(message);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
deleted file mode 100644
index 5dd1124..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class ChatAlreadyExistException extends RuntimeException {
-
- public ChatAlreadyExistException() {
- }
-
- public ChatAlreadyExistException(String message) {
- super(message);
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
deleted file mode 100644
index 29dc8cf..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class ChatNotFoundException extends RuntimeException {
-
- public ChatNotFoundException(String message) {
- super(message);
- }
-
- public ChatNotFoundException() {
- }
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
deleted file mode 100644
index 9bf30c3..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class GitHubRequestException extends RuntimeException{
-
- public GitHubRequestException() {
- }
-
- public GitHubRequestException(String message) {
- super(message);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
deleted file mode 100644
index 58a7dfb..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class LinkIsAlreadyAddedException extends RuntimeException {
-
-
- public LinkIsAlreadyAddedException(String message) {
- super(message);
- }
-
- public LinkIsAlreadyAddedException() {
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
deleted file mode 100644
index e5c5c62..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class LinkNotFoundException extends RuntimeException {
-
- public LinkNotFoundException() {
- }
-
- public LinkNotFoundException(String message) {
- super(message);
- }
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
deleted file mode 100644
index e714110..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.exception;
-
-public class StackOverflowRequestException extends RuntimeException{
-
- public StackOverflowRequestException() {
- super();
- }
-
- public StackOverflowRequestException(String message) {
- super(message);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java
new file mode 100644
index 0000000..55fc0c9
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java
@@ -0,0 +1,78 @@
+package ru.tinkoff.edu.java.scrapper.exceptions;
+
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MissingRequestHeaderException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryNotExsistException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.NullLinkException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException;
+import ru.tinkoff.edu.java.scrapper.exceptions.model.ApiErrorResponse;
+
+@RestControllerAdvice
+public class ScrapperExceptionHandler {
+
+ private ApiErrorResponse setException(Exception exception) {
+ String[] parsing_class = exception.getClass().toString().split("\\.");
+ String class_name = parsing_class[parsing_class.length - 1];
+ ApiErrorResponse errorObj = new ApiErrorResponse(
+ exception.getMessage(),
+ class_name,
+ exception.toString()
+ );
+ return errorObj;
+ }
+
+ @ExceptionHandler(HttpMessageNotReadableException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse MessageNotReadable(HttpMessageNotReadableException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse MethodNotSupported(HttpRequestMethodNotSupportedException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(MissingRequestHeaderException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse MissingRequestHeader(MissingRequestHeaderException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse ArgumentTypeMismatch(MethodArgumentTypeMismatchException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(NullLinkException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ApiErrorResponse NullLink(NullLinkException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(UnauthorizationException.class)
+ @ResponseStatus(HttpStatus.UNAUTHORIZED)
+ public ApiErrorResponse Unauthorization(UnauthorizationException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(EntryExsistException.class)
+ @ResponseStatus(HttpStatus.FOUND)
+ public ApiErrorResponse EntryExsist(EntryExsistException e) {
+ return setException(e);
+ }
+
+ @ExceptionHandler(EntryNotExsistException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ApiErrorResponse EntryNotExsist(EntryNotExsistException e) {
+ return setException(e);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java
new file mode 100644
index 0000000..fca436d
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions;
+
+public class EntryExsistException extends RuntimeException {
+
+ public EntryExsistException() {
+ super();
+ }
+
+ public EntryExsistException(String s) {
+ super(s);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java
new file mode 100644
index 0000000..e25ba25
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions;
+
+public class EntryNotExsistException extends RuntimeException {
+
+ public EntryNotExsistException() {
+ super();
+ }
+
+ public EntryNotExsistException(String s) {
+ super(s);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java
new file mode 100644
index 0000000..cd7baa2
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions;
+
+public class NullDBException extends RuntimeException {
+
+ public NullDBException() {
+ super();
+ }
+
+ public NullDBException(String s) {
+ super(s);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java
new file mode 100644
index 0000000..00ddf4e
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions;
+
+public class NullLinkException extends RuntimeException {
+
+ public NullLinkException() {
+ super();
+ }
+
+ public NullLinkException(String s) {
+ super(s);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java
new file mode 100644
index 0000000..2135ddc
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java
@@ -0,0 +1,12 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions;
+
+public class UnauthorizationException extends RuntimeException {
+
+ public UnauthorizationException() {
+ super();
+ }
+
+ public UnauthorizationException(String s) {
+ super(s);
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java
new file mode 100644
index 0000000..0a8994e
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java
@@ -0,0 +1,7 @@
+package ru.tinkoff.edu.java.scrapper.exceptions.model;
+
+public record ApiErrorResponse(
+ String exceptionMessage,
+ String description,
+ String exceptionName
+) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java
new file mode 100644
index 0000000..c8757c8
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.scrapper.jdbc;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
+
+public class JdbcChatService implements LinkOperations, ChatOperations, LinkChatOperations {
+ public void addChat(JdbcTemplate jdbc, long chat) {
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id != 0) {
+ throw new EntryExsistException("Вы уже зарегистрированы");
+ } else {
+ i_addChat(jdbc, chat);
+ }
+ }
+
+ public void removeChat(JdbcTemplate jdbc, long chat) {
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id != 0) {
+ i_removeChat(jdbc, chat);
+ i_removeLinkChatAllChat(jdbc, chat_id);
+ } else throw new EntryNotExsistException("Пользователь не найден");
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
new file mode 100644
index 0000000..6eb52b5
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
@@ -0,0 +1,75 @@
+package ru.tinkoff.edu.java.scrapper.jdbc;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
+import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest;
+import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JdbcLinkService implements LinkOperations, ChatOperations, LinkChatOperations {
+ public void addLink(JdbcTemplate jdbc, AddLinkRequest link, Long chat) {
+ ClientConfiguration client = new ClientConfiguration();
+ LinkParser parser = new LinkParser();
+ if (parser.getLink(link.link()) == null) {
+ throw new NullLinkException("Ссылка невалидна");
+ }
+ try {
+ client.gitHubClient(parser.getLink(link.link()));
+ } catch (WebClientResponseException e) {
+ try {
+ client.stackOverflowClient(parser.getLink(link.link()));
+ } catch (WebClientResponseException ex) {
+ throw new NullLinkException("Ссылка не поддерживается, доступны: Git, StackOverFlow");
+ }
+ }
+ int link_id = i_findLink(jdbc, link.link());
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
+ }
+ if (link_id == 0) {
+ i_addLink(jdbc, link);
+ link_id = i_findLink(jdbc, link.link());
+ }
+ if (i_findLinkChat(jdbc, link_id, chat_id)) {
+ addLinkChat(jdbc, link_id, chat_id);
+ }else throw new EntryExsistException("Ссылка уже добавлена!");
+ }
+
+ public void removeLink(JdbcTemplate jdbc, RemoveLinkRequest link, long chat) {
+ int link_id = i_findLink(jdbc, link.link());
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
+ }
+ if (link_id != 0) {
+ i_removeLink(jdbc, link);
+ } else throw new EntryNotExsistException("Ссылки не существует");
+ if (!i_findLinkChat(jdbc, link_id, chat_id)) {
+ i_removeLinkChat(jdbc, link_id, chat_id);
+ }
+ }
+
+ public List getLinks(JdbcTemplate jdbc, long chat) {
+ int i;
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
+ }
+ ArrayList link_list = new ArrayList<>();
+ for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++){
+ link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid());
+ }
+ return i_findAllLink(jdbc, link_list);
+ }
+
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
new file mode 100644
index 0000000..8db6ed9
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
@@ -0,0 +1,25 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+import javax.sql.DataSource;
+@Configuration
+public class jdbcBean {
+ @Bean
+ public DataSource dataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName("org.postgresql.Driver");
+ dataSource.setUrl("jdbc:postgresql://localhost:5432/scrapper");
+ dataSource.setUsername("scrap_user");
+ dataSource.setPassword("hard_password");
+
+ return dataSource;
+ }
+ @Bean
+ public JdbcTemplate jdbcTemplate () {
+ return new JdbcTemplate (dataSource());
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
new file mode 100644
index 0000000..b979f13
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.mappers;
+
+import org.springframework.jdbc.core.RowMapper;
+import ru.tinkoff.edu.java.scrapper.api.model.ChatResponse;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class ChatMapper implements RowMapper {
+ @Override
+ public ChatResponse mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new ChatResponse(rs.getLong("tg_chat_id"), rs.getInt("id"));
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
new file mode 100644
index 0000000..e9e98e7
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
@@ -0,0 +1,14 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.mappers;
+
+import org.springframework.jdbc.core.RowMapper;
+import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class LinkChatMapper implements RowMapper {
+ @Override
+ public LinkChatResponse mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new LinkChatResponse(rs.getInt("linkid"), rs.getInt("chatid"));
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
new file mode 100644
index 0000000..ac50329
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
@@ -0,0 +1,15 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.mappers;
+
+
+import org.springframework.jdbc.core.RowMapper;
+import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class LinkMapper implements RowMapper {
+ @Override
+ public LinkResponse mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new LinkResponse(rs.getString("link"), rs.getInt("id"));
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java
new file mode 100644
index 0000000..3c36c88
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java
@@ -0,0 +1,50 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.operations;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.scrapper.jdbc.mappers.ChatMapper;
+import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper;
+
+public interface ChatOperations {
+ default void i_addChat(
+ JdbcTemplate jdbcTemplate,
+ long chat
+ ) {
+ int chat_id;
+
+ try {
+ chat_id = jdbcTemplate.query(
+ "SELECT * FROM tgchats WHERE id=(SELECT MAX(id) FROM tgchats)",
+ new ChatMapper()
+ ).get(0).id() + 1;
+ } catch (IndexOutOfBoundsException e) {
+ chat_id = 1;
+ }
+
+ jdbcTemplate.update("INSERT INTO tgchats VALUES(?, ?)", chat_id, chat);
+ }
+
+ default void i_removeChat(
+ JdbcTemplate jdbcTemplate,
+ long chat
+ ){
+ String query = "DELETE FROM tgchats WHERE tg_chat_id=(%d)";
+ query = query.formatted(chat);
+ jdbcTemplate.update(query);
+ }
+
+ default int i_findChat(
+ JdbcTemplate jdbcTemplate,
+ long chat
+ ){
+ try {
+ String query = "SELECT * FROM tgchats WHERE tg_chat_id=(%d)";
+ query = query.formatted(chat);
+ return jdbcTemplate.query(
+ query,
+ new ChatMapper()
+ ).get(0).id();
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return 0;
+ }
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
new file mode 100644
index 0000000..29cfe7d
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
@@ -0,0 +1,61 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.operations;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse;
+import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkChatMapper;
+
+import java.util.List;
+
+public interface LinkChatOperations {
+ default void addLinkChat(
+ JdbcTemplate jdbcTemplate,
+ int link_id,
+ int chat_id
+ ) {
+ jdbcTemplate.update("INSERT INTO links_tgchats VALUES(?, ?)", link_id, chat_id);
+ }
+
+ default void i_removeLinkChat(
+ JdbcTemplate jdbcTemplate,
+ int link_id,
+ int chat_id
+ ) {
+ String query = "DELETE FROM links_tgchats WHERE linkid=(%d) AND chatid=(%d)";
+ query = query.formatted(link_id, chat_id);
+ jdbcTemplate.update(query);
+ }
+
+ default void i_removeLinkChatAllChat(
+ JdbcTemplate jdbcTemplate,
+ int chat_id
+ ) {
+ String query = "DELETE FROM links_tgchats WHERE chatid=(%d)";
+ query = query.formatted(chat_id);
+ jdbcTemplate.update(query);
+ }
+
+ default boolean i_findLinkChat(
+ JdbcTemplate jdbcTemplate,
+ int link_id,
+ int chat_id
+ ){
+ try {
+ String query = "SELECT * FROM links_tgchats WHERE linkid=(%d) AND chatid=(%d)";
+ query = query.formatted(link_id, chat_id);
+ jdbcTemplate.query(query, new LinkChatMapper()).get(0);
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return true;
+ }
+ return false;
+ }
+
+ default List i_get_all_links_for_chat(JdbcTemplate jdbcTemplate, int chat_id) {
+ try {
+ String query = "SELECT * FROM links_tgchats WHERE chatid=(%d)";
+ query = query.formatted(chat_id);
+ return jdbcTemplate.query(query, new LinkChatMapper());
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return null;
+ }
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
new file mode 100644
index 0000000..ad282fe
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
@@ -0,0 +1,83 @@
+package ru.tinkoff.edu.java.scrapper.jdbc.operations;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest;
+import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public interface LinkOperations {
+ default void i_addLink(
+ JdbcTemplate jdbcTemplate,
+ AddLinkRequest addLinkRequest
+ ) {
+ int link_id;
+
+ try {
+ link_id = jdbcTemplate.query(
+ "SELECT * FROM links WHERE id=(SELECT MAX(id) FROM links)",
+ new LinkMapper()
+ ).get(0).id() + 1;
+ } catch (IndexOutOfBoundsException e) {
+ link_id = 1;
+ }
+
+ jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, addLinkRequest.link());
+ }
+
+ default void i_removeLink(
+ JdbcTemplate jdbcTemplate,
+ RemoveLinkRequest removeLinkRequest
+ ){
+ String query = "DELETE FROM links where link IN ('%s')";
+ query = query.formatted(removeLinkRequest.link());
+ jdbcTemplate.update(query);
+ }
+
+ default List i_findAllLink(
+ JdbcTemplate jdbcTemplate,
+ ArrayList links_ids
+ ){
+ try {
+ String ids = Arrays.toString(links_ids.toArray());
+ ids = ids.substring(1, ids.length() - 1);
+ String query = "SELECT * FROM links WHERE id IN (%s)";
+ query = query.formatted(ids);
+ return jdbcTemplate.query(
+ query,
+ new LinkMapper()
+ );
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return null;
+ }
+ }
+
+ default int i_findLink(
+ JdbcTemplate jdbcTemplate,
+ String link
+ ){
+ try {
+ String query = "SELECT * FROM links WHERE link IN ('%s')";
+ query = query.formatted(link);
+ return jdbcTemplate.query(
+ query,
+ new LinkMapper()
+ ).get(0).id();
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return 0;
+ }
+ }
+
+ default List i_getAllIds(JdbcTemplate jdbcTemplate) {
+ try {
+ String query = "SELECT * FROM links";
+ return jdbcTemplate.query(query, new LinkMapper());
+ } catch (IndexOutOfBoundsException e) { // Если значение не нашлось
+ return null;
+ }
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
deleted file mode 100644
index 72df1e2..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.mapper;
-
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import ru.tinkoff.edu.java.scrapper.model.User;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-@Component
-public class LinkRowMapper implements RowMapper {
-
- @Override
- public Link mapRow(ResultSet rs, int rowNum) throws SQLException {
- Link link = new Link();
- link.setId(rs.getLong("id"));
- link.setUrl(rs.getString("url"));
- link.setCheckedAt(rs.getTimestamp("checked_at"));
- link.setGhPushedAt(rs.getTimestamp("gh_pushed_at"));
- link.setGhDescription(rs.getString("gh_description"));
- link.setGhForksCount(rs.getInt("gh_forks_count"));
- link.setSoAnswerCount(rs.getInt("so_answer_count"));
- link.setSoLastEditDate(rs.getTimestamp("so_last_edit_date"));
- return link;
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
deleted file mode 100644
index bd76b2b..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.mapper;
-
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.scrapper.model.Relation;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-@Component
-public class SubscriptionRowMapper implements RowMapper {
-
- @Override
- public Relation mapRow(ResultSet rs, int rowNum) throws SQLException {
- Relation relation = new Relation();
- relation.setLinkId(rs.getLong("link_id"));
- relation.setChatId(rs.getLong("chat_id"));
-
- return relation;
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
deleted file mode 100644
index 4597040..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.mapper;
-
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.scrapper.model.User;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-
-@Component
-public class UserRowMapper implements RowMapper {
-
-
- @Override
- public User mapRow(ResultSet rs, int rowNum) throws SQLException {
- User user = new User();
- user.setChatId(rs.getLong("chat_id"));
- user.setUsername(rs.getString("username"));
- user.setFirstName(rs.getString("first_name"));
- user.setLastName(rs.getString("last_name"));
- return user;
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
deleted file mode 100644
index 59b4a92..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.model.commonDto;
-
-import lombok.Data;
-import java.sql.Timestamp;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-
-@Data
-public class Link {
-
-
- private Long id;
- private String url;
- private Timestamp checkedAt;
- private Timestamp ghPushedAt;
- private String ghDescription;
- private int ghForksCount;
- private Timestamp soLastEditDate;
- private int soAnswerCount;
- public static Link fromEntity(LinkEntity linkEntity){
- Link link = new Link();
- link.setId(linkEntity.getId());
- link.setUrl(linkEntity.getUrl());
- link.setCheckedAt(linkEntity.getCheckedAt());
- link.setGhDescription(linkEntity.getGhDescription());
- link.setGhPushedAt(linkEntity.getGhPushedAt());
- Integer forks = linkEntity.getGhForksCount(); if (forks == null) link.setGhForksCount(0); else link.setGhForksCount(forks);
- Integer answers = linkEntity.getSoAnswerCount(); if (answers == null) link.setSoAnswerCount(0); else link.setSoAnswerCount(answers);
- link.setSoLastEditDate(linkEntity.getSoLastEditDate());
- return link;
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
deleted file mode 100644
index 74f7693..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.model.commonDto;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
-
-@Data
-@NoArgsConstructor
-public class User {
-
- public User(Long chatId, String username, String firstName, String lastName) {
- this.chatId = chatId;
- this.username = username;
- this.firstName = firstName;
- this.lastName = lastName;
- }
-
- private Long chatId;
- private String username;
- private String firstName;
- private String lastName;
- public static UserEntity toEntity(User user){
- UserEntity userEntity = new UserEntity();
-
- userEntity.setChatId(user.getChatId());
- userEntity.setUsername(user.getUsername());
- userEntity.setFirstName(user.getFirstName());
- userEntity.setLastName(user.getLastName());
-
- return userEntity;
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
deleted file mode 100644
index abe684a..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq;
-
-import lombok.Data;
-
-@Data
-public class Relation {
-
- private Long linkId;
- private Long chatId;
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
deleted file mode 100644
index bd4469b..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.model.jpa;
-
-import jakarta.persistence.*;
-import lombok.Data;
-import java.sql.Timestamp;
-import java.util.List;
-
-@Entity
-@Table(name = "link")
-@Data
-public class LinkEntity {
-
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- @Column(name = "url", unique = true, nullable = false)
- private String url;
-
- @Column(name = "checked_at", nullable = false)
- private Timestamp checkedAt;
-
- @Column(name = "gh_pushed_at")
- private Timestamp ghPushedAt;
-
- @Column(name = "gh_description")
- private String ghDescription;
-
- @Column(name = "gh_forks_count")
- private Integer ghForksCount;
-
- @Column(name = "so_last_edit_date")
- private Timestamp soLastEditDate;
-
- @Column(name = "so_answer_count")
- private Integer soAnswerCount;
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
deleted file mode 100644
index 8f49d40..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.model.jpa;
-
-import jakarta.persistence.*;
-import lombok.Data;
-import java.util.List;
-
-@Entity
-@Table(name = "\"user\"")
-@Data
-public class UserEntity {
-
- @Id
- @Column(name = "chat_id")
- private Long chatId;
-
- @Column(name = "username", unique = true, nullable = false)
- private String username;
-
- @Column(name = "first_name")
- private String firstName;
-
- @Column(name = "last_name")
- private String lastName;
-
- @ManyToMany(fetch = FetchType.LAZY)
- @JoinTable(name = "user_link",
- joinColumns = @JoinColumn(name = "chat_id"),
- inverseJoinColumns = @JoinColumn(name = "link_id"))
- private List links;
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
similarity index 95%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
index cf4a7ae..3507568 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
@@ -1,5 +1,3 @@
-package ru.tinkoff.edu.java.bot.service;
-
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
@@ -29,4 +27,4 @@ public void receiver(LinkUpdate update) {
}
-}
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
similarity index 50%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
index 91471de..84baa14 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
@@ -1,13 +1,14 @@
-package ru.tinkoff.edu.java.scrapper.service;
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
-import lombok.extern.slf4j.Slf4j;
+import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.stereotype.Service;
+import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
+
import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
-import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
-@Slf4j
-//бин регистрируется в конфиге, т.к. его не нужно инициализировать в случае общения по HTTP
-public class ScrapperQueueProducer implements UpdateNotificationService {
+@Service
+public class ScrapperQueueProducer {
private final AmqpTemplate rabbitTemplate;
@@ -19,8 +20,8 @@ public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig conf
this.config = config;
}
- public void updateLink(LinkUpdate update) {
+ public void send(LinkUpdate update) {
rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update);
- log.info("UpdateMessage " + update + " has been sent");
+ System.out.println("Mess update: " + update);
}
-}
\ No newline at end of file
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
deleted file mode 100644
index 38d0931..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbc;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.repository.LinkRepository;
-
-import java.sql.Timestamp;
-import java.util.List;
-
-@Slf4j
-public class LinkJdbcTemplateRepository implements LinkRepository {
-
-
- private final JdbcTemplate jdbcTemplate;
-
- private final LinkRowMapper linkRowMapper;
-
- public LinkJdbcTemplateRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) {
- this.jdbcTemplate = jdbcTemplate;
- this.linkRowMapper = linkRowMapper;
- }
-
-
- @Override
- public List findAll() {
- log.info("findAll() method invocation in linkRepo");
- String sql = "select * from link";
- return jdbcTemplate.query(sql, linkRowMapper);
- }
-
- @Override
- public Link findByUrl(String url) {
- log.info("findByUrl() method invocation in linkRepo");
- String sql = "select * from link where link.url = ?";
- List link = jdbcTemplate.query(sql, linkRowMapper, url);
- return link.size() == 0 ? null : link.get(0);
- }
-
- @Override
- public void add(Link link) {
- log.info("add() method invocation in linkRepo");
- String sql = "insert into link (url, updated_at) values(?, ?)";
- jdbcTemplate.update(sql, link.getUrl(), link.getUpdatedAt());
- }
-
-
- @Override
- public void updateDate(Link link) {
- log.info("updateDate() method invocation in linkRepo");
- String sql = "update link set updated_at = ? where id = ?";
- jdbcTemplate.update(sql, link.getUpdatedAt(), link.getId());
- }
-
- @Override
- public void remove(Long id) {
- log.info("remove() method invocation in linkRepo");
- String sql = "delete from link where link.id = ?";
- jdbcTemplate.update(sql, id);
- }
-
- @Override
- //поиск ссылок по критерию
- public List findOldLinks(Long timeUpdateDelta) {
- log.info("findOldLinks() method invocation in linkRepo");
- Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDelta*1000);
- String sql = "select * from link where link.updated_at < ? order by link.updated_at desc";
- return jdbcTemplate.query(sql,linkRowMapper,compareDate);
- }
- @Override
- public void updateGhLink(Link link) {
- log.info("updateGhLink() method invocation in linkJdbcRepo");
- String sql = "update link set gh_forks_count = ?, gh_description = ?, gh_pushed_at = ? where id = ?";
- jdbcTemplate.update(sql, link.getGhForksCount(), link.getGhDescription(), link.getGhPushedAt(), link.getId());
- }
-
- @Override
- public void updateSoLink(Link link) {
- log.info("updateSoLastEditDate() method invocation in linkJdbcRepo");
- String sql = "update link set so_last_edit_date = ?, so_answer_count = ? where id = ?";
- jdbcTemplate.update(sql, link.getSoLastEditDate(), link.getSoAnswerCount(), link.getId());
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
deleted file mode 100644
index fce7af7..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbc;
-
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
-import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import ru.tinkoff.edu.java.scrapper.model.Relation;
-import ru.tinkoff.edu.java.scrapper.model.User;
-import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository;
-
-import java.util.List;
-
-@Repository
-@Slf4j
-public class SubscriptionJdbcTemplateRepository implements SubscriptionRepository {
-
- private final JdbcTemplate jdbcTemplate;
-
- private final SubscriptionRowMapper subscriptionRowMapper;
-
- private final LinkRowMapper linkRowMapper;
-
- public SubscriptionJdbcTemplateRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper, LinkRowMapper linkRowMapper) {
- this.jdbcTemplate = jdbcTemplate;
- this.subscriptionRowMapper = subscriptionRowMapper;
- this.linkRowMapper = linkRowMapper;
- }
-
- @Override
- public List findLinksByChat(Long chatId) {
- log.info("findLinksByChat() method invocation in subscriptionRepo");
- String sql = "select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?";
- return jdbcTemplate.query(sql, linkRowMapper, chatId);
- }
-
- @Override
- public List findChatsByLink(Long linkId) {
- log.info("findChatsByLink() method invocation in subscriptionRepo");
- String sql = "select * from user_link where user_link.link_id = ?";
- return jdbcTemplate.query(sql, subscriptionRowMapper, linkId);
- }
-
- @Override
- public Relation findSubscription(Long linkId, Long chatId) {
- log.info("findSubscription() method invocation in subscriptionRepo");
- String sql = "select * from user_link rel where rel.chat_id = ? and rel.link_id = ?";
- List relation = jdbcTemplate.query(sql, subscriptionRowMapper, chatId, linkId);
- return relation.size() == 0 ? null : relation.get(0);
- }
-
-
- @Override
- public void addRelation(Relation relation) {
- log.info("addRelation() method invocation in subscriptionRepo");
- String sql = "insert into user_link (link_id, chat_id) values(?, ?)";
- jdbcTemplate.update(sql, relation.getLinkId(), relation.getChatId());
- }
-
- @Override
- public void remove(Long linkId, Long chatId) {
- log.info("remove() method invocation in subscriptionRepo");
- String sql = "delete from user_link where user_link.link_id = ? and user_link.chat_id = ?";
- jdbcTemplate.update(sql, linkId, chatId);
- }
-
- @Override
- public void removeAllByUser(Long chatId) {
- log.info("removeAllByUser() method invocation in subscriptionRepo");
- String sql = "delete from user_link where user_link.chat_id = ?";
- jdbcTemplate.update(sql, chatId);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
deleted file mode 100644
index d59d09c..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbc;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.User;
-import ru.tinkoff.edu.java.scrapper.repository.UserRepository;
-
-import java.util.List;
-
-@Repository
-@Slf4j
-public class UserJdbcTemplateRepository implements UserRepository {
-
-
- private final JdbcTemplate jdbcTemplate;
-
- private final UserRowMapper userRowMapper;
-
-
- public UserJdbcTemplateRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) {
- this.jdbcTemplate = jdbcTemplate;
- this.userRowMapper = userRowMapper;
- }
-
- @Override
- public List findAll(){
- log.info("findAll() method invocation in userRepo");
- String sql = "select * from \"user\"";
- return jdbcTemplate.query(sql, userRowMapper);
- }
-
- @Override
- public User findByChatId(Long id) {
- log.info("findByChatId() method invocation in userRepo");
- String sql = "select * from \"user\" where \"user\".chat_id = ?";
- List user = jdbcTemplate.query(sql, userRowMapper, id);
- return user.size() == 0 ? null : user.get(0);
- }
-
- @Override
- public void add(User user){
- log.info("add() method invocation in userRepo");
- String sql = "insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)";
- jdbcTemplate.update(sql, user.getChatId(), user.getUsername(), user.getFirstName(), user.getLastName());
- }
-
- @Override
- public void remove(Long chatId){
- log.info("remove() method invocation in userRepo");
- String sql = "delete from \"user\" where \"user\".chat_id = ?";
- jdbcTemplate.update(sql,chatId);
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
deleted file mode 100644
index 0298278..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import java.util.List;
-
-
-public interface LinkRepository {
- List findAll();
-
-
- Link findByUrl(String url);
- void add(Link link);
-
- void updateCheckDate(Link link);
- void remove(Long id);
- List findOldLinks(Long timeUpdateDeltaInSeconds);
-
- void updateGhLink(Link link);
-
- void updateSoLink(Link link);
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
deleted file mode 100644
index 0dde7e4..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
-
-import java.util.List;
-
-public interface SubscriptionRepository {
-
- List findLinksByChat(Long chatId);
-
- List findChatsByLink(Long linkId);
-
- Relation findSubscription(Long linkId, Long chatId);
- void addRelation(Relation relation);
- void remove(Long linkId, Long chatId);
-
- void removeAllByUser(Long chatId);
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
deleted file mode 100644
index 87cbf34..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-import java.util.List;
-
-public interface UserRepository {
- List findAll();
-
- User findByChatId(Long id);
- void add(User user);
- void remove(Long id);
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
deleted file mode 100644
index 7371ffd..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jooq;
-
-import lombok.extern.slf4j.Slf4j;
-import org.jooq.DSLContext;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
-import java.sql.Timestamp;
-import java.util.List;
-import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*;
-
-@Slf4j
-public class LinkJooqRepository implements LinkRepository {
-
-
- private final DSLContext dslContext;
-
-
-
- public LinkJooqRepository(DSLContext dslContext) {
- this.dslContext = dslContext;
- }
-
- @Override
- public List findAll() {
- log.info("findAll() method invocation in linkJooqRepo");
- return dslContext.selectFrom(LINK)
- .fetchInto(Link.class);
- }
-
- @Override
- public Link findByUrl(String url) {
- log.info("findByUrl() method invocation in linkJooqRepo");
- return dslContext.selectFrom(LINK)
- .where(LINK.URL.eq(url))
- .fetchOneInto(Link.class);
- }
-
- @Override
- public void add(Link link) {
- log.info("add() method invocation in linkJooqRepo");
- dslContext.insertInto(LINK)
- .set(LINK.URL, link.getUrl())
- .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
- .execute();
- }
-
- @Override
- public void updateCheckDate(Link link) {
- log.info("updateDate() method invocation in linkJooqRepo");
- dslContext.update(LINK)
- .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
- .where(LINK.ID.eq(link.getId()))
- .execute();
- }
-
- @Override
- public void remove(Long id) {
- log.info("remove() method invocation in linkJooqRepo");
- dslContext.deleteFrom(LINK)
- .where(LINK.ID.eq(id))
- .execute();
- }
-
- @Override
- public List findOldLinks(Long timeUpdateDeltaInSeconds) {
- log.info("findOldLinks() method invocation in linkJooqRepo");
- Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds * 1000);
- return dslContext.selectFrom(LINK)
- .where(LINK.CHECKED_AT.lessThan(compareDate.toLocalDateTime()))
- .orderBy(LINK.CHECKED_AT.desc())
- .fetchInto(Link.class);
- }
-
- @Override
- public void updateGhLink(Link link) {
- log.info("updateGhLink() method invocation in linkJooqRepo");
- dslContext.update(LINK)
- .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
- .set(LINK.GH_FORKS_COUNT, link.getGhForksCount())
- .set(LINK.GH_DESCRIPTION, link.getGhDescription())
- .set(LINK.GH_PUSHED_AT, link.getGhPushedAt().toLocalDateTime())
- .where(LINK.ID.eq(link.getId()))
- .execute();
- }
-
- @Override
- public void updateSoLink(Link link) {
- log.info("updateSoLink() method invocation in linkJooqRepo");
- dslContext.update(LINK)
- .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime())
- .set(LINK.SO_LAST_EDIT_DATE, link.getSoLastEditDate().toLocalDateTime())
- .set(LINK.SO_ANSWER_COUNT, link.getSoAnswerCount())
- .where(LINK.ID.eq(link.getId()))
- .execute();
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
deleted file mode 100644
index 6463de4..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jooq;
-
-import lombok.extern.slf4j.Slf4j;
-import org.jooq.DSLContext;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import ru.tinkoff.edu.java.scrapper.model.Relation;
-import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository;
-
-import java.util.List;
-
-import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.UserLink.*;
-import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*;
-
-
-@Repository
-@Slf4j
-public class SubscriptionJooqRepository implements SubscriptionRepository {
-
-
- private final DSLContext dslContext;
-
-
- public SubscriptionJooqRepository(DSLContext dslContext) {
- this.dslContext = dslContext;
- }
-
-
- @Override
- public List findLinksByChat(Long chatId) {
- log.info("findLinksByChat() method invocation in subscriptionJooqRepo");
- return dslContext.select()
- .from(LINK)
- .join(USER_LINK).on(LINK.ID.eq(USER_LINK.LINK_ID))
- .where(USER_LINK.CHAT_ID.eq(chatId))
- .fetchInto(Link.class);
- }
-
- @Override
- public List findChatsByLink(Long linkId) {
- log.info("findChatsByLink() method invocation in subscriptionJooqRepo");
- return dslContext.select()
- .from(USER_LINK)
- .where(USER_LINK.LINK_ID.eq(linkId))
- .fetchInto(Relation.class);
- }
-
- @Override
- public Relation findSubscription(Long linkId, Long chatId) {
- log.info("findSubscription() method invocation in subscriptionJooqRepo");
- return dslContext.select()
- .from(USER_LINK)
- .where(USER_LINK.CHAT_ID.eq(chatId).and(USER_LINK.LINK_ID.eq(linkId)))
- .fetchOneInto(Relation.class);
- }
-
- @Override
- public void addRelation(Relation relation) {
- log.info("addRelation() method invocation in subscriptionJooqRepo");
- dslContext.insertInto(USER_LINK, USER_LINK.LINK_ID, USER_LINK.CHAT_ID)
- .values(relation.getLinkId(), relation.getChatId())
- .execute();
- }
-
- @Override
- public void remove(Long linkId, Long chatId) {
- log.info("remove() method invocation in subscriptionJooqRepo");
- dslContext.deleteFrom(USER_LINK)
- .where(USER_LINK.LINK_ID.eq(linkId).and(USER_LINK.CHAT_ID.eq(chatId)))
- .execute();
- }
-
- @Override
- public void removeAllByUser(Long chatId) {
- log.info("removeAllByUser() method invocation in subscriptionJooqRepo");
- dslContext.deleteFrom(USER_LINK)
- .where(USER_LINK.CHAT_ID.eq(chatId))
- .execute();
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
deleted file mode 100644
index d942314..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jooq;
-
-import lombok.extern.slf4j.Slf4j;
-import org.jooq.DSLContext;
-import org.springframework.stereotype.Repository;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
-import java.util.List;
-
-import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.User.*;
-
-@Repository
-@Slf4j
-public class UserJooqRepository implements UserRepository {
-
- private final DSLContext dslContext;
-
-
- public UserJooqRepository(DSLContext dslContext) {
- this.dslContext = dslContext;
- }
-
- @Override
- public List findAll() {
- log.info("findAll() method invocation in userJooqRepo");
-
- return dslContext.selectFrom(USER).fetchInto(User.class);
- }
-
- @Override
- public User findByChatId(Long id) {
- log.info("findByChatId() method invocation in userJooqRepo");
-
- return dslContext.selectFrom(USER)
- .where(USER.CHAT_ID.eq(id))
- .fetchOneInto(User.class);
- }
-
- @Override
- public void add(User user) {
- log.info("add() method invocation in userJooqRepo");
-
- dslContext.insertInto(USER)
- .set(USER.CHAT_ID, user.getChatId())
- .set(USER.USERNAME, user.getUsername())
- .set(USER.FIRST_NAME, user.getFirstName())
- .set(USER.LAST_NAME, user.getLastName())
- .execute();
- }
-
- @Override
- public void remove(Long chatId) {
- log.info("remove() method invocation in userJooqRepo");
-
- dslContext.deleteFrom(USER)
- .where(USER.CHAT_ID.eq(chatId))
- .execute();
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
deleted file mode 100644
index 2f1dab8..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jpa;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-
-import java.sql.Timestamp;
-import java.util.List;
-import java.util.Optional;
-
-public interface JpaLinkRepository extends JpaRepository {
- Optional findByUrl(String url);
-
- @Query("select u.chatId from UserEntity u join u.links l where l.id = :id")
- List findChatIdsByLinkId(@Param("id") Long id);
-
- List findByCheckedAtLessThanOrderByCheckedAtDesc(Timestamp compareDate);
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
deleted file mode 100644
index cdcb762..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.repository.jpa;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
-
-import java.util.List;
-import java.util.Optional;
-
-public interface JpaUserRepository extends JpaRepository {
-
- @Query("select link from UserEntity u join u.links link where u.chatId = :chatId")
- List findAllLinksByChat(@Param("chatId") Long chatId);
-
-
- @Query("select u from UserEntity u join fetch u.links link where u.chatId = :chatId")
- Optional findByChatIdWithLinks(@Param("chatId") Long chatId);
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
deleted file mode 100644
index 388ebac..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.rest;
-
-import org.springframework.web.bind.annotation.*;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-import ru.tinkoff.edu.java.scrapper.dto.UserAddDto;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-
-@RestController
-@RequestMapping("/tg-chat")
-public class ChatRestController {
-
-
- private final TgChatService chatService;
-
- public ChatRestController(TgChatService chatService) {
- this.chatService = chatService;
- }
-
- @PostMapping(value = "{id}")
- public void registerChat(@PathVariable Long id, @RequestBody UserAddDto userAddDto) {
- chatService.register(new User(id, userAddDto.username(), userAddDto.firstName(), userAddDto.lastName()));
- }
-
- @DeleteMapping(value = "{id}")
- public void deleteChat(@PathVariable Long id) {
- chatService.unregister(id);
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
deleted file mode 100644
index 5aef3ac..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.rest;
-
-import org.springframework.web.bind.annotation.*;
-import ru.tinkoff.edu.java.scrapper.dto.AddLinkRequest;
-import ru.tinkoff.edu.java.scrapper.dto.LinkResponse;
-import ru.tinkoff.edu.java.scrapper.dto.ListLinkResponse;
-import ru.tinkoff.edu.java.scrapper.dto.RemoveLinkRequest;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkService;
-import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
-import java.net.URI;
-import java.util.List;
-
-@RestController
-@RequestMapping("/links")
-public class LinkRestController {
-
- private final SubscriptionService subscriptionService;
-
- public LinkRestController(SubscriptionService subscriptionService) {
- this.subscriptionService = subscriptionService;
- }
-
- @GetMapping
- public ListLinkResponse getLinks(@RequestHeader("Tg-Chat-Id") Long chatId) {
- List list = subscriptionService.getLinksByChat(chatId);
- return new ListLinkResponse(list, list.size());
- }
-
- @PostMapping
- public LinkResponse addLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody AddLinkRequest request) {
- Link link = subscriptionService.subscribe(chatId, URI.create(request.link()));
- return new LinkResponse(link.getId(), link.getUrl());
- }
-
- @DeleteMapping
- public LinkResponse deleteLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody RemoveLinkRequest request) {
- Link link = subscriptionService.unsubscribe(chatId, URI.create(request.link()));
- if (link == null) throw new LinkNotFoundException("Ссылка с таким url не отслеживается!");
- return new LinkResponse(link.getId(), link.getUrl());
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
deleted file mode 100644
index eec99f7..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.schedule;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-
-import java.util.List;
-
-@Slf4j
-@Component
-public class LinkUpdateScheduler {
-
- private final LinkUpdateService linkUpdateService;
-
-
- public LinkUpdateScheduler(LinkUpdateService linkUpdateService, Parser_Link linkParser) {
- this.linkUpdateService = linkUpdateService;
- }
-
- @Scheduled(fixedDelayString = "#{@schedulerIntervalMs}")
- public void update() {
- log.info("update() method invocation in LinkUpdateScheduler");
- linkUpdateService.updateLinks();
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
new file mode 100644
index 0000000..10c9caa
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
@@ -0,0 +1,63 @@
+package ru.tinkoff.edu.java.scrapper.schedule;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
+import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
+import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
+
+import java.lang.ref.Cleaner;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+@Service
+public class LinkUpdaterScheduler implements LinkOperations {
+ private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+
+ private final JdbcTemplate jdbcTemplate;
+ ArrayList link_list = new ArrayList<>();
+ static int ix = 0;
+ ClientConfiguration client = new ClientConfiguration();
+ LinkParser pars = new LinkParser();
+ boolean git_link_is_activity;
+ boolean stack_link_is_activity;
+
+ public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Scheduled(fixedDelayString = "${app.scheduler.interval}")
+ public void update() {
+ int i;
+ for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){
+ if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) {
+ link_list.add(i_getAllIds(jdbcTemplate).get(i).url());
+ }
+ }
+ try {
+ client.gitHubClient(pars.getLink(link_list.get(ix)));
+ git_link_is_activity = true;
+ } catch (WebClientResponseException e) {
+ git_link_is_activity = false;
+ }
+ try {
+ client.stackOverflowClient(pars.getLink(link_list.get(ix)));
+ stack_link_is_activity = true;
+ } catch (WebClientResponseException ignored) {
+ stack_link_is_activity = false;
+ }
+ if (!(git_link_is_activity || stack_link_is_activity)) {
+ String link = "Ссылка %s устарела";
+ link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url());
+ LOGGER.log(Level.INFO, link);
+ }
+ ix++;
+ if (ix == link_list.size()) ix = 0;
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
index 623f12b..d060c22 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
@@ -2,5 +2,4 @@
import java.time.Duration;
-public record Scheduler(Duration interval) {
-}
\ No newline at end of file
+public record Scheduler(Duration interval) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
deleted file mode 100644
index 61ee96d..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service;
-
-import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
-
-public interface UpdateNotificationService {
-
- void updateLink(LinkUpdate request);
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
deleted file mode 100644
index 10646d7..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.contract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import java.util.List;
-
-public interface LinkUpdateService {
-
-
- List getOldLinks();
-
- void updateLinks();
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
deleted file mode 100644
index b35caad..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.contract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import java.net.URI;
-import java.util.List;
-
-public interface SubscriptionService {
-
- Link add(Long chatId, URI url);
- Link remove(Long chatId, URI url);
-
- List getAllByUser(Long chatId);
-
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
deleted file mode 100644
index adf1fde..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.contract;
-
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-
-public interface TgChatService {
-
- void register(User user);
-
- void unregister(Long chatId);
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
deleted file mode 100644
index 983fdb9..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
-import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
-import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
-import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
-import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
-import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
-//import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-//import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
-//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
-//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-//import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-
-import java.sql.Timestamp;
-import java.time.ZoneOffset;
-import java.util.List;
-
-@Slf4j
-public class LinkUpdateServiceImpl implements LinkUpdateService {
-
-
- @Value("${update.delta.time}")
- private Long timeUpdateDeltaInSeconds;
-
- private final LinkRepository linkRepository;
-
- private final SubscriptionRepository subscriptionRepository;
-
- private final Link_Parser linkParser;
-
- private final GitHubClient gitHubClient;
-
- private final StackOverflowClient stackOverflowClient;
-
- private final BotClient botClient;
-
-
- public LinkUpdateServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository, Link_Parser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) {
- this.linkRepository = linkRepository;
- this.subscriptionRepository = subscriptionRepository;
- this.linkParser = linkParser;
- this.gitHubClient = gitHubClient;
- this.stackOverflowClient = stackOverflowClient;
- this.botClient = botClient;
- }
-
- @Override
- public List getOldLinks() {
- return linkRepository.findOldLinks(timeUpdateDeltaInSeconds);
- }
-
-
- public void updateLinks() {
- List oldLinks = getOldLinks();
-
- for (Link link : oldLinks) {
- Parser_Link result = linkParser.parseUrl(link.getUrl());
- if (result instanceof GitHub_Link) {
- try {
- boolean isUpdated = false;
- String updateDescription = "";
-
-
- GitHubResponse response = gitHubClient.fetchRepo(((GithubParseResult) result).username(), ((GithubParseResult) result).repository());
-
-
- if (response.forksCount() != link.getGhForksCount()) {
- isUpdated = true;
- if (response.forksCount() < link.getGhForksCount()) {
- updateDescription += "В репозитории уменьшилось кол-во форков\n";
- }
- if (response.forksCount() > link.getGhForksCount()) {
- updateDescription += "В репозитории появились новые форки\n";
- }
- link.setGhForksCount(response.forksCount());
- }
-
-
- if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) {
- if (link.getGhDescription() != null) isUpdated = true;
- link.setGhDescription(response.description());
- updateDescription += "В репозитории изменилось описание\n";
- }
-
- if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) {
- if (link.getGhPushedAt() != null) isUpdated = true;
- link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli()));
- updateDescription += "В репозитории появился новый commit\n";
- }
-
-
- linkRepository.updateCheckDate(link);
-
- if (isUpdated) {
- Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new);
- botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chats));
- }
-
-
- } catch (GitHubRequestException e) {
- log.warn(e.getMessage());
- }
-
- } else if (result instanceof StackOverflow_Link) {
- try {
-
- boolean isUpdated = false;
- String updateDescription = "";
-
-
- StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id());
-
-
- if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) {
- if (link.getSoLastEditDate() != null) isUpdated = true;
- link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli()));
- updateDescription += "Текст вопроса был изменён\n";
- }
-
- if (response.answerCount() != link.getSoAnswerCount()) {
- isUpdated = true;
- if (response.answerCount() < link.getSoAnswerCount()) {
- updateDescription += "На вопрос уменьшилось кол-во ответов\n";
- }
- if (response.answerCount() > link.getSoAnswerCount()) {
- updateDescription += "На вопрос появились новые ответы\n";
- }
- link.setSoAnswerCount(response.answerCount());
- }
-
- linkRepository.updateCheckDate(link);
-
- if (isUpdated) {
-
- Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new);
- botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chats));
- }
-
- } catch (StackOverflowRequestException e) {
- log.warn(e.getMessage());
- }
- }
- }
- }
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
deleted file mode 100644
index 4476e8b..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
-
-import java.net.URI;
-import java.sql.Timestamp;
-import java.util.List;
-
-
-@Slf4j
-public class SubscriptionServiceImpl implements SubscriptionService {
-
-
- private final LinkRepository linkRepository;
-
- private final SubscriptionRepository subscriptionRepository;
-
-
-
- public SubscriptionServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository) {
- this.linkRepository = linkRepository;
- this.subscriptionRepository = subscriptionRepository;
- }
-
- @Override
- @Transactional
- public Link subscribe(Long chatId, URI url) {
- log.info("subscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
- Link link = linkRepository.findByUrl(url.toString());
- if (link == null) {
- link = new Link();
- link.setUrl(url.toString());
- link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
- linkRepository.add(link);
- //обращение ниже нужно, чтобы получить id из БД
- link = linkRepository.findByUrl(link.getUrl());
- }
- Relation relation = subscriptionRepository.findSubscription(link.getId(), chatId);
-
- if (relation == null) {
- relation = new Relation();
- relation.setChatId(chatId);
- relation.setLinkId(link.getId());
- subscriptionRepository.addRelation(relation);
- }
- return link;
- }
-
- @Override
- @Transactional
- public Link unsubscribe(Long chatId, URI url) {
- log.info("unsubscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
- Link link = linkRepository.findByUrl(url.toString());
-
- if (link != null) {
-// linkRepository.remove(link.getId());
- subscriptionRepository.remove(link.getId(), chatId);
- }
- return link;
- }
-
- @Override
- public List getLinksByChat(Long chatId) {
- log.info("getLinksByChat() method invocation in SubscriptionServiceImpl. chatId = "+chatId);
- return subscriptionRepository.findLinksByChat(chatId);
- }
-
- @Override
- public List getChatIdsByLink(Long linkId) {
- log.info("getChatIdsByLink() method invocation in SubscriptionServiceImpl. linkId = "+linkId);
- return null;
- }
-
- @Override
- public Link add(Long chatId, URI url) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Link remove(Long chatId, URI url) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List getAllByUser(Long chatId) {
- // TODO Auto-generated method stub
- return null;
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
deleted file mode 100644
index 84a130a..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-
-@Slf4j
-public class TgChatServiceImpl implements TgChatService {
-
- private final UserRepository userRepository;
-
- private final SubscriptionRepository subscriptionRepository;
-
-
- public TgChatServiceImpl(UserRepository userRepository, SubscriptionRepository subscriptionRepository) {
- this.userRepository = userRepository;
- this.subscriptionRepository = subscriptionRepository;
- }
-
- @Override
- public void register(User user) {
- log.info("register() method invocation in TgChatServiceImpl. chatId = "+user.getChatId());
- User userInBd = userRepository.findByChatId(user.getChatId());
- if (userInBd != null) throw new ChatAlreadyExistException();
- userRepository.add(user);
- }
-
- @Override
- @Transactional
- public void unregister(Long chatId) {
- log.info("unregister() method invocation in TgChatServiceImpl. chatId = "+chatId);
- userRepository.remove(chatId);
- subscriptionRepository.removeAllByUser(chatId);
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
deleted file mode 100644
index f27d081..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.link_parser.parser.Link_Parser;
-import ru.tinkoff.edu.java.link_parser.link.GitHub_Link;
-import ru.tinkoff.edu.java.link_parser.link.Parser_Link;
-import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link;
-import ru.tinkoff.edu.java.scrapper.client.BotClient;
-import ru.tinkoff.edu.java.scrapper.client.GitHubClient;
-import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient;
-import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse;
-import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate;
-import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem;
-import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException;
-import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
-import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService;
-
-import java.sql.Timestamp;
-import java.time.ZoneOffset;
-import java.util.List;
-
-@Slf4j
-public class JpaLinkUpdateServiceImpl implements LinkUpdateService {
-
- @Value("${update.delta.time}")
- private Long timeUpdateDeltaInSeconds;
-
- private final JpaLinkRepository linkRepository;
-
-
-
- private final Link_Parser linkParser;
-
- private final GitHubClient gitHubClient;
-
- private final StackOverflowClient stackOverflowClient;
-
- private final BotClient botClient;
-
-
- public JpaLinkUpdateServiceImpl(JpaLinkRepository linkRepository, LinkParser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) {
- this.linkRepository = linkRepository;
- this.linkParser = linkParser;
- this.gitHubClient = gitHubClient;
- this.stackOverflowClient = stackOverflowClient;
- this.botClient = botClient;
- }
-
- @Override
- public List getOldLinks() {
- log.info("getOldLinks() method invocation in JpaLinkUpdateServiceImpl");
- Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000);
- return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate).stream().map(Link::fromEntity).toList();
- }
-
-
- public List getOldEntityLinks() {
- Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000);
- return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate);
- }
-
- @Override
- @Transactional
- public void updateLinks() {
- log.info("updateLinks() method invocation in JpaLinkUpdateServiceImpl");
- List oldLinks = getOldEntityLinks();
-
- for (LinkEntity link : oldLinks) {
- Parser_Link result = linkParser.parseUrl(link.getUrl());
- if (result instanceof GitHub_Link) {
- try {
- boolean isUpdated = false;
- String updateDescription = "";
-
-
- System.out.println(link.getUrl());
- GitHubResponse response = gitHubClient.fetchRepo(((GitHub_Link) result).username(), ((GithubParseResult) result).repository());
- System.out.println(response);
-
-
- if (link.getGhForksCount() == null || response.forksCount() != link.getGhForksCount()) {
- isUpdated = true;
- if (link.getGhForksCount() == null) {link.setGhForksCount(0); isUpdated = false;}
- if (isUpdated && response.forksCount() < link.getGhForksCount()) {
- updateDescription += "В репозитории уменьшилось кол-во форков\n";
- }
- if (isUpdated && response.forksCount() > link.getGhForksCount()) {
- updateDescription += "В репозитории появились новые форки\n";
- }
- link.setGhForksCount(response.forksCount());
- }
-
-
- if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) {
- if (link.getGhDescription() != null) isUpdated = true;
- link.setGhDescription(response.description());
- updateDescription += "В репозитории изменилось описание\n";
- }
-
- if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) {
- if (link.getGhPushedAt() != null) isUpdated = true;
- link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli()));
- updateDescription += "В репозитории появился новый commit\n";
- }
-
- link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
-
- linkRepository.save(link);
-
- if (isUpdated) {
- List chatsIds = linkRepository.findChatIdsByLinkId(link.getId());
- botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chatsIds.toArray(new Long[0])));
- }
-
-
- } catch (GitHubRequestException e) {
- log.warn(e.getMessage());
- }
-
- } else if (result instanceof StackOverflow_Link) {
- try {
-
- boolean isUpdated = false;
- String updateDescription = "";
-
-
- System.out.println(link.getUrl());
- StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id());
- System.out.println(response);
-
-
-
- if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) {
- if (link.getSoLastEditDate() != null) isUpdated = true;
- link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli()));
- updateDescription += "Текст вопроса был изменён\n";
- }
-
- if (link.getSoAnswerCount() == null || response.answerCount() != link.getSoAnswerCount()) {
- isUpdated = true;
- if (link.getSoAnswerCount() == null) {link.setSoAnswerCount(0); isUpdated = false;}
- if (isUpdated && response.answerCount() < link.getSoAnswerCount()) {
- updateDescription += "На вопрос уменьшилось кол-во ответов\n";
- }
- if (isUpdated && response.answerCount() > link.getSoAnswerCount()) {
- updateDescription += "На вопрос появились новые ответы\n";
- }
- link.setSoAnswerCount(response.answerCount());
- }
-
-
- link.setCheckedAt(new Timestamp(System.currentTimeMillis()));
-
- linkRepository.save(link);
-
- if (isUpdated) {
- List chatsIds = linkRepository.findChatIdsByLinkId(link.getId());
- botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chatsIds.toArray(new Long[0])));
- }
-
- } catch (StackOverflowRequestException e) {
- log.warn(e.getMessage());
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
deleted file mode 100644
index c5c9749..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
-import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.Link;
-import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity;
-import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
-import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService;
-
-import java.net.URI;
-import java.sql.Timestamp;
-import java.util.List;
-import java.util.Optional;
-
-@Slf4j
-public class JpaSubscriptionServiceImpl implements SubscriptionService {
-
- private final JpaLinkRepository linkRepository;
-
- private final JpaUserRepository userRepository;
-
- public JpaSubscriptionServiceImpl(JpaLinkRepository linkRepository, JpaUserRepository userRepository) {
- this.linkRepository = linkRepository;
- this.userRepository = userRepository;
- }
-
-
- @Override
- @Transactional
- public Link subscribe(Long chatId, URI url) {
- log.info("subscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
- Optional optionalLink = linkRepository.findByUrl(url.toString());
- LinkEntity linkToAdd = new LinkEntity();
- if (optionalLink.isEmpty()) {
- linkToAdd.setUrl(url.toString());
- } else {
- linkToAdd = optionalLink.get();
- }
- linkToAdd.setCheckedAt(new Timestamp(System.currentTimeMillis()));
- linkRepository.save(linkToAdd);
-
- Optional optionalUser = userRepository.findById(chatId);
- if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
- UserEntity user = optionalUser.get();
- List userLinks = user.getLinks();
-
- if (!userLinks.contains(linkToAdd)) {
- userLinks.add(linkToAdd);
- }
-
- userRepository.save(user);
- return Link.fromEntity(linkToAdd);
- }
-
- @Override
- @Transactional
- public Link unsubscribe(Long chatId, URI url) {
- log.info("unsubscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString());
- Optional optionalUser = userRepository.findByChatIdWithLinks(chatId);
- Optional optionalLink = linkRepository.findByUrl(url.toString());
-
-
- if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой пользователь не зарегистрирован");
-
- UserEntity user = optionalUser.get();
-
- List userLinks = user.getLinks();
-
- if (optionalLink.isEmpty() || !userLinks.contains(optionalLink.get()))
- throw new LinkNotFoundException("Такая ссылка не отслеживается");
-
- userLinks.remove(optionalLink.get());
- userRepository.save(user);
-
- return Link.fromEntity(optionalLink.get());
- }
-
- @Override
- public List getLinksByChat(Long chatId) {
- log.info("getAllByUser() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId);
- Optional optionalUser = userRepository.findById(chatId);
- if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
- return userRepository.findAllLinksByChat(chatId).stream().map(Link::fromEntity).toList();
- }
-
-
- @Override
- public List getChatIdsByLink(Long linkId) {
- log.info("getChatIdsByLink() method invocation in JpaSubscriptionServiceImpl. linkId = "+linkId);
- Optional optionalLink = linkRepository.findById(linkId);
- if (optionalLink.isEmpty()) throw new LinkNotFoundException("Такая ссылка не отслеживается");
- return linkRepository.findChatIdsByLinkId(linkId);
- }
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
deleted file mode 100644
index b87e274..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.service.jpa.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException;
-import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException;
-import ru.tinkoff.edu.java.scrapper.model.commonDto.User;
-import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity;
-import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository;
-import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService;
-
-import java.util.Optional;
-
-
-@Slf4j
-public class JpaTgChatServiceImpl implements TgChatService {
-
- private final JpaUserRepository userRepository;
-
- public JpaTgChatServiceImpl(JpaUserRepository userRepository) {
- this.userRepository = userRepository;
- }
-
- @Override
- public void register(User user) {
- log.info("register() method invocation in JpaTgChatServiceImpl. User chatId = "+user.getChatId());
- Optional optionalUser = userRepository.findById(user.getChatId());
- if (optionalUser.isPresent()) throw new ChatAlreadyExistException("Такой чат уже зарегистрирован!");
- userRepository.save(User.toEntity(user));
- }
-
- @Override
- public void unregister(Long chatId) {
- log.info("unregister() method invocation in JpaTgChatServiceImpl. User chatId = "+chatId);
- Optional optionalUser = userRepository.findById(chatId);
- if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!");
- userRepository.delete(optionalUser.get());
- }
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties
index 3761f00..00d78d2 100644
--- a/FP/scrapper/src/main/resources/application.properties
+++ b/FP/scrapper/src/main/resources/application.properties
@@ -1,23 +1,5 @@
-server.port=8080
-app.test=beamer-scrapper
-gh.baseurl=https://api.github.com
-so.baseurl=https://api.stackexchange.com/2.3/
-bot.baseurl=http://localhost:8081
-app.scheduler.interval=61000
-update.delta.time=20
+app.test=123
springdoc.swagger-ui.path=/swagger-ui
-
-spring.datasource.driver-class-name=org.postgresql.Driver
-spring.datasource.url=jdbc:postgresql://localhost:5432/scrapper
-spring.datasource.username=romanova
-spring.datasource.password=12345654321
-spring.jpa.properties.hibernate.show_sql=true
-
-spring.rabbitmq.host=localhost
-spring.rabbitmq.port=5672
-spring.rabbitmq.username=romanova
-spring.rabbitmq.password=12345654321
-app.queue-name=scrapper-bot-queue
-app.exchange-name=scrapper-bot-exchange
-app.routing-key=scrapper-bot-key
-app.use-queue=true
+app.scheduler.interval=5000
+git.link=https://github.com/Ray-Not/JavaGuava
+stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c
diff --git a/FP/scrapper/src/main/resources/logback-test.xml b/FP/scrapper/src/main/resources/logback-test.xml
deleted file mode 100644
index 900637e..0000000
--- a/FP/scrapper/src/main/resources/logback-test.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
-
-
-
-
-
-
-
-
-
-
-
-
-.
diff --git a/FP/scrapper/src/main/resources/scrapperapi.yml b/FP/scrapper/src/main/resources/scrapperapi.yml
new file mode 100644
index 0000000..c98cf7d
--- /dev/null
+++ b/FP/scrapper/src/main/resources/scrapperapi.yml
@@ -0,0 +1,184 @@
+openapi: 3.0.1
+info:
+ title: Scrapper API
+ version: 1.0.0
+ contact:
+ name: Alexander Biryukov
+ url: https://github.com
+paths:
+ /tg-chat/{id}:
+ post:
+ summary: Зарегистрировать чат
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Чат зарегистрирован
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ delete:
+ summary: Удалить чат
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Чат успешно удалён
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '404':
+ description: Чат не существует
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ /links:
+ get:
+ summary: Получить все отслеживаемые ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Ссылки успешно получены
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListLinksResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ post:
+ summary: Добавить отслеживание ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddLinkRequest'
+ required: true
+ responses:
+ '200':
+ description: Ссылка успешно добавлена
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LinkResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ delete:
+ summary: Убрать отслеживание ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RemoveLinkRequest'
+ required: true
+ responses:
+ '200':
+ description: Ссылка успешно убрана
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LinkResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '404':
+ description: Ссылка не найдена
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+components:
+ schemas:
+ LinkResponse:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ url:
+ type: string
+ format: uri
+ ApiErrorResponse:
+ type: object
+ properties:
+ description:
+ type: string
+ code:
+ type: string
+ exceptionName:
+ type: string
+ exceptionMessage:
+ type: string
+ stacktrace:
+ type: array
+ items:
+ type: string
+ AddLinkRequest:
+ type: object
+ properties:
+ link:
+ type: string
+ format: uri
+ ListLinksResponse:
+ type: object
+ properties:
+ links:
+ type: array
+ items:
+ $ref: '#/components/schemas/LinkResponse'
+ size:
+ type: integer
+ format: int32
+ RemoveLinkRequest:
+ type: object
+ properties:
+ link:
+ type: string
+ format: uri
diff --git a/FP/scrapper/src/test/java/BaseTest.java b/FP/scrapper/src/test/java/BaseTest.java
new file mode 100644
index 0000000..447e5c5
--- /dev/null
+++ b/FP/scrapper/src/test/java/BaseTest.java
@@ -0,0 +1,11 @@
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class BaseTest extends IntegrationEnvironment {
+
+ @Test
+ void create_test() {
+ Assertions.assertTrue(Postgre_container.isCreated());
+ System.out.println(Postgre_container.getImage());
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/IntegrationEnvironment.java b/FP/scrapper/src/test/java/IntegrationEnvironment.java
new file mode 100644
index 0000000..7fef825
--- /dev/null
+++ b/FP/scrapper/src/test/java/IntegrationEnvironment.java
@@ -0,0 +1,45 @@
+import liquibase.Contexts;
+import liquibase.LabelExpression;
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.DatabaseFactory;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.LiquibaseException;
+import liquibase.resource.DirectoryResourceAccessor;
+import org.testcontainers.containers.PostgreSQLContainer;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+public abstract class IntegrationEnvironment {
+
+ static final protected PostgreSQLContainer Postgre_container;
+
+ static {
+ Postgre_container = new PostgreSQLContainer<>("postgres:14");
+ Postgre_container.start();
+
+ try {
+ Connection connection = DriverManager.getConnection(
+ Postgre_container.getJdbcUrl(),
+ Postgre_container.getUsername(),
+ Postgre_container.getPassword());
+ Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
+ Liquibase liquibase = new liquibase.Liquibase(
+ "master.xml",
+ new DirectoryResourceAccessor(Path.of(".")
+ .toAbsolutePath()
+ .getParent()
+ .getParent()
+ .resolve("migrations")),
+ database);
+ liquibase.update(new Contexts(), new LabelExpression());
+ } catch (SQLException | LiquibaseException | FileNotFoundException e) {
+ System.out.println(e.getMessage());
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/FP/scrapper/src/test/java/JdbcAddTest.java b/FP/scrapper/src/test/java/JdbcAddTest.java
new file mode 100644
index 0000000..d5de9ec
--- /dev/null
+++ b/FP/scrapper/src/test/java/JdbcAddTest.java
@@ -0,0 +1,9 @@
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class JdbcAddTest extends IntegrationEnvironment {
+ @Test
+ void create_test() {
+// Postgre_container.
+ }
+}
diff --git a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
deleted file mode 100644
index 1c2378c..0000000
--- a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package scrapper;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import java.sql.*;
-
-public class DatabaseTest extends IntegrationEnvironment{
-
-
- @Test
- @DisplayName("Тест для проверки запуска контейнера с PostgreSQL")
- public void testIfContainerIsRunning() {
- Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL");
- }
-
- @Test
- @DisplayName("Тест для проверки успешного применения миграций")
- void testMigrations() throws SQLException {
- try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getPassword());
- Statement statement = conn.createStatement()) {
-
- ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\"");
- Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана");
- ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\"");
- Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана");
- ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\"");
- Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана");
- }
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
deleted file mode 100644
index 2f0bdfa..0000000
--- a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package scrapper;
-
-import liquibase.Contexts;
-import liquibase.LabelExpression;
-import liquibase.Liquibase;
-import liquibase.database.Database;
-import liquibase.database.DatabaseFactory;
-import liquibase.database.jvm.JdbcConnection;
-import liquibase.exception.LiquibaseException;
-import liquibase.resource.DirectoryResourceAccessor;
-import org.testcontainers.containers.PostgreSQLContainer;
-import org.testcontainers.junit.jupiter.Testcontainers;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.nio.file.Path;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-abstract class IntegrationEnvironment {
-
- static final String IMAGE_VERSION = "postgres:15";
-
- static final PostgreSQLContainer POSTGRES_CONTAINER;
-
- static {
- POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION)
- .withDatabaseName("scrapper")
- .withUsername("lwbeamer")
- .withPassword("2281337");
-
-
- POSTGRES_CONTAINER.start();
- executeMigrations();
- }
-
- private static void executeMigrations() {
- try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) {
- Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn));
- Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations");
- Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database);
- liquibase.update(new Contexts(), new LabelExpression());
- } catch (SQLException | LiquibaseException e) {
- throw new RuntimeException("Failed to execute migrations", e);
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Changelog file not found",e);
- }
- }
-
- public static void stopContainer() {
- POSTGRES_CONTAINER.stop();
- }
diff --git a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
deleted file mode 100644
index d0ac18a..0000000
--- a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package scrapper.environment;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import java.sql.*;
-
-public class DatabaseTest extends IntegrationEnvironment{
-
-
- @Test
- @DisplayName("Тест для проверки запуска контейнера с PostgreSQL")
- public void testIfContainerIsRunning() {
- Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL");
- }
-
- @Test
- @DisplayName("Тест для проверки успешного применения миграций")
- void testMigrations() throws SQLException {
- try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getPassword());
- Statement statement = conn.createStatement()) {
-
- ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\"");
- Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана");
- ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\"");
- Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана");
- ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\"");
- Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана");
- }
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
deleted file mode 100644
index 416b086..0000000
--- a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package scrapper.environment;
-
-import liquibase.Contexts;
-import liquibase.LabelExpression;
-import liquibase.Liquibase;
-import liquibase.database.Database;
-import liquibase.database.DatabaseFactory;
-import liquibase.database.jvm.JdbcConnection;
-import liquibase.exception.LiquibaseException;
-import liquibase.resource.DirectoryResourceAccessor;
-import org.springframework.boot.jdbc.DataSourceBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.context.ContextConfiguration;
-import org.testcontainers.containers.PostgreSQLContainer;
-
-import javax.sql.DataSource;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.nio.file.Path;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-@ContextConfiguration(classes = IntegrationEnvironment.EnvironmentConfiguration.class)
-public abstract class IntegrationEnvironment {
-
-
- @Configuration
- static class EnvironmentConfiguration{
- @Bean
- public DataSource dataSource() {
- return DataSourceBuilder.create()
- .url(POSTGRES_CONTAINER.getJdbcUrl())
- .username(POSTGRES_CONTAINER.getUsername())
- .password(POSTGRES_CONTAINER.getPassword())
- .build();
- }
-
- @Bean
- public JdbcTemplate jdbcTemplate(DataSource dataSource){
- return new JdbcTemplate(dataSource);
- }
-
- }
-
- static final String IMAGE_VERSION = "postgres:15";
-
- static final PostgreSQLContainer POSTGRES_CONTAINER;
-
- static {
- POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION)
- .withDatabaseName("scrapper")
- .withUsername("lwbeamer")
- .withPassword("2281337");
-
-
- POSTGRES_CONTAINER.start();
- executeMigrations();
- }
-
- private static void executeMigrations() {
- try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(),
- IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) {
- Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn));
- Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations");
- Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database);
- liquibase.update(new Contexts(), new LabelExpression());
- } catch (SQLException | LiquibaseException e) {
- throw new RuntimeException("Failed to execute migrations", e);
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Changelog file not found",e);
- }
- }
-
- public static void stopContainer() {
- POSTGRES_CONTAINER.stop();
- }
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
deleted file mode 100644
index a4ff395..0000000
--- a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package scrapper.environment;
-
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
-
-@EnableAutoConfiguration(exclude = { LiquibaseAutoConfiguration.class })
-public class TestConfiguration {
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
deleted file mode 100644
index 436f01a..0000000
--- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package scrapper.jdbc;
-
-import scrapper.environment.IntegrationEnvironment;
-import scrapper.environment.TestConfiguration;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.annotation.Rollback;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
-import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import ru.tinkoff.edu.java.scrapper.repository.*;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
-
-import java.sql.Timestamp;
-import java.util.List;
-
-@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
-public class JdbcLinkTest extends IntegrationEnvironment {
-
- @Autowired
- private LinkJdbcTemplateRepository linkRepository;
-
- @Autowired
- private LinkRowMapper linkRowMapper;
-
- @Autowired
- private JdbcTemplate jdbcTemplate;
-
-
- @Test
- @Transactional
- @Rollback
- public void addLinkTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
-
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- linkRepository.add(linkToAdd);
-
- List addedLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertNotNull(addedLink.get(0));
- Assertions.assertEquals("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file", addedLink.get(0).getUrl());
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void removeLinkTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
-
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
-
- List afterInsertionLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
-
- linkRepository.remove(afterInsertionLink.get(0).getId());
-
- List afterRemovingLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper);
-
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 1);
- Assertions.assertEquals(afterRemovingLink.size(), 0);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void findAllTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- for (int i = 0; i < 10; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = linkRepository.findAll();
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 10);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void findByUrlTest(){
- List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- for (int i = 0; i < 10; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
- Link foundedByUrlLink = linkRepository.findByUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file0");
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 10);
- Assertions.assertNotNull(foundedByUrlLink);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void updateDateTest(){
- List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
-
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
- Timestamp timestampBefore = new Timestamp(System.currentTimeMillis());
- linkToAdd.setUpdatedAt(timestampBefore);
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
-
-
- List linkBeforeUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
-
- Assertions.assertEquals(linkBeforeUpdate.get(0).getUpdatedAt(),timestampBefore);
-
- linkBeforeUpdate.get(0).setUpdatedAt(new Timestamp(100000));
-
- linkRepository.updateDate(linkBeforeUpdate.get(0));
-
- List linkAfterUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(linkAfterUpdate.get(0).getUpdatedAt(),new Timestamp(100000));
- }
-
-
-
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
deleted file mode 100644
index 0813c59..0000000
--- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package scrapper.jdbc;
-
-import scrapper.environment.IntegrationEnvironment;
-import scrapper.environment.TestConfiguration;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.annotation.Rollback;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
-import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper;
-import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.Link;
-import ru.tinkoff.edu.java.scrapper.model.Relation;
-import ru.tinkoff.edu.java.scrapper.model.User;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository;
-
-import java.sql.Timestamp;
-import java.util.List;
-
-@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
-public class JdbcSubscriptionTest extends IntegrationEnvironment {
-
- @Autowired
- private SubscriptionJdbcTemplateRepository subscriptionRepository;
-
- @Autowired
- private LinkRowMapper linkRowMapper;
-
- @Autowired
- private SubscriptionRowMapper subscriptionRowMapper;
-
- @Autowired
- private JdbcTemplate jdbcTemplate;
-
-
- @Test
- @Transactional
- @Rollback
- public void findLinksByChatTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith");
-
- //всего добавим 20 ссылок
- for (int i = 0; i < 20; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- //из 20-ти ссылок подпишемся лишь на 10
- for (int i = 0; i < 10; i++) {
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
- }
-
- //на оставшиеся 10 подпишем другого пользователя
- for (int i = 10; i < 20; i++) {
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L);
- }
-
- List userLinks = subscriptionRepository.findLinksByChat(42L);
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 20);
- Assertions.assertEquals(userLinks.size(), 10);
- }
-
- @Test
- @Transactional
- @Rollback
- public void removeRelationTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
-
- for (int i = 0; i < 20; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- for (int i = 0; i < 10; i++) {
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
- }
-
- List userLinksBeforeRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- subscriptionRepository.remove(afterInsertionLink.get(0).getId(), 42L);
- subscriptionRepository.remove(afterInsertionLink.get(4).getId(), 42L);
- subscriptionRepository.remove(afterInsertionLink.get(6).getId(), 42L);
-
- List userLinksAfterRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 20);
- Assertions.assertEquals(userLinksBeforeRemove.size(), 10);
- Assertions.assertEquals(userLinksAfterRemove.size(), 7);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void addRelationTest() {
- List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
-
- for (int i = 0; i < 20; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- for (int i = 0; i < 10; i++) {
- Relation relation = new Relation();
- relation.setLinkId(afterInsertionLink.get(i).getId());
- relation.setChatId(42L);
- subscriptionRepository.addRelation(relation);
- }
-
-
- List userLinks = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- Assertions.assertEquals(beforeAddLink.size(), 0);
- Assertions.assertEquals(afterInsertionLink.size(), 20);
- Assertions.assertEquals(userLinks.size(), 10);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void findChatsByLinkTest() {
- List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
-
-
- for (int i = 0; i < 10; i++) {
- User user = new User(42L + i, "robtop21" + i, "Robert", "Polson");
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
- user.getChatId(),
- user.getUsername(),
- user.getFirstName(),
- user.getLastName());
- }
-
-
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
-
- for (int i = 0; i < 7; i++) {
- Relation relation = new Relation();
- relation.setLinkId(afterInsertionLink.get(0).getId());
- relation.setChatId(42L + i);
- subscriptionRepository.addRelation(relation);
- }
-
- List afterSubscribe = subscriptionRepository.findChatsByLink(afterInsertionLink.get(0).getId());
-
- Assertions.assertEquals(beforeAddRelation.size(), 0);
- Assertions.assertEquals(afterSubscribe.size(), 7);
- }
-
- @Test
- @Transactional
- @Rollback
- public void findSubscriptionTest() {
- List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
-
-
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file");
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(0).getId(), 42L);
-
- Relation relation = subscriptionRepository.findSubscription(afterInsertionLink.get(0).getId(), 42L);
-
-
- Assertions.assertEquals(beforeAddRelation.size(),0);
- Assertions.assertEquals(afterInsertionLink.size(),1);
- Assertions.assertNotNull(relation);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void removeAllByUserTest(){
- List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper);
-
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson");
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith");
-
- //всего добавим 20 ссылок
- for (int i = 0; i < 20; i++) {
- Link linkToAdd = new Link();
- linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i);
- linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
- jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt());
- }
-
- List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper);
-
- //из 20-ти ссылок подпишемся лишь на 10
- for (int i = 0; i < 10; i++) {
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L);
- }
-
- //на оставшиеся 10 подпишем другого пользователя
- for (int i = 10; i < 20; i++) {
- jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L);
- }
-
- List userLinksBeforeDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- subscriptionRepository.removeAllByUser(42L);
-
- List userLinksAfterDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L);
-
- Assertions.assertEquals(beforeAddRelation.size(),0);
- Assertions.assertEquals(afterInsertionLink.size(), 20);
- Assertions.assertEquals(userLinksBeforeDelete.size(), 10);
- Assertions.assertEquals(userLinksAfterDelete.size(), 0);
- }
-
-}
diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
deleted file mode 100644
index df7d245..0000000
--- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package scrapper.jdbc;
-
-import scrapper.environment.IntegrationEnvironment;
-import scrapper.environment.TestConfiguration;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.annotation.Rollback;
-import org.springframework.transaction.annotation.Transactional;
-import ru.tinkoff.edu.java.scrapper.ScrapperApplication;
-import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper;
-import ru.tinkoff.edu.java.scrapper.model.User;
-import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository;
-
-import java.util.List;
-
-@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class})
-public class JdbcUserTest extends IntegrationEnvironment {
-
- @Autowired
- private UserJdbcTemplateRepository userRepository;
-
- @Autowired
- private UserRowMapper userRowMapper;
-
- @Autowired
- private JdbcTemplate jdbcTemplate;
-
-
- @Test
- @Transactional
- @Rollback
- public void addUserTest() {
- List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
- User user = new User(42L, "robtop21", "Robert","Polson");
-
-
- userRepository.add(user);
-
- List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
- Assertions.assertEquals(beforeAddUser.size(), 0);
- Assertions.assertEquals(afterAddUser.size(), 1);
- Assertions.assertNotNull(afterAddUser.get(0));
- Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void removeUserTest() {
- List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
- User user = new User(42L, "robtop21", "Robert","Polson");
-
-
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
- user.getChatId(),
- user.getUsername(),
- user.getFirstName(),
- user.getLastName());
-
-
- List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
- userRepository.remove(42L);
-
- List afterRemoveUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
-
- Assertions.assertEquals(beforeAddUser.size(), 0);
- Assertions.assertEquals(afterAddUser.size(), 1);
- Assertions.assertNotNull(afterAddUser.get(0));
- Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L);
- Assertions.assertEquals(afterRemoveUser.size(), 0);
- }
-
- @Test
- @Transactional
- @Rollback
- public void findAllTest() {
- List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
-
- for (int i = 0; i < 10; i++) {
- User user = new User(42L + i, "robtop21" + i, "Robert","Polson");
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
- user.getChatId(),
- user.getUsername(),
- user.getFirstName(),
- user.getLastName());
- }
-
- List afterInsertionUser = userRepository.findAll();
-
- Assertions.assertEquals(beforeAddUser.size(), 0);
- Assertions.assertEquals(afterInsertionUser.size(), 10);
- }
-
-
- @Test
- @Transactional
- @Rollback
- public void findByChatIdTest(){
- List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
-
- for (int i = 0; i < 10; i++) {
- User user = new User(42L + i, "robtop21" + i, "Robert","Polson");
-
- jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)",
- user.getChatId(),
- user.getUsername(),
- user.getFirstName(),
- user.getLastName());
- }
-
- List afterInsertionUser = jdbcTemplate.query("select * from \"user\"", userRowMapper);
-
- User foundedByIdUser = userRepository.findByChatId(42L);
-
- Assertions.assertEquals(beforeAddUser.size(), 0);
- Assertions.assertEquals(afterInsertionUser.size(), 10);
- Assertions.assertNotNull(foundedByIdUser);
-
- }
-
-
-}
\ No newline at end of file
diff --git a/README.md b/README.md
index dbfb550..e69de29 100644
--- a/README.md
+++ b/README.md
@@ -1 +0,0 @@
-# JavaGuava
From 5cc44299996fe74ceebdf1b339c104bd71785041 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 04:09:08 +0500
Subject: [PATCH 5/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20RabbitConfig=20=D0=B8=20=D0=BE=D1=81=D0=BD?=
=?UTF-8?q?=D0=BE=D0=B2=D0=BD=D1=8B=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE?=
=?UTF-8?q?=D0=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/bot/pom.xml | 8 ++-
.../tinkoff/edu/java/bot/BotApplication.java | 5 +-
.../edu/java/bot/api/BotController.java | 2 +-
.../exceptionHandler/BotExceptionHandler.java | 2 +-
.../edu/java/bot/api/model/LinkUpdate.java | 6 --
.../configuration/RabbitMQConfiguration.java | 56 +++---------------
.../bot/configuration/configRecords/Bot.java | 4 --
.../{ => records}/ApplicationConfig.java | 7 ++-
.../java/bot/configuration/records/Bot.java | 4 ++
.../{configRecords => records}/Scheduler.java | 2 +-
.../bot/{firstBot => handler}/BotMain.java | 4 +-
.../java/bot/{firstBot => handler}/DB.java | 2 +-
.../{firstBot => handler}/MessageHandler.java | 4 +-
.../bot/{firstBot => handler}/Updater.java | 2 +-
.../{firstBot => handler}/commands/All.java | 2 +-
.../{firstBot => handler}/commands/Help.java | 2 +-
.../{firstBot => handler}/commands/List.java | 4 +-
.../{firstBot => handler}/commands/Start.java | 2 +-
.../{firstBot => handler}/commands/Track.java | 4 +-
.../commands/Untrack.java | 4 +-
.../bot/{api => }/model/ApiErrorResponse.java | 2 +-
.../edu/java/bot/model/LinkUpdate.java | 6 ++
.../src/main/resources/application.properties | 2 +-
FP/bot/src/main/resources/botapi.yml | 59 -------------------
FP/bot/src/test/java/BotTest.java | 4 +-
FP/bot/target/classes/application.properties | 9 +++
FP/bot/target/consumer7370489798140565122pom | 0
FP/docker-compose.yml | 5 +-
FP/scrapper/pom.xml | 6 ++
.../configuration/ApplicationConfig.java | 21 ++++++-
.../configuration/RabbitMQConfiguration.java | 31 ++++------
.../rabbitmq/ScrapperQueueListener.java | 30 ----------
.../rabbitmq/ScrapperQueueProducer.java | 22 +++----
.../rabbitmq/SendNoticeServiceHttp.java | 11 ++++
.../rabbitmq/SendNoticeServiceImplement.java | 5 ++
.../rabbitmq/SendNoticeServiceQueue.java | 20 +++++++
.../src/main/resources/application.properties | 3 +
37 files changed, 150 insertions(+), 212 deletions(-)
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/{ => records}/ApplicationConfig.java (72%)
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/{configRecords => records}/Scheduler.java (55%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/BotMain.java (89%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/DB.java (94%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/MessageHandler.java (88%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/Updater.java (97%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/All.java (76%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Help.java (91%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/List.java (68%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Start.java (69%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Track.java (77%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Untrack.java (78%)
rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{api => }/model/ApiErrorResponse.java (82%)
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java
delete mode 100644 FP/bot/src/main/resources/botapi.yml
create mode 100644 FP/bot/target/classes/application.properties
create mode 100644 FP/bot/target/consumer7370489798140565122pom
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 60f49bd..3b3c9e6 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -22,7 +22,7 @@
org.springdoc
springdoc-openapi-starter-webmvc-ui
- 2.0.2
+ 2.1.0
org.apache.commons
@@ -84,5 +84,11 @@
maven-surefire-plugin
2.22.2
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+ 3.0.6
+
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
index 312857e..0bdeff0 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
@@ -3,8 +3,8 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig;
-import ru.tinkoff.edu.java.bot.firstBot.BotMain;
+import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
+import ru.tinkoff.edu.java.bot.handler.BotMain;
@SpringBootApplication
@@ -14,7 +14,6 @@ public class BotApplication
public static void main(String[] args){
var ctx = SpringApplication.run(BotApplication.class, args);
ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
-
BotMain bot = new BotMain(config.bot().token());
bot.start();
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
index 25186cf..6a559cf 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
@@ -1,7 +1,7 @@
package ru.tinkoff.edu.java.bot.api;
import org.springframework.web.bind.annotation.*;
-import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
+import ru.tinkoff.edu.java.bot.model.LinkUpdate;
@RestController
@RequestMapping("/update")
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
index 732a56e..5beb1bd 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java
@@ -6,7 +6,7 @@
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-import ru.tinkoff.edu.java.bot.api.model.ApiErrorResponse;
+import ru.tinkoff.edu.java.bot.model.ApiErrorResponse;
@RestControllerAdvice
public class BotExceptionHandler {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
deleted file mode 100644
index 0f44607..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ru.tinkoff.edu.java.bot.api.model;
-
-import java.util.List;
-
-public record LinkUpdate(long id, String url, String description, List tgChatIds) {
-}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
index b944fc5..86178a0 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -1,16 +1,11 @@
package ru.tinkoff.edu.java.bot.configuration;
import org.springframework.amqp.core.*;
-import org.springframework.amqp.support.converter.ClassMapper;
-import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
-
-import java.util.HashMap;
-import java.util.Map;
+import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
@Configuration
public class RabbitMQConfiguration {
@@ -22,57 +17,22 @@ public RabbitMQConfiguration(ApplicationConfig config) {
}
@Bean
- Queue queue() {
- return QueueBuilder.durable(config.queueName())
- .withArgument("x-dead-letter-exchange", config.exchangeName())
- .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq")
- .build();
- }
-
-
- @Bean
- Queue deadLetterQueue() {
- return new Queue(config.queueName() + ".dlq", true);
+ public DirectExchange exchange() {
+ return new DirectExchange(config.exchange());
}
@Bean
- DirectExchange exchange() {
- return new DirectExchange(config.exchangeName());
+ public Queue queue() {
+ return new Queue(config.queue());
}
@Bean
- Binding binding(Queue queue, DirectExchange exchange) {
+ public Binding binding(Queue queue, DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(config.routingKey());
}
@Bean
- Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) {
- return BindingBuilder.bind(deadLetterQueue).to(exchange).with(config.routingKey() + ".dlq");
- }
-
- @Bean
- public ClassMapper classMapper() {
- Map> mappings = new HashMap<>();
- mappings.put("ru.tinkoff.edu.java.bot.api.model.LinkUpdate", LinkUpdate.class);
-
- DefaultClassMapper classMapper = new DefaultClassMapper();
- classMapper.setTrustedPackages("ru.tinkoff.edu.java.bot.api.model.*");
- classMapper.setIdClassMapping(mappings);
- return classMapper;
- }
-
- @Bean
- public MessageConverter jsonMessageConverter(ClassMapper classMapper) {
- Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
- jsonConverter.setClassMapper(classMapper);
- return jsonConverter;
+ public MessageConverter jsonMessageConverter() {
+ return new Jackson2JsonMessageConverter();
}
-
-
- @Bean
- public ScrapperQueueListener scrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) {
- return new ScrapperQueueListener(rabbitTemplate, updateService);
- }
-
-
}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
deleted file mode 100644
index 37f4842..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package ru.tinkoff.edu.java.bot.configuration.configRecords;
-
-public record Bot(String token, String name) {
-}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
similarity index 72%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
index 49ce5e3..5ee81b6 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
@@ -1,11 +1,9 @@
-package ru.tinkoff.edu.java.bot.configuration;
+package ru.tinkoff.edu.java.bot.configuration.records;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
-import ru.tinkoff.edu.java.bot.configuration.configRecords.Bot;
-import ru.tinkoff.edu.java.bot.configuration.configRecords.Scheduler;
@Validated
@EnableScheduling
@@ -13,6 +11,9 @@
public record ApplicationConfig(
@NotNull String test,
@NotNull Scheduler scheduler,
+ String exchange,
+ String routingKey,
+ String queue,
Bot bot
) {
}
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java
new file mode 100644
index 0000000..0a1fff4
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java
@@ -0,0 +1,4 @@
+package ru.tinkoff.edu.java.bot.configuration.records;
+
+public record Bot(String token, String name) {
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
similarity index 55%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
index 08278f6..daed115 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.configuration.configRecords;
+package ru.tinkoff.edu.java.bot.configuration.records;
import java.time.Duration;
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
similarity index 89%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
index f758472..33e72c8 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
@@ -1,9 +1,9 @@
-package ru.tinkoff.edu.java.bot.firstBot;
+package ru.tinkoff.edu.java.bot.handler;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.request.SendMessage;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
@EnableConfigurationProperties(ApplicationConfig.class)
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
similarity index 94%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
index 486a886..6b57338 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.firstBot;
+package ru.tinkoff.edu.java.bot.handler;
import java.util.ArrayList;
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
similarity index 88%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
index f003c84..56cfd57 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
@@ -1,6 +1,6 @@
-package ru.tinkoff.edu.java.bot.firstBot;
+package ru.tinkoff.edu.java.bot.handler;
-import ru.tinkoff.edu.java.bot.firstBot.commands.All;
+import ru.tinkoff.edu.java.bot.handler.commands.All;
public class MessageHandler extends All {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
similarity index 97%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
index a01e4d9..746ad5e 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.firstBot;
+package ru.tinkoff.edu.java.bot.handler;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener;
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
similarity index 76%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
index 991b177..5f63723 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
public class All implements List, Start, Track, Untrack, Help {
protected String unknow() {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
similarity index 91%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
index 0761e05..4d0da5a 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
public interface Help {
default String help() {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
similarity index 68%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
index 8673887..fdadd4f 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
@@ -1,6 +1,6 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
-import ru.tinkoff.edu.java.bot.firstBot.DB;
+import ru.tinkoff.edu.java.bot.handler.DB;
public interface List {
default String list() {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
similarity index 69%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
index d58c89c..5c4b5d7 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
public interface Start {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
similarity index 77%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
index 0f4669e..fcd1042 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
@@ -1,6 +1,6 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
-import ru.tinkoff.edu.java.bot.firstBot.DB;
+import ru.tinkoff.edu.java.bot.handler.DB;
public interface Track {
default String track(String link) {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
similarity index 78%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
index 6550daf..a196195 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
@@ -1,6 +1,6 @@
-package ru.tinkoff.edu.java.bot.firstBot.commands;
+package ru.tinkoff.edu.java.bot.handler.commands;
-import ru.tinkoff.edu.java.bot.firstBot.DB;
+import ru.tinkoff.edu.java.bot.handler.DB;
public interface Untrack {
default String untrack(String link) {
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
similarity index 82%
rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java
rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
index f43001e..57e1c06 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.bot.api.model;
+package ru.tinkoff.edu.java.bot.model;
import java.util.List;
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java
new file mode 100644
index 0000000..d6b250b
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.bot.model;
+
+import java.util.List;
+
+public record LinkUpdate(String url) {
+}
\ No newline at end of file
diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties
index fedebeb..95d9a47 100644
--- a/FP/bot/src/main/resources/application.properties
+++ b/FP/bot/src/main/resources/application.properties
@@ -3,4 +3,4 @@ springdoc.swagger-ui.path=/swagger-ui
app.scheduler.interval=50000
app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
app.bot.name=@SFRETbot
-server.port=8081
+server.port=8081
\ No newline at end of file
diff --git a/FP/bot/src/main/resources/botapi.yml b/FP/bot/src/main/resources/botapi.yml
deleted file mode 100644
index 489441e..0000000
--- a/FP/bot/src/main/resources/botapi.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-openapi: 3.0.1
-info:
- title: Bot API
- version: 1.0.0
- contact:
- name: Alexander Biryukov
- url: https://github.com
-paths:
- /updates:
- post:
- summary: Отправить обновление
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/LinkUpdate'
- required: true
- responses:
- '200':
- description: Обновление обработано
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
-components:
- schemas:
- ApiErrorResponse:
- type: object
- properties:
- description:
- type: string
- code:
- type: string
- exceptionName:
- type: string
- exceptionMessage:
- type: string
- stacktrace:
- type: array
- items:
- type: string
- LinkUpdate:
- type: object
- properties:
- id:
- type: integer
- format: int64
- url:
- type: string
- format: uri
- description:
- type: string
- tgChatIds:
- type: array
- items:
- type: integer
- format: int64
diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java
index 1548bc9..4e14a70 100644
--- a/FP/bot/src/test/java/BotTest.java
+++ b/FP/bot/src/test/java/BotTest.java
@@ -1,7 +1,7 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import ru.tinkoff.edu.java.bot.firstBot.DB;
-import ru.tinkoff.edu.java.bot.firstBot.MessageHandler;
+import ru.tinkoff.edu.java.bot.handler.DB;
+import ru.tinkoff.edu.java.bot.handler.MessageHandler;
public class BotTest {
diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties
new file mode 100644
index 0000000..6600aaa
--- /dev/null
+++ b/FP/bot/target/classes/application.properties
@@ -0,0 +1,9 @@
+app.test=123
+springdoc.swagger-ui.path=/swagger-ui
+app.scheduler.interval=50000
+app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
+app.bot.name=@SFRETbot
+server.port=8081
+app.exchange=my-direct-exchange
+app.queue=my-queue
+app.routingKey=my-routing-key
\ No newline at end of file
diff --git a/FP/bot/target/consumer7370489798140565122pom b/FP/bot/target/consumer7370489798140565122pom
new file mode 100644
index 0000000..e69de29
diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml
index b9f4994..3eeb07e 100644
--- a/FP/docker-compose.yml
+++ b/FP/docker-compose.yml
@@ -36,6 +36,7 @@ services:
- ./migrations:/liquibase/changelog
networks:
- backend
+
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
@@ -44,8 +45,8 @@ services:
volumes:
- ./rabbitmq:/var/lib/rabbitmq
environment:
- - RABBITMQ_DEFAULT_USER=root
- - RABBITMQ_DEFAULT_PASS=root
+ - RABBITMQ_DEFAULT_USER=guest
+ - RABBITMQ_DEFAULT_PASS=guest
networks:
backend:
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index bbd37fb..ff9b45a 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -112,5 +112,11 @@
maven-surefire-plugin
2.22.2
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+ 3.0.6
+
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
index 3a82d60..ec1a1e8 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -1,9 +1,15 @@
package ru.tinkoff.edu.java.scrapper.configuration;
import jakarta.validation.constraints.NotNull;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceHttp;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceImplement;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceQueue;
import ru.tinkoff.edu.java.scrapper.schedule.Scheduler;
@Validated
@@ -11,5 +17,16 @@
@EnableScheduling
public record ApplicationConfig(
@NotNull String test,
- @NotNull Scheduler scheduler
-) {}
+ @NotNull Scheduler scheduler,
+ @Value("${useQueue}") boolean useQueue
+) {
+@Bean
+public SendNoticeServiceImplement notificationService(ScrapperQueueProducer queueProducer/*, BotClient botClient */) {
+ if (useQueue) {
+ return new SendNoticeServiceQueue(queueProducer);
+ } else {
+ /* Заглушка */
+ return new SendNoticeServiceHttp();
+ }
+}
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
index b0d9449..40ffb29 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -1,17 +1,13 @@
package ru.tinkoff.edu.java.scrapper.configuration;
import org.springframework.amqp.core.*;
-import org.springframework.amqp.rabbit.connection.ConnectionFactory;
-import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
-import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
-import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
+import org.springframework.context.annotation.Configuration;
+import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
-@SpringBootApplication
+@Configuration
public class RabbitMQConfiguration {
private final ApplicationConfig config;
@@ -19,21 +15,19 @@ public class RabbitMQConfiguration {
public RabbitMQConfiguration(ApplicationConfig config) {
this.config = config;
}
+
@Bean
- Queue queue() {
- return QueueBuilder.durable(config.queueName())
- .withArgument("x-dead-letter-exchange", config.exchangeName())
- .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq")
- .build();
+ public DirectExchange exchange() {
+ return new DirectExchange(config.exchange());
}
@Bean
- DirectExchange exchange() {
- return new DirectExchange(config.exchangeName());
+ public Queue queue() {
+ return new Queue(config.queue());
}
@Bean
- Binding binding(Queue queue, DirectExchange exchange) {
+ public Binding binding(Queue queue, DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(config.routingKey());
}
@@ -41,9 +35,4 @@ Binding binding(Queue queue, DirectExchange exchange) {
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
-
- @Bean
- public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) {
- return new ScrapperQueueProducer(rabbitTemplate, config);
- }
-}
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
deleted file mode 100644
index 3507568..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.amqp.core.AmqpTemplate;
-import org.springframework.amqp.rabbit.annotation.RabbitHandler;
-import org.springframework.amqp.rabbit.annotation.RabbitListener;
-import ru.tinkoff.edu.java.bot.dto.LinkUpdate;
-
-@RabbitListener(queues = "${app.queue-name}")
-@Slf4j
-public class ScrapperQueueListener {
-
-
- private final AmqpTemplate rabbitTemplate;
-
- private final UpdateService updateService;
-
-
- public ScrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) {
- this.rabbitTemplate = rabbitTemplate;
- this.updateService = updateService;
- }
-
- @RabbitHandler
- public void receiver(LinkUpdate update) {
- log.info("Сообщение об обновлении получено: "+update);
-// throw new RuntimeException("test exception");
- updateService.updateLink(update);
- }
-
-
-}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
index 84baa14..60990fd 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
@@ -1,27 +1,27 @@
package ru.tinkoff.edu.java.scrapper.rabbitmq;
-import lombok.RequiredArgsConstructor;
-import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.bot.api.model.LinkUpdate;
-
-import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.bot.configuration.RabbitMQConfiguration;
+import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
+import ru.tinkoff.edu.java.bot.model.LinkUpdate;
@Service
public class ScrapperQueueProducer {
-
- private final AmqpTemplate rabbitTemplate;
+ private final RabbitTemplate rabbitTemplate;
private final ApplicationConfig config;
-
- public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig config) {
+ public ScrapperQueueProducer(RabbitTemplate rabbitTemplate, ApplicationConfig config) {
this.rabbitTemplate = rabbitTemplate;
this.config = config;
}
public void send(LinkUpdate update) {
- rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update);
- System.out.println("Mess update: " + update);
+ String exchange = config.exchange(); // Имя обмена
+ String routingKey = config.routingKey(); // Маршрутный ключ
+
+ rabbitTemplate.convertAndSend(exchange, routingKey, update);
}
}
+
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java
new file mode 100644
index 0000000..7067329
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class SendNoticeServiceHttp implements SendNoticeServiceImplement {
+ @Override
+ public void sendNotice(String message) {
+ // TO DO WHERE CLIENT
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java
new file mode 100644
index 0000000..680f7fe
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+public interface SendNoticeServiceImplement {
+ void sendNotice(String notice);
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
new file mode 100644
index 0000000..c1ccbe3
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
@@ -0,0 +1,20 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+import org.springframework.stereotype.Service;
+import ru.tinkoff.edu.java.bot.model.LinkUpdate;
+
+@Service
+public class SendNoticeServiceQueue implements SendNoticeServiceImplement {
+ private final ScrapperQueueProducer queueProducer;
+
+ public SendNoticeServiceQueue(ScrapperQueueProducer queueProducer) {
+ this.queueProducer = queueProducer;
+ }
+
+ @Override
+ public void sendNotice(String message) {
+ // Отправка сообщения в очередь через ScrapperQueueProducer
+ LinkUpdate update = new LinkUpdate(message);
+ queueProducer.send(update);
+ }
+}
diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties
index 00d78d2..9bdcc75 100644
--- a/FP/scrapper/src/main/resources/application.properties
+++ b/FP/scrapper/src/main/resources/application.properties
@@ -3,3 +3,6 @@ springdoc.swagger-ui.path=/swagger-ui
app.scheduler.interval=5000
git.link=https://github.com/Ray-Not/JavaGuava
stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c
+app.exchange=my-direct-exchange
+app.queue=my-queue
+app.routingKey=my-routing-key
\ No newline at end of file
From d086f8d834180439028a4732d788682411293475 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 05:44:05 +0500
Subject: [PATCH 6/9] =?UTF-8?q?=D0=92=D1=81=D0=B5=20=D1=80=D0=B5=D0=B0?=
=?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=BE,=20=D0=BD?=
=?UTF-8?q?=D0=B5=D1=82=20=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0=20?=
=?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?=
=?UTF-8?q?=D0=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../configuration/RabbitMQConfiguration.java | 26 ++-
FP/bot/target/classes/application.properties | 5 +-
FP/scrapper/pom.xml | 6 -
.../java/scrapper/ScrapperApplication.java | 12 +-
.../scrapper/api/ScrapperControllerLinks.java | 4 +-
.../scrapper/api/model/AddLinkRequest.java | 3 -
.../scrapper/api/model/UpdateService.java | 4 -
.../configuration/ApplicationConfig.java | 7 +-
.../configuration/RabbitMQConfiguration.java | 41 +++-
.../java/scrapper/jdbc/JdbcLinkService.java | 6 +-
.../scrapper/jdbc/mappers/ChatMapper.java | 2 +-
.../scrapper/jdbc/mappers/LinkChatMapper.java | 2 +-
.../scrapper/jdbc/mappers/LinkMapper.java | 2 +-
.../jdbc/operations/LinkChatOperations.java | 2 +-
.../jdbc/operations/LinkOperations.java | 6 +-
.../java/scrapper/model/AddLinkRequest.java | 3 +
.../{api => }/model/ChatResponse.java | 2 +-
.../{api => }/model/LinkChatResponse.java | 2 +-
.../{api => }/model/LinkResponse.java | 2 +-
.../edu/java/scrapper/model/LinkUpdate.java | 4 +
.../{api => }/model/ListLinksResponse.java | 2 +-
.../{api => }/model/RemoveLinkRequest.java | 2 +-
.../java/scrapper/model/UpdateService.java | 4 +
.../HandleNoticeServiceImplement.java | 5 +
.../rabbitmq/HandleNoticeServiceQueue.java | 16 ++
.../rabbitmq/ScrapperQueueListener.java | 19 ++
.../rabbitmq/ScrapperQueueProducer.java | 9 +-
.../rabbitmq/SendNoticeServiceQueue.java | 2 +-
.../schedule/LinkUpdaterScheduler.java | 84 ++++----
.../src/main/resources/application.properties | 3 +-
.../target/classes/application.properties | 9 +
FP/scrapper/target/classes/scrapperapi.yml | 184 ++++++++++++++++++
32 files changed, 388 insertions(+), 92 deletions(-)
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/ChatResponse.java (52%)
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/LinkChatResponse.java (55%)
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/LinkResponse.java (51%)
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/ListLinksResponse.java (66%)
rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/RemoveLinkRequest.java (50%)
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
create mode 100644 FP/scrapper/target/classes/application.properties
create mode 100644 FP/scrapper/target/classes/scrapperapi.yml
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
index 86178a0..1616669 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -7,6 +7,8 @@
import org.springframework.context.annotation.Configuration;
import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
+import java.util.Collections;
+
@Configuration
public class RabbitMQConfiguration {
@@ -23,16 +25,32 @@ public DirectExchange exchange() {
@Bean
public Queue queue() {
- return new Queue(config.queue());
+ return QueueBuilder.durable(config.queue())
+ .withArgument("x-dead-letter-exchange",config.queue() + ".dlq")
+ .build();
}
@Bean
public Binding binding(Queue queue, DirectExchange exchange) {
- return BindingBuilder.bind(queue).to(exchange).with(config.routingKey());
+ return BindingBuilder.bind(queue)
+ .to(exchange)
+ .with(config.routingKey());
+ }
+
+ @Bean
+ public DirectExchange dlqExchange() {
+ return new DirectExchange(config.exchange() + ".dlq");
+ }
+
+ @Bean
+ public Queue dlqQueue() {
+ return QueueBuilder.durable(config.queue() + ".dlq").build();
}
@Bean
- public MessageConverter jsonMessageConverter() {
- return new Jackson2JsonMessageConverter();
+ public Binding dlqBinding() {
+ return BindingBuilder.bind(dlqQueue())
+ .to(dlqExchange())
+ .with(config.routingKey());
}
}
\ No newline at end of file
diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties
index 6600aaa..95d9a47 100644
--- a/FP/bot/target/classes/application.properties
+++ b/FP/bot/target/classes/application.properties
@@ -3,7 +3,4 @@ springdoc.swagger-ui.path=/swagger-ui
app.scheduler.interval=50000
app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
app.bot.name=@SFRETbot
-server.port=8081
-app.exchange=my-direct-exchange
-app.queue=my-queue
-app.routingKey=my-routing-key
\ No newline at end of file
+server.port=8081
\ No newline at end of file
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index ff9b45a..fad5590 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -71,12 +71,6 @@
3.0.5
-
- org.example
- bot
- 1.0
- compile
-
org.testcontainers
junit-jupiter
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
index 959ba70..c2e1b98 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -1,12 +1,15 @@
package ru.tinkoff.edu.java.scrapper;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceQueue;
@SpringBootApplication
@EnableConfigurationProperties(ApplicationConfig.class)
@@ -16,6 +19,11 @@ public class ScrapperApplication {
public static void main(String[] args) {
var ctx = SpringApplication.run(ScrapperApplication.class, args);
ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
- System.out.println("----------------------------------------------------------------");
+ System.out.println("----------------------------------------------------------------" + config);
+ SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer(
+ new RabbitTemplate(),
+ config
+ ));
+ notificationService.sendNotice("Вот-вот");
}
}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
index c4ad690..47540df 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
@@ -5,8 +5,10 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import ru.tinkoff.edu.java.scrapper.api.model.*;
import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService;
+import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest;
import java.util.List;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
deleted file mode 100644
index 7282291..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java
+++ /dev/null
@@ -1,3 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
-
-public record AddLinkRequest(String link) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
deleted file mode 100644
index 006d0b0..0000000
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
-
-public class UpdateService {
-}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
index ec1a1e8..52af096 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -1,9 +1,11 @@
package ru.tinkoff.edu.java.scrapper.configuration;
import jakarta.validation.constraints.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
@@ -18,7 +20,10 @@
public record ApplicationConfig(
@NotNull String test,
@NotNull Scheduler scheduler,
- @Value("${useQueue}") boolean useQueue
+ Boolean useQueue,
+ String exchange,
+ String routingKey,
+ String queue
) {
@Bean
public SendNoticeServiceImplement notificationService(ScrapperQueueProducer queueProducer/*, BotClient botClient */) {
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
index 40ffb29..f89b8b8 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -1,11 +1,19 @@
package ru.tinkoff.edu.java.scrapper.configuration;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
import org.springframework.amqp.core.*;
+import org.springframework.amqp.support.converter.ClassMapper;
+import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.model.LinkUpdate;
+
+import java.util.HashMap;
+import java.util.Map;
@Configuration
public class RabbitMQConfiguration {
@@ -23,7 +31,9 @@ public DirectExchange exchange() {
@Bean
public Queue queue() {
- return new Queue(config.queue());
+ return QueueBuilder.durable(config.queue())
+ .withArgument("x-dead-letter-exchange", config.queue() + ".dlq")
+ .build();
}
@Bean
@@ -32,7 +42,30 @@ public Binding binding(Queue queue, DirectExchange exchange) {
}
@Bean
- public MessageConverter jsonMessageConverter() {
- return new Jackson2JsonMessageConverter();
+ public ClassMapper classMapper(){
+ Map> mappings = new HashMap<>();
+ mappings.put("ru.tinkoff.edu.java.scrapper.model.LinkUpdate", LinkUpdate.class);
+
+ DefaultClassMapper classMapper = new DefaultClassMapper();
+ classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.model.*");
+ classMapper.setIdClassMapping(mappings);
+ return classMapper;
+ }
+
+ @Bean
+ public MessageConverter jsonMessageConverter(ClassMapper classMapper){
+ Jackson2JsonMessageConverter jsonConverter=new Jackson2JsonMessageConverter();
+ jsonConverter.setClassMapper(classMapper);
+ return jsonConverter;
+ }
+
+ @Bean
+ public ConnectionFactory connectionFactory() {
+ CachingConnectionFactory connectionFactory = new CachingConnectionFactory("0.0.0.0", 5672);
+ connectionFactory.setUsername("guest");
+ connectionFactory.setPassword("guest");
+ // Другие настройки, если необходимо
+
+ return connectionFactory;
}
}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
index 6eb52b5..380ca48 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
@@ -3,9 +3,9 @@
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import ru.tinkoff.edu.java.linkparser.LinkParser;
-import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest;
-import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
-import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest;
import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*;
import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
index b979f13..026139a 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java
@@ -1,7 +1,7 @@
package ru.tinkoff.edu.java.scrapper.jdbc.mappers;
import org.springframework.jdbc.core.RowMapper;
-import ru.tinkoff.edu.java.scrapper.api.model.ChatResponse;
+import ru.tinkoff.edu.java.scrapper.model.ChatResponse;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
index e9e98e7..4b52ef9 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java
@@ -1,7 +1,7 @@
package ru.tinkoff.edu.java.scrapper.jdbc.mappers;
import org.springframework.jdbc.core.RowMapper;
-import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse;
+import ru.tinkoff.edu.java.scrapper.model.LinkChatResponse;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
index ac50329..914d113 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java
@@ -2,7 +2,7 @@
import org.springframework.jdbc.core.RowMapper;
-import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.model.LinkResponse;
import java.sql.ResultSet;
import java.sql.SQLException;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
index 29cfe7d..e40b248 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java
@@ -1,7 +1,7 @@
package ru.tinkoff.edu.java.scrapper.jdbc.operations;
import org.springframework.jdbc.core.JdbcTemplate;
-import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse;
+import ru.tinkoff.edu.java.scrapper.model.LinkChatResponse;
import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkChatMapper;
import java.util.List;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
index ad282fe..7907633 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
@@ -1,9 +1,9 @@
package ru.tinkoff.edu.java.scrapper.jdbc.operations;
import org.springframework.jdbc.core.JdbcTemplate;
-import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest;
-import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse;
-import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest;
+import ru.tinkoff.edu.java.scrapper.model.LinkResponse;
+import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest;
import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper;
import java.util.ArrayList;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java
new file mode 100644
index 0000000..e7f8aa4
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java
@@ -0,0 +1,3 @@
+package ru.tinkoff.edu.java.scrapper.model;
+
+public record AddLinkRequest(String link) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
similarity index 52%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
index eb09922..d1e1893 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
@@ -1,3 +1,3 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
+package ru.tinkoff.edu.java.scrapper.model;
public record ChatResponse(long chat_id, int id) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
similarity index 55%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
index 1f62147..6ef6a2c 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
@@ -1,3 +1,3 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
+package ru.tinkoff.edu.java.scrapper.model;
public record LinkChatResponse(int linkid, int chatid) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
similarity index 51%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
index 023172d..d5192ab 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
@@ -1,3 +1,3 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
+package ru.tinkoff.edu.java.scrapper.model;
public record LinkResponse(String url, int id) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java
new file mode 100644
index 0000000..ba13a15
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java
@@ -0,0 +1,4 @@
+package ru.tinkoff.edu.java.scrapper.model;
+
+public record LinkUpdate(String url) {
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
similarity index 66%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
index 9c9ed5b..6a04698 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
@@ -1,4 +1,4 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
+package ru.tinkoff.edu.java.scrapper.model;
import java.util.*;
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
similarity index 50%
rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
index 3e2a8f0..1f9b6ee 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
@@ -1,3 +1,3 @@
-package ru.tinkoff.edu.java.scrapper.api.model;
+package ru.tinkoff.edu.java.scrapper.model;
public record RemoveLinkRequest(String link) {}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java
new file mode 100644
index 0000000..4d53819
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java
@@ -0,0 +1,4 @@
+package ru.tinkoff.edu.java.scrapper.model;
+
+public class UpdateService {
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java
new file mode 100644
index 0000000..8432dad
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+public interface HandleNoticeServiceImplement {
+ void handleNotification(String message);
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java
new file mode 100644
index 0000000..deb53c3
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java
@@ -0,0 +1,16 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class HandleNoticeServiceQueue implements HandleNoticeServiceImplement {
+
+ Logger log = LoggerFactory.getLogger(HandleNoticeServiceQueue.class);
+ @Override
+ public void handleNotification(String message) {
+ log.info("Пришло уведомление с Rabbit очереди: " + message);
+ }
+}
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
new file mode 100644
index 0000000..1d587b6
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java
@@ -0,0 +1,19 @@
+package ru.tinkoff.edu.java.scrapper.rabbitmq;
+
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import ru.tinkoff.edu.java.scrapper.model.LinkUpdate;
+
+@RabbitListener(queues = "${app.queue}")
+public class ScrapperQueueListener {
+ private final HandleNoticeServiceQueue handleNoticeServiceQueue;
+
+ public ScrapperQueueListener(HandleNoticeServiceQueue notificationHandler) {
+ this.handleNoticeServiceQueue = notificationHandler;
+ }
+
+ @RabbitHandler
+ public void receiver(LinkUpdate update) {
+ handleNoticeServiceQueue.handleNotification(update.url());
+ }
+}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
index 60990fd..c592025 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
@@ -1,12 +1,13 @@
package ru.tinkoff.edu.java.scrapper.rabbitmq;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.bot.configuration.RabbitMQConfiguration;
-import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
-import ru.tinkoff.edu.java.bot.model.LinkUpdate;
+import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.model.LinkUpdate;
@Service
+
public class ScrapperQueueProducer {
private final RabbitTemplate rabbitTemplate;
@@ -21,7 +22,7 @@ public void send(LinkUpdate update) {
String exchange = config.exchange(); // Имя обмена
String routingKey = config.routingKey(); // Маршрутный ключ
- rabbitTemplate.convertAndSend(exchange, routingKey, update);
+ rabbitTemplate.convertAndSend(exchange, routingKey, update.url());
}
}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
index c1ccbe3..70eed14 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java
@@ -1,7 +1,7 @@
package ru.tinkoff.edu.java.scrapper.rabbitmq;
import org.springframework.stereotype.Service;
-import ru.tinkoff.edu.java.bot.model.LinkUpdate;
+import ru.tinkoff.edu.java.scrapper.model.LinkUpdate;
@Service
public class SendNoticeServiceQueue implements SendNoticeServiceImplement {
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
index 10c9caa..63acc43 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
@@ -18,46 +18,46 @@
@Service
public class LinkUpdaterScheduler implements LinkOperations {
- private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
-
- private final JdbcTemplate jdbcTemplate;
- ArrayList link_list = new ArrayList<>();
- static int ix = 0;
- ClientConfiguration client = new ClientConfiguration();
- LinkParser pars = new LinkParser();
- boolean git_link_is_activity;
- boolean stack_link_is_activity;
-
- public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- }
-
- @Scheduled(fixedDelayString = "${app.scheduler.interval}")
- public void update() {
- int i;
- for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){
- if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) {
- link_list.add(i_getAllIds(jdbcTemplate).get(i).url());
- }
- }
- try {
- client.gitHubClient(pars.getLink(link_list.get(ix)));
- git_link_is_activity = true;
- } catch (WebClientResponseException e) {
- git_link_is_activity = false;
- }
- try {
- client.stackOverflowClient(pars.getLink(link_list.get(ix)));
- stack_link_is_activity = true;
- } catch (WebClientResponseException ignored) {
- stack_link_is_activity = false;
- }
- if (!(git_link_is_activity || stack_link_is_activity)) {
- String link = "Ссылка %s устарела";
- link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url());
- LOGGER.log(Level.INFO, link);
- }
- ix++;
- if (ix == link_list.size()) ix = 0;
- }
+// private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+//
+// private final JdbcTemplate jdbcTemplate;
+// ArrayList link_list = new ArrayList<>();
+// static int ix = 0;
+// ClientConfiguration client = new ClientConfiguration();
+// LinkParser pars = new LinkParser();
+// boolean git_link_is_activity;
+// boolean stack_link_is_activity;
+//
+// public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) {
+// this.jdbcTemplate = jdbcTemplate;
+// }
+//
+// @Scheduled(fixedDelayString = "${app.scheduler.interval}")
+// public void update() {
+// int i;
+// for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){
+// if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) {
+// link_list.add(i_getAllIds(jdbcTemplate).get(i).url());
+// }
+// }
+// try {
+// client.gitHubClient(pars.getLink(link_list.get(ix)));
+// git_link_is_activity = true;
+// } catch (WebClientResponseException e) {
+// git_link_is_activity = false;
+// }
+// try {
+// client.stackOverflowClient(pars.getLink(link_list.get(ix)));
+// stack_link_is_activity = true;
+// } catch (WebClientResponseException ignored) {
+// stack_link_is_activity = false;
+// }
+// if (!(git_link_is_activity || stack_link_is_activity)) {
+// String link = "Ссылка %s устарела";
+// link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url());
+// LOGGER.log(Level.INFO, link);
+// }
+// ix++;
+// if (ix == link_list.size()) ix = 0;
+// }
}
diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties
index 9bdcc75..d4267e9 100644
--- a/FP/scrapper/src/main/resources/application.properties
+++ b/FP/scrapper/src/main/resources/application.properties
@@ -5,4 +5,5 @@ git.link=https://github.com/Ray-Not/JavaGuava
stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c
app.exchange=my-direct-exchange
app.queue=my-queue
-app.routingKey=my-routing-key
\ No newline at end of file
+app.routingKey=my-routing-key
+app.useQueue=True
\ No newline at end of file
diff --git a/FP/scrapper/target/classes/application.properties b/FP/scrapper/target/classes/application.properties
new file mode 100644
index 0000000..d4267e9
--- /dev/null
+++ b/FP/scrapper/target/classes/application.properties
@@ -0,0 +1,9 @@
+app.test=123
+springdoc.swagger-ui.path=/swagger-ui
+app.scheduler.interval=5000
+git.link=https://github.com/Ray-Not/JavaGuava
+stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c
+app.exchange=my-direct-exchange
+app.queue=my-queue
+app.routingKey=my-routing-key
+app.useQueue=True
\ No newline at end of file
diff --git a/FP/scrapper/target/classes/scrapperapi.yml b/FP/scrapper/target/classes/scrapperapi.yml
new file mode 100644
index 0000000..c98cf7d
--- /dev/null
+++ b/FP/scrapper/target/classes/scrapperapi.yml
@@ -0,0 +1,184 @@
+openapi: 3.0.1
+info:
+ title: Scrapper API
+ version: 1.0.0
+ contact:
+ name: Alexander Biryukov
+ url: https://github.com
+paths:
+ /tg-chat/{id}:
+ post:
+ summary: Зарегистрировать чат
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Чат зарегистрирован
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ delete:
+ summary: Удалить чат
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Чат успешно удалён
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '404':
+ description: Чат не существует
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ /links:
+ get:
+ summary: Получить все отслеживаемые ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Ссылки успешно получены
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ListLinksResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ post:
+ summary: Добавить отслеживание ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddLinkRequest'
+ required: true
+ responses:
+ '200':
+ description: Ссылка успешно добавлена
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LinkResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ delete:
+ summary: Убрать отслеживание ссылки
+ parameters:
+ - name: Tg-Chat-Id
+ in: header
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RemoveLinkRequest'
+ required: true
+ responses:
+ '200':
+ description: Ссылка успешно убрана
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/LinkResponse'
+ '400':
+ description: Некорректные параметры запроса
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '404':
+ description: Ссылка не найдена
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+components:
+ schemas:
+ LinkResponse:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ url:
+ type: string
+ format: uri
+ ApiErrorResponse:
+ type: object
+ properties:
+ description:
+ type: string
+ code:
+ type: string
+ exceptionName:
+ type: string
+ exceptionMessage:
+ type: string
+ stacktrace:
+ type: array
+ items:
+ type: string
+ AddLinkRequest:
+ type: object
+ properties:
+ link:
+ type: string
+ format: uri
+ ListLinksResponse:
+ type: object
+ properties:
+ links:
+ type: array
+ items:
+ $ref: '#/components/schemas/LinkResponse'
+ size:
+ type: integer
+ format: int32
+ RemoveLinkRequest:
+ type: object
+ properties:
+ link:
+ type: string
+ format: uri
From 86e51d7ba653c8fede6ab23199dacb668b238c17 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 16:50:01 +0500
Subject: [PATCH 7/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=BD?=
=?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B0?=
=?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=91=D0=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +-
FP/bot/target/classes/application.properties | 6 -
FP/bot/target/consumer7370489798140565122pom | 0
FP/docker-compose.yml | 1 +
FP/migrations/chats_links_scheme.sql | 8 +
FP/migrations/master.xml | 11 ++
.../configuration/RabbitMQConfiguration.java | 2 +-
.../src/main/resources/scrapperapi.yml | 184 ------------------
.../target/classes/application.properties | 9 -
FP/scrapper/target/classes/scrapperapi.yml | 184 ------------------
10 files changed, 22 insertions(+), 385 deletions(-)
delete mode 100644 FP/bot/target/classes/application.properties
delete mode 100644 FP/bot/target/consumer7370489798140565122pom
create mode 100644 FP/migrations/chats_links_scheme.sql
create mode 100644 FP/migrations/master.xml
delete mode 100644 FP/scrapper/src/main/resources/scrapperapi.yml
delete mode 100644 FP/scrapper/target/classes/application.properties
delete mode 100644 FP/scrapper/target/classes/scrapperapi.yml
diff --git a/.gitignore b/.gitignore
index d457c3c..f87b265 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,5 +27,5 @@ hs_err_pid*
FP/.idea/
# volumes
-FP/migrations/
+FP/migrations/postgres_data/
FP/rabbitmq/
\ No newline at end of file
diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties
deleted file mode 100644
index 95d9a47..0000000
--- a/FP/bot/target/classes/application.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-app.test=123
-springdoc.swagger-ui.path=/swagger-ui
-app.scheduler.interval=50000
-app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
-app.bot.name=@SFRETbot
-server.port=8081
\ No newline at end of file
diff --git a/FP/bot/target/consumer7370489798140565122pom b/FP/bot/target/consumer7370489798140565122pom
deleted file mode 100644
index e69de29..0000000
diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml
index 3eeb07e..1d76d36 100644
--- a/FP/docker-compose.yml
+++ b/FP/docker-compose.yml
@@ -39,6 +39,7 @@ services:
rabbitmq:
image: rabbitmq:3-management-alpine
+ container_name: rabbitmq
ports:
- 5672:5672 # Порт для AMQP
- 15672:15672 # Порт для RabbitMQ Management UI
diff --git a/FP/migrations/chats_links_scheme.sql b/FP/migrations/chats_links_scheme.sql
new file mode 100644
index 0000000..63882e8
--- /dev/null
+++ b/FP/migrations/chats_links_scheme.sql
@@ -0,0 +1,8 @@
+CREATE TABLE links (id INTEGER, link VARCHAR(128) NOT NULL);
+
+CREATE TABLE tgChats (id INTEGER, tg_chat_id BIGINT NOT NULL);
+
+CREATE TABLE links_tgChats (
+ linkid INTEGER,
+ chatid INTEGER
+);
\ No newline at end of file
diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml
new file mode 100644
index 0000000..5d643de
--- /dev/null
+++ b/FP/migrations/master.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
index f89b8b8..8682387 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -61,7 +61,7 @@ public MessageConverter jsonMessageConverter(ClassMapper classMapper){
@Bean
public ConnectionFactory connectionFactory() {
- CachingConnectionFactory connectionFactory = new CachingConnectionFactory("0.0.0.0", 5672);
+ CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost", 5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// Другие настройки, если необходимо
diff --git a/FP/scrapper/src/main/resources/scrapperapi.yml b/FP/scrapper/src/main/resources/scrapperapi.yml
deleted file mode 100644
index c98cf7d..0000000
--- a/FP/scrapper/src/main/resources/scrapperapi.yml
+++ /dev/null
@@ -1,184 +0,0 @@
-openapi: 3.0.1
-info:
- title: Scrapper API
- version: 1.0.0
- contact:
- name: Alexander Biryukov
- url: https://github.com
-paths:
- /tg-chat/{id}:
- post:
- summary: Зарегистрировать чат
- parameters:
- - name: id
- in: path
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Чат зарегистрирован
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- delete:
- summary: Удалить чат
- parameters:
- - name: id
- in: path
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Чат успешно удалён
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- '404':
- description: Чат не существует
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- /links:
- get:
- summary: Получить все отслеживаемые ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Ссылки успешно получены
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ListLinksResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- post:
- summary: Добавить отслеживание ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/AddLinkRequest'
- required: true
- responses:
- '200':
- description: Ссылка успешно добавлена
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/LinkResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- delete:
- summary: Убрать отслеживание ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/RemoveLinkRequest'
- required: true
- responses:
- '200':
- description: Ссылка успешно убрана
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/LinkResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- '404':
- description: Ссылка не найдена
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
-components:
- schemas:
- LinkResponse:
- type: object
- properties:
- id:
- type: integer
- format: int64
- url:
- type: string
- format: uri
- ApiErrorResponse:
- type: object
- properties:
- description:
- type: string
- code:
- type: string
- exceptionName:
- type: string
- exceptionMessage:
- type: string
- stacktrace:
- type: array
- items:
- type: string
- AddLinkRequest:
- type: object
- properties:
- link:
- type: string
- format: uri
- ListLinksResponse:
- type: object
- properties:
- links:
- type: array
- items:
- $ref: '#/components/schemas/LinkResponse'
- size:
- type: integer
- format: int32
- RemoveLinkRequest:
- type: object
- properties:
- link:
- type: string
- format: uri
diff --git a/FP/scrapper/target/classes/application.properties b/FP/scrapper/target/classes/application.properties
deleted file mode 100644
index d4267e9..0000000
--- a/FP/scrapper/target/classes/application.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-app.test=123
-springdoc.swagger-ui.path=/swagger-ui
-app.scheduler.interval=5000
-git.link=https://github.com/Ray-Not/JavaGuava
-stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c
-app.exchange=my-direct-exchange
-app.queue=my-queue
-app.routingKey=my-routing-key
-app.useQueue=True
\ No newline at end of file
diff --git a/FP/scrapper/target/classes/scrapperapi.yml b/FP/scrapper/target/classes/scrapperapi.yml
deleted file mode 100644
index c98cf7d..0000000
--- a/FP/scrapper/target/classes/scrapperapi.yml
+++ /dev/null
@@ -1,184 +0,0 @@
-openapi: 3.0.1
-info:
- title: Scrapper API
- version: 1.0.0
- contact:
- name: Alexander Biryukov
- url: https://github.com
-paths:
- /tg-chat/{id}:
- post:
- summary: Зарегистрировать чат
- parameters:
- - name: id
- in: path
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Чат зарегистрирован
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- delete:
- summary: Удалить чат
- parameters:
- - name: id
- in: path
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Чат успешно удалён
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- '404':
- description: Чат не существует
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- /links:
- get:
- summary: Получить все отслеживаемые ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- responses:
- '200':
- description: Ссылки успешно получены
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ListLinksResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- post:
- summary: Добавить отслеживание ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/AddLinkRequest'
- required: true
- responses:
- '200':
- description: Ссылка успешно добавлена
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/LinkResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- delete:
- summary: Убрать отслеживание ссылки
- parameters:
- - name: Tg-Chat-Id
- in: header
- required: true
- schema:
- type: integer
- format: int64
- requestBody:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/RemoveLinkRequest'
- required: true
- responses:
- '200':
- description: Ссылка успешно убрана
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/LinkResponse'
- '400':
- description: Некорректные параметры запроса
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
- '404':
- description: Ссылка не найдена
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ApiErrorResponse'
-components:
- schemas:
- LinkResponse:
- type: object
- properties:
- id:
- type: integer
- format: int64
- url:
- type: string
- format: uri
- ApiErrorResponse:
- type: object
- properties:
- description:
- type: string
- code:
- type: string
- exceptionName:
- type: string
- exceptionMessage:
- type: string
- stacktrace:
- type: array
- items:
- type: string
- AddLinkRequest:
- type: object
- properties:
- link:
- type: string
- format: uri
- ListLinksResponse:
- type: object
- properties:
- links:
- type: array
- items:
- $ref: '#/components/schemas/LinkResponse'
- size:
- type: integer
- format: int32
- RemoveLinkRequest:
- type: object
- properties:
- link:
- type: string
- format: uri
From d19eaa4bcaf8c088382eb65ae8dea3574f82fe03 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 18:45:33 +0500
Subject: [PATCH 8/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B8=20=D0=91?=
=?UTF-8?q?=D0=94=20=D0=B8=20=D0=B1=D0=BE=D1=82=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/bot/pom.xml | 16 +++++++
.../tinkoff/edu/java/bot/BotApplication.java | 8 +++-
.../edu/java/bot/configuration/jdbcBean.java | 26 ++++++++++
.../records/ApplicationConfig.java | 3 ++
.../tinkoff/edu/java/bot/handler/BotMain.java | 19 ++++----
.../edu/java/bot/handler/MessageHandler.java | 21 +++++---
.../tinkoff/edu/java/bot/handler/Updater.java | 9 +++-
.../edu/java/bot/handler/commands/List.java | 35 ++++++++++++--
.../edu/java/bot/handler/commands/Start.java | 16 +++++--
.../edu/java/bot/handler/commands/Track.java | 48 ++++++++++++++++---
.../java/bot/handler/commands/Untrack.java | 24 +++++++---
.../src/main/resources/application.properties | 5 +-
FP/bot/src/test/java/BotTest.java | 24 ----------
FP/docker-compose.yml | 4 +-
.../java/scrapper/ScrapperApplication.java | 14 +++---
.../java/scrapper/jdbc/JdbcLinkService.java | 16 +++++--
.../java/scrapper/jdbc/config/jdbcBean.java | 2 +-
.../jdbc/operations/LinkOperations.java | 8 ++--
18 files changed, 213 insertions(+), 85 deletions(-)
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java
delete mode 100644 FP/bot/src/test/java/BotTest.java
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 3b3c9e6..96dea0d 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -90,5 +90,21 @@
spring-boot-starter-amqp
3.0.6
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.example
+ scrapper
+ 1.0
+ compile
+
\ No newline at end of file
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
index 0bdeff0..92ae210 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
@@ -1,11 +1,16 @@
package ru.tinkoff.edu.java.bot;
import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.jdbc.core.JdbcTemplate;
import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
import ru.tinkoff.edu.java.bot.handler.BotMain;
+import javax.sql.DataSource;
+
@SpringBootApplication
@EnableConfigurationProperties(ApplicationConfig.class)
@@ -14,7 +19,8 @@ public class BotApplication
public static void main(String[] args){
var ctx = SpringApplication.run(BotApplication.class, args);
ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
- BotMain bot = new BotMain(config.bot().token());
+ JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
+ BotMain bot = new BotMain(config.bot().token(), jdbcTemplate);
bot.start();
}
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java
new file mode 100644
index 0000000..e768de5
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java
@@ -0,0 +1,26 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class jdbcBean {
+ @Bean
+ public DataSource dataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName("org.postgresql.Driver");
+ dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres");
+ dataSource.setUsername("scrap_user");
+ dataSource.setPassword("hard_password");
+
+ return dataSource;
+ }
+ @Bean
+ public JdbcTemplate jdbcTemplate () {
+ return new JdbcTemplate (dataSource());
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
index 5ee81b6..c23d07b 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
@@ -1,12 +1,15 @@
package ru.tinkoff.edu.java.bot.configuration.records;
import jakarta.validation.constraints.NotNull;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
@Validated
@EnableScheduling
+@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
public record ApplicationConfig(
@NotNull String test,
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
index 33e72c8..13d6b65 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
@@ -2,35 +2,32 @@
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.jdbc.core.JdbcTemplate;
import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig;
+@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@EnableConfigurationProperties(ApplicationConfig.class)
public class BotMain {
String token;
static TelegramBot bot;
+ private JdbcTemplate jdbcTemplate;
- public BotMain(String token) {
+ public BotMain(String token, JdbcTemplate jdbcTemplate) {
this.token = token;
+ this.jdbcTemplate = jdbcTemplate;
}
public void start() {
bot = new TelegramBot(token);
- bot.setUpdatesListener(new Updater(bot));
+ bot.setUpdatesListener(new Updater(bot, jdbcTemplate));
}
public void end() {
bot.removeGetUpdatesListener();
}
-
- public static void apiCommand(long tgChatId, String command) {
-
- MessageHandler handler = new MessageHandler();
- String[] parse = command.split(" ");
- if(parse.length > 1) command = handler.call_command(parse[0], parse[1]);
- else command = handler.call_command(parse[0]);
- bot.execute(new SendMessage(tgChatId, command));
- }
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
index 56cfd57..87f2ab0 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
@@ -1,29 +1,38 @@
package ru.tinkoff.edu.java.bot.handler;
+import org.springframework.jdbc.core.JdbcTemplate;
import ru.tinkoff.edu.java.bot.handler.commands.All;
public class MessageHandler extends All {
+ private final JdbcTemplate jdbcTemplate;
+ private final long chatid;
+
+ public MessageHandler(JdbcTemplate jdbcTemplate, long chatid) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.chatid = chatid;
+ }
+
public boolean is_command(String message) {
return message.startsWith("/");
}
public String call_command(String command, String arg) {
return switch (command) {
- case "/start" -> start();
+ case "/start" -> start(jdbcTemplate, chatid);
case "/help" -> help();
- case "/track" -> track(arg);
- case "/list" -> list();
- case "/untrack" -> untrack(arg);
+ case "/track" -> track(jdbcTemplate, arg, chatid);
+ case "/list" -> list(jdbcTemplate, chatid);
+ case "/untrack" -> untrack(jdbcTemplate, arg, chatid);
default -> unknow();
};
}
public String call_command(String command) {
return switch (command) {
- case "/start" -> start();
+ case "/start" -> start(jdbcTemplate, chatid);
case "/help" -> help();
- case "/list" -> list();
+ case "/list" -> list(jdbcTemplate, chatid);
default -> unknow();
};
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
index 746ad5e..7965170 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
@@ -5,22 +5,27 @@
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.model.request.*;
import com.pengrad.telegrambot.request.SendMessage;
+import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class Updater implements UpdatesListener {
- MessageHandler handler = new MessageHandler();
+ MessageHandler handler;
String command;
TelegramBot bot;
+ private JdbcTemplate jdbcTemplate;
+ private long chatid;
- public Updater(TelegramBot bot) {
+ public Updater(TelegramBot bot, JdbcTemplate jdbcTemplate) {
this.bot = bot;
+ this.jdbcTemplate = jdbcTemplate;
}
@Override
public int process(List updates) {
Update update = updates.get(0);
+ handler = new MessageHandler(jdbcTemplate, update.message().chat().id());
if(handler.is_command(update.message().text())) {
String[] parse = update.message().text().split(" ");
if(parse.length > 1) command = handler.call_command(parse[0], parse[1]);
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
index fdadd4f..280f80a 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
@@ -1,10 +1,37 @@
package ru.tinkoff.edu.java.bot.handler.commands;
+import com.google.gson.JsonObject;
+import okhttp3.Interceptor;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.core.JdbcTemplate;
import ru.tinkoff.edu.java.bot.handler.DB;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
-public interface List {
- default String list() {
- if(DB.listIsEmpty()) return "list пустой";
- return "Отслеживаемые ссылки: " + DB.getListParse() + "";
+import java.util.ArrayList;
+
+public interface List extends LinkOperations, ChatOperations, LinkChatOperations {
+
+ default String list(JdbcTemplate jdbc, long chat) {
+ int i;
+ String links = "";
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ return "Перед использованием нужно зарегистрироваться";
+ }
+ ArrayList link_list = new ArrayList<>();
+ try {
+ for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++) {
+ link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid());
+ }
+ for (i = 0; i < i_findAllLink(jdbc, link_list).size(); i++) {
+ links += i_findAllLink(jdbc, link_list).get(i).url() + "\n";
+ }
+ return links;
+ } catch (BadSqlGrammarException e) {
+ return "У вас нет ссылок";
+ }
}
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
index 5c4b5d7..d2d5459 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
@@ -1,9 +1,19 @@
package ru.tinkoff.edu.java.bot.handler.commands;
-public interface Start {
+import org.springframework.jdbc.core.JdbcTemplate;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+
+public interface Start extends ChatOperations {
- default String start() {
- return "Бот начал работу";
+ default String start(JdbcTemplate jdbc, long chat) {
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id != 0) {
+ return "Вы уже зарегистрированы";
+ } else {
+ i_addChat(jdbc, chat);
+ return "Регистрация успешна, ваш tg_id = " + chat;
+ }
}
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
index fcd1042..9080b48 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
@@ -1,13 +1,47 @@
package ru.tinkoff.edu.java.bot.handler.commands;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
import ru.tinkoff.edu.java.bot.handler.DB;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
+import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryNotExsistException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.NullLinkException;
+import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
+import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest;
-public interface Track {
- default String track(String link) {
- link = link.trim();
- if(link.equals("")) return "ведите ссылку";
- if(DB.linkContain(link)) return "Ссылка уже есть";
- DB.addLink(link);
- return "ссылка " + link + " добавлена";
+public interface Track extends LinkOperations, LinkChatOperations, ChatOperations {
+ default String track(JdbcTemplate jdbc, String link, long chat) {
+ ClientConfiguration client = new ClientConfiguration();
+ LinkParser parser = new LinkParser();
+ if (parser.getLink(link) == null) {
+ return "Ссылка невалидна";
+ }
+ try {
+ client.gitHubClient(parser.getLink(link));
+ } catch (WebClientResponseException e) {
+ try {
+ client.stackOverflowClient(parser.getLink(link));
+ } catch (WebClientResponseException ex) {
+ return "Ссылка не поддерживается, доступны: Git, StackOverFlow";
+ }
+ }
+ int link_id = i_findLink(jdbc, link);
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ return "Перед использованием нужно зарегистрироваться";
+ }
+ if (link_id == 0) {
+ i_addLink(jdbc, link);
+ link_id = i_findLink(jdbc, link);
+ }
+ if (i_findLinkChat(jdbc, link_id, chat_id)) {
+ addLinkChat(jdbc, link_id, chat_id);
+ return "Ссылка успешно добавлена!";
+ }else return"Ссылка уже добавлена!";
}
}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
index a196195..6615feb 100644
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
@@ -1,14 +1,24 @@
package ru.tinkoff.edu.java.bot.handler.commands;
+import org.springframework.jdbc.core.JdbcTemplate;
import ru.tinkoff.edu.java.bot.handler.DB;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations;
+import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations;
-public interface Untrack {
- default String untrack(String link) {
- if(link.equals("")) return "ведите ссылку";
- if(DB.linkContain(link)) {
- DB.rmLink(link);
- return "ссылка " + link + " удалена";
+public interface Untrack extends LinkOperations, LinkChatOperations, ChatOperations {
+ default String untrack(JdbcTemplate jdbc, String link, long chat) {
+ int link_id = i_findLink(jdbc, link);
+ int chat_id = i_findChat(jdbc, chat);
+ if (chat_id == 0) {
+ return "Перед использованием нужно зарегистрироваться";
}
- return "ссылки " + link + " нет в пуле";
+ if (link_id != 0) {
+ i_removeLink(jdbc, link);
+ if (!i_findLinkChat(jdbc, link_id, chat_id)) {
+ i_removeLinkChat(jdbc, link_id, chat_id);
+ }
+ return "Ссылка удалена";
+ } else return "Ссылки не существует";
}
}
diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties
index 95d9a47..6600aaa 100644
--- a/FP/bot/src/main/resources/application.properties
+++ b/FP/bot/src/main/resources/application.properties
@@ -3,4 +3,7 @@ springdoc.swagger-ui.path=/swagger-ui
app.scheduler.interval=50000
app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ
app.bot.name=@SFRETbot
-server.port=8081
\ No newline at end of file
+server.port=8081
+app.exchange=my-direct-exchange
+app.queue=my-queue
+app.routingKey=my-routing-key
\ No newline at end of file
diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java
deleted file mode 100644
index 4e14a70..0000000
--- a/FP/bot/src/test/java/BotTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import ru.tinkoff.edu.java.bot.handler.DB;
-import ru.tinkoff.edu.java.bot.handler.MessageHandler;
-
-
-public class BotTest {
-
- String except_empty_list = "list пустой";
- String except_unknow_command = "Неизвестная команда";
- MessageHandler handler = new MessageHandler();
-
- @Test
- public void listTest() {
- Assertions.assertEquals(handler.call_command("/list"), except_empty_list);
- DB.addLink("link");
- Assertions.assertNotEquals(handler.call_command("/list"), except_empty_list);
- }
-
- @Test
- public void unknowCommandAndFormatTest() {
- Assertions.assertEquals(handler.call_command("/uno"), except_unknow_command);
- }
-}
diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml
index 1d76d36..4195e6e 100644
--- a/FP/docker-compose.yml
+++ b/FP/docker-compose.yml
@@ -5,7 +5,7 @@ services:
container_name: postgres
image: postgres:15.2
environment:
- POSTGRES_DB: scrapper
+ POSTGRES_DB: postgres
POSTGRES_USER: scrap_user
POSTGRES_PASSWORD: hard_password
volumes:
@@ -27,7 +27,7 @@ services:
- --hub-mode=off
- --changelog-file=master.xml
- --driver=org.postgresql.Driver
- - --url=jdbc:postgresql://postgres:5432/scrapper
+ - --url=jdbc:postgresql://postgres:5432/postgres
- --username=scrap_user
- --password=hard_password
- --logLevel=debug
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
index c2e1b98..0539e02 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -1,7 +1,6 @@
package ru.tinkoff.edu.java.scrapper;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -19,11 +18,12 @@ public class ScrapperApplication {
public static void main(String[] args) {
var ctx = SpringApplication.run(ScrapperApplication.class, args);
ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
- System.out.println("----------------------------------------------------------------" + config);
- SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer(
- new RabbitTemplate(),
- config
- ));
- notificationService.sendNotice("Вот-вот");
+ System.out.println("----------------------------------------------------------------");
+// SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer(
+// new RabbitTemplate(),
+// config
+// ));
+// notificationService.sendNotice("Вот-вот");
+// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null
}
}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
index 380ca48..2d62856 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
@@ -1,5 +1,6 @@
package ru.tinkoff.edu.java.scrapper.jdbc;
+import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import ru.tinkoff.edu.java.linkparser.LinkParser;
@@ -37,7 +38,7 @@ public void addLink(JdbcTemplate jdbc, AddLinkRequest link, Long chat) {
throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
}
if (link_id == 0) {
- i_addLink(jdbc, link);
+ i_addLink(jdbc, link.link());
link_id = i_findLink(jdbc, link.link());
}
if (i_findLinkChat(jdbc, link_id, chat_id)) {
@@ -52,7 +53,7 @@ public void removeLink(JdbcTemplate jdbc, RemoveLinkRequest link, long chat) {
throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
}
if (link_id != 0) {
- i_removeLink(jdbc, link);
+ i_removeLink(jdbc, link.link());
} else throw new EntryNotExsistException("Ссылки не существует");
if (!i_findLinkChat(jdbc, link_id, chat_id)) {
i_removeLinkChat(jdbc, link_id, chat_id);
@@ -66,10 +67,15 @@ public List getLinks(JdbcTemplate jdbc, long chat) {
throw new UnauthorizationException("Перед использованием нужно зарегистрироваться");
}
ArrayList link_list = new ArrayList<>();
- for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++){
- link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid());
+ try {
+ for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++) {
+ link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid());
+ }
+ return i_findAllLink(jdbc, link_list);
+ } catch (BadSqlGrammarException e) {
+ throw new EntryNotExsistException("У вас нет ссылок");
}
- return i_findAllLink(jdbc, link_list);
+
}
}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
index 8db6ed9..74a1fbe 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java
@@ -12,7 +12,7 @@ public class jdbcBean {
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
- dataSource.setUrl("jdbc:postgresql://localhost:5432/scrapper");
+ dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres");
dataSource.setUsername("scrap_user");
dataSource.setPassword("hard_password");
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
index 7907633..dfdbe71 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java
@@ -13,7 +13,7 @@
public interface LinkOperations {
default void i_addLink(
JdbcTemplate jdbcTemplate,
- AddLinkRequest addLinkRequest
+ String link
) {
int link_id;
@@ -26,15 +26,15 @@ default void i_addLink(
link_id = 1;
}
- jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, addLinkRequest.link());
+ jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, link);
}
default void i_removeLink(
JdbcTemplate jdbcTemplate,
- RemoveLinkRequest removeLinkRequest
+ String link
){
String query = "DELETE FROM links where link IN ('%s')";
- query = query.formatted(removeLinkRequest.link());
+ query = query.formatted(link);
jdbcTemplate.update(query);
}
From b5dde2a410fa96a50411406d9e2be7112e00c44f Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 18:59:25 +0500
Subject: [PATCH 9/9] =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D1=82=D0=B0=D1=86?=
=?UTF-8?q?=D0=B8=D1=8F=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=BC=D0=BE=D0=B3?=
=?UTF-8?q?=D0=BB=D0=B0=20PS=20Rabbit?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java | 3 +--
.../edu/java/scrapper/configuration/ApplicationConfig.java | 2 ++
.../edu/java/scrapper/configuration/RabbitMQConfiguration.java | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
index 0539e02..1ef6a07 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -24,6 +24,5 @@ public static void main(String[] args) {
// config
// ));
// notificationService.sendNotice("Вот-вот");
-// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null
- }
+ }
}
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
index 52af096..2651ea3 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -6,6 +6,7 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.validation.annotation.Validated;
import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
@@ -17,6 +18,7 @@
@Validated
@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
@EnableScheduling
+@Import(RabbitMQConfiguration.class)
public record ApplicationConfig(
@NotNull String test,
@NotNull Scheduler scheduler,
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
index 8682387..fc60661 100644
--- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -61,7 +61,7 @@ public MessageConverter jsonMessageConverter(ClassMapper classMapper){
@Bean
public ConnectionFactory connectionFactory() {
- CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost", 5672);
+ CachingConnectionFactory connectionFactory = new CachingConnectionFactory("rabbitmq", 5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
// Другие настройки, если необходимо